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

Windows编程

开发平台:

Visual C++

  1. /*+==========================================================================
  2.   File:      UTCRUCAR.CPP
  3.   Summary:   Implementation file for the aggregatable COUtilityCruiseCar
  4.              COM object class.
  5.              UTCRUCAR showcases the construction of the COUtilityCruiseCar
  6.              COM object class with the IUnknown, ICar, ICruise, and
  7.              IUtility interfaces.  This is done through Containment reuse
  8.              of COCruiseCar's ICar and ICruise interface features.
  9.              For a comprehensive tutorial code tour of this module's
  10.              contents and offerings see the tutorial APTCLIEN.HTM
  11.              file.  For more specific technical details on the internal
  12.              workings see the comments dispersed throughout the
  13.              module's source code.
  14.   Classes:   COUtilityCruiseCar.
  15.   Functions: CreateUtilityCruiseCar.
  16.   Origin:    3-20-96: atrent - Editor inheritance from LOCCLIEN source.
  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 make calls to 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 APTCLIEN.H because it has class and resource definitions
  37.     specific to this LOCCLIEN application.
  38.   We include UTCRUCAR.H because it has the COUtilityCruiseCar declarations.
  39. ---------------------------------------------------------------------------*/
  40. #include <windows.h>
  41. #include <ole2.h>
  42. #include <apputil.h>
  43. #include <micars.h>
  44. #include <carguids.h>
  45. #include "aptclien.h"
  46. #include "utcrucar.h"
  47. /*---------------------------------------------------------------------------
  48.   COUtilityCruiseCar's implementation of its main COM object class including
  49.   Constructor, Destructor, QueryInterface, AddRef, and Release.
  50. ---------------------------------------------------------------------------*/
  51. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  52.   Method:   COUtilityCruiseCar::COUtilityCruiseCar
  53.   Summary:  COUtilityCruiseCar Constructor. Note the member initializer:
  54.             "m_ImpIUtility(this, pUnkOuter)" which is used to pass the
  55.             'this' and pUnkOuter pointers of this constructor function to
  56.             the constructor in the instantiation of the implementation of
  57.             the CImpIUtility interface (which is nested inside this
  58.             present COUtilityCruiseCar Object Class).
  59.   Args:     IUnknown* pUnkOuter)
  60.               Pointer to the the outer Unknown.  NULL means this COM Object
  61.               is not being Aggregated.  Non NULL means it is being created
  62.               on behalf of an outside COM object that is reusing it via
  63.               aggregation.
  64.   Modifies: m_cRefs, m_pUnkOuter, m_pUnkCruiseCar.
  65.   Returns:  void
  66. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  67. COUtilityCruiseCar::COUtilityCruiseCar(
  68.   IUnknown* pUnkOuter) :
  69.   m_ImpICar(this, pUnkOuter),
  70.   m_ImpICruise(this, pUnkOuter),
  71.   m_ImpIUtility(this, pUnkOuter)
  72. {
  73.   // Zero the COM object's reference count.
  74.   m_cRefs = 0;
  75.   // No AddRef necessary if non-NULL, as this COM object's lifetime
  76.   // is totally coupled with the controlling Outer object's lifetime.
  77.   m_pUnkOuter = pUnkOuter;
  78.   // Zero the pointer to the contained COCruiseCar object's ICar interface.
  79.   m_pICar = NULL;
  80.   // Zero the pointer to the contained COCruiseCar object's ICruise
  81.   // interface.
  82.   m_pICruise = NULL;
  83.   LOGF1("C: COUtilityCruiseCar Constructor. m_pUnkOuter=0x%X.", m_pUnkOuter);
  84.   return;
  85. }
  86. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  87.   Method:   COUtilityCruiseCar::~COUtilityCruiseCar
  88.   Summary:  COUtilityCruiseCar Destructor.
  89.   Args:     void
  90.   Modifies: .
  91.   Returns:  void
  92. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  93. COUtilityCruiseCar::~COUtilityCruiseCar(void)
  94. {
  95.   LOG("C: COUtilityCruiseCar::Destructor.");
  96.   // Release the contained CruiseCar interfaces.
  97.   m_pICruise->Release();
  98.   m_pICar->Release();
  99.   return;
  100. }
  101. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  102.   Method:   COUtilityCruiseCar::Init
  103.   Summary:  COUtilityCruiseCar Initialization method.
  104.   Args:     void
  105.   Modifies: m_pICar, m_pICruise, m_cRefs.
  106.   Returns:  HRESULT
  107.               Standard result code. NOERROR for success.
  108. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  109. HRESULT COUtilityCruiseCar::Init(void)
  110. {
  111.   HRESULT hr;
  112.   IClassFactory* pICFCruiseCar;
  113.   // Set up the right pIUnknown for delegation.  If we are being
  114.   // aggregated then we pass the pUnkOuter in turn to any COM objects
  115.   // that we are aggregating.  m_pUnkOuter was set in the Constructor.
  116.   IUnknown* pUnkOuter = (NULL == m_pUnkOuter) ? this : m_pUnkOuter;
  117.   LOGF1("C: COUtilityCruiseCar::Init. pUnkOuter=0x%X",pUnkOuter);
  118.   // Get a class factory for AptCruiseCar and issue IClassFactory's
  119.   // CreateInstance method to manufacture a COCruiseCar COM object.
  120.   LOG("C: COUtilityCruiseCar::Init. Obtain CruiseCar Class Factory.");
  121.   hr = CoGetClassObject(
  122.          CLSID_AptCruiseCar,
  123.          CLSCTX_LOCAL_SERVER,
  124.          NULL,
  125.          IID_IClassFactory,
  126.          (PPVOID)&pICFCruiseCar);
  127.   if (SUCCEEDED(hr))
  128.   {
  129.     LOG("C: COUtilityCruiseCar::Init. CruiseCar Class Factory obtained.");
  130.     LOG("C: COUtilityCruiseCar::Init. Calling CFCruiseCar::CreateInstance.");
  131.     // A NULL pUnkOuter is passed indicating that we are creating a
  132.     // COCruiseCar component via the Containment reuse method.  We can
  133.     // currently pass nothing other than this NULL pUnkOuter because
  134.     // aggregation is not supported across process or machine boundaries.
  135.     // Since we are not requesting a COCruiseCar create for aggregation we
  136.     // can directly request for the ICruise interface on the new object.
  137.     hr = pICFCruiseCar->CreateInstance(
  138.                           NULL,
  139.                           IID_ICruise,
  140.                           (PPVOID)&m_pICruise);
  141.     LOG("C: COUtilityCruiseCar::Init. Releasing CruiseCar Class Factory.");
  142.     pICFCruiseCar->Release();
  143.     if (SUCCEEDED(hr))
  144.     {
  145.       // Now that we have a valid interface pointer (m_pICruise) on the
  146.       // new object we can obtain and cache a pointer to that contained
  147.       // object's ICar interface as well.  We must QI using the obtained
  148.       // ICruise pointer on the object to ensure that the marshaling proxy
  149.       // is involved in the QueryInterface call to provide the pointer to
  150.       // the ICar interface proxy.
  151.       hr = m_pICruise->QueryInterface(IID_ICar, (PPVOID)&m_pICar);
  152.     }
  153.   }
  154.   if (SUCCEEDED(hr))
  155.   {
  156.     LOG("C: COUtilityCruiseCar::Init (CruiseCar Containment) Succeeded.");
  157.   }
  158.   else
  159.   {
  160.     LOGF1("C: COUtilityCruiseCar::Init (CruiseCar Containment) Failed. hr=0x%X",hr);
  161.   }
  162.   return (hr);
  163. }
  164. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  165.   Method:   COUtilityCruiseCar::QueryInterface
  166.   Summary:  QueryInterface of the COUtilityCruiseCar non-delegating
  167.             IUnknown implementation.
  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.   Modifies: *ppv.
  174.   Returns:  HRESULT
  175. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  176. STDMETHODIMP COUtilityCruiseCar::QueryInterface(
  177.                REFIID riid,
  178.                PPVOID ppv)
  179. {
  180.   HRESULT hr = E_NOINTERFACE;
  181.   *ppv = NULL;
  182.   if (IID_IUnknown == riid)
  183.   {
  184.     *ppv = this;
  185.     LOG("C: COUtilityCruiseCar::QueryInterface. 'this' pIUnknown returned.");
  186.   }
  187.   else if (IID_ICar == riid)
  188.   {
  189.     *ppv = &m_ImpICar;
  190.     LOG("C: COUtilityCruiseCar::QueryInterface. pICar returned");
  191.   }
  192.   else if (IID_ICruise == riid)
  193.   {
  194.     *ppv = &m_ImpICruise;
  195.     LOG("C: COUtilityCruiseCar::QueryInterface. pICruise returned");
  196.   }
  197.   else if (IID_IUtility == riid)
  198.   {
  199.     // This IUtility interface is implemented in this COUtilityCruiseCar
  200.     // object as a native interface of COUtilityCruiseCar.
  201.     *ppv = &m_ImpIUtility;
  202.     LOG("C: COUtilityCruiseCar::QueryInterface. pIUtility returned.");
  203.   }
  204.   if (NULL != *ppv)
  205.   {
  206.     // We've handed out a pointer to an interface so obey the COM rules
  207.     // and AddRef its reference count.
  208.     ((LPUNKNOWN)*ppv)->AddRef();
  209.     hr = NOERROR;
  210.   }
  211.   return (hr);
  212. }
  213. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  214.   Method:   COUtilityCruiseCar::AddRef
  215.   Summary:  AddRef of the COUtilityCruiseCar non-delegating
  216.             IUnknown implementation.
  217.   Args:     void
  218.   Modifies: m_cRefs.
  219.   Returns:  ULONG
  220.               New value of m_cRefs (COM object's reference count).
  221. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  222. STDMETHODIMP_(ULONG) COUtilityCruiseCar::AddRef(void)
  223. {
  224.   m_cRefs++;
  225.   LOGF1("C: COUtilityCruiseCar::AddRef. New cRefs=%i.", m_cRefs);
  226.   return m_cRefs;
  227. }
  228. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  229.   Method:   COUtilityCruiseCar::Release
  230.   Summary:  Release of the COUtilityCruiseCar non-delegating IUnknown
  231.             implementation.
  232.   Args:     void
  233.   Modifies: m_cRefs.
  234.   Returns:  ULONG
  235.               New value of m_cRefs (COM object's reference count).
  236. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  237. STDMETHODIMP_(ULONG) COUtilityCruiseCar::Release(void)
  238. {
  239.   ULONG ulCount = --m_cRefs;
  240.   LOGF1("C: COUtilityCruiseCar::Release. New cRefs=%i.", m_cRefs);
  241.   if (0 == m_cRefs)
  242.   {
  243.     // We artificially bump the main ref count.  This fulfills one of
  244.     // the rules of aggregated objects and ensures that an indirect
  245.     // recursive call to this release won't occur because of other
  246.     // delegating releases that might happen in our own destructor.
  247.     m_cRefs++;
  248.     delete this;
  249.   }
  250.   return ulCount;
  251. }
  252. /*---------------------------------------------------------------------------
  253.   COUtilityCruiseCar's nested implementation of the ICar interface
  254.   including Constructor, Destructor, QueryInterface, AddRef, Release,
  255.   Shift, Clutch, Speed, and Steer.
  256. ---------------------------------------------------------------------------*/
  257. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  258.   Method:   COUtilityCruiseCar::CImpICar::CImpICar
  259.   Summary:  Constructor for the CImpICar interface instantiation.
  260.   Args:     COUtilityCruiseCar* pBackObj,
  261.               Back pointer to the parent outer object.
  262.             IUnknown* pUnkOuter,
  263.               Pointer to the outer Unknown.  For delegation.
  264.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  265.   Returns:  void
  266. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  267. COUtilityCruiseCar::CImpICar::CImpICar(
  268.   COUtilityCruiseCar* pBackObj,
  269.   IUnknown* pUnkOuter)
  270. {
  271.   // Init the Interface Ref Count (used for debugging only).
  272.   m_cRefI = 0;
  273.   // Init the Back Object Pointer to point to the outer object.
  274.   m_pBackObj = pBackObj;
  275.   // Init the CImpICar interface's delegating Unknown pointer.  We use
  276.   // the Back Object pointer for IUnknown delegation here if we are not
  277.   // being aggregated.  If we are being aggregated we use the supplied
  278.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  279.   // assignment requires no AddRef because the CImpICar lifetime is
  280.   // quaranteed by the lifetime of the parent object in which
  281.   // CImpICar is nested.
  282.   if (NULL == pUnkOuter)
  283.   {
  284.     m_pUnkOuter = pBackObj;
  285.     LOG("C: COUtilityCruiseCar::CImpICar Constructor. Non-Aggregating");
  286.   }
  287.   else
  288.   {
  289.     m_pUnkOuter = pUnkOuter;
  290.     LOG("C: COUtilityCruiseCar::CImpICar Constructor. Aggregating");
  291.   }
  292.   return;
  293. }
  294. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  295.   Method:   COUtilityCruiseCar::CImpICar::~CImpICar
  296.   Summary:  Destructor for the CImpICar interface instantiation.
  297.   Args:     void
  298.   Modifies: .
  299.   Returns:  void
  300. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  301. COUtilityCruiseCar::CImpICar::~CImpICar(void)
  302. {
  303.   LOG("C: COUtilityCruiseCar::CImpICar Destructor.");
  304.   return;
  305. }
  306. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  307.   Method:   COUtilityCruiseCar::CImpICar::QueryInterface
  308.   Summary:  The QueryInterface IUnknown member of this ICar interface
  309.             implementation that delegates to m_pUnkOuter, whatever it is.
  310.   Args:     REFIID riid,
  311.               [in] GUID of the Interface being requested.
  312.             PPVOID ppv)
  313.               [out] Address of the caller's pointer variable that will
  314.               receive the requested interface pointer.
  315.   Modifies: *ppv.
  316.   Returns:  HRESULT
  317.               Returned by the delegated outer QueryInterface call.
  318. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  319. STDMETHODIMP COUtilityCruiseCar::CImpICar::QueryInterface(
  320.                REFIID riid,
  321.                PPVOID ppv)
  322. {
  323.   LOG("C: COUtilityCruiseCar::CImpICar::QueryInterface. Delegating.");
  324.   // Delegate this call to the outer object's QueryInterface.
  325.   return m_pUnkOuter->QueryInterface(riid, ppv);
  326. }
  327. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  328.   Method:   COUtilityCruiseCar::CImpICar::AddRef
  329.   Summary:  The AddRef IUnknown member of this ICar interface
  330.             implementation that delegates to m_pUnkOuter, whatever it is.
  331.   Args:     void
  332.   Modifies: m_cRefI.
  333.   Returns:  ULONG
  334.               Returned by the delegated outer AddRef call.
  335. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  336. STDMETHODIMP_(ULONG) COUtilityCruiseCar::CImpICar::AddRef(void)
  337. {
  338.   // Increment the Interface Reference Count.
  339.   ++m_cRefI;
  340.   LOGF1("C: COUtilityCruiseCar::CImpICar::Addref. Delegating. New cI=%i.", m_cRefI);
  341.   // Delegate this call to the outer object's AddRef.
  342.   return m_pUnkOuter->AddRef();
  343. }
  344. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  345.   Method:   COUtilityCruiseCar::CImpICar::Release
  346.   Summary:  The Release IUnknown member of this ICar interface
  347.             implementation that delegates to m_pUnkOuter, whatever it is.
  348.   Args:     void
  349.   Modifies: m_cRefI.
  350.   Returns:  ULONG
  351.               Returned by the delegated outer Release call.
  352. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  353. STDMETHODIMP_(ULONG) COUtilityCruiseCar::CImpICar::Release(void)
  354. {
  355.   // Decrement the Interface Reference Count.
  356.   --m_cRefI;
  357.   LOGF1("C: COUtilityCruiseCar::CImpICar::Release. Delegating. New cI=%i.", m_cRefI);
  358.   // Delegate this call to the outer object's Release.
  359.   return m_pUnkOuter->Release();
  360. }
  361. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  362.   Method:   COUtilityCruiseCar::CImpICar::Shift
  363.   Summary:  The Shift member method of this ICar interface implementation.
  364.             A simple empty method on a COUtilityCruiseCar COM object for
  365.             tutorial purposes.  Presumably if this Car object were
  366.             modeling a real Car then the Shift method would shift to the
  367.             specified gear.
  368.   Args:     short nGear
  369.               0 - Neutral; 1 - 5 First 5 forward gears; 6 - Reverse.
  370.   Modifies: .
  371.   Returns:  HRESULT
  372.               Delegated HRESULT.
  373. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  374. STDMETHODIMP COUtilityCruiseCar::CImpICar::Shift(
  375.                short nGear)
  376. {
  377.   LOGF1("C: COUtilityCruiseCar::CImpICar::Shift. Delegating. nGear=%i.",nGear);
  378.   // Delegate this call to the contained COCruiseCar's ICar::Shift.
  379.   return m_pBackObj->m_pICar->Shift(nGear);
  380. }
  381. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  382.   Method:   COUtilityCruiseCar::CImpICar::Clutch
  383.   Summary:  The Clutch member method of this ICar interface
  384.             implementation. A simple empty method on a COUtilityCruiseCar
  385.             COM object for tutorial purposes.  Presumably if this Car
  386.             object were modeling a real Car then the Clutch method would
  387.             engage the clutch the specified amount.
  388.   Args:     short nEngaged)
  389.               Percent clutch is engaged (0 to 100%).
  390.   Modifies: .
  391.   Returns:  HRESULT
  392.               Delegated HRESULT.
  393. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  394. STDMETHODIMP COUtilityCruiseCar::CImpICar::Clutch(
  395.                short nEngaged)
  396. {
  397.   LOGF1("C: COUtilityCruiseCar::CImpICar::Clutch. Delegating. nEngaged=%i.", nEngaged);
  398.   // Delegate this call to the contained COCruiseCar's ICar::Clutch.
  399.   return m_pBackObj->m_pICar->Clutch(nEngaged);
  400. }
  401. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  402.   Method:   COUtilityCruiseCar::CImpICar::Speed
  403.   Summary:  The Propel member method of this ICar interface
  404.             implementation. A simple empty method on a COUtilityCruiseCar
  405.             COM object for tutorial purposes.  Presumably if this Car
  406.             object were modeling a real Car then this method would
  407.             accelerate/brake to bring the car to the specified speed.
  408.   Args:     short nMph
  409.               New speed in miles per hour.
  410.   Modifies: .
  411.   Returns:  HRESULT
  412.               Delegated HRESULT.
  413. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  414. STDMETHODIMP COUtilityCruiseCar::CImpICar::Speed(
  415.                short nMph)
  416. {
  417.   LOGF1("C: COUtilityCruiseCar::CImpICar::Speed. Delegating. nMph=%i.",nMph);
  418.   // Delegate this call to the contained COCruiseCar's ICar::Speed.
  419.   return m_pBackObj->m_pICar->Speed(nMph);
  420. }
  421. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  422.   Method:   COUtilityCruiseCar::CImpICar::Steer
  423.   Summary:  The Steer member method of this ICar interface implementation.
  424.             A simple empty method on a COUtilityCruiseCar COM object for
  425.             tutorial purposes.  Presumably if this Car object were
  426.             modeling a real Car then the Steer method would set the
  427.             steering angle of the Car.
  428.   Args:     short nAngle)
  429.               0 degrees straight ahead, -45 Full left, +45 Full right.
  430.   Modifies: .
  431.   Returns:  HRESULT
  432.               Delegated HRESULT.
  433. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  434. STDMETHODIMP COUtilityCruiseCar::CImpICar::Steer(
  435.                short nAngle)
  436. {
  437.   LOGF1("C: COUtilityCruiseCar::CImpICar::Steer. Delegating. nAngle=%i.",nAngle);
  438.   // Delegate this call to the contained COCruiseCar's ICar::Steer.
  439.   return m_pBackObj->m_pICar->Steer(nAngle);
  440. }
  441. /*---------------------------------------------------------------------------
  442.   COUtilityCruiseCar's nested implementation of the ICruise interface
  443.   including Constructor, Destructor, QueryInterface, AddRef, Release,
  444.   Engage, and Adjust.
  445. ---------------------------------------------------------------------------*/
  446. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  447.   Method:   COUtilityCruiseCar::CImpICruise::CImpICruise
  448.   Summary:  Constructor for the CImpICruise interface instantiation.
  449.   Args:     COUtilityCruiseCar* pBackObj,
  450.               Back pointer to the parent outer object.
  451.             IUnknown* pUnkOuter,
  452.               Pointer to the outer Unknown.  For delegation.
  453.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  454.   Returns:  void
  455. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  456. COUtilityCruiseCar::CImpICruise::CImpICruise(
  457.   COUtilityCruiseCar* pBackObj,
  458.   IUnknown* pUnkOuter)
  459. {
  460.   // Init the Interface Ref Count (used for debugging only).
  461.   m_cRefI = 0;
  462.   // Init the Back Object Pointer to point to the outer object.
  463.   m_pBackObj = pBackObj;
  464.   // Init the CImpICruise interface's delegating Unknown pointer.  We use
  465.   // the Back Object pointer for IUnknown delegation here if we are not
  466.   // being aggregated.  If we are being aggregated we use the supplied
  467.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  468.   // assignment requires no AddRef because the CImpICruise lifetime is
  469.   // quaranteed by the lifetime of the parent object in which
  470.   // CImpICruise is nested.
  471.   if (NULL == pUnkOuter)
  472.   {
  473.     m_pUnkOuter = pBackObj;
  474.     LOG("C: COUtilityCruiseCar::CImpICruise Constructor. Non-Aggregating");
  475.   }
  476.   else
  477.   {
  478.     m_pUnkOuter = pUnkOuter;
  479.     LOG("C: COUtilityCruiseCar::CImpICruise Constructor. Aggregating");
  480.   }
  481.   return;
  482. }
  483. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  484.   Method:   COUtilityCruiseCar::CImpICruise::~CImpICruise
  485.   Summary:  Destructor for the CImpICruise interface instantiation.
  486.   Args:     void
  487.   Modifies: .
  488.   Returns:  void
  489. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  490. COUtilityCruiseCar::CImpICruise::~CImpICruise(void)
  491. {
  492.   LOG("C: COUtilityCruiseCar::CImpICruise Destructor.");
  493.   return;
  494. }
  495. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  496.   Method:   COUtilityCruiseCar::CImpICruise::QueryInterface
  497.   Summary:  The QueryInterface IUnknown member of this ICruise interface
  498.             implementation that delegates to m_pUnkOuter, whatever it is.
  499.   Args:     REFIID riid,
  500.               [in] GUID of the Interface being requested.
  501.             PPVOID ppv)
  502.               [out] Address of the caller's pointer variable that will
  503.               receive the requested interface pointer.
  504.   Modifies: *ppv.
  505.   Returns:  HRESULT
  506.               Returned by the delegated outer QueryInterface call.
  507. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  508. STDMETHODIMP COUtilityCruiseCar::CImpICruise::QueryInterface(
  509.                REFIID riid,
  510.                PPVOID ppv)
  511. {
  512.   LOG("C: COUtilityCruiseCar::CImpICruise::QueryInterface. Delegating.");
  513.   // Delegate this call to the outer object's QueryInterface.
  514.   return m_pUnkOuter->QueryInterface(riid, ppv);
  515. }
  516. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  517.   Method:   COUtilityCruiseCar::CImpICruise::AddRef
  518.   Summary:  The AddRef IUnknown member of this ICruise interface
  519.             implementation that delegates to m_pUnkOuter, whatever it is.
  520.   Args:     void
  521.   Modifies: m_cRefI.
  522.   Returns:  ULONG
  523.               Returned by the delegated outer AddRef call.
  524. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  525. STDMETHODIMP_(ULONG) COUtilityCruiseCar::CImpICruise::AddRef(void)
  526. {
  527.   // Increment the Interface Reference Count.
  528.   ++m_cRefI;
  529.   LOGF1("C: COUtilityCruiseCar::CImpICruise::Addref. Delegating. New cI=%i.", m_cRefI);
  530.   // Delegate this call to the outer object's AddRef.
  531.   return m_pUnkOuter->AddRef();
  532. }
  533. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  534.   Method:   COUtilityCruiseCar::CImpICruise::Release
  535.   Summary:  The Release IUnknown member of this ICruise interface
  536.             implementation that delegates to m_pUnkOuter, whatever it is.
  537.   Args:     void
  538.   Modifies: m_cRefI.
  539.   Returns:  ULONG
  540.               Returned by the delegated outer Release call.
  541. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  542. STDMETHODIMP_(ULONG) COUtilityCruiseCar::CImpICruise::Release(void)
  543. {
  544.   // Decrement the Interface Reference Count.
  545.   --m_cRefI;
  546.   LOGF1("C: COUtilityCruiseCar::CImpICruise::Release. Delegating. New cI=%i.", m_cRefI);
  547.   // Delegate this call to the outer object's Release.
  548.   return m_pUnkOuter->Release();
  549. }
  550. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  551.   Method:   COUtilityCruiseCar::CImpICruise::Engage
  552.   Summary:  The Engage member method of this ICruise interface
  553.             implementation.  A simple empty method on a COUtilityCruiseCar
  554.             COM object for tutorial purposes.  Presumably if this Car
  555.             object were modeling a real Car then the Engage method would
  556.             turn the Cruise control system on or off.
  557.   Args:     BOOL bOnOff)
  558.               TRUE for On; FALSE for Off.
  559.   Modifies: .
  560.   Returns:  HRESULT
  561.               Delegated HRESULT.
  562. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  563. STDMETHODIMP COUtilityCruiseCar::CImpICruise::Engage(
  564.                BOOL bOnOff)
  565. {
  566.   LOGF1("C: COUtilityCruiseCar::CImpICruise::Engage. Delegating. bOnOff=%i.",bOnOff);
  567.   // Delegate this call to the contained COCruiseCar's ICruise::Engage.
  568.   m_pBackObj->m_pICruise->Engage(bOnOff);
  569.   return NOERROR;
  570. }
  571. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  572.   Method:   COUtilityCruiseCar::CImpICruise::Adjust
  573.   Summary:  The Adjust member method of this ICruise interface
  574.             implementation.  A simple empty method on a COUtilityCruiseCar
  575.             COM object for tutorial purposes.  Presumably if this Car
  576.             object were modeling a real Car then the Adjust method would
  577.             allow notching the cruise set speed up or down by increments
  578.             of 3 mph.
  579.   Args:     BOOL bUpDown)
  580.               TRUE for Up; FALSE for Down.
  581.   Modifies: .
  582.   Returns:  HRESULT
  583.               Delegated HRESULT.
  584. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  585. STDMETHODIMP COUtilityCruiseCar::CImpICruise::Adjust(
  586.                BOOL bUpDown)
  587. {
  588.   LOGF1("C: COUtilityCruiseCar::CImpICruise::Adjust. Delegating. bUpDown=%i.",bUpDown);
  589.   // Delegate this call to the contained COCruiseCar's ICruise::Adjust.
  590.   m_pBackObj->m_pICruise->Adjust(bUpDown);
  591.   return NOERROR;
  592. }
  593. /*---------------------------------------------------------------------------
  594.   COUtilityCruiseCar's nested implementation of the IUtility interface
  595.   including methods: Constructor, Destructor, QueryInterface, AddRef,
  596.   Release, Offroad, and Winch.
  597. ---------------------------------------------------------------------------*/
  598. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  599.   Method:   COUtilityCruiseCar::CImpIUtility::CImpIUtility
  600.   Summary:  Constructor for the CImpIUtility interface instantiation.
  601.   Args:     COUtilityCruiseCar* pBackObj,
  602.               Back pointer to the parent outer object.
  603.             IUnknown* pUnkOuter)
  604.               Pointer to the outer Unknown.  For delegation.
  605.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  606.   Returns:  void
  607. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  608. COUtilityCruiseCar::CImpIUtility::CImpIUtility(
  609.   COUtilityCruiseCar* pBackObj,
  610.   IUnknown* pUnkOuter)
  611. {
  612.   // Init the Interface Ref Count (used for debugging only).
  613.   m_cRefI = 0;
  614.   // Init the Back Object Pointer to point to the outer object.
  615.   m_pBackObj = pBackObj;
  616.   // Init the CImpIUtility interface's delegating IUnknown pointer.  We use
  617.   // the Back Object pointer for IUnknown delegation here if we are not
  618.   // being aggregated.  If we are being aggregated we use the supplied
  619.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  620.   // assignment requires no AddRef because the CImpIUtility lifetime is
  621.   // quaranteed by the lifetime of the parent object in which
  622.   // CImpIUtility is nested.
  623.   if (NULL == pUnkOuter)
  624.   {
  625.     m_pUnkOuter = pBackObj;
  626.     LOG("C: COUtilityCruiseCar::CImpIUtility Constructor. Non-Aggregating.");
  627.   }
  628.   else
  629.   {
  630.     m_pUnkOuter = pUnkOuter;
  631.     LOG("C: COUtilityCruiseCar::CImpIUtility Constructor. Aggregating.");
  632.   }
  633.   return;
  634. }
  635. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  636.   Method:   COUtilityCruiseCar::CImpIUtility::~CImpIUtility
  637.   Summary:  Destructor for the CImpIUtility interface instantiation.
  638.   Args:     void
  639.   Modifies: .
  640.   Returns:  void
  641. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  642. COUtilityCruiseCar::CImpIUtility::~CImpIUtility(void)
  643. {
  644.   LOG("C: COUtilityCruiseCar::CImpIUtility Destructor.");
  645.   return;
  646. }
  647. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  648.   Method:   COUtilityCruiseCar::CImpIUtility::QueryInterface
  649.   Summary:  The QueryInterface IUnknown member of this IUtility interface
  650.             implementation that delegates to m_pUnkOuter, whatever it is.
  651.   Args:     REFIID riid,
  652.               [in] GUID of the Interface being requested.
  653.             PPVOID ppv)
  654.               [out] Address of the caller's pointer variable that will
  655.               receive the requested interface pointer.
  656.   Modifies: *ppv.
  657.   Returns:  HRESULT
  658.               Returned by the delegated outer QueryInterface call.
  659. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  660. STDMETHODIMP COUtilityCruiseCar::CImpIUtility::QueryInterface(
  661.                REFIID riid,
  662.                PPVOID ppv)
  663. {
  664.   LOG("C: COUtilityCruiseCar::CImpIUtility::QueryInterface. Delegating.");
  665.   // Delegate this call to the outer object's QueryInterface.
  666.   return m_pUnkOuter->QueryInterface(riid, ppv);
  667. }
  668. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  669.   Method:   COUtilityCruiseCar::CImpIUtility::AddRef
  670.   Summary:  The AddRef IUnknown member of this IUtility interface
  671.             implementation that delegates to m_pUnkOuter, whatever it is.
  672.   Args:     void
  673.   Modifies: m_cRefI.
  674.   Returns:  ULONG
  675.               Returned by the delegated outer AddRef call.
  676. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  677. STDMETHODIMP_(ULONG) COUtilityCruiseCar::CImpIUtility::AddRef(void)
  678. {
  679.   // Increment the Interface Reference Count.
  680.   ++m_cRefI;
  681.   LOGF1("C: COUtilityCruiseCar::CImpIUtility::Addref. Delegating. New cI=%i.", m_cRefI);
  682.   // Delegate this call to the outer object's AddRef.
  683.   return m_pUnkOuter->AddRef();
  684. }
  685. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  686.   Method:   COUtilityCruiseCar::CImpIUtility::Release
  687.   Summary:  The Release IUnknown member of this IUtility interface
  688.             implementation that delegates to m_pUnkOuter, whatever it is.
  689.   Args:     void
  690.   Modifies: m_cRefI.
  691.   Returns:  ULONG
  692.               Returned by the delegated outer Release call.
  693. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  694. STDMETHODIMP_(ULONG) COUtilityCruiseCar::CImpIUtility::Release(void)
  695. {
  696.   // Decrement the Interface Reference Count.
  697.   --m_cRefI;
  698.   LOGF1("C: COUtilityCruiseCar::CImpIUtility::Release. Delegating. New cI=%i.", m_cRefI);
  699.   // Delegate this call to the outer object's Release.
  700.   return m_pUnkOuter->Release();
  701. }
  702. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  703.   Method:   COUtilityCruiseCar::CImpIUtility::Offroad
  704.   Summary:  The Offroad member method of this IUtility interface
  705.             implementation.  A simple empty method on a COUtilityCruiseCar
  706.             COM object for tutorial purposes.  Presumably if this
  707.             UtilityCruise Car object were modeling a real Car then the
  708.             Offroad method would function the 4-wheel drive transfer case
  709.             and shift it to the specified 4-wheel drive mode.
  710.   Args:     short nGear
  711.               0 = 2H or regular 2-wheel drive;
  712.               1 = 4H or 4-wheel drive high speed;
  713.               2 = neutral; and
  714.               3 = 4L or 4-wheel drive low speed).
  715.   Modifies: .
  716.   Returns:  HRESULT
  717.               NOERROR
  718. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  719. STDMETHODIMP COUtilityCruiseCar::CImpIUtility::Offroad(
  720.                short nGear)
  721. {
  722.   LOGF1("C: COUtilityCruiseCar::CImpIUtility::Offroad. Called. nGear=%i.",nGear);
  723.   // We don't delegate because this IUtility implementation is native to
  724.   // the composite COUtilityCruiseCar object.
  725.   return NOERROR;
  726. }
  727. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  728.   Method:   COUtilityCruiseCar::CImpIUtility::Winch
  729.   Summary:  The Winch member method of this IUtility interface
  730.             implementation.  A simple empty method on a COUtilityCruiseCar
  731.             COM object for tutorial purposes.  Presumably if this
  732.             UtilityCruiseCar object were modeling a real Car then the
  733.             Winch method would turn on/off the front-mounted Winch to the
  734.             specified RPMs.
  735.   Args:     short nRpm
  736.               0 = off; 1 - 50 RPM.
  737.   Modifies: .
  738.   Returns:  HRESULT
  739.               NOERROR
  740. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  741. STDMETHODIMP COUtilityCruiseCar::CImpIUtility::Winch(
  742.                short nRpm)
  743. {
  744.   LOGF1("C: COUtilityCruiseCar::CImpIUtility::Winch. Called. nRpm=%i.",nRpm);
  745.   // We don't delegate because this IUtility implementation is native to
  746.   // the composite COUtilityCruiseCar object.
  747.   return NOERROR;
  748. }
  749. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  750.   Function: CreateUtilityCruiseCar
  751.   Summary:  Creates an instance of the COUtilityCruiseCar COM object class
  752.             returning a requested interface pointer. COUtilityCruiseCar
  753.             uses the Containment reuse technique to incorporate
  754.             COCruiseCar features (ie, ICar and ICruise implementations)
  755.             into its Interface offerings of IUnknown and IUtility. With
  756.             this containment, the ICar and ICruise interfaces are
  757.             implemented in COUtilityCruiseCar as delegating interfaces
  758.             that delegate to their matching interface implementations in
  759.             an instance of the contained COCruiseCar.  COCruiseCar is
  760.             provided by the outside APTSERVE.EXE server.
  761.   Args:     IUnknown* pUnkOuter,
  762.               Pointer the outer Unknown interface.  Non NULL implies
  763.               that the new COM object is being created via an
  764.               aggregation with an Outer object.  NULL implies that the
  765.               object is not being created via aggregation.
  766.             REFIID riid,
  767.               The GUID of the interface requested on the new COM Object.
  768.             PPVOID ppv)
  769.               Address of the caller's pointer variable that will
  770.               receive the requested interface pointer.
  771.   Returns:  HRESULT
  772.               NOERROR if successful, CLASS_E_NOAGREGATION if IUnknown is
  773.               not requested with non-NULL pUnkOuter, or other errors as
  774.               appropriate.
  775. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  776. HRESULT CreateUtilityCruiseCar(
  777.           IUnknown* pUnkOuter,
  778.           REFIID riid,
  779.           PPVOID ppv)
  780. {
  781.   HRESULT hr;
  782.   COUtilityCruiseCar* pCob;
  783.   LOGF1("C: CreateUtilityCruiseCar. pUnkOuter=0x%X.",pUnkOuter);
  784.   // If the creation call is requesting aggregation (pUnkOuter != NULL),
  785.   // the COM rules state the IUnknown interface MUST also be concomitantly
  786.   // requested.  If it is not so requested ( riid != IID_IUnknown) then
  787.   // an error must be returned indicating that no aggregate creation of
  788.   // the COUtilityCruiseCar COM Object can be performed using anything
  789.   // other than a controlling IUnknown interface.
  790.   if (NULL != pUnkOuter && riid != IID_IUnknown)
  791.     hr = CLASS_E_NOAGGREGATION;
  792.   else
  793.   {
  794.     // Instantiate a COUtilityCruiseCar COM Object.
  795.     pCob = new COUtilityCruiseCar(pUnkOuter);
  796.     if (NULL != pCob)
  797.     {
  798.       // If we have succeeded in instantiating the COUtilityCruiseCar object
  799.       // we initialize it (with any subordinate COM objects) to offer it's
  800.       // interfaces.
  801.       hr = pCob->Init();
  802.       if (SUCCEEDED(hr))
  803.       {
  804.         // We QueryInterface this new COM Object not only to deposit the
  805.         // main interface pointer to the caller's pointer variable, but to
  806.         // also automatically bump the Reference Count on the new COM
  807.         // Object after handing out this *ppv reference to it.
  808.         hr = pCob->QueryInterface(riid, (PPVOID)ppv);
  809.       }
  810.       else
  811.         DELETE_POINTER(pCob);
  812.     }
  813.     else
  814.       hr = E_OUTOFMEMORY;
  815.   }
  816.   if (SUCCEEDED(hr))
  817.   {
  818.     LOGF1("C: CreateUtilityCruiseCar Succeeded. *ppv=0x%X.",*ppv);
  819.   }
  820.   else
  821.   {
  822.     LOGF1("C: CreateUtilityCruiseCar Failed. hr=0x%X.",hr);
  823.   }
  824.   return hr;
  825. }