You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
12 KiB
393 lines
12 KiB
//============================================================================
|
|
// 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_
|