📄 unkimp.h
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
//
//
// Macro implementation of IUnknown
//
// Description:
// This file defines classes and Macro's to simplify the implementation
// of IUnknown in RMA objects.
// It also implements object creation methods
// (CreateObject, CreateInstance)
//
// Usage Tips:
//
// Never use the new operator to create a class instance!!
// Instead use CreateObject if you need to use non-interface
// methods and CreateInstance otherwise.
//
// Class(es) Defined in this file:
//
// CUnknownIMP
// The COM Object implementation must inherit from this class.
//
// CAggregateImpl
// Used internally to support Aggregation.
//
// Macros Defined in this file:
//
// DECLARE_UNKNOWN(THIS_CLASS)
// This must be in the class declaration.
//
// BEGIN_INTERFACE_LIST(THIS_CLASS)
// This must be in the class implementation.
//
// END_INTERFACE_LIST
// This must be in the class implementation.
//
// INTERFACE_LIST_ENTRY(INTERFACE_IID, INTERFACE_CLASS)
// Defines the QI of a locally implemented interface.
// Optional: if used must be in the class implementation.
//
// INTERFACE_LIST_ENTRY2(DERIVED_CLASS, BASE_INTERFACE_IID, BASE_CLASS)
// Defines the QI of a locally implemented interface that must be
// disambiguated. DERIVED_CLASS is the intermediate class used to
// achieve the disambiguation.
//
// INTERFACE_LIST_ENTRY_DELEGATE(INTERFACE_IID, DELEGATE_QI_FUNCTION)
// Defines the QI of a single interface supported by an aggregated
// object.
// Optional: if used must be in the class implementation.
//
// INTERFACE_LIST_ENTRY_DELEGATE_BLIND(DELEGATE_QI_FUNCTION)
// Defines the QI of all interfaces supported by an aggregated object.
// Optional: if used must be in the class implementation.
//
// INTERFACE_LIST_ENTRY_BASE
// Specifies a base class whose query interface function should be called.
//
// Example:
//
// rmabuffer.h
// #include <unkimp.h>
//
// class CHXBuffer
// : public CUnknownIMP
// , public IHXBuffer
// {
// DECLARE_UNKNOWN(CHXBuffer)
// public:
// STDMETHOD(FinalConstruct)();
// void FinalRelease();
//
// // List of IHXBuffer Methods..
//
// private:
// // List of private members..
// DECLARE_SMART_POINTER_UNKNOWN m_spunkOther;
// DECLARE_SMART_POINTER_UNKNOWN m_spunkYetAnother;
// };
//
// rmabuffer.cpp
// #include "rmabuffer.h"
//
// BEGIN_INTERFACE_LIST(CHXBuffer)
// INTERFACE_LIST_ENTRY(IID_IHXBuffer, IHXBuffer)
// INTERFACE_LIST_ENTRY_DELEGATE
// (
// IID_IHXOther,
// m_spunkOther.QueryInterface
// )
// INTERFACE_LIST_ENTRY_DELEGATE_BLIND
// (
// m_spunkYetAnother.QueryInterface
// )
// END_INTERFACE_LIST
//
// STDMETHODIMP CHXBuffer::FinalConstruct()
// {
// // Create the Aggregated objects here..
// //
// if
// (
// SUCCEEDED
// (
// CIHXOther::CreateInstance
// (
// GetControllingUnknown(),
// &m_spunkOther
// )
// )
// &&
// SUCCEEDED
// (
// CIHXYetAnother::CreateInstance
// (
// GetControllingUnknown(),
// &m_spunkYetAnother
// )
// )
// )
// {
// return HXR_OK;
// }
// return HXR_FAIL;
// }
//
// void CHXBuffer::FinalRelease()
// {
// // If we were not using SmartPointers, we would
// // release the Aggregated objects here.
// }
//
// // Implement IHXBuffer methods..
//
#ifndef __CUnknownIMP_H__
#define __CUnknownIMP_H__
#include "hxcom.h"
#include "hxassert.h"
#ifdef INCLUDE_DEBUG_LIFETIME
#include <io.h>
#include <fcntl.h>
#include "chxdataf.h"
#include "hxtrace.h"
#include "hxstring.h"
#endif // INCLUDE_DEBUG_LIFETIME
#ifdef ENABLE_UNKIMP_TRACKER
#include "ihxiunknowntracker.h"
#endif
class CUnknownIMP : public IUnknown
{
public:
CUnknownIMP() : m_lCount(0), m_punkOuter(NULL)
#ifdef INCLUDE_DEBUG_LIFETIME
,m_pRaFileDebugLifetime(NULL)
#endif
{
m_punkControlling = this;
}
virtual ~CUnknownIMP()
{}
/*
* IUnknown methods
*/
STDMETHOD(QueryInterface)
(
THIS_
REFIID riid,
void** ppvObj
)
{
if(m_punkOuter)
{
return m_punkOuter->QueryInterface(riid, ppvObj);
}
return _ActualQI(riid, ppvObj);
}
STDMETHOD_(ULONG32,AddRef) (THIS)
{
if(m_punkOuter)
{
return m_punkOuter->AddRef();
}
return ActualAddRef();
}
STDMETHOD_(ULONG32,Release) (THIS)
{
if(m_punkOuter)
{
return m_punkOuter->Release();
}
return ActualRelease();
}
const IUnknown* GetUnknown() const
{
return this;
}
IUnknown* GetUnknown()
{
return this;
}
IUnknown* GetControllingUnknown()
{
return m_punkControlling;
}
STDMETHOD(SetupAggregation)( IUnknown* pvOuterObj, IUnknown** pvResult );
#ifdef ENABLE_UNKIMP_TRACKER
static void SetIUnknownTracker( IHXIUnknownTracker* pIUnknownTracker )
{
if (pIUnknownTracker != ms_pIUnknownTracker)
{
if (ms_pIUnknownTracker)
{
IHXIUnknownTracker* pIOldUnknownTracker = ms_pIUnknownTracker;
ms_pIUnknownTracker = NULL;
HX_RELEASE(pIOldUnknownTracker);
}
if (pIUnknownTracker)
{
pIUnknownTracker->AddRef();
ms_pIUnknownTracker = pIUnknownTracker;
}
}
}
#endif
protected:
// This is overriden in the derived object to provide
// an object specific imp.
STDMETHOD(_ActualQI)(REFIID riid, void** ppvObj) PURE;
#ifdef INCLUDE_DEBUG_LIFETIME
CHXDataFile* m_pRaFileDebugLifetime;
CHXString m_StringFilename;
void InitFilename(const char* pFilename)
{
m_StringFilename = pFilename;
}
STDMETHOD_(ULONG32,ActualAddRef) ()
{
if (m_pRaFileDebugLifetime)
{
char buf[80]; /* Flawfinder: ignore */
sprintf(buf, "*** AddRef %d ***\r\n", m_lCount+1); /* Flawfinder: ignore */
m_pRaFileDebugLifetime->Write(buf, strlen(buf));
UINT32* pBinaryStackTrace = NULL;
if (GetStack(&pBinaryStackTrace))
{
char* pCharStackTrace = NULL;
if (GetStackSymbols(pBinaryStackTrace, &pCharStackTrace))
{
m_pRaFileDebugLifetime->Write
(
pCharStackTrace,
strlen(pCharStackTrace)
);
}
HX_VECTOR_DELETE(pCharStackTrace);
}
HX_VECTOR_DELETE(pBinaryStackTrace);
}
return InterlockedIncrement(&m_lCount);
}
STDMETHOD_(ULONG32,ActualRelease) ()
{
if (m_pRaFileDebugLifetime)
{
char buf[80]; /* Flawfinder: ignore */
sprintf(buf, "*** Release %d ***\r\n", m_lCount-1); /* Flawfinder: ignore */
m_pRaFileDebugLifetime->Write(buf, strlen(buf));
UINT32* pBinaryStackTrace = NULL;
if (GetStack(&pBinaryStackTrace))
{
char* pCharStackTrace = NULL;
if (GetStackSymbols(pBinaryStackTrace, &pCharStackTrace))
{
m_pRaFileDebugLifetime->Write
(
pCharStackTrace,
strlen(pCharStackTrace)
);
}
HX_VECTOR_DELETE(pCharStackTrace);
}
HX_VECTOR_DELETE(pBinaryStackTrace);
}
HX_ASSERT(m_lCount>0);
if (InterlockedDecrement(&m_lCount) > 0)
{
return m_lCount;
}
FinalRelease();
delete this;
return 0;
}
STDMETHOD(FinalConstruct)()
{
if (m_StringFilename.IsEmpty())
{
return HXR_OK;
}
char szTemp[32]; /* Flawfinder: ignore */
m_StringFilename.GetBuffer(0)[4] = '\0';
m_StringFilename.ReleaseBuffer();
ltoa((UINT32)this, szTemp, 16);
m_StringFilename += szTemp;
m_StringFilename.GetBuffer(0)[8] = '.';
if (m_StringFilename.GetLength() > 12)
{ \
m_StringFilename.GetBuffer(0)[11] = '\0';
m_StringFilename.ReleaseBuffer();
} \
m_pRaFileDebugLifetime = CHXDataFile::Construct();
m_pRaFileDebugLifetime->Open(m_StringFilename, _O_CREAT | _O_RDWR);
m_pRaFileDebugLifetime->Write
(
"*** Created new class instance ***\r\n",
sizeof("*** Created new class instance ***\r\n")
);
UINT32* pBinaryStackTrace = NULL;
if (GetStack(&pBinaryStackTrace))
{
char* pCharStackTrace = NULL;
if (GetStackSymbols(pBinaryStackTrace, &pCharStackTrace))
{
m_pRaFileDebugLifetime->Write
(
pCharStackTrace,
strlen(pCharStackTrace)
);
}
HX_VECTOR_DELETE(pCharStackTrace);
}
HX_VECTOR_DELETE(pBinaryStackTrace);
return HXR_OK;
}
virtual void FinalRelease()
{
if (m_pRaFileDebugLifetime)
{
m_pRaFileDebugLifetime->Write("*** Deleted ***\r\n", 17);
UINT32* pBinaryStackTrace = NULL;
if (GetStack(&pBinaryStackTrace))
{
char* pCharStackTrace = NULL;
if (GetStackSymbols(pBinaryStackTrace, &pCharStackTrace))
{
m_pRaFileDebugLifetime->Write
(
pCharStackTrace,
strlen(pCharStackTrace)
);
}
HX_VECTOR_DELETE(pCharStackTrace);
}
HX_VECTOR_DELETE(pBinaryStackTrace);
m_pRaFileDebugLifetime->Close();
}
HX_DELETE(m_pRaFileDebugLifetime);
}
#else
// These can be overriden in the derived object to provide
// an object specific imp.
STDMETHOD_(ULONG32,ActualAddRef) (THIS)
{
#ifdef ENABLE_UNKIMP_TRACKER
ULONG32 postAddRefRefCount = InterlockedIncrement(&m_lCount);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -