home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////////////////////////
- // UTILCLS.H - Utility Classes
- //
- // $Revision: 1.32.1.34 $
- // $Date: 20 Jan 1999 17:58:28 $
- //
- // Copyright (c) 1998, 1999 Borland International
- /////////////////////////////////////////////////////////////////////////////
- #ifndef __UTILCLS_H
- #define __UTILCLS_H
-
- // To keep track of version of UTILITY class header
- //
- #define __UTILCLS_H_VERSION 0x0101
-
- #include <objbase.h>
- #include <oleauto.h>
- #include <cguid.h>
- #include <stdarg.h>
- #include <tchar.h>
-
- #if defined(DEBUG)
- #include <ocidl.h>
- #if sizeof(QACONTAINER) != 64
- #error sizeof(QACONTAINER) is off!!
- #endif
- #if sizeof(TLIBATTR) != 32
- #error sizeof(TLIBATTR) is off !!
- #endif
- #endif // DEBUG
-
-
- // Typedefs to avoid 'simple type expected' error from compiler
- //
- typedef signed char signed_char;
- typedef unsigned char unsigned_char;
- typedef unsigned short unsigned_short;
- typedef unsigned long unsigned_long;
- typedef unsigned __int64 unsigned_int64;
-
- // Forward ref.
- //
- template <class DISPINTF = IDispatch>
- class TAutoDriver;
- template <class DISPINTF = IDispatch>
- class TDispId;
-
- //////////////////////////////////////////////////////////////////////////////
- // Macros
- //////////////////////////////////////////////////////////////////////////////
-
- // Until Compiler supports __declspec(uuid(....)) [and __uuidof(...)]
- //
- #if !defined(DECLSPEC_UUID)
- #define DECLSPEC_UUID(guid)
- #endif
-
- // CONNECTIONPOINT_ARRAY_SIZE is used by the Fire_xxxx Event templates generated for
- // outgoing interfaces in the xxxx_TLB.H file.
- //
- #if !defined(CONNECTIONPOINT_ARRAY_SIZE)
- #define CONNECTIONPOINT_ARRAY_SIZE 5
- #endif
-
- #if !defined(OLETEXT)
- #define OLETEXT(x) L ## x
- #endif
-
- #if !defined(NO_PROMPT_ON_ASSSERTE_FAILURE)
- #define PROMPT_ON_ASSERTE_FAILURE 1
- #endif
- #if !defined(NO_PROMPT_ON_HRCHECK_FAILURE)
- #define PROMPT_ON_HRCHECK_FAILURE 1
- #endif
-
- // Implementation of TRACE_HLPR
- //
- template <class T>
- class TDebugHlpr
- {
- public:
- static void __cdecl TRACE_HLPR(T* szFormat, ...);
- };
-
- // Implementation of OLECHECK - Throw an exception if !SUCCEEDED(hr)
- //
- template <class T>
- HRESULT DebugHlpr_HRCHECK(HRESULT hr, T* expr, T* file, int line)
- {
- if (!SUCCEEDED(hr))
- {
- TCHAR szMsg[_MAX_PATH*2];
-
- if (!file)
- file = _T("");
-
- LPVOID msg = 0;
- if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, hr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), LPTSTR(&msg), 0, 0) && (msg != 0))
- {
- ::wsprintf(szMsg, _T("'%s': %s @ %s/%d"), expr, LPTSTR(msg), file, line);
- ::LocalFree(msg);
- }
- else
- ::wsprintf(szMsg, _T("(%s) Error: %lX (%ld) @ %s/%d"), expr, LONG(hr), LONG(hr), file, line);
-
- #if !defined(PROMPT_ON_HRCHECK_FAILURE)
- int i = IDYES;
- #else
- int i = DebugHlpr_PROMPT(_T("HRCHECK: "), szMsg);
- #endif
- if (i == IDYES)
- DebugHlpr_THROW(szMsg);
- else if (i == IDCANCEL)
- ::DebugBreak();
- // NOTE: IDNO - implies we keep chugging along
- }
-
- return hr;
- }
-
- // _ASSERTE helper return MB_YES, MB_NO or MB_CANCEL
- //
- template <class T>
- int DebugHlpr_ASSERTE(T* expr, T* file, int line)
- {
- TCHAR msg[_MAX_PATH*2];
- ::wsprintf(msg, _T("%s @ %s/%d"), LPTSTR(expr), file, line);
-
- #if !defined(PROMPT_ON_ASSERTE_FAILURE)
- int i = IDYES;
- #else
- int i = DebugHlpr_PROMPT(_T("_ASSERTE: "), msg);
- #endif
-
- if (i == IDYES)
- {
- ::wsprintf(msg, _T("%s failed - %s/%d"), expr, file, line);
- DebugHlpr_THROW(msg);
- }
- return i;
- }
-
- // Helper used to throw an exception
- //
- template <class T>
- void DebugHlpr_THROW(T* msg)
- {
- /* THROW SOMETHING BETTER */
- throw msg;
- }
-
- // Helper used to display a MessageBox
- //
- template <class T>
- int DebugHlpr_PROMPT(T* caption, T* msg)
- {
- TCHAR szMsg[_MAX_PATH*2];
- wsprintf(szMsg, _T("%s\nPress [Y]es to terminate, [N]o to continue and [C]ancel to Debug"), msg);
- return ::MessageBox(0, szMsg, caption, MB_TASKMODAL|MB_ICONQUESTION|MB_YESNOCANCEL);
- }
-
-
- #if !defined(OLETRACE)
- #define OLETRACE TDebugHlpr<TCHAR>::TRACE_HLPR
- #endif
-
- #if !defined(OLECHECK)
- #define OLECHECK(hrexpr) DebugHlpr_HRCHECK(hrexpr, #hrexpr, __FILE__, __LINE__)
- #endif
-
- #if !defined(_ASSERTE)
- #define _ASSERTE(expr) do { \
- if (!(expr) && DebugHlpr_ASSERTE(#expr, __FILE__, __LINE__) == IDCANCEL) \
- ::DebugBreak(); \
- } while (0)
- #endif
-
-
- // Version of _ASSERTE usable within inline functions
- // i.e. Does not have do/while construct which is not allowed in inline functions currently
- //
- #if !defined(_ASSERTE_)
- #define _ASSERTE_(expr) ((expr) ? (0) : DebugHlpr_ASSERTE(#expr, __FILE__, __LINE__))
- #endif
-
- template <class T>
- void __cdecl TDebugHlpr<T>::TRACE_HLPR(T* szFormat, ...)
- {
- va_list args;
- va_start(args, szFormat);
- int bufSize;
- TCHAR szBuffer[_MAX_PATH*2];
- bufSize = wvsprintf(szBuffer, szFormat, args);
- _ASSERTE(bufSize < sizeof(szBuffer));
- ::OutputDebugString(szBuffer);
- va_end(args);
- }
-
-
- // Template to 'hide' some functions for string conversions
- //
- template <class T = TCHAR>
- class TStringConverter
- {
- public:
- static LPSTR WideToAnsi(LPCWSTR src);
- static LPWSTR AnsiToWide(LPCSTR src);
- static LPWSTR AnsiToOLESTR(LPCSTR src);
- static LPWSTR WideToOLESTR(LPCWSTR src);
- static TCHAR* strnewdup(const T* src);
- };
-
-
- // String Helper conversion routines
- // NOTE: Return value must be deleted[]
- //
- template <class T> LPSTR
- TStringConverter<T>::WideToAnsi(LPCWSTR src)
- {
- int size = ::WideCharToMultiByte(CP_ACP, 0, src, -1, 0, 0, 0, 0);
- LPSTR dst = new char[size];
- size = ::WideCharToMultiByte(CP_ACP, 0, src, -1, dst, size, 0, 0);
- _ASSERTE(size != 0);
- return dst;
- }
-
- // NOTE: Return value must be passed to '::SysFreeString'
- //
- template <class T> OLECHAR*
- TStringConverter<T>::AnsiToOLESTR(LPCSTR src)
- {
- int size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, 0, 0);
- LPWSTR dst = ::SysAllocStringLen(0, size);
- size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, dst, size);
- _ASSERTE(size != 0);
- return dst;
- }
-
- // NOTE: Return value must be deleted[]
- //
- template <class T> LPWSTR
- TStringConverter<T>::AnsiToWide(LPCSTR src)
- {
- int size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, 0, 0);
- LPWSTR dst = new wchar_t[size];
- size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, dst, size);
- _ASSERTE(size != 0);
- return dst;
- }
-
- // NOTE: Return value must be passed to '::SysFreeString'
- //
- template <class T> OLECHAR*
- TStringConverter<T>::WideToOLESTR(LPCWSTR src)
- {
- return ::SysAllocString(src);
- }
-
- // NOTE: Return value must be deleted[]
- //
- template <class T> TCHAR*
- TStringConverter<T>::strnewdup(const T* str)
- {
- _ASSERTE(str);
- return lstrcpy(new TCHAR[lstrlen(str)+1], str);
- }
-
-
- // Return value must be deleted[]
- //
- inline LPSTR WideToAnsi(LPCWSTR src)
- {
- return TStringConverter<TCHAR>::WideToAnsi(src);
- }
-
- // NOTE: Return value must be passed to '::SysFreeString'
- //
- inline OLECHAR* AnsiToOLESTR(LPCSTR src)
- {
- return TStringConverter<TCHAR>::AnsiToOLESTR(src);
- }
-
- // NOTE: Return value must be '::SysFreeString'
- //
- inline OLECHAR* WideToOLESTR(LPCWSTR src)
- {
- return TStringConverter<TCHAR>::WideToOLESTR(src);
- }
-
- // NOTE: Return value must be delete[]
- //
- inline TCHAR* strnewdup(LPCSTR str)
- {
- _ASSERTE_(str);
- return TStringConverter<TCHAR>::strnewdup(str);
- }
-
-
- // Wrapper for freeing BSTRs
- //
- class TOleString
- {
- public:
- TOleString(BSTR bstr) : m_bstr(bstr) {}
- TOleString(const CHAR *str) : m_bstr(str ? AnsiToOLESTR(str) : 0) {}
- ~TOleString() { ::SysFreeString(m_bstr); }
-
- operator BSTR() const { return m_bstr;}
-
- protected:
- BSTR m_bstr;
- };
-
-
- // Cheap coder's quick buffer wrapper...
- //
- template <int LEN>
- class TCharBuff
- {
- public:
- TCharBuff() : m_Data(new TCHAR[LEN]) { m_Data[0] = 0; }
- TCharBuff(LPCTSTR src) : m_Data(new TCHAR[LEN]) { *this = src; }
- TCharBuff(const TCharBuff& src) { *this = src; }
- ~TCharBuff() { delete[] m_Data; }
-
- operator LPCTSTR() const { return m_Data; }
- int Len() const { return LEN; }
- bool operator !() const { return m_Data[0]==0;}
-
- LPTSTR Copy(LPCTSTR src) { return lstrcpyn(m_Data, src, LEN); }
- LPTSTR Cat (LPCTSTR src) { return lstrcat(m_Data, src); }
-
- TCharBuff& operator =(LPCTSTR src) { Copy(src); return *this; }
- TCharBuff& operator =(const TCharBuff& src) { Copy(src); return *this; }
- TCharBuff& operator+=(LPCTSTR src) { Cat(src); return *this; }
-
- protected:
- LPTSTR m_Data;
- };
-
-
- // TPtrBase
- // Base class for automation pointer management. Provides basic implementation for
- // smart pointer object.
- //
- template<class T>
- class TPtrBase
- {
- public:
- // Methods implementing pointer semantics
- //
- T& operator * () const { _ASSERTE_(m_ptr); return *m_ptr; }
- operator T* () const { return m_ptr;}
- bool operator !() const { return m_ptr == 0; }
- T* operator->() const { _ASSERTE_(m_ptr); return m_ptr; }
- T** operator &()/*const*/ { return &m_ptr; }
-
- // Comparison operators
- //
- bool operator == (T *rhs) const { return m_ptr == rhs;}
- bool operator == (const TPtrBase<T> &rhs) const { return m_ptr == rhs.m_ptr; }
- bool operator != (T *rhs) const { return m_ptr != rhs;}
- bool operator != (const TPtrBase<T> &rhs) const { return m_ptr != rhs.m_ptr; }
-
- protected:
- TPtrBase() : m_ptr(0) {}
- TPtrBase(T* p) : m_ptr(p) {}
-
- T* get () const { return m_ptr; }
- T* release () { return reset(0); }
- T* reset (T* p = 0) { T* tmp = m_ptr; m_ptr = p; return tmp; }
-
- // Actual data
- //
- T* m_ptr;
-
- private:
- // Prevent new/delete
- //
- void* operator new(size_t);
- void operator delete(void*/*p*/){/*::delete p;*/};
- };
-
-
- // TPtr: Smart pointer object for non-array pointers
- //
- template<class T>
- class TPtr : public TPtrBase<T>
- {
- public:
- TPtr() : TPtrBase<T>() {}
- TPtr(T* src) : TPtrBase<T>(src) {}
- TPtr(TPtr<T>& src) : TPtrBase<T>(src.release()) {}
- ~TPtr() {clear(0);}
-
- // Assignment operators
- //
- TPtr& operator = (TPtr<T>& src)
- {
- // Transfer ownership of pointer to receiver
- //
- reset(src.release());
- return *this;
- }
- TPtr& operator = (T* src)
- {
- clear(src);
- return *this;
- }
- T* operator& () const
- {
- return get();
- }
-
- // Clear object - free pointer
- //
- void clear(T *src)
- {
- if (m_ptr)
- delete m_ptr;
- m_ptr = src;
- }
- };
-
-
- // TAPtr: Smart pointer object for array new'ed memory
- //
- template<class T>
- class TAPtr : public TPtrBase<T>
- {
- public:
- TAPtr() : TPtrBase<T>() {}
- TAPtr(T src[]) : TPtrBase<T>(src) {}
- TAPtr(TPtr<T>& src) : TPtrBase<T>(src.release()) {}
- ~TAPtr() {clear(0);}
-
- // Assignment operators
- //
- TAPtr& operator = (TAPtr<T>& src)
- {
- // Transfer ownership of pointer to receiver
- //
- reset(src.release());
- return *this;
- }
- TAPtr& operator = (T src[])
- {
- clear(src);
- return *this;
- }
-
- // Subscript operator (for array)
- //
- T& operator [](int i) const
- {
- _ASSERTE_(m_ptr);
- return m_ptr[i];
- }
-
- // Clear object - free pointer
- //
- void clear(T src[])
- {
- if (m_ptr)
- delete []m_ptr;
- m_ptr = src;
- }
- };
-
-
- // TInitOle: Simple object to initialize and unintialize Ole in a safe fashion
- //
- template <class T>
- class TInitOleT
- {
- public:
- TInitOleT(COINIT initFlag = m_DefaultInitFlag)
- {
- HRESULT hr_Initializing_OLE = ::CoInitializeEx(0, initFlag);
- /* OLECHECK(hr_Initializing_OLE); */
- init = SUCCEEDED(hr_Initializing_OLE);
- }
- ~TInitOleT()
- {
- if (init)
- ::CoUninitialize();
- }
-
- // Methods to test whether initialization was succcessful
- //
- operator bool () const { return init; }
- int operator ! () const { return init == false; }
-
- // static members
- //
- static COINIT m_DefaultInitFlag;
- static void Init();
-
- protected:
- // Flags if initialization was successful
- //
- bool init;
-
- private:
- // Prevent accidental copy to ensure equal numbers of Init/UnInit
- //
- TInitOleT(const TInitOleT<T>&);
- TInitOleT<T>& operator = (const TInitOleT<T>&);
- };
-
- // Default flag when initializing OLE
- //
- #if !defined(_ATL_COINIT_MULTITHREADED)
- template <class T> COINIT
- TInitOleT<T>::m_DefaultInitFlag = COINIT_APARTMENTTHREADED;
- #else
- template <class T> COINIT
- TInitOleT<T>::m_DefaultInitFlag = COINIT_MULTITHREADED;
- #endif
-
-
- // Creates a single instance that initializes OLE
- //
- template <class T> void
- TInitOleT<T>::Init()
- {
- static TInitOle<T> instance(m_DefaultInitFlag);
- }
-
- // TInitOle is backward compatible with v3.0's TInitOle
- //
- typedef TInitOleT</*Pick a type*/int> TInitOle;
-
- // Helper class used to create Default Interface Wrapper of CoClasses
- // (Used by Code generated by TLIBIMP)
- //
- class CoClassCreator
- {
- public:
- // Enhanced version of CoCreateInstance that handles failure due to CLSCTX_REMOTESERVER Flag
- //
- static HRESULT CoCreateInstance(REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
- {
- HRESULT hr;
-
- // Define NO_REMOTE_BINDING if you do not want to try to bind to a remote server
- //
- #if !defined(NO_REMOTE_BINDING)
- hr = ::CoCreateInstance(rclsid, 0, CLSCTX_SERVER, riid, ppv);
-
- // If succeeded, or failed for reasons other than invalid arguments
- //
- if (SUCCEEDED(hr) || hr != E_INVALIDARG)
- return hr;
- #endif
-
- // Call CoCreateInstance, this time masking off CLSCTX_REMOTE_SERVER
- //
- hr = ::CoCreateInstance(rclsid, 0, CLSCTX_SERVER & ~CLSCTX_REMOTE_SERVER, riid, ppv);
- return hr;
- }
- };
-
- // Generic COM Interface wrapper
- // Performs proper AddRef/Release when object is copied, assigned to and deleted
- //
- template <class T>
- class TComInterface
- {
- public:
- TComInterface() : intf(0)
- {}
-
- // NOTE: The default behaviour of the constructor is not to AddRef the interface
- // pointer parameter. This is appropriate if the interface was obtained
- // has already been addRef'ed - as when retrieving a Font property.
- //
- TComInterface(T* p, bool addRef = false)
- {
- if (((intf = p) != 0) && addRef)
- intf->AddRef();
- }
-
- TComInterface(const TComInterface<T>& src)
- {
- if ((intf = src.intf) != 0)
- intf->AddRef();
- }
-
- ~TComInterface()
- {
- Reset();
- }
-
- operator T* () const
- {
- return intf;
- }
-
- T& operator*()
- {
- _ASSERTE_(intf!=0);
- return *intf;
- }
-
- // NOTE: You must explicitly Reset() any held interface pointers before invoking
- // the &operator (presumably to store another interface in the object)
- //
- T** operator & ()
- {
- _ASSERTE_(intf==0);
- return &intf;
- }
-
- T* operator->() const
- {
- _ASSERTE_(intf != 0);
- return intf;
- }
-
- T* operator->()
- {
- _ASSERTE_(intf != 0);
- return intf;
- }
-
- void Reset(T* p = 0)
- {
- if (intf)
- intf->Release();
- intf=p;
- }
-
- void Bind(T* p, bool addRef = false)
- {
- if (p && addRef)
- p->AddRef();
- Reset(p);
- }
-
- void Unbind() { Reset(0); }
-
- // NOTE: The assignment operator does *NOT* addRef the interface pointer being
- // assigned to this object.
- //
- TComInterface<T>& operator=(T* p)
- {
- Bind(p);
- return *this;
- }
-
- TComInterface<T>& operator=(const TComInterface<T>& src)
- {
- if (src.intf != 0)
- src.intf->AddRef();
- Reset(src.intf);
- return *this;
- }
-
- bool operator ! () const { return (intf == 0); }
- operator bool () const { return (intf != 0); }
- bool IsBound() const { return !!(*this); }
-
- protected:
- T* intf;
- };
-
- // Typedefs for standard interfaces
- //
- typedef TComInterface<IUnknown> TCOMIUnknown;
- typedef TComInterface<IDispatch> TCOMIDispatch;
-
- // Just in case this class is used solely for helper objects and
- // not for Automation
- //
- #if !defined(UTILCLS_NO_AUTOMATION)
-
- // VARIANT_BOOL is really just a short. Therefore it's not distinguishable from a
- // VT_I2. Most servers will take VT_I2 in a VARIANT when expecting a BOOLEAN.
- // However, some (such as Excel97) won't. So to distinguish, we'll expose VT_BOOL
- // as TOLEBOOL instead of VARIANT_BOOL.
- //
- class TOLEBOOL
- {
- public:
- TOLEBOOL(bool flag = false) : m_VariantBool(flag ? VARIANT_TRUE : VARIANT_FALSE) {}
- TOLEBOOL(VARIANT_BOOL flag) : m_VariantBool(flag ? VARIANT_TRUE : VARIANT_FALSE) {}
- TOLEBOOL(int flag) : m_VariantBool(flag ? VARIANT_TRUE : VARIANT_FALSE) {}
- TOLEBOOL(const TOLEBOOL& src) : m_VariantBool(src.m_VariantBool) {}
-
- TOLEBOOL& operator=(const TOLEBOOL& src)
- {
- m_VariantBool = src.m_VariantBool;
- return *this;
- }
- TOLEBOOL& operator=(bool flag)
- {
- m_VariantBool = flag ? VARIANT_TRUE : VARIANT_FALSE;
- return *this;
- }
- TOLEBOOL& operator=(VARIANT_BOOL flag)
- {
- m_VariantBool = flag ? VARIANT_TRUE : VARIANT_FALSE;
- return *this;
- }
- TOLEBOOL& operator=(int flag)
- {
- m_VariantBool = flag ? VARIANT_TRUE : VARIANT_FALSE;
- return *this;
- }
-
- bool operator==(bool val) { return val ? (m_VariantBool != VARIANT_FALSE) : (m_VariantBool == VARIANT_FALSE); }
- bool operator==(VARIANT_BOOL val) { return m_VariantBool == val; }
-
- operator bool () const { return m_VariantBool != VARIANT_FALSE; }
- operator VARIANT_BOOL () const { return (m_VariantBool != VARIANT_FALSE) ? VARIANT_TRUE : VARIANT_FALSE; }
-
- protected:
- VARIANT_BOOL m_VariantBool;
- };
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // The following macros utilize the Variant access macros defined in OLEAUTO.H
- // to set the VARTYPE (vt) and the related variable at once. For example:
- //
- // V_TYPE_VAR(CY, amount) expands to vt = VT_CY;
- // V_CY(this) = amount;
- ///////////////////////////////////////////////////////////////////////////////
- #if !defined(SET_VTYPE_AND_VAR)
- #define SET_VTYPE_AND_VAR(type, val) vt = VT_ ## type ; \
- V_ ## type (this) = val;
- #endif
- #if !defined(SET_VTYPE_AND_VARREF)
- #define SET_VTYPE_AND_VARREF(type, val) vt = VT_ ## type | VT_BYREF; \
- V_ ## type ## REF (this) = val;
- #endif
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // TVariantT
- // ========
- // Templatized VARIANT support. T must be a VARIANT or VARIANT-derived type
- ///////////////////////////////////////////////////////////////////////////////
- template <class T>
- class TVariantT : public T
- {
- public:
- TVariantT()
- {
- ::VariantInit(this);
- }
- ~TVariantT()
- {
- ::VariantClear(this);
- }
-
- TVariantT(const TVariantT& src)
- {
- ::VariantInit(this);
- ::VariantCopy(this, (VARIANT*)&src);
- }
-
- // Ctr - From basic C++ types
- TVariantT(bool src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(BOOL, src ? VARIANT_TRUE : VARIANT_FALSE);
- }
- TVariantT(const TOLEBOOL& src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(BOOL, src ? VARIANT_TRUE : VARIANT_FALSE);
- }
- TVariantT(char src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(I1, src);
- }
- TVariantT(signed char src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(I1, src);
- }
- TVariantT(unsigned char src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(UI1, src);
- }
- TVariantT(short src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(I2, src);
- }
- TVariantT(unsigned short src, bool isBoolean = false)
- {
- ::VariantInit(this);
- if (isBoolean)
- {
- SET_VTYPE_AND_VAR(BOOL, src);
- }
- else
- {
- SET_VTYPE_AND_VAR(UI2, src);
- }
- }
- TVariantT(int src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(I4, src);
- }
- TVariantT(unsigned int src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(UI4, src);
- }
- TVariantT(long src, bool isError = false)
- {
- ::VariantInit(this);
- if (isError)
- {
- SET_VTYPE_AND_VAR(ERROR, src);
- }
- else
- {
- SET_VTYPE_AND_VAR(I4, src);
- }
- }
- TVariantT(unsigned long src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(UI4, src);
- }
- TVariantT(float src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(R4, src);
- }
- TVariantT(double src, bool isDate = false)
- {
- ::VariantInit(this);
- if (isDate)
- {
- SET_VTYPE_AND_VAR(DATE, src);
- }
- else
- {
- SET_VTYPE_AND_VAR(R8, src);
- }
- }
- TVariantT(long double src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(R8, double(src));
- }
-
- // Ctr - From OLE structures
- TVariantT(const CURRENCY& src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(CY, src);
- }
- TVariantT(SAFEARRAY& src)
- {
- ::VariantInit(this);
- SetSAFEARRAY(&src);
- }
- TVariantT(SAFEARRAY* src)
- {
- ::VariantInit(this);
- SetSAFEARRAY(src);
- }
- TVariantT(const VARIANT& src)
- {
- ::VariantInit(this);
- ::VariantCopy(this, const_cast<VARIANTARG*>(&src));
- }
- TVariantT(VARIANT* src)
- {
- ::VariantInit(this);
- ::VariantCopy(this, src);
- }
-
- // Ctr - From VCL utility classes (Members are exposed only of VCL headers have been included)
- //
- #if defined(DSTRING_H)
- TVariantT(const AnsiString& src)
- {
- ::VariantInit(this);
- *this = src.c_str();
- }
- #endif
- #if defined(SYSCURR_H)
- TVariantT(const Currency& src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(CY, *(reinterpret_cast<tagCY*>(&(const_cast<Currency&>(src).Val))))
- }
- TVariantT(Currency* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(CY, reinterpret_cast<tagCY*>(&(src->Val)));
- }
- #endif
- #if defined(SYSTDATE_H)
- TVariantT(const TDateTime& src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(DATE, src);
- }
- TVariantT(TDateTime* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(DATE, reinterpret_cast<DATE*>(src));
- }
- #endif
- #if defined(WSTRING_H)
- TVariantT(const WideString& src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(BSTR, src.Copy());
- }
- #endif
- #if defined(SYSTOBJ_H)
- // Ref-counted Dispatch interface object
- TVariantT(const System::DelphiInterface<IDispatch>& src)
- {
- ::VariantInit(this);
- if (!!src)
- src->AddRef();
- SET_VTYPE_AND_VAR(DISPATCH, src);
- }
- #endif
-
- // Asciiz pointer
- TVariantT(const char* src) // Treated as pointer Asciiz string
- {
- ::VariantInit(this);
- int size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, 0, 0);
- LPWSTR dst = ::SysAllocStringLen(0, size);
- ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, dst, size);
- SET_VTYPE_AND_VAR(BSTR, dst);
- }
-
- // Ctr - OLE ptrs
- // Set isSysString to False if TVariantT must allocate a copy of the WCHAR* passed in.
- // Otherwise, this constructor assumes that the WCHAR* was allocated via 'SysAlloc...'
- // and it takes ownership of the pointer.
- TVariantT(wchar_t* src, bool isSysString = true) // BSTR support
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VAR(BSTR, isSysString ? src : ::SysAllocString(src));
- }
- TVariantT(IUnknown* src)
- {
- ::VariantInit(this);
- if (src)
- src->AddRef();
- SET_VTYPE_AND_VAR(UNKNOWN, src);
- }
- TVariantT(IDispatch* src)
- {
- ::VariantInit(this);
- if (src)
- src->AddRef();
- SET_VTYPE_AND_VAR(DISPATCH, src);
- }
-
-
- //By ref constructors
-
- // NOTE: We cannot take a bool* since the sizes of VARIANT_BOOL and bool
- // differ. Instead we'll take a TOLEBOOL. Taking a VARIANT_BOOL*
- // is not distinguishable from a short pointer.
- //
- TVariantT(TOLEBOOL* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(BOOL, src);
- }
- TVariantT(signed char* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(I1, src);
- }
- TVariantT(unsigned char* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(UI1, src);
- }
- TVariantT(short* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(I2, src);
- }
- TVariantT(unsigned short* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(UI2, src);
- }
- TVariantT(int* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(I4, src);
- }
- TVariantT(unsigned int* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(UI4, src);
- }
- TVariantT(long* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(I4, src);
- }
- TVariantT(unsigned long* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(UI4, src);
- }
- TVariantT(float* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(R4, src);
- }
- TVariantT(double* src, bool isDate = false)
- {
- ::VariantInit(this);
- if (isDate)
- {
- SET_VTYPE_AND_VARREF(DATE, src);
- }
- else
- {
- SET_VTYPE_AND_VARREF(R8, src);
- }
- }
- TVariantT(CURRENCY* src)
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(CY, src);
- }
- TVariantT(SAFEARRAY** src)
- {
- ::VariantInit(this);
- SetSAFEARRAY(src);
- }
- TVariantT(wchar_t** src) // VT_BSTR|VT_BYREF
- {
- ::VariantInit(this);
- SET_VTYPE_AND_VARREF(BSTR, src);
- }
-
- // Helper for SAFEARRAY
- void SetSAFEARRAY(SAFEARRAY *psa)
- {
- VARTYPE _vt;
- ::SafeArrayGetVartype(psa, &_vt);
- vt = VT_ARRAY|_vt;
- V_ARRAY(this) = psa;
- }
- void SetSAFEARRAY(SAFEARRAY **ppsa)
- {
- VARTYPE _vt;
- ::SafeArrayGetVartype(*ppsa, &_vt);
- vt = VT_ARRAY|VT_BYREF|_vt;
- V_ARRAYREF(this) = ppsa;
- }
-
- // Assignments
- TVariantT& operator =(const TVariantT& rhs)
- {
- ::VariantClear(this);
- ::VariantCopy(this, &(const_cast<TVariantT&>(rhs)));
- return *this;
- }
- TVariantT& operator =(bool src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(BOOL, src ? VARIANT_TRUE : VARIANT_FALSE);
- return *this;
- }
- TVariantT& operator =(const TOLEBOOL& src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(BOOL, src ? VARIANT_TRUE : VARIANT_FALSE);
- return *this;
- }
- TVariantT& operator =(char src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(I1, src);
- return *this;
- }
- TVariantT& operator =(signed char src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(I1, src);
- return *this;
- }
- TVariantT& operator =(unsigned char src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(UI1, src);
- return *this;
- }
- TVariantT& operator =(short src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(I2, src);
- return *this;
- }
- TVariantT& operator =(unsigned short src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(UI2, src);
- return *this;
- }
- TVariantT& operator =(int src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(I4, src);
- return *this;
- }
- TVariantT& operator =(unsigned int src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(UI4, src);
- return *this;
- }
- TVariantT& operator =(long src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(I4, src);
- return *this;
- }
- TVariantT& operator =(unsigned long src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(UI4, src);
- return *this;
- }
- TVariantT& operator =(float src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(R4, src);
- return *this;
- }
- TVariantT& operator =(double src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(R8, src);
- return *this;
- }
- TVariantT& operator =(const CURRENCY& src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(CY, src);
- return *this;
- }
- TVariantT& operator =(SAFEARRAY* src)
- {
- ::VariantClear(this);
- SetSAFEARRAY(src);
- return *this;
- }
- TVariantT& operator =(SAFEARRAY& src)
- {
- ::VariantClear(this);
- SetSAFEARRAY(&src);
- return *this;
- }
- TVariantT& operator =(VARIANT& rhs)
- {
- ::VariantClear(this);
- ::VariantCopy(this, &rhs);
- return *this;
- }
- TVariantT& operator =(VARIANT* rhs)
- {
- ::VariantClear(this);
- // Can only have one level of indirection with VT_VARIANT
- //
- if (rhs && rhs->vt != VT_VARIANT && rhs->vt != (VT_VARIANT|VT_BYREF))
- {
- SET_VTYPE_AND_VARREF(VARIANT, rhs);
- }
- else
- {
- ::VariantCopy(this, rhs);
- }
- return *this;
- }
- #if defined(DSTRING_H)
- TVariantT& operator=(const AnsiString& src)
- {
- *this = src.c_str();
- return *this;
- }
- #endif
- #if defined(SYSCURR_H)
- TVariantT& operator=(const Currency& src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(CY, *(reinterpret_cast<tagCY*>(&(const_cast<Currency&>(src).Val))))
- return *this;
- }
- #endif
- #if defined(SYSTDATE_H)
- TVariantT& operator=(const TDateTime& src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(DATE, src);
- return *this;
- }
- #endif
- #if defined(WSTRING_H)
- TVariantT& operator=(const WideString& src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(BSTR, src.Copy());
- return *this;
- }
- #endif
- #if defined(SYSTOBJ_H)
- TVariantT& operator=(const System::DelphiInterface<IDispatch>& src)
- {
- ::VariantClear(this);
- if (!!src)
- src->AddRef();
- SET_VTYPE_AND_VAR(DISPATCH, src);
- return *this;
- }
- #endif
-
- TVariantT& operator =(wchar_t* src) // BSTR support
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(BSTR, src);
- return *this;
- }
- TVariantT& operator =(IUnknown* src)
- {
- ::VariantClear(this);
- if (src)
- src->AddRef();
- SET_VTYPE_AND_VAR(UNKNOWN, src);
- return *this;
- }
- TVariantT& operator =(IDispatch* src)
- {
- ::VariantClear(this);
- if (src)
- src->AddRef();
- SET_VTYPE_AND_VAR(DISPATCH, src);
- return *this;
- }
-
-
- // By ref Assignment
- // NOTE: We cannot take a 'bool*' - the size of VARIANT_BOOL and bool differ
- TVariantT& operator =(TOLEBOOL* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(BOOL, (VARIANT_BOOL*)src);
- return *this;
- }
- TVariantT& operator =(const char* src) // Treated as pointer Asciiz string
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VAR(BSTR, AnsiToOLESTR(src));
- return *this;
- }
- TVariantT& operator =(signed char* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(I1, reinterpret_cast<char*>(src));
- return *this;
- }
- TVariantT& operator =(unsigned char* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(UI1, src);
- return *this;
- }
- TVariantT& operator =(short* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(I2, src);
- return *this;
- }
- TVariantT& operator =(unsigned short* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(UI2, src);
- return *this;
- }
- TVariantT& operator =(int* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(I4, (long*)src);
- return *this;
- }
- TVariantT& operator =(unsigned int* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(UI4, reinterpret_cast<unsigned long*>(src));
- return *this;
- }
- TVariantT& operator =(long* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(I4, src);
- return *this;
- }
- TVariantT& operator =(unsigned long* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(UI4, src);
- return *this;
- }
- TVariantT& operator =(float* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(R4, src);
- return *this;
- }
- TVariantT& operator =(double* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(R8, src);
- return *this;
- }
- TVariantT& operator =(CURRENCY* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(CY, src);
- return *this;
- }
- TVariantT& operator =(SAFEARRAY** src)
- {
- ::VariantClear(this);
- SetSAFEARRAY(src);
- return *this;
- }
- TVariantT& operator =(wchar_t** src) // VT_BSTR|VT_BYREF
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(BSTR, src);
- return *this;
- }
- TVariantT& operator =(IUnknown** src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(UNKNOWN, src);
- return *this;
- }
- TVariantT& operator =(IDispatch** src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(DISPATCH, src);
- return *this;
- }
-
- #if defined(SYSCURR_H)
- TVariantT& operator=(Currency* src)
- {
- ::VariantClear(this);
- if(! (src==NULL))
- SET_VTYPE_AND_VARREF(CY, reinterpret_cast<tagCY*>(&(src->Val)));
- // else fail silently
- return* this;
- }
- #endif
- #if defined(SYSTDATE_H)
- TVariantT& operator=(TDateTime* src)
- {
- ::VariantClear(this);
- SET_VTYPE_AND_VARREF(DATE, src);
- return *this;
- }
- #endif
- #if defined(SYSTOBJ_H)
- TVariantT& operator=(const System::DelphiInterface<IDispatch>* src)
- {
- ::VariantClear(this);
- if (!!src)
- SET_VTYPE_AND_VARREF(DISPATCH, src);
- return *this;
- }
- #endif
-
- HRESULT ChangeType(VARTYPE vtNew, const VARIANT& src)
- {
- return ::VariantChangeType(this, &src, 0, vtNew);
- }
- HRESULT ChangeType(VARTYPE vtNew)
- {
- return ::VariantChangeType(this, this, 0, vtNew);
- }
-
- // Returns pointer to base Variant type when Variant holds other Variant
- //
- TVariantT* GetBaseVariant();
-
- // Conversion operators
- operator bool() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_BOOL);
- return V_BOOL(&v) != VARIANT_FALSE;
- }
- operator TOLEBOOL() const
- {
- return TOLEBOOL(bool(*this));
- }
- operator char() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_I1);
- return V_I1(&v);
- }
- operator signed char() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_I1);
- return V_I1(&v);
- }
- operator unsigned char() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_UI1);
- return V_UI1(&v);
- }
- operator short() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_I2);
- return V_I2(&v);
- }
- operator unsigned short() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_UI2);
- return V_UI2(&v);
- }
- operator int() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_I4);
- return V_I4(&v);
- }
- operator unsigned int() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_UI4);
- return V_UI4(&v);
- }
- operator long() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_I4);
- return V_I4(&v);
- }
- operator unsigned long() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_UI4);
- return V_UI4(&v);
- }
- operator float() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_R4);
- return V_R4(&v);
- }
- operator double() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_R8);
- return V_R8(&v);
- }
- #if defined(DSTRING_H)
- operator AnsiString() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_BSTR);
- WideString temp(V_BSTR(&v));
- AnsiString retval(temp);
- return retval;
- }
- #endif
- #if defined(SYSCURR_H)
- operator Currency() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_CY);
- Currency retval;
- retval.val = *v;
- return retval;
- }
- #endif
- #if defined(SYSTDATE_H)
- operator TDateTime() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_DATE);
- TDateTime retval(v.date);
- return retval;
- }
- #endif
- #if defined(WSTRING_H)
- operator WideString() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_BSTR);
- return WideString(::SysAllocString(V_BSTR(&v)));
- }
- #endif
-
- operator CURRENCY() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_CY);
- return V_CY(&v);
- }
- operator VARIANT() const
- {
- TVariantT v(*this);
- return v;
- }
-
- // NOTE: Caller must free SysString
- operator wchar_t*() const
- {
- TVariantT v(*this);
- v.ChangeType(VT_BSTR);
- return ::SysAllocString(V_BSTR(&v));
- }
-
- operator IUnknown*();
- operator IDispatch*();
-
- // by ref conversion operators
- /* operator char*(); */ // Dangerous - easily used as string instead of VT_I1|VT_BYREF
-
- operator signed char*()
- {
- if (vt == (VT_I1|VT_BYREF))
- return (signed char*)V_I1REF(this);
- else if (vt == VT_I1)
- return (signed char*)&(V_I1(this));
- }
- operator unsigned char*()
- {
- if (vt == (VT_UI1 | VT_BYREF))
- return V_UI1REF(this);
- else if (vt == VT_UI1)
- return &(V_UI1(this));
- }
- operator short*()
- {
- if (vt == (VT_I2|VT_BYREF))
- return V_I2REF(this);
- else if (vt == VT_I2)
- return &(V_I2(this));
- return NULL;
- }
- operator unsigned short*()
- {
- if (vt == (VT_UI2|VT_BYREF))
- return V_UI2REF(this);
- else if (vt == VT_UI2)
- return &(V_UI2(this));
- return NULL;
- }
- operator int*()
- {
- if (vt == (VT_I4|VT_BYREF))
- return (int*)V_I4REF(this);
- else if (vt == VT_I4)
- return (int*)&(V_I4(this));
- return NULL;
- }
- operator unsigned int*()
- {
- if (vt == (VT_UI4|VT_BYREF))
- return (unsigned int*)V_UI4REF(this);
- else if (vt == VT_UI4)
- return (unsigned int*)&(V_UI4(this));
- return NULL;
- }
- operator float*()
- {
- if (vt == (VT_R4|VT_BYREF))
- return V_R4REF(this);
- else if (vt == VT_R4)
- return &(V_R4(this));
- return NULL;
- }
- operator double*()
- {
- if (vt == (VT_R8|VT_BYREF))
- return V_R8REF(this);
- else if (vt == VT_R8)
- return &(V_R8(this));
- return NULL;
- }
- operator wchar_t**()
- {
- if (vt == (VT_BSTR|VT_BYREF))
- return V_BSTRREF(this);
- else if (vt == VT_BSTR)
- return V_BSTR(this);
- return NULL;
- }
- operator VARIANT*()
- {
- return reinterpret_cast<VARIANT*>(GetBaseVariant());
- }
-
- // NOTE: Caller must destroy SAFEARRAY*
- operator SAFEARRAY*()
- {
- SAFEARRAY *pSAOut = 0;
- if (vt & (VT_ARRAY|VT_BYREF))
- ::SafeArrayCopy(*V_ARRAYREF(this), &pSAOut);
- else if (vt & VT_ARRAY)
- ::SafeArrayCopy(V_ARRAY(this), &pSAOut);
- return pSAOut;
- }
-
- /*operator CURRENCY*() const;*/
- /*operator SAFEARRAY**() const;*/
-
- #if defined(SYSCURR_H)
- operator Currency*()
- {
- if (vt==(VT_CY|VT_BYREF))
- return reinterpret_cast<Currency*>(pcyVal);
- else if (vt==VT_CY)
- return reinterpret_cast<Currency*>(&cyVal);
- return NULL;
- }
- #endif
- #if defined(SYSTDATE_H)
- operator TDateTime*()
- {
- if (vt==(VT_DATE|VT_BYREF))
- return reinterpret_cast<TDateTime*>(pdate);
- else if (vt==VT_DATE)
- return reinterpret_cast<TDateTime*>(&date);
- return NULL;
- }
- #endif
-
- // Generic == operator (NOTE: Relies on conversion operator for TYPE)
- //
- template <class TYPE>
- bool operator == (TYPE rhs)
- {
- TVariant tmp(*this);
- return TYPE(tmp) == rhs;
- }
- };
-
- // Returns 'base-most' VARIANT pointed to by a TVariantT instance
- // (i.e. skip cases where VARIANT points to other VARIANT - VT_VARIANT)
- //
- template <class T>
- TVariantT<T>* TVariantT<T>::GetBaseVariant()
- {
- TVariantT *pVar = this;
-
- // NOTE: Technically there could only be one level of indirection for VT_VARIANT
- // Additionally, VT_VARIANT should always be used in combination with VT_BYREF
- // However, it does not hurt to catch multiple indirection or check a simple
- // VT_VARIANT VARTYPE. Never know what's being packed and sent down out there
- //
- while (((pVar->vt == VT_VARIANT) || (pVar->vt == (VT_VARIANT|VT_BYREF))) && (V_VARIANTREF(pVar)))
- pVar = reinterpret_cast<TVariantT*>(V_VARIANTREF(pVar));
- return pVar;
- }
-
-
- // Extracts an IUnknown* from the TVariantT instance.
- // NOTE: Caller must 'Release' interface.
- //
- template <class T>
- TVariantT<T>::operator IUnknown*()
- {
- // Handle easy case right away
- //
- if (vt==VT_NULL || vt==VT_EMPTY)
- return 0;
-
- IDispatch* disp;
- IUnknown* punk = 0;
- TVariantT* pVar = GetBaseVariant();
-
- // Get Data out of Variant
- //
- switch(pVar->vt)
- {
- case VT_UNKNOWN:
- case VT_UNKNOWN|VT_BYREF:
- punk = (vt==VT_UNKNOWN ? V_UNKNOWN(pVar) : (*(V_UNKNOWNREF(pVar))));
- punk->AddRef();
- return punk;
-
- case VT_DISPATCH:
- case VT_DISPATCH|VT_BYREF:
- disp = (vt==VT_DISPATCH ? V_DISPATCH(pVar) : (*(V_DISPATCHREF(pVar))));
- if (disp)
- disp->QueryInterface(IID_IUnknown, (LPVOID*)&punk);
- return punk;
-
- // Hopefully, we'll never get here, but as last resort
- //
- default:
- TVariantT v(*this);
- v.ChangeType(VT_UNKNOWN);
- V_UNKNOWN(&v)->AddRef();
- return V_UNKNOWN(&v);
- }
- }
-
-
- // Extracts an IDispatch* from the TVariantT instance.
- // NOTE: Caller must 'Release' interface.
- //
- template <class T>
- TVariantT<T>::operator IDispatch*()
- {
- // Handle easy case right away
- //
- if (vt==VT_NULL || vt==VT_EMPTY)
- return 0;
-
- IUnknown* punk;
- IDispatch* disp= 0;
- TVariantT* pVar= GetBaseVariant();
-
- // Get data out of Variant
- //
- switch(pVar->vt)
- {
- case VT_DISPATCH:
- case VT_DISPATCH|VT_BYREF:
- disp = (vt==VT_DISPATCH ? V_DISPATCH(pVar) : (*(V_DISPATCHREF(pVar))));
- if (disp)
- disp->AddRef();
- return disp;
-
- case VT_UNKNOWN:
- case VT_UNKNOWN|VT_BYREF:
- punk = (vt==VT_UNKNOWN ? V_UNKNOWN(pVar) : (*(V_UNKNOWNREF(pVar))));
- punk->QueryInterface(IID_IDispatch, (LPVOID*)&disp);
- return disp;
-
- default:
- TVariantT v(*pVar);
- v.ChangeType(VT_DISPATCH);
- V_DISPATCH(&v)->AddRef();
- return V_DISPATCH(&v);
- }
- }
-
-
- // Default VARIANT wrapper used by TAutoArgs
- //
- typedef TVariantT<VARIANT> TVariant;
- typedef TVariantT<VARIANT> VARIANTOBJ;
-
-
- // Template used to expose 'factory-like' Create/CreateRemote routines for Clients
- //
- template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
- class TCoClassCreatorT : public CoClassCreator
- {
- public:
- static TOBJ Create();
- static HRESULT Create(TOBJ& intfObj);
- static HRESULT Create(INTF** ppintf);
-
- static TOBJ CreateRemote(LPCWSTR machineName);
- static HRESULT CreateRemote(LPCWSTR machineName, TOBJ& intfObj);
- static HRESULT CreateRemote(LPCWSTR machineName, INTF** ppIntf);
- };
-
- template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
- TOBJ TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create()
- {
- TOBJ intfObj;
- OLECHECK(Create(intfObj));
- return intfObj;
- }
-
- template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
- HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create(TOBJ& intfObj)
- {
- INTF* pintf;
- HRESULT hr = Create(&pintf);
- if (SUCCEEDED(hr))
- intfObj = pintf;
- return hr;
- }
-
- template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
- HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create(INTF **ppIntf)
- {
- static TInitOle initOle;
- return CoCreateInstance(*clsid, *iid, (LPVOID*)ppIntf);
- }
-
- template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
- TOBJ TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName)
- {
- TOBJ intfObj;
- OLECHECK(CreateRemote(machineName, intfObj));
- return intfObj;
- }
-
- template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
- HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName, INTF **ppIntf)
- {
- static TInitOle initOle;
- COSERVERINFO serverInfo = {0, const_cast<LPWSTR>(machineName), 0, 0};
- MULTI_QI mqi = {iid, 0, 0};
- HRESULT hr = ::CoCreateInstanceEx(*clsid, 0,
- CLSCTX_REMOTE_SERVER,
- &serverInfo, 1, &mqi);
- if (SUCCEEDED(hr))
- *ppIntf = (INTF*)mqi.pItf;
- return hr;
- }
-
- template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
- HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName, TOBJ& intfObj)
- {
- INTF* pintf= 0;
- HRESULT hr = CreateRemote(machineName, &pintf);
- if (SUCCEEDED(hr))
- intfObj = pintf;
- return hr;
- }
-
-
- // Helper class for cases where VARIANT* or VARIANT& is expected for optional parameters
- //
- class TNoParam
- {
- public:
- TNoParam()
- {
- m_Variant.vt = VT_ERROR;
- V_ERROR(&m_Variant) = DISP_E_PARAMNOTFOUND;
- }
-
- operator VARIANT* () { return &m_Variant;}
- operator VARIANT& () { return m_Variant; }
- operator TVariant* () { return &m_Variant;}
- operator TVariant& () { return m_Variant; }
-
- private:
- TVariant m_Variant;
- };
-
- // Helper class for default LOCALE values
- //
- class TDefLCID
- {
- public:
- TDefLCID(LCID lcid = LOCALE_SYSTEM_DEFAULT) : m_Lcid(lcid) {}
- operator LCID () const { return m_Lcid; }
-
- protected:
- LCID m_Lcid;
- };
-
-
- // Base class that exposes basic behaviour of our array of Variants
- //
- class TAutoArgsBase
- {
- protected:
- TAutoArgsBase(VARIANTOBJ *pVariant, int count) : m_Variant(pVariant), m_Count(count)
- {}
-
- public:
- VARIANTOBJ& operator[](int index) const
- {
- // NOTE: It's OK to use Count - there's an extra Variant for return result
- // Zero'th entry's reserved for return value.
- //
- _ASSERTE_(index <= m_Count);
- _ASSERTE_(index >= 0);
-
- // Make up for C++ vs. Basic reverse indexing
- //
- return m_Variant[index ? (m_Count+1-index) : 0];
- }
-
- VARIANT* GetRetVal() const
- {
- return (VARIANT*)(m_Variant);
- }
-
- VARIANTOBJ& GetRetVariant()
- {
- return *m_Variant;
- }
-
- VARIANT* GetArgs() const
- {
- return (VARIANT*)(m_Variant+1);
- }
-
- int GetCount() const
- {
- return m_Count;
- }
-
- private:
- TAutoArgsBase(const TAutoArgsBase&);
- TAutoArgsBase& operator=(const TAutoArgsBase&);
-
- VARIANTOBJ *m_Variant;
- int m_Count;
- };
-
-
- // TAutoArgs - Encapsulates array of Variants. Use for Invoke calls
- //
- template <int Count>
- class TAutoArgs : public TAutoArgsBase
- {
- public:
- TAutoArgs();
- ~TAutoArgs();
-
- private:
- // Allocate an extra Variant. It's the first entry and
- // it is reserved for return result. The rest are for parameters
- //
- VARIANTOBJ m_Array[Count+1];
- };
-
-
- // Build an array of Count (actualy Count+1, extra one for return value)
- // of VARIANTs.
- //
- template <int Count>
- TAutoArgs<Count>::TAutoArgs() : TAutoArgsBase(m_Array, Count)
- {}
-
- // Cleanup array of Variants
- //
- template <int Count>
- TAutoArgs<Count>::~TAutoArgs()
- {}
-
- // Enumeration describing DISPATCH type
- //
- enum DispatchFlag
- {
- dfMethod = DISPATCH_METHOD,
- dfPropGet = DISPATCH_PROPERTYGET,
- dfPropPut = DISPATCH_PROPERTYPUT,
- dfPropPutRef= DISPATCH_PROPERTYPUTREF
- };
-
- // Sets the value in the returnVariant to the retVal variable if SUCCEEDED(hr)
- // Used by DispInterface Code Generated by TLIBIMP
- //
- template <class T>
- HRESULT OutRetValSetterPtr(T* retVal, TAutoArgsBase& args, HRESULT hr)
- {
- if (SUCCEEDED(hr))
- *retVal = T(args.GetRetVariant());
- return hr;
- }
-
- // Sets the value in the returnVariant to the retVal variable if SUCCEEDED(hr)
- // Used by DispInterface Code Generated by TLIBIMP
- template <class T>
- HRESULT OutRetValSetterRef(T& retVal, TAutoArgsBase& args, HRESULT hr)
- {
- if (SUCCEEDED(hr))
- retVal = T(args.GetRetVariant());
- return hr;
- }
-
-
- // Base class of smart interface wrappers - provides an optional parameter
- //
- template <class INTF>
- class TComInterfaceBase
- {
- public:
- static TNoParam OptParam;
- static LCID lcid;
- static VARIANT_BOOL Variant_False;
- static VARIANT_BOOL Variant_True;
- };
-
- // Static/shared instance of 'Optional parameter' and 'lcid' settings
- //
- template <class T>
- TNoParam TComInterfaceBase<T>::OptParam;
- template <class T>
- LCID TComInterfaceBase<T>::lcid = LOCALE_SYSTEM_DEFAULT;
- template <class T>
- VARIANT_BOOL TComInterfaceBase<T>::Variant_False = VARIANT_FALSE;
- template <class T>
- VARIANT_BOOL TComInterfaceBase<T>::Variant_True = VARIANT_TRUE;
-
- // Base class of AutoDrivers - provides an optional parameter
- //
- template <class DISPINTF>
- class TAutoDriverBase
- {
- public:
- static TNoParam OptParam;
- static VARIANT_BOOL Variant_False;
- static VARIANT_BOOL Variant_True;
- static TInitOle InitOle;
- };
-
- // Static/shared instance of 'Optional Parameter'
- //
- template <class T>
- TNoParam TAutoDriverBase<T>::OptParam;
- template <class T>
- VARIANT_BOOL TAutoDriverBase<T>::Variant_False = VARIANT_FALSE;
- template <class T>
- VARIANT_BOOL TAutoDriverBase<T>::Variant_True = VARIANT_TRUE;
- template <class T>
- TInitOle TAutoDriverBase<T>::InitOle;
-
- // TAutoDriver - DispInterface Automation Proxy Driver
- //
- template <class DISPINTF>
- class TAutoDriver : public TAutoDriverBase<IDispatch>
- {
- public:
- TAutoDriver(LCID lcid = LOCALE_SYSTEM_DEFAULT);
- TAutoDriver(const TAutoDriver<DISPINTF> &src);
- ~TAutoDriver();
-
- // Bind via various mechanisms & Unbind
- // NOTE: Does *NOT* AddRef interface by default
- //
- void Bind(DISPINTF *pintf, bool addRef = false);
- HRESULT Bind(LPUNKNOWN punk);
- HRESULT Bind(const GUID& guid);
- HRESULT Bind(LPCWSTR progid);
-
- // Bind to running copy of Server
- //
- HRESULT BindToActive(const GUID& guid);
- HRESULT BindToActive(LPCWSTR propid);
-
- // Bind to remote server
- //
- HRESULT BindToRemote(LPCWSTR machineName, const CLSID& clsid);
-
- // Unbind from DispInterface
- //
- void Unbind(bool release = true);
-
- // Assignment of interface to object implies Bind to interface
- //
- TAutoDriver<DISPINTF>& operator =(DISPINTF *pintf)
- {
- Bind(pintf);
- return *this;
- }
-
- // Return Dispatch Interface
- //
- operator DISPINTF*() const;
-
- // Bound or not?
- //
- bool IsBound() const;
- bool operator ! () const { return m_Dispatch == 0; }
- operator bool () const { return m_Dispatch != 0; }
-
- // Allows access to interface being held
- // NOTE: Useful when dealing with dual interfaces
- // Using '->' yields Vtable call while '.' yields Invoke call
- DISPINTF* operator -> ()
- {
- return m_Dispatch;
- }
-
- // Return address of interface
- //
- DISPINTF** operator & ()
- {
- // Can take address (to presumably stuff new interface pointer) only if
- // not currently Bound;
- _ASSERTE_(m_Dispatch==0);
- return &m_Dispatch;
- }
-
- // Wrappers of IDispatch methods
- //
- HRESULT GetIDsOfNames(LPCWSTR name, DISPID &id);
- HRESULT Invoke(DispatchFlag dFlags, LPCWSTR name, TAutoArgsBase* args, bool hasRetVal = true);
- HRESULT Invoke(DispatchFlag dFlags, DISPID dispId, TAutoArgsBase* args, bool hasRetVal = true);
-
- // Access to LCID settings
- //
- LCID get_lcid() const { return m_lcid;}
- void set_lcid(LCID l) { m_lcid = l; }
-
- // Access to EXCEPINFO
- //
- EXCEPINFO& get_excepinfo() const { return m_ExcepInfo; }
-
- // Properties
- //
- __property LCID lcid = { read = get_lcid, write = set_lcid };
- __property EXCEPINFO excepinfo = { read = get_excepinfo };
-
- // Procedures with/without parameters
- //
- HRESULT OleProcedure(DISPID dispId, TAutoArgsBase& args)
- {
- return Invoke(dfMethod, dispId, &args, false);
- }
- HRESULT OleProcedure(DISPID dispid)
- {
- return Invoke(dfMethod, dispid, 0, false);
- }
-
- // FUnctions with/without parameters
- HRESULT OleFunction(DISPID dispid, TAutoArgsBase& args)
- {
- return Invoke(dfMethod, dispid, &args, true);
- }
- HRESULT OleFunction(DISPID dispid)
- {
- return Invoke(dfMethod, dispid, 0, false);
- }
-
- // Property put (always has parameters)
- HRESULT OlePropertyPut(DISPID dispid, TAutoArgsBase& args)
- {
- return Invoke(dfPropPut, dispid, &args, false);
- }
-
- // Property get (always has parameters, even if just TAutoArgs<0>)
- HRESULT OlePropertyGet(DISPID dispid, TAutoArgsBase& args)
- {
- return Invoke(dfPropGet, dispid, &args, true);
- }
-
- // Property get that returns VARIANT
- VARIANTOBJ OlePropertyGet(DISPID dispid);
-
- protected:
-
- typedef TDispId<DISPINTF> _TDispID;
-
- // Functions hold and let go of interface (no AddRef or Releases)
- // Used by Events interface wrappers
- //
- void Attach(DISPINTF *pintf) { m_Dispatch = pintf;}
- void Detach() { m_Dispatch = 0; }
-
- DISPINTF *m_Dispatch; // Disp Interface Pointer
- LCID m_lcid; // Locale for DispId lookup & Invoke
- EXCEPINFO m_ExcepInfo; // Exception Structure
- UINT m_ErrArg; // Index of erroneous argument
- };
-
-
- // TDispIdBase - Base class used by TDispId; allows us to have only one copy of the
- // flag governing whether DISPID should be looked up
- template <class T>
- class TDispIdBase
- {
- public:
- static bool m_AlwaysGetDispid;
- };
-
- // This flag triggers a lookup even if the object was pass a valid (non -1) dispid!
- // (Be careful if you enable this: Source interfaces do not typically expect a GetIDsofNames call)
- //
- template <class T>
- bool TDispIdBase<T>::m_AlwaysGetDispid = false;
-
- // TDispId - Class used to retrieve and cache a DISPID
- //
- template<class DISPINTF>
- class TDispId : public TDispIdBase<DISPINTF>
- {
- public:
- TDispId(TAutoDriver<DISPINTF>& dispatch, LPCWSTR pName, DISPID id= DISPID_UNKNOWN) : m_DispId(id),
- m_HResult(S_OK)
- {
- if (id == DISPID_UNKNOWN || m_AlwaysGetDispid)
- m_HResult = GetID(dispatch, pName);
- }
-
- TDispId(DISPID id) : m_DispId(id), m_HResult(S_OK)
- {}
-
- HRESULT GetID(TAutoDriver<DISPINTF>& dispatch, LPCWSTR pName)
- {
- return dispatch.GetIDsOfNames(pName, m_DispId);
- }
-
- operator DISPID() const
- {
- return m_DispId;
- }
-
- HRESULT GetResult() const
- {
- return m_HResult;
- }
-
-
- protected:
- DISPID m_DispId;
- HRESULT m_HResult;
- };
-
-
- // Ctr & Dtr of Automation Driver class
- //
- template <class DISPINTF>
- TAutoDriver<DISPINTF>::TAutoDriver(LCID lcid) : m_Dispatch(0), m_lcid(lcid)
- {}
-
- //
- template <class DISPINTF>
- TAutoDriver<DISPINTF>::TAutoDriver(const TAutoDriver<DISPINTF> &src)
- {
- // NOTE: We do not copy the Exception, ErrArg or InitOle object
- // We simply clear them out
- m_ErrArg = 0;
- ::ZeroMemory(&m_ExcepInfo, sizeof(m_ExcepInfo));
-
- // Copy Interface and AddRefCount
- m_Dispatch = src.m_Dispatch;
- if (m_Dispatch)
- m_Dispatch->AddRef();
-
- // Copy Locale
- m_lcid = src.m_lcid;
- }
-
- template <class DISPINTF>
- TAutoDriver<DISPINTF>::~TAutoDriver()
- {
- Unbind();
- }
-
- // Bind via Dispatch Interface
- // NOTE: Does *NOT* AddRef interface
- //
- template <class DISPINTF> void
- TAutoDriver<DISPINTF>::Bind(DISPINTF *pintf, bool addRef)
- {
- Unbind();
- m_Dispatch = pintf;
- if (m_Dispatch && addRef)
- m_Dispatch->AddRef();
- }
-
- // Bind via IUnknown
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Bind(LPUNKNOWN punk)
- {
- _ASSERTE(punk);
- HRESULT hr = E_POINTER;
- if (punk)
- {
- DISPINTF *disp;
- hr = punk->QueryInterface(/* __uuidof(DISPINTF) */ IID_IDispatch, (LPVOID*)&disp);
- if (SUCCEEDED(hr))
- Bind(disp, false /* Don't AddRef */);
- }
- return hr;
- }
-
- // Bind via GUID
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Bind(const GUID& clsid)
- {
- static TInitOle initOle;
-
- LPUNKNOWN punk = 0;
- HRESULT hr = CoClassCreator::CoCreateInstance(clsid, IID_IUnknown, (LPVOID*)&punk);
- if (SUCCEEDED(hr))
- {
- // We should have a valid interface pointer
- //
- _ASSERTE(punk);
-
- // Run Object - just in case
- //
- hr = ::OleRun(punk);
-
- // Bind to running IUnknown
- //
- if (SUCCEEDED(hr))
- hr = Bind(punk);
-
- // Release IUnknown
- //
- punk->Release();
- }
- return hr;
- }
-
- // Bind via ProgId
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Bind(LPCWSTR progid)
- {
- GUID clsid;
- HRESULT hr = ::CLSIDFromProgID(progid, &clsid);
- if (SUCCEEDED(hr))
- return Bind(clsid);
- return hr;
- }
-
- // Bind to running copy of Object of this CLSID
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::BindToActive(const GUID& guid)
- {
- LPUNKNOWN punk = 0;
- HRESULT hr = ::GetActiveObject(guid, 0, &punk);
- if (SUCCEEDED(hr))
- return Bind(punk);
- return hr;
- }
-
- // Bind to running copy of object with the specified progId
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::BindToActive(LPCWSTR progid)
- {
- CLSID clsid;
- HRESULT hr = ::CLSIDFromProgID(progid, &clsid);
- if (SUCCEEDED(hr))
- return BindToActive(clsid);
- return hr;
- }
-
- // Bind to remote server on specified machine
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::BindToRemote(LPCWSTR machineName, const CLSID& clsid)
- {
- // Must unbind before binding to remote server
- //
- _ASSERTE(!IsBound());
- DISPINTF *pIntf;
- HRESULT hr = TCoClassCreatorT< TAutoDriver<DISPINTF>, DISPINTF,
- clsid,
- IID_IDispatch>::CreateRemote(machineName, &pIntf);
- if (SUCCEEDED(hr))
- Bind(pIntf);
- return hr;
- }
-
- // Release Dispatch Interface
- //
- template <class DISPINTF> void
- TAutoDriver<DISPINTF>::Unbind(bool release)
- {
- if (release && m_Dispatch)
- m_Dispatch->Release();
- m_Dispatch = 0;
- }
-
- // Return Dispatch Interface
- //
- template <class DISPINTF>
- TAutoDriver<DISPINTF>::operator DISPINTF* () const
- {
- return m_Dispatch;
- }
-
- // Returns Boolean indicating whether we're currently bound to the Server
- //
- template <class DISPINTF> bool
- TAutoDriver<DISPINTF>::IsBound() const
- {
- return m_Dispatch != 0;
- }
-
- // Encapsulation of IDispatch->GetIDsOfNames
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::GetIDsOfNames(LPCWSTR name, DISPID &id)
- {
- _ASSERTE(name);
- _ASSERTE(IsBound());
- return m_Dispatch->GetIDsOfNames(IID_NULL, (LPWSTR*)(&name), 1, m_lcid, &id);
- }
-
- // Invoke specified 'name'
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Invoke(DispatchFlag dFlags, LPCWSTR name, TAutoArgsBase* args, bool hasRetVal)
- {
- DISPID dispid;
- HRESULT hr = GetIDsOfNames(name, dispId);
- if (SUCCEEDED(hr))
- hr = Invoke(dFlags, dispid, args);
- return hr;
- }
-
- // Invoke specified 'DispId'
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Invoke(DispatchFlag dFlags, DISPID dispid, TAutoArgsBase* args, bool hasRetVal)
- {
- _ASSERTE(IsBound());
-
- VARIANT* retVal = 0;
-
- // Having return value implies an Args array (even if it contains only one
- // variant for the return value).
- //
- _ASSERTE((hasRetVal==false && args==0) ||
- (hasRetVal==false && args!=0) ||
- (hasRetVal==true && args!=0));
-
- // Setup return VARIANT
- // NOTE: PROPERTYPUTs do not return a result
- //
- if (!(dFlags & (dfPropPut|dfPropPutRef)) && hasRetVal)
- retVal = args->GetRetVal();
-
- // Special DispId for Property Puts
- //
- static DISPID DispIdPropertyPut = DISPID_PROPERTYPUT;
-
- // Setup DISPATCH parameters
- //
- DISPPARAMS params;
- ::ZeroMemory(¶ms, sizeof(params));
-
- // Set parameters (Note: PropPut[Ref] expected to have Count)
- if (args && args->GetCount())
- {
- params.cArgs = args->GetCount();
- params.rgvarg= args->GetArgs();
-
- // Handle PROPERTYPUT
- // NOTE: Assumes no named-arguments params have been setup
- //
- if (dFlags & (dfPropPut|dfPropPutRef))
- {
- params.cNamedArgs = 1;
- params.rgdispidNamedArgs = &DispIdPropertyPut;
- }
- }
-
- // Reset Error Information
- m_ErrArg = 0;
- ::ZeroMemory(&m_ExcepInfo, sizeof(m_ExcepInfo));
-
- // Invoke
- HRESULT hr = m_Dispatch->Invoke(dispid, IID_NULL, m_lcid, WORD(dFlags), ¶ms,
- retVal, &m_ExcepInfo, &m_ErrArg);
-
- // Check for deferred EXCEPTION fill-in
- if (hr == DISP_E_EXCEPTION)
- if (m_ExcepInfo.pfnDeferredFillIn)
- (*(m_ExcepInfo.pfnDeferredFillIn))(&m_ExcepInfo);
-
- // Turn on '__CHECKHR_ON_INVOKE' when you're debugging calls using the DISP wrappers
- //
- #if defined(__CHECKHR_ON_INVOKE)
- OLECHECK(hr);
- #endif
-
- // Output a little trace
- OLETRACE("Inv(%d) %s, 0x%lX, retVT(0x%X), ErrArg(%d)\n",
- dispid, SUCCEEDED(hr) ? "OK" : "FL", LONG(hr),
- retVal ? retVal->vt : VT_NULL, m_ErrArg);
-
- // Return result
- return hr;
- }
-
- // Property Get that returns a Variant (takes no parameters)
- //
- template <class DISPINTF> VARIANTOBJ
- TAutoDriver<DISPINTF>::OlePropertyGet(DISPID dispid)
- {
- TAutoArgs<0> args;
- OlePropertyGet(dispid, args);
- return args.GetRetVariant();
- }
-
- #endif // UTILCLS_NO_AUTOMATION
-
- // Wrapper class encapsulating a DLL
- //
- class TDll
- {
- public:
- TDll(LPCTSTR name) : m_Hinstance(::LoadLibrary(name)) {}
- ~TDll()
- {
- if (m_Hinstance)
- ::FreeLibrary(m_Hinstance);
- }
-
- operator HINSTANCE() const { return m_Hinstance; }
- FARPROC GetProcAddress(LPCTSTR funcName) const { return ::GetProcAddress(*this, funcName); }
-
- protected:
- HINSTANCE m_Hinstance;
-
- private:
- TDll(const TDll&);
- const TDll& operator=(const TDll&);
- };
-
- // TDllProc: Encapsulates a DLL EntryPoint/FARPROC
- //
- class TDllProc
- {
- public:
- TDllProc(const TDll& dll, LPCTSTR funcName)
- {
- m_Proc = dll.GetProcAddress(funcName);
- }
- operator bool() { return m_Proc != 0; }
- protected:
- FARPROC m_Proc;
- };
-
- // FARPROC that's CDECL, returns HRESULT and takes one parameter
- //
- template <class P1>
- class TDllProc1 : public TDllProc
- {
- public:
- TDllProc1(const TDll& dll , LPCTSTR funcName) : TDllProc(dll, funcName) {};
- HRESULT operator ()(P1 erste)
- {
- typedef HRESULT (__cdecl* outproc)(P1 erste);
- return ((outproc)m_Proc)(erste);
- }
- };
-
- // FARPROC that's STDCALL, returns HRESULT and take two parameters
- //
- template <class P1, class P2>
- class TDllStdProc2 : public TDllProc
- {
- public:
- TDllStdProc2(const TDll& dll, LPCTSTR funcName) : TDllProc(dll, funcName) {}
- HRESULT operator () (P1 p1, P2 p2)
- {
- typedef HRESULT (__stdcall* outproc)(P1 p1, P2 p2);
- return ((outproc)m_Proc)(p1, p2);
- }
- };
-
- #endif __UTILCLS_H
-