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 / crucar.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-04  |  16.0 KB  |  479 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 object
  8.              class with the IUnknown, ICar, and ICruise interfaces.  This
  9.              is done through Aggregation reuse of COCar's ICar
  10.              interface features.
  11.  
  12.              For a comprehensive tutorial code tour of this module's
  13.              contents and offerings see the tutorial COMOBJ.HTM
  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:   COCruiseCar
  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 CRUCAR.H because it has the class COCruiseCar 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 "crucar.h"
  63.  
  64.  
  65. /*---------------------------------------------------------------------------
  66.   COCruiseCar'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:   COCruiseCar::COCruiseCar
  72.  
  73.   Summary:  COCruiseCar Constructor. Note the member initializer:
  74.             "m_ImpICruise(this, pUnkOuter)" which is used to pass the
  75.             'this' and pUnkOuter pointers of this constructor function
  76.             to the constructor in the instantiation of the implementation
  77.             of the CImpICar interface (which is nested inside this present
  78.             COCruiseCar Object Class).
  79.  
  80.   Args:     IUnknown* pUnkOuter)
  81.               Pointer to the the outer Unknown.  NULL means this COM Object
  82.               is not being Aggregated.  Non NULL means it is being created
  83.               on behalf of an outside COM object that is reusing it via
  84.               aggregation.
  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.   m_ImpICruise(this, pUnkOuter)
  93. {
  94.   // Zero the COM object's reference count.
  95.   m_cRefs = 0;
  96.  
  97.   // No AddRef necessary if non-NULL, as this present COM object's lifetime
  98.   // is totally coupled with the controlling Outer object's lifetime.
  99.   m_pUnkOuter = pUnkOuter;
  100.  
  101.   // Zero the pointer to the aggregated COCar object's IUnknown
  102.   // interface (for delegation of IUnknown calls to it).
  103.   m_pUnkCar = NULL;
  104.  
  105.   LOGF1("D: COCruiseCar 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:   COCruiseCar::~COCruiseCar
  113.  
  114.   Summary:  COCruiseCar 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. COCruiseCar::~COCruiseCar(void)
  123. {
  124.   LOG("D: COCruiseCar::Destructor.");
  125.  
  126.   RELEASE_INTERFACE(m_pUnkCar);
  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:   COCruiseCar::Init
  134.  
  135.   Summary:  COCruiseCar 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 COCruiseCar::Init(void)
  145. {
  146.   HRESULT hr;
  147.   // Set up the right pIUnknown for delegation.  If we are being
  148.   // aggregated then we pass the pUnkOuter in turn to any COM objects
  149.   // that we are aggregating.  m_pUnkOuter was set in the Constructor.
  150.   IUnknown* pUnkOuter = (NULL == m_pUnkOuter) ? this : m_pUnkOuter;
  151.  
  152.   LOG("D: COCruiseCar::Init.");
  153.  
  154.   // We create an instance of the COCar object and do this via the
  155.   // Aggregation reuse technique.  Note we pass pUnkOuter as the
  156.   // Aggregation pointer.  It is the 'this' pointer to this present
  157.   // CruiseCar object if we are not being aggregated; otherwise it is
  158.   // the pointer to the outermost object's controlling IUnknown.  Following
  159.   // the rules of Aggregation we ask CreateCar for an IID_IUnknown
  160.   // interface.  We cache this pointer to the IUnknown of the new COCar
  161.   // COM object for later use in delegating IUnknown calls.
  162.   hr = CreateCar(pUnkOuter, IID_IUnknown, (PPVOID)&m_pUnkCar);
  163.  
  164.   return (hr);
  165. }
  166.  
  167.  
  168. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  169.   Method:   COCruiseCar::QueryInterface
  170.  
  171.   Summary:  QueryInterface of the COCruiseCar non-delegating
  172.             IUnknown implementation.
  173.  
  174.   Args:     REFIID riid,
  175.               [in] GUID of the Interface being requested.
  176.             PPVOID ppv)
  177.               [out] Address of the caller's pointer variable that will
  178.               receive the requested interface pointer.
  179.  
  180.   Modifies: .
  181.  
  182.   Returns:  HRESULT
  183. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  184. STDMETHODIMP COCruiseCar::QueryInterface(
  185.                REFIID riid,
  186.                PPVOID ppv)
  187. {
  188.   HRESULT hr = E_NOINTERFACE;
  189.   *ppv = NULL;
  190.  
  191.   if (IID_IUnknown == riid)
  192.   {
  193.     *ppv = this;
  194.     LOG("D: COCruiseCar::QueryInterface. 'this' pIUnknown returned.");
  195.   }
  196.   else if (IID_ICruise == riid)
  197.   {
  198.     // This ICruise interface is implemented in this COCruiseCar object and
  199.     // might be called a native interface of COCruiseCar.
  200.     *ppv = &m_ImpICruise;
  201.     LOG("D: COCruiseCar::QueryInterface. pICruise returned.");
  202.   }
  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.   else if (IID_ICar == riid)
  212.   {
  213.     LOG("D: COCruiseCar::QueryInterface. ICar delegating.");
  214.     // We didn't implement the ICar interface in this COCruiseCar object.
  215.     // The aggregated inner COCar object is contributing the ICar
  216.     // interface to this present composite or aggregating CruiseCar object.
  217.     // So, to satisfy a QI request for the ICar interface, we delegate
  218.     // the QueryInterface to the inner object's controlling IUnknown.
  219.     hr = m_pUnkCar->QueryInterface(riid, ppv);
  220.   }
  221.  
  222.   return (hr);
  223. }
  224.  
  225.  
  226. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  227.   Method:   COCruiseCar::AddRef
  228.  
  229.   Summary:  AddRef of the COCruiseCar non-delegating IUnknown implementation.
  230.  
  231.   Args:     void
  232.  
  233.   Modifies: m_cRefs.
  234.  
  235.   Returns:  ULONG
  236.               New value of m_cRefs (COM object's reference count).
  237. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  238. STDMETHODIMP_(ULONG) COCruiseCar::AddRef(void)
  239. {
  240.   m_cRefs++;
  241.  
  242.   LOGF1("D: COCruiseCar::AddRef. New cRefs=%i.", m_cRefs);
  243.  
  244.   return m_cRefs;
  245. }
  246.  
  247.  
  248. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  249.   Method:   COCruiseCar::Release
  250.  
  251.   Summary:  Release of the COCruiseCar non-delegating IUnknown implementation.
  252.  
  253.   Args:     void
  254.  
  255.   Modifies: m_cRefs.
  256.  
  257.   Returns:  ULONG
  258.               New value of m_cRefs (COM object's reference count).
  259. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  260. STDMETHODIMP_(ULONG) COCruiseCar::Release(void)
  261. {
  262.   ULONG ulCount = --m_cRefs;
  263.  
  264.   LOGF1("D: COCruiseCar::Release. New cRefs=%i.", m_cRefs);
  265.  
  266.   if (0 == m_cRefs)
  267.   {
  268.     // We artificially bump the main ref count.  This fulfills one of
  269.     // the rules of aggregated objects and ensures that an indirect
  270.     // recursive call to this release won't occur because of other
  271.     // delegating releases that might happen in our own destructor.
  272.     m_cRefs++;
  273.     delete this;
  274.   }
  275.  
  276.   return ulCount;
  277. }
  278.  
  279.  
  280. /*---------------------------------------------------------------------------
  281.   COCruiseCar's nested implementation of the ICruise interface including
  282.   Constructor, Destructor, QueryInterface, AddRef, Release,
  283.   Engage, and Adjust.
  284. ---------------------------------------------------------------------------*/
  285.  
  286. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  287.   Method:   COCruiseCar::CImpICruise::CImpICruise
  288.  
  289.   Summary:  Constructor for the CImpICruise interface instantiation.
  290.  
  291.   Args:     COCruiseCar* pBackObj,
  292.               Back pointer to the parent outer object.
  293.             IUnknown* pUnkOuter)
  294.               Pointer to the outer Unknown.  For delegation.
  295.  
  296.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  297.  
  298.   Returns:  void
  299. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  300. COCruiseCar::CImpICruise::CImpICruise(
  301.   COCruiseCar* pBackObj,
  302.   IUnknown* pUnkOuter)
  303. {
  304.   // Init the Interface Ref Count (used for debugging only).
  305.   m_cRefI = 0;
  306.  
  307.   // Init the Back Object Pointer to point to the outer object.
  308.   m_pBackObj = pBackObj;
  309.  
  310.   // Init the CImpICruise interface's delegating Unknown pointer.  We use
  311.   // the Back Object pointer for IUnknown delegation here if we are not
  312.   // being aggregated.  If we are being aggregated we use the supplied
  313.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  314.   // assignment requires no AddRef because the CImpICruise lifetime is
  315.   // quaranteed by the lifetime of the parent object in which
  316.   // CImpICruise is nested.
  317.   if (NULL == pUnkOuter)
  318.   {
  319.     m_pUnkOuter = pBackObj;
  320.     LOG("D: COCruiseCar::CImpICruise Constructor. Non-Aggregating.");
  321.   }
  322.   else
  323.   {
  324.     m_pUnkOuter = pUnkOuter;
  325.     LOG("D: COCruiseCar::CImpICruise Constructor. Aggregating.");
  326.   }
  327.  
  328.   return;
  329. }
  330.  
  331.  
  332. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  333.   Method:   COCruiseCar::CImpICruise::~CImpICruise
  334.  
  335.   Summary:  Destructor for the CImpICruise interface instantiation.
  336.  
  337.   Args:     void
  338.  
  339.   Modifies: .
  340.  
  341.   Returns:  void
  342. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  343. COCruiseCar::CImpICruise::~CImpICruise(void)
  344. {
  345.   LOG("D: COCruiseCar::CImpICruise Destructor.");
  346.  
  347.   return;
  348. }
  349.  
  350.  
  351. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  352.   Method:   COCruiseCar::CImpICruise::QueryInterface
  353.  
  354.   Summary:  The QueryInterface IUnknown member of this ICruise interface
  355.             implementation that delegates to m_pUnkOuter, whatever it is.
  356.  
  357.   Args:     REFIID riid,
  358.               [in] GUID of the Interface being requested.
  359.             PPVOID ppv)
  360.               [out] Address of the caller's pointer variable that will
  361.               receive the requested interface pointer.
  362.  
  363.   Modifies: .
  364.  
  365.   Returns:  HRESULT
  366.               Returned by the delegated outer QueryInterface call.
  367. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  368. STDMETHODIMP COCruiseCar::CImpICruise::QueryInterface(
  369.                REFIID riid,
  370.                PPVOID ppv)
  371. {
  372.   LOG("D: COCruiseCar::CImpICruise::QueryInterface. Delegating.");
  373.  
  374.   // Delegate this call to the outer object's QueryInterface.
  375.   return m_pUnkOuter->QueryInterface(riid, ppv);
  376. }
  377.  
  378.  
  379. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  380.   Method:   COCruiseCar::CImpICruise::AddRef
  381.  
  382.   Summary:  The AddRef IUnknown member of this ICruise interface
  383.             implementation that delegates to m_pUnkOuter, whatever it is.
  384.  
  385.   Args:     void
  386.  
  387.   Modifies: m_cRefI.
  388.  
  389.   Returns:  ULONG
  390.               Returned by the delegated outer AddRef call.
  391. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  392. STDMETHODIMP_(ULONG) COCruiseCar::CImpICruise::AddRef(void)
  393. {
  394.   // Increment the Interface Reference Count.
  395.   ++m_cRefI;
  396.  
  397.   LOGF1("D: COCruiseCar::CImpICruise::Addref. Delegating. New cI=%i.", m_cRefI);
  398.  
  399.   // Delegate this call to the outer object's AddRef.
  400.   return m_pUnkOuter->AddRef();
  401. }
  402.  
  403.  
  404. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  405.   Method:   COCruiseCar::CImpICruise::Release
  406.  
  407.   Summary:  The Release IUnknown member of this ICruise interface
  408.             implementation that delegates to m_pUnkOuter, whatever it is.
  409.  
  410.   Args:     void
  411.  
  412.   Modifies: .
  413.  
  414.   Returns:  ULONG
  415.               Returned by the delegated outer Release call.
  416. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  417. STDMETHODIMP_(ULONG) COCruiseCar::CImpICruise::Release(void)
  418. {
  419.   // Decrement the Interface Reference Count.
  420.   --m_cRefI;
  421.  
  422.   LOGF1("D: COCruiseCar::CImpICruise::Release. Delegating. New cI=%i.", m_cRefI);
  423.  
  424.   // Delegate this call to the outer object's Release.
  425.   return m_pUnkOuter->Release();
  426. }
  427.  
  428.  
  429. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  430.   Method:   COCruiseCar::CImpICruise::Engage
  431.  
  432.   Summary:  The Engage member method of this ICruise interface
  433.             implementation.  A simple empty method on a COCruiseCar COM
  434.             object for tutorial purposes.  Presumably if this Car object
  435.             were modeling a real Car then the Engage method would turn
  436.             the Cruise control system on or off.
  437.  
  438.   Args:     BOOL bOnOff)
  439.               TRUE for On; FALSE for Off.
  440.  
  441.   Modifies: .
  442.  
  443.   Returns:  HRESULT
  444.               NOERROR
  445. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  446. STDMETHODIMP COCruiseCar::CImpICruise::Engage(
  447.                BOOL bOnOff)
  448. {
  449.   LOGF1("D: COCruiseCar::CImpICruise::Engage. Called. bOnOff=%i.",bOnOff);
  450.  
  451.   return NOERROR;
  452. }
  453.  
  454.  
  455. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  456.   Method:   COCruiseCar::CImpICruise::Adjust
  457.  
  458.   Summary:  The Adjust member method of this ICruise interface
  459.             implementation.  A simple empty method on a COCruiseCar COM
  460.             object for tutorial purposes.  Presumably if this Car object
  461.             were modeling a real Car then the Adjust method would allow
  462.             notching the cruise set speed up or down by increments of 3 mph.
  463.  
  464.   Args:     BOOL bUpDown)
  465.               TRUE for Up; FALSE for Down.
  466.  
  467.   Modifies: .
  468.  
  469.   Returns:  HRESULT
  470.               NOERROR
  471. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  472. STDMETHODIMP COCruiseCar::CImpICruise::Adjust(
  473.                BOOL bUpDown)
  474. {
  475.   LOGF1("D: COCruiseCar::CImpICruise::Adjust. Called. bUpDown=%i.",bUpDown);
  476.  
  477.   return NOERROR;
  478. }
  479.