windows-nt/Source/XPSP1/NT/printscan/ui/shellext/common/unknown.cpp
2020-09-26 16:20:57 +08:00

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;
}