122 lines
3.2 KiB
C++
122 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 ); // ref counting problem
|
|
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()
|
|
{
|
|
TraceAssert( 0 == m_cRefCount );
|
|
ULONG cRef = InterlockedDecrement(&m_cRefCount);
|
|
if ( 0 == cRef )
|
|
{
|
|
delete this;
|
|
}
|
|
return cRef;
|
|
}
|