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 / comobj / utilcar.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-04  |  23.3 KB  |  729 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 accompanying COMOBJ.TXT
  14.              file.  For more specific technical details on the internal
  15.              workings see the comments dispersed throughout the
  16.              module's source code.
  17.  
  18.   Classes:   COUtilityCar
  19.  
  20.   Functions: none.
  21.  
  22.   Origin:    10-3-97: atrent - Created. [Revised]
  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 ICARS.H and CARGUIDS.H for the common car-related Interface
  46.     class, GUID, and CLSID specifications.
  47.   We include COMOBJI.H because it has internal class declarations and
  48.     resource ID definitions specific for this DLL.
  49.   We include COMOBJ.H because it has the interface declarations.
  50.   We include CAR.H because it has the class COCar declarations.
  51.   We include UTILCAR.H because it has the class COUtilityCar declarations.
  52. ---------------------------------------------------------------------------*/
  53. #include <windows.h>
  54. #include <ole2.h>
  55. #include <apputil.h>
  56. #include <icars.h>
  57. #include <carguids.h>
  58. #include "comobji.h"
  59. #define _LOCALCALLS_
  60. #include "comobj.h"
  61. #include "car.h"
  62. #include "utilcar.h"
  63.  
  64.  
  65. /*---------------------------------------------------------------------------
  66.   COUtilityCar's implementation of its main COM object class including
  67.   Constructor, Destructor, QueryInterface, AddRef, and Release.
  68. ---------------------------------------------------------------------------*/
  69.  
  70. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  71.   Method:   COUtilityCar::COUtilityCar
  72.  
  73.   Summary:  COUtilityCar Constructor. Note the member initializers:
  74.             "m_ImpICar(this, pUnkOuter)" and "m_ImpIUtility(this,
  75.             pUnkOuter)" which are used to pass the 'this' and
  76.             pUnkOuter pointers of this constructor function to the
  77.             constructors that instantiate the implementations of
  78.             the CImpICar and CImpIUtility interfaces (which are both
  79.             nested inside this present COUtilityCar Object Class.
  80.  
  81.   Args:     IUnknown* pUnkOuter)
  82.               Pointer to the the outer Unknown.  NULL means this COM Object
  83.               is not being Aggregated.  Non NULL means it is being created
  84.               on behalf of an outside COM object that is reusing it via
  85.               aggregation.
  86.  
  87.   Modifies: m_cRefs, m_pUnkOuter.
  88.  
  89.   Returns:  void
  90. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  91. COUtilityCar::COUtilityCar(
  92.   IUnknown* pUnkOuter) :
  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 we're nested.
  100.   m_pUnkOuter = pUnkOuter;
  101.  
  102.   // Zero the pointer to the contained COCar object's ICar interface.
  103.   m_pICar = NULL;
  104.  
  105.   LOGF1("D: COUtilityCar Constructor. m_pUnkOuter=0x%X.", m_pUnkOuter);
  106.  
  107.   return;
  108. }
  109.  
  110.  
  111. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  112.   Method:   COUtilityCar::~COUtilityCar
  113.  
  114.   Summary:  COUtilityCar Destructor.
  115.  
  116.   Args:     void
  117.  
  118.   Modifies: .
  119.  
  120.   Returns:  void
  121. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  122. COUtilityCar::~COUtilityCar(void)
  123. {
  124.   LOG("D: COUtilityCar::Destructor.");
  125.  
  126.   m_pICar->Release();
  127.  
  128.   return;
  129. }
  130.  
  131.  
  132. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  133.   Method:   COUtilityCar::Init
  134.  
  135.   Summary:  COUtilityCar Initialization method.
  136.  
  137.   Args:     void
  138.  
  139.   Modifies: m_pUnkCar, m_pICar, m_cRefs.
  140.  
  141.   Returns:  HRESULT
  142.               Standard result code. NOERROR for success.
  143. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  144. HRESULT COUtilityCar::Init(void)
  145. {
  146.   HRESULT hr;
  147.  
  148.   LOG("D: COUtilityCar::Init.");
  149.  
  150.   // Create an instance of the COCar object and ask for its ICar
  151.   // interface directly.  We pass NULL for the pUnkOuter because we
  152.   // are not aggregating.  It is here that we are reusing the COCar
  153.   // COM Object through the Containment technique.  We cache the
  154.   // pointer to the ICar interface for later delegation use.  We
  155.   // don't need to AddRef it here because CreateCar does that for us.
  156.   hr = CreateCar(NULL, IID_ICar, (PPVOID) &m_pICar);
  157.  
  158.   return (hr);
  159. }
  160.  
  161.  
  162. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  163.   Method:   COUtilityCar::QueryInterface
  164.  
  165.   Summary:  QueryInterface of the COUtilityCar non-delegating
  166.             IUnknown implementation.
  167.  
  168.   Args:     REFIID riid,
  169.               [in] GUID of the Interface being requested.
  170.             PPVOID ppv)
  171.               [out] Address of the caller's pointer variable that will
  172.               receive the requested interface pointer.
  173.  
  174.   Modifies: .
  175.  
  176.   Returns:  HRESULT
  177. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  178. STDMETHODIMP COUtilityCar::QueryInterface(
  179.                REFIID riid,
  180.                PPVOID ppv)
  181. {
  182.   HRESULT hr = E_NOINTERFACE;
  183.   *ppv = NULL;
  184.  
  185.   if (IID_IUnknown == riid)
  186.   {
  187.     *ppv = this;
  188.     LOG("D: COUtilityCar::QueryInterface. 'this' pIUnknown returned");
  189.   }
  190.   else if (IID_ICar == riid)
  191.   {
  192.     *ppv = &m_ImpICar;
  193.     LOG("D: COUtilityCar::QueryInterface. pICar returned");
  194.   }
  195.   else if (IID_IUtility == riid)
  196.   {
  197.     *ppv = &m_ImpIUtility;
  198.     LOG("D: COUtilityCar::QueryInterface. pIUtility returned");
  199.   }
  200.  
  201.   if (NULL != *ppv)
  202.   {
  203.     // We've handed out a pointer to the interface so obey the COM rules
  204.     //   and AddRef the reference count.
  205.     ((LPUNKNOWN)*ppv)->AddRef();
  206.     hr = NOERROR;
  207.   }
  208.  
  209.   return (hr);
  210. }
  211.  
  212.  
  213. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  214.   Method:   COUtilityCar::AddRef
  215.  
  216.   Summary:  AddRef of the COUtilityCar non-delegating IUnknown implementation.
  217.  
  218.   Args:     void
  219.  
  220.   Modifies: m_cRefs.
  221.  
  222.   Returns:  ULONG
  223.               New value of m_cRefs (COM object's reference count).
  224. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  225. STDMETHODIMP_(ULONG) COUtilityCar::AddRef(void)
  226. {
  227.   m_cRefs++;
  228.  
  229.   LOGF1("D: COUtilityCar::AddRef. New cRefs=%i.", m_cRefs);
  230.  
  231.   return m_cRefs;
  232. }
  233.  
  234.  
  235. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  236.   Method:   COUtilityCar::Release
  237.  
  238.   Summary:  Release of the COUtilityCar non-delegating IUnknown implementation.
  239.  
  240.   Args:     void
  241.  
  242.   Modifies: m_cRefs.
  243.  
  244.   Returns:  ULONG
  245.               New value of m_cRefs (COM object's reference count).
  246. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  247. STDMETHODIMP_(ULONG) COUtilityCar::Release(void)
  248. {
  249.   m_cRefs--;
  250.  
  251.   LOGF1("D: COUtilityCar::Release. New cRefs=%i.", m_cRefs);
  252.  
  253.   if (0 == m_cRefs)
  254.   {
  255.     // We artificially bump the main ref count to prevent reentrancy
  256.     // via the main object destructor.
  257.     m_cRefs++;
  258.     delete this;
  259.   }
  260.  
  261.   return m_cRefs;;
  262. }
  263.  
  264.  
  265. /*---------------------------------------------------------------------------
  266.   COUtilityCar's nested implementation of the ICar interface including
  267.   Constructor, Destructor, QueryInterface, AddRef, Release,
  268.   Shift, Clutch, Speed, and Steer.
  269. ---------------------------------------------------------------------------*/
  270.  
  271. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  272.   Method:   COUtilityCar::CImpICar::CImpICar
  273.  
  274.   Summary:  Constructor for the CImpICar interface instantiation.
  275.  
  276.   Args:     COUtilityCar* pBackObj,
  277.               Back pointer to the parent outer object.
  278.             IUnknown* pUnkOuter)
  279.               Pointer to the outer Unknown.  For delegation.
  280.  
  281.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  282.  
  283.   Returns:  void
  284. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  285. COUtilityCar::CImpICar::CImpICar(
  286.   COUtilityCar* pBackObj,
  287.   IUnknown* pUnkOuter)
  288. {
  289.   // Init the Interface Ref Count (used for debugging only).
  290.   m_cRefI=0;
  291.  
  292.   // Init the Back Object Pointer to point to the outer object.
  293.   m_pBackObj=pBackObj;
  294.  
  295.   // Init the CImpICar interface's delegating Unknown pointer.  We use
  296.   // the Back Object pointer for IUnknown delegation here if we are not
  297.   // being aggregated.  If we are being aggregated we use the supplied
  298.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  299.   // assignment requires no AddRef because the CImpICar lifetime is
  300.   // quaranteed by the lifetime of the parent object in which
  301.   // CImpICar is nested.
  302.   if (NULL == pUnkOuter)
  303.   {
  304.     m_pUnkOuter = pBackObj;
  305.     LOG("D: COUtilityCar::CImpICar Constructor. Non-Aggregating");
  306.   }
  307.   else
  308.   {
  309.     m_pUnkOuter = pUnkOuter;
  310.     LOG("D: COUtilityCar::CImpICar Constructor. Aggregating");
  311.   }
  312.  
  313.   return;
  314. }
  315.  
  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::~CImpICar
  319.  
  320.   Summary:  Destructor for the CImpICar interface instantiation.
  321.  
  322.   Args:     void
  323.  
  324.   Modifies: .
  325.  
  326.   Returns:  void
  327. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  328. COUtilityCar::CImpICar::~CImpICar(void)
  329. {
  330.   LOG("D: COUtilityCar::CImpICar Destructor.");
  331.  
  332.   return;
  333. }
  334.  
  335.  
  336. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  337.   Method:   COUtilityCar::CImpICar::QueryInterface
  338.  
  339.   Summary:  The QueryInterface IUnknown member of this ICar interface
  340.             implementation that delegates to m_pUnkOuter, whatever it is.
  341.  
  342.   Args:     REFIID riid,
  343.               [in] GUID of the Interface being requested.
  344.             PPVOID ppv)
  345.               [out] Address of the caller's pointer variable that will
  346.               receive the requested interface pointer.
  347.  
  348.   Modifies: .
  349.  
  350.   Returns:  HRESULT
  351.               Returned by the delegated outer QueryInterface call.
  352. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  353. STDMETHODIMP COUtilityCar::CImpICar::QueryInterface(
  354.                REFIID riid,
  355.                PPVOID ppv)
  356. {
  357.   LOG("D: COUtilityCar::CImpICar::QueryInterface. Delegating.");
  358.  
  359.   // Delegate this call to the outer object's QueryInterface.
  360.   return m_pUnkOuter->QueryInterface(riid, ppv);
  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:   COUtilityCar::CImpICar::AddRef
  366.  
  367.   Summary:  The AddRef IUnknown member of this ICar interface
  368.             implementation that delegates to m_pUnkOuter, whatever it is.
  369.  
  370.   Args:     void
  371.  
  372.   Modifies: m_cRefI.
  373.  
  374.   Returns:  ULONG
  375.               Returned by the delegated outer AddRef 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) COUtilityCar::CImpICar::AddRef(void)
  378. {
  379.   // Increment the Interface Reference Count.
  380.   ++m_cRefI;
  381.  
  382.   LOGF1("D: COUtilityCar::CImpICar::Addref. Delegating. New cI=%i.", m_cRefI);
  383.  
  384.   // Delegate this call to the outer object's AddRef.
  385.   return m_pUnkOuter->AddRef();
  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:   COUtilityCar::CImpICar::Release
  391.  
  392.   Summary:  The Release IUnknown member of this ICar interface
  393.             implementation that delegates to m_pUnkOuter, whatever it is.
  394.  
  395.   Args:     void
  396.  
  397.   Modifies: .
  398.  
  399.   Returns:  ULONG
  400.               Returned by the delegated outer Release call.
  401. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  402. STDMETHODIMP_(ULONG) COUtilityCar::CImpICar::Release(void)
  403. {
  404.   // Decrement the Interface Reference Count.
  405.   --m_cRefI;
  406.  
  407.   LOGF1("D: COUtilityCar::CImpICar::Release. Delegating. New cI=%i.", m_cRefI);
  408.  
  409.   // Delegate this call to the outer object's Release.
  410.   return m_pUnkOuter->Release();
  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:   COUtilityCar::CImpICar::Shift
  416.  
  417.   Summary:  The Shift member method of this ICar interface implementation.
  418.             A simple empty method on a COUtilityCar COM object for tutorial
  419.             purposes.  Presumably if this Car object were modeling
  420.             a real Car then the Shift method would shift to the specified
  421.             gear.
  422.  
  423.   Args:     short nGear
  424.               0 - Neutral; 1 - 5 First 5 forward gears; 6 - Reverse.
  425.  
  426.   Modifies: .
  427.  
  428.   Returns:  HRESULT
  429.               NOERROR
  430. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  431. STDMETHODIMP COUtilityCar::CImpICar::Shift(
  432.                short nGear)
  433. {
  434.   LOGF1("D: COUtilityCar::CImpICar::Shift. Delegating. nGear=%i.",nGear);
  435.  
  436.   m_pBackObj->m_pICar->Shift(nGear);
  437.  
  438.   return NOERROR;
  439. }
  440.  
  441.  
  442. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  443.   Method:   COUtilityCar::CImpICar::Clutch
  444.  
  445.   Summary:  The Clutch member method of this ICar interface implementation.
  446.             A simple empty method on a COUtilityCar COM object for tutorial
  447.             purposes.  Presumably if this Car object were modeling
  448.             a real Car then the Clutch method would engage the clutch the
  449.             specified amount.
  450.  
  451.   Args:     short nEngaged)
  452.               Percent clutch is engaged (0 to 100%).
  453.  
  454.   Modifies: .
  455.  
  456.   Returns:  HRESULT
  457.               NOERROR
  458. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  459. STDMETHODIMP COUtilityCar::CImpICar::Clutch(
  460.                short nEngaged)
  461. {
  462.   LOGF1("D: COUtilityCar::CImpICar::Clutch. Delegating. nEngaged=%i.",nEngaged);
  463.  
  464.   m_pBackObj->m_pICar->Clutch(nEngaged);
  465.  
  466.   return NOERROR;
  467. }
  468.  
  469.  
  470. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  471.   Method:   COUtilityCar::CImpICar::Speed
  472.  
  473.   Summary:  The Propel member method of this ICar interface implementation.
  474.             A simple empty method on a COUtilityCar COM object for tutorial
  475.             purposes.  Presumably if this Car object were modeling
  476.             a real Car then this method would accelerate/brake to bring
  477.             the car to the specified speed.
  478.  
  479.   Args:     short nMph
  480.               New speed in miles per hour.
  481.  
  482.   Modifies: .
  483.  
  484.   Returns:  HRESULT
  485.               NOERROR
  486. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  487. STDMETHODIMP COUtilityCar::CImpICar::Speed(
  488.                short nMph)
  489. {
  490.   LOGF1("D: COUtilityCar::CImpICar::Speed. Delegating. nMph=%i.",nMph);
  491.  
  492.   m_pBackObj->m_pICar->Speed(nMph);
  493.  
  494.   return NOERROR;
  495. }
  496.  
  497.  
  498. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  499.   Method:   COUtilityCar::CImpICar::Steer
  500.  
  501.   Summary:  The Steer member method of this ICar interface implementation.
  502.             A simple empty method on a COUtilityCar COM object for tutorial
  503.             purposes.  Presumably if this Car object were modeling
  504.             a real Car then the Steer method would set the steering
  505.             angle of the Car.
  506.  
  507.   Args:     short nAngle)
  508.               0 degrees straight ahead, -45 Full left, +45 Full right.
  509.  
  510.   Modifies: .
  511.  
  512.   Returns:  HRESULT
  513.               NOERROR
  514. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  515. STDMETHODIMP COUtilityCar::CImpICar::Steer(
  516.                short nAngle)
  517. {
  518.  LOGF1("D: COUtilityCar::CImpICar::Steer. Delegating. nAngle=%i.",nAngle);
  519.  
  520.   m_pBackObj->m_pICar->Steer(nAngle);
  521.  
  522.   return NOERROR;
  523. }
  524.  
  525.  
  526. /*---------------------------------------------------------------------------
  527.   COUtilityCar's nested implementation of the IUtility interface including
  528.   Constructor, Destructor, QueryInterface, AddRef, Release,
  529.   Offroad, and Winch.
  530. ---------------------------------------------------------------------------*/
  531.  
  532. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  533.   Method:   COUtilityCar::CImpIUtility::CImpIUtility
  534.  
  535.   Summary:  Constructor for the CImpIUtility interface instantiation.
  536.  
  537.   Args:     COUtilityCar* pBackObj,
  538.               Back pointer to the parent outer object.
  539.             IUnknown* pUnkOuter)
  540.               Pointer to the outer Unknown.  For delegation.
  541.  
  542.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  543.  
  544.   Returns:  void
  545. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  546. COUtilityCar::CImpIUtility::CImpIUtility(
  547.   COUtilityCar* pBackObj,
  548.   IUnknown* pUnkOuter)
  549. {
  550.   // Init the Interface Ref Count (used for debugging only).
  551.   m_cRefI = 0;
  552.  
  553.   // Init the Back Object Pointer to point to the outer object.
  554.   m_pBackObj = pBackObj;
  555.  
  556.   // Init the CImpIUtility interface's delegating Unknown pointer.  We use
  557.   // the Back Object pointer for IUnknown delegation here if we are not
  558.   // being aggregated.  If we are being aggregated we use the supplied
  559.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  560.   // assignment requires no AddRef because the CImpIUtility lifetime is
  561.   // quaranteed by the lifetime of the parent object in which
  562.   // CImpIUtility is nested.
  563.   if (NULL == pUnkOuter)
  564.   {
  565.     m_pUnkOuter = pBackObj;
  566.     LOG("D: COUtilityCar::CImpIUtility Constructor. Non-Aggregating.");
  567.   }
  568.   else
  569.   {
  570.     m_pUnkOuter = pUnkOuter;
  571.     LOG("D: COUtilityCar::CImpIUtility Constructor. Aggregating.");
  572.   }
  573.  
  574.   return;
  575. }
  576.  
  577.  
  578. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  579.   Method:   COUtilityCar::CImpIUtility::~CImpIUtility
  580.  
  581.   Summary:  Destructor for the CImpIUtility interface instantiation.
  582.  
  583.   Args:     void
  584.  
  585.   Modifies: .
  586.  
  587.   Returns:  void
  588. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  589. COUtilityCar::CImpIUtility::~CImpIUtility(void)
  590. {
  591.   LOG("D: COUtilityCar::CImpIUtility Destructor.");
  592.  
  593.   return;
  594. }
  595.  
  596.  
  597. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  598.   Method:   COUtilityCar::CImpIUtility::QueryInterface
  599.  
  600.   Summary:  The QueryInterface IUnknown member of this IUtility interface
  601.             implementation that delegates to m_pUnkOuter, whatever it is.
  602.  
  603.   Args:     REFIID riid,
  604.               [in] GUID of the Interface being requested.
  605.             PPVOID ppv)
  606.               [out] Address of the caller's pointer variable that will
  607.               receive the requested interface pointer.
  608.  
  609.   Modifies: .
  610.  
  611.   Returns:  HRESULT
  612.               Returned by the delegated outer QueryInterface call.
  613. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  614. STDMETHODIMP COUtilityCar::CImpIUtility::QueryInterface(
  615.                REFIID riid,
  616.                PPVOID ppv)
  617. {
  618.   LOG("D: COUtilityCar::CImpIUtility::QueryInterface. Delegating.");
  619.  
  620.   // Delegate this call to the outer object's QueryInterface.
  621.   return m_pUnkOuter->QueryInterface(riid, ppv);
  622. }
  623.  
  624.  
  625. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  626.   Method:   COUtilityCar::CImpIUtility::AddRef
  627.  
  628.   Summary:  The AddRef IUnknown member of this IUtility interface
  629.             implementation that delegates to m_pUnkOuter, whatever it is.
  630.  
  631.   Args:     void
  632.  
  633.   Modifies: m_cRefI.
  634.  
  635.   Returns:  ULONG
  636.               Returned by the delegated outer AddRef call.
  637. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  638. STDMETHODIMP_(ULONG) COUtilityCar::CImpIUtility::AddRef(void)
  639. {
  640.   // Increment the Interface Reference Count.
  641.   ++m_cRefI;
  642.  
  643.   LOGF1("D: COUtilityCar::CImpIUtility::Addref. Delegating. New cI=%i.", m_cRefI);
  644.  
  645.   // Delegate this call to the outer object's AddRef.
  646.   return m_pUnkOuter->AddRef();
  647. }
  648.  
  649.  
  650. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  651.   Method:   COUtilityCar::CImpIUtility::Release
  652.  
  653.   Summary:  The Release IUnknown member of this IUtility interface
  654.             implementation that delegates to m_pUnkOuter, whatever it is.
  655.  
  656.   Args:     void
  657.  
  658.   Modifies: .
  659.  
  660.   Returns:  ULONG
  661.               Returned by the delegated outer Release call.
  662. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  663. STDMETHODIMP_(ULONG) COUtilityCar::CImpIUtility::Release(void)
  664. {
  665.   // Decrement the Interface Reference Count.
  666.   --m_cRefI;
  667.  
  668.   LOGF1("D: COUtilityCar::CImpIUtility::Release. Delegating. New cI=%i.", m_cRefI);
  669.  
  670.   // Delegate this call to the outer object's Release.
  671.   return m_pUnkOuter->Release();
  672. }
  673.  
  674.  
  675. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  676.   Method:   COUtilityCar::CImpIUtility::Offroad
  677.  
  678.   Summary:  The Offroad member method of this IUtility interface
  679.             implementation.  A simple empty method on a COUtilityCar
  680.             COM object for tutorial purposes.  Presumably if this
  681.             UtilityCar object were modeling a real Car then the Offroad
  682.             method would function the 4-wheel drive transfer case and
  683.             shift it to the specified 4-wheel drive mode.
  684.  
  685.   Args:     short nGear
  686.               0 = 2H or regular 2-wheel drive;
  687.               1 = 4H or 4-wheel drive high speed;
  688.               2 = neutral; and
  689.               3 = 4L or 4-wheel drive low speed).
  690.  
  691.   Modifies: .
  692.  
  693.   Returns:  HRESULT
  694.               NOERROR
  695. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  696. STDMETHODIMP COUtilityCar::CImpIUtility::Offroad(
  697.                short nGear)
  698. {
  699.   LOGF1("D: COUtilityCar::CImpIUtility::Offroad. Called. nGear=%i.",nGear);
  700.  
  701.   return NOERROR;
  702. }
  703.  
  704.  
  705. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  706.   Method:   COUtilityCar::CImpIUtility::Winch
  707.  
  708.   Summary:  The Winch member method of this IUtility interface
  709.             implementation.  A simple empty method on a COUtilityCar COM
  710.             object for tutorial purposes.  Presumably if this UtilityCar
  711.             object were modeling a real Car then the Winch method would
  712.             turn on/off the front-mounted Winch to the specified RPMs.
  713.  
  714.   Args:     short nRpm
  715.               0 = off; 1 - 50 RPM.
  716.  
  717.   Modifies: .
  718.  
  719.   Returns:  HRESULT
  720.               NOERROR
  721. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  722. STDMETHODIMP COUtilityCar::CImpIUtility::Winch(
  723.                short nRpm)
  724. {
  725.   LOGF1("D: COUtilityCar::CImpIUtility::Winch. Called. nRpm=%i.",nRpm);
  726.  
  727.   return NOERROR;
  728. }
  729.