home *** CD-ROM | disk | FTP | other *** search
/ PC Press 1997 July / Sezamfile97_2.iso / windows / program / activex / axtsamp.exe / TSBRANCH.EXE / APTSERVE / CRUCAR.CPP < prev    next >
C/C++ Source or Header  |  1996-12-29  |  26KB  |  766 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 Containment 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 APTSERVE.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:    3-20-96: atrent - Editor-inheritance from CRUCAR.CPP in
  23.                the LOCSERVE Tutorial Code Sample.
  24.  
  25. ----------------------------------------------------------------------------
  26.   This file is part of the Microsoft ActiveX 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 make calls to 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_ImpICar(this, pUnkOuter),
  94.   m_ImpICruise(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.   // Assign the pointer to the server's control object.
  107.   m_pServer = pServer;
  108.  
  109.   LOGF2("L<%X>: COCruiseCar 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:   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.   LOGF1("L<%X>: COCruiseCar::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:   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.   LOGF1("L<%X>: COCruiseCar::Init.",TID);
  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.   // Containment reuse technique.  We ask for the new COM object's
  163.   // ICar interface directly.  We pass NULL for the pUnkOuter
  164.   // aggregation pointer because we are not aggregating.  It is here
  165.   // that we are reusing the COCar COM Object through the Containment
  166.   // technique.  We cache the requested ICar interface pointer in this
  167.   // COCruiseCar COM object for later use.  We don't need to AddRef
  168.   // this interface because the CoCreateInstance will do this for us.
  169.   hr = CoCreateInstance(
  170.          CLSID_AptCar,
  171.          NULL,
  172.          CLSCTX_LOCAL_SERVER,
  173.          IID_ICar,
  174.          (PPVOID)&m_pICar);
  175.  
  176.   if (SUCCEEDED(hr))
  177.   {
  178.     LOGF1("L<%X>: COCruiseCar::Init (New Containment of COCar) Succeeded.",TID);
  179.   }
  180.   else
  181.   {
  182.     LOGF2("L<%X>: COCruiseCar::Init (New Containment of COCar) Failed. hr=0x%X.",TID,hr);
  183.   }
  184.  
  185.   return (hr);
  186. }
  187.  
  188.  
  189. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  190.   Method:   COCruiseCar::QueryInterface
  191.  
  192.   Summary:  QueryInterface of the COCruiseCar non-delegating
  193.             IUnknown implementation.
  194.  
  195.   Args:     REFIID riid,
  196.               [in] GUID of the Interface being requested.
  197.             PPVOID ppv)
  198.               [out] Address of the caller's pointer variable that will
  199.               receive the requested interface pointer.
  200.  
  201.   Modifies: *ppv.
  202.  
  203.   Returns:  HRESULT
  204. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  205. STDMETHODIMP COCruiseCar::QueryInterface(
  206.                REFIID riid,
  207.                PPVOID ppv)
  208. {
  209.   HRESULT hr = E_NOINTERFACE;
  210.   *ppv = NULL;
  211.  
  212.   if (IID_IUnknown == riid)
  213.   {
  214.     *ppv = this;
  215.     LOGF1("L<%X>: COCruiseCar::QueryInterface. 'this' pIUnknown returned.",TID);
  216.   }
  217.   else if (IID_ICar == riid)
  218.   {
  219.     *ppv = &m_ImpICar;
  220.     LOGF1("L<%X>: COCruiseCar::QueryInterface. pICar returned",TID);
  221.   }
  222.   else if (IID_ICruise == riid)
  223.   {
  224.     // This ICruise interface is implemented in this COCruiseCar object
  225.     // and might be called a native interface of COCruiseCar.
  226.     *ppv = &m_ImpICruise;
  227.     LOGF1("L<%X>: COCruiseCar::QueryInterface. pICruise returned.",TID);
  228.   }
  229.  
  230.   if (NULL != *ppv)
  231.   {
  232.     // We've handed out a pointer to an interface so obey the COM rules
  233.     // and AddRef its reference count.
  234.     ((LPUNKNOWN)*ppv)->AddRef();
  235.     hr = NOERROR;
  236.   }
  237.  
  238.   return (hr);
  239. }
  240.  
  241.  
  242. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  243.   Method:   COCruiseCar::AddRef
  244.  
  245.   Summary:  AddRef of the COCruiseCar non-delegating IUnknown implementation.
  246.  
  247.   Args:     void
  248.  
  249.   Modifies: m_cRefs.
  250.  
  251.   Returns:  ULONG
  252.               New value of m_cRefs (COM object's reference count).
  253. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  254. STDMETHODIMP_(ULONG) COCruiseCar::AddRef(void)
  255. {
  256.   m_cRefs++;
  257.  
  258.   LOGF2("L<%X>: COCruiseCar::AddRef. New cRefs=%i.",TID,m_cRefs);
  259.  
  260.   return m_cRefs;
  261. }
  262.  
  263.  
  264. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  265.   Method:   COCruiseCar::Release
  266.  
  267.   Summary:  Release of the COCruiseCar non-delegating IUnknown
  268.             implementation.
  269.  
  270.   Args:     void
  271.  
  272.   Modifies: m_cRefs.
  273.  
  274.   Returns:  ULONG
  275.               New value of m_cRefs (COM object's reference count).
  276. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  277. STDMETHODIMP_(ULONG) COCruiseCar::Release(void)
  278. {
  279.   ULONG ulCount = --m_cRefs;
  280.  
  281.   LOGF2("L<%X>: COCruiseCar::Release. New cRefs=%i.",TID,m_cRefs);
  282.  
  283.   if (0 == m_cRefs)
  284.   {
  285.     // We've reached a zero reference count for this COM object.
  286.     // So we tell the server housing to decrement its global object
  287.     // count so that the server will be unloaded if appropriate.
  288.     if (NULL != m_pServer)
  289.       m_pServer->ObjectsDown();
  290.  
  291.     // We artificially bump the main ref count to ensure that an indirect
  292.     // recursive call to this release won't occur because of other
  293.     // delegating releases that might happen in our own destructor.
  294.     m_cRefs++;
  295.     delete this;
  296.   }
  297.  
  298.   return ulCount;
  299. }
  300.  
  301.  
  302. /*---------------------------------------------------------------------------
  303.   COCruiseCar's nested implementation of the ICar interface including
  304.   Constructor, Destructor, QueryInterface, AddRef, Release,
  305.   Shift, Clutch, Speed, and Steer.
  306. ---------------------------------------------------------------------------*/
  307.  
  308. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  309.   Method:   COCruiseCar::CImpICar::CImpICar
  310.  
  311.   Summary:  Constructor for the CImpICar interface instantiation.
  312.  
  313.   Args:     COCruiseCar* pBackObj,
  314.               Back pointer to the parent outer object.
  315.             IUnknown* pUnkOuter,
  316.               Pointer to the outer Unknown.  For delegation.
  317.  
  318.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  319.  
  320.   Returns:  void
  321. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  322. COCruiseCar::CImpICar::CImpICar(
  323.   COCruiseCar* pBackObj,
  324.   IUnknown* pUnkOuter)
  325. {
  326.   // Init the Interface Ref Count (used for debugging only).
  327.   m_cRefI = 0;
  328.  
  329.   // Init the Back Object Pointer to point to the outer object.
  330.   m_pBackObj = pBackObj;
  331.  
  332.   // Init the CImpICar interface's delegating Unknown pointer.  We use
  333.   // the Back Object pointer for IUnknown delegation here if we are not
  334.   // being aggregated.  If we are being aggregated we use the supplied
  335.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  336.   // assignment requires no AddRef because the CImpICar lifetime is
  337.   // quaranteed by the lifetime of the parent object in which
  338.   // CImpICar is nested.
  339.   if (NULL == pUnkOuter)
  340.   {
  341.     m_pUnkOuter = pBackObj;
  342.     LOGF1("L<%X>: COCruiseCar::CImpICar Constructor. Non-Aggregating",TID);
  343.   }
  344.   else
  345.   {
  346.     m_pUnkOuter = pUnkOuter;
  347.     LOGF1("L<%X>: COCruiseCar::CImpICar Constructor. Aggregating",TID);
  348.   }
  349.  
  350.   return;
  351. }
  352.  
  353.  
  354. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  355.   Method:   COCruiseCar::CImpICar::~CImpICar
  356.  
  357.   Summary:  Destructor for the CImpICar interface instantiation.
  358.  
  359.   Args:     void
  360.  
  361.   Modifies: .
  362.  
  363.   Returns:  void
  364. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  365. COCruiseCar::CImpICar::~CImpICar(void)
  366. {
  367.   LOGF1("L<%X>: COCruiseCar::CImpICar Destructor.",TID);
  368.  
  369.   return;
  370. }
  371.  
  372.  
  373. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  374.   Method:   COCruiseCar::CImpICar::QueryInterface
  375.  
  376.   Summary:  The QueryInterface IUnknown member of this ICar interface
  377.             implementation that delegates to m_pUnkOuter, whatever it is.
  378.  
  379.   Args:     REFIID riid,
  380.               [in] GUID of the Interface being requested.
  381.             PPVOID ppv)
  382.               [out] Address of the caller's pointer variable that will
  383.               receive the requested interface pointer.
  384.  
  385.   Modifies: .
  386.  
  387.   Returns:  HRESULT
  388.               Returned by the delegated outer QueryInterface call.
  389. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  390. STDMETHODIMP COCruiseCar::CImpICar::QueryInterface(
  391.                REFIID riid,
  392.                PPVOID ppv)
  393. {
  394.   LOGF1("L<%X>: COCruiseCar::CImpICar::QueryInterface. Delegating.",TID);
  395.  
  396.   // Delegate this call to the outer object's QueryInterface.
  397.   return m_pUnkOuter->QueryInterface(riid, ppv);
  398. }
  399.  
  400.  
  401. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  402.   Method:   COCruiseCar::CImpICar::AddRef
  403.  
  404.   Summary:  The AddRef IUnknown member of this ICar interface
  405.             implementation that delegates to m_pUnkOuter, whatever it is.
  406.  
  407.   Args:     void
  408.  
  409.   Modifies: m_cRefI.
  410.  
  411.   Returns:  ULONG
  412.               Returned by the delegated outer AddRef call.
  413. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  414. STDMETHODIMP_(ULONG) COCruiseCar::CImpICar::AddRef(void)
  415. {
  416.   // Increment the Interface Reference Count.
  417.   ++m_cRefI;
  418.  
  419.   LOGF2("L<%X>: COCruiseCar::CImpICar::Addref. Delegating. New cI=%i.",TID,m_cRefI);
  420.  
  421.   // Delegate this call to the outer object's AddRef.
  422.   return m_pUnkOuter->AddRef();
  423. }
  424.  
  425.  
  426. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  427.   Method:   COCruiseCar::CImpICar::Release
  428.  
  429.   Summary:  The Release IUnknown member of this ICar interface
  430.             implementation that delegates to m_pUnkOuter, whatever it is.
  431.  
  432.   Args:     void
  433.  
  434.   Modifies: m_cRefI.
  435.  
  436.   Returns:  ULONG
  437.               Returned by the delegated outer Release call.
  438. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  439. STDMETHODIMP_(ULONG) COCruiseCar::CImpICar::Release(void)
  440. {
  441.   // Decrement the Interface Reference Count.
  442.   --m_cRefI;
  443.  
  444.   LOGF2("L<%X>: COCruiseCar::CImpICar::Release. Delegating. New cI=%i.",TID,m_cRefI);
  445.  
  446.   // Delegate this call to the outer object's Release.
  447.   return m_pUnkOuter->Release();
  448. }
  449.  
  450.  
  451. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  452.   Method:   COCruiseCar::CImpICar::Shift
  453.  
  454.   Summary:  The Shift member method of this ICar interface implementation.
  455.             A simple empty method on a COCruiseCar COM object for tutorial
  456.             purposes.  Presumably if this Car object were modeling
  457.             a real Car then the Shift method would shift to the specified
  458.             gear.
  459.  
  460.   Args:     short nGear
  461.               0 - Neutral; 1 - 5 First 5 forward gears; 6 - Reverse.
  462.  
  463.   Modifies: .
  464.  
  465.   Returns:  HRESULT
  466.               NOERROR
  467. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  468. STDMETHODIMP COCruiseCar::CImpICar::Shift(
  469.                short nGear)
  470. {
  471.   LOGF2("L<%X>: COCruiseCar::CImpICar::Shift. Delegating. nGear=%i.",TID,nGear);
  472.  
  473.   // Delegate to the contained object implementation of ICar.
  474.   m_pBackObj->m_pICar->Shift(nGear);
  475.  
  476.   return NOERROR;
  477. }
  478.  
  479.  
  480. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  481.   Method:   COCruiseCar::CImpICar::Clutch
  482.  
  483.   Summary:  The Clutch member method of this ICar interface implementation.
  484.             A simple empty method on a COCruiseCar COM object for tutorial
  485.             purposes.  Presumably if this Car object were modeling
  486.             a real Car then the Clutch method would engage the clutch the
  487.             specified amount.
  488.  
  489.   Args:     short nEngaged)
  490.               Percent clutch is engaged (0 to 100%).
  491.  
  492.   Modifies: .
  493.  
  494.   Returns:  HRESULT
  495.               NOERROR
  496. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  497. STDMETHODIMP COCruiseCar::CImpICar::Clutch(
  498.                short nEngaged)
  499. {
  500.   LOGF2("L<%X>: COCruiseCar::CImpICar::Clutch. Delegating. nEngaged=%i.",TID,nEngaged);
  501.  
  502.   // Delegate to the contained object implementation of ICar.
  503.   m_pBackObj->m_pICar->Clutch(nEngaged);
  504.  
  505.   return NOERROR;
  506. }
  507.  
  508.  
  509. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  510.   Method:   COCruiseCar::CImpICar::Speed
  511.  
  512.   Summary:  The Propel member method of this ICar interface implementation.
  513.             A simple empty method on a COCruiseCar COM object for tutorial
  514.             purposes.  Presumably if this Car object were modeling
  515.             a real Car then this method would accelerate/brake to bring
  516.             the car to the specified speed.
  517.  
  518.   Args:     short nMph
  519.               New speed in miles per hour.
  520.  
  521.   Modifies: .
  522.  
  523.   Returns:  HRESULT
  524.               NOERROR
  525. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  526. STDMETHODIMP COCruiseCar::CImpICar::Speed(
  527.                short nMph)
  528. {
  529.   LOGF2("L<%X>: COCruiseCar::CImpICar::Speed. Delegating. nMph=%i.",TID,nMph);
  530.  
  531.   // Delegate to the contained object implementation of ICar.
  532.   m_pBackObj->m_pICar->Speed(nMph);
  533.  
  534.   return NOERROR;
  535. }
  536.  
  537.  
  538. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  539.   Method:   COCruiseCar::CImpICar::Steer
  540.  
  541.   Summary:  The Steer member method of this ICar interface implementation.
  542.             A simple empty method on a COCruiseCar COM object for tutorial
  543.             purposes.  Presumably if this Car object were modeling
  544.             a real Car then the Steer method would set the steering
  545.             angle of the Car.
  546.  
  547.   Args:     short nAngle)
  548.               0 degrees straight ahead, -45 Full left, +45 Full right.
  549.  
  550.   Modifies: .
  551.  
  552.   Returns:  HRESULT
  553.               NOERROR
  554. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  555. STDMETHODIMP COCruiseCar::CImpICar::Steer(
  556.                short nAngle)
  557. {
  558.   LOGF2("L<%X>: COCruiseCar::CImpICar::Steer. Delegating. nAngle=%i.",TID,nAngle);
  559.  
  560.   // Delegate to the contained object implementation of ICar.
  561.   m_pBackObj->m_pICar->Steer(nAngle);
  562.  
  563.   return NOERROR;
  564. }
  565.  
  566.  
  567. /*---------------------------------------------------------------------------
  568.   COCruiseCar's nested implementation of the ICruise interface including
  569.   Constructor, Destructor, QueryInterface, AddRef, Release,
  570.   Engage, and Adjust.
  571. ---------------------------------------------------------------------------*/
  572.  
  573. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  574.   Method:   COCruiseCar::CImpICruise::CImpICruise
  575.  
  576.   Summary:  Constructor for the CImpICruise interface instantiation.
  577.  
  578.   Args:     COCruiseCar* pBackObj,
  579.               Back pointer to the parent outer object.
  580.             IUnknown* pUnkOuter)
  581.               Pointer to the outer Unknown.  For delegation.
  582.  
  583.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  584.  
  585.   Returns:  void
  586. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  587. COCruiseCar::CImpICruise::CImpICruise(
  588.   COCruiseCar* pBackObj,
  589.   IUnknown* pUnkOuter)
  590. {
  591.   // Init the Interface Ref Count (used for debugging only).
  592.   m_cRefI = 0;
  593.  
  594.   // Init the Back Object Pointer to point to the outer object.
  595.   m_pBackObj = pBackObj;
  596.  
  597.   // Init the CImpICruise interface's delegating Unknown pointer.  We use
  598.   // the Back Object pointer for IUnknown delegation here if we are not
  599.   // being aggregated.  If we are being aggregated we use the supplied
  600.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  601.   // assignment requires no AddRef because the CImpICruise lifetime is
  602.   // quaranteed by the lifetime of the parent object in which
  603.   // CImpICruise is nested.
  604.   if (NULL == pUnkOuter)
  605.   {
  606.     m_pUnkOuter = pBackObj;
  607.     LOGF1("L<%X>: COCruiseCar::CImpICruise Constructor. Non-Aggregating.",TID);
  608.   }
  609.   else
  610.   {
  611.     m_pUnkOuter = pUnkOuter;
  612.     LOGF1("L<%X>: COCruiseCar::CImpICruise Constructor. Aggregating.",TID);
  613.   }
  614.  
  615.   return;
  616. }
  617.  
  618.  
  619. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  620.   Method:   COCruiseCar::CImpICruise::~CImpICruise
  621.  
  622.   Summary:  Destructor for the CImpICruise interface instantiation.
  623.  
  624.   Args:     void
  625.  
  626.   Modifies: .
  627.  
  628.   Returns:  void
  629. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  630. COCruiseCar::CImpICruise::~CImpICruise(void)
  631. {
  632.   LOGF1("L<%X>: COCruiseCar::CImpICruise Destructor.",TID);
  633.  
  634.   return;
  635. }
  636.  
  637.  
  638. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  639.   Method:   COCruiseCar::CImpICruise::QueryInterface
  640.  
  641.   Summary:  The QueryInterface IUnknown member of this ICruise interface
  642.             implementation that delegates to m_pUnkOuter, whatever it is.
  643.  
  644.   Args:     REFIID riid,
  645.               [in] GUID of the Interface being requested.
  646.             PPVOID ppv)
  647.               [out] Address of the caller's pointer variable that will
  648.               receive the requested interface pointer.
  649.  
  650.   Modifies: .
  651.  
  652.   Returns:  HRESULT
  653.               Returned by the delegated outer QueryInterface call.
  654. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  655. STDMETHODIMP COCruiseCar::CImpICruise::QueryInterface(
  656.                REFIID riid,
  657.                PPVOID ppv)
  658. {
  659.   LOGF1("L<%X>: COCruiseCar::CImpICruise::QueryInterface. Delegating.",TID);
  660.  
  661.   // Delegate this call to the outer object's QueryInterface.
  662.   return m_pUnkOuter->QueryInterface(riid, ppv);
  663. }
  664.  
  665.  
  666. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  667.   Method:   COCruiseCar::CImpICruise::AddRef
  668.  
  669.   Summary:  The AddRef IUnknown member of this ICruise interface
  670.             implementation that delegates to m_pUnkOuter, whatever it is.
  671.  
  672.   Args:     void
  673.  
  674.   Modifies: m_cRefI.
  675.  
  676.   Returns:  ULONG
  677.               Returned by the delegated outer AddRef call.
  678. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  679. STDMETHODIMP_(ULONG) COCruiseCar::CImpICruise::AddRef(void)
  680. {
  681.   // Increment the Interface Reference Count.
  682.   ++m_cRefI;
  683.  
  684.   LOGF2("L<%X>: COCruiseCar::CImpICruise::Addref. Delegating. New cI=%i.",TID,m_cRefI);
  685.  
  686.   // Delegate this call to the outer object's AddRef.
  687.   return m_pUnkOuter->AddRef();
  688. }
  689.  
  690.  
  691. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  692.   Method:   COCruiseCar::CImpICruise::Release
  693.  
  694.   Summary:  The Release IUnknown member of this ICruise interface
  695.             implementation that delegates to m_pUnkOuter, whatever it is.
  696.  
  697.   Args:     void
  698.  
  699.   Modifies: m_cRefI.
  700.  
  701.   Returns:  ULONG
  702.               Returned by the delegated outer Release call.
  703. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  704. STDMETHODIMP_(ULONG) COCruiseCar::CImpICruise::Release(void)
  705. {
  706.   // Decrement the Interface Reference Count.
  707.   --m_cRefI;
  708.  
  709.   LOGF2("L<%X>: COCruiseCar::CImpICruise::Release. Delegating. New cI=%i.",TID,m_cRefI);
  710.  
  711.   // Delegate this call to the outer object's Release.
  712.   return m_pUnkOuter->Release();
  713. }
  714.  
  715.  
  716. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  717.   Method:   COCruiseCar::CImpICruise::Engage
  718.  
  719.   Summary:  The Engage member method of this ICruise interface
  720.             implementation.  A simple empty method on a COCruiseCar COM
  721.             object for tutorial purposes.  Presumably if this Car object
  722.             were modeling a real Car then the Engage method would turn
  723.             the Cruise control system on or off.
  724.  
  725.   Args:     BOOL bOnOff)
  726.               TRUE for On; FALSE for Off.
  727.  
  728.   Modifies: .
  729.  
  730.   Returns:  HRESULT
  731.               NOERROR
  732. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  733. STDMETHODIMP COCruiseCar::CImpICruise::Engage(
  734.                BOOL bOnOff)
  735. {
  736.   LOGF2("L<%X>: COCruiseCar::CImpICruise::Engage. Called. bOnOff=%i.",TID,bOnOff);
  737.  
  738.   return NOERROR;
  739. }
  740.  
  741.  
  742. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  743.   Method:   COCruiseCar::CImpICruise::Adjust
  744.  
  745.   Summary:  The Adjust member method of this ICruise interface
  746.             implementation.  A simple empty method on a COCruiseCar COM
  747.             object for tutorial purposes.  Presumably if this Car object
  748.             were modeling a real Car then the Adjust method would allow
  749.             notching the cruise set speed up or down by increments of 3 mph.
  750.  
  751.   Args:     BOOL bUpDown)
  752.               TRUE for Up; FALSE for Down.
  753.  
  754.   Modifies: .
  755.  
  756.   Returns:  HRESULT
  757.               NOERROR
  758. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  759. STDMETHODIMP COCruiseCar::CImpICruise::Adjust(
  760.                BOOL bUpDown)
  761. {
  762.   LOGF2("L<%X>: COCruiseCar::CImpICruise::Adjust. Called. bUpDown=%i.",TID,bUpDown);
  763.  
  764.   return NOERROR;
  765. }
  766.