home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap02 / reuse / koalaa.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  6KB  |  280 lines

  1. /*
  2.  * KOALAA.CPP
  3.  *
  4.  * Koala Object Reusing Animal via Aggregation, Chapter 2
  5.  *
  6.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  7.  *
  8.  * Kraig Brockschmidt, Microsoft
  9.  * Internet  :  kraigb@microsoft.com
  10.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  11.  */
  12.  
  13. #include <windows.h>
  14. #include "reuse.h"
  15. #include "koalaa.h"
  16.  
  17.  
  18. /*
  19.  * CreateKoalaAggregation
  20.  *
  21.  * Purpose:
  22.  *  Creates an instance of KoalaA returning an IUnknown
  23.  *  interface.
  24.  *
  25.  * Parameters:
  26.  *  ppUnk           IUnknown ** in which to return the pointer.
  27.  *
  28.  * Return Value:
  29.  *  BOOL            TRUE if successful, FALSE otherwise.
  30.  */
  31.  
  32. BOOL CreateKoalaAggregation(IUnknown **ppUnk)
  33.     {
  34.     CKoalaA    *pObj;
  35.     HRESULT     hr;
  36.  
  37.     pObj=new CKoalaA();
  38.  
  39.     if (NULL==pObj)
  40.         return FALSE;
  41.  
  42.     if (!pObj->Init())
  43.         return FALSE;
  44.  
  45.     hr=pObj->QueryInterface(IID_IUnknown, (PPVOID)ppUnk);
  46.     return SUCCEEDED(hr);
  47.     }
  48.  
  49.  
  50.  
  51.  
  52.  
  53. /*
  54.  * CKoalaA::CKoalaA
  55.  * CKoalaA::~CKoalaA
  56.  *
  57.  * Constructor Parameters:
  58.  *  None
  59.  */
  60.  
  61. CKoalaA::CKoalaA(void)
  62.     {
  63.     m_cRef=0;
  64.     m_pImpIKoala=NULL;
  65.     m_pIUnknown=NULL;
  66.     m_pIAnimal=NULL;
  67.     return;
  68.     }
  69.  
  70. CKoalaA::~CKoalaA(void)
  71.     {
  72.     /*
  73.      * Since this KoalaA is not aggregatable, we can use the
  74.      * 32-bit rule under Win16 as well.
  75.      */
  76.     AddRef();
  77.     ReleaseInterface(m_pIAnimal);
  78.  
  79.     ReleaseInterface(m_pIUnknown);
  80.     DeleteInterfaceImp(m_pImpIKoala);
  81.     return;
  82.     }
  83.  
  84.  
  85.  
  86. /*
  87.  * CKoalaA::Init
  88.  *
  89.  * Purpose:
  90.  *  Instantiates the interface implementations for this object.
  91.  *
  92.  * Parameters:
  93.  *  None
  94.  *
  95.  * Return Value:
  96.  *  BOOL            TRUE if initialization succeeds, FALSE otherwise.
  97.  */
  98.  
  99. BOOL CKoalaA::Init(void)
  100.     {
  101.     HRESULT     hr;
  102.  
  103.     //Create our interface
  104.     m_pImpIKoala=new CImpIKoala_A(this);
  105.  
  106.     if (NULL==m_pImpIKoala)
  107.         return FALSE;
  108.  
  109.     /*
  110.      * Create an instance of the Animal object, saving an
  111.      * IUnknown but also saving a released IAnimal.  We use
  112.      * Animal's global API function for this.
  113.      */
  114.     hr=CreateAnimal(this, IID_IUnknown, (void **)&m_pIUnknown);
  115.  
  116.     if (FAILED(hr))
  117.         return FALSE;
  118.  
  119.     /*
  120.      * Grab an IAnimal to show the Release rule.  We don't do
  121.      * anything with this pointer, but we want to show the Release.
  122.      */
  123.     hr=m_pIUnknown->QueryInterface(IID_IAnimal, (void **)&m_pIAnimal);
  124.  
  125.     if (FAILED(hr))
  126.         return FALSE;
  127.  
  128.     /*
  129.      * In caching the IAnimal pointer we have to fix our
  130.      * reference count.  SInce KoalaC is not aggregatable itself,
  131.      * we can use the 32-bit rule for this case in 16-bit
  132.      * compilations as well.
  133.      *
  134.      * Our reference count may be as little as one at this pointer
  135.      * so calling our own Release (or m_pIAnimal's) is a bad idea.
  136.      * Since we just need to fix the count, we can just decrement
  137.      * m_cRef.  If we have to call someone's Release, then we'd
  138.      * need to wrap that call in m_cRef++ and m_cRef--.
  139.      */
  140.     m_cRef--;
  141.  
  142.     return TRUE;
  143.     }
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150. /*
  151.  * CKoalaA::QueryInterface
  152.  * CKoalaA::AddRef
  153.  * CKoalaA::Release
  154.  *
  155.  * Purpose:
  156.  *  KoalaA's IUnknown implementation which serves as the outer
  157.  *  unknown in the aggregation.
  158.  */
  159.  
  160. STDMETHODIMP CKoalaA::QueryInterface(REFIID riid, PPVOID ppv)
  161.     {
  162.     *ppv=NULL;
  163.  
  164.     if (IID_IUnknown==riid)
  165.         *ppv=this;
  166.  
  167.     //Alternately *ppv=m_pIAnimal; works for this case
  168.     if (IID_IAnimal==riid)
  169.         return m_pIUnknown->QueryInterface(riid, ppv);
  170.  
  171.     if (IID_IKoala==riid)
  172.         *ppv=m_pImpIKoala;
  173.  
  174.     if (NULL==*ppv)
  175.         return ResultFromScode(E_NOINTERFACE);
  176.  
  177.     ((LPUNKNOWN)*ppv)->AddRef();
  178.     return NOERROR;
  179.     }
  180.  
  181.  
  182. DWORD CKoalaA::AddRef(void)
  183.     {
  184.     return ++m_cRef;
  185.     }
  186.  
  187. DWORD CKoalaA::Release(void)
  188.     {
  189.     if (0!=--m_cRef)
  190.         return m_cRef;
  191.  
  192.     m_cRef++;       //Artificial count preventing reentrancy
  193.     delete this;
  194.     return 0;
  195.     }
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202. //CImpIKoala_A interface implementation
  203.  
  204.  
  205. /*
  206.  * CImpIKoala_A::CImpIKoala_A
  207.  * CImpIKoala_A::~CImpIKoala_A
  208.  *
  209.  * Constructor Parameters:
  210.  *  pObj            PCKoalaA to the outer object
  211.  */
  212.  
  213. CImpIKoala_A::CImpIKoala_A(PCKoalaA pObj)
  214.     {
  215.     m_cRef=0;
  216.     m_pObj=pObj;
  217.     return;
  218.     }
  219.  
  220. CImpIKoala_A::~CImpIKoala_A(void)
  221.     {
  222.     return;
  223.     }
  224.  
  225.  
  226.  
  227. /*
  228.  * CImpIKoala_A::QueryInterface
  229.  * CImpIKoala_A::AddRef
  230.  * CImpIKoala_A::Release
  231.  *
  232.  * IUnknown members that delegate to KoalaA
  233.  */
  234.  
  235. STDMETHODIMP CImpIKoala_A::QueryInterface(REFIID riid, PPVOID ppv)
  236.     {
  237.     return m_pObj->QueryInterface(riid, ppv);
  238.     }
  239.  
  240. DWORD CImpIKoala_A::AddRef(void)
  241.     {
  242.     ++m_cRef;
  243.     return m_pObj->AddRef();
  244.     }
  245.  
  246. DWORD CImpIKoala_A::Release(void)
  247.     {
  248.     --m_cRef;
  249.     return m_pObj->Release();
  250.     }
  251.  
  252.  
  253.  
  254. /*
  255.  * CImpIKoala_A::ClimbEucalyptusTrees
  256.  * CImpIKoala_A::PouchOpensDown
  257.  * CImpIKoala_A::SleepForHoursAfterEating
  258.  *
  259.  * Purpose:
  260.  *  Empty sample functions, no parameters, return NOERROR
  261.  */
  262.  
  263. STDMETHODIMP CImpIKoala_A::ClimbEucalyptusTrees(void)
  264.     {
  265.     ODS("KoalaA's IKoala::ClimbEucalyptusTrees called");
  266.     return NOERROR;
  267.     }
  268.  
  269. STDMETHODIMP CImpIKoala_A::PouchOpensDown(void)
  270.     {
  271.     ODS("KoalaA's IKoala::PouchOpensDown called");
  272.     return NOERROR;
  273.     }
  274.  
  275. STDMETHODIMP CImpIKoala_A::SleepForHoursAfterEating(void)
  276.     {
  277.     ODS("KoalaA's IKoala::SleepForHoursAfterEating called");
  278.     return NOERROR;
  279.     }
  280.