unknown.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 4k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*----------------------------------------------------------------------------
  2. / Title;
  3. /   unknown.cpp
  4. /
  5. / Authors;
  6. /   David De Vorchik (daviddv)
  7. /
  8. / Notes;
  9. /   Helper functions for handling IUnknown
  10. /----------------------------------------------------------------------------*/
  11. #include "pch.h"
  12. #include "cfdefs.h"
  13. #pragma hdrstop
  14. /*-----------------------------------------------------------------------------
  15. / CUnknown
  16. /   Helper functions to aid the implementation of IUnknown within objects,
  17. /   handles not only AddRef and Release, but also QueryInterface.
  18. /----------------------------------------------------------------------------*/
  19. LONG g_cRefCount = 0;          // global reference count
  20. CUnknown::CUnknown() :
  21.     m_cRefCount(1)
  22. {
  23.     InterlockedIncrement(&g_cRefCount);
  24. }
  25. CUnknown::~CUnknown()
  26. {
  27.     InterlockedDecrement(&g_cRefCount);
  28. }
  29. STDMETHODIMP CUnknown::HandleQueryInterface(REFIID riid, LPVOID* ppvObject, LPINTERFACES aInterfaces, int cif)
  30. {
  31.     HRESULT hr = S_OK;
  32.     int i;
  33.     TraceAssert(ppvObject);
  34.     TraceAssert(aInterfaces);
  35.     TraceAssert(cif);
  36.     if ( !ppvObject )
  37.         ExitGracefully(hr, E_INVALIDARG, "Bailing because ppvObject == NULL");
  38.     *ppvObject = NULL;                                              // no interface yet
  39.     for ( i = 0; i != cif; i++ )
  40.     {
  41.         if ( IsEqualIID(riid, *aInterfaces[i].piid) || IsEqualIID(riid, IID_IUnknown) )
  42.         {
  43.             *ppvObject = aInterfaces[i].pvObject;
  44.             goto exit_gracefully;
  45.         }
  46.     }
  47.     hr = E_NOINTERFACE;         // failed.
  48. exit_gracefully:
  49.     if ( SUCCEEDED(hr) )
  50.         ((LPUNKNOWN)*ppvObject)->AddRef();
  51.     return hr;
  52. }
  53. STDMETHODIMP_(ULONG) CUnknown::HandleAddRef()
  54. {
  55.     return InterlockedIncrement(&m_cRefCount);
  56. }
  57. STDMETHODIMP_(ULONG) CUnknown::HandleRelease()
  58. {
  59.     ULONG cRefCount; 
  60.     cRefCount = InterlockedDecrement(&m_cRefCount);
  61.         
  62.     if ( cRefCount )
  63.         return cRefCount;
  64.     delete this;    
  65.     return 0;
  66. }
  67. /*-----------------------------------------------------------------------------
  68. / Static class factory - from browseui
  69. /----------------------------------------------------------------------------*/
  70. STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
  71. {
  72.     if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  73.     {
  74.         *ppvObj = (void *)GET_ICLASSFACTORY(this);
  75.         InterlockedIncrement(&g_cRefCount);
  76.         return NOERROR;
  77.     }
  78.     *ppvObj = NULL;
  79.     return E_NOINTERFACE;
  80. }
  81. STDMETHODIMP_(ULONG) CClassFactory::AddRef()
  82. {
  83.     InterlockedIncrement(&g_cRefCount);
  84.     return 2;
  85. }
  86. STDMETHODIMP_(ULONG) CClassFactory::Release()
  87. {
  88.     InterlockedDecrement(&g_cRefCount);
  89.     return 1;
  90. }
  91. STDMETHODIMP CClassFactory::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
  92. {
  93.     *ppv = NULL;
  94.     if (punkOuter && !IsEqualIID(riid, IID_IUnknown))
  95.     {
  96.         // It is technically illegal to aggregate an object and request
  97.         // any interface other than IUnknown. Enforce this.
  98.         //
  99.         return CLASS_E_NOAGGREGATION;
  100.     }
  101.     else
  102.     {
  103.         LPOBJECTINFO pthisobj = (LPOBJECTINFO)this;
  104.         if ( punkOuter )
  105.             return CLASS_E_NOAGGREGATION;
  106.         IUnknown *punk;
  107.         HRESULT hres = pthisobj->pfnCreateInstance(punkOuter, &punk, pthisobj);
  108.         if (SUCCEEDED(hres))
  109.         {
  110.             hres = punk->QueryInterface(riid, ppv);
  111.             punk->Release();
  112.         }
  113.         return hres;
  114.     }
  115. }
  116. STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
  117. {
  118.     if (fLock)
  119.         InterlockedIncrement(&g_cRefCount);
  120.     else
  121.         InterlockedDecrement(&g_cRefCount);
  122.     return S_OK;
  123. }