home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap14 / cosmo / iclassf.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-21  |  7.0 KB  |  266 lines

  1. /*
  2.  * ICLASSF.CPP
  3.  * Cosmo Chapter 14
  4.  *
  5.  * Implementation of a class factory for Cosmo's OLE Automation
  6.  * support.  This same implementation handles CLSID_CosmoFigure
  7.  * as well as CLSID_Cosmo2Application.  The CLSID is given to the
  8.  * constructor.
  9.  *
  10.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  11.  *
  12.  * Kraig Brockschmidt, Microsoft
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include "cosmo.h"
  19.  
  20.  
  21. /*
  22.  * CClassFactory::CClassFactory
  23.  * CClassFactory::~CClassFactory
  24.  *
  25.  * Constructor Parameters:
  26.  *  pFR             PCCosmoFrame that can create documents.
  27.  *  rclsID          REFCLSID of the object this factory should
  28.  *                  create.
  29.  */
  30.  
  31. CClassFactory::CClassFactory(PCCosmoFrame pFR, REFCLSID rclsID)
  32.     {
  33.     m_cRef=0L;
  34.     m_pFR=pFR;
  35.     m_clsID=rclsID;
  36.     m_fCreated=FALSE;
  37.     return;
  38.     }
  39.  
  40.  
  41. CClassFactory::~CClassFactory(void)
  42.     {
  43.     return;
  44.     }
  45.  
  46.  
  47.  
  48.  
  49. /*
  50.  * CClassFactory::QueryInterface
  51.  * CClassFactory::AddRef
  52.  * CClassFactory::Release
  53.  */
  54.  
  55. STDMETHODIMP CClassFactory::QueryInterface(REFIID riid
  56.     , PPVOID ppv)
  57.     {
  58.     *ppv=NULL;
  59.  
  60.     if (IID_IUnknown==riid || IID_IClassFactory==riid)
  61.         *ppv=this;
  62.  
  63.     if (NULL!=*ppv)
  64.         {
  65.         ((LPUNKNOWN)*ppv)->AddRef();
  66.         return NOERROR;
  67.         }
  68.  
  69.     return ResultFromScode(E_NOINTERFACE);
  70.     }
  71.  
  72.  
  73. STDMETHODIMP_(ULONG) CClassFactory::AddRef(void)
  74.     {
  75.     return ++m_cRef;
  76.     }
  77.  
  78.  
  79. STDMETHODIMP_(ULONG) CClassFactory::Release(void)
  80.     {
  81.     if (0!=--m_cRef)
  82.         return m_cRef;
  83.  
  84.     delete this;
  85.     return 0;
  86.     }
  87.  
  88.  
  89.  
  90.  
  91. /*
  92.  * CClassFactory::CreateInstance
  93.  *
  94.  * Purpose:
  95.  *  Instantiates a Figure object that supports embedding.
  96.  *
  97.  * Parameters:
  98.  *  pUnkOuter       LPUNKNOWN to the controlling IUnknown if we are
  99.  *                  being used in an aggregation.
  100.  *  riid            REFIID identifying the interface the caller
  101.  *                  desires to have for the new object.
  102.  *  ppvObj          PPVOID in which to store the desired
  103.  *                  interface pointer for the new object.
  104.  *
  105.  * Return Value:
  106.  *  HRESULT         NOERROR if successful, otherwise contains
  107.  *                  E_NOINTERFACE if we cannot support the requested
  108.  *                  interface.
  109.  */
  110.  
  111. STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter
  112.     , REFIID riid, PPVOID ppvObj)
  113.     {
  114.     HRESULT             hr;
  115.  
  116.     *ppvObj=NULL;
  117.  
  118.     /*
  119.      * We can only create one instance of the application object
  120.      * from this factory, but we can create multiple figure
  121.      * objects.  Creation of a figure never sets this flag.
  122.      */
  123.     if (m_fCreated)
  124.         return ResultFromScode(E_UNEXPECTED);
  125.  
  126.     hr=ResultFromScode(E_OUTOFMEMORY);
  127.  
  128.     //We don't support aggregation
  129.     if (NULL!=pUnkOuter)
  130.         return ResultFromScode(CLASS_E_NOAGGREGATION);
  131.  
  132.     //Check which class we're supposed to create
  133.     if (CLSID_Cosmo2Application==m_clsID)
  134.         {
  135.         /*
  136.          * By virtue of this application running, the frame
  137.          * object has already created the 'application' object
  138.          * we want to return.  So we just grab the right interface
  139.          * pointer from it.
  140.          */
  141.         hr=m_pFR->AutoApp()->QueryInterface(riid, ppvObj);
  142.  
  143.         //Assume we created an object.
  144.         g_cObj++;
  145.         }
  146.  
  147.  
  148.     if (CLSID_CosmoFigure==m_clsID)
  149.         {
  150.         /*
  151.          * We can actually use the Figures collection object
  152.          * that the client object maintains since it has
  153.          * creation code in it already.
  154.          */
  155.         IDispatch      *pIDispatch;
  156.         ICosmoFigures  *pICosmoFigs;
  157.  
  158.         pIDispatch=m_pFR->AutoApp()->get_Figures();
  159.  
  160.         if (NULL!=pIDispatch)
  161.             {
  162.             /*
  163.              * We have the collection IDispatch, we want to
  164.              * call the Add method which we can do through
  165.              * ICosmoFigures.
  166.              */
  167.             if (SUCCEEDED(pIDispatch->QueryInterface
  168.                 (IID_ICosmoFigures, (PPVOID)&pICosmoFigs)))
  169.                 {
  170.                 pIDispatch->Release();
  171.  
  172.                 /*
  173.                  * Get the pointer for the new figure.  This will
  174.                  * increment g_cObj when successful.
  175.                  */
  176.                 pIDispatch=pICosmoFigs->Add();
  177.  
  178.                 if (NULL!=pIDispatch)
  179.                     {
  180.                     //Get the originally requested pointer.
  181.                     hr=pIDispatch->QueryInterface(riid, ppvObj);
  182.                     pIDispatch->Release();
  183.  
  184.                     /*
  185.                      * Also force an AddRef on the application object
  186.                      * to prevent shutdown when we access it through
  187.                      * Figure::Application.  Such an access would
  188.                      * AddRef it and Release it, then cause shutdown.
  189.                      * The application object isn't any good any more.
  190.                      *
  191.                      * Note that since we didn't put the /Automation
  192.                      * flag on the LocalServer[32] entry for the
  193.                      * figure CLSID (we did for the app CLSID) then
  194.                      * the app class factory was never registered
  195.                      * and there's no danger of the app object being
  196.                      * created later.
  197.                      */
  198.                     m_pFR->AutoApp()->AddRef();
  199.                     }
  200.                 else
  201.                     g_cObj++;   //To fake shutdown
  202.                 }
  203.             }
  204.         }
  205.  
  206.     /*
  207.      * By assuming we created an object (with g_cObj++) allows us
  208.      * to just call ObjectDestroyed to do shutdown as necessary.
  209.      * If this CreateInstance was for the application object,
  210.      * then this app was launched for the purpose of getting
  211.      * at the object, so shutdown will occur (the class factory
  212.      * is only registered if /Automation is present).
  213.      *
  214.      * For the Figure object, that class factory is always
  215.      * registered, so there might be other object and there
  216.      * might be user control, so ObjectDestroyed will not necessarily
  217.      * cause shutdown.
  218.      */
  219.  
  220.     if (FAILED(hr))
  221.         ObjectDestroyed();
  222.     else
  223.         {
  224.         //Prevent second 'instantiations' of the application object.
  225.         m_fCreated=(CLSID_Cosmo2Application==m_clsID);
  226.         }
  227.  
  228.     return hr;
  229.     }
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236. /*
  237.  * CClassFactory::LockServer
  238.  *
  239.  * Purpose:
  240.  *  Increments or decrements the lock count of the serving
  241.  *  IClassFactory object.  When the number of locks goes to
  242.  *  zero and the number of objects is zero, we shut down the
  243.  *  application.
  244.  *
  245.  * Parameters:
  246.  *  fLock           BOOL specifying whether to increment or
  247.  *                  decrement the lock count.
  248.  *
  249.  * Return Value:
  250.  *  HRESULT         NOERROR always.
  251.  */
  252.  
  253. STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
  254.     {
  255.     if (fLock)
  256.         g_cLock++;
  257.     else
  258.         {
  259.         g_cLock--;
  260.         g_cObj++;
  261.         ObjectDestroyed();
  262.         }
  263.  
  264.     return NOERROR;
  265.     }
  266.