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 / query / object2.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  7KB  |  309 lines

  1. /*
  2.  * OBJECT2.CPP
  3.  *
  4.  * Object implementation using contained interface classes
  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 "query.h"
  15.  
  16.  
  17. //Message strings for the interface functions
  18. static TCHAR szMessage[]=TEXT("Message from ISampleOne::GetMessage");
  19. static TCHAR szString[] =TEXT("Message from ISampleTwo::GetString");
  20.  
  21.  
  22. /*
  23.  * CreateObject2
  24.  *
  25.  * Purpose:
  26.  *  Creates an instance of Object2 returning an IUnknown
  27.  *  interface.
  28.  *
  29.  * Parameters:
  30.  *  ppUnk           IUnknown ** in which to return the
  31.  *                  interface pointer.
  32.  *
  33.  * Return Value:
  34.  *  BOOL            TRUE if the function is successful,
  35.  *                  FALSE otherwise.
  36.  */
  37.  
  38. BOOL CreateObject2(IUnknown **ppUnk)
  39.     {
  40.     HRESULT     hr;
  41.     CObject2   *pObj;
  42.  
  43.     if (NULL==ppUnk)
  44.         return FALSE;
  45.  
  46.     //Create the new object, which gives us a C++ object pointer
  47.     pObj=new CObject2();
  48.  
  49.     if (NULL==pObj)
  50.         return FALSE;
  51.  
  52.     /*
  53.      * Now get the IUnknown interface to this object and make
  54.      * sure that it's reference count is correct.  We could either
  55.      * typecast pObj to IUnknown and call AddRef explicitly, or
  56.      * we can simply call pObj->QueryInterface and let it do the
  57.      * typecast and the AddRef for us.
  58.      */
  59.     hr=pObj->QueryInterface(IID_IUnknown, (PPVOID)ppUnk);
  60.     return SUCCEEDED(hr);
  61.     }
  62.  
  63.  
  64.  
  65.  
  66.  
  67. /*
  68.  * CObject2::CObject2
  69.  * CObject2::~CObject2
  70.  *
  71.  * Constructor Parameters:
  72.  *  None
  73.  */
  74.  
  75. CObject2::CObject2(void)
  76.     : m_ImpISampleOne(this), m_ImpISampleTwo(this)
  77.     {
  78.     m_cRef=0;
  79.     return;
  80.     }
  81.  
  82. CObject2::~CObject2(void)
  83.     {
  84.     //Interfaces cleaned up automatically
  85.     return;
  86.     }
  87.  
  88.  
  89.  
  90.  
  91.  
  92. /*
  93.  * CObject2::QueryInterface
  94.  *
  95.  * Purpose:
  96.  *  Manages the interfaces for this object which supports the
  97.  *  IUnknown, ISampleOne, and ISampleTwo interfaces.
  98.  *
  99.  * Parameters:
  100.  *  riid            REFIID of the interface to return.
  101.  *  ppv             PPVOID in which to store the pointer.
  102.  *
  103.  * Return Value:
  104.  *  HRESULT         NOERROR on success, E_NOINTERFACE if the
  105.  *                  interface is not supported.
  106.  */
  107.  
  108. STDMETHODIMP CObject2::QueryInterface(REFIID riid, PPVOID ppv)
  109.     {
  110.     //Always NULL the out-parameters
  111.     *ppv=NULL;
  112.  
  113.     /*
  114.      * IUnknown comes from CObject2.  Note that here we do not need
  115.      * to explicitly typecast the object pointer into an interface
  116.      * pointer because the vtables are identical.  If we had
  117.      * additional virtual member functions in the object, we would
  118.      * have to cast in order to set the right vtable.  This is
  119.      * demonstrated in the multiple-inheritance version, CObject3.
  120.      */
  121.     if (IID_IUnknown==riid)
  122.         *ppv=this;
  123.  
  124.     //Other interfaces come from contained classes
  125.     if (IID_ISampleOne==riid)
  126.         *ppv=&m_ImpISampleOne;
  127.  
  128.     if (IID_ISampleTwo==riid)
  129.         *ppv=&m_ImpISampleTwo;
  130.  
  131.     if (NULL==*ppv)
  132.         return ResultFromScode(E_NOINTERFACE);
  133.  
  134.     //AddRef any interface we'll return.
  135.     ((LPUNKNOWN)*ppv)->AddRef();
  136.     return NOERROR;
  137.     }
  138.  
  139.  
  140.  
  141. /*
  142.  * CObject2::AddRef
  143.  * CObject2::Release
  144.  *
  145.  * Reference counting members.  When Release sees a zero count
  146.  * the object destroys itself.
  147.  */
  148.  
  149. DWORD CObject2::AddRef(void)
  150.     {
  151.     return ++m_cRef;
  152.     }
  153.  
  154. DWORD CObject2::Release(void)
  155.     {
  156.     if (0!=--m_cRef)
  157.         return m_cRef;
  158.  
  159.     delete this;
  160.     return 0;
  161.     }
  162.  
  163.  
  164.  
  165.  
  166. //CObject2::CImpISampleOne interface implementation
  167.  
  168.  
  169. //Constructor/destructor inline in object2.h
  170.  
  171. /*
  172.  * CObject2::CImpISampleOne::QueryInterface
  173.  * CObject2::CImpISampleOne::AddRef
  174.  * CObject2::CImpISampleOne::Release
  175.  *
  176.  * IUnknown members that delegate to m_pObj
  177.  */
  178.  
  179. STDMETHODIMP CObject2::CImpISampleOne::QueryInterface(REFIID riid
  180.     , PPVOID ppv)
  181.     {
  182.     return m_pObj->QueryInterface(riid, ppv);
  183.     }
  184.  
  185. DWORD CObject2::CImpISampleOne::AddRef(void)
  186.     {
  187.     /*
  188.      * We maintain an "interface reference count" for debugging
  189.      * purposes, because the client of an object should match
  190.      * AddRef and Release calls through each interface pointer.
  191.      */
  192.     ++m_cRef;
  193.     return m_pObj->AddRef();
  194.     }
  195.  
  196. DWORD CObject2::CImpISampleOne::Release(void)
  197.     {
  198.     /*
  199.      * m_cRef is again only for debugging.  It doesn't affect
  200.      * CObject2 although the call to m_pObj->Release does.
  201.      */
  202.     --m_cRef;
  203.     return m_pObj->Release();
  204.     }
  205.  
  206.  
  207.  
  208. /*
  209.  * CObject2::CImpISampleOne::GetMessage
  210.  *
  211.  * Purpose:
  212.  *  Returns a string to the caller.
  213.  *
  214.  * Parameters:
  215.  *  psz             LPTSTR in which to store the string.
  216.  *  cch             UINT size of psz.
  217.  *
  218.  * Return Value:
  219.  *  HRESULT         NOERROR if the string is stored, E_OUTOFMEMORY
  220.  *                  if the buffer is too small.
  221.  */
  222.  
  223. STDMETHODIMP CObject2::CImpISampleOne::GetMessage(LPTSTR psz, UINT cch)
  224.     {
  225.     if (NULL==psz)
  226.         return ResultFromScode(E_POINTER);
  227.  
  228.     if (cch < (UINT)lstrlen(szMessage))
  229.         return ResultFromScode(E_OUTOFMEMORY);
  230.  
  231.     lstrcpy(psz, szMessage);
  232.     return NOERROR;
  233.     }
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241. //CObject2::CImpISampleTwo interface implementation
  242.  
  243.  
  244. //Constructor/destructor inline in object2.h
  245.  
  246. /*
  247.  * CObject2::CImpISampleTwo::QueryInterface
  248.  * CObject2::CImpISampleTwo::AddRef
  249.  * CObject2::CImpISampleTwo::Release
  250.  *
  251.  * IUnknown members that delegate to m_pObj
  252.  */
  253.  
  254. STDMETHODIMP CObject2::CImpISampleTwo::QueryInterface(REFIID riid
  255.     , PPVOID ppv)
  256.     {
  257.     return m_pObj->QueryInterface(riid, ppv);
  258.     }
  259.  
  260. DWORD CObject2::CImpISampleTwo::AddRef(void)
  261.     {
  262.     /*
  263.      * We maintain an "interface reference count" for debugging
  264.      * purposes, because the client of an object should match
  265.      * AddRef and Release calls through each interface pointer.
  266.      */
  267.     ++m_cRef;
  268.     return m_pObj->AddRef();
  269.     }
  270.  
  271. DWORD CObject2::CImpISampleTwo::Release(void)
  272.     {
  273.     /*
  274.      * m_cRef is again only for debugging.  It doesn't affect
  275.      * CObject2 although the call to m_pObj->Release does.
  276.      */
  277.     --m_cRef;
  278.     return m_pObj->Release();
  279.     }
  280.  
  281.  
  282.  
  283. /*
  284.  * CObject2::CImpISampleTwo::GetString
  285.  *
  286.  * Purpose:
  287.  *  Returns a string to the caller.
  288.  *
  289.  * Parameters:
  290.  *  psz             LPTSTR in which to store the string.
  291.  *  cch             UINT size of psz.
  292.  *
  293.  * Return Value:
  294.  *  HRESULT         NOERROR if the string is stored, E_OUTOFMEMORY
  295.  *                  if the buffer is too small.
  296.  */
  297.  
  298. STDMETHODIMP CObject2::CImpISampleTwo::GetString(LPTSTR psz, UINT cch)
  299.     {
  300.     if (NULL==psz)
  301.         return ResultFromScode(E_POINTER);
  302.  
  303.     if (cch < (UINT)lstrlen(szString))
  304.         return ResultFromScode(E_OUTOFMEMORY);
  305.  
  306.     lstrcpy(psz, szString);
  307.     return NOERROR;
  308.     }
  309.