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 / chap12 / datatran / datatran.cpp < prev    next >
C/C++ Source or Header  |  1996-05-21  |  7KB  |  319 lines

  1. /*
  2.  * DATATRAN.CPP
  3.  * Data Transfer Object Chapter 12
  4.  *
  5.  * Transfer data object implemented in a DLL.  This data object will
  6.  * cache specific formats and renderings such that its IDataObject
  7.  * interface could be plopped on the clipboard or used in drag-drop.
  8.  *
  9.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Microsoft
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  */
  15.  
  16.  
  17. #define INITGUIDS
  18. #include "datatran.h"
  19.  
  20.  
  21. //Count number of objects and number of locks.
  22. ULONG       g_cObj=0;
  23. ULONG       g_cLock=0;
  24.  
  25. //Make this global for the data object to create listboxes.
  26. HINSTANCE   g_hInst=NULL;
  27.  
  28.  
  29.  
  30. /*
  31.  * LibMain(32)
  32.  *
  33.  * Purpose:
  34.  *  Entry point conditionally compiled for Windows NT and Windows
  35.  *  3.1.  Provides the proper structure for each environment.
  36.  */
  37.  
  38. #ifdef WIN32
  39. BOOL WINAPI LibMain32(HINSTANCE hInstance, ULONG ulReason
  40.     , LPVOID pvReserved)
  41.     {
  42.     if (DLL_PROCESS_DETACH==ulReason)
  43.         {
  44.         return TRUE;
  45.         }
  46.     else
  47.         {
  48.         if (DLL_PROCESS_ATTACH!=ulReason)
  49.             return TRUE;
  50.         }
  51.  
  52.     return TRUE;
  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.     //Check that we can provide the interface
  100.     if (IID_IUnknown!=riid && IID_IClassFactory!=riid)
  101.         return ResultFromScode(E_NOINTERFACE);
  102.  
  103.     *ppv=NULL;
  104.  
  105.     //Check each of the three CLSIDs we support.
  106.     if (CLSID_DataTransferObject==rclsid)
  107.         *ppv=new CDataTransferClassFactory();
  108.  
  109.     if (NULL==*ppv)
  110.         return ResultFromScode(E_OUTOFMEMORY);
  111.  
  112.     ((LPUNKNOWN)*ppv)->AddRef();
  113.     g_cObj++;
  114.     return NOERROR;
  115.     }
  116.  
  117.  
  118.  
  119.  
  120.  
  121. /*
  122.  * DllCanUnloadNow
  123.  *
  124.  * Purpose:
  125.  *  Answers if the DLL can be freed, that is, if there are no
  126.  *  references to anything this DLL provides.
  127.  *
  128.  * Parameters:
  129.  *  None
  130.  *
  131.  * Return Value:
  132.  *  BOOL            TRUE if nothing is using us, FALSE otherwise.
  133.  */
  134.  
  135. STDAPI DllCanUnloadNow(void)
  136.     {
  137.     SCODE   sc;
  138.  
  139.     //Our answer is whether there are any object or locks
  140.     sc=(0L==g_cObj && 0L==g_cLock) ? S_OK : S_FALSE;
  141.     return ResultFromScode(sc);
  142.     }
  143.  
  144.  
  145.  
  146.  
  147. /*
  148.  * ObjectDestroyed
  149.  *
  150.  * Purpose:
  151.  *  Function for the DataObject object to call when it gets
  152.  *  destroyed.  Since we're in a DLL we only track the number
  153.  *  of objects here letting DllCanUnloadNow take care of the rest.
  154.  */
  155.  
  156. void ObjectDestroyed(void)
  157.     {
  158.     g_cObj--;
  159.     return;
  160.     }
  161.  
  162.  
  163.  
  164.  
  165.  
  166. /*
  167.  * CDataTransferClassFactory::CDataTransferClassFactory
  168.  * CDataTransferClassFactory::~CDataTransferClassFactory
  169.  *
  170.  * Constructor Parameters:
  171.  *  None
  172.  */
  173.  
  174. CDataTransferClassFactory::CDataTransferClassFactory(void)
  175.     {
  176.     m_cRef=0L;
  177.     return;
  178.     }
  179.  
  180.  
  181. CDataTransferClassFactory::~CDataTransferClassFactory(void)
  182.     {
  183.     return;
  184.     }
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191. /*
  192.  * CDataTransferClassFactory::QueryInterface
  193.  * CDataTransferClassFactory::AddRef
  194.  * CDataTransferClassFactory::Release
  195.  */
  196.  
  197. STDMETHODIMP CDataTransferClassFactory::QueryInterface
  198.     (REFIID riid, PPVOID ppv)
  199.     {
  200.     *ppv=NULL;
  201.  
  202.     //Any interface on this object is the object pointer.
  203.     if (IID_IUnknown==riid || IID_IClassFactory==riid)
  204.         *ppv=this;
  205.  
  206.     if (NULL!=*ppv)
  207.         {
  208.         ((LPUNKNOWN)*ppv)->AddRef();
  209.         return NOERROR;
  210.         }
  211.  
  212.     return ResultFromScode(E_NOINTERFACE);
  213.     }
  214.  
  215.  
  216. STDMETHODIMP_(ULONG) CDataTransferClassFactory::AddRef(void)
  217.     {
  218.     return ++m_cRef;
  219.     }
  220.  
  221.  
  222. STDMETHODIMP_(ULONG) CDataTransferClassFactory::Release(void)
  223.     {
  224.     if (0!=--m_cRef)
  225.         return m_cRef;
  226.  
  227.     delete this;
  228.     ObjectDestroyed();
  229.     return 0;
  230.     }
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238. /*
  239.  * CDataTransferClassFactory::CreateInstance
  240.  *
  241.  * Purpose:
  242.  *  Instantiates a DataObject object that supports the IDataObject
  243.  *  and IUnknown interfaces.  If the caller asks for a different
  244.  *  interface than these two then we fail.
  245.  *
  246.  * Parameters:
  247.  *  pUnkOuter       LPUNKNOWN to the controlling IUnknown if we
  248.  *                  are being used in an aggregation.
  249.  *  riid            REFIID identifying the interface the caller
  250.  *                  desires to have for the new object.
  251.  *  ppvObj          PPVOID in which to store the desired
  252.  *                  interface pointer for the new object.
  253.  *
  254.  * Return Value:
  255.  *  HRESULT         NOERROR if successful, otherwise E_NOINTERFACE
  256.  *                  if we cannot support the requested interface.
  257.  */
  258.  
  259. STDMETHODIMP CDataTransferClassFactory::CreateInstance
  260.     (LPUNKNOWN pUnkOuter, REFIID riid, PPVOID ppvObj)
  261.     {
  262.     PCDataObject        pObj;
  263.     HRESULT             hr;
  264.  
  265.     *ppvObj=NULL;
  266.     hr=ResultFromScode(E_OUTOFMEMORY);
  267.  
  268.     if (NULL!=pUnkOuter && IID_IUnknown!=riid)
  269.         return ResultFromScode(E_NOINTERFACE);
  270.  
  271.     //Create the object telling it the data size to work with
  272.     pObj=new CDataObject(pUnkOuter, ObjectDestroyed);
  273.  
  274.     if (NULL==pObj)
  275.         return hr;
  276.  
  277.     if (pObj->Init())
  278.         hr=pObj->QueryInterface(riid, ppvObj);
  279.  
  280.     //Kill the object if initial creation or Init failed.
  281.     if (FAILED(hr))
  282.         delete pObj;
  283.     else
  284.         g_cObj++;
  285.  
  286.     return hr;
  287.     }
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294. /*
  295.  * CDataTransferClassFactory::LockServer
  296.  *
  297.  * Purpose:
  298.  *  Increments or decrements the lock count of the DLL.  If the lock
  299.  *  count goes to zero and there are no objects, the DLL is allowed
  300.  *  to unload.  See DllCanUnloadNow.
  301.  *
  302.  * Parameters:
  303.  *  fLock           BOOL specifying whether to increment or
  304.  *                  decrement the lock count.
  305.  *
  306.  * Return Value:
  307.  *  HRESULT         NOERROR always.
  308.  */
  309.  
  310. STDMETHODIMP CDataTransferClassFactory::LockServer(BOOL fLock)
  311.     {
  312.     if (fLock)
  313.         g_cLock++;
  314.     else
  315.         g_cLock--;
  316.  
  317.     return NOERROR;
  318.     }
  319.