|
|
// This is a part of the Active Template Library.
// Copyright (C) 1996-1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
#ifndef __ATLBASE_H__
#define __ATLBASE_H__
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#ifdef _UNICODE
#ifndef UNICODE
#define UNICODE // UNICODE is used by Windows headers
#endif
#endif
#ifdef UNICODE
#ifndef _UNICODE
#define _UNICODE // _UNICODE is used by C-runtime/MFC headers
#endif
#endif
#ifdef _DEBUG
#ifndef DEBUG
#define DEBUG
#endif
#endif
// namespace and our templates don't quite work with earlier compiler
// Can turn off namespace support directly, also
#if _MSC_VER<1100
#ifndef ATL_NO_NAMESPACE
#define ATL_NO_NAMESPACE
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
// __declspec(novtable) is used on a class declaration to prevent the vtable
// pointer from being initialized in the constructor and destructor for the
// class. This has many benefits because the linker can now eliminate the
// vtable and all the functions pointed to by the vtable. Also, the actual
// constructor and destructor code are now smaller.
///////////////////////////////////////////////////////////////////////////////
// This should only be used on a class that is not directly createable but is
// rather only used as a base class. Additionally, the constructor and
// destructor (if provided by the user) should not call anything that may cause
// a virtual function call to occur back on the object.
///////////////////////////////////////////////////////////////////////////////
// By default, the wizards will generate new ATL object classes with this
// attribute (through the ATL_NO_VTABLE macro). This is normally safe as long
// the restriction mentioned above is followed. It is always safe to remove
// this macro from your class, so if in doubt, remove it.
///////////////////////////////////////////////////////////////////////////////
#if _MSC_VER<1100
#define ATL_NO_VTABLE
#else
#ifdef _ATL_DISABLE_NO_VTABLE
#define ATL_NO_VTABLE
#else
#define ATL_NO_VTABLE __declspec(novtable)
#endif
#endif
#ifndef _ATL_NO_PRAGMA_WARNINGS
#pragma warning(disable: 4201) // nameless unions are part of C++
#pragma warning(disable: 4127) // constant expression
#pragma warning(disable: 4505) // unreferenced local function has been removed
#pragma warning(disable: 4512) // can't generate assignment operator (so what?)
#pragma warning(disable: 4514) // unreferenced inlines are common
#pragma warning(disable: 4103) // pragma pack
#pragma warning(disable: 4702) // unreachable code
#pragma warning(disable: 4237) // bool
#pragma warning(disable: 4710) // function couldn't be inlined
#pragma warning(disable: 4355) // 'this' : used in base member initializer list
#pragma warning(disable: 4097) // typedef name used as synonym for class-name
#pragma warning(disable: 4786) // identifier was truncated in the debug information
#pragma warning(disable: 4268) // const static/global data initialized to zeros
#pragma warning(disable: 4291) // allow placement new
#endif //!_ATL_NO_PRAGMA_WARNINGS
#include <windows.h>
#include <winnls.h>
#include <ole2.h>
#include <stddef.h>
#include <tchar.h>
#include <malloc.h>
#ifndef _ATL_NO_DEBUG_CRT
// Warning: if you define the above symbol, you will have
// to provide your own definition of the _ASSERTE(x) macro
// in order to compile ATL
#include <crtdbg.h>
#endif
#ifndef ATLASSERT
#define ATLASSERT(expr) _ASSERTE(expr)
#endif
#include <olectl.h>
#include <winreg.h>
#include <atliface.h>
#ifndef _ATL_PACKING
#define _ATL_PACKING 8
#endif
#pragma pack(push, _ATL_PACKING)
#include <atlconv.h>
#if defined(_ATL_DLL)
#define ATLAPI extern "C" HRESULT __declspec(dllimport) __stdcall
#define ATLAPI_(x) extern "C" __declspec(dllimport) x __stdcall
#define ATLINLINE
#elif defined(_ATL_DLL_IMPL)
#define ATLAPI extern "C" HRESULT __declspec(dllexport) __stdcall
#define ATLAPI_(x) extern "C" __declspec(dllexport) x __stdcall
#define ATLINLINE
#else
#define ATLAPI HRESULT __stdcall
#define ATLAPI_(x) x __stdcall
#define ATLINLINE inline
#endif
#ifndef ATL_NO_NAMESPACE
#ifndef _ATL_DLL_IMPL
namespace ATL { #endif
#endif
typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void* pv, REFIID riid, LPVOID* ppv); typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void* pv, REFIID riid, LPVOID* ppv, ULONG_PTR dw); typedef HRESULT (WINAPI _ATL_MODULEFUNC)(ULONG_PTR dw); typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC)();
struct _ATL_OBJMAP_ENTRY { const CLSID* pclsid; HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); _ATL_CREATORFUNC* pfnGetClassObject; _ATL_CREATORFUNC* pfnCreateInstance; IUnknown* pCF; DWORD dwRegister; _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription; HRESULT WINAPI RevokeClassObject() { return CoRevokeClassObject(dwRegister); } HRESULT WINAPI RegisterClassObject(DWORD dwClsContext, DWORD dwFlags) { IUnknown* p = NULL; if (pfnGetClassObject == NULL) return S_OK;
HRESULT hRes = pfnGetClassObject(pfnCreateInstance, IID_IUnknown, (LPVOID*) &p); if (SUCCEEDED(hRes)) hRes = CoRegisterClassObject(*pclsid, p, dwClsContext, dwFlags, &dwRegister); if (p != NULL) p->Release(); return hRes; } };
struct _ATL_REGMAP_ENTRY { LPCOLESTR szKey; LPCOLESTR szData; };
struct _ATL_MODULE { // Attributes
public: UINT cbSize; HINSTANCE m_hInst; HINSTANCE m_hInstResource; HINSTANCE m_hInstTypeLib; _ATL_OBJMAP_ENTRY* m_pObjMap; LONG m_nLockCnt; HANDLE m_hHeap; CRITICAL_SECTION m_csTypeInfoHolder; CRITICAL_SECTION m_csWindowCreate; CRITICAL_SECTION m_csObjMap; };
//This define makes debugging asserts easier.
#define _ATL_SIMPLEMAPENTRY ((_ATL_CREATORARGFUNC*)1)
struct _ATL_INTMAP_ENTRY { const IID* piid; // the interface id (IID)
ULONG_PTR dw; _ATL_CREATORARGFUNC* pFunc; //NULL:end, 1:offset, n:ptr
};
/////////////////////////////////////////////////////////////////////////////
// QI Support
ATLAPI AtlInternalQueryInterface(void* pThis, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject);
/////////////////////////////////////////////////////////////////////////////
// Smart Pointer helpers
ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp); ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid);
/////////////////////////////////////////////////////////////////////////////
// Inproc Marshaling helpers
ATLAPI AtlFreeMarshalStream(IStream* pStream); ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream); ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk);
ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent);
/////////////////////////////////////////////////////////////////////////////
// Connection Point Helpers
ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw); ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw);
/////////////////////////////////////////////////////////////////////////////
// IDispatch Error handling
ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst);
/////////////////////////////////////////////////////////////////////////////
// Module
ATLAPI AtlModuleInit(_ATL_MODULE* pM, _ATL_OBJMAP_ENTRY* p, HINSTANCE h); ATLAPI AtlModuleRegisterClassObjects(_ATL_MODULE* pM, DWORD dwClsContext, DWORD dwFlags); ATLAPI AtlModuleRevokeClassObjects(_ATL_MODULE* pM); ATLAPI AtlModuleGetClassObject(_ATL_MODULE* pM, REFCLSID rclsid, REFIID riid, LPVOID* ppv); ATLAPI AtlModuleTerm(_ATL_MODULE* pM); ATLAPI AtlModuleRegisterServer(_ATL_MODULE* pM, BOOL bRegTypeLib, const CLSID* pCLSID = NULL); ATLAPI AtlModuleUnregisterServer(_ATL_MODULE* pM, const CLSID* pCLSID = NULL); ATLAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE*pM, LPCOLESTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg = NULL); ATLAPI AtlModuleRegisterTypeLib(_ATL_MODULE* pM, LPCOLESTR lpszIndex);
#ifndef ATL_NO_NAMESPACE
#ifndef _ATL_DLL_IMPL
}; //namespace ATL
#endif
#endif
#ifndef ATL_NO_NAMESPACE
namespace ATL { #endif
#if defined (_CPPUNWIND) & (defined(_ATL_EXCEPTIONS) | defined(_AFX))
#define ATLTRY(x) try{x;} catch(...) {}
#else
#define ATLTRY(x) x;
#endif
#ifdef _DEBUG
void _cdecl AtlTrace(LPCTSTR lpszFormat, ...); #ifndef ATLTRACE
#define ATLTRACE AtlTrace
#endif
#define ATLTRACENOTIMPL(funcname) ATLTRACE(_T("%s not implemented.\n"), funcname); return E_NOTIMPL
#else
inline void _cdecl AtlTrace(LPCTSTR , ...){} #ifndef ATLTRACE
#define ATLTRACE 1 ? (void)0 : AtlTrace
#endif
#define ATLTRACENOTIMPL(funcname) return E_NOTIMPL
#endif //_DEBUG
#ifndef offsetofclass
#define offsetofclass(base, derived) ((ULONG_PTR)(static_cast<base*>((derived*)8))-8)
#endif
/////////////////////////////////////////////////////////////////////////////
// Master version numbers
#define _ATL 1 // Active Template Library
#undef _ATL_VER
#define _ATL_VER 0x0203 // Active Template Library version 2.03, XP Security changes
/////////////////////////////////////////////////////////////////////////////
// Error to HRESULT helpers
inline HRESULT AtlHresultFromLastError() { DWORD dwErr = ::GetLastError(); return HRESULT_FROM_WIN32(dwErr); }
inline HRESULT AtlHresultFromWin32(DWORD nError) { return( HRESULT_FROM_WIN32( nError ) ); }
inline void __declspec(noreturn) _AtlRaiseException( DWORD dwExceptionCode, DWORD dwExceptionFlags = EXCEPTION_NONCONTINUABLE ) { RaiseException( dwExceptionCode, dwExceptionFlags, 0, NULL ); }
// Validation macro for OUT pointer
// Used in QI and CreateInstance
#define _ATL_VALIDATE_OUT_POINTER(x) _ASSERTE(x != NULL); \
if (x == NULL) \ return E_POINTER; \ *x = NULL
/////////////////////////////////////////////////////////////////////////////
// Win32 libraries
#ifndef _ATL_NO_FORCE_LIBS
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")
#pragma comment(lib, "olepro32.lib")
#pragma comment(lib, "uuid.lib")
#pragma comment(lib, "advapi32.lib")
#endif // _ATL_NO_FORCE_LIBS
template <class T> class _NoAddRefReleaseOnCComPtr : public T { private: STDMETHOD_(ULONG, AddRef)()=0; STDMETHOD_(ULONG, Release)()=0; };
template <class T> class CComPtr { public: typedef T _PtrClass; CComPtr() {p=NULL;} CComPtr(T* lp) { if ((p = lp) != NULL) p->AddRef(); } CComPtr(const CComPtr<T>& lp) { if ((p = lp.p) != NULL) p->AddRef(); } ~CComPtr() {if (p) p->Release();} void Release() { #if 0 // Remove for now, there's instances of people using this on a class instead of just templates.
IUnknown* pTemp = p; #else
T* pTemp = p; #endif
if (pTemp) { p = NULL; pTemp->Release(); } } operator T*() {return (T*)p;} T& operator*() {ATLASSERT(p!=NULL); return *p; } //The assert on operator& usually indicates a bug. If this is really
//what is needed, however, take the address of the p member explicitly.
T** operator&() { ATLASSERT(p==NULL); return &p; } _NoAddRefReleaseOnCComPtr<T>* operator->() { ATLASSERT(p!=NULL); return (_NoAddRefReleaseOnCComPtr<T>*)p; } T* operator=(T* lp){return (T*)AtlComPtrAssign((IUnknown**)&p, lp);} T* operator=(const CComPtr<T>& lp) { return (T*)AtlComPtrAssign((IUnknown**)&p, lp.p); } #if _MSC_VER>1020
bool operator!(){return (p == NULL);} #else
BOOL operator!(){return (p == NULL) ? TRUE : FALSE;} #endif
T* p; };
//Note: CComQIPtr<IUnknown, &IID_IUnknown> is not meaningful
// Use CComPtr<IUnknown>
template <class T, const IID* piid> class CComQIPtr { public: typedef T _PtrClass; CComQIPtr() {p=NULL;} CComQIPtr(T* lp) { if ((p = lp) != NULL) p->AddRef(); } CComQIPtr(const CComQIPtr<T,piid>& lp) { if ((p = lp.p) != NULL) p->AddRef(); } // If you get an error that this member is already defined, you are probably
// using a CComQIPtr<IUnknown, &IID_IUnknown>. This is not necessary.
// Use CComPtr<IUnknown>
CComQIPtr(IUnknown* lp) { p=NULL; if (lp != NULL) lp->QueryInterface(*piid, (void **)&p); } ~CComQIPtr() {if (p) p->Release();} void Release() { IUnknown* pTemp = p; if (pTemp) { p = NULL; pTemp->Release(); } } operator T*() {return p;} T& operator*() {ATLASSERT(p!=NULL); return *p; } //The assert on operator& usually indicates a bug. If this is really
//what is needed, however, take the address of the p member explicitly.
T** operator&() { ATLASSERT(p==NULL); return &p; } _NoAddRefReleaseOnCComPtr<T>* operator->() { ATLASSERT(p!=NULL); return (_NoAddRefReleaseOnCComPtr<T>*)p; }
T* operator=(T* lp){return (T*)AtlComPtrAssign((IUnknown**)&p, lp);} T* operator=(const CComQIPtr<T,piid>& lp) { return (T*)AtlComPtrAssign((IUnknown**)&p, lp.p); } T* operator=(IUnknown* lp) { return (T*)AtlComQIPtrAssign((IUnknown**)&p, lp, *piid); } #if _MSC_VER>1020
bool operator!(){return (p == NULL);} #else
BOOL operator!(){return (p == NULL) ? TRUE : FALSE;} #endif
T* p; };
/////////////////////////////////////////////////////////////////////////////
// CComBSTR
class CComBSTR { public: BSTR m_str; CComBSTR() { m_str = NULL; } /*explicit*/ CComBSTR(int nSize, LPCOLESTR sz = NULL) { m_str = ::SysAllocStringLen(sz, nSize); } /*explicit*/ CComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } /*explicit*/ CComBSTR(const CComBSTR& src) { m_str = src.Copy(); } CComBSTR& operator=(const CComBSTR& src); CComBSTR& operator=(LPCOLESTR pSrc); ~CComBSTR() { ::SysFreeString(m_str); } unsigned int Length() const { return SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR Copy() const { return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); } void Attach(BSTR src) { ATLASSERT(m_str == NULL); m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } void Empty() { ::SysFreeString(m_str); m_str = NULL; } #if _MSC_VER>1020
bool operator!() { return (m_str == NULL); } #else
BOOL operator!() { return (m_str == NULL) ? TRUE : FALSE; } #endif
HRESULT Append(const CComBSTR& bstrSrc) { return Append(bstrSrc.m_str, SysStringLen(bstrSrc.m_str)); } HRESULT Append(LPCOLESTR lpsz) { return Append(lpsz, (int) ocslen(lpsz)); } // a BSTR is just a LPCOLESTR so we need a special version to signify
// that we are appending a BSTR
HRESULT AppendBSTR(BSTR p) { return Append(p, SysStringLen(p)); } HRESULT Append(LPCOLESTR lpsz, int nLen);
CComBSTR& operator+=(const CComBSTR& bstrSrc) { AppendBSTR(bstrSrc.m_str); return *this; } #ifndef OLE2ANSI
/*explicit*/ CComBSTR(LPCSTR pSrc); /*explicit*/ CComBSTR(int nSize, LPCSTR sz = NULL); CComBSTR& operator=(LPCSTR pSrc); HRESULT Append(LPCSTR); #endif
HRESULT WriteToStream(IStream* pStream); HRESULT ReadFromStream(IStream* pStream); };
/////////////////////////////////////////////////////////////////////////////
// CComVariant
class CComVariant : public tagVARIANT { // Constructors
public: CComVariant() { ::VariantInit(this); } ~CComVariant() { Clear(); }
CComVariant(const VARIANT& varSrc) { ::VariantInit(this); InternalCopy(&varSrc); }
CComVariant(const CComVariant& varSrc) { ::VariantInit(this); InternalCopy(&varSrc); }
CComVariant(BSTR bstrSrc) { ::VariantInit(this); *this = bstrSrc; } CComVariant(LPCOLESTR lpszSrc) { ::VariantInit(this); *this = lpszSrc; }
#ifndef OLE2ANSI
CComVariant(LPCSTR lpszSrc) { ::VariantInit(this); *this = lpszSrc;} #endif
#if _MSC_VER>1020
CComVariant(bool bSrc) { ::VariantInit(this); vt = VT_BOOL; #pragma warning(disable: 4310) // cast truncates constant value
boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; #pragma warning(default: 4310) // cast truncates constant value
} #endif
CComVariant(int nSrc) { ::VariantInit(this); vt = VT_I4; lVal = nSrc; } CComVariant(BYTE nSrc) { ::VariantInit(this); vt = VT_UI1; bVal = nSrc; } CComVariant(short nSrc) { ::VariantInit(this); vt = VT_I2; iVal = nSrc; } CComVariant(long nSrc, VARTYPE vtSrc = VT_I4) { ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_ERROR); ::VariantInit(this); vt = vtSrc; lVal = nSrc; } CComVariant(float fltSrc) { ::VariantInit(this); vt = VT_R4; fltVal = fltSrc; } CComVariant(double dblSrc) { ::VariantInit(this); vt = VT_R8; dblVal = dblSrc; } CComVariant(CY cySrc) { ::VariantInit(this); vt = VT_CY; cyVal.Hi = cySrc.Hi; cyVal.Lo = cySrc.Lo; } CComVariant(IDispatch* pSrc) { ::VariantInit(this); vt = VT_DISPATCH; pdispVal = pSrc; // Need to AddRef as VariantClear will Release
if (pdispVal != NULL) pdispVal->AddRef(); } CComVariant(IUnknown* pSrc) { ::VariantInit(this); vt = VT_UNKNOWN; punkVal = pSrc; // Need to AddRef as VariantClear will Release
if (punkVal != NULL) punkVal->AddRef(); }
// Assignment Operators
public: CComVariant& operator=(const CComVariant& varSrc) { InternalCopy(&varSrc); return *this; } CComVariant& operator=(const VARIANT& varSrc) { InternalCopy(&varSrc); return *this; }
CComVariant& operator=(BSTR bstrSrc); CComVariant& operator=(LPCOLESTR lpszSrc);
#ifndef OLE2ANSI
CComVariant& operator=(LPCSTR lpszSrc); #endif
#if _MSC_VER>1020
CComVariant& operator=(bool bSrc); #endif
CComVariant& operator=(int nSrc); CComVariant& operator=(BYTE nSrc); CComVariant& operator=(short nSrc); CComVariant& operator=(long nSrc); CComVariant& operator=(float fltSrc); CComVariant& operator=(double dblSrc); CComVariant& operator=(CY cySrc);
CComVariant& operator=(IDispatch* pSrc); CComVariant& operator=(IUnknown* pSrc);
// Comparison Operators
public: #if _MSC_VER>1020
bool operator==(const VARIANT& varSrc); bool operator!=(const VARIANT& varSrc) {return !operator==(varSrc);} #else
BOOL operator==(const VARIANT& varSrc); BOOL operator!=(const VARIANT& varSrc) {return !operator==(varSrc);} #endif
// Operations
public: HRESULT Clear() { return ::VariantClear(this); } HRESULT Copy(const VARIANT* pSrc) { return ::VariantCopy(this, const_cast<VARIANT*>(pSrc)); } HRESULT Attach(VARIANT* pSrc); HRESULT Detach(VARIANT* pDest); HRESULT ChangeType(VARTYPE vtNew, const VARIANT* pSrc = NULL); HRESULT WriteToStream(IStream* pStream); HRESULT ReadFromStream(IStream* pStream);
// Implementation
public: HRESULT InternalClear(); void InternalCopy(const VARIANT* pSrc); }; /////////////////////////////////////////////////////////////////////////////
// GUID comparison
#if 0
inline BOOL InlineIsEqualGUID(REFGUID rguid1, REFGUID rguid2) { return ( ((PLONG) &rguid1)[0] == ((PLONG) &rguid2)[0] && ((PLONG) &rguid1)[1] == ((PLONG) &rguid2)[1] && ((PLONG) &rguid1)[2] == ((PLONG) &rguid2)[2] && ((PLONG) &rguid1)[3] == ((PLONG) &rguid2)[3]); } #endif
inline BOOL InlineIsEqualUnknown(REFGUID rguid1) { return ( ((PLONG) &rguid1)[0] == 0 && ((PLONG) &rguid1)[1] == 0 && #ifdef _MAC
((PLONG) &rguid1)[2] == 0xC0000000 && ((PLONG) &rguid1)[3] == 0x00000046); #else
((PLONG) &rguid1)[2] == 0x000000C0 && ((PLONG) &rguid1)[3] == 0x46000000); #endif
}
/////////////////////////////////////////////////////////////////////////////
// Threading Model Support
class CComCriticalSection { public: void Lock() {EnterCriticalSection(&m_sec);} void Unlock() {LeaveCriticalSection(&m_sec);} void Init() {InitializeCriticalSection(&m_sec);} void Term() {DeleteCriticalSection(&m_sec);} CRITICAL_SECTION m_sec; };
class CComAutoCriticalSection { public: void Lock() {EnterCriticalSection(&m_sec);} void Unlock() {LeaveCriticalSection(&m_sec);} CComAutoCriticalSection() {InitializeCriticalSection(&m_sec);} ~CComAutoCriticalSection() {DeleteCriticalSection(&m_sec);} CRITICAL_SECTION m_sec; };
class CComFakeCriticalSection { public: void Lock() {} void Unlock() {} void Init() {} void Term() {} };
class CComMultiThreadModelNoCS { public: static ULONG WINAPI Increment(LPLONG p) {return InterlockedIncrement(p);} static ULONG WINAPI Decrement(LPLONG p) {return InterlockedDecrement(p);} typedef CComFakeCriticalSection AutoCriticalSection; typedef CComFakeCriticalSection CriticalSection; typedef CComMultiThreadModelNoCS ThreadModelNoCS; };
class CComMultiThreadModel { public: static ULONG WINAPI Increment(LPLONG p) {return InterlockedIncrement(p);} static ULONG WINAPI Decrement(LPLONG p) {return InterlockedDecrement(p);} typedef CComAutoCriticalSection AutoCriticalSection; typedef CComCriticalSection CriticalSection; typedef CComMultiThreadModelNoCS ThreadModelNoCS; };
class CComSingleThreadModel { public: static ULONG WINAPI Increment(LPLONG p) {return ++(*p);} static ULONG WINAPI Decrement(LPLONG p) {return --(*p);} typedef CComFakeCriticalSection AutoCriticalSection; typedef CComFakeCriticalSection CriticalSection; typedef CComSingleThreadModel ThreadModelNoCS; };
#ifndef _ATL_SINGLE_THREADED
#ifndef _ATL_APARTMENT_THREADED
#ifndef _ATL_FREE_THREADED
#define _ATL_FREE_THREADED
#endif
#endif
#endif
#if defined(_ATL_SINGLE_THREADED)
typedef CComSingleThreadModel CComObjectThreadModel; typedef CComSingleThreadModel CComGlobalsThreadModel; #elif defined(_ATL_APARTMENT_THREADED)
typedef CComSingleThreadModel CComObjectThreadModel; typedef CComMultiThreadModel CComGlobalsThreadModel; #else
typedef CComMultiThreadModel CComObjectThreadModel; typedef CComMultiThreadModel CComGlobalsThreadModel; #endif
/////////////////////////////////////////////////////////////////////////////
// CComModule
#define THREADFLAGS_APARTMENT 0x1
#define THREADFLAGS_BOTH 0x2
#define AUTPRXFLAG 0x4
struct _AtlCreateWndData { void* m_pThis; DWORD m_dwThreadID; _AtlCreateWndData* m_pNext; };
class CComModule : public _ATL_MODULE { // Operations
public: _AtlCreateWndData* m_pCreateWndList;
void AddCreateWndData(_AtlCreateWndData* pData, void* pObject); void* ExtractCreateWndData();
HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h) { cbSize = sizeof(_ATL_MODULE); m_pCreateWndList = NULL; return AtlModuleInit(this, p, h); } void Term() { AtlModuleTerm(this); }
LONG Lock() {return CComGlobalsThreadModel::Increment(&m_nLockCnt);} LONG Unlock() {return CComGlobalsThreadModel::Decrement(&m_nLockCnt);} LONG GetLockCount() {return m_nLockCnt;}
HINSTANCE GetModuleInstance() {return m_hInst;} HINSTANCE GetResourceInstance() {return m_hInstResource;} HINSTANCE GetTypeLibInstance() {return m_hInstTypeLib;}
// Registry support (helpers)
HRESULT RegisterTypeLib() { return AtlModuleRegisterTypeLib(this, NULL); } HRESULT RegisterTypeLib(LPCTSTR lpszIndex) { USES_CONVERSION_EX; LPCOLESTR p = NULL; if(lpszIndex != NULL) { p = T2COLE_EX(lpszIndex,_ATL_SAFE_ALLOCA_DEF_THRESHOLD); #ifndef _UNICODE
if(p == NULL) return E_OUTOFMEMORY; #endif
}
return AtlModuleRegisterTypeLib(this, p); }
HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) { return AtlModuleRegisterServer(this, bRegTypeLib, pCLSID); }
HRESULT UnregisterServer(const CLSID* pCLSID = NULL) { return AtlModuleUnregisterServer(this, pCLSID); }
// Resource-based Registration
HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) { if(lpszRes == NULL) return E_INVALIDARG; USES_CONVERSION_EX; LPCOLESTR p = T2COLE_EX(lpszRes,_ATL_SAFE_ALLOCA_DEF_THRESHOLD); #ifdef _UNICODE
if(p == NULL) return E_OUTOFMEMORY; #endif
return AtlModuleUpdateRegistryFromResourceD(this, p, bRegister, pMapEntries); } HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) { return AtlModuleUpdateRegistryFromResourceD(this, (LPCOLESTR)MAKEINTRESOURCE(nResID), bRegister, pMapEntries); }
#ifdef _ATL_STATIC_REGISTRY
// Statically linking to Registry Ponent
HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries = NULL); HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries = NULL); #endif //_ATL_STATIC_REGISTRY
// Standard Registration
HRESULT WINAPI UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister); HRESULT WINAPI RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags); HRESULT WINAPI UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID);
// Register/Revoke All Class Factories with the OS (EXE only)
HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) { return AtlModuleRegisterClassObjects(this, dwClsContext, dwFlags); } HRESULT RevokeClassObjects() { return AtlModuleRevokeClassObjects(this); }
// Obtain a Class Factory (DLL only)
HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { return AtlModuleGetClassObject(this, rclsid, riid, ppv); }
// Only used in CComAutoThreadModule
HRESULT CreateInstance(void* /*pfnCreateInstance*/, REFIID /*riid*/, void** /*ppvObj*/) { return S_OK; } };
/////////////////////////////////////////////////////////////////////////////////////////////
// Thread Pooling classes
class _AtlAptCreateObjData { public: _ATL_CREATORFUNC* pfnCreateInstance; const IID* piid; HANDLE hEvent; LPSTREAM pStream; HRESULT hRes; };
class CComApartment { public: static UINT ATL_CREATE_OBJECT; static DWORD WINAPI _Apartment(void* pv) { ATLASSERT(pv != NULL); return ((CComApartment*)pv)->Apartment(); } DWORD Apartment() { CoInitialize(NULL); MSG msg; while(GetMessage(&msg, 0, 0, 0)) { if (msg.message == ATL_CREATE_OBJECT) { _AtlAptCreateObjData* pdata = (_AtlAptCreateObjData*)msg.lParam; IUnknown* pUnk = NULL; pdata->hRes = pdata->pfnCreateInstance(NULL, IID_IUnknown, (void**)&pUnk); if (SUCCEEDED(pdata->hRes)) pdata->hRes = CoMarshalInterThreadInterfaceInStream(*pdata->piid, pUnk, &pdata->pStream); if (SUCCEEDED(pdata->hRes)) { pUnk->Release(); ATLTRACE(_T("Object created on thread = %d\n"), GetCurrentThreadId()); } SetEvent(pdata->hEvent); } DispatchMessage(&msg); } CoUninitialize(); return 0; } LONG Lock() {return CComGlobalsThreadModel::Increment(&m_nLockCnt);} LONG Unlock(){return CComGlobalsThreadModel::Decrement(&m_nLockCnt); } LONG GetLockCount() {return m_nLockCnt;}
DWORD m_dwThreadID; HANDLE m_hThread; LONG m_nLockCnt; };
class CComSimpleThreadAllocator { public: CComSimpleThreadAllocator() { m_nThread = 0; } int GetThread(CComApartment* /*pApt*/, int nThreads) { if (++m_nThread == nThreads) m_nThread = 0; return m_nThread; } int m_nThread; };
#if _MSC_VER>1020
template <class ThreadAllocator = CComSimpleThreadAllocator> #else
template <class ThreadAllocator> #endif
class CComAutoThreadModule : public CComModule { public: HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, int nThreads = GetDefaultThreads()); ~CComAutoThreadModule(); HRESULT CreateInstance(void* pfnCreateInstance, REFIID riid, void** ppvObj); LONG Lock(); LONG Unlock(); DWORD dwThreadID; int m_nThreads; CComApartment* m_pApartments; ThreadAllocator m_Allocator; static int GetDefaultThreads() { SYSTEM_INFO si; GetSystemInfo(&si); return si.dwNumberOfProcessors * 4; } };
#ifdef _ATL_STATIC_REGISTRY
#define UpdateRegistryFromResource UpdateRegistryFromResourceS
#else
#define UpdateRegistryFromResource UpdateRegistryFromResourceD
#endif
/////////////////////////////////////////////////////////////////////////////
// CRegKey
class CRegKey { public: CRegKey(); ~CRegKey();
// Attributes
public: operator HKEY() const; HKEY m_hKey;
// Operations
public: LONG SetValue(DWORD dwValue, LPCTSTR lpszValueName); LONG QueryValue(DWORD& dwValue, LPCTSTR lpszValueName); LONG QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount); LONG SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL);
LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL); static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL);
LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName, LPTSTR lpszClass = REG_NONE, DWORD dwOptions = REG_OPTION_NON_VOLATILE, REGSAM samDesired = KEY_ALL_ACCESS, LPSECURITY_ATTRIBUTES lpSecAttr = NULL, LPDWORD lpdwDisposition = NULL); LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired = KEY_ALL_ACCESS); LONG Close(); HKEY Detach(); void Attach(HKEY hKey); LONG DeleteSubKey(LPCTSTR lpszSubKey); LONG RecurseDeleteKey(LPCTSTR lpszKey); LONG DeleteValue(LPCTSTR lpszValue); };
inline CRegKey::CRegKey() {m_hKey = NULL;}
inline CRegKey::~CRegKey() {Close();}
inline CRegKey::operator HKEY() const {return m_hKey;}
inline HKEY CRegKey::Detach() { HKEY hKey = m_hKey; m_hKey = NULL; return hKey; }
inline void CRegKey::Attach(HKEY hKey) { ATLASSERT(m_hKey == NULL); m_hKey = hKey; }
inline LONG CRegKey::DeleteSubKey(LPCTSTR lpszSubKey) { ATLASSERT(m_hKey != NULL); return RegDeleteKey(m_hKey, lpszSubKey); }
inline LONG CRegKey::DeleteValue(LPCTSTR lpszValue) { ATLASSERT(m_hKey != NULL); return RegDeleteValue(m_hKey, (LPTSTR)lpszValue); }
#pragma pack(pop)
#ifndef ATL_NO_NAMESPACE
}; //namespace ATL
using namespace ATL; #endif
#endif // __ATLBASE_H__
/////////////////////////////////////////////////////////////////////////////
|