home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / tutsamp / aptserve / factory.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-30  |  44.6 KB  |  1,362 lines

  1. /*+==========================================================================
  2.   File:      FACTORY.CPP
  3.  
  4.   Summary:   Implementation file for the ClassFactories of the APTSERVE
  5.              server.  This server provides several Car-related COM
  6.              Components: Car, UtilityCar, and CruiseCar.  For each of
  7.              these components, IClassFactory is implemented in
  8.              appropriate ClassFactory COM objects: CFCar, CFUtilityCar,
  9.              and CFCruiseCar. The COM Components that can be manufactured
  10.              by this server are known outside the server by their
  11.              respective CLSIDs: CLSID_AptCar, CLSID_AptUtilityCar,
  12.              and CLSID_AptCruiseCar.
  13.  
  14.              For a comprehensive tutorial code tour of this module's
  15.              contents and offerings see the tutorial APTSERVE.HTM file.
  16.              For more specific technical details on the internal workings
  17.              see the comments dispersed throughout the module's source code.
  18.  
  19.   Classes:   CFCar, CFUtilityCar, CFCruiseCar
  20.  
  21.   Functions: .
  22.  
  23.   Origin:    3-20-96: atrent - Editor-inheritance from CAR.CPP in
  24.                the LOCSERVE Tutorial Code Sample.
  25.  
  26. ----------------------------------------------------------------------------
  27.   This file is part of the Microsoft COM Tutorial Code Samples.
  28.  
  29.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  30.  
  31.   This source code is intended only as a supplement to Microsoft
  32.   Development Tools and/or on-line documentation.  See these other
  33.   materials for detailed information regarding Microsoft code samples.
  34.  
  35.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  36.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  37.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  38.   PARTICULAR PURPOSE.
  39. ==========================================================================+*/
  40.  
  41. /*---------------------------------------------------------------------------
  42.   We include WINDOWS.H for all Win32 applications.
  43.   We include OLE2.H because we will be calling the COM/OLE Libraries.
  44.   We include APPUTIL.H because we will be building this DLL using
  45.     the convenient Virtual Window and Dialog classes and other
  46.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  47.   We include MICARS.H and CARGUIDS.H for the common car-related Interface
  48.     class, GUID, and CLSID specifications.
  49.   We include SERVER.H because it has the necessary internal class and
  50.     resource definitions for this DLL.
  51.   We include FACTORY.H because it has the necessary internal class factory
  52.     declarations for this DLL component server.  Those factories we will be
  53.     implementing in this module.
  54.   We include CAR.H, UTILCAR,H, and, CRUCAR.H for the object class
  55.     declarations for the COCar, COUtilityCar, and COCruiseCar COM objects.
  56. ---------------------------------------------------------------------------*/
  57. #include <windows.h>
  58. #include <ole2.h>
  59. #include <apputil.h>
  60. #include <micars.h>
  61. #include <carguids.h>
  62. #include "server.h"
  63. #include "factory.h"
  64. #include "car.h"
  65. #include "utilcar.h"
  66. #include "crucar.h"
  67.  
  68. /*---------------------------------------------------------------------------
  69.   Implementation the CFCar Class Factory.  CFCar is the COM
  70.   object class for the Class Factory that can manufacture COCar
  71.   COM Components.
  72. ---------------------------------------------------------------------------*/
  73.  
  74. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  75.   Method:   CFCar::CFCar
  76.  
  77.   Summary:  CFCar Constructor. Note the member initializer:
  78.             "m_ImpIClassFactory(this, pUnkOuter, pServer)" which is used
  79.             to pass the 'this', pUnkOuter, and pServer pointers of this
  80.             constructor function to the constructor executed in the
  81.             instantiation of the CImpIClassFactory interface whose
  82.             implementation is nested inside this present object class.
  83.  
  84.   Args:     IUnknown* pUnkOuter,
  85.               Pointer to the the outer Unknown.  NULL means this COM Object
  86.               is not being Aggregated.  Non NULL means it is being created
  87.               on behalf of an outside COM object that is reusing it via
  88.               aggregation.
  89.             CServer* pServer)
  90.               Pointer to the server's control object.
  91.  
  92.   Modifies: m_cRefs, m_pUnkOuter.
  93.  
  94.   Returns:  void
  95. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  96. CFCar::CFCar(
  97.   IUnknown* pUnkOuter,
  98.   CServer* pServer) :
  99.   m_ImpIClassFactory(this, pUnkOuter, pServer)
  100. {
  101.   // Zero the COM object's reference count.
  102.   m_cRefs = 0;
  103.  
  104.   // No AddRef necessary if non-NULL, as we're nested.
  105.   m_pUnkOuter = pUnkOuter;
  106.  
  107.   // Init the pointer to the server control object.
  108.   m_pServer = pServer;
  109.  
  110.   LOGF2("L<%X>: CFCar Constructor. m_pUnkOuter=0x%X.",TID,m_pUnkOuter);
  111.  
  112.   return;
  113. }
  114.  
  115.  
  116. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  117.   Method:   CFCar::~CFCar
  118.  
  119.   Summary:  CFCar Destructor.
  120.  
  121.   Args:     void
  122.  
  123.   Returns:  void
  124. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  125. CFCar::~CFCar(void)
  126. {
  127.   LOGF1("L<%X>: CFCar::Destructor.",TID);
  128.  
  129.   return;
  130. }
  131.  
  132.  
  133. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  134.   Method:   CFCar::QueryInterface
  135.  
  136.   Summary:  QueryInterface of the CFCar non-delegating
  137.             IUnknown implementation.
  138.  
  139.   Args:     REFIID riid,
  140.               [in] GUID of the Interface being requested.
  141.             PPVOID ppv)
  142.               [out] Address of the caller's pointer variable that will
  143.               receive the requested interface pointer.
  144.  
  145.   Returns:  HRESULT
  146.               Standard result code. NOERROR for success.
  147. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  148. STDMETHODIMP CFCar::QueryInterface(
  149.                REFIID riid,
  150.                PPVOID ppv)
  151. {
  152.   HRESULT hr = E_NOINTERFACE;
  153.   *ppv = NULL;
  154.  
  155.   if (IID_IUnknown == riid)
  156.   {
  157.     *ppv = this;
  158.     LOGF1("L<%X>: CFCar::QueryInterface. 'this' pIUnknown returned.",TID);
  159.   }
  160.   else if (IID_IClassFactory == riid)
  161.   {
  162.     *ppv = &m_ImpIClassFactory;
  163.     LOGF1("L<%X>: CFCar::QueryInterface. pIClassFactory returned.",TID);
  164.   }
  165.  
  166.   if (NULL != *ppv)
  167.   {
  168.     // We've handed out a pointer to the interface so obey the COM rules
  169.     // and AddRef the reference count.
  170.     ((LPUNKNOWN)*ppv)->AddRef();
  171.     hr = NOERROR;
  172.   }
  173.  
  174.   return (hr);
  175. }
  176.  
  177.  
  178. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  179.   Method:   CFCar::AddRef
  180.  
  181.   Summary:  AddRef of the CFCar non-delegating IUnknown implementation.
  182.  
  183.   Args:     void
  184.  
  185.   Modifies: m_cRefs.
  186.  
  187.   Returns:  ULONG
  188.               New value of m_cRefs (COM object's reference count).
  189. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  190. STDMETHODIMP_(ULONG) CFCar::AddRef(void)
  191. {
  192.   m_cRefs++;
  193.  
  194.   LOGF2("L<%X>: CFCar::AddRef. New cRefs=%i.",TID,m_cRefs);
  195.  
  196.   return m_cRefs;
  197. }
  198.  
  199.  
  200. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  201.   Method:   CFCar::Release
  202.  
  203.   Summary:  Release of the CFCar non-delegating IUnknown implementation.
  204.  
  205.   Args:     void
  206.  
  207.   Modifies: m_cRefs.
  208.  
  209.   Returns:  ULONG
  210.               New value of m_cRefs (COM object's reference count).
  211. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  212. STDMETHODIMP_(ULONG) CFCar::Release(void)
  213. {
  214.   m_cRefs--;
  215.  
  216.   LOGF2("L<%X>: CFCar::Release. New cRefs=%i.",TID,m_cRefs);
  217.  
  218.   if (0 == m_cRefs)
  219.   {
  220.     // We artificially bump the main ref count to prevent reentrancy
  221.     // via the main object destructor.  Not really needed in this
  222.     // CFCar but a good practice because we are aggregatable and
  223.     // may at some point in the future add something entertaining like
  224.     // some Releases to the CFCar destructor.
  225.     m_cRefs++;
  226.     delete this;
  227.   }
  228.  
  229.   return m_cRefs;
  230. }
  231.  
  232.  
  233. /*---------------------------------------------------------------------------
  234.   CFCar's nested implementation of the IClassFactory interface
  235.   including Constructor, Destructor, QueryInterface, AddRef, Release,
  236.   CreateInstance, and LockServer methods.
  237. ---------------------------------------------------------------------------*/
  238.  
  239. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  240.   Method:   CFCar::CImpIClassFactory::CImpIClassFactory
  241.  
  242.   Summary:  Constructor for the CImpIClassFactory interface instantiation.
  243.  
  244.   Args:     CFCar* pBackObj,
  245.               Back pointer to the parent outer object.
  246.             IUnknown* pUnkOuter,
  247.               Pointer to the outer Unknown.  For delegation.
  248.             CServer* pServer)
  249.               Pointer to the server's control object.
  250.  
  251.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter, m_pServer.
  252.  
  253.   Returns:  void
  254. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  255. CFCar::CImpIClassFactory::CImpIClassFactory(
  256.   CFCar* pBackObj,
  257.   IUnknown* pUnkOuter,
  258.   CServer* pServer)
  259. {
  260.   // Init the Interface Ref Count (used for debugging only).
  261.   m_cRefI = 0;
  262.  
  263.   // Init the Back Object Pointer to point to the parent object.
  264.   m_pBackObj = pBackObj;
  265.  
  266.   // Init the pointer to the server control object.
  267.   m_pServer = pServer;
  268.  
  269.   // Init the CImpIClassFactory interface's delegating Unknown pointer.
  270.   // We use the Back Object pointer for IUnknown delegation here if we are
  271.   // not being aggregated.  If we are being aggregated we use the supplied
  272.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  273.   // assignment requires no AddRef because the CImpIClassFactory lifetime is
  274.   // quaranteed by the lifetime of the parent object in which
  275.   // CImpIClassFactory is nested.
  276.   if (NULL == pUnkOuter)
  277.   {
  278.     m_pUnkOuter = pBackObj;
  279.     LOGF1("L<%X>: CFCar::CImpIClassFactory Constructor. Non-Aggregating.",TID);
  280.   }
  281.   else
  282.   {
  283.     m_pUnkOuter = pUnkOuter;
  284.     LOGF1("L<%X>: CFCar::CImpIClassFactory Constructor. Aggregating.",TID);
  285.   }
  286.  
  287.   return;
  288. }
  289.  
  290.  
  291. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  292.   Method:   CFCar::CImpIClassFactory::~CImpIClassFactory
  293.  
  294.   Summary:  Destructor for the CImpIClassFactory interface instantiation.
  295.  
  296.   Args:     void
  297.  
  298.   Returns:  void
  299. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  300. CFCar::CImpIClassFactory::~CImpIClassFactory(void)
  301. {
  302.   LOGF1("L<%X>: CFCar::CImpIClassFactory Destructor.",TID);
  303.  
  304.   return;
  305. }
  306.  
  307.  
  308. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  309.   Method:   CFCar::CImpIClassFactory::QueryInterface
  310.  
  311.   Summary:  The QueryInterface IUnknown member of this IClassFactory
  312.             interface implementation that delegates to m_pUnkOuter,
  313.             whatever it is.
  314.  
  315.   Args:     REFIID riid,
  316.               [in] GUID of the Interface being requested.
  317.             PPVOID ppv)
  318.               [out] Address of the caller's pointer variable that will
  319.               receive the requested interface pointer.
  320.  
  321.   Returns:  HRESULT
  322.               Standard result code. NOERROR for success.
  323.               Returned by the delegated outer QueryInterface call.
  324. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  325. STDMETHODIMP CFCar::CImpIClassFactory::QueryInterface(
  326.                REFIID riid,
  327.                PPVOID ppv)
  328. {
  329.   LOGF1("L<%X>: CFCar::CImpIClassFactory::QueryInterface. Delegating.",TID);
  330.  
  331.   // Delegate this call to the outer object's QueryInterface.
  332.   return m_pUnkOuter->QueryInterface(riid, ppv);
  333. }
  334.  
  335.  
  336. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  337.   Method:   CFCar::CImpIClassFactory::AddRef
  338.  
  339.   Summary:  The AddRef IUnknown member of this IClassFactory interface
  340.             implementation that delegates to m_pUnkOuter, whatever it is.
  341.  
  342.   Args:     void
  343.  
  344.   Modifies: m_cRefI.
  345.  
  346.   Returns:  ULONG
  347.               Returned by the delegated outer AddRef call.
  348. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  349. STDMETHODIMP_(ULONG) CFCar::CImpIClassFactory::AddRef(void)
  350. {
  351.   // Increment the Interface Reference Count.
  352.   ++m_cRefI;
  353.  
  354.   LOGF2("L<%X>: CFCar::CImpIClassFactory::Addref. Delegating. New cI=%i.",TID,m_cRefI);
  355.  
  356.   // Delegate this call to the outer object's AddRef.
  357.   return m_pUnkOuter->AddRef();
  358. }
  359.  
  360.  
  361. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  362.   Method:   CFCar::CImpIClassFactory::Release
  363.  
  364.   Summary:  The Release IUnknown member of this IClassFactory interface
  365.             implementation that delegates to m_pUnkOuter, whatever it is.
  366.  
  367.   Args:     void
  368.  
  369.   Returns:  ULONG
  370.               Returned by the delegated outer Release call.
  371. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  372. STDMETHODIMP_(ULONG) CFCar::CImpIClassFactory::Release(void)
  373. {
  374.   // Decrement the Interface Reference Count.
  375.   --m_cRefI;
  376.  
  377.   LOGF2("L<%X>: CFCar::CImpIClassFactory::Release. Delegating. New cI=%i.",TID,m_cRefI);
  378.  
  379.   // Delegate this call to the outer object's Release.
  380.   return m_pUnkOuter->Release();
  381. }
  382.  
  383.  
  384. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  385.   Method:   CFCar::CImpIClassFactory::CreateInstance
  386.  
  387.   Summary:  The CreateInstance member method of this IClassFactory
  388.             interface implementation.  Creates an instance of the COCar
  389.             COM component.
  390.  
  391.   Args:     IUnknown* pUnkOuter,
  392.               [in] Pointer to the controlling IUnknown.
  393.             REFIID riid,
  394.               [in] GUID of the Interface being requested.
  395.             PPVOID ppvCob)
  396.               [out] Address of the caller's pointer variable that will
  397.               receive the requested interface pointer.
  398.  
  399.   Returns:  HRESULT
  400.               Standard result code. NOERROR for success.
  401. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  402. STDMETHODIMP CFCar::CImpIClassFactory::CreateInstance(
  403.                IUnknown* pUnkOuter,
  404.                REFIID riid,
  405.                PPVOID ppv)
  406. {
  407.   HRESULT hr = E_FAIL;
  408.   COCar* pCob = NULL;
  409.  
  410.   LOGF2("L<%X>: CFCar::CImpIClassFactory::CreateInstance. pUnkOuter=0x%X.",TID,pUnkOuter);
  411.  
  412.   // NULL the output pointer.
  413.   *ppv = NULL;
  414.  
  415.   // If the creation call is requesting aggregation (pUnkOuter != NULL),
  416.   // the COM rules state the IUnknown interface MUST also be concomitantly
  417.   // requested.  If it is not so requested (riid != IID_IUnknown) then
  418.   // an error must be returned indicating that no aggregate creation of
  419.   // the CFCar COM Object can be performed.
  420.   if (NULL != pUnkOuter && riid != IID_IUnknown)
  421.     hr = CLASS_E_NOAGGREGATION;
  422.   else
  423.   {
  424.     // Instantiate a COCar COM Object.
  425.     pCob = new COCar(pUnkOuter, m_pServer);
  426.     if (NULL != pCob)
  427.     {
  428.       // We initially created the new COM object so tell the server
  429.       // to increment its global server object count to help ensure
  430.       // that the server remains loaded until this partial creation
  431.       // of a COM component is completed.
  432.       m_pServer->ObjectsUp();
  433.  
  434.       // We QueryInterface this new COM Object not only to deposit the
  435.       // main interface pointer to the caller's pointer variable, but to
  436.       // also automatically bump the Reference Count on the new COM
  437.       // Object after handing out this reference to it.
  438.       hr = pCob->QueryInterface(riid, (PPVOID)ppv);
  439.       if (FAILED(hr))
  440.       {
  441.         delete pCob;
  442.         m_pServer->ObjectsDown();
  443.       }
  444.     }
  445.     else
  446.     {
  447.       // If we were launched to create this object and could not then
  448.       // we should force a shutdown of this server.
  449.       m_pServer->ObjectsUp();
  450.       m_pServer->ObjectsDown();
  451.       hr = E_OUTOFMEMORY;
  452.     }
  453.   }
  454.  
  455.   if (SUCCEEDED(hr))
  456.   {
  457.     LOGF2("L<%X>: CFCar::CImpIClassFactory::CreateInstance Succeeded. *ppv=0x%X.",TID,*ppv);
  458.   }
  459.   else
  460.   {
  461.     LOGF1("L<%X>: CFCar::CImpIClassFactory::CreateInstance Failed.",TID);
  462.   }
  463.  
  464.   return hr;
  465. }
  466.  
  467.  
  468. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  469.   Method:   CFCar::CImpIClassFactory::LockServer
  470.  
  471.   Summary:  The LockServer member method of this IClassFactory interface
  472.             implementation.
  473.  
  474.   Args:     BOOL fLock)
  475.               [in] Flag determining whether to Lock or Unlock the server.
  476.  
  477.   Returns:  HRESULT
  478.               Standard result code. NOERROR for success.
  479. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  480. STDMETHODIMP CFCar::CImpIClassFactory::LockServer(
  481.                BOOL fLock)
  482. {
  483.   HRESULT hr = NOERROR;
  484.  
  485.   LOGF1("L<%X>: CFCar::CImpIClassFactory::LockServer.",TID);
  486.  
  487.   if (fLock)
  488.     m_pServer->Lock();
  489.   else
  490.     m_pServer->Unlock();
  491.  
  492.   return hr;
  493. }
  494.  
  495.  
  496. /*---------------------------------------------------------------------------
  497.   Implementation the CFUtilityCar Class Factory.  CFUtilityCar is the COM
  498.   object class for the Class Factory that can manufacture COUtilityCar
  499.   COM Components.
  500. ---------------------------------------------------------------------------*/
  501.  
  502. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  503.   Method:   CFUtilityCar::CFUtilityCar
  504.  
  505.   Summary:  CFUtilityCar Constructor. Note the member initializer:
  506.             "m_ImpIClassFactory(this, pUnkOuter, pServer)" which is used
  507.             to pass the 'this', pUnkOuter, and pServer pointers of this
  508.             constructor function to the constructor executed in the
  509.             instantiation of the CImpIClassFactory interface whose
  510.             implementation is nested inside this present object class.
  511.  
  512.   Args:     IUnknown* pUnkOuter,
  513.               Pointer to the the outer Unknown.  NULL means this COM Object
  514.               is not being Aggregated.  Non NULL means it is being created
  515.               on behalf of an outside COM object that is reusing it via
  516.               aggregation.
  517.             CServer* pServer)
  518.               Pointer to the server's control object.
  519.  
  520.   Modifies: m_cRefs, m_pUnkOuter.
  521.  
  522.   Returns:  void
  523. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  524. CFUtilityCar::CFUtilityCar(
  525.   IUnknown* pUnkOuter,
  526.   CServer* pServer) :
  527.   m_ImpIClassFactory(this, pUnkOuter, pServer)
  528. {
  529.   // Zero the COM object's reference count.
  530.   m_cRefs = 0;
  531.  
  532.   // No AddRef necessary if non-NULL, as we're nested.
  533.   m_pUnkOuter = pUnkOuter;
  534.  
  535.   // Init the pointer to the server control object.
  536.   m_pServer = pServer;
  537.  
  538.   LOGF2("L<%X>: CFUtilityCar Constructor. m_pUnkOuter=0x%X.",TID,m_pUnkOuter);
  539.  
  540.   return;
  541. }
  542.  
  543.  
  544. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  545.   Method:   CFUtilityCar::~CFUtilityCar
  546.  
  547.   Summary:  CFUtilityCar Destructor.
  548.  
  549.   Args:     void
  550.  
  551.   Returns:  void
  552. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  553. CFUtilityCar::~CFUtilityCar(void)
  554. {
  555.   LOGF1("L<%X>: CFUtilityCar::Destructor.",TID);
  556.  
  557.   return;
  558. }
  559.  
  560.  
  561. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  562.   Method:   CFUtilityCar::QueryInterface
  563.  
  564.   Summary:  QueryInterface of the CFUtilityCar non-delegating
  565.             IUnknown implementation.
  566.  
  567.   Args:     REFIID riid,
  568.               [in] GUID of the Interface being requested.
  569.             PPVOID ppv)
  570.               [out] Address of the caller's pointer variable that will
  571.               receive the requested interface pointer.
  572.  
  573.   Returns:  HRESULT
  574.               Standard result code. NOERROR for success.
  575. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  576. STDMETHODIMP CFUtilityCar::QueryInterface(
  577.                REFIID riid,
  578.                PPVOID ppv)
  579. {
  580.   HRESULT hr = E_NOINTERFACE;
  581.   *ppv = NULL;
  582.  
  583.   if (IID_IUnknown == riid)
  584.   {
  585.     *ppv = this;
  586.     LOGF1("L<%X>: CFUtilityCar::QueryInterface. 'this' pIUnknown returned.",TID);
  587.   }
  588.   else if (IID_IClassFactory == riid)
  589.   {
  590.     *ppv = &m_ImpIClassFactory;
  591.     LOGF1("L<%X>: CFUtilityCar::QueryInterface. pIClassFactory returned.",TID);
  592.   }
  593.  
  594.   if (NULL != *ppv)
  595.   {
  596.     // We've handed out a pointer to the interface so obey the COM rules
  597.     //   and AddRef the reference count.
  598.     ((LPUNKNOWN)*ppv)->AddRef();
  599.     hr = NOERROR;
  600.   }
  601.  
  602.   return (hr);
  603. }
  604.  
  605.  
  606. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  607.   Method:   CFUtilityCar::AddRef
  608.  
  609.   Summary:  AddRef of the CFUtilityCar non-delegating IUnknown implementation.
  610.  
  611.   Args:     void
  612.  
  613.   Modifies: m_cRefs.
  614.  
  615.   Returns:  ULONG
  616.               New value of m_cRefs (COM object's reference count).
  617. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  618. STDMETHODIMP_(ULONG) CFUtilityCar::AddRef(void)
  619. {
  620.   m_cRefs++;
  621.  
  622.   LOGF2("L<%X>: CFUtilityCar::AddRef. New cRefs=%i.",TID,m_cRefs);
  623.  
  624.   return m_cRefs;
  625. }
  626.  
  627.  
  628. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  629.   Method:   CFUtilityCar::Release
  630.  
  631.   Summary:  Release of the CFUtilityCar non-delegating IUnknown implementation.
  632.  
  633.   Args:     void
  634.  
  635.   Modifies: m_cRefs.
  636.  
  637.   Returns:  ULONG
  638.               New value of m_cRefs (COM object's reference count).
  639. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  640. STDMETHODIMP_(ULONG) CFUtilityCar::Release(void)
  641. {
  642.   m_cRefs--;
  643.  
  644.   LOGF2("L<%X>: CFUtilityCar::Release. New cRefs=%i.",TID,m_cRefs);
  645.  
  646.   if (0 == m_cRefs)
  647.   {
  648.     // We artificially bump the main ref count to prevent reentrancy
  649.     // via the main object destructor.  Not really needed in this
  650.     // CFUtilityCar but a good practice because we are aggregatable and
  651.     // may at some point in the future add something entertaining like
  652.     // some Releases to the CFUtilityCar destructor.
  653.     m_cRefs++;
  654.     delete this;
  655.   }
  656.  
  657.   return m_cRefs;
  658. }
  659.  
  660.  
  661. /*---------------------------------------------------------------------------
  662.   CFUtilityCar's nested implementation of the IClassFactory interface
  663.   including Constructor, Destructor, QueryInterface, AddRef, Release,
  664.   CreateInstance, and LockServer methods.
  665. ---------------------------------------------------------------------------*/
  666.  
  667. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  668.   Method:   CFUtilityCar::CImpIClassFactory::CImpIClassFactory
  669.  
  670.   Summary:  Constructor for the CImpIClassFactory interface instantiation.
  671.  
  672.   Args:     CFUtilityCar* pBackObj,
  673.               Back pointer to the parent outer object.
  674.             IUnknown* pUnkOuter,
  675.               Pointer to the outer Unknown.  For delegation.
  676.             CServer* pServer)
  677.               Pointer to the server's control object.
  678.  
  679.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter, m_pServer.
  680.  
  681.   Returns:  void
  682. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  683. CFUtilityCar::CImpIClassFactory::CImpIClassFactory(
  684.   CFUtilityCar* pBackObj,
  685.   IUnknown* pUnkOuter,
  686.   CServer* pServer)
  687. {
  688.   // Init the Interface Ref Count (used for debugging only).
  689.   m_cRefI = 0;
  690.  
  691.   // Init the Back Object Pointer to point to the parent object.
  692.   m_pBackObj = pBackObj;
  693.  
  694.   // Init the pointer to the server control object.
  695.   m_pServer = pServer;
  696.  
  697.   // Init the CImpIClassFactory interface's delegating Unknown pointer.
  698.   // We use the Back Object pointer for IUnknown delegation here if we are
  699.   // not being aggregated.  If we are being aggregated we use the supplied
  700.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  701.   // assignment requires no AddRef because the CImpIClassFactory lifetime is
  702.   // quaranteed by the lifetime of the parent object in which
  703.   // CImpIClassFactory is nested.
  704.   if (NULL == pUnkOuter)
  705.   {
  706.     m_pUnkOuter = pBackObj;
  707.     LOGF1("L<%X>: CFUtilityCar::CImpIClassFactory Constructor. Non-Aggregating.",TID);
  708.   }
  709.   else
  710.   {
  711.     m_pUnkOuter = pUnkOuter;
  712.     LOGF1("L<%X>: CFUtilityCar::CImpIClassFactory Constructor. Aggregating.",TID);
  713.   }
  714.  
  715.   return;
  716. }
  717.  
  718.  
  719. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  720.   Method:   CFUtilityCar::CImpIClassFactory::~CImpIClassFactory
  721.  
  722.   Summary:  Destructor for the CImpIClassFactory interface instantiation.
  723.  
  724.   Args:     void
  725.  
  726.   Returns:  void
  727. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  728. CFUtilityCar::CImpIClassFactory::~CImpIClassFactory(void)
  729. {
  730.   LOGF1("L<%X>: CFUtilityCar::CImpIClassFactory Destructor.",TID);
  731.  
  732.   return;
  733. }
  734.  
  735.  
  736. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  737.   Method:   CFUtilityCar::CImpIClassFactory::QueryInterface
  738.  
  739.   Summary:  The QueryInterface IUnknown member of this IClassFactory
  740.             interface implementation that delegates to m_pUnkOuter,
  741.             whatever it is.
  742.  
  743.   Args:     REFIID riid,
  744.               [in] GUID of the Interface being requested.
  745.             PPVOID ppv)
  746.               [out] Address of the caller's pointer variable that will
  747.               receive the requested interface pointer.
  748.  
  749.   Returns:  HRESULT
  750.               Standard result code. NOERROR for success.
  751.               Returned by the delegated outer QueryInterface call.
  752. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  753. STDMETHODIMP CFUtilityCar::CImpIClassFactory::QueryInterface(
  754.                REFIID riid,
  755.                PPVOID ppv)
  756. {
  757.   LOGF1("L<%X>: CFUtilityCar::CImpIClassFactory::QueryInterface. Delegating.",TID);
  758.  
  759.   // Delegate this call to the outer object's QueryInterface.
  760.   return m_pUnkOuter->QueryInterface(riid, ppv);
  761. }
  762.  
  763.  
  764. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  765.   Method:   CFUtilityCar::CImpIClassFactory::AddRef
  766.  
  767.   Summary:  The AddRef IUnknown member of this IClassFactory interface
  768.             implementation that delegates to m_pUnkOuter, whatever it is.
  769.  
  770.   Args:     void
  771.  
  772.   Modifies: m_cRefI.
  773.  
  774.   Returns:  ULONG
  775.               Returned by the delegated outer AddRef call.
  776. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  777. STDMETHODIMP_(ULONG) CFUtilityCar::CImpIClassFactory::AddRef(void)
  778. {
  779.   // Increment the Interface Reference Count.
  780.   ++m_cRefI;
  781.  
  782.   LOGF2("L<%X>: CFUtilityCar::CImpIClassFactory::Addref. Delegating. New cI=%i.",TID,m_cRefI);
  783.  
  784.   // Delegate this call to the outer object's AddRef.
  785.   return m_pUnkOuter->AddRef();
  786. }
  787.  
  788.  
  789. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  790.   Method:   CFUtilityCar::CImpIClassFactory::Release
  791.  
  792.   Summary:  The Release IUnknown member of this IClassFactory interface
  793.             implementation that delegates to m_pUnkOuter, whatever it is.
  794.  
  795.   Args:     void
  796.  
  797.   Modifies: m_cRefI.
  798.  
  799.   Returns:  ULONG
  800.               Returned by the delegated outer Release call.
  801. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  802. STDMETHODIMP_(ULONG) CFUtilityCar::CImpIClassFactory::Release(void)
  803. {
  804.   // Decrement the Interface Reference Count.
  805.   --m_cRefI;
  806.  
  807.   LOGF2("L<%X>: CFUtilityCar::CImpIClassFactory::Release. Delegating. New cI=%i.",TID,m_cRefI);
  808.  
  809.   // Delegate this call to the outer object's Release.
  810.   return m_pUnkOuter->Release();
  811. }
  812.  
  813.  
  814. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  815.   Method:   CFUtilityCar::CImpIClassFactory::CreateInstance
  816.  
  817.   Summary:  The CreateInstance member method of this IClassFactory interface
  818.             implementation.  Creates an instance of the COUtilityCar COM
  819.             component.
  820.  
  821.   Args:     IUnknown* pUnkOuter,
  822.               [in] Pointer to the controlling IUnknown.
  823.             REFIID riid,
  824.               [in] GUID of the Interface being requested.
  825.             PPVOID ppvCob)
  826.               [out] Address of the caller's pointer variable that will
  827.               receive the requested interface pointer.
  828.  
  829.   Returns:  HRESULT
  830.               Standard result code. NOERROR for success.
  831. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  832. STDMETHODIMP CFUtilityCar::CImpIClassFactory::CreateInstance(
  833.                IUnknown* pUnkOuter,
  834.                REFIID riid,
  835.                PPVOID ppv)
  836. {
  837.   HRESULT hr = E_FAIL;
  838.   COUtilityCar* pCob = NULL;
  839.  
  840.   LOGF2("L<%X>: CFUtilityCar::CImpIClassFactory::CreateInstance. pUnkOuter=0x%X.",TID,pUnkOuter);
  841.  
  842.   // If the creation call is requesting aggregation (pUnkOuter != NULL),
  843.   // the COM rules state the IUnknown interface MUST also be concomitantly
  844.   // requested.  If it is not so requested ( riid != IID_IUnknown) then
  845.   // an error must be returned indicating that no aggregate creation of
  846.   // the COUtilityCar COM Object can be performed.
  847.   if (NULL != pUnkOuter && riid != IID_IUnknown)
  848.     hr = CLASS_E_NOAGGREGATION;
  849.   else
  850.   {
  851.     // Instantiate a COUtilityCar COM Object.
  852.     pCob = new COUtilityCar(pUnkOuter, m_pServer);
  853.     if (NULL != pCob)
  854.     {
  855.       // We initially created the new COM object so tell the server
  856.       // to increment its global server object count to help ensure
  857.       // that the server remains loaded until this partial creation
  858.       // of a COM component is completed.
  859.       m_pServer->ObjectsUp();
  860.  
  861.       // If we have succeeded in instantiating the COM object we
  862.       // initialize it to set up any subordinate objects.
  863.       hr = pCob->Init();
  864.       if (SUCCEEDED(hr))
  865.       {
  866.         // We QueryInterface this new COM Object not only to deposit the
  867.         // main interface pointer to the caller's pointer variable, but to
  868.         // also automatically bump the Reference Count on the new COM
  869.         // Object after handing out this reference to it.
  870.         hr = pCob->QueryInterface(riid, (PPVOID)ppv);
  871.       }
  872.  
  873.       if (FAILED(hr))
  874.       {
  875.         delete pCob;
  876.         m_pServer->ObjectsDown();
  877.       }
  878.     }
  879.     else
  880.     {
  881.       // If we were launched to create this object and could not then
  882.       // we should force a shutdown of this server.
  883.       m_pServer->ObjectsUp();
  884.       m_pServer->ObjectsDown();
  885.       hr = E_OUTOFMEMORY;
  886.     }
  887.   }
  888.  
  889.   if (SUCCEEDED(hr))
  890.   {
  891.     LOGF2("L<%X>: CFUtilityCar::CImpIClassFactory::CreateInstance Succeeded. *ppv=0x%X.",TID,*ppv);
  892.   }
  893.   else
  894.   {
  895.     LOGF1("L<%X>: CFUtilityCar::CImpIClassFactory::CreateInstance Failed.",TID);
  896.   }
  897.  
  898.   return hr;
  899. }
  900.  
  901.  
  902. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  903.   Method:   CFUtilityCar::CImpIClassFactory::LockServer
  904.  
  905.   Summary:  The LockServer member method of this IClassFactory interface
  906.             implementation.
  907.  
  908.   Args:     BOOL fLock)
  909.               [in] Flag determining whether to Lock or Unlock the server.
  910.  
  911.   Returns:  HRESULT
  912.               Standard result code. NOERROR for success.
  913. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  914. STDMETHODIMP CFUtilityCar::CImpIClassFactory::LockServer(
  915.                BOOL fLock)
  916. {
  917.   HRESULT hr = NOERROR;
  918.  
  919.   LOGF1("L<%X>: CFUtilityCar::CImpIClassFactory::LockServer.",TID);
  920.  
  921.   if (fLock)
  922.     m_pServer->Lock();
  923.   else
  924.     m_pServer->Unlock();
  925.  
  926.   return hr;
  927. }
  928.  
  929.  
  930. /*---------------------------------------------------------------------------
  931.   Implementation the CFCruiseCar Class Factory.  CFCruiseCar is the COM
  932.   object class for the Class Factory that can manufacture COCruiseCar
  933.   COM Components.
  934. ---------------------------------------------------------------------------*/
  935.  
  936. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  937.   Method:   CFCruiseCar::CFCruiseCar
  938.  
  939.   Summary:  CFCruiseCar Constructor. Note the member initializer:
  940.             "m_ImpIClassFactory(this, pUnkOuter, pServer)" which is used
  941.             to pass the 'this', pUnkOuter, and pServer pointers of this
  942.             constructor function to the constructor executed in the
  943.             instantiation of the CImpIClassFactory interface whose
  944.             implementation is nested inside this present object class.
  945.  
  946.   Args:     IUnknown* pUnkOuter,
  947.               Pointer to the the outer Unknown.  NULL means this COM Object
  948.               is not being Aggregated.  Non NULL means it is being created
  949.               on behalf of an outside COM object that is reusing it via
  950.               aggregation.
  951.             CServer* pServer)
  952.               Pointer to the server's control object.
  953.  
  954.   Modifies: m_cRefs, m_pUnkOuter, m_pServer.
  955.  
  956.   Returns:  void
  957. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  958. CFCruiseCar::CFCruiseCar(
  959.   IUnknown* pUnkOuter,
  960.   CServer* pServer) :
  961.   m_ImpIClassFactory(this, pUnkOuter, pServer)
  962. {
  963.   // Zero the COM object's reference count.
  964.   m_cRefs = 0;
  965.  
  966.   // No AddRef necessary if non-NULL, as we're nested.
  967.   m_pUnkOuter = pUnkOuter;
  968.  
  969.   // Init the pointer to the server control object.
  970.   m_pServer = pServer;
  971.  
  972.   LOGF2("L<%X>: CFCruiseCar Constructor. m_pUnkOuter=0x%X.",TID,m_pUnkOuter);
  973.  
  974.   return;
  975. }
  976.  
  977.  
  978. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  979.   Method:   CFCruiseCar::~CFCruiseCar
  980.  
  981.   Summary:  CFCruiseCar Destructor.
  982.  
  983.   Args:     void
  984.  
  985.   Returns:  void
  986. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  987. CFCruiseCar::~CFCruiseCar(void)
  988. {
  989.   LOGF1("L<%X>: CFCruiseCar::Destructor.",TID);
  990.  
  991.   return;
  992. }
  993.  
  994.  
  995. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  996.   Method:   CFCruiseCar::QueryInterface
  997.  
  998.   Summary:  QueryInterface of the CFCruiseCar non-delegating
  999.             IUnknown implementation.
  1000.  
  1001.   Args:     REFIID riid,
  1002.               [in] GUID of the Interface being requested.
  1003.             PPVOID ppv)
  1004.               [out] Address of the caller's pointer variable that will
  1005.               receive the requested interface pointer.
  1006.  
  1007.   Returns:  HRESULT
  1008.               Standard result code. NOERROR for success.
  1009. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1010. STDMETHODIMP CFCruiseCar::QueryInterface(
  1011.                REFIID riid,
  1012.                PPVOID ppv)
  1013. {
  1014.   HRESULT hr = E_NOINTERFACE;
  1015.   *ppv = NULL;
  1016.  
  1017.   if (IID_IUnknown == riid)
  1018.   {
  1019.     *ppv = this;
  1020.     LOGF1("L<%X>: CFCruiseCar::QueryInterface. 'this' pIUnknown returned.",TID);
  1021.   }
  1022.   else if (IID_IClassFactory == riid)
  1023.   {
  1024.     *ppv = &m_ImpIClassFactory;
  1025.     LOGF1("L<%X>: CFCruiseCar::QueryInterface. pIClassFactory returned.",TID);
  1026.   }
  1027.  
  1028.   if (NULL != *ppv)
  1029.   {
  1030.     // We've handed out a pointer to the interface so obey the COM rules
  1031.     // and AddRef the reference count.
  1032.     ((LPUNKNOWN)*ppv)->AddRef();
  1033.     hr = NOERROR;
  1034.   }
  1035.  
  1036.   return (hr);
  1037. }
  1038.  
  1039.  
  1040. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1041.   Method:   CFCruiseCar::AddRef
  1042.  
  1043.   Summary:  AddRef of the CFCruiseCar non-delegating IUnknown implementation.
  1044.  
  1045.   Args:     void
  1046.  
  1047.   Modifies: m_cRefs.
  1048.  
  1049.   Returns:  ULONG
  1050.               New value of m_cRefs (COM object's reference count).
  1051. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1052. STDMETHODIMP_(ULONG) CFCruiseCar::AddRef(void)
  1053. {
  1054.   m_cRefs++;
  1055.  
  1056.   LOGF2("L<%X>: CFCruiseCar::AddRef. New cRefs=%i.",TID,m_cRefs);
  1057.  
  1058.   return m_cRefs;
  1059. }
  1060.  
  1061.  
  1062. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1063.   Method:   CFCruiseCar::Release
  1064.  
  1065.   Summary:  Release of the CFCruiseCar non-delegating IUnknown implementation.
  1066.  
  1067.   Args:     void
  1068.  
  1069.   Modifies: m_cRefs.
  1070.  
  1071.   Returns:  ULONG
  1072.               New value of m_cRefs (COM object's reference count).
  1073. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1074. STDMETHODIMP_(ULONG) CFCruiseCar::Release(void)
  1075. {
  1076.   m_cRefs--;
  1077.  
  1078.   LOGF2("L<%X>: CFCruiseCar::Release. New cRefs=%i.",TID,m_cRefs);
  1079.  
  1080.   if (0 == m_cRefs)
  1081.   {
  1082.     // We artificially bump the main ref count to prevent reentrancy
  1083.     // via the main object destructor.  Not really needed in this
  1084.     // CFCruiseCar but a good practice because we are aggregatable and
  1085.     // may at some point in the future add something entertaining like
  1086.     // some Releases to the CFCruiseCar destructor.
  1087.     m_cRefs++;
  1088.     delete this;
  1089.   }
  1090.  
  1091.   return m_cRefs;
  1092. }
  1093.  
  1094.  
  1095. /*---------------------------------------------------------------------------
  1096.   CFCruiseCar's nested implementation of the IClassFactory interface
  1097.   including Constructor, Destructor, QueryInterface, AddRef, Release,
  1098.   CreateInstance, and LockServer methods.
  1099. ---------------------------------------------------------------------------*/
  1100.  
  1101. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1102.   Method:   CFCruiseCar::CImpIClassFactory::CImpIClassFactory
  1103.  
  1104.   Summary:  Constructor for the CImpIClassFactory interface instantiation.
  1105.  
  1106.   Args:     CFCruiseCar* pBackObj,
  1107.               Back pointer to the parent outer object.
  1108.             IUnknown* pUnkOuter,
  1109.               Pointer to the outer Unknown.  For delegation.
  1110.             CServer* pServer)
  1111.               Pointer to the server's control object.
  1112.  
  1113.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter, m_pServer.
  1114.  
  1115.   Returns:  void
  1116. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1117. CFCruiseCar::CImpIClassFactory::CImpIClassFactory(
  1118.   CFCruiseCar* pBackObj,
  1119.   IUnknown* pUnkOuter,
  1120.   CServer* pServer)
  1121. {
  1122.   // Init the Interface Ref Count (used for debugging only).
  1123.   m_cRefI = 0;
  1124.  
  1125.   // Init the Back Object Pointer to point to the parent object.
  1126.   m_pBackObj = pBackObj;
  1127.  
  1128.   // Init the pointer to the server control object.
  1129.   m_pServer = pServer;
  1130.  
  1131.   // Init the CImpIClassFactory interface's delegating Unknown pointer.
  1132.   // We use the Back Object pointer for IUnknown delegation here if we are
  1133.   // not being aggregated.  If we are being aggregated we use the supplied
  1134.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  1135.   // assignment requires no AddRef because the CImpIClassFactory lifetime is
  1136.   // quaranteed by the lifetime of the parent object in which
  1137.   // CImpIClassFactory is nested.
  1138.   if (NULL == pUnkOuter)
  1139.   {
  1140.     m_pUnkOuter = pBackObj;
  1141.     LOGF1("L<%X>: CFCruiseCar::CImpIClassFactory Constructor. Non-Aggregating.",TID);
  1142.   }
  1143.   else
  1144.   {
  1145.     m_pUnkOuter = pUnkOuter;
  1146.     LOGF1("L<%X>: CFCruiseCar::CImpIClassFactory Constructor. Aggregating.",TID);
  1147.   }
  1148.  
  1149.   return;
  1150. }
  1151.  
  1152.  
  1153. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1154.   Method:   CFCruiseCar::CImpIClassFactory::~CImpIClassFactory
  1155.  
  1156.   Summary:  Destructor for the CImpIClassFactory interface instantiation.
  1157.  
  1158.   Args:     void
  1159.  
  1160.   Returns:  void
  1161. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1162. CFCruiseCar::CImpIClassFactory::~CImpIClassFactory(void)
  1163. {
  1164.   LOGF1("L<%X>: CFCruiseCar::CImpIClassFactory Destructor.",TID);
  1165.  
  1166.   return;
  1167. }
  1168.  
  1169.  
  1170. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1171.   Method:   CFCruiseCar::CImpIClassFactory::QueryInterface
  1172.  
  1173.   Summary:  The QueryInterface IUnknown member of this IClassFactory
  1174.             interface implementation that delegates to m_pUnkOuter,
  1175.             whatever it is.
  1176.  
  1177.   Args:     REFIID riid,
  1178.               [in] GUID of the Interface being requested.
  1179.             PPVOID ppv)
  1180.               [out] Address of the caller's pointer variable that will
  1181.               receive the requested interface pointer.
  1182.  
  1183.   Returns:  HRESULT
  1184.               Standard result code. NOERROR for success.
  1185.               Returned by the delegated outer QueryInterface call.
  1186. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1187. STDMETHODIMP CFCruiseCar::CImpIClassFactory::QueryInterface(
  1188.                REFIID riid,
  1189.                PPVOID ppv)
  1190. {
  1191.   LOGF1("L<%X>: CFCruiseCar::CImpIClassFactory::QueryInterface. Delegating.",TID);
  1192.  
  1193.   // Delegate this call to the outer object's QueryInterface.
  1194.   return m_pUnkOuter->QueryInterface(riid, ppv);
  1195. }
  1196.  
  1197.  
  1198. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1199.   Method:   CFCruiseCar::CImpIClassFactory::AddRef
  1200.  
  1201.   Summary:  The AddRef IUnknown member of this IClassFactory interface
  1202.             implementation that delegates to m_pUnkOuter, whatever it is.
  1203.  
  1204.   Args:     void
  1205.  
  1206.   Modifies: m_cRefI.
  1207.  
  1208.   Returns:  ULONG
  1209.               Returned by the delegated outer AddRef call.
  1210. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1211. STDMETHODIMP_(ULONG) CFCruiseCar::CImpIClassFactory::AddRef(void)
  1212. {
  1213.   // Increment the Interface Reference Count.
  1214.   ++m_cRefI;
  1215.  
  1216.   LOGF2("L<%X>: CFCruiseCar::CImpIClassFactory::Addref. Delegating. New cI=%i.",TID,m_cRefI);
  1217.  
  1218.   // Delegate this call to the outer object's AddRef.
  1219.   return m_pUnkOuter->AddRef();
  1220. }
  1221.  
  1222.  
  1223. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1224.   Method:   CFCruiseCar::CImpIClassFactory::Release
  1225.  
  1226.   Summary:  The Release IUnknown member of this IClassFactory interface
  1227.             implementation that delegates to m_pUnkOuter, whatever it is.
  1228.  
  1229.   Args:     void
  1230.  
  1231.   Modifies: m_cRefI.
  1232.  
  1233.   Returns:  ULONG
  1234.               Returned by the delegated outer Release call.
  1235. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1236. STDMETHODIMP_(ULONG) CFCruiseCar::CImpIClassFactory::Release(void)
  1237. {
  1238.   // Decrement the Interface Reference Count.
  1239.   --m_cRefI;
  1240.  
  1241.   LOGF2("L<%X>: CFCruiseCar::CImpIClassFactory::Release. Delegating. New cI=%i.",TID,m_cRefI);
  1242.  
  1243.   // Delegate this call to the outer object's Release.
  1244.   return m_pUnkOuter->Release();
  1245. }
  1246.  
  1247.  
  1248. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1249.   Method:   CFCruiseCar::CImpIClassFactory::CreateInstance
  1250.  
  1251.   Summary:  The CreateInstance member method of this IClassFactory interface
  1252.             implementation.  Creates an instance of the COCruiseCar COM
  1253.             component.
  1254.  
  1255.   Args:     IUnknown* pUnkOuter,
  1256.               [in] Pointer to the controlling IUnknown.
  1257.             REFIID riid,
  1258.               [in] GUID of the Interface being requested.
  1259.             PPVOID ppvCob)
  1260.               [out] Address of the caller's pointer variable that will
  1261.               receive the requested interface pointer.
  1262.  
  1263.   Returns:  HRESULT
  1264.               Standard result code. NOERROR for success.
  1265. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1266. STDMETHODIMP CFCruiseCar::CImpIClassFactory::CreateInstance(
  1267.                IUnknown* pUnkOuter,
  1268.                REFIID riid,
  1269.                PPVOID ppv)
  1270. {
  1271.   HRESULT hr = E_FAIL;
  1272.   COCruiseCar* pCob = NULL;
  1273.  
  1274.   LOGF2("L<%X>: CFCruiseCar::CImpIClassFactory::CreateInstance. pUnkOuter=0x%X.",TID,pUnkOuter);
  1275.  
  1276.   // If the creation call is requesting aggregation (pUnkOuter != NULL),
  1277.   // the COM rules state the IUnknown interface MUST also be concomitantly
  1278.   // requested.  If it is not so requested ( riid != IID_IUnknown) then
  1279.   // an error must be returned indicating that no aggregate creation of
  1280.   // the COCruiseCarFactory COM Object can be performed.
  1281.   if (NULL != pUnkOuter && riid != IID_IUnknown)
  1282.     hr = CLASS_E_NOAGGREGATION;
  1283.   else
  1284.   {
  1285.     // Instantiate a COCruiseCar COM Object.
  1286.     pCob = new COCruiseCar(pUnkOuter, m_pServer);
  1287.     if (NULL != pCob)
  1288.     {
  1289.       // We initially created the new COM object so tell the server
  1290.       // to increment its global server object count to help ensure
  1291.       // that the server remains loaded until this partial creation
  1292.       // of a COM component is completed.
  1293.       m_pServer->ObjectsUp();
  1294.  
  1295.       // If we have succeeded in instantiating the COM object we
  1296.       // initialize it to set up any subordinate objects.
  1297.       hr = pCob->Init();
  1298.       if (SUCCEEDED(hr))
  1299.       {
  1300.         // We QueryInterface this new COM Object not only to deposit the
  1301.         // main interface pointer to the caller's pointer variable, but to
  1302.         // also automatically bump the Reference Count on the new COM
  1303.         // Object after handing out this reference to it.
  1304.         hr = pCob->QueryInterface(riid, (PPVOID)ppv);
  1305.       }
  1306.  
  1307.       if (FAILED(hr))
  1308.       {
  1309.         delete pCob;
  1310.         m_pServer->ObjectsDown();
  1311.       }
  1312.     }
  1313.     else
  1314.     {
  1315.       // If we were launched to create this object and could not then
  1316.       // we should force a shutdown of this server.
  1317.       m_pServer->ObjectsUp();
  1318.       m_pServer->ObjectsDown();
  1319.       hr = E_OUTOFMEMORY;
  1320.     }
  1321.   }
  1322.  
  1323.   if (SUCCEEDED(hr))
  1324.   {
  1325.     LOGF2("L<%X>: CFCruiseCar::CImpIClassFactory::CreateInstance Succeeded. *ppv=0x%X.",TID,*ppv);
  1326.   }
  1327.   else
  1328.   {
  1329.     LOGF1("L<%X>: CFCruiseCar::CImpIClassFactory::CreateInstance Failed.",TID);
  1330.   }
  1331.  
  1332.   return hr;
  1333. }
  1334.  
  1335.  
  1336. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  1337.   Method:   CFCruiseCar::CImpIClassFactory::LockServer
  1338.  
  1339.   Summary:  The LockServer member method of this IClassFactory interface
  1340.             implementation.
  1341.  
  1342.   Args:     BOOL fLock)
  1343.               [in] Flag determining whether to Lock or Unlock the server.
  1344.  
  1345.   Returns:  HRESULT
  1346.               Standard result code. NOERROR for success.
  1347. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  1348. STDMETHODIMP CFCruiseCar::CImpIClassFactory::LockServer(
  1349.                BOOL fLock)
  1350. {
  1351.   HRESULT hr = NOERROR;
  1352.  
  1353.   LOGF1("L<%X>: CFCruiseCar::CImpIClassFactory::LockServer.",TID);
  1354.  
  1355.   if (fLock)
  1356.     m_pServer->Lock();
  1357.   else
  1358.     m_pServer->Unlock();
  1359.  
  1360.   return hr;
  1361. }
  1362.