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 / perdraw / factory.cpp < prev    next >
C/C++ Source or Header  |  1997-08-30  |  16KB  |  475 lines

  1. /*+==========================================================================
  2.   File:      FACTORY.CPP
  3.  
  4.   Summary:   Implementation file for the class factories of the PERDRAW
  5.              server.  This server provides the DrawPage COM component.
  6.              For this component, IClassFactory is implemented in an
  7.              appropriate class factory COM object: CFDrawPage. The COM
  8.              component that can be manufactured by this server is known
  9.              outside the server by its CLSID: CLSID_DrawPage.
  10.  
  11.              The class factories in this server use the CThreaded
  12.              OwnThis mechanism to ensure mutually exclusive access by
  13.              contending multiple threads.
  14.  
  15.              For a comprehensive tutorial code tour of this module's
  16.              contents and offerings see the tutorial PERDRAW.HTM
  17.              file. For more specific technical details on the internal
  18.              workings see the comments dispersed throughout the module's
  19.              source code.
  20.  
  21.   Classes:   CFDrawPage.
  22.  
  23.   Functions: .
  24.  
  25.   Origin:    5-20-97: atrent - Editor-inheritance from FACTORY.CPP in
  26.                the STOSERVE Tutorial Code Sample.
  27.  
  28. ----------------------------------------------------------------------------
  29.   This file is part of the Microsoft COM Tutorial Code Samples.
  30.  
  31.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  32.  
  33.   This source code is intended only as a supplement to Microsoft
  34.   Development Tools and/or on-line documentation.  See these other
  35.   materials for detailed information regarding Microsoft code samples.
  36.  
  37.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  38.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  39.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  40.   PARTICULAR PURPOSE.
  41. ==========================================================================+*/
  42.  
  43. /*---------------------------------------------------------------------------
  44.   We include WINDOWS.H for all Win32 applications.
  45.   We include OLE2.H because we will be calling the COM/OLE Libraries.
  46.   We include OLECTL.H because it has definitions for connectable objects.
  47.   We include APPUTIL.H because we will be building this DLL using
  48.     the convenient Virtual Window and Dialog classes and other
  49.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  50.   We include IPAGES.H and PAGEGUID.H for the common DrawPage-related
  51.     Interface class, GUID, and CLSID specifications.
  52.   We include SERVER.H because it has the necessary internal class and
  53.     resource definitions for this DLL and for the server housing.
  54.   We include FACTORY.H because it has the necessary internal class factory
  55.     declarations for this DLL component server.  Those are the factories
  56.     we will be implementing in this module.
  57.   We include CONNECT.H for object class declarations for the various
  58.     connection point and connection COM objects used in PERDRAW.
  59.   We include DRAWPAGE.H, for the object class declarations for the
  60.     CODrawPage COM object.
  61. ---------------------------------------------------------------------------*/
  62. #include <windows.h>
  63. #include <ole2.h>
  64. #include <olectl.h>
  65. #include <apputil.h>
  66. #include <ipages.h>
  67. #include <pageguid.h>
  68. #include "server.h"
  69. #include "factory.h"
  70. #include "connect.h"
  71. #include "drawpage.h"
  72.  
  73. /*---------------------------------------------------------------------------
  74.   Implementation the CFDrawPage Class Factory.  CFDrawPage is the COM
  75.   object class for the Class Factory that can manufacture CODrawPage
  76.   COM Components.
  77. ---------------------------------------------------------------------------*/
  78.  
  79. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  80.   Method:   CFDrawPage::CFDrawPage
  81.  
  82.   Summary:  CFDrawPage Constructor. Note the member initializer:
  83.             "m_ImpIClassFactory(this, pUnkOuter, pServer)" which is used
  84.             to pass the 'this', pUnkOuter, and pServer pointers of this
  85.             constructor function to the constructor executed in the
  86.             instantiation of the CImpIClassFactory interface whose
  87.             implementation is nested inside this present object class.
  88.  
  89.   Args:     IUnknown* pUnkOuter,
  90.               Pointer to the the outer Unknown.  NULL means this COM Object
  91.               is not being Aggregated.  Non NULL means it is being created
  92.               on behalf of an outside COM object that is reusing it via
  93.               aggregation.
  94.             CServer* pServer)
  95.               Pointer to the server's control object.
  96.  
  97.   Modifies: m_cRefs, m_pUnkOuter.
  98.  
  99.   Returns:  void
  100. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  101. CFDrawPage::CFDrawPage(
  102.   IUnknown* pUnkOuter,
  103.   CServer* pServer) :
  104.   m_ImpIClassFactory(this, pUnkOuter, pServer)
  105. {
  106.   // Zero the COM object's reference count.
  107.   m_cRefs = 0;
  108.  
  109.   // No AddRef necessary if non-NULL, as we're nested.
  110.   m_pUnkOuter = pUnkOuter;
  111.  
  112.   // Init the pointer to the server control object.
  113.   m_pServer = pServer;
  114.  
  115.   return;
  116. }
  117.  
  118.  
  119. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  120.   Method:   CFDrawPage::~CFDrawPage
  121.  
  122.   Summary:  CFDrawPage Destructor.
  123.  
  124.   Args:     void
  125.  
  126.   Returns:  void
  127. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  128. CFDrawPage::~CFDrawPage(void)
  129. {
  130.   return;
  131. }
  132.  
  133.  
  134. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  135.   Method:   CFDrawPage::QueryInterface
  136.  
  137.   Summary:  QueryInterface of the CFDrawPage non-delegating
  138.             IUnknown implementation.
  139.  
  140.   Args:     REFIID riid,
  141.               [in] GUID of the Interface being requested.
  142.             PPVOID ppv)
  143.               [out] Address of the caller's pointer variable that will
  144.               receive the requested interface pointer.
  145.  
  146.   Returns:  HRESULT
  147.               Standard result code. NOERROR for success.
  148. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  149. STDMETHODIMP CFDrawPage::QueryInterface(
  150.                REFIID riid,
  151.                PPVOID ppv)
  152. {
  153.   HRESULT hr = E_NOINTERFACE;
  154.  
  155.   if (OwnThis())
  156.   {
  157.     *ppv = NULL;
  158.  
  159.     if (IID_IUnknown == riid)
  160.       *ppv = this;
  161.     else if (IID_IClassFactory == riid)
  162.       *ppv = &m_ImpIClassFactory;
  163.  
  164.     if (NULL != *ppv)
  165.     {
  166.       // We've handed out a pointer to the interface so obey the COM rules
  167.       // and AddRef the reference count.
  168.       ((LPUNKNOWN)*ppv)->AddRef();
  169.       hr = NOERROR;
  170.     }
  171.  
  172.     UnOwnThis();
  173.   }
  174.  
  175.   return (hr);
  176. }
  177.  
  178.  
  179. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  180.   Method:   CFDrawPage::AddRef
  181.  
  182.   Summary:  AddRef of the CFDrawPage non-delegating IUnknown implementation.
  183.  
  184.   Args:     void
  185.  
  186.   Modifies: m_cRefs.
  187.  
  188.   Returns:  ULONG
  189.               New value of m_cRefs (COM object's reference count).
  190. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  191. STDMETHODIMP_(ULONG) CFDrawPage::AddRef(void)
  192. {
  193.   ULONG cRefs;
  194.  
  195.   if (OwnThis())
  196.   {
  197.     cRefs = ++m_cRefs;
  198.  
  199.     UnOwnThis();
  200.   }
  201.  
  202.   return cRefs;
  203. }
  204.  
  205.  
  206. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  207.   Method:   CFDrawPage::Release
  208.  
  209.   Summary:  Release of the CFDrawPage non-delegating IUnknown implementation.
  210.  
  211.   Args:     void
  212.  
  213.   Modifies: m_cRefs.
  214.  
  215.   Returns:  ULONG
  216.               New value of m_cRefs (COM object's reference count).
  217. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  218. STDMETHODIMP_(ULONG) CFDrawPage::Release(void)
  219. {
  220.   ULONG cRefs;
  221.  
  222.   if (OwnThis())
  223.   {
  224.     cRefs = --m_cRefs;
  225.  
  226.     if (0 == cRefs)
  227.     {
  228.       // We've reached a zero reference count for this COM object.
  229.       // So we tell the server housing to decrement its global object
  230.       // count so that the server will be unloaded if appropriate.
  231.       if (NULL != m_pServer)
  232.         m_pServer->ObjectsDown();
  233.  
  234.       // We artificially bump the main ref count to prevent reentrancy
  235.       // via the main object destructor.  Not really needed in this
  236.       // CFDrawPage but a good practice because we are aggregatable and
  237.       // may at some point in the future add something entertaining like
  238.       // some Releases to the CFDrawPage destructor.
  239.       m_cRefs++;
  240.       UnOwnThis();
  241.       delete this;
  242.     }
  243.     else
  244.       UnOwnThis();
  245.   }
  246.  
  247.   return cRefs;
  248. }
  249.  
  250.  
  251. /*---------------------------------------------------------------------------
  252.   CFDrawPage's nested implementation of the IClassFactory interface
  253.   including Constructor, Destructor, QueryInterface, AddRef, Release,
  254.   CreateInstance, and LockServer methods.
  255. ---------------------------------------------------------------------------*/
  256.  
  257. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  258.   Method:   CFDrawPage::CImpIClassFactory::CImpIClassFactory
  259.  
  260.   Summary:  Constructor for the CImpIClassFactory interface instantiation.
  261.  
  262.   Args:     CFDrawPage* pCO,
  263.               Back pointer to the parent outer object.
  264.             IUnknown* pUnkOuter,
  265.               Pointer to the outer Unknown.  For delegation.
  266.             CServer* pServer)
  267.               Pointer to the server's control object.
  268.  
  269.   Modifies: m_pCO, m_pUnkOuter, m_pServer.
  270.  
  271.   Returns:  void
  272. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  273. CFDrawPage::CImpIClassFactory::CImpIClassFactory(
  274.   CFDrawPage* pCO,
  275.   IUnknown* pUnkOuter,
  276.   CServer* pServer)
  277. {
  278.   // Init the main Object Pointer to point to the parent object.
  279.   m_pCO = pCO;
  280.  
  281.   // Init the pointer to the server control object.
  282.   m_pServer = pServer;
  283.  
  284.   // Init the CImpIClassFactory interface's delegating Unknown pointer.
  285.   // We use the main Object pointer for IUnknown delegation here if we are
  286.   // not being aggregated. If we are being aggregated we use the supplied
  287.   // pUnkOuter for IUnknown delegation. In either case the pointer
  288.   // assignment requires no AddRef because the CImpIClassFactory lifetime
  289.   // is quaranteed by the lifetime of the parent object in which
  290.   // CImpIClassFactory is nested.
  291.   if (NULL == pUnkOuter)
  292.     m_pUnkOuter = pCO;
  293.   else
  294.     m_pUnkOuter = pUnkOuter;
  295.  
  296.   return;
  297. }
  298.  
  299.  
  300. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  301.   Method:   CFDrawPage::CImpIClassFactory::~CImpIClassFactory
  302.  
  303.   Summary:  Destructor for the CImpIClassFactory interface instantiation.
  304.  
  305.   Args:     void
  306.  
  307.   Returns:  void
  308. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  309. CFDrawPage::CImpIClassFactory::~CImpIClassFactory(void)
  310. {
  311.   return;
  312. }
  313.  
  314.  
  315. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  316.   Method:   CFDrawPage::CImpIClassFactory::QueryInterface
  317.  
  318.   Summary:  The QueryInterface IUnknown member of this IClassFactory
  319.             interface implementation that delegates to m_pUnkOuter,
  320.             whatever it is.
  321.  
  322.   Args:     REFIID riid,
  323.               [in] GUID of the Interface being requested.
  324.             PPVOID ppv)
  325.               [out] Address of the caller's pointer variable that will
  326.               receive the requested interface pointer.
  327.  
  328.   Returns:  HRESULT
  329.               Standard result code. NOERROR for success.
  330.               Returned by the delegated outer QueryInterface call.
  331. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  332. STDMETHODIMP CFDrawPage::CImpIClassFactory::QueryInterface(
  333.                REFIID riid,
  334.                PPVOID ppv)
  335. {
  336.   // Delegate this call to the outer object's QueryInterface.
  337.   return m_pUnkOuter->QueryInterface(riid, ppv);
  338. }
  339.  
  340.  
  341. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  342.   Method:   CFDrawPage::CImpIClassFactory::AddRef
  343.  
  344.   Summary:  The AddRef IUnknown member of this IClassFactory interface
  345.             implementation that delegates to m_pUnkOuter, whatever it is.
  346.  
  347.   Args:     void
  348.  
  349.   Returns:  ULONG
  350.               Returned by the delegated outer AddRef call.
  351. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  352. STDMETHODIMP_(ULONG) CFDrawPage::CImpIClassFactory::AddRef(void)
  353. {
  354.   // Delegate this call to the outer object's AddRef.
  355.   return m_pUnkOuter->AddRef();
  356. }
  357.  
  358.  
  359. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  360.   Method:   CFDrawPage::CImpIClassFactory::Release
  361.  
  362.   Summary:  The Release IUnknown member of this IClassFactory interface
  363.             implementation that delegates to m_pUnkOuter, whatever it is.
  364.  
  365.   Args:     void
  366.  
  367.   Returns:  ULONG
  368.               Returned by the delegated outer Release call.
  369. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  370. STDMETHODIMP_(ULONG) CFDrawPage::CImpIClassFactory::Release(void)
  371. {
  372.   // Delegate this call to the outer object's Release.
  373.   return m_pUnkOuter->Release();
  374. }
  375.  
  376.  
  377. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  378.   Method:   CFDrawPage::CImpIClassFactory::CreateInstance
  379.  
  380.   Summary:  The CreateInstance member method of this IClassFactory
  381.             interface implementation.  Creates an instance of the CODrawPage
  382.             COM component.
  383.  
  384.   Args:     IUnknown* pUnkOuter,
  385.               [in] Pointer to the controlling IUnknown.
  386.             REFIID riid,
  387.               [in] GUID of the Interface being requested.
  388.             PPVOID ppv)
  389.               [out] Address of the caller's pointer variable that will
  390.               receive the requested interface pointer.
  391.  
  392.   Returns:  HRESULT
  393.               Standard result code. NOERROR for success.
  394. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  395. STDMETHODIMP CFDrawPage::CImpIClassFactory::CreateInstance(
  396.                IUnknown* pUnkOuter,
  397.                REFIID riid,
  398.                PPVOID ppv)
  399. {
  400.   HRESULT hr = E_FAIL;
  401.   CODrawPage* pCO = NULL;
  402.  
  403.   // NULL the output pointer.
  404.   *ppv = NULL;
  405.  
  406.   // If the creation call is requesting aggregation (pUnkOuter != NULL),
  407.   // the COM rules state the IUnknown interface MUST also be concomitantly
  408.   // be requested.  If it is not so requested (riid != IID_IUnknown) then
  409.   // an error must be returned indicating that no aggregate creation of
  410.   // the CFDrawPage COM Object can be performed.
  411.   if (NULL != pUnkOuter && riid != IID_IUnknown)
  412.     hr = CLASS_E_NOAGGREGATION;
  413.   else
  414.   {
  415.     // Instantiate a CODrawPage COM Object.
  416.     pCO = new CODrawPage(pUnkOuter, m_pServer);
  417.     if (NULL != pCO)
  418.     {
  419.       // Create and initialize any subordinate objects.
  420.       hr = pCO->Init();
  421.       if (SUCCEEDED(hr))
  422.       {
  423.         // We successfully created the new COM object so tell the server
  424.         // to increment its global server object count to help ensure
  425.         // that the server remains loaded until this partial creation
  426.         // of a COM component is completed.
  427.         m_pServer->ObjectsUp();
  428.  
  429.         // We QueryInterface this new COM Object not only to deposit the
  430.         // main interface pointer to the caller's pointer variable, but to
  431.         // also automatically bump the Reference Count on the new COM
  432.         // Object after handing out this reference to it.
  433.         hr = pCO->QueryInterface(riid, (PPVOID)ppv);
  434.         if (FAILED(hr))
  435.         {
  436.           m_pServer->ObjectsDown();
  437.           delete pCO;
  438.         }
  439.       }
  440.       else
  441.         delete pCO;
  442.     }
  443.     else
  444.       hr = E_OUTOFMEMORY;
  445.   }
  446.  
  447.   return hr;
  448. }
  449.  
  450.  
  451. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  452.   Method:   CFDrawPage::CImpIClassFactory::LockServer
  453.  
  454.   Summary:  The LockServer member method of this IClassFactory interface
  455.             implementation.
  456.  
  457.   Args:     BOOL bLock)
  458.               [in] Flag determining whether to Lock or Unlock the server.
  459.  
  460.   Returns:  HRESULT
  461.               Standard result code. NOERROR for success.
  462. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  463. STDMETHODIMP CFDrawPage::CImpIClassFactory::LockServer(
  464.                BOOL bLock)
  465. {
  466.   HRESULT hr = NOERROR;
  467.  
  468.   if (bLock)
  469.     m_pServer->Lock();
  470.   else
  471.     m_pServer->Unlock();
  472.  
  473.   return hr;
  474. }
  475.