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 / chap08 / polyline / dllpoly.cpp next >
C/C++ Source or Header  |  1996-05-21  |  8KB  |  343 lines

  1. /*
  2.  * DLLPOLY.CPP
  3.  * Polyline Component Chapter 8
  4.  *
  5.  * Polyline component object used in CoCosmo that supports a custom
  6.  * interface IPolyline.  Contains DLL entry code and the component
  7.  * object exports DllGetClassObject and DllCanUnloadNow and the
  8.  * class factory object.
  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. #define INITGUIDS
  19. #include "polyline.h"
  20.  
  21.  
  22. //Count number of objects and number of locks.
  23. ULONG       g_cObj=0;
  24. ULONG       g_cLock=0;
  25.  
  26. //DLL Instance handle
  27. HINSTANCE   g_hInst=0;
  28.  
  29.  
  30. /*
  31.  * LibMain32 (Win32)
  32.  *
  33.  * Purpose:
  34.  *  Entry point for Win32 DLLs that calls the Win16 LibMain.
  35.  */
  36.  
  37. #ifdef WIN32
  38. BOOL WINAPI LibMain32(HINSTANCE hInstance, ULONG ulReason
  39.     , LPVOID pvReserved)
  40.     {
  41.     if (DLL_PROCESS_DETACH==ulReason)
  42.         {
  43.         return TRUE;
  44.         }
  45.     else
  46.         {
  47.         if (DLL_PROCESS_ATTACH!=ulReason)
  48.             return TRUE;
  49.         }
  50.  
  51.     return (0!=LibMain(hInstance, 0,  0, NULL));
  52.     }
  53. #endif
  54.  
  55.  
  56.  
  57. /*
  58.  * LibMain (also called from Win32 LibMain32)
  59.  *
  60.  * Purpose:
  61.  *  DLL-specific entry point called from LibEntry.
  62.  */
  63.  
  64. int PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg
  65.     , WORD cbHeapSize, LPSTR lpCmdLine)
  66.     {
  67.     WNDCLASS    wc;
  68.  
  69.     if (GetClassInfo(hInst, SZCLASSPOLYLINE, &wc))
  70.         return (int)hInst;
  71.  
  72.    #ifndef WIN32
  73.     if (0!=cbHeapSize)
  74.         UnlockData(0);
  75.    #endif
  76.  
  77.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  78.     wc.hInstance     = hInst;
  79.     wc.cbClsExtra    = 0;
  80.     wc.lpfnWndProc   = PolylineWndProc;
  81.     wc.cbWndExtra    = CBPOLYLINEWNDEXTRA;
  82.     wc.hIcon         = NULL;
  83.     wc.hCursor       = LoadCursor(NULL, IDC_CROSS);
  84.     wc.hbrBackground = NULL;
  85.     wc.lpszMenuName  = NULL;
  86.     wc.lpszClassName = SZCLASSPOLYLINE;
  87.  
  88.     if (!RegisterClass(&wc))
  89.         return 0;
  90.  
  91.     g_hInst=hInst;
  92.     return (int)hInst;
  93.     }
  94.  
  95.  
  96.  
  97.  
  98.  
  99. /*
  100.  * DllGetClassObject
  101.  *
  102.  * Purpose:
  103.  *  Provides an IClassFactory for a given CLSID that this DLL is
  104.  *  registered to support.  This DLL is placed under the CLSID
  105.  *  in the registration database as the InProcServer.
  106.  *
  107.  * Parameters:
  108.  *  clsID           REFCLSID that identifies the class factory
  109.  *                  desired.  Since this parameter is passed this
  110.  *                  DLL can handle any number of objects simply
  111.  *                  by returning different class factories here
  112.  *                  for different CLSIDs.
  113.  *
  114.  *  riid            REFIID specifying the interface the caller wants
  115.  *                  on the class object, usually IID_ClassFactory.
  116.  *
  117.  *  ppv             PPVOID in which to return the interface
  118.  *                  pointer.
  119.  *
  120.  * Return Value:
  121.  *  HRESULT         NOERROR on success, otherwise an error code.
  122.  */
  123.  
  124. HRESULT APIENTRY DllGetClassObject(REFCLSID rclsid
  125.     , REFIID riid, PPVOID ppv)
  126.     {
  127.     //CHAPTER8MOD
  128.     if (CLSID_Polyline8!=rclsid)
  129.         return ResultFromScode(E_FAIL);
  130.     //End CHAPTER8MOD
  131.  
  132.     //Check that we can provide the interface
  133.     if (IID_IUnknown!=riid && IID_IClassFactory!=riid)
  134.         return ResultFromScode(E_NOINTERFACE);
  135.  
  136.     //Return our IClassFactory for Polyline objects
  137.     *ppv=new CPolylineClassFactory;
  138.  
  139.     if (NULL==*ppv)
  140.         return ResultFromScode(E_OUTOFMEMORY);
  141.  
  142.     //AddRef the object through any interface we return
  143.     ((LPUNKNOWN)*ppv)->AddRef();
  144.     g_cObj++;
  145.     return NOERROR;
  146.     }
  147.  
  148.  
  149.  
  150.  
  151.  
  152. /*
  153.  * DllCanUnloadNow
  154.  *
  155.  * Purpose:
  156.  *  Answers if the DLL can be freed, that is, if there are no
  157.  *  references to anything this DLL provides.
  158.  *
  159.  * Parameters:
  160.  *  None
  161.  *
  162.  * Return Value:
  163.  *  BOOL            TRUE if nothing is using us, FALSE otherwise.
  164.  */
  165.  
  166. STDAPI DllCanUnloadNow(void)
  167.     {
  168.     SCODE   sc;
  169.  
  170.     //Our answer is whether there are any object or locks
  171.     sc=(0L==g_cObj && 0L==g_cLock) ? S_OK : S_FALSE;
  172.     return ResultFromScode(sc);
  173.     }
  174.  
  175.  
  176.  
  177.  
  178. /*
  179.  * ObjectDestroyed
  180.  *
  181.  * Purpose:
  182.  *  Function for the Polyline object to call when it gets destroyed.
  183.  *  Since we're in a DLL we only track the number of objects here
  184.  *  letting DllCanUnloadNow take care of the rest.
  185.  */
  186.  
  187. void ObjectDestroyed(void)
  188.     {
  189.     g_cObj--;
  190.     return;
  191.     }
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198. /*
  199.  * CPolylineClassFactory::CPolylineClassFactory
  200.  * CPolylineClassFactory::~CPolylineClassFactory
  201.  */
  202.  
  203. CPolylineClassFactory::CPolylineClassFactory(void)
  204.     {
  205.     m_cRef=0L;
  206.     return;
  207.     }
  208.  
  209. CPolylineClassFactory::~CPolylineClassFactory(void)
  210.     {
  211.     return;
  212.     }
  213.  
  214.  
  215.  
  216.  
  217. /*
  218.  * CPolylineClassFactory::QueryInterface
  219.  * CPolylineClassFactory::AddRef
  220.  * CPolylineClassFactory::Release
  221.  */
  222.  
  223. STDMETHODIMP CPolylineClassFactory::QueryInterface(REFIID riid
  224.     , PPVOID ppv)
  225.     {
  226.     *ppv=NULL;
  227.  
  228.     if (IID_IUnknown==riid || IID_IClassFactory==riid)
  229.         *ppv=this;
  230.  
  231.     if (NULL!=*ppv)
  232.         {
  233.         ((LPUNKNOWN)*ppv)->AddRef();
  234.         return NOERROR;
  235.         }
  236.  
  237.     return ResultFromScode(E_NOINTERFACE);
  238.     }
  239.  
  240.  
  241. STDMETHODIMP_(ULONG) CPolylineClassFactory::AddRef(void)
  242.     {
  243.     return ++m_cRef;
  244.     }
  245.  
  246.  
  247. STDMETHODIMP_(ULONG) CPolylineClassFactory::Release(void)
  248.     {
  249.     if (0L!=--m_cRef)
  250.         return m_cRef;
  251.  
  252.     delete this;
  253.     ObjectDestroyed();
  254.     return 0L;
  255.     }
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263. /*
  264.  * CPolylineClassFactory::CreateInstance
  265.  *
  266.  * Purpose:
  267.  *  Instantiates a Polyline object.
  268.  *
  269.  * Parameters:
  270.  *  pUnkOuter       LPUNKNOWN to the controlling IUnknown if we
  271.  *                  are being used in an aggregation.
  272.  *  riid            REFIID identifying the interface the caller
  273.  *                  desires to have for the new object.
  274.  *  ppvObj          PPVOID in which to store the desired
  275.  *                  interface pointer for the new object.
  276.  *
  277.  * Return Value:
  278.  *  HRESULT         NOERROR if successful, otherwise E_NOINTERFACE
  279.  *                  if we cannot support the requested interface.
  280.  */
  281.  
  282. STDMETHODIMP CPolylineClassFactory::CreateInstance
  283.     (LPUNKNOWN pUnkOuter, REFIID riid, PPVOID ppvObj)
  284.     {
  285.     PCPolyline          pObj;
  286.     HRESULT             hr;
  287.  
  288.     *ppvObj=NULL;
  289.     hr=ResultFromScode(E_OUTOFMEMORY);
  290.  
  291.     //Verify that a controlling unknown asks for IUnknown
  292.     if (NULL!=pUnkOuter && IID_IUnknown!=riid)
  293.         return ResultFromScode(E_NOINTERFACE);
  294.  
  295.     //Create the object.  This also creates a window.
  296.     pObj=new CPolyline(pUnkOuter, ObjectDestroyed, g_hInst);
  297.  
  298.     if (NULL==pObj)
  299.         return hr;
  300.  
  301.     if (pObj->Init())
  302.         hr=pObj->QueryInterface(riid, ppvObj);
  303.  
  304.     //Kill the object if initial creation or Init failed.
  305.     if (FAILED(hr))
  306.         delete pObj;
  307.     else
  308.         g_cObj++;
  309.  
  310.     return hr;
  311.     }
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318. /*
  319.  * CPolylineClassFactory::LockServer
  320.  *
  321.  * Purpose:
  322.  *  Increments or decrements the lock count of the DLL.  If the lock
  323.  *  count goes to zero and there are no objects, the DLL is allowed
  324.  *  to unload.  See DllCanUnloadNow.
  325.  *
  326.  * Parameters:
  327.  *  fLock           BOOL specifying whether to increment or
  328.  *                  decrement the lock count.
  329.  *
  330.  * Return Value:
  331.  *  HRESULT         NOERROR always.
  332.  */
  333.  
  334. STDMETHODIMP CPolylineClassFactory::LockServer(BOOL fLock)
  335.     {
  336.     if (fLock)
  337.         g_cLock++;
  338.     else
  339.         g_cLock--;
  340.  
  341.     return NOERROR;
  342.     }
  343.