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 / object1.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  8KB  |  395 lines

  1. /*
  2.  * OBJECT1.CPP
  3.  *
  4.  * Object implementation using interface implementations.
  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.  * CreateObject1
  24.  *
  25.  * Purpose:
  26.  *  Creates an instance of CObject1 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 CreateObject1(IUnknown **ppUnk)
  39.     {
  40.     HRESULT     hr;
  41.     CObject1   *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 CObject1();
  48.  
  49.     if (NULL==pObj)
  50.         return FALSE;
  51.  
  52.     if (!pObj->Init())
  53.         return FALSE;
  54.  
  55.     /*
  56.      * Now get the IUnknown interface to this object and make
  57.      * sure that it's reference count is correct.  We could either
  58.      * typecast pObj to IUnknown and call AddRef explicitly, or
  59.      * we can simply call pObj->QueryInterface and let it do the
  60.      * typecast and the AddRef for us.
  61.      */
  62.     hr=pObj->QueryInterface(IID_IUnknown, (PPVOID)ppUnk);
  63.     return SUCCEEDED(hr);
  64.     }
  65.  
  66.  
  67.  
  68.  
  69.  
  70. /*
  71.  * CObject1::CObject1
  72.  * CObject1::~CObject1
  73.  *
  74.  * Constructor Parameters:
  75.  *  None
  76.  */
  77.  
  78. CObject1::CObject1(void)
  79.     {
  80.     m_cRef=0;
  81.  
  82.     m_pImpISampleOne=NULL;
  83.     m_pImpISampleTwo=NULL;
  84.  
  85.     return;
  86.     }
  87.  
  88. CObject1::~CObject1(void)
  89.     {
  90.     //Delete the interface implementations created in Init
  91.     DeleteInterfaceImp(m_pImpISampleTwo);
  92.     DeleteInterfaceImp(m_pImpISampleOne);
  93.     return;
  94.     }
  95.  
  96.  
  97.  
  98. /*
  99.  * CObject1::Init
  100.  *
  101.  * Purpose:
  102.  *  Instantiates the interface implementations for this object.
  103.  *
  104.  * Parameters:
  105.  *  None
  106.  *
  107.  * Return Value:
  108.  *  BOOL            TRUE if initialization succeeds, FALSE otherwise.
  109.  */
  110.  
  111. BOOL CObject1::Init(void)
  112.     {
  113.     /*
  114.      * Creating the interfaces means creating instances of
  115.      * the interface implementation classes.  The constructor
  116.      * parameters is a pointer to CObject1 that has the
  117.      * IUnknown functions to which the interface implementations
  118.      * delegate.
  119.      */
  120.  
  121.     m_pImpISampleOne=new CImpISampleOne(this);
  122.  
  123.     if (NULL==m_pImpISampleOne)
  124.         return FALSE;
  125.  
  126.     m_pImpISampleTwo=new CImpISampleTwo(this);
  127.  
  128.     if (NULL==m_pImpISampleTwo)
  129.         return FALSE;
  130.  
  131.     return TRUE;
  132.     }
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139. /*
  140.  * CObject1::QueryInterface
  141.  *
  142.  * Purpose:
  143.  *  Manages the interfaces for this object which supports the
  144.  *  IUnknown, ISampleOne, and ISampleTwo interfaces.
  145.  *
  146.  * Parameters:
  147.  *  riid            REFIID of the interface to return.
  148.  *  ppv             PPVOID in which to store the pointer.
  149.  *
  150.  * Return Value:
  151.  *  HRESULT         NOERROR on success, E_NOINTERFACE if the
  152.  *                  interface is not supported.
  153.  */
  154.  
  155. STDMETHODIMP CObject1::QueryInterface(REFIID riid, PPVOID ppv)
  156.     {
  157.     //Always NULL the out-parameters
  158.     *ppv=NULL;
  159.  
  160.     /*
  161.      * IUnknown comes from CObject1.  Note that here and in
  162.      * the lines below we do not need to explicitly typecast
  163.      * the object pointers into interface pointers because
  164.      * the vtables are identical.  If we had additional virtual
  165.      * member functions in the object, we would have to cast
  166.      * in order to set the right vtable.  This is demonstrated
  167.      * in the multiple-inheritance version, CObject3.
  168.      */
  169.     if (IID_IUnknown==riid)
  170.         *ppv=this;
  171.  
  172.     //Other interfaces come from interface implementations
  173.     if (IID_ISampleOne==riid)
  174.         *ppv=m_pImpISampleOne;
  175.  
  176.     if (IID_ISampleTwo==riid)
  177.         *ppv=m_pImpISampleTwo;
  178.  
  179.     if (NULL==*ppv)
  180.         return ResultFromScode(E_NOINTERFACE);
  181.  
  182.     //AddRef any interface we'll return.
  183.     ((LPUNKNOWN)*ppv)->AddRef();
  184.     return NOERROR;
  185.     }
  186.  
  187.  
  188.  
  189. /*
  190.  * CObject1::AddRef
  191.  * CObject1::Release
  192.  *
  193.  * Reference counting members.  When Release sees a zero count
  194.  * the object destroys itself.
  195.  */
  196.  
  197. DWORD CObject1::AddRef(void)
  198.     {
  199.     return ++m_cRef;
  200.     }
  201.  
  202. DWORD CObject1::Release(void)
  203.     {
  204.     if (0!=--m_cRef)
  205.         return m_cRef;
  206.  
  207.     delete this;
  208.     return 0;
  209.     }
  210.  
  211.  
  212.  
  213.  
  214. //CImpISampleOne interface implementation
  215.  
  216.  
  217. /*
  218.  * CImpISampleOne::CImpISampleOne
  219.  * CImpISampleOne::~CImpISampleOne
  220.  *
  221.  * Constructor Parameters:
  222.  *  pObj            PCObject1 to the outer object
  223.  */
  224.  
  225. CImpISampleOne::CImpISampleOne(PCObject1 pObj)
  226.     {
  227.     m_cRef=0;
  228.     m_pObj=pObj;
  229.     return;
  230.     }
  231.  
  232. CImpISampleOne::~CImpISampleOne(void)
  233.     {
  234.     return;
  235.     }
  236.  
  237.  
  238.  
  239. /*
  240.  * CImpISampleOne::QueryInterface
  241.  * CImpISampleOne::AddRef
  242.  * CImpISampleOne::Release
  243.  *
  244.  * IUnknown members that delegate to m_pObj
  245.  */
  246.  
  247. STDMETHODIMP CImpISampleOne::QueryInterface(REFIID riid, PPVOID ppv)
  248.     {
  249.     return m_pObj->QueryInterface(riid, ppv);
  250.     }
  251.  
  252. DWORD CImpISampleOne::AddRef(void)
  253.     {
  254.     /*
  255.      * We maintain an "interface reference count" for debugging
  256.      * purposes, because the client of an object should match
  257.      * AddRef and Release calls through each interface pointer.
  258.      */
  259.     ++m_cRef;
  260.     return m_pObj->AddRef();
  261.     }
  262.  
  263. DWORD CImpISampleOne::Release(void)
  264.     {
  265.     /*
  266.      * m_cRef is again only for debugging.  It doesn't affect
  267.      * CObject1 although the call to m_pObj->Release does.
  268.      */
  269.     --m_cRef;
  270.     return m_pObj->Release();
  271.     }
  272.  
  273.  
  274.  
  275. /*
  276.  * CImpISampleOne::GetMessage
  277.  *
  278.  * Purpose:
  279.  *  Returns a string to the caller.
  280.  *
  281.  * Parameters:
  282.  *  psz             LPTSTR in which to store the string.
  283.  *  cch             UINT size of psz.
  284.  *
  285.  * Return Value:
  286.  *  HRESULT         NOERROR if the string is stored, E_OUTOFMEMORY
  287.  *                  if the buffer is too small.
  288.  */
  289.  
  290. STDMETHODIMP CImpISampleOne::GetMessage(LPTSTR psz, UINT cch)
  291.     {
  292.     if (NULL==psz)
  293.         return ResultFromScode(E_POINTER);
  294.  
  295.     if (cch < (UINT)lstrlen(szMessage))
  296.         return ResultFromScode(E_OUTOFMEMORY);
  297.  
  298.     lstrcpy(psz, szMessage);
  299.     return NOERROR;
  300.     }
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308. //CImpISampleTwo interface implementation
  309.  
  310.  
  311. /*
  312.  * CImpISampleTwo::CImpISampleTwo
  313.  * CImpISampleTwo::~CImpISampleTwo
  314.  *
  315.  * Constructor Parameters:
  316.  *  pObj            PCObject1 to the outer object
  317.  */
  318.  
  319. CImpISampleTwo::CImpISampleTwo(PCObject1 pObj)
  320.     {
  321.     m_cRef=0;
  322.     m_pObj=pObj;
  323.     return;
  324.     }
  325.  
  326. CImpISampleTwo::~CImpISampleTwo(void)
  327.     {
  328.     return;
  329.     }
  330.  
  331.  
  332.  
  333. /*
  334.  * CImpISampleTwo::QueryInterface
  335.  * CImpISampleTwo::AddRef
  336.  * CImpISampleTwo::Release
  337.  *
  338.  * IUnknown members that delegate to m_pObj
  339.  */
  340.  
  341. STDMETHODIMP CImpISampleTwo::QueryInterface(REFIID riid, PPVOID ppv)
  342.     {
  343.     return m_pObj->QueryInterface(riid, ppv);
  344.     }
  345.  
  346. DWORD CImpISampleTwo::AddRef(void)
  347.     {
  348.     /*
  349.      * We maintain an "interface reference count" for debugging
  350.      * purposes, because the client of an object should match
  351.      * AddRef and Release calls through each interface pointer.
  352.      */
  353.     ++m_cRef;
  354.     return m_pObj->AddRef();
  355.     }
  356.  
  357. DWORD CImpISampleTwo::Release(void)
  358.     {
  359.     /*
  360.      * m_cRef is again only for debugging.  It doesn't affect
  361.      * CObject1 although the call to m_pObj->Release does.
  362.      */
  363.     --m_cRef;
  364.     return m_pObj->Release();
  365.     }
  366.  
  367.  
  368.  
  369. /*
  370.  * CImpISampleTwo::GetString
  371.  *
  372.  * Purpose:
  373.  *  Returns a string to the caller.
  374.  *
  375.  * Parameters:
  376.  *  psz             LPTSTR in which to store the string.
  377.  *  cch             UINT size of psz.
  378.  *
  379.  * Return Value:
  380.  *  HRESULT         NOERROR if the string is stored, E_OUTOFMEMORY
  381.  *                  if the buffer is too small.
  382.  */
  383.  
  384. STDMETHODIMP CImpISampleTwo::GetString(LPTSTR psz, UINT cch)
  385.     {
  386.     if (NULL==psz)
  387.         return ResultFromScode(E_POINTER);
  388.  
  389.     if (cch < (UINT)lstrlen(szString))
  390.         return ResultFromScode(E_OUTOFMEMORY);
  391.  
  392.     lstrcpy(psz, szString);
  393.     return NOERROR;
  394.     }
  395.