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 / locserve / factory.cpp < prev    next >
C/C++ Source or Header  |  1997-08-30  |  45KB  |  1,376 lines

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