|
|
//============================================================================
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: std.h
//
// History:
//
// 03/15/97 Kenn Takara Created.
//
// Declarations for some common code/macros.
//============================================================================
#ifndef _STD_H_
#define _STD_H_
#if _MSC_VER >= 1000 // VC 5.0 or later
#pragma once
#endif
#ifndef _DBGUTIL_H
#include "dbgutil.h"
#endif
#include "malloc.h"
#ifndef TFSCORE_API
#define TFSCORE_API(type) __declspec( dllexport ) type FAR PASCAL
#define TFSCORE_APIV(type) __declspec( dllexport ) type FAR CDECL
#endif
#define hrOK HRESULT(0)
#define hrTrue HRESULT(0)
#define hrFalse ResultFromScode(S_FALSE)
#define hrFail ResultFromScode(E_FAIL)
#define hrNotImpl ResultFromScode(E_NOTIMPL)
#define hrNoInterface ResultFromScode(E_NOINTERFACE)
#define hrNoMem ResultFromScode(E_OUTOFMEMORY)
#define OffsetOf(s,m) (size_t)( (char *)&(((s *)0)->m) - (char *)0 )
#define EmbeddorOf(C,m,p) ((C *)(((char *)p) - OffsetOf(C,m)))
#define DimensionOf(rgx) (sizeof((rgx)) / sizeof(*(rgx)))
/*!--------------------------------------------------------------------------
DeclareSP, DeclareSPBasic DeclareSRG, DeclareSRGBasic DeclareSPT, DeclareSPTBasic DeclareSPM, DeclareSPMBasic
These macros declare 'smart' pointers. Smart pointers behave like normal pointers with the exception that a smart pointer destructor frees the thing it is pointing at and assignment to a non-null smart pointer is not allowed.
The DeclareSxx macros differ by how the generated smart pointer frees the memory:
Macro Free Smart Pointer Type ====================== ============ ================== DeclareSP(TAG, Type) delete p; SPTAG DeclareSRG(TAG, Type) delete [] p; SRGTAG DeclareSPT(TAG, Type) TMemFree(p); SPTTAG DeclareSPM(TAG, Type) MMemFree(p); SPMTAG
NOTE: use the 'Basic' variants (DeclareSPBasic, etc) for pointer to non-struct types (e.g. char, int, etc). Smart pointers have two methods:
void SPTAG::Free() Free and then null the internally maintained pointer.
Type *SPTAG::Transfer() Transfers pointer ownership to caller. The internally maintained pointer is cleared on exit.
Author: GaryBu ---------------------------------------------------------------------------*/
#define DeclareSP(TAG,Type) DeclareSmartPointer(SP##TAG,Type,delete m_p)
#define DeclareSRG(TAG,Type) DeclareSmartPointer(SRG##TAG,Type,delete [] m_p)
#define DeclareSPT(TAG,Type) DeclareSmartPointer(SPT##TAG,Type,TMemFree(m_p))
#define DeclareSPM(TAG,Type) DeclareSmartPointer(SPM##TAG,Type,MMemFree(m_p))
#define DeclareSPBasic(TAG,Type)\
DeclareSPPrivateBasic(SP##TAG,Type, delete m_p) #define DeclareSRGBasic(TAG,Type)\
DeclareSPPrivateBasic(SRG##TAG,Type, delete [] m_p) #define DeclareSPTBasic(TAG,Type)\
DeclareSPPrivateBasic(SPT##TAG,Type,TMemFree(m_p)) #define DeclareSPMBasic(TAG,Type)\
DeclareSPPrivateBasic(SPM##TAG,Type,MMemFree(m_p))
#define DeclareSPPrivateCore(klass, Type, free)\
class klass \ {\ public:\ klass() { m_p = 0; }\ klass(Type *p) { m_p = p; }\ ~klass() { free; }\ operator Type*() const { return m_p; }\ Type &operator*() const { return *m_p; }\ Type &operator[](int i) const { return m_p[i]; }\ Type &nth(int i) const { return m_p[i]; }\ Type **operator &() { Assert(!m_p); return &m_p; }\ Type *operator=(Type *p){ Assert(!m_p); return m_p = p; }\ Type *Transfer() { Type *p = m_p; m_p = 0; return p; }\ void Free() { free; m_p = 0; }\ private:\ void *operator=(const klass &);\ klass(const klass &);\ Type *m_p;
#define DeclareSPPrivateBasic(klass, Type, free)\
DeclareSPPrivateCore(klass, Type, free)\ };
/*!--------------------------------------------------------------------------
DeclareSPBasicEx Variant of smart pointers that allows an extra member variable.
The klassFree parameter lets you supply an alias for Free(). An example is IPropertyAccess and StdRowEditingTable:
DeclareSPPrivateBasicEx(SPIPropertyAccess,IPropertyAccess, m_pex->ReleaseContext(m_p), StdRowEditingTable, ReleaseContext)
SPIPropertyAccess sppac(pstdtable); sppac = pstdtable->GetContext(0); ...use spfc... sppac.ReleaseContext();
Author: KennT ---------------------------------------------------------------------------*/ #define DeclareSPBasicEx(klass, Type, free, klassEx, klassFree)\
DeclareSPPrivateCore(klass, Type, free)\ public:\ klass(klassEx *pex) \ {\ m_p = 0; m_pex=pex; } \ void klassFree() \ { Free(); } \ private:\ klassEx *m_pex; \ };
#define DeclareSmartPointer(klass, Type, free)\
DeclareSPPrivateCore(klass, Type, free)\ public:\ Type * operator->() const { return m_p; }\ };
TFSCORE_API(HRESULT) HrQueryInterface(IUnknown *punk, REFIID iid, LPVOID *ppv);
template <class T, const IID *piid> class ComSmartPointer { public: typedef T _PtrClass; ComSmartPointer() {p=NULL;} ~ComSmartPointer() { Release(); } // set p to NULL before releasing, this fixes a subtle bug
// A has a ptr to B, B has a ptr to A
// A gets told to release B
// A calls spB.Release();
// in spB.Release(), B gets destructed and calls spA.Release()
// in spA.Release(), A gets destructed and calls spB.Release()
// since the ptr in spB has not been set to NULL (which is bad
// since B has already gone away).
void Release() {T* pTemp = p; if (p) { p=NULL; pTemp->Release(); }} operator T*() {return (T*)p;} T& operator*() {Assert(p!=NULL); return *p; } T** operator&() { Assert(p==NULL); return &p; } T* operator->() { Assert(p!=NULL); return p; } T* operator=(T* lp){ Release(); p = lp; return p;} T* operator=(const ComSmartPointer<T,piid>& lp) { if (p) p->Release(); p = lp.p; return p; } void Set(T* lp) { Release(); p = lp; if (p) p->AddRef(); } T * Transfer() { T* pTemp=p; p=NULL; return pTemp; } BOOL operator!(){return (p == NULL) ? TRUE : FALSE;} void Query(IUnknown *punk) { HrQuery(punk); } HRESULT HrQuery(IUnknown *punk) { return ::HrQueryInterface(punk, *piid, (LPVOID *) &p); } T* p;
private: // These methods should NEVER get called.
ComSmartPointer(T* lp); ComSmartPointer(const ComSmartPointer<T,piid>& lp); };
// Interface utilities
TFSCORE_API(void) SetI(IUnknown * volatile *punkL, IUnknown *punkR); TFSCORE_API(void) ReleaseI(IUnknown *punk);
// Utilities for dealing with embedded classes
#define DeclareEmbeddedInterface(interface, base) \
class E##interface : public interface \ { \ public: \ Declare##base##Members(IMPL) \ Declare##interface##Members(IMPL) \ } m_##interface; \ friend class E##interface;
#define ImplementEmbeddedUnknown(embeddor, interface) \
STDMETHODIMP embeddor::E##interface::QueryInterface(REFIID iid,void **ppv)\ { \ return EmbeddorOf(embeddor,m_##interface,this)->QueryInterface(iid,ppv);\ } \ STDMETHODIMP_(ULONG) embeddor::E##interface::AddRef() \ { \ return EmbeddorOf(embeddor, m_##interface, this)->AddRef(); \ } \ STDMETHODIMP_(ULONG) embeddor::E##interface::Release() \ { \ return EmbeddorOf(embeddor, m_##interface, this)->Release(); \ }
#define ImplementEmbeddedUnknownNoRefCount(embeddor, interface) \
STDMETHODIMP embeddor::E##interface::QueryInterface(REFIID iid,void **ppv)\ { \ return EmbeddorOf(embeddor,m_##interface,this)->QueryInterface(iid,ppv);\ }
#define EMPrologIsolated(embeddor, interface, method) \
embeddor *pThis = EmbeddorOf(embeddor, m_##interface, this);
#define ImplementIsolatedUnknown(embeddor, interface) \
STDMETHODIMP embeddor::E##interface::QueryInterface(REFIID iid,void **ppv)\ { \ EMPrologIsolated(embeddor, interface, QueryInterface); \ Assert(!FHrSucceeded(pThis->QueryInterface(IID_##interface, ppv))); \ *ppv = 0; \ if (iid == IID_IUnknown) *ppv = (IUnknown *) this; \ else if (iid == IID_##interface) *ppv = (interface *) this; \ else return ResultFromScode(E_NOINTERFACE); \ ((IUnknown *) *ppv)->AddRef(); \ return HRESULT_OK; \ } \ STDMETHODIMP_(ULONG) embeddor::E##interface::AddRef() \ { \ EMPrologIsolated(embeddor, interface, AddRef) \ return 1; \ } \ STDMETHODIMP_(ULONG) embeddor::E##interface::Release() \ { \ EMPrologIsolated(embeddor, interface, Release) \ return 1; \ }
#define InitPThis(embeddor, object)\
embeddor *pThis = EmbeddorOf(embeddor, m_##object, this);\
/*---------------------------------------------------------------------------
Implements the controlling IUnknown interface for the inner object of an aggregation. ---------------------------------------------------------------------------*/ #define IMPLEMENT_AGGREGATION_IUNKNOWN(klass) \
STDMETHODIMP_(ULONG) klass::AddRef() \ { \ Assert(m_pUnknownOuter); \ return m_pUnknownOuter->AddRef(); \ } \ STDMETHODIMP_(ULONG) klass::Release() \ { \ Assert(m_pUnknownOuter); \ return m_pUnknownOuter->Release(); \ } \ STDMETHODIMP klass::QueryInterface(REFIID riid, LPVOID *ppv) \ { \ Assert(m_pUnknownOuter); \ return m_pUnknownOuter->QueryInterface(riid, ppv); \ } \
/*---------------------------------------------------------------------------
Declares the non-delegating IUnknown implementation in a class. ---------------------------------------------------------------------------*/ #define DECLARE_AGGREGATION_NONDELEGATING_IUNKNOWN(klass) \
class ENonDelegatingIUnknown : public IUnknown \ { \ public: \ DeclareIUnknownMembers(IMPL) \ } m_ENonDelegatingIUnknown; \ friend class ENonDelegatingIUnknown; \ IUnknown *m_pUnknownOuter; \
/*---------------------------------------------------------------------------
Implements the non-delegating IUnknown for a class. ---------------------------------------------------------------------------*/ #define IMPLEMENT_AGGREGATION_NONDELEGATING_ADDREFRELEASE(klass,interface) \
STDMETHODIMP_(ULONG) klass::ENonDelegatingIUnknown::AddRef() \ { \ InitPThis(klass, ENonDelegatingIUnknown); \ return InterlockedIncrement(&(pThis->m_cRef)); \ } \ STDMETHODIMP_(ULONG) klass::ENonDelegatingIUnknown::Release() \ { \ InitPThis(klass, ENonDelegatingIUnknown); \ if (0 == InterlockedDecrement(&(pThis->m_cRef))) \ { \ delete pThis; \ return 0; \ } \ return pThis->m_cRef; \ } \
#define IMPLEMENT_AGGREGATION_NONDELEGATING_IUNKNOWN(klass,interface) \
IMPLEMENT_AGGREGATION_NONDELEGATING_ADDREFRELEASE(klass,interface) \ STDMETHODIMP klass::ENonDelegatingIUnknown::QueryInterface(REFIID riid, LPVOID *ppv) \ { \ InitPThis(klass, ENonDelegatingIUnknown); \ if (ppv == NULL) \ return E_INVALIDARG; \ *ppv = NULL; \ if (riid == IID_IUnknown) \ *ppv = (IUnknown *) this; \ else if (riid == IID_##interface) \ *ppv = (interface *) pThis; \ else \ return E_NOINTERFACE; \ ((IUnknown *)*ppv)->AddRef(); \ return hrOK; \ } \
/*---------------------------------------------------------------------------
Standard TRY/CATCH wrappers for the COM interfaces ---------------------------------------------------------------------------*/
#define COM_PROTECT_TRY \
try
#define COM_PROTECT_ERROR_LABEL Error: ;\
#ifdef DEBUG
#define COM_PROTECT_CATCH \
catch(CException *pe) \ { \ hr = COleException::Process(pe); \ } \ catch(...) \ { \ hr = E_FAIL; \ } #else
#define COM_PROTECT_CATCH \
catch(CException *pe) \ { \ hr = COleException::Process(pe); \ } \ catch(...) \ { \ hr = E_FAIL; \ } #endif
/*---------------------------------------------------------------------------
Some useful smart pointers ---------------------------------------------------------------------------*/ DeclareSPPrivateBasic(SPSZ, TCHAR, delete[] m_p); DeclareSPPrivateBasic(SPWSZ, WCHAR, delete[] m_p); DeclareSPPrivateBasic(SPASZ, char, delete[] m_p); DeclareSPPrivateBasic(SPBYTE, BYTE, delete m_p);
typedef ComSmartPointer<IUnknown, &IID_IUnknown> SPIUnknown; typedef ComSmartPointer<IStream, &IID_IStream> SPIStream; typedef ComSmartPointer<IPersistStreamInit, &IID_IPersistStreamInit> SPIPersistStreamInit;
#endif // _STD_H_
|