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 / edataobj / edataobj.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  9.2 KB  |  440 lines

  1. /*
  2.  * EDATAOBJ.CPP
  3.  * Data Object EXE Chapter 10
  4.  *
  5.  * Data Object implemented in an application.  This object supports
  6.  * IUnknown and IDataObject interfaces.
  7.  *
  8.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Microsoft
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #define INITGUIDS
  17. #include "edataobj.h"
  18.  
  19.  
  20. //Count number of objects and number of locks.
  21. ULONG       g_cObj=0;
  22. ULONG       g_cLock=0;
  23.  
  24. //Make window handle global so other code can cause a shutdown
  25. HWND        g_hWnd=NULL;
  26. HINSTANCE   g_hInst=NULL;
  27.  
  28.  
  29.  
  30. /*
  31.  * WinMain
  32.  *
  33.  * Purpose:
  34.  *  Main entry point of application.
  35.  */
  36.  
  37. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev
  38.     , LPSTR pszCmdLine, int nCmdShow)
  39.     {
  40.     MSG     msg;
  41.     PAPP    pApp;
  42.  
  43.     SETMESSAGEQUEUE(96);
  44.  
  45.     g_hInst=hInst;
  46.  
  47.     pApp=new CApp(hInst, hInstPrev, pszCmdLine, nCmdShow);
  48.  
  49.     if (NULL==pApp)
  50.         return -1;
  51.  
  52.     if (pApp->Init())
  53.         {
  54.         while (GetMessage(&msg, NULL, 0,0 ))
  55.             {
  56.             TranslateMessage(&msg);
  57.             DispatchMessage(&msg);
  58.             }
  59.         }
  60.  
  61.     delete pApp;
  62.     return msg.wParam;
  63.     }
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71. /*
  72.  * DataObjectWndProc
  73.  *
  74.  * Purpose:
  75.  *  Standard window class procedure.
  76.  */
  77.  
  78. LRESULT APIENTRY DataObjectWndProc(HWND hWnd, UINT iMsg
  79.     , WPARAM wParam, LPARAM lParam)
  80.     {
  81.     switch (iMsg)
  82.         {
  83.         case WM_DESTROY:
  84.             PostQuitMessage(0);
  85.             break;
  86.  
  87.         default:
  88.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  89.         }
  90.  
  91.     return 0L;
  92.     }
  93.  
  94.  
  95.  
  96.  
  97.  
  98. /*
  99.  * ObjectDestroyed
  100.  *
  101.  * Purpose:
  102.  *  Function for the DataObject object to call when it gets
  103.  *  destroyed. We destroy the main window if the proper
  104.  *  conditions are met for shutdown.
  105.  */
  106.  
  107. void ObjectDestroyed(void)
  108.     {
  109.     g_cObj--;
  110.  
  111.     //No more objects and no locks, shut the app down.
  112.     if (0L==g_cObj && 0L==g_cLock && IsWindow(g_hWnd))
  113.         PostMessage(g_hWnd, WM_CLOSE, 0, 0L);
  114.  
  115.     return;
  116.     }
  117.  
  118.  
  119.  
  120.  
  121. /*
  122.  * CApp::CApp
  123.  * CApp::~CApp
  124.  *
  125.  * Constructor Parameters:
  126.  *  hInst           HINSTANCE of the Application from WinMain
  127.  *  hInstPrev       HINSTANCE of a previous instance from WinMain
  128.  *  pszCmdLine      LPSTR of the command line.
  129.  *  nCmdShow        UINT specifying how to show the app window,
  130.  *                  from WinMain.
  131.  */
  132.  
  133. CApp::CApp(HINSTANCE hInst, HINSTANCE hInstPrev
  134.     , LPSTR pszCmdLine, UINT nCmdShow)
  135.     {
  136.     UINT        i;
  137.  
  138.     m_hInst     =hInst;
  139.     m_hInstPrev =hInstPrev;
  140.     m_pszCmdLine=pszCmdLine;
  141.  
  142.     m_hWnd=NULL;
  143.  
  144.     for (i=0; i < DOSIZE_CSIZES; i++)
  145.         {
  146.         m_rgdwRegCO[i]=0;
  147.         m_rgpIClassFactory[i]=NULL;
  148.         }
  149.  
  150.     m_fInitialized=FALSE;
  151.     return;
  152.     }
  153.  
  154.  
  155. CApp::~CApp(void)
  156.     {
  157.     UINT        i;
  158.  
  159.     //Revoke and destroy the class factories of all sizes
  160.     for (i=0; i < DOSIZE_CSIZES; i++)
  161.         {
  162.         if (0L!=m_rgdwRegCO[i])
  163.             CoRevokeClassObject(m_rgdwRegCO[i]);
  164.  
  165.         ReleaseInterface(m_rgpIClassFactory[i]);
  166.         }
  167.  
  168.     if (m_fInitialized)
  169.         CoUninitialize();
  170.  
  171.     return;
  172.     }
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179. /*
  180.  * CApp::Init
  181.  *
  182.  * Purpose:
  183.  *  Initializes an CApp object by registering window classes,
  184.  *  creating the main window, and doing anything else prone to
  185.  *  failure.  If this function fails the caller should guarantee
  186.  *  that the destructor is called.
  187.  *
  188.  * Parameters:
  189.  *  None
  190.  *
  191.  * Return Value:
  192.  *  BOOL            TRUE if successful, FALSE otherwise.
  193.  */
  194.  
  195. BOOL CApp::Init(void)
  196.     {
  197.     WNDCLASS        wc;
  198.     HRESULT         hr, hr2, hr3;
  199.     UINT            i;
  200.  
  201.     CHECKVER_COM;
  202.  
  203.     //Check command line for -Embedding
  204.     if (lstrcmpiA(m_pszCmdLine, "-Embedding"))
  205.         return FALSE;
  206.  
  207.     if (FAILED(CoInitialize(NULL)))
  208.         return FALSE;
  209.  
  210.     m_fInitialized=TRUE;
  211.  
  212.     if (!m_hInstPrev)
  213.         {
  214.         wc.style          = CS_HREDRAW | CS_VREDRAW;
  215.         wc.lpfnWndProc    = DataObjectWndProc;
  216.         wc.cbClsExtra     = 0;
  217.         wc.cbWndExtra     = 0;
  218.         wc.hInstance      = m_hInst;
  219.         wc.hIcon          = NULL;
  220.         wc.hCursor        = NULL;
  221.         wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  222.         wc.lpszMenuName   = NULL;
  223.         wc.lpszClassName  = TEXT("EXEDataObject");
  224.  
  225.         if (!RegisterClass(&wc))
  226.             return FALSE;
  227.         }
  228.  
  229.     m_hWnd=CreateWindow(TEXT("EXEDataObject")
  230.         , TEXT("EXE DataObject"), WS_OVERLAPPEDWINDOW
  231.         , 35, 35, 350, 250, NULL, NULL, m_hInst, NULL);
  232.  
  233.     if (NULL==m_hWnd)
  234.         return FALSE;
  235.  
  236.     g_hWnd=m_hWnd;
  237.  
  238.     /*
  239.      * This code supplies three different classes, one for each type
  240.      * of data object that handles a different size of data. All the
  241.      * class factories share the same implementation, but their
  242.      * instantiations differ by the type passed in the constructor.
  243.      * When the class factories create objects, they pass that size
  244.      * to the CDataObject contstructor as well.
  245.      */
  246.  
  247.     for (i=0; i < DOSIZE_CSIZES; i++)
  248.         {
  249.         m_rgpIClassFactory[i]=new CDataObjectClassFactory(i);
  250.  
  251.         if (NULL==m_rgpIClassFactory[i])
  252.             return FALSE;
  253.  
  254.         m_rgpIClassFactory[i]->AddRef();
  255.         }
  256.  
  257.     hr=CoRegisterClassObject(CLSID_DataObjectSmall
  258.         , m_rgpIClassFactory[0], CLSCTX_LOCAL_SERVER
  259.         , REGCLS_MULTIPLEUSE, &m_rgdwRegCO[0]);
  260.  
  261.     hr2=CoRegisterClassObject(CLSID_DataObjectMedium
  262.         , m_rgpIClassFactory[1], CLSCTX_LOCAL_SERVER
  263.         , REGCLS_MULTIPLEUSE, &m_rgdwRegCO[1]);
  264.  
  265.     hr3=CoRegisterClassObject(CLSID_DataObjectLarge
  266.         , m_rgpIClassFactory[2], CLSCTX_LOCAL_SERVER
  267.         , REGCLS_MULTIPLEUSE, &m_rgdwRegCO[2]);
  268.  
  269.     if (FAILED(hr) || FAILED(hr2) || FAILED(hr3))
  270.         return FALSE;
  271.  
  272.     return TRUE;
  273.     }
  274.  
  275.  
  276.  
  277.  
  278.  
  279. /*
  280.  * CDataObjectClassFactory::CDataObjectClassFactory
  281.  * CDataObjectClassFactory::~CDataObjectClassFactory
  282.  *
  283.  * Constructor Parameters:
  284.  *  iSize           UINT specifying the data size for this class.
  285.  */
  286.  
  287. CDataObjectClassFactory::CDataObjectClassFactory(UINT iSize)
  288.     {
  289.     m_cRef=0L;
  290.     m_iSize=iSize;
  291.     return;
  292.     }
  293.  
  294.  
  295. CDataObjectClassFactory::~CDataObjectClassFactory(void)
  296.     {
  297.     return;
  298.     }
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305. /*
  306.  * CDataObjectClassFactory::QueryInterface
  307.  * CDataObjectClassFactory::AddRef
  308.  * CDataObjectClassFactory::Release
  309.  */
  310.  
  311. STDMETHODIMP CDataObjectClassFactory::QueryInterface(REFIID riid
  312.     , PPVOID ppv)
  313.     {
  314.     *ppv=NULL;
  315.  
  316.     if (IID_IUnknown==riid || IID_IClassFactory==riid)
  317.         *ppv=this;
  318.  
  319.     if (NULL!=*ppv)
  320.         {
  321.         ((LPUNKNOWN)*ppv)->AddRef();
  322.         return NOERROR;
  323.         }
  324.  
  325.     return ResultFromScode(E_NOINTERFACE);
  326.     }
  327.  
  328.  
  329. STDMETHODIMP_(ULONG) CDataObjectClassFactory::AddRef(void)
  330.     {
  331.     return ++m_cRef;
  332.     }
  333.  
  334.  
  335. STDMETHODIMP_(ULONG) CDataObjectClassFactory::Release(void)
  336.     {
  337.     if (0!=--m_cRef)
  338.         return m_cRef;
  339.  
  340.     delete this;
  341.     return 0;
  342.     }
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.  
  350. /*
  351.  * CDataObjectClassFactory::CreateInstance
  352.  *
  353.  * Purpose:
  354.  *  Instantiates a CDataObject object that supports the IDataObject
  355.  *  and IUnknown interfaces.  If the caller asks for a different
  356.  *  interface than these two then we fail.
  357.  *
  358.  * Parameters:
  359.  *  pUnkOuter       LPUNKNOWN to the controlling IUnknown if we are
  360.  *                  being used in an aggregation.
  361.  *  riid            REFIID identifying the interface the caller
  362.  *                  desires to have for the new object.
  363.  *  ppvObj          PPVOID in which to store the desired interface
  364.  *                  pointer for the new object.
  365.  *
  366.  * Return Value:
  367.  *  HRESULT         NOERROR if successful, otherwise contains
  368.  *                  E_NOINTERFACE if we cannot support the
  369.  *                  requested interface.
  370.  */
  371.  
  372. STDMETHODIMP CDataObjectClassFactory::CreateInstance
  373.     (LPUNKNOWN pUnkOuter, REFIID riid, PPVOID ppvObj)
  374.     {
  375.     PCDataObject        pObj;
  376.     HRESULT             hr;
  377.  
  378.     *ppvObj=NULL;
  379.     hr=ResultFromScode(E_OUTOFMEMORY);
  380.  
  381.     if (NULL!=pUnkOuter && IID_IUnknown!=riid)
  382.         return ResultFromScode(E_NOINTERFACE);
  383.  
  384.     //Create the object telling it the data size to work with
  385.     pObj=new CDataObject(pUnkOuter, ObjectDestroyed, m_iSize);
  386.  
  387.     if (NULL==pObj)
  388.         return hr;
  389.  
  390.     if (pObj->Init())
  391.         hr=pObj->QueryInterface(riid, ppvObj);
  392.  
  393.     g_cObj++;
  394.  
  395.     if (FAILED(hr))
  396.         {
  397.         delete pObj;
  398.         ObjectDestroyed();  //Decrements g_cObj
  399.         }
  400.  
  401.     return hr;
  402.     }
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409. /*
  410.  * CDataObjectClassFactory::LockServer
  411.  *
  412.  * Purpose:
  413.  *  Increments or decrements the lock count of the serving
  414.  *  IClassFactory object.  When the number of locks goes to
  415.  *  zero and the number of objects is zero, we shut down the
  416.  *  application.
  417.  *
  418.  * Parameters:
  419.  *  fLock           BOOL specifying whether to increment or
  420.  *                  decrement the lock count.
  421.  *
  422.  * Return Value:
  423.  *  HRESULT         NOERROR always.
  424.  */
  425.  
  426. STDMETHODIMP CDataObjectClassFactory::LockServer(BOOL fLock)
  427.     {
  428.     if (fLock)
  429.         g_cLock++;
  430.     else
  431.         {
  432.         g_cLock--;
  433.  
  434.         g_cObj++;
  435.         ObjectDestroyed();
  436.         }
  437.  
  438.     return NOERROR;
  439.     }
  440.