138 lines
3.5 KiB
C++
138 lines
3.5 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1998 - 1999
|
|
//
|
|
// File: unknown.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
/*----------------------------------------------------------------------------
|
|
/ Title;
|
|
/ unknown.cpp
|
|
/
|
|
/ Authors;
|
|
/ David De Vorchik (daviddv)
|
|
/
|
|
/ Notes;
|
|
/ Helper functions for handling IUnknown
|
|
/----------------------------------------------------------------------------*/
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
/ CUnknown
|
|
/ Helper functions to aid the implementation of IUnknown within objects,
|
|
/ handles not only AddRef and Release, but also QueryInterface.
|
|
/----------------------------------------------------------------------------*/
|
|
|
|
LONG g_cRefCount = 0; // global reference count
|
|
|
|
CUnknown::CUnknown()
|
|
{
|
|
m_cRefCount = 1;
|
|
InterlockedIncrement(&g_cRefCount);
|
|
}
|
|
|
|
CUnknown::~CUnknown()
|
|
{
|
|
TraceAssert( m_cRefCount == 0 );
|
|
InterlockedDecrement(&g_cRefCount);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
/ CUnknown::HandleQueryInterface
|
|
/ ------------------------------
|
|
/ A table driven implementation of QueryInterface that scans through trying
|
|
/ to find a suitable match for the object.
|
|
/
|
|
/ In:
|
|
/ riid = interface being requested
|
|
/ ppvObject -> receives a pointer to the object
|
|
/ aIntefaces = array of interface descriptions
|
|
/ cif = number of interfaces in array
|
|
/
|
|
/ Out:
|
|
/ -
|
|
/----------------------------------------------------------------------------*/
|
|
STDMETHODIMP CUnknown::HandleQueryInterface(REFIID riid, LPVOID* ppvObject, LPINTERFACES aInterfaces, int cif)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int i;
|
|
|
|
TraceAssert(ppvObject);
|
|
TraceAssert(aInterfaces);
|
|
TraceAssert(cif);
|
|
|
|
if (ppvObject)
|
|
{
|
|
*ppvObject = NULL; // no interface yet
|
|
}
|
|
|
|
|
|
|
|
for ( i = 0; aInterfaces && ppvObject && (i != cif); i++ )
|
|
{
|
|
if ( IsEqualIID(riid, *aInterfaces[i].piid) || IsEqualIID(riid, IID_IUnknown) )
|
|
{
|
|
*ppvObject = aInterfaces[i].pvObject;
|
|
goto exit_gracefully;
|
|
}
|
|
}
|
|
|
|
hr = E_NOINTERFACE; // failed.
|
|
|
|
exit_gracefully:
|
|
|
|
if ( ppvObject && SUCCEEDED(hr) )
|
|
((LPUNKNOWN)*ppvObject)->AddRef();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
/ CUnknown::HandleAddRef
|
|
/ ----------------------
|
|
/ Increase the objects reference count. Global reference count increase
|
|
/ by the constructor.
|
|
/
|
|
/ In:
|
|
/ -
|
|
/ Out:
|
|
/ current reference count
|
|
/----------------------------------------------------------------------------*/
|
|
STDMETHODIMP_(ULONG) CUnknown::HandleAddRef()
|
|
{
|
|
return InterlockedIncrement(&m_cRefCount);
|
|
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
/ CUnknown::HandleRelease
|
|
/ -----------------------
|
|
/ Decrease the reference counts, when the objects reaches zero then
|
|
/ destroy it (which inturn will decrease the global reference count).
|
|
/
|
|
/ In:
|
|
/ -
|
|
/ Out:
|
|
/ current reference count == 0 if destroyed
|
|
/----------------------------------------------------------------------------*/
|
|
STDMETHODIMP_(ULONG) CUnknown::HandleRelease()
|
|
{
|
|
ULONG cRefCount;
|
|
|
|
cRefCount = InterlockedDecrement(&m_cRefCount);
|
|
|
|
if ( cRefCount )
|
|
return cRefCount;
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|