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 / aptserve / utilcar.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-05  |  25.3 KB  |  769 lines

  1. /*+==========================================================================
  2.   File:      UTILCAR.CPP
  3.  
  4.   Summary:   Implementation file for the aggregatable COUtilityCar COM
  5.              object class.
  6.  
  7.              UTILCAR showcases the construction of the COUtilityCar COM
  8.              object class with the IUnknown, ICar, and IUtility interfaces.
  9.              This is done through Containment reuse of COCar's ICar
  10.              interface features.
  11.  
  12.              For a comprehensive tutorial code tour of this module's
  13.              contents and offerings see the tutorial APTSERVE.HTM file.
  14.              For more specific technical details on the internal workings
  15.              see the comments dispersed throughout the module's source code.
  16.  
  17.   Classes:   COUtilityCar.
  18.  
  19.   Functions: none.
  20.  
  21.   Origin:    3-20-96: atrent - Editor-inheritance from UTILCAR.CPP in
  22.                the LOCSERVE Tutorial Code Sample.
  23.  
  24. ----------------------------------------------------------------------------
  25.   This file is part of the Microsoft COM Tutorial Code Samples.
  26.  
  27.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  28.  
  29.   This source code is intended only as a supplement to Microsoft
  30.   Development Tools and/or on-line documentation.  See these other
  31.   materials for detailed information regarding Microsoft code samples.
  32.  
  33.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  34.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  35.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  36.   PARTICULAR PURPOSE.
  37. ==========================================================================+*/
  38.  
  39. /*---------------------------------------------------------------------------
  40.   We include WINDOWS.H for all Win32 applications.
  41.   We include OLE2.H because we will make calls to the COM/OLE Libraries.
  42.   We include APPUTIL.H because we will be building this application using
  43.     the convenient Virtual Window and Dialog classes and other
  44.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  45.   We include MICARS.H and CARGUIDS.H for the common car-related Interface
  46.     class, GUID, and CLSID specifications.
  47.   We include SERVER.H because it has internal class declarations and
  48.     resource ID definitions specific for this DLL.
  49.   We include CAR.H because it has the class COCar declarations.
  50.   We include UTILCAR.H because it has the class COUtilityCar declarations.
  51. ---------------------------------------------------------------------------*/
  52. #include <windows.h>
  53. #include <ole2.h>
  54. #include <apputil.h>
  55. #include <micars.h>
  56. #include <carguids.h>
  57. #include "server.h"
  58. #include "car.h"
  59. #include "utilcar.h"
  60.  
  61.  
  62. /*---------------------------------------------------------------------------
  63.   COUtilityCar's implementation of its main COM object class including
  64.   Constructor, Destructor, QueryInterface, AddRef, and Release.
  65. ---------------------------------------------------------------------------*/
  66.  
  67. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  68.   Method:   COUtilityCar::COUtilityCar
  69.  
  70.   Summary:  COUtilityCar Constructor. Note the member initializers:
  71.             "m_ImpICar(this, pUnkOuter)" and "m_ImpIUtility(this,
  72.             pUnkOuter)" which are used to pass the 'this' and
  73.             pUnkOuter pointers of this constructor function to the
  74.             constructors that instantiate the implementations of
  75.             the CImpICar and CImpIUtility interfaces (which are both
  76.             nested inside this present COUtilityCar 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. COUtilityCar::COUtilityCar(
  91.   IUnknown* pUnkOuter,
  92.   CServer* pServer) :
  93.   m_ImpICar(this, pUnkOuter),
  94.   m_ImpIUtility(this, pUnkOuter)
  95. {
  96.   // Zero the COM object's reference count.
  97.   m_cRefs = 0;
  98.  
  99.   // No AddRef necessary if non-NULL, as this present COM object's lifetime
  100.   // is totally coupled with the controlling Outer object's lifetime.
  101.   m_pUnkOuter = pUnkOuter;
  102.  
  103.   // Zero the pointer to the contained COCar object's ICar interface.
  104.   m_pICar = NULL;
  105.  
  106.   // Init the pointer to the server's control object.
  107.   m_pServer = pServer;
  108.  
  109.   LOGF2("L<%X>: COUtilityCar Constructor. m_pUnkOuter=0x%X.",TID,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:   COUtilityCar::~COUtilityCar
  117.  
  118.   Summary:  COUtilityCar 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. COUtilityCar::~COUtilityCar(void)
  127. {
  128.   LOGF1("L<%X>: COUtilityCar::Destructor.",TID);
  129.  
  130.   // Release the contained Car object.
  131.   RELEASE_INTERFACE(m_pICar);
  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:   COUtilityCar::Init
  139.  
  140.   Summary:  COUtilityCar Initialization method.
  141.  
  142.   Args:     void
  143.  
  144.   Modifies: m_pUnkCar, m_pICar, m_cRefs.
  145.  
  146.   Returns:  HRESULT
  147.               Standard result code. NOERROR for success.
  148. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  149. HRESULT COUtilityCar::Init(void)
  150. {
  151.   HRESULT hr;
  152.  
  153.   LOGF1("L<%X>: COUtilityCar::Init.",TID);
  154.  
  155.   // Set up the right pIUnknown for delegation.  If we are being
  156.   // aggregated then we pass the pUnkOuter in turn to any COM objects
  157.   // that we are aggregating.  m_pUnkOuter was set in the Constructor.
  158.   IUnknown* pUnkOuter = (NULL == m_pUnkOuter) ? this : m_pUnkOuter;
  159.  
  160.   // We create an instance of the COCar object and do this via the
  161.   // Containment reuse technique.  We ask for the new COM object's
  162.   // ICar interface directly.  We pass NULL for the pUnkOuter
  163.   // aggregation pointer because we are not aggregating.  It is here
  164.   // that we are reusing the COCar COM Object through the Containment
  165.   // technique.  We cache the requested ICar interface pointer in this
  166.   // COUtilityCar COM object for later use.  We don't need to AddRef
  167.   // this interface because the CoCreateInstance will do this for us.
  168.   hr = CoCreateInstance(
  169.          CLSID_AptCar,
  170.          NULL,
  171.          CLSCTX_LOCAL_SERVER,
  172.          IID_ICar,
  173.          (PPVOID)&m_pICar);
  174.  
  175.   if (SUCCEEDED(hr))
  176.   {
  177.     LOGF1("L<%X>: COUtilityCar::Init (New Containment of COCar) Succeeded.",TID);
  178.   }
  179.   else
  180.   {
  181.     LOGF2("L<%X>: COUtilityCar::Init (New Containment of COCar) Failed. hr=0x%X.",TID,hr);
  182.   }
  183.  
  184.   return (hr);
  185. }
  186.  
  187.  
  188. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  189.   Method:   COUtilityCar::QueryInterface
  190.  
  191.   Summary:  QueryInterface of the COUtilityCar non-delegating
  192.             IUnknown implementation.
  193.  
  194.   Args:     REFIID riid,
  195.               [in] GUID of the Interface being requested.
  196.             PPVOID ppv)
  197.               [out] Address of the caller's pointer variable that will
  198.               receive the requested interface pointer.
  199.  
  200.   Modifies: *ppv.
  201.  
  202.   Returns:  HRESULT
  203. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  204. STDMETHODIMP COUtilityCar::QueryInterface(
  205.                REFIID riid,
  206.                PPVOID ppv)
  207. {
  208.   HRESULT hr = E_NOINTERFACE;
  209.   *ppv = NULL;
  210.  
  211.   if (IID_IUnknown == riid)
  212.   {
  213.     *ppv = this;
  214.     LOGF1("L<%X>: COUtilityCar::QueryInterface. 'this' pIUnknown returned",TID);
  215.   }
  216.   else if (IID_ICar == riid)
  217.   {
  218.     *ppv = &m_ImpICar;
  219.     LOGF1("L<%X>: COUtilityCar::QueryInterface. pICar returned",TID);
  220.   }
  221.   else if (IID_IUtility == riid)
  222.   {
  223.     // This IUtility interface is implemented in this COUtilityCar object
  224.     // and might be called a native interface of COCruiseCar.
  225.     *ppv = &m_ImpIUtility;
  226.     LOGF1("L<%X>: COUtilityCar::QueryInterface. pIUtility returned",TID);
  227.   }
  228.  
  229.   if (NULL != *ppv)
  230.   {
  231.     // We've handed out a pointer to the interface so obey the COM rules
  232.     // and AddRef the reference count.
  233.     ((LPUNKNOWN)*ppv)->AddRef();
  234.     hr = NOERROR;
  235.   }
  236.  
  237.   return (hr);
  238. }
  239.  
  240.  
  241. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  242.   Method:   COUtilityCar::AddRef
  243.  
  244.   Summary:  AddRef of the COUtilityCar non-delegating IUnknown implementation.
  245.  
  246.   Args:     void
  247.  
  248.   Modifies: m_cRefs.
  249.  
  250.   Returns:  ULONG
  251.               New value of m_cRefs (COM object's reference count).
  252. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  253. STDMETHODIMP_(ULONG) COUtilityCar::AddRef(void)
  254. {
  255.   m_cRefs++;
  256.  
  257.   LOGF2("L<%X>: COUtilityCar::AddRef. New cRefs=%i.",TID,m_cRefs);
  258.  
  259.   return m_cRefs;
  260. }
  261.  
  262.  
  263. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  264.   Method:   COUtilityCar::Release
  265.  
  266.   Summary:  Release of the COUtilityCar non-delegating IUnknown
  267.             implementation.
  268.  
  269.   Args:     void
  270.  
  271.   Modifies: m_cRefs.
  272.  
  273.   Returns:  ULONG
  274.               New value of m_cRefs (COM object's reference count).
  275. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  276. STDMETHODIMP_(ULONG) COUtilityCar::Release(void)
  277. {
  278.   ULONG ulCount = --m_cRefs;
  279.  
  280.   LOGF2("L<%X>: COUtilityCar::Release. New cRefs=%i.",TID,m_cRefs);
  281.  
  282.   if (0 == m_cRefs)
  283.   {
  284.     // We artificially bump the main ref count to ensure that an indirect
  285.     // recursive call to this release won't occur because of other
  286.     // delegating releases that might happen in our own destructor.
  287.     m_cRefs++;
  288.     delete this;
  289.  
  290.     // We've reached a zero reference count for this COM object.
  291.     // So we tell the server housing to decrement its global object
  292.     // count so that the server will be unloaded if appropriate.
  293.     if (NULL != m_pServer)
  294.       m_pServer->ObjectsDown();
  295.   }
  296.  
  297.   return ulCount;
  298. }
  299.  
  300.  
  301. /*---------------------------------------------------------------------------
  302.   COUtilityCar's nested implementation of the ICar interface including
  303.   Constructor, Destructor, QueryInterface, AddRef, Release,
  304.   Shift, Clutch, Speed, and Steer.
  305. ---------------------------------------------------------------------------*/
  306.  
  307. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  308.   Method:   COUtilityCar::CImpICar::CImpICar
  309.  
  310.   Summary:  Constructor for the CImpICar interface instantiation.
  311.  
  312.   Args:     COUtilityCar* pBackObj,
  313.               Back pointer to the parent outer object.
  314.             IUnknown* pUnkOuter,
  315.               Pointer to the outer Unknown.  For delegation.
  316.  
  317.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  318.  
  319.   Returns:  void
  320. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  321. COUtilityCar::CImpICar::CImpICar(
  322.   COUtilityCar* pBackObj,
  323.   IUnknown* pUnkOuter)
  324. {
  325.   // Init the Interface Ref Count (used for debugging only).
  326.   m_cRefI = 0;
  327.  
  328.   // Init the Back Object Pointer to point to the outer object.
  329.   m_pBackObj = pBackObj;
  330.  
  331.   // Init the CImpICar interface's delegating Unknown pointer.  We use
  332.   // the Back Object pointer for IUnknown delegation here if we are not
  333.   // being aggregated.  If we are being aggregated we use the supplied
  334.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  335.   // assignment requires no AddRef because the CImpICar lifetime is
  336.   // quaranteed by the lifetime of the parent object in which
  337.   // CImpICar is nested.
  338.   if (NULL == pUnkOuter)
  339.   {
  340.     m_pUnkOuter = pBackObj;
  341.     LOGF1("L<%X>: COUtilityCar::CImpICar Constructor. Non-Aggregating",TID);
  342.   }
  343.   else
  344.   {
  345.     m_pUnkOuter = pUnkOuter;
  346.     LOGF1("L<%X>: COUtilityCar::CImpICar Constructor. Aggregating",TID);
  347.   }
  348.  
  349.   return;
  350. }
  351.  
  352.  
  353. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  354.   Method:   COUtilityCar::CImpICar::~CImpICar
  355.  
  356.   Summary:  Destructor for the CImpICar interface instantiation.
  357.  
  358.   Args:     void
  359.  
  360.   Modifies: .
  361.  
  362.   Returns:  void
  363. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  364. COUtilityCar::CImpICar::~CImpICar(void)
  365. {
  366.   LOGF1("L<%X>: COUtilityCar::CImpICar Destructor.",TID);
  367.  
  368.   return;
  369. }
  370.  
  371.  
  372. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  373.   Method:   COUtilityCar::CImpICar::QueryInterface
  374.  
  375.   Summary:  The QueryInterface IUnknown member of this ICar interface
  376.             implementation that delegates to m_pUnkOuter, whatever it is.
  377.  
  378.   Args:     REFIID riid,
  379.               [in] GUID of the Interface being requested.
  380.             PPVOID ppv)
  381.               [out] Address of the caller's pointer variable that will
  382.               receive the requested interface pointer.
  383.  
  384.   Modifies: .
  385.  
  386.   Returns:  HRESULT
  387.               Returned by the delegated outer QueryInterface call.
  388. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  389. STDMETHODIMP COUtilityCar::CImpICar::QueryInterface(
  390.                REFIID riid,
  391.                PPVOID ppv)
  392. {
  393.   LOGF1("L<%X>: COUtilityCar::CImpICar::QueryInterface. Delegating.",TID);
  394.  
  395.   // Delegate this call to the outer object's QueryInterface.
  396.   return m_pUnkOuter->QueryInterface(riid, ppv);
  397. }
  398.  
  399.  
  400. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  401.   Method:   COUtilityCar::CImpICar::AddRef
  402.  
  403.   Summary:  The AddRef IUnknown member of this ICar interface
  404.             implementation that delegates to m_pUnkOuter, whatever it is.
  405.  
  406.   Args:     void
  407.  
  408.   Modifies: m_cRefI.
  409.  
  410.   Returns:  ULONG
  411.               Returned by the delegated outer AddRef call.
  412. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  413. STDMETHODIMP_(ULONG) COUtilityCar::CImpICar::AddRef(void)
  414. {
  415.   // Increment the Interface Reference Count.
  416.   ++m_cRefI;
  417.  
  418.   LOGF2("L<%X>: COUtilityCar::CImpICar::Addref. Delegating. New cI=%i.",TID,m_cRefI);
  419.  
  420.   // Delegate this call to the outer object's AddRef.
  421.   return m_pUnkOuter->AddRef();
  422. }
  423.  
  424.  
  425. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  426.   Method:   COUtilityCar::CImpICar::Release
  427.  
  428.   Summary:  The Release IUnknown member of this ICar interface
  429.             implementation that delegates to m_pUnkOuter, whatever it is.
  430.  
  431.   Args:     void
  432.  
  433.   Modifies: m_cRefI.
  434.  
  435.   Returns:  ULONG
  436.               Returned by the delegated outer Release call.
  437. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  438. STDMETHODIMP_(ULONG) COUtilityCar::CImpICar::Release(void)
  439. {
  440.   // Decrement the Interface Reference Count.
  441.   --m_cRefI;
  442.  
  443.   LOGF2("L<%X>: COUtilityCar::CImpICar::Release. Delegating. New cI=%i.",TID,m_cRefI);
  444.  
  445.   // Delegate this call to the outer object's Release.
  446.   return m_pUnkOuter->Release();
  447. }
  448.  
  449.  
  450. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  451.   Method:   COUtilityCar::CImpICar::Shift
  452.  
  453.   Summary:  The Shift member method of this ICar interface implementation.
  454.             A simple empty method on a COUtilityCar COM object for tutorial
  455.             purposes.  Presumably if this Car object were modeling
  456.             a real Car then the Shift method would shift to the specified
  457.             gear.
  458.  
  459.   Args:     short nGear
  460.               0 - Neutral; 1 - 5 First 5 forward gears; 6 - Reverse.
  461.  
  462.   Modifies: .
  463.  
  464.   Returns:  HRESULT
  465.               NOERROR
  466. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  467. STDMETHODIMP COUtilityCar::CImpICar::Shift(
  468.                short nGear)
  469. {
  470.   LOGF2("L<%X>: COUtilityCar::CImpICar::Shift. Delegating. nGear=%i.",TID,nGear);
  471.  
  472.   // Delegate to the contained object implementation of ICar.
  473.   m_pBackObj->m_pICar->Shift(nGear);
  474.  
  475.   return NOERROR;
  476. }
  477.  
  478.  
  479. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  480.   Method:   COUtilityCar::CImpICar::Clutch
  481.  
  482.   Summary:  The Clutch member method of this ICar interface implementation.
  483.             A simple empty method on a COUtilityCar COM object for tutorial
  484.             purposes.  Presumably if this Car object were modeling
  485.             a real Car then the Clutch method would engage the clutch the
  486.             specified amount.
  487.  
  488.   Args:     short nEngaged)
  489.               Percent clutch is engaged (0 to 100%).
  490.  
  491.   Modifies: .
  492.  
  493.   Returns:  HRESULT
  494.               NOERROR
  495. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  496. STDMETHODIMP COUtilityCar::CImpICar::Clutch(
  497.                short nEngaged)
  498. {
  499.   LOGF2("L<%X>: COUtilityCar::CImpICar::Clutch. Delegating. nEngaged=%i.",TID,nEngaged);
  500.  
  501.   // Delegate to the contained object implementation of ICar.
  502.   m_pBackObj->m_pICar->Clutch(nEngaged);
  503.  
  504.   return NOERROR;
  505. }
  506.  
  507.  
  508. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  509.   Method:   COUtilityCar::CImpICar::Speed
  510.  
  511.   Summary:  The Propel member method of this ICar interface implementation.
  512.             A simple empty method on a COUtilityCar COM object for tutorial
  513.             purposes.  Presumably if this Car object were modeling
  514.             a real Car then this method would accelerate/brake to bring
  515.             the car to the specified speed.
  516.  
  517.   Args:     short nMph
  518.               New speed in miles per hour.
  519.  
  520.   Modifies: .
  521.  
  522.   Returns:  HRESULT
  523.               NOERROR
  524. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  525. STDMETHODIMP COUtilityCar::CImpICar::Speed(
  526.                short nMph)
  527. {
  528.   LOGF2("L<%X>: COUtilityCar::CImpICar::Speed. Delegating. nMph=%i.",TID,nMph);
  529.  
  530.   // Delegate to the contained object implementation of ICar.
  531.   m_pBackObj->m_pICar->Speed(nMph);
  532.  
  533.   return NOERROR;
  534. }
  535.  
  536.  
  537. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  538.   Method:   COUtilityCar::CImpICar::Steer
  539.  
  540.   Summary:  The Steer member method of this ICar interface implementation.
  541.             A simple empty method on a COUtilityCar COM object for tutorial
  542.             purposes.  Presumably if this Car object were modeling
  543.             a real Car then the Steer method would set the steering
  544.             angle of the Car.
  545.  
  546.   Args:     short nAngle)
  547.               0 degrees straight ahead, -45 Full left, +45 Full right.
  548.  
  549.   Modifies: .
  550.  
  551.   Returns:  HRESULT
  552.               NOERROR
  553. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  554. STDMETHODIMP COUtilityCar::CImpICar::Steer(
  555.                short nAngle)
  556. {
  557.   LOGF2("L<%X>: COUtilityCar::CImpICar::Steer. Delegating. nAngle=%i.",TID,nAngle);
  558.  
  559.   // Delegate to the contained object implementation of ICar.
  560.   m_pBackObj->m_pICar->Steer(nAngle);
  561.  
  562.   return NOERROR;
  563. }
  564.  
  565.  
  566. /*---------------------------------------------------------------------------
  567.   COUtilityCar's nested implementation of the IUtility interface including
  568.   Constructor, Destructor, QueryInterface, AddRef, Release,
  569.   Offroad, and Winch.
  570. ---------------------------------------------------------------------------*/
  571.  
  572. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  573.   Method:   COUtilityCar::CImpIUtility::CImpIUtility
  574.  
  575.   Summary:  Constructor for the CImpIUtility interface instantiation.
  576.  
  577.   Args:     COUtilityCar* pBackObj,
  578.               Back pointer to the parent outer object.
  579.             IUnknown* pUnkOuter)
  580.               Pointer to the outer Unknown.  For delegation.
  581.  
  582.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  583.  
  584.   Returns:  void
  585. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  586. COUtilityCar::CImpIUtility::CImpIUtility(
  587.   COUtilityCar* pBackObj,
  588.   IUnknown* pUnkOuter)
  589. {
  590.   // Init the Interface Ref Count (used for debugging only).
  591.   m_cRefI = 0;
  592.  
  593.   // Init the Back Object Pointer to point to the outer object.
  594.   m_pBackObj = pBackObj;
  595.  
  596.   // Init the CImpIUtility interface's delegating Unknown pointer.  We use
  597.   // the Back Object pointer for IUnknown delegation here if we are not
  598.   // being aggregated.  If we are being aggregated we use the supplied
  599.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  600.   // assignment requires no AddRef because the CImpIUtility lifetime is
  601.   // quaranteed by the lifetime of the parent object in which
  602.   // CImpIUtility is nested.
  603.   if (NULL == pUnkOuter)
  604.   {
  605.     m_pUnkOuter = pBackObj;
  606.     LOGF1("L<%X>: COUtilityCar::CImpIUtility Constructor. Non-Aggregating.",TID);
  607.   }
  608.   else
  609.   {
  610.     m_pUnkOuter = pUnkOuter;
  611.     LOGF1("L<%X>: COUtilityCar::CImpIUtility Constructor. Aggregating.",TID);
  612.   }
  613.  
  614.   return;
  615. }
  616.  
  617.  
  618. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  619.   Method:   COUtilityCar::CImpIUtility::~CImpIUtility
  620.  
  621.   Summary:  Destructor for the CImpIUtility interface instantiation.
  622.  
  623.   Args:     void
  624.  
  625.   Modifies: .
  626.  
  627.   Returns:  void
  628. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  629. COUtilityCar::CImpIUtility::~CImpIUtility(void)
  630. {
  631.   LOGF1("L<%X>: COUtilityCar::CImpIUtility Destructor.",TID);
  632.  
  633.   return;
  634. }
  635.  
  636.  
  637. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  638.   Method:   COUtilityCar::CImpIUtility::QueryInterface
  639.  
  640.   Summary:  The QueryInterface IUnknown member of this IUtility interface
  641.             implementation that delegates to m_pUnkOuter, whatever it is.
  642.  
  643.   Args:     REFIID riid,
  644.               [in] GUID of the Interface being requested.
  645.             PPVOID ppv)
  646.               [out] Address of the caller's pointer variable that will
  647.               receive the requested interface pointer.
  648.  
  649.   Modifies: .
  650.  
  651.   Returns:  HRESULT
  652.               Returned by the delegated outer QueryInterface call.
  653. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  654. STDMETHODIMP COUtilityCar::CImpIUtility::QueryInterface(
  655.                REFIID riid,
  656.                PPVOID ppv)
  657. {
  658.   LOGF1("L<%X>: COUtilityCar::CImpIUtility::QueryInterface. Delegating.",TID);
  659.  
  660.   // Delegate this call to the outer object's QueryInterface.
  661.   return m_pUnkOuter->QueryInterface(riid, ppv);
  662. }
  663.  
  664.  
  665. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  666.   Method:   COUtilityCar::CImpIUtility::AddRef
  667.  
  668.   Summary:  The AddRef IUnknown member of this IUtility interface
  669.             implementation that delegates to m_pUnkOuter, whatever it is.
  670.  
  671.   Args:     void
  672.  
  673.   Modifies: m_cRefI.
  674.  
  675.   Returns:  ULONG
  676.               Returned by the delegated outer AddRef call.
  677. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  678. STDMETHODIMP_(ULONG) COUtilityCar::CImpIUtility::AddRef(void)
  679. {
  680.   // Increment the Interface Reference Count.
  681.   ++m_cRefI;
  682.  
  683.   LOGF2("L<%X>: COUtilityCar::CImpIUtility::Addref. Delegating. New cI=%i.",TID,m_cRefI);
  684.  
  685.   // Delegate this call to the outer object's AddRef.
  686.   return m_pUnkOuter->AddRef();
  687. }
  688.  
  689.  
  690. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  691.   Method:   COUtilityCar::CImpIUtility::Release
  692.  
  693.   Summary:  The Release IUnknown member of this IUtility interface
  694.             implementation that delegates to m_pUnkOuter, whatever it is.
  695.  
  696.   Args:     void
  697.  
  698.   Modifies: m_cRefI.
  699.  
  700.   Returns:  ULONG
  701.               Returned by the delegated outer Release call.
  702. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  703. STDMETHODIMP_(ULONG) COUtilityCar::CImpIUtility::Release(void)
  704. {
  705.   // Decrement the Interface Reference Count.
  706.   --m_cRefI;
  707.  
  708.   LOGF2("L<%X>: COUtilityCar::CImpIUtility::Release. Delegating. New cI=%i.",TID,m_cRefI);
  709.  
  710.   // Delegate this call to the outer object's Release.
  711.   return m_pUnkOuter->Release();
  712. }
  713.  
  714.  
  715. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  716.   Method:   COUtilityCar::CImpIUtility::Offroad
  717.  
  718.   Summary:  The Offroad member method of this IUtility interface
  719.             implementation.  A simple empty method on a COUtilityCar
  720.             COM object for tutorial purposes.  Presumably if this
  721.             UtilityCar object were modeling a real Car then the Offroad
  722.             method would function the 4-wheel drive transfer case and
  723.             shift it to the specified 4-wheel drive mode.
  724.  
  725.   Args:     short nGear
  726.               0 = 2H or regular 2-wheel drive;
  727.               1 = 4H or 4-wheel drive high speed;
  728.               2 = neutral; and
  729.               3 = 4L or 4-wheel drive low speed).
  730.  
  731.   Modifies: .
  732.  
  733.   Returns:  HRESULT
  734.               NOERROR
  735. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  736. STDMETHODIMP COUtilityCar::CImpIUtility::Offroad(
  737.                short nGear)
  738. {
  739.   LOGF2("L<%X>: COUtilityCar::CImpIUtility::Offroad. Called. nGear=%i.",TID,nGear);
  740.  
  741.   return NOERROR;
  742. }
  743.  
  744.  
  745. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  746.   Method:   COUtilityCar::CImpIUtility::Winch
  747.  
  748.   Summary:  The Winch member method of this IUtility interface
  749.             implementation.  A simple empty method on a COUtilityCar COM
  750.             object for tutorial purposes.  Presumably if this UtilityCar
  751.             object were modeling a real Car then the Winch method would
  752.             turn on/off the front-mounted Winch to the specified RPMs.
  753.  
  754.   Args:     short nRpm
  755.               0 = off; 1 - 50 RPM.
  756.  
  757.   Modifies: .
  758.  
  759.   Returns:  HRESULT
  760.               NOERROR
  761. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  762. STDMETHODIMP COUtilityCar::CImpIUtility::Winch(
  763.                short nRpm)
  764. {
  765.   LOGF2("L<%X>: COUtilityCar::CImpIUtility::Winch. Called. nRpm=%i.",TID,nRpm);
  766.  
  767.   return NOERROR;
  768. }
  769.