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 / locserve / crucar.cpp < prev    next >
C/C++ Source or Header  |  1997-08-05  |  18KB  |  514 lines

  1. /*+==========================================================================
  2.   File:      CRUCAR.CPP
  3.  
  4.   Summary:   Implementation file for the aggregatable COCruiseCar COM
  5.              object class.
  6.  
  7.              CRUCAR showcases the construction of the COCruiseCar COM
  8.              object class with the IUnknown, ICar, and ICruise interfaces.
  9.              This is done through Aggregation reuse of COCar's ICar
  10.              interface features.  This multiple interface COM Object Class
  11.              is achieved via the technique of nested classes.
  12.  
  13.              For a comprehensive tutorial code tour of this module's
  14.              contents and offerings see the tutorial LOCSERVE.HTM file.
  15.              For more specific technical details on the internal workings
  16.              see the comments dispersed throughout the module's source code.
  17.  
  18.   Classes:   COCruiseCar.
  19.  
  20.   Functions: none.
  21.  
  22.   Origin:    11-14-95: atrent - Editor-inheritance from CRUCAR.CPP in
  23.                the DLLSERVE Tutorial Code Sample.
  24.  
  25. ----------------------------------------------------------------------------
  26.   This file is part of the Microsoft COM Tutorial Code Samples.
  27.  
  28.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  29.  
  30.   This source code is intended only as a supplement to Microsoft
  31.   Development Tools and/or on-line documentation.  See these other
  32.   materials for detailed information regarding Microsoft code samples.
  33.  
  34.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  35.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  36.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  37.   PARTICULAR PURPOSE.
  38. ==========================================================================+*/
  39.  
  40. /*---------------------------------------------------------------------------
  41.   We include WINDOWS.H for all Win32 applications.
  42.   We include OLE2.H because we will be calling the COM/OLE Libraries.
  43.   We include APPUTIL.H because we will be building this application using
  44.     the convenient Virtual Window and Dialog classes and other
  45.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  46.   We include MICARS.H and CARGUIDS.H for the common car-related Interface
  47.     class, GUID, and CLSID specifications.
  48.   We include SERVER.H because it has the necessary internal class and
  49.     resource definitions for this DLL.
  50.   We include CAR.H because it has the class COCar declarations.
  51.   We include CRUCAR.H because it has the class COCruiseCar declarations.
  52. ---------------------------------------------------------------------------*/
  53. #include <windows.h>
  54. #include <ole2.h>
  55. #include <apputil.h>
  56. #include <micars.h>
  57. #include <carguids.h>
  58. #include "server.h"
  59. #include "car.h"
  60. #include "crucar.h"
  61.  
  62.  
  63. /*---------------------------------------------------------------------------
  64.   COCruiseCar's implementation of its main COM object class including
  65.   Constructor, Destructor, QueryInterface, AddRef, and Release.
  66. ---------------------------------------------------------------------------*/
  67.  
  68. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  69.   Method:   COCruiseCar::COCruiseCar
  70.  
  71.   Summary:  COCruiseCar Constructor. Note the member initializer:
  72.             "m_ImpICruise(this, pUnkOuter)" which is used to pass the
  73.             'this' and pUnkOuter pointers of this constructor function
  74.             to the constructor in the instantiation of the implementation
  75.             of the CImpICruise interface (which is nested inside this
  76.             present COCruiseCar Object Class).
  77.  
  78.   Args:     IUnknown* pUnkOuter,
  79.               Pointer to the the outer Unknown.  NULL means this COM Object
  80.               is not being Aggregated.  Non NULL means it is being created
  81.               on behalf of an outside COM object that is reusing it via
  82.               aggregation.
  83.             CServer* pServer)
  84.               Pointer to the server's control object.
  85.  
  86.   Modifies: m_cRefs, m_pUnkOuter.
  87.  
  88.   Returns:  void
  89. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  90. COCruiseCar::COCruiseCar(
  91.   IUnknown* pUnkOuter,
  92.   CServer* pServer) :
  93.   m_ImpICruise(this, pUnkOuter)
  94. {
  95.   // Zero the COM object's reference count.
  96.   m_cRefs = 0;
  97.  
  98.   // No AddRef necessary if non-NULL, as this present COM object's lifetime
  99.   // is totally coupled with the controlling Outer object's lifetime.
  100.   m_pUnkOuter = pUnkOuter;
  101.  
  102.   // Zero the pointer to the aggregated COCar object's IUnknown
  103.   // interface (for delegation of IUnknown calls to it).
  104.   m_pUnkCar = NULL;
  105.  
  106.   // Assign the pointer to the server's control object.
  107.   m_pServer = pServer;
  108.  
  109.   LOGF1("L: COCruiseCar Constructor. m_pUnkOuter=0x%X.", m_pUnkOuter);
  110.  
  111.   return;
  112. }
  113.  
  114.  
  115. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  116.   Method:   COCruiseCar::~COCruiseCar
  117.  
  118.   Summary:  COCruiseCar Destructor.
  119.  
  120.   Args:     void
  121.  
  122.   Modifies: .
  123.  
  124.   Returns:  void
  125. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  126. COCruiseCar::~COCruiseCar(void)
  127. {
  128.   LOG("L: COCruiseCar::Destructor.");
  129.  
  130.   // Release the aggragated COCar object.
  131.   RELEASE_INTERFACE(m_pUnkCar);
  132.  
  133.   return;
  134. }
  135.  
  136.  
  137. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  138.   Method:   COCruiseCar::Init
  139.  
  140.   Summary:  COCruiseCar Initialization method.  Creates any subordinate
  141.             COM objects.
  142.  
  143.   Args:     void
  144.  
  145.   Modifies: m_pUnkCar, m_pICar, m_cRefs.
  146.  
  147.   Returns:  HRESULT
  148.               Standard result code. NOERROR for success.
  149. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  150. HRESULT COCruiseCar::Init(void)
  151. {
  152.   HRESULT hr;
  153.  
  154.   LOG("L: COCruiseCar::Init.");
  155.  
  156.   // Set up the right pIUnknown for delegation.  If we are being
  157.   // aggregated then we pass the pUnkOuter in turn to any COM objects
  158.   // that we are aggregating.  m_pUnkOuter was set in the Constructor.
  159.   IUnknown* pUnkOuter = (NULL == m_pUnkOuter) ? this : m_pUnkOuter;
  160.  
  161.   // We create an instance of the COCar object and do this via the
  162.   // Aggregation reuse technique.  Note we pass pUnkOuter as the
  163.   // Aggregation pointer.  It is the 'this' pointer to this present
  164.   // CruiseCar object if we are not being aggregated; otherwise it is the
  165.   // pointer to the outermost object's controlling IUnknown.  Following
  166.   // the rules of Aggregation we must ask for an IID_IUnknown interface.
  167.   // We cache the requested  pointer to the IUnknown of the new COCar COM
  168.   // object for later use in delegating IUnknown calls. Since we know that
  169.   // this LocCar component is housed in this very same server, we can
  170.   // specify an execution context of CLSCTX_INPROC_SERVER. This allows us
  171.   // to aggregate the COCar COM object. Though the object is in a local
  172.   // server, it will be instantiated and run within the same process of
  173.   // this present local server. If we specify CLSCTX_LOCAL_SERVER, COM
  174.   // will not currently permit the creation using aggregation across
  175.   // process boundaries and CoCreateInstance would return an error.
  176.   hr = CoCreateInstance(
  177.          CLSID_LocCar,
  178.          pUnkOuter,
  179.          CLSCTX_INPROC_SERVER,
  180.          IID_IUnknown,
  181.          (PPVOID)&m_pUnkCar);
  182.  
  183.   if (SUCCEEDED(hr))
  184.   {
  185.     LOG("L: COCruiseCar::Init (New Aggregation of COCar) Succeeded.");
  186.   }
  187.   else
  188.   {
  189.     LOGERROR("L: COCruiseCar::Init (New Containment of COCar)",hr);
  190.   }
  191.  
  192.   return (hr);
  193. }
  194.  
  195.  
  196. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  197.   Method:   COCruiseCar::QueryInterface
  198.  
  199.   Summary:  QueryInterface of the COCruiseCar non-delegating
  200.             IUnknown implementation.
  201.  
  202.   Args:     REFIID riid,
  203.               [in] GUID of the Interface being requested.
  204.             PPVOID ppv)
  205.               [out] Address of the caller's pointer variable that will
  206.               receive the requested interface pointer.
  207.  
  208.   Modifies: *ppv.
  209.  
  210.   Returns:  HRESULT
  211. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  212. STDMETHODIMP COCruiseCar::QueryInterface(
  213.                REFIID riid,
  214.                PPVOID ppv)
  215. {
  216.   HRESULT hr = E_NOINTERFACE;
  217.   *ppv = NULL;
  218.  
  219.   if (IID_IUnknown == riid)
  220.   {
  221.     *ppv = this;
  222.     LOG("L: COCruiseCar::QueryInterface. 'this' pIUnknown returned.");
  223.   }
  224.   else if (IID_ICruise == riid)
  225.   {
  226.     // This ICruise interface is implemented in this COCruiseCar object and
  227.     // might be called a native interface of COCruiseCar.
  228.     *ppv = &m_ImpICruise;
  229.     LOG("L: COCruiseCar::QueryInterface. pICruise returned.");
  230.   }
  231.  
  232.   if (NULL != *ppv)
  233.   {
  234.     // We've handed out a pointer to an interface so obey the COM rules
  235.     //   and AddRef its reference count.
  236.     ((LPUNKNOWN)*ppv)->AddRef();
  237.     hr = NOERROR;
  238.   }
  239.   else if (IID_ICar == riid)
  240.   {
  241.     LOG("L: COCruiseCar::QueryInterface. ICar delegating.");
  242.     // We didn't implement the ICar interface in this COCruiseCar object.
  243.     // The aggregated inner COCar object is contributing the ICar
  244.     // interface to this present composite or aggregating CruiseCar object.
  245.     // So, to satisfy a QI request for the ICar interface, we delegate
  246.     // the QueryInterface to the inner object's principal IUnknown.
  247.     hr = m_pUnkCar->QueryInterface(riid, ppv);
  248.   }
  249.  
  250.   return (hr);
  251. }
  252.  
  253.  
  254. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  255.   Method:   COCruiseCar::AddRef
  256.  
  257.   Summary:  AddRef of the COCruiseCar non-delegating IUnknown implementation.
  258.  
  259.   Args:     void
  260.  
  261.   Modifies: m_cRefs.
  262.  
  263.   Returns:  ULONG
  264.               New value of m_cRefs (COM object's reference count).
  265. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  266. STDMETHODIMP_(ULONG) COCruiseCar::AddRef(void)
  267. {
  268.   m_cRefs++;
  269.  
  270.   LOGF1("L: COCruiseCar::AddRef. New cRefs=%i.", m_cRefs);
  271.  
  272.   return m_cRefs;
  273. }
  274.  
  275.  
  276. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  277.   Method:   COCruiseCar::Release
  278.  
  279.   Summary:  Release of the COCruiseCar non-delegating IUnknown
  280.             implementation.
  281.  
  282.   Args:     void
  283.  
  284.   Modifies: m_cRefs.
  285.  
  286.   Returns:  ULONG
  287.               New value of m_cRefs (COM object's reference count).
  288. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  289. STDMETHODIMP_(ULONG) COCruiseCar::Release(void)
  290. {
  291.   ULONG ulCount = --m_cRefs;
  292.  
  293.   LOGF1("L: COCruiseCar::Release. New cRefs=%i.", m_cRefs);
  294.  
  295.   if (0 == m_cRefs)
  296.   {
  297.     // We've reached a zero reference count for this COM object.
  298.     // So we tell the server housing to decrement its global object
  299.     // count so that the server will be unloaded if appropriate.
  300.     if (NULL != m_pServer)
  301.       m_pServer->ObjectsDown();
  302.  
  303.     // We artificially bump the main ref count.  This fulfills one of
  304.     // the rules of aggregated objects and ensures that an indirect
  305.     // recursive call to this release won't occur because of other
  306.     // delegating releases that might happen in our own destructor.
  307.     m_cRefs++;
  308.     delete this;
  309.   }
  310.  
  311.   return ulCount;
  312. }
  313.  
  314.  
  315. /*---------------------------------------------------------------------------
  316.   COCruiseCar's nested implementation of the ICruise interface including
  317.   Constructor, Destructor, QueryInterface, AddRef, Release,
  318.   Engage, and Adjust.
  319. ---------------------------------------------------------------------------*/
  320.  
  321. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  322.   Method:   COCruiseCar::CImpICruise::CImpICruise
  323.  
  324.   Summary:  Constructor for the CImpICruise interface instantiation.
  325.  
  326.   Args:     COCruiseCar* pBackObj,
  327.               Back pointer to the parent outer object.
  328.             IUnknown* pUnkOuter)
  329.               Pointer to the outer Unknown.  For delegation.
  330.  
  331.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  332.  
  333.   Returns:  void
  334. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  335. COCruiseCar::CImpICruise::CImpICruise(
  336.   COCruiseCar* pBackObj,
  337.   IUnknown* pUnkOuter)
  338. {
  339.   // Init the Interface Ref Count (used for debugging only).
  340.   m_cRefI = 0;
  341.  
  342.   // Init the Back Object Pointer to point to the outer object.
  343.   m_pBackObj = pBackObj;
  344.  
  345.   // Init the CImpICruise interface's delegating Unknown pointer.  We use
  346.   // the Back Object pointer for IUnknown delegation here if we are not
  347.   // being aggregated.  If we are being aggregated we use the supplied
  348.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  349.   // assignment requires no AddRef because the CImpICruise lifetime is
  350.   // quaranteed by the lifetime of the parent object in which
  351.   // CImpICruise is nested.
  352.   if (NULL == pUnkOuter)
  353.   {
  354.     m_pUnkOuter = pBackObj;
  355.     LOG("L: COCruiseCar::CImpICruise Constructor. Non-Aggregating.");
  356.   }
  357.   else
  358.   {
  359.     m_pUnkOuter = pUnkOuter;
  360.     LOG("L: COCruiseCar::CImpICruise Constructor. Aggregating.");
  361.   }
  362.  
  363.   return;
  364. }
  365.  
  366.  
  367. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  368.   Method:   COCruiseCar::CImpICruise::~CImpICruise
  369.  
  370.   Summary:  Destructor for the CImpICruise interface instantiation.
  371.  
  372.   Args:     void
  373.  
  374.   Modifies: .
  375.  
  376.   Returns:  void
  377. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  378. COCruiseCar::CImpICruise::~CImpICruise(void)
  379. {
  380.   LOG("L: COCruiseCar::CImpICruise Destructor.");
  381.  
  382.   return;
  383. }
  384.  
  385.  
  386. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  387.   Method:   COCruiseCar::CImpICruise::QueryInterface
  388.  
  389.   Summary:  The QueryInterface IUnknown member of this ICruise interface
  390.             implementation that delegates to m_pUnkOuter, whatever it is.
  391.  
  392.   Args:     REFIID riid,
  393.               [in] GUID of the Interface being requested.
  394.             PPVOID ppv)
  395.               [out] Address of the caller's pointer variable that will
  396.               receive the requested interface pointer.
  397.  
  398.   Modifies: .
  399.  
  400.   Returns:  HRESULT
  401.               Returned by the delegated outer QueryInterface call.
  402. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  403. STDMETHODIMP COCruiseCar::CImpICruise::QueryInterface(
  404.                REFIID riid,
  405.                PPVOID ppv)
  406. {
  407.   LOG("L: COCruiseCar::CImpICruise::QueryInterface. Delegating.");
  408.  
  409.   // Delegate this call to the outer object's QueryInterface.
  410.   return m_pUnkOuter->QueryInterface(riid, ppv);
  411. }
  412.  
  413.  
  414. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  415.   Method:   COCruiseCar::CImpICruise::AddRef
  416.  
  417.   Summary:  The AddRef IUnknown member of this ICruise interface
  418.             implementation that delegates to m_pUnkOuter, whatever it is.
  419.  
  420.   Args:     void
  421.  
  422.   Modifies: m_cRefI.
  423.  
  424.   Returns:  ULONG
  425.               Returned by the delegated outer AddRef call.
  426. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  427. STDMETHODIMP_(ULONG) COCruiseCar::CImpICruise::AddRef(void)
  428. {
  429.   // Increment the Interface Reference Count.
  430.   ++m_cRefI;
  431.  
  432.   LOGF1("L: COCruiseCar::CImpICruise::Addref. Delegating. New cI=%i.", m_cRefI);
  433.  
  434.   // Delegate this call to the outer object's AddRef.
  435.   return m_pUnkOuter->AddRef();
  436. }
  437.  
  438.  
  439. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  440.   Method:   COCruiseCar::CImpICruise::Release
  441.  
  442.   Summary:  The Release IUnknown member of this ICruise interface
  443.             implementation that delegates to m_pUnkOuter, whatever it is.
  444.  
  445.   Args:     void
  446.  
  447.   Modifies: m_cRefI.
  448.  
  449.   Returns:  ULONG
  450.               Returned by the delegated outer Release call.
  451. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  452. STDMETHODIMP_(ULONG) COCruiseCar::CImpICruise::Release(void)
  453. {
  454.   // Decrement the Interface Reference Count.
  455.   --m_cRefI;
  456.  
  457.   LOGF1("L: COCruiseCar::CImpICruise::Release. Delegating. New cI=%i.",m_cRefI);
  458.  
  459.   // Delegate this call to the outer object's Release.
  460.   return m_pUnkOuter->Release();
  461. }
  462.  
  463.  
  464. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  465.   Method:   COCruiseCar::CImpICruise::Engage
  466.  
  467.   Summary:  The Engage member method of this ICruise interface
  468.             implementation.  A simple empty method on a COCruiseCar COM
  469.             object for tutorial purposes.  Presumably if this Car object
  470.             were modeling a real Car then the Engage method would turn
  471.             the Cruise control system on or off.
  472.  
  473.   Args:     BOOL bOnOff)
  474.               TRUE for On; FALSE for Off.
  475.  
  476.   Modifies: .
  477.  
  478.   Returns:  HRESULT
  479.               NOERROR
  480. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  481. STDMETHODIMP COCruiseCar::CImpICruise::Engage(
  482.                BOOL bOnOff)
  483. {
  484.   LOGF1("L: COCruiseCar::CImpICruise::Engage. Called. bOnOff=%i.",bOnOff);
  485.  
  486.   return NOERROR;
  487. }
  488.  
  489.  
  490. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  491.   Method:   COCruiseCar::CImpICruise::Adjust
  492.  
  493.   Summary:  The Adjust member method of this ICruise interface
  494.             implementation.  A simple empty method on a COCruiseCar COM
  495.             object for tutorial purposes.  Presumably if this Car object
  496.             were modeling a real Car then the Adjust method would allow
  497.             notching the cruise set speed up or down by increments of 3 mph.
  498.  
  499.   Args:     BOOL bUpDown)
  500.               TRUE for Up; FALSE for Down.
  501.  
  502.   Modifies: .
  503.  
  504.   Returns:  HRESULT
  505.               NOERROR
  506. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  507. STDMETHODIMP COCruiseCar::CImpICruise::Adjust(
  508.                BOOL bUpDown)
  509. {
  510.   LOGF1("L: COCruiseCar::CImpICruise::Adjust. Called. bUpDown=%i.",bUpDown);
  511.  
  512.   return NOERROR;
  513. }
  514.