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 / aptserve / car.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-05  |  15.9 KB  |  501 lines

  1. /*+==========================================================================
  2.   File:      CAR.CPP
  3.  
  4.   Summary:   Implementation file for the COCar COM Object Class (for
  5.              aggregatable Car COM Objects).
  6.  
  7.              COCar offers a main IUnknown interface and the ICar
  8.              interface (Car-related features).  This multiple interface
  9.              COM Object Class is achieved via the technique of nested
  10.              classes--the implementation of the ICar interface is
  11.              nested inside of the COCar Class.
  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:   COCar.
  19.  
  20.   Functions: none.
  21.  
  22.   Origin:    3-20-96: atrent - Editor-inheritance from CAR.CPP in
  23.                the LOCSERVE Tutorial Code Sample.
  24.  
  25. ----------------------------------------------------------------------------
  26.   This file is part of the Microsoft COM 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. /*---------------------------------------------------------------------------
  42.   We include WINDOWS.H for all Win32 applications.
  43.   We include OLE2.H because we will make calls to the COM/OLE Libraries.
  44.   We include APPUTIL.H because we will be building this application using
  45.     the convenient Virtual Window and Dialog classes and other
  46.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  47.   We include MICARS.H and CARGUIDS.H for the common car-related Interface
  48.     class, GUID, and CLSID specifications.
  49.   We include SERVER.H because it has internal class declarations and
  50.     resource ID definitions specific for this executable.
  51.   We include CAR.H because it has the class COCar 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.  
  61.  
  62. /*---------------------------------------------------------------------------
  63.   COCar's implementation of its main COM object class including
  64.   Constructor, Destructor, QueryInterface, AddRef, and Release.
  65. ---------------------------------------------------------------------------*/
  66.  
  67. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  68.   Method:   COCar::COCar
  69.  
  70.   Summary:  COCar Constructor. Note the member initializer:
  71.             "m_ImpICar(this, pUnkOuter)" which is used to pass the 'this'
  72.             and pUnkOuter pointers of this constructor function to the
  73.             constructor in the instantiation of the implementation of
  74.             the CImpICar interface (which is nested inside this present
  75.             COCar Object Class).
  76.  
  77.   Args:     IUnknown* pUnkOuter,
  78.               Pointer to the the outer Unknown.  NULL means this COM Object
  79.               is not being Aggregated.  Non NULL means it is being created
  80.               on behalf of an outside COM object that is reusing it via
  81.               aggregation.
  82.             CServer* pServer)
  83.               Pointer to the server's control object.
  84.  
  85.   Modifies: m_cRefs, m_pUnkOuter, m_pServer.
  86.  
  87.   Returns:  void
  88. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  89. COCar::COCar(
  90.   IUnknown* pUnkOuter,
  91.   CServer* pServer) :
  92.   m_ImpICar(this, pUnkOuter)
  93. {
  94.   // Zero the COM object's reference count.
  95.   m_cRefs = 0;
  96.  
  97.   // No AddRef necessary if non-NULL, as we're nested.
  98.   m_pUnkOuter = pUnkOuter;
  99.  
  100.   // Assign the pointer to the server control object.
  101.   m_pServer = pServer;
  102.  
  103.   LOGF2("L<%X>: COCar Constructor. m_pUnkOuter=0x%X.",TID,m_pUnkOuter);
  104.  
  105.   return;
  106. }
  107.  
  108.  
  109. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  110.   Method:   COCar::~COCar
  111.  
  112.   Summary:  COCar Destructor.
  113.  
  114.   Args:     void
  115.  
  116.   Modifies: .
  117.  
  118.   Returns:  void
  119. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  120. COCar::~COCar(void)
  121. {
  122.   LOGF1("L<%X>: COCar::Destructor.",TID);
  123.  
  124.   return;
  125. }
  126.  
  127.  
  128. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  129.   Method:   COCar::QueryInterface
  130.  
  131.   Summary:  QueryInterface of the COCar non-delegating
  132.             IUnknown implementation.
  133.  
  134.   Args:     REFIID riid,
  135.               [in] GUID of the Interface being requested.
  136.             PPVOID ppv)
  137.               [out] Address of the caller's pointer variable that will
  138.               receive the requested interface pointer.
  139.  
  140.   Modifies: *ppv.
  141.  
  142.   Returns:  HRESULT
  143. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  144. STDMETHODIMP COCar::QueryInterface(
  145.                REFIID riid,
  146.                PPVOID ppv)
  147. {
  148.   HRESULT hr = E_NOINTERFACE;
  149.   *ppv = NULL;
  150.  
  151.   if (IID_IUnknown == riid)
  152.   {
  153.     *ppv = this;
  154.     LOGF1("L<%X>: COCar::QueryInterface. 'this' pIUnknown returned.",TID);
  155.   }
  156.   else if (IID_ICar == riid)
  157.   {
  158.     *ppv = &m_ImpICar;
  159.     LOGF1("L<%X>: COCar::QueryInterface. pICar returned.",TID);
  160.   }
  161.  
  162.   if (NULL != *ppv)
  163.   {
  164.     // We've handed out a pointer to the interface so obey the COM rules
  165.     // and AddRef the reference count.
  166.     ((LPUNKNOWN)*ppv)->AddRef();
  167.     hr = NOERROR;
  168.   }
  169.  
  170.   return (hr);
  171. }
  172.  
  173.  
  174. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  175.   Method:   COCar::AddRef
  176.  
  177.   Summary:  AddRef of the COCar non-delegating IUnknown implementation.
  178.  
  179.   Args:     void
  180.  
  181.   Modifies: m_cRefs.
  182.  
  183.   Returns:  ULONG
  184.               New value of m_cRefs (COM object's reference count).
  185. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  186. STDMETHODIMP_(ULONG) COCar::AddRef(void)
  187. {
  188.   m_cRefs++;
  189.  
  190.   LOGF2("L<%X>: COCar::AddRef. New cRefs=%i.",TID,m_cRefs);
  191.  
  192.   return m_cRefs;
  193. }
  194.  
  195.  
  196. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  197.   Method:   COCar::Release
  198.  
  199.   Summary:  Release of the COCar non-delegating IUnknown implementation.
  200.  
  201.   Args:     void
  202.  
  203.   Modifies: m_cRefs.
  204.  
  205.   Returns:  ULONG
  206.               New value of m_cRefs (COM object's reference count).
  207. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  208. STDMETHODIMP_(ULONG) COCar::Release(void)
  209. {
  210.   m_cRefs--;
  211.  
  212.   LOGF2("L<%X>: COCar::Release. New cRefs=%i.",TID,m_cRefs);
  213.  
  214.   if (0 == m_cRefs)
  215.   {
  216.     // We artificially bump the main ref count to prevent reentrancy
  217.     // via the main object destructor.  Not really needed in this
  218.     // COCar but a good practice because we are aggregatable and
  219.     // may at some point in the future add something entertaining like
  220.     // some Releases in the COCar destructor.
  221.     m_cRefs++;
  222.     delete this;
  223.  
  224.     // We've reached a zero reference count for this COM object.
  225.     // So we tell the server housing to decrement its global object
  226.     // count so that the server will be unloaded if appropriate.
  227.     if (NULL != m_pServer)
  228.       m_pServer->ObjectsDown();
  229.   }
  230.  
  231.   return m_cRefs;
  232. }
  233.  
  234.  
  235. /*---------------------------------------------------------------------------
  236.   COCar's nested implementation of the ICar interface including
  237.   Constructor, Destructor, QueryInterface, AddRef, Release,
  238.   Shift, Clutch, Speed, and Steer.
  239. ---------------------------------------------------------------------------*/
  240.  
  241. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  242.   Method:   COCar::CImpICar::CImpICar
  243.  
  244.   Summary:  Constructor for the CImpICar interface instantiation.
  245.  
  246.   Args:     COCar* pBackObj,
  247.               Back pointer to the parent outer object.
  248.             IUnknown* pUnkOuter
  249.               Pointer to the outer Unknown.  For delegation.
  250.  
  251.   Modifies: m_cRefI, m_pBackObj, m_pUnkOuter.
  252.  
  253.   Returns:  void
  254. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  255. COCar::CImpICar::CImpICar(
  256.   COCar* pBackObj,
  257.   IUnknown* pUnkOuter)
  258. {
  259.   // Zero an ICar method call counter (used for tutorial purposes only).
  260.   m_C = 0;
  261.  
  262.   // Init the Interface Ref Count (used for debugging only).
  263.   m_cRefI = 0;
  264.  
  265.   // Init the Back Object Pointer to point to the parent object.
  266.   m_pBackObj = pBackObj;
  267.  
  268.   // Init the CImpICar interface's delegating Unknown pointer.  We use
  269.   // the Back Object pointer for IUnknown delegation here if we are not
  270.   // being aggregated.  If we are being aggregated we use the supplied
  271.   // pUnkOuter for IUnknown delegation.  In either case the pointer
  272.   // assignment requires no AddRef because the CImpICar lifetime is
  273.   // guaranteed by the lifetime of the parent object in which
  274.   // CImpICar is nested.
  275.   if (NULL == pUnkOuter)
  276.   {
  277.     m_pUnkOuter = pBackObj;
  278.     LOGF1("L<%X>: COCar::CImpICar Constructor. Non-Aggregating.",TID);
  279.   }
  280.   else
  281.   {
  282.     m_pUnkOuter = pUnkOuter;
  283.     LOGF1("L<%X>: COCar::CImpICar Constructor. Aggregating.",TID);
  284.   }
  285.  
  286.   return;
  287. }
  288.  
  289.  
  290. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  291.   Method:   COCar::CImpICar::~CImpICar
  292.  
  293.   Summary:  Destructor for the CImpICar interface instantiation.
  294.  
  295.   Args:     void
  296.  
  297.   Modifies: .
  298.  
  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. COCar::CImpICar::~CImpICar(void)
  302. {
  303.   LOGF1("L<%X>: COCar::CImpICar Destructor.",TID);
  304.  
  305.   return;
  306. }
  307.  
  308.  
  309. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  310.   Method:   COCar::CImpICar::QueryInterface
  311.  
  312.   Summary:  The QueryInterface IUnknown member of this ICar interface
  313.             implementation that delegates to m_pUnkOuter, whatever it is.
  314.  
  315.   Args:     REFIID riid,
  316.               [in] GUID of the Interface being requested.
  317.             PPVOID ppv)
  318.               [out] Address of the caller's pointer variable that will
  319.               receive the requested interface pointer.
  320.  
  321.   Modifies: .
  322.  
  323.   Returns:  HRESULT
  324.               Returned by the delegated outer QueryInterface call.
  325. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  326. STDMETHODIMP COCar::CImpICar::QueryInterface(
  327.                REFIID riid,
  328.                PPVOID ppv)
  329. {
  330.   LOGF1("L<%X>: COCar::CImpICar::QueryInterface. Delegating.",TID);
  331.  
  332.   // Delegate this call to the outer object's QueryInterface.
  333.   return m_pUnkOuter->QueryInterface(riid, ppv);
  334. }
  335.  
  336.  
  337. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  338.   Method:   COCar::CImpICar::AddRef
  339.  
  340.   Summary:  The AddRef IUnknown member of this ICar interface
  341.             implementation that delegates to m_pUnkOuter, whatever it is.
  342.  
  343.   Args:     void
  344.  
  345.   Modifies: m_cRefI.
  346.  
  347.   Returns:  ULONG
  348.               Returned by the delegated outer AddRef call.
  349. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  350. STDMETHODIMP_(ULONG) COCar::CImpICar::AddRef(void)
  351. {
  352.   // Increment the Interface Reference Count.
  353.   ++m_cRefI;
  354.  
  355.   LOGF2("L<%X>: COCar::CImpICar::Addref. Delegating. New cI=%i.",TID,m_cRefI);
  356.  
  357.   // Delegate this call to the outer object's AddRef.
  358.   return m_pUnkOuter->AddRef();
  359. }
  360.  
  361.  
  362. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  363.   Method:   COCar::CImpICar::Release
  364.  
  365.   Summary:  The Release IUnknown member of this ICar interface
  366.             implementation that delegates to m_pUnkOuter, whatever it is.
  367.  
  368.   Args:     void
  369.  
  370.   Modifies: m_cRefI.
  371.  
  372.   Returns:  ULONG
  373.               Returned by the delegated outer Release call.
  374. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  375. STDMETHODIMP_(ULONG) COCar::CImpICar::Release(void)
  376. {
  377.   // Decrement the Interface Reference Count.
  378.   --m_cRefI;
  379.  
  380.   LOGF2("L<%X>: COCar::CImpICar::Release. Delegating. New cI=%i.",TID,m_cRefI);
  381.  
  382.   // Delegate this call to the outer object's Release.
  383.   return m_pUnkOuter->Release();
  384. }
  385.  
  386.  
  387. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  388.   Method:   COCar::CImpICar::Shift
  389.  
  390.   Summary:  The Shift member method of this ICar interface implementation.
  391.             A simple empty method on a COCar COM object for tutorial
  392.             purposes.  Presumably if this Car object were modeling
  393.             a real Car then the Shift method would shift to the specified
  394.             gear.
  395.  
  396.   Args:     short nGear
  397.               0 - Neutral; 1 - 5 First 5 forward gears; 6 - Reverse.
  398.  
  399.   Modifies: m_C.
  400.  
  401.   Returns:  HRESULT
  402.               NOERROR
  403. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  404. STDMETHODIMP COCar::CImpICar::Shift(
  405.                short nGear)
  406. {
  407.   // Increment method call counter purely for tutorial reasons.
  408.   m_C++;
  409.  
  410.   LOGF2("L<%X>: COCar::CImpICar::Shift. Called. ICar calls=%i.",TID,m_C);
  411.  
  412.   return NOERROR;
  413. }
  414.  
  415.  
  416. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  417.   Method:   COCar::CImpICar::Clutch
  418.  
  419.   Summary:  The Clutch member method of this ICar interface implementation.
  420.             A simple empty method on a COCar COM object for tutorial
  421.             purposes.  Presumably if this Car object were modeling
  422.             a real Car then the Clutch method would engage the clutch the
  423.             specified amount.
  424.  
  425.   Args:     short nEngaged)
  426.               Percent clutch is engaged (0 to 100%).
  427.  
  428.   Modifies: m_C.
  429.  
  430.   Returns:  HRESULT
  431.               NOERROR
  432. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  433. STDMETHODIMP COCar::CImpICar::Clutch(
  434.                short nEngaged)
  435. {
  436.   // Increment method call counter purely for tutorial reasons.
  437.   m_C++;
  438.  
  439.   LOGF2("L<%X>: COCar::CImpICar::Clutch. Called. ICar calls=%i.",TID,m_C);
  440.  
  441.   return NOERROR;
  442. }
  443.  
  444.  
  445. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  446.   Method:   COCar::CImpICar::Speed
  447.  
  448.   Summary:  The Speed member method of this ICar interface implementation.
  449.             A simple empty method on a COCar COM object for tutorial
  450.             purposes.  Presumably if this Car object were modeling
  451.             a real Car then this method would accelerate/brake to bring
  452.             the car to the specified speed.
  453.  
  454.   Args:     short nMph
  455.               New speed in miles per hour.
  456.  
  457.   Modifies: m_C.
  458.  
  459.   Returns:  HRESULT
  460.               NOERROR
  461. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  462. STDMETHODIMP COCar::CImpICar::Speed(
  463.                short nMph)
  464. {
  465.   // Increment method call counter purely for tutorial reasons.
  466.   m_C++;
  467.  
  468.   LOGF2("L<%X>: COCar::CImpICar::Speed. Called. ICar calls=%i.",TID,m_C);
  469.  
  470.   return NOERROR;
  471. }
  472.  
  473.  
  474. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  475.   Method:   COCar::CImpICar::Steer
  476.  
  477.   Summary:  The Steer member method of this ICar interface implementation.
  478.             A simple empty method on a COCar COM object for tutorial
  479.             purposes.  Presumably if this Car object were modeling
  480.             a real Car then the Steer method would set the steering
  481.             angle of the Car.
  482.  
  483.   Args:     short nAngle)
  484.               0 degrees straight ahead, -45 Full left, +45 Full right.
  485.  
  486.   Modifies: m_C.
  487.  
  488.   Returns:  HRESULT
  489.               NOERROR
  490. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  491. STDMETHODIMP COCar::CImpICar::Steer(
  492.                short nAngle)
  493. {
  494.   // Increment method call counter purely for tutorial reasons.
  495.   m_C++;
  496.  
  497.   LOGF2("L<%X>: COCar::CImpICar::Steer. Called. ICar calls=%i.",TID,m_C);
  498.  
  499.   return NOERROR;
  500. }
  501.