125 lines
3.2 KiB
C++
125 lines
3.2 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
||
|
//
|
||
|
// File: unknown.cpp
|
||
|
//
|
||
|
// Helper functions for handling IUnknown
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include "pch.h"
|
||
|
#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 = 0;
|
||
|
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);
|
||
|
|
||
|
*ppvObject = NULL; // no interface yet
|
||
|
|
||
|
for ( i = 0; 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 ( 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;
|
||
|
}
|