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 / chap10 / ddataobj / ddataobj.cpp < prev    next >
C/C++ Source or Header  |  1996-05-21  |  7KB  |  329 lines

  1. /*
  2.  * DDATAOBJ.CPP
  3.  * Data Object DLL Chapter 10
  4.  *
  5.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  6.  *
  7.  * Kraig Brockschmidt, Microsoft
  8.  * Internet  :  kraigb@microsoft.com
  9.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  10.  */
  11.  
  12.  
  13. #define INITGUIDS
  14. #include "ddataobj.h"
  15.  
  16.  
  17. //Count number of objects and number of locks.
  18. ULONG       g_cObj=0;
  19. ULONG       g_cLock=0;
  20.  
  21. //Make this global for the data object to load resources.
  22. HINSTANCE   g_hInst=NULL;
  23.  
  24.  
  25.  
  26. /*
  27.  * LibMain(32)
  28.  *
  29.  * Purpose:
  30.  *  Entry point conditionally compiled for Windows NT and Windows
  31.  *  3.1.  Provides the proper structure for each environment.
  32.  */
  33.  
  34. #ifdef WIN32
  35. BOOL WINAPI LibMain32(HINSTANCE hInstance, ULONG ulReason
  36.     , LPVOID pvReserved)
  37.     {
  38.     if (DLL_PROCESS_DETACH==ulReason)
  39.         {
  40.         //Must unregsiter the class we registered
  41.         UnregisterClass(TEXT("Advisor"), hInstance);
  42.         return TRUE;
  43.         }
  44.     else
  45.         {
  46.         if (DLL_PROCESS_ATTACH!=ulReason)
  47.             return TRUE;
  48.         }
  49.  
  50.     g_hInst=hInstance;
  51.     return TRUE;
  52.     }
  53.  
  54. #else
  55. int PASCAL LibMain(HINSTANCE hInstance, WORD wDataSeg
  56.     , WORD cbHeapSize, LPSTR lpCmdLine)
  57.     {
  58.     if (0!=cbHeapSize)
  59.         UnlockData(0);
  60.  
  61.     g_hInst=hInstance;
  62.     return (int)hInstance;
  63.     }
  64. #endif
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71. /*
  72.  * DllGetClassObject
  73.  *
  74.  * Purpose:
  75.  *  Provides an IClassFactory for a given CLSID that this DLL is
  76.  *  registered to support.  This DLL is placed under the CLSID
  77.  *  in the registration database as the InProcServer.
  78.  *
  79.  * Parameters:
  80.  *  clsID           REFCLSID that identifies the class factory
  81.  *                  desired.  Since this parameter is passed this
  82.  *                  DLL can handle any number of objects simply
  83.  *                  by returning different class factories here
  84.  *                  for different CLSIDs.
  85.  *
  86.  *  riid            REFIID specifying the interface the caller wants
  87.  *                  on the class object, usually IID_ClassFactory.
  88.  *
  89.  *  ppv             PPVOID in which to return the interface
  90.  *                  pointer.
  91.  *
  92.  * Return Value:
  93.  *  HRESULT         NOERROR on success, otherwise an error code.
  94.  */
  95.  
  96. HRESULT APIENTRY DllGetClassObject(REFCLSID rclsid
  97.     , REFIID riid, PPVOID ppv)
  98.     {
  99.     HRESULT        hr;
  100.     IClassFactory *pObj;
  101.  
  102.     *ppv=NULL;
  103.  
  104.     //Check each of the three CLSIDs we support.
  105.     if (CLSID_DataObjectSmall==rclsid)
  106.         pObj=new CDataObjectClassFactory(DOSIZE_SMALL);
  107.  
  108.     if (CLSID_DataObjectMedium==rclsid)
  109.         pObj=new CDataObjectClassFactory(DOSIZE_MEDIUM);
  110.  
  111.     if (CLSID_DataObjectLarge==rclsid)
  112.         pObj=new CDataObjectClassFactory(DOSIZE_LARGE);
  113.  
  114.     if (NULL==pObj)
  115.         return ResultFromScode(E_OUTOFMEMORY);
  116.  
  117.     hr=pObj->QueryInterface(riid, ppv);
  118.  
  119.     if (FAILED(hr))
  120.         delete pObj;
  121.     else
  122.         g_cObj++;
  123.  
  124.     return hr;
  125.     }
  126.  
  127.  
  128.  
  129.  
  130.  
  131. /*
  132.  * DllCanUnloadNow
  133.  *
  134.  * Purpose:
  135.  *  Answers if the DLL can be freed, that is, if there are no
  136.  *  references to anything this DLL provides.
  137.  *
  138.  * Parameters:
  139.  *  None
  140.  *
  141.  * Return Value:
  142.  *  BOOL            TRUE if nothing is using us, FALSE otherwise.
  143.  */
  144.  
  145. STDAPI DllCanUnloadNow(void)
  146.     {
  147.     SCODE   sc;
  148.  
  149.     //Our answer is whether there are any object or locks
  150.     sc=(0L==g_cObj && 0L==g_cLock) ? S_OK : S_FALSE;
  151.     return ResultFromScode(sc);
  152.     }
  153.  
  154.  
  155.  
  156.  
  157. /*
  158.  * ObjectDestroyed
  159.  *
  160.  * Purpose:
  161.  *  Function for the Koala object to call when it gets destroyed.
  162.  *  Since we're in a DLL we only track the number of objects here,
  163.  *  letting DllCanUnloadNow take care of the rest.
  164.  */
  165.  
  166. void ObjectDestroyed(void)
  167.     {
  168.     g_cObj--;
  169.     return;
  170.     }
  171.  
  172.  
  173.  
  174.  
  175.  
  176. /*
  177.  * CDataObjectClassFactory::CDataObjectClassFactory
  178.  * CDataObjectClassFactory::~CDataObjectClassFactory
  179.  *
  180.  * Constructor Parameters:
  181.  *  iSize           UINT specifying the data size for this class.
  182.  */
  183.  
  184. CDataObjectClassFactory::CDataObjectClassFactory(UINT iSize)
  185.     {
  186.     m_cRef=0L;
  187.     m_iSize=iSize;
  188.     return;
  189.     }
  190.  
  191.  
  192. CDataObjectClassFactory::~CDataObjectClassFactory(void)
  193.     {
  194.     return;
  195.     }
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202. /*
  203.  * CDataObjectClassFactory::QueryInterface
  204.  * CDataObjectClassFactory::AddRef
  205.  * CDataObjectClassFactory::Release
  206.  */
  207.  
  208. STDMETHODIMP CDataObjectClassFactory::QueryInterface(REFIID riid
  209.     , PPVOID ppv)
  210.     {
  211.     *ppv=NULL;
  212.  
  213.     if (IID_IUnknown==riid || IID_IClassFactory==riid)
  214.         *ppv=this;
  215.  
  216.     if (NULL!=*ppv)
  217.         {
  218.         ((LPUNKNOWN)*ppv)->AddRef();
  219.         return NOERROR;
  220.         }
  221.  
  222.     return ResultFromScode(E_NOINTERFACE);
  223.     }
  224.  
  225.  
  226. STDMETHODIMP_(ULONG) CDataObjectClassFactory::AddRef(void)
  227.     {
  228.     return ++m_cRef;
  229.     }
  230.  
  231.  
  232. STDMETHODIMP_(ULONG) CDataObjectClassFactory::Release(void)
  233.     {
  234.     if (0!=--m_cRef)
  235.         return m_cRef;
  236.  
  237.     delete this;
  238.     ObjectDestroyed();
  239.     return 0;
  240.     }
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248. /*
  249.  * CDataObjectClassFactory::CreateInstance
  250.  *
  251.  * Purpose:
  252.  *  Instantiates a CDataObject object that supports the IDataObject
  253.  *  and IUnknown interfaces.  If the caller asks for a different
  254.  *  interface than these two then we fail.
  255.  *
  256.  * Parameters:
  257.  *  pUnkOuter       LPUNKNOWN to the controlling IUnknown if we are
  258.  *                  being used in an aggregation.
  259.  *  riid            REFIID identifying the interface the caller
  260.  *                  desires to have for the new object.
  261.  *  ppvObj          PPVOID in which to store the desired
  262.  *                  interface pointer for the new object.
  263.  *
  264.  * Return Value:
  265.  *  HRESULT         NOERROR if successful, otherwise E_NOINTERFACE
  266.  *                  if we cannot support the requested interface.
  267.  */
  268.  
  269. STDMETHODIMP CDataObjectClassFactory::CreateInstance
  270.     (LPUNKNOWN pUnkOuter, REFIID riid, PPVOID ppvObj)
  271.     {
  272.     PCDataObject        pObj;
  273.     HRESULT             hr;
  274.  
  275.     *ppvObj=NULL;
  276.     hr=ResultFromScode(E_OUTOFMEMORY);
  277.  
  278.     if (NULL!=pUnkOuter && IID_IUnknown!=riid)
  279.         return ResultFromScode(E_NOINTERFACE);
  280.  
  281.     //Create the object telling it the data size to work with
  282.     pObj=new CDataObject(pUnkOuter, ObjectDestroyed, m_iSize);
  283.  
  284.     if (NULL==pObj)
  285.         return hr;
  286.  
  287.     if (pObj->Init())
  288.         hr=pObj->QueryInterface(riid, ppvObj);
  289.  
  290.     //Kill the object if initial creation or FInit failed.
  291.     if (FAILED(hr))
  292.         delete pObj;
  293.     else
  294.         g_cObj++;
  295.  
  296.     return hr;
  297.     }
  298.  
  299.  
  300.  
  301.  
  302.  
  303. /*
  304.  * CDataObjectClassFactory::LockServer
  305.  *
  306.  * Purpose:
  307.  *  Increments or decrements the lock count of the serving
  308.  *  IClassFactory object.  When the number of locks goes to
  309.  *  zero and the number of objects is zero, we shut down the
  310.  *  application.
  311.  *
  312.  * Parameters:
  313.  *  fLock           BOOL specifying whether to increment or
  314.  *                  decrement the lock count.
  315.  *
  316.  * Return Value:
  317.  *  HRESULT         NOERROR always.
  318.  */
  319.  
  320. STDMETHODIMP CDataObjectClassFactory::LockServer(BOOL fLock)
  321.     {
  322.     if (fLock)
  323.         g_cLock++;
  324.     else
  325.         g_cLock--;
  326.  
  327.     return NOERROR;
  328.     }
  329.