home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / tutsamp / licserve / sample.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-05  |  16.0 KB  |  487 lines

  1. /*+==========================================================================
  2.   File:      SAMPLE.CPP
  3.  
  4.   Summary:   Implementation file for the COLicCarSample sample utility COM
  5.              object.  This object exposes the ISample interface that is
  6.              used to allow better integration of server with client as a
  7.              code sample (eg, set up trace logging from server to client's
  8.              log display).
  9.  
  10.              For a comprehensive tutorial code tour of this module's
  11.              contents and offerings see the tutorial LICSERVE.HTM file.
  12.              For more specific technical details on the internal workings
  13.              see the comments dispersed throughout the module's source code.
  14.  
  15.   Classes:   COLicCarSample.
  16.  
  17.   Functions:
  18.  
  19.   Origin:    10-5-95: atrent - Editor-inheritance from SAMPLE.CPP in
  20.                the DLLSERVE Tutorial Code Sample.
  21.  
  22. ----------------------------------------------------------------------------
  23.   This file is part of the Microsoft COM Tutorial Code Samples.
  24.  
  25.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  26.  
  27.   This source code is intended only as a supplement to Microsoft
  28.   Development Tools and/or on-line documentation.  See these other
  29.   materials for detailed information regarding Microsoft code samples.
  30.  
  31.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  32.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  33.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  34.   PARTICULAR PURPOSE.
  35. ==========================================================================+*/
  36.  
  37. /*---------------------------------------------------------------------------
  38.   We include WINDOWS.H for all Win32 applications.
  39.   We include OLE2.H because we will be calling the COM/OLE Libraries.
  40.   We include APPUTIL.H because we will be building this DLL using
  41.     the convenient Virtual Window and Dialog classes and other
  42.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  43.   We include ICARS.H and CARGUIDS.H for the common car-related Interface
  44.     class, GUID, and CLSID specifications.
  45.   We include SERVER.H for the object class declarations for the
  46.     CServer server control object.
  47.   We include SAMPLE.H for the object class declarations for the
  48.     COLicCarSample COM object.
  49. ---------------------------------------------------------------------------*/
  50. #include <windows.h>
  51. #include <ole2.h>
  52. #include <apputil.h>
  53. #include <icars.h>
  54. #include <carguids.h>
  55. #include "server.h"
  56. #include "sample.h"
  57.  
  58. /*---------------------------------------------------------------------------
  59.   Implementation the COLicCarSample COM object.  Used to expose a utility
  60.   server interface for the server as a code sample.  COLicCarSample exposes
  61.   the ISample interface.
  62. ---------------------------------------------------------------------------*/
  63.  
  64. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  65.   Method:   COLicCarSample::COLicCarSample
  66.  
  67.   Summary:  COLicCarSample Constructor. Note the member initializer:
  68.             "m_ImpISample(this, pUnkOuter, pServer)" which is used to pass
  69.             the 'this', pUnkOuter, and pServer pointers of this
  70.             constructor function to the constructor in the instantiation
  71.             of the implementation of the CImpISample interface (which is
  72.             nested inside this present COLicCarSample Object Class).
  73.  
  74.   Args:     IUnknown* pUnkOuter,
  75.               Pointer to the the outer Unknown.  NULL means this COM Object
  76.               is not being Aggregated.  Non NULL means it is being created
  77.               on behalf of an outside COM object that is reusing it via
  78.               aggregation.
  79.             CServer* pServer
  80.               Pointer to the server's control object.
  81.  
  82.   Modifies: m_cRefs, m_pUnkOuter.
  83.  
  84.   Returns:  void
  85. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  86. COLicCarSample::COLicCarSample(
  87.   IUnknown* pUnkOuter,
  88.   CServer* pServer) :
  89.   m_ImpISample(this, pUnkOuter, pServer)
  90. {
  91.   // Zero the COM object's reference count.
  92.   m_cRefs = 0;
  93.  
  94.   // No AddRef necessary if non-NULL, as we're nested.
  95.   m_pUnkOuter = pUnkOuter;
  96.  
  97.   // Init the pointer to the server's control object.
  98.   m_pServer = pServer;
  99.  
  100.   LOGF1("P: COLicCarSample Constructor. m_pUnkOuter=0x%X.", m_pUnkOuter);
  101.  
  102.   return;
  103. }
  104.  
  105.  
  106. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  107.   Method:   COLicCarSample::~COLicCarSample
  108.  
  109.   Summary:  COLicCarSample Destructor.
  110.  
  111.   Args:     void
  112.  
  113.   Modifies: .
  114.  
  115.   Returns:  void
  116. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  117. COLicCarSample::~COLicCarSample(void)
  118. {
  119.   LOG("P: COLicCarSample::Destructor.");
  120.  
  121.   return;
  122. }
  123.  
  124.  
  125. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  126.   Method:   COLicCarSample::QueryInterface
  127.  
  128.   Summary:  QueryInterface of the COLicCarSample non-delegating
  129.             IUnknown implementation.
  130.  
  131.   Args:     REFIID riid,
  132.               [in] GUID of the Interface being requested.
  133.             PPVOID ppv)
  134.               [out] Address of the caller's pointer variable that will
  135.               receive the requested interface pointer.
  136.  
  137.   Modifies: .
  138.  
  139.   Returns:  HRESULT
  140. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  141. STDMETHODIMP COLicCarSample::QueryInterface(
  142.                REFIID riid,
  143.                PPVOID ppv)
  144. {
  145.   HRESULT hr = E_NOINTERFACE;
  146.   *ppv = NULL;
  147.  
  148.   if (IID_IUnknown == riid)
  149.   {
  150.     *ppv = this;
  151.     LOG("P: COLicCarSample::QueryInterface. 'this' pIUnknown returned.");
  152.   }
  153.   else if (IID_ISample == riid)
  154.   {
  155.     *ppv = &m_ImpISample;
  156.     LOG("P: COLicCarSample::QueryInterface. pISample returned.");
  157.   }
  158.  
  159.   if (NULL != *ppv)
  160.   {
  161.     // We've handed out a pointer to the interface so obey the COM rules
  162.     // and AddRef the reference count.
  163.     ((LPUNKNOWN)*ppv)->AddRef();
  164.     hr = NOERROR;
  165.   }
  166.  
  167.   return (hr);
  168. }
  169.  
  170.  
  171. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  172.   Method:   COLicCarSample::AddRef
  173.  
  174.   Summary:  AddRef of the COLicCarSample non-delegating IUnknown
  175.             implementation.
  176.  
  177.   Args:     void
  178.  
  179.   Modifies: m_cRefs.
  180.  
  181.   Returns:  ULONG
  182.               New value of m_cRefs (COM object's reference count).
  183. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  184. STDMETHODIMP_(ULONG) COLicCarSample::AddRef(void)
  185. {
  186.   m_cRefs++;
  187.  
  188.   LOGF1("P: COLicCarSample::AddRef. New cRefs=%i.", m_cRefs);
  189.  
  190.   return m_cRefs;
  191. }
  192.  
  193.  
  194. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  195.   Method:   COLicCarSample::Release
  196.  
  197.   Summary:  Release of the COLicCarSample non-delegating IUnknown
  198.             implementation.
  199.  
  200.   Args:     void
  201.  
  202.   Modifies: m_cRefs.
  203.  
  204.   Returns:  ULONG
  205.               New value of m_cRefs (COM object's reference count).
  206. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  207. STDMETHODIMP_(ULONG) COLicCarSample::Release(void)
  208. {
  209.   m_cRefs--;
  210.  
  211.   LOGF1("P: COLicCarSample::Release. New cRefs=%i.", m_cRefs);
  212.  
  213.   if (0 == m_cRefs)
  214.   {
  215.     // We've reached a zero reference count for this COM object.
  216.     // So we tell the server housing to decrement its global object
  217.     // count so that the server will be unloaded if appropriate.
  218.     if (NULL != m_pServer)
  219.       m_pServer->ObjectsDown();
  220.  
  221.     // We artificially bump the main ref count to prevent reentrancy
  222.     // via the main object destructor.  Not really needed in this
  223.     // COLicCarSample but a good practice because we are aggregatable and
  224.     // may at some point in the future add something entertaining like
  225.     // some Releases to the COLicCarSample destructor.
  226.     m_cRefs++;
  227.     delete this;
  228.   }
  229.  
  230.   return m_cRefs;
  231. }
  232.  
  233.  
  234. /*---------------------------------------------------------------------------
  235.   COLicCarSample's nested implementation of the ISample interface
  236.   including Constructor, Destructor, QueryInterface, AddRef, Release,
  237.   Init, and AboutBox methods.
  238. ---------------------------------------------------------------------------*/
  239.  
  240. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  241.   Method:   COLicCarSample::CImpISample::CImpISample
  242.  
  243.   Summary:  Constructor for the CImpISample interface instantiation.
  244.  
  245.   Args:     COLicCarSample* pBackObj,
  246.               Back pointer to the parent outer object.
  247.             IUnknown* pUnkOuter,
  248.               Pointer to the outer Unknown.  For delegation.
  249.             CServer* pServer)
  250.               Pointer to the server's control object.
  251.  
  252.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter, m_pServer.
  253.  
  254.   Returns:  void
  255. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  256. COLicCarSample::CImpISample::CImpISample(
  257.   COLicCarSample* pBackObj,
  258.   IUnknown* pUnkOuter,
  259.   CServer* pServer)
  260. {
  261.   // Init the Interface Ref Count (used for debugging only).
  262.   m_cRefI = 0;
  263.  
  264.   // Init the Back Object Pointer to point to the outer object.
  265.   m_pBackObj = pBackObj;
  266.  
  267.   // Init the pointer to the server control object.
  268.   m_pServer = pServer;
  269.  
  270.   // Init the CImpISample interface's delegating Unknown pointer.  We use
  271.   // the Back Object pointer for IUnknown delegation here if we are not
  272.   // being aggregated.  If we are being aggregated we use the supplied
  273.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  274.   // assignment requires no AddRef because the CImpISample lifetime is
  275.   // quaranteed by the lifetime of the parent object in which
  276.   // CImpISample is nested.
  277.   if (NULL == pUnkOuter)
  278.   {
  279.     m_pUnkOuter = pBackObj;
  280.     LOG("P: COLicCarSample::CImpISample Constructor. Non-Aggregating.");
  281.   }
  282.   else
  283.   {
  284.     m_pUnkOuter = pUnkOuter;
  285.     LOG("P: COLicCarSample::CImpISample Constructor. Aggregating.");
  286.   }
  287.  
  288.   return;
  289. }
  290.  
  291.  
  292. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  293.   Method:   COLicCarSample::CImpISample::~CImpISample
  294.  
  295.   Summary:  Destructor for the CImpISample interface instantiation.
  296.  
  297.   Args:     void
  298.  
  299.   Modifies: .
  300.  
  301.   Returns:  void
  302. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  303. COLicCarSample::CImpISample::~CImpISample(void)
  304. {
  305.   LOG("P: COLicCarSample::CImpISample Destructor.");
  306.  
  307.   return;
  308. }
  309.  
  310.  
  311. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  312.   Method:   COLicCarSample::CImpISample::QueryInterface
  313.  
  314.   Summary:  The QueryInterface IUnknown member of this ISample interface
  315.             implementation that delegates to m_pUnkOuter, whatever it is.
  316.  
  317.   Args:     REFIID riid,
  318.               [in] GUID of the Interface being requested.
  319.             PPVOID ppv)
  320.               [out] Address of the caller's pointer variable that will
  321.               receive the requested interface pointer.
  322.  
  323.   Modifies: .
  324.  
  325.   Returns:  HRESULT
  326.               Returned by the delegated outer QueryInterface call.
  327. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  328. STDMETHODIMP COLicCarSample::CImpISample::QueryInterface(
  329.                REFIID riid,
  330.                PPVOID ppv)
  331. {
  332.   LOG("P: COLicCarSample::CImpISample::QueryInterface. Delegating.");
  333.  
  334.   // Delegate this call to the outer object's QueryInterface.
  335.   return m_pUnkOuter->QueryInterface(riid, ppv);
  336. }
  337.  
  338.  
  339. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  340.   Method:   COLicCarSample::CImpISample::AddRef
  341.  
  342.   Summary:  The AddRef IUnknown member of this ISample interface
  343.             implementation that delegates to m_pUnkOuter, whatever it is.
  344.  
  345.   Args:     void
  346.  
  347.   Modifies: m_cRefI.
  348.  
  349.   Returns:  ULONG
  350.               Returned by the delegated outer AddRef call.
  351. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  352. STDMETHODIMP_(ULONG) COLicCarSample::CImpISample::AddRef(void)
  353. {
  354.   // Increment the Interface Reference Count.
  355.   ++m_cRefI;
  356.  
  357.   LOGF1("P: COLicCarSample::CImpISample::Addref. Delegating. New cI=%i.", m_cRefI);
  358.  
  359.   // Delegate this call to the outer object's AddRef.
  360.   return m_pUnkOuter->AddRef();
  361. }
  362.  
  363.  
  364. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  365.   Method:   COLicCarSample::CImpISample::Release
  366.  
  367.   Summary:  The Release IUnknown member of this ISample interface
  368.             implementation that delegates to m_pUnkOuter, whatever it is.
  369.  
  370.   Args:     void
  371.  
  372.   Modifies: .
  373.  
  374.   Returns:  ULONG
  375.               Returned by the delegated outer Release call.
  376. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  377. STDMETHODIMP_(ULONG) COLicCarSample::CImpISample::Release(void)
  378. {
  379.   // Decrement the Interface Reference Count.
  380.   --m_cRefI;
  381.  
  382.   LOGF1("P: COLicCarSample::CImpISample::Release. Delegating. New cI=%i.", m_cRefI);
  383.  
  384.   // Delegate this call to the outer object's Release.
  385.   return m_pUnkOuter->Release();
  386. }
  387.  
  388.  
  389. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  390.   Method:   COLicCarSample::CImpISample::Init
  391.  
  392.   Summary:  Initialize the COLicCarSample object to enable trace logging
  393.             from server to client.  This includes passing in a pointer
  394.             that points the Client EXE's MsgLog facility so that the
  395.             LOG* trace logging macros in the server will be logged in
  396.             the Client's message log window.  This Init function also
  397.             rigs up the same kind of trace logging for the subordinate
  398.             DLLSERVE server.
  399.  
  400.   Args:     HWND hWndParent
  401.               [in] Handle of a client's parent owning window.
  402.             PVOID pvMsgLog
  403.               [in] Pointer to the Client's MsgLog object.  If NULL
  404.               then setup independent logging window for this DLL.
  405.  
  406.   Modifies: .
  407.  
  408.   Returns:  HRESULT
  409.               Standard result code. NOERROR for success.
  410. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  411. STDMETHODIMP COLicCarSample::CImpISample::Init(
  412.                HWND hWndParent,
  413.                PVOID pvMsgLog)
  414. {
  415.   HRESULT hr = NOERROR;
  416.  
  417.   // Init this DLL's MsgBox facility.
  418.   g_pServer->m_pMsgBox->Init(g_pServer->m_hDllInst, hWndParent);
  419.  
  420.   if (NULL != pvMsgLog)
  421.   {
  422.     // Set up a pointer to the client EXE's Message Log facility so
  423.     // that any LOG macros used in this DLL will log to the host EXE's
  424.     // log window.
  425.     g_pMsgLog = (CMsgLog *)pvMsgLog;
  426.     LOG("P: --- LICSERVE.DLL now logging to Client ---");
  427.   }
  428.   else
  429.   {
  430.     // But if pvMsgLog is passed in as NULL then Create an independent
  431.     // logging facility for this DLL (use the client EXE's main window
  432.     // as the parent window).
  433.     CMsgLog* pMsgLog = new CMsgLog;
  434.  
  435.     if (NULL != pMsgLog)
  436.     {
  437.       if (pMsgLog->Create(g_pServer->m_hDllInst, hWndParent, FALSE))
  438.       {
  439.         g_pMsgLog = pMsgLog;
  440.         LOG("P: --- LICSERVE.DLL now logging ---");
  441.       }
  442.       else
  443.         delete pMsgLog;
  444.     }
  445.   }
  446.  
  447.   return hr;
  448. }
  449.  
  450.  
  451. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  452.   Method:   COLicCarSample::CImpISample::AboutBox
  453.  
  454.   Summary:  The AboutBox method commands the Server to display its own
  455.             About dialog box (using resources stored in this DLL itself.
  456.  
  457.   Args:     HWND hWnd
  458.               [in] Handle of window (ie of client) that is to be parent of
  459.               the About dialog window.
  460.  
  461.   Modifies: .
  462.  
  463.   Returns:  HRESULT
  464.               Standard result code.
  465. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  466. HRESULT COLicCarSample::CImpISample::AboutBox(
  467.           HWND hWnd)
  468. {
  469.   HRESULT hr = NOERROR;
  470.  
  471.   LOG("P: COLicCarSample::CImpISample::AboutBox.");
  472.  
  473.   // Define one of those nifty APPUTIL CAboutBox modal dialog objects.
  474.   CAboutBox dlgAboutBox;
  475.  
  476.   // Show the standard About Box dialog for this DLL by telling the dialog
  477.   // C++ object to show itself by invoking its ShowDialog method.
  478.   // Pass it this DLL instance and the parent window handle.  Use a dialog
  479.   // resource ID for the dialog stored in this DLL module's resources.
  480.   dlgAboutBox.ShowDialog(
  481.     m_pServer->m_hDllInst,
  482.     MAKEINTRESOURCE(IDD_ABOUTBOX),
  483.     hWnd);
  484.  
  485.   return hr;
  486. }
  487.