UTILCAR.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:25k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*+==========================================================================
  2.   File:      UTILCAR.CPP
  3.   Summary:   Implementation file for the aggregatable COUtilityCar COM
  4.              object class.
  5.              UTILCAR showcases the construction of the COUtilityCar COM
  6.              object class with the IUnknown, ICar, and IUtility interfaces.
  7.              This is done through Containment reuse of COCar's ICar
  8.              interface features.
  9.              For a comprehensive tutorial code tour of this module's
  10.              contents and offerings see the tutorial LOCSERVE.HTM file.
  11.              For more specific technical details on the internal workings
  12.              see the comments dispersed throughout the module's source code.
  13.   Classes:   COUtilityCar.
  14.   Functions: none.
  15.   Origin:    11-14-95: atrent - Editor-inheritance from UTILCAR.CPP in
  16.                the DLLSERVE Tutorial Code Sample.
  17. ----------------------------------------------------------------------------
  18.   This file is part of the Microsoft COM Tutorial Code Samples.
  19.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  20.   This source code is intended only as a supplement to Microsoft
  21.   Development Tools and/or on-line documentation.  See these other
  22.   materials for detailed information regarding Microsoft code samples.
  23.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  24.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  25.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  26.   PARTICULAR PURPOSE.
  27. ==========================================================================+*/
  28. /*---------------------------------------------------------------------------
  29.   We include WINDOWS.H for all Win32 applications.
  30.   We include OLE2.H because we will be calling the COM/OLE Libraries.
  31.   We include APPUTIL.H because we will be building this application using
  32.     the convenient Virtual Window and Dialog classes and other
  33.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  34.   We include MICARS.H and CARGUIDS.H for the common car-related Interface
  35.     class, GUID, and CLSID specifications.
  36.   We include SERVER.H because it has internal class declarations and
  37.     resource ID definitions specific for this DLL.
  38.   We include CAR.H because it has the class COCar declarations.
  39.   We include UTILCAR.H because it has the class COUtilityCar declarations.
  40. ---------------------------------------------------------------------------*/
  41. #include <windows.h>
  42. #include <ole2.h>
  43. #include <apputil.h>
  44. #include <micars.h>
  45. #include <carguids.h>
  46. #include "server.h"
  47. #include "car.h"
  48. #include "utilcar.h"
  49. /*---------------------------------------------------------------------------
  50.   COUtilityCar's implementation of its main COM object class including
  51.   Constructor, Destructor, QueryInterface, AddRef, and Release.
  52. ---------------------------------------------------------------------------*/
  53. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  54.   Method:   COUtilityCar::COUtilityCar
  55.   Summary:  COUtilityCar Constructor. Note the member initializers:
  56.             "m_ImpICar(this, pUnkOuter)" and "m_ImpIUtility(this,
  57.             pUnkOuter)" which are used to pass the 'this' and
  58.             pUnkOuter pointers of this constructor function to the
  59.             constructors that instantiate the implementations of
  60.             the CImpICar and CImpIUtility interfaces (which are both
  61.             nested inside this present COUtilityCar Object Class.
  62.   Args:     IUnknown* pUnkOuter,
  63.               Pointer to the the outer Unknown.  NULL means this COM Object
  64.               is not being Aggregated.  Non NULL means it is being created
  65.               on behalf of an outside COM object that is reusing it via
  66.               aggregation.
  67.             CServer* pServer)
  68.               Pointer to the server's control object.
  69.   Modifies: m_cRefs, m_pUnkOuter.
  70.   Returns:  void
  71. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  72. COUtilityCar::COUtilityCar(
  73.   IUnknown* pUnkOuter,
  74.   CServer* pServer) :
  75.   m_ImpICar(this, pUnkOuter),
  76.   m_ImpIUtility(this, pUnkOuter)
  77. {
  78.   // Zero the COM object's reference count.
  79.   m_cRefs = 0;
  80.   // No AddRef necessary if non-NULL, as we're nested.
  81.   m_pUnkOuter = pUnkOuter;
  82.   // Zero the pointer to the contained COCar object's ICar interface.
  83.   m_pICar = NULL;
  84.   // Init the pointer to the server's control object.
  85.   m_pServer = pServer;
  86.   LOGF1("L: COUtilityCar Constructor. m_pUnkOuter=0x%X.", m_pUnkOuter);
  87.   return;
  88. }
  89. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  90.   Method:   COUtilityCar::~COUtilityCar
  91.   Summary:  COUtilityCar Destructor.
  92.   Args:     void
  93.   Modifies: .
  94.   Returns:  void
  95. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  96. COUtilityCar::~COUtilityCar(void)
  97. {
  98.   LOG("L: COUtilityCar::Destructor.");
  99.   // Release the contained Car object.
  100.   m_pICar->Release();
  101.   return;
  102. }
  103. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  104.   Method:   COUtilityCar::Init
  105.   Summary:  COUtilityCar Initialization method.
  106.   Args:     void
  107.   Modifies: m_pUnkCar, m_pICar, m_cRefs.
  108.   Returns:  HRESULT
  109.               Standard result code. NOERROR for success.
  110. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  111. HRESULT COUtilityCar::Init(void)
  112. {
  113.   HRESULT hr;
  114.   LOG("L: COUtilityCar::Init.");
  115.   // Set up the right pIUnknown for delegation.  If we are being
  116.   // aggregated then we pass the pUnkOuter in turn to any COM objects
  117.   // that we are aggregating.  m_pUnkOuter was set in the Constructor.
  118.   IUnknown* pUnkOuter = (NULL == m_pUnkOuter) ? this : m_pUnkOuter;
  119.   // We create an instance of the COCar object and do this via the
  120.   // Containment reuse technique.  We ask for the new COM object's
  121.   // ICar interface directly.  We pass NULL for the pUnkOuter
  122.   // aggregation pointer because we are not aggregating.  It is here
  123.   // that we are reusing the COCar COM Object through the Containment
  124.   // technique.  We cache the requested ICar interface pointer in this
  125.   // COUtilityCar COM object for later use.  We don't need to AddRef
  126.   // this interface because the CoCreateInstance will do this for us.
  127.   hr = CoCreateInstance(
  128.          CLSID_LocCar,
  129.          NULL,
  130.          CLSCTX_LOCAL_SERVER,
  131.          IID_ICar,
  132.          (PPVOID)&m_pICar);
  133.   if (SUCCEEDED(hr))
  134.   {
  135.     LOG("L: COUtilityCar::Init (New Containment of COCar) Succeeded.");
  136.   }
  137.   else
  138.   {
  139.     LOG("L: COUtilityCar::Init (New Containment of COCar) Failed.");
  140.   }
  141.   return (hr);
  142. }
  143. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  144.   Method:   COUtilityCar::QueryInterface
  145.   Summary:  QueryInterface of the COUtilityCar non-delegating
  146.             IUnknown implementation.
  147.   Args:     REFIID riid,
  148.               [in] GUID of the Interface being requested.
  149.             PPVOID ppv)
  150.               [out] Address of the caller's pointer variable that will
  151.               receive the requested interface pointer.
  152.   Modifies: .
  153.   Returns:  HRESULT
  154. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  155. STDMETHODIMP COUtilityCar::QueryInterface(
  156.                REFIID riid,
  157.                PPVOID ppv)
  158. {
  159.   HRESULT hr = E_NOINTERFACE;
  160.   *ppv = NULL;
  161.   if (IID_IUnknown == riid)
  162.   {
  163.     *ppv = this;
  164.     LOG("L: COUtilityCar::QueryInterface. 'this' pIUnknown returned");
  165.   }
  166.   else if (IID_ICar == riid)
  167.   {
  168.     *ppv = &m_ImpICar;
  169.     LOG("L: COUtilityCar::QueryInterface. pICar returned");
  170.   }
  171.   else if (IID_IUtility == riid)
  172.   {
  173.     *ppv = &m_ImpIUtility;
  174.     LOG("L: COUtilityCar::QueryInterface. pIUtility returned");
  175.   }
  176.   if (NULL != *ppv)
  177.   {
  178.     // We've handed out a pointer to the interface so obey the COM rules
  179.     // and AddRef the reference count.
  180.     ((LPUNKNOWN)*ppv)->AddRef();
  181.     hr = NOERROR;
  182.   }
  183.   return (hr);
  184. }
  185. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  186.   Method:   COUtilityCar::AddRef
  187.   Summary:  AddRef of the COUtilityCar non-delegating IUnknown implementation.
  188.   Args:     void
  189.   Modifies: m_cRefs.
  190.   Returns:  ULONG
  191.               New value of m_cRefs (COM object's reference count).
  192. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  193. STDMETHODIMP_(ULONG) COUtilityCar::AddRef(void)
  194. {
  195.   m_cRefs++;
  196.   LOGF1("L: COUtilityCar::AddRef. New cRefs=%i.", m_cRefs);
  197.   return m_cRefs;
  198. }
  199. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  200.   Method:   COUtilityCar::Release
  201.   Summary:  Release of the COUtilityCar non-delegating IUnknown implementation.
  202.   Args:     void
  203.   Modifies: m_cRefs.
  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) COUtilityCar::Release(void)
  208. {
  209.   m_cRefs--;
  210.   LOGF1("L: COUtilityCar::Release. New cRefs=%i.", m_cRefs);
  211.   if (0 == m_cRefs)
  212.   {
  213.     // We've reached a zero reference count for this COM object.
  214.     // So we tell the server housing to decrement its global object
  215.     // count so that the server will be unloaded if appropriate.
  216.     if (NULL != m_pServer)
  217.       m_pServer->ObjectsDown();
  218.     // We artificially bump the main ref count to prevent reentrancy
  219.     // via the main object destructor.
  220.     m_cRefs++;
  221.     delete this;
  222.   }
  223.   return m_cRefs;
  224. }
  225. /*---------------------------------------------------------------------------
  226.   COUtilityCar's nested implementation of the ICar interface including
  227.   Constructor, Destructor, QueryInterface, AddRef, Release,
  228.   Shift, Clutch, Speed, and Steer.
  229. ---------------------------------------------------------------------------*/
  230. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  231.   Method:   COUtilityCar::CImpICar::CImpICar
  232.   Summary:  Constructor for the CImpICar interface instantiation.
  233.   Args:     COUtilityCar* pBackObj,
  234.               Back pointer to the parent outer object.
  235.             IUnknown* pUnkOuter,
  236.               Pointer to the outer Unknown.  For delegation.
  237.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  238.   Returns:  void
  239. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  240. COUtilityCar::CImpICar::CImpICar(
  241.   COUtilityCar* pBackObj,
  242.   IUnknown* pUnkOuter)
  243. {
  244.   // Init the Interface Ref Count (used for debugging only).
  245.   m_cRefI = 0;
  246.   // Init the Back Object Pointer to point to the outer object.
  247.   m_pBackObj = pBackObj;
  248.   // Init the CImpICar interface's delegating Unknown pointer.  We use
  249.   // the Back Object pointer for IUnknown delegation here if we are not
  250.   // being aggregated.  If we are being aggregated we use the supplied
  251.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  252.   // assignment requires no AddRef because the CImpICar lifetime is
  253.   // quaranteed by the lifetime of the parent object in which
  254.   // CImpICar is nested.
  255.   if (NULL == pUnkOuter)
  256.   {
  257.     m_pUnkOuter = pBackObj;
  258.     LOG("L: COUtilityCar::CImpICar Constructor. Non-Aggregating");
  259.   }
  260.   else
  261.   {
  262.     m_pUnkOuter = pUnkOuter;
  263.     LOG("L: COUtilityCar::CImpICar Constructor. Aggregating");
  264.   }
  265.   return;
  266. }
  267. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  268.   Method:   COUtilityCar::CImpICar::~CImpICar
  269.   Summary:  Destructor for the CImpICar interface instantiation.
  270.   Args:     void
  271.   Modifies: .
  272.   Returns:  void
  273. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  274. COUtilityCar::CImpICar::~CImpICar(void)
  275. {
  276.   LOG("L: COUtilityCar::CImpICar Destructor.");
  277.   return;
  278. }
  279. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  280.   Method:   COUtilityCar::CImpICar::QueryInterface
  281.   Summary:  The QueryInterface IUnknown member of this ICar interface
  282.             implementation that delegates to m_pUnkOuter, whatever it is.
  283.   Args:     REFIID riid,
  284.               [in] GUID of the Interface being requested.
  285.             PPVOID ppv)
  286.               [out] Address of the caller's pointer variable that will
  287.               receive the requested interface pointer.
  288.   Modifies: .
  289.   Returns:  HRESULT
  290.               Returned by the delegated outer QueryInterface call.
  291. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  292. STDMETHODIMP COUtilityCar::CImpICar::QueryInterface(
  293.                REFIID riid,
  294.                PPVOID ppv)
  295. {
  296.   LOG("L: COUtilityCar::CImpICar::QueryInterface. Delegating.");
  297.   // Delegate this call to the outer object's QueryInterface.
  298.   return m_pUnkOuter->QueryInterface(riid, ppv);
  299. }
  300. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  301.   Method:   COUtilityCar::CImpICar::AddRef
  302.   Summary:  The AddRef IUnknown member of this ICar interface
  303.             implementation that delegates to m_pUnkOuter, whatever it is.
  304.   Args:     void
  305.   Modifies: m_cRefI.
  306.   Returns:  ULONG
  307.               Returned by the delegated outer AddRef call.
  308. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  309. STDMETHODIMP_(ULONG) COUtilityCar::CImpICar::AddRef(void)
  310. {
  311.   // Increment the Interface Reference Count.
  312.   ++m_cRefI;
  313.   LOGF1("L: COUtilityCar::CImpICar::Addref. Delegating. New cI=%i.", m_cRefI);
  314.   // Delegate this call to the outer object's AddRef.
  315.   return m_pUnkOuter->AddRef();
  316. }
  317. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  318.   Method:   COUtilityCar::CImpICar::Release
  319.   Summary:  The Release IUnknown member of this ICar interface
  320.             implementation that delegates to m_pUnkOuter, whatever it is.
  321.   Args:     void
  322.   Modifies: .
  323.   Returns:  ULONG
  324.               Returned by the delegated outer Release call.
  325. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  326. STDMETHODIMP_(ULONG) COUtilityCar::CImpICar::Release(void)
  327. {
  328.   // Decrement the Interface Reference Count.
  329.   --m_cRefI;
  330.   LOGF1("L: COUtilityCar::CImpICar::Release. Delegating. New cI=%i.", m_cRefI);
  331.   // Delegate this call to the outer object's Release.
  332.   return m_pUnkOuter->Release();
  333. }
  334. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  335.   Method:   COUtilityCar::CImpICar::Shift
  336.   Summary:  The Shift member method of this ICar interface implementation.
  337.             A simple empty method on a COUtilityCar COM object for tutorial
  338.             purposes.  Presumably if this Car object were modeling
  339.             a real Car then the Shift method would shift to the specified
  340.             gear.
  341.   Args:     short nGear
  342.               0 - Neutral; 1 - 5 First 5 forward gears; 6 - Reverse.
  343.   Modifies: .
  344.   Returns:  HRESULT
  345.               NOERROR
  346. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  347. STDMETHODIMP COUtilityCar::CImpICar::Shift(
  348.                short nGear)
  349. {
  350.   LOGF1("L: COUtilityCar::CImpICar::Shift. Delegating. nGear=%i.",nGear);
  351.   // Delegate to the contained object implementation of ICar.
  352.   m_pBackObj->m_pICar->Shift(nGear);
  353.   return NOERROR;
  354. }
  355. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  356.   Method:   COUtilityCar::CImpICar::Clutch
  357.   Summary:  The Clutch member method of this ICar interface implementation.
  358.             A simple empty method on a COUtilityCar COM object for tutorial
  359.             purposes.  Presumably if this Car object were modeling
  360.             a real Car then the Clutch method would engage the clutch the
  361.             specified amount.
  362.   Args:     short nEngaged)
  363.               Percent clutch is engaged (0 to 100%).
  364.   Modifies: .
  365.   Returns:  HRESULT
  366.               NOERROR
  367. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  368. STDMETHODIMP COUtilityCar::CImpICar::Clutch(
  369.                short nEngaged)
  370. {
  371.   LOGF1("L: COUtilityCar::CImpICar::Clutch. Delegating. nEngaged=%i.", nEngaged);
  372.   // Delegate to the contained object implementation of ICar.
  373.   m_pBackObj->m_pICar->Clutch(nEngaged);
  374.   return NOERROR;
  375. }
  376. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  377.   Method:   COUtilityCar::CImpICar::Speed
  378.   Summary:  The Propel member method of this ICar interface implementation.
  379.             A simple empty method on a COUtilityCar COM object for tutorial
  380.             purposes.  Presumably if this Car object were modeling
  381.             a real Car then this method would accelerate/brake to bring
  382.             the car to the specified speed.
  383.   Args:     short nMph
  384.               New speed in miles per hour.
  385.   Modifies: .
  386.   Returns:  HRESULT
  387.               NOERROR
  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::Speed(
  390.                short nMph)
  391. {
  392.   LOGF1("L: COUtilityCar::CImpICar::Speed. Delegating. nMph=%i.",nMph);
  393.   // Delegate to the contained object implementation of ICar.
  394.   m_pBackObj->m_pICar->Speed(nMph);
  395.   return NOERROR;
  396. }
  397. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  398.   Method:   COUtilityCar::CImpICar::Steer
  399.   Summary:  The Steer member method of this ICar interface implementation.
  400.             A simple empty method on a COUtilityCar COM object for tutorial
  401.             purposes.  Presumably if this Car object were modeling
  402.             a real Car then the Steer method would set the steering
  403.             angle of the Car.
  404.   Args:     short nAngle)
  405.               0 degrees straight ahead, -45 Full left, +45 Full right.
  406.   Modifies: .
  407.   Returns:  HRESULT
  408.               NOERROR
  409. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  410. STDMETHODIMP COUtilityCar::CImpICar::Steer(
  411.                short nAngle)
  412. {
  413.   LOGF1("L: COUtilityCar::CImpICar::Steer. Delegating. nAngle=%i.",nAngle);
  414.   // Delegate to the contained object implementation of ICar.
  415.   m_pBackObj->m_pICar->Steer(nAngle);
  416.   return NOERROR;
  417. }
  418. /*---------------------------------------------------------------------------
  419.   COUtilityCar's nested implementation of the IUtility interface including
  420.   Constructor, Destructor, QueryInterface, AddRef, Release,
  421.   Offroad, and Winch.
  422. ---------------------------------------------------------------------------*/
  423. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  424.   Method:   COUtilityCar::CImpIUtility::CImpIUtility
  425.   Summary:  Constructor for the CImpIUtility interface instantiation.
  426.   Args:     COUtilityCar* pBackObj,
  427.               Back pointer to the parent outer object.
  428.             IUnknown* pUnkOuter)
  429.               Pointer to the outer Unknown.  For delegation.
  430.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  431.   Returns:  void
  432. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  433. COUtilityCar::CImpIUtility::CImpIUtility(
  434.   COUtilityCar* pBackObj,
  435.   IUnknown* pUnkOuter)
  436. {
  437.   // Init the Interface Ref Count (used for debugging only).
  438.   m_cRefI = 0;
  439.   // Init the Back Object Pointer to point to the outer object.
  440.   m_pBackObj = pBackObj;
  441.   // Init the CImpIUtility interface's delegating Unknown pointer.  We use
  442.   // the Back Object pointer for IUnknown delegation here if we are not
  443.   // being aggregated.  If we are being aggregated we use the supplied
  444.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  445.   // assignment requires no AddRef because the CImpIUtility lifetime is
  446.   // quaranteed by the lifetime of the parent object in which
  447.   // CImpIUtility is nested.
  448.   if (NULL == pUnkOuter)
  449.   {
  450.     m_pUnkOuter = pBackObj;
  451.     LOG("L: COUtilityCar::CImpIUtility Constructor. Non-Aggregating.");
  452.   }
  453.   else
  454.   {
  455.     m_pUnkOuter = pUnkOuter;
  456.     LOG("L: COUtilityCar::CImpIUtility Constructor. Aggregating.");
  457.   }
  458.   return;
  459. }
  460. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  461.   Method:   COUtilityCar::CImpIUtility::~CImpIUtility
  462.   Summary:  Destructor for the CImpIUtility interface instantiation.
  463.   Args:     void
  464.   Modifies: .
  465.   Returns:  void
  466. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  467. COUtilityCar::CImpIUtility::~CImpIUtility(void)
  468. {
  469.   LOG("L: COUtilityCar::CImpIUtility Destructor.");
  470.   return;
  471. }
  472. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  473.   Method:   COUtilityCar::CImpIUtility::QueryInterface
  474.   Summary:  The QueryInterface IUnknown member of this IUtility interface
  475.             implementation that delegates to m_pUnkOuter, whatever it is.
  476.   Args:     REFIID riid,
  477.               [in] GUID of the Interface being requested.
  478.             PPVOID ppv)
  479.               [out] Address of the caller's pointer variable that will
  480.               receive the requested interface pointer.
  481.   Modifies: .
  482.   Returns:  HRESULT
  483.               Returned by the delegated outer QueryInterface call.
  484. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  485. STDMETHODIMP COUtilityCar::CImpIUtility::QueryInterface(
  486.                REFIID riid,
  487.                PPVOID ppv)
  488. {
  489.   LOG("L: COUtilityCar::CImpIUtility::QueryInterface. Delegating.");
  490.   // Delegate this call to the outer object's QueryInterface.
  491.   return m_pUnkOuter->QueryInterface(riid, ppv);
  492. }
  493. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  494.   Method:   COUtilityCar::CImpIUtility::AddRef
  495.   Summary:  The AddRef IUnknown member of this IUtility interface
  496.             implementation that delegates to m_pUnkOuter, whatever it is.
  497.   Args:     void
  498.   Modifies: m_cRefI.
  499.   Returns:  ULONG
  500.               Returned by the delegated outer AddRef call.
  501. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  502. STDMETHODIMP_(ULONG) COUtilityCar::CImpIUtility::AddRef(void)
  503. {
  504.   // Increment the Interface Reference Count.
  505.   ++m_cRefI;
  506.   LOGF1("L: COUtilityCar::CImpIUtility::Addref. Delegating. New cI=%i.", m_cRefI);
  507.   // Delegate this call to the outer object's AddRef.
  508.   return m_pUnkOuter->AddRef();
  509. }
  510. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  511.   Method:   COUtilityCar::CImpIUtility::Release
  512.   Summary:  The Release IUnknown member of this IUtility interface
  513.             implementation that delegates to m_pUnkOuter, whatever it is.
  514.   Args:     void
  515.   Modifies: .
  516.   Returns:  ULONG
  517.               Returned by the delegated outer Release call.
  518. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  519. STDMETHODIMP_(ULONG) COUtilityCar::CImpIUtility::Release(void)
  520. {
  521.   // Decrement the Interface Reference Count.
  522.   --m_cRefI;
  523.   LOGF1("L: COUtilityCar::CImpIUtility::Release. Delegating. New cI=%i.", m_cRefI);
  524.   // Delegate this call to the outer object's Release.
  525.   return m_pUnkOuter->Release();
  526. }
  527. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  528.   Method:   COUtilityCar::CImpIUtility::Offroad
  529.   Summary:  The Offroad member method of this IUtility interface
  530.             implementation.  A simple empty method on a COUtilityCar
  531.             COM object for tutorial purposes.  Presumably if this
  532.             UtilityCar object were modeling a real Car then the Offroad
  533.             method would function the 4-wheel drive transfer case and
  534.             shift it to the specified 4-wheel drive mode.
  535.   Args:     short nGear
  536.               0 = 2H or regular 2-wheel drive;
  537.               1 = 4H or 4-wheel drive high speed;
  538.               2 = neutral; and
  539.               3 = 4L or 4-wheel drive low speed).
  540.   Modifies: .
  541.   Returns:  HRESULT
  542.               NOERROR
  543. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  544. STDMETHODIMP COUtilityCar::CImpIUtility::Offroad(
  545.                short nGear)
  546. {
  547.   LOGF1("L: COUtilityCar::CImpIUtility::Offroad. Called. nGear=%i.",nGear);
  548.   return NOERROR;
  549. }
  550. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  551.   Method:   COUtilityCar::CImpIUtility::Winch
  552.   Summary:  The Winch member method of this IUtility interface
  553.             implementation.  A simple empty method on a COUtilityCar COM
  554.             object for tutorial purposes.  Presumably if this UtilityCar
  555.             object were modeling a real Car then the Winch method would
  556.             turn on/off the front-mounted Winch to the specified RPMs.
  557.   Args:     short nRpm
  558.               0 = off; 1 - 50 RPM.
  559.   Modifies: .
  560.   Returns:  HRESULT
  561.               NOERROR
  562. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  563. STDMETHODIMP COUtilityCar::CImpIUtility::Winch(
  564.                short nRpm)
  565. {
  566.   LOGF1("L: COUtilityCar::CImpIUtility::Winch. Called. nRpm=%i.",nRpm);
  567.   return NOERROR;
  568. }