home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 May / PCP163A.iso / Runimage / Cbuilder4 / Source / Vcl / UTILCLS.H < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-26  |  61.9 KB  |  2,579 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // UTILCLS.H - Utility Classes
  3. //
  4. // $Revision:   1.32.1.34  $
  5. // $Date:   20 Jan 1999 17:58:28  $
  6. //
  7. // Copyright (c) 1998, 1999 Borland International              
  8. /////////////////////////////////////////////////////////////////////////////
  9. #ifndef __UTILCLS_H
  10. #define __UTILCLS_H
  11.  
  12. // To keep track of version of UTILITY class header
  13. //
  14. #define __UTILCLS_H_VERSION 0x0101
  15.  
  16. #include <objbase.h>
  17. #include <oleauto.h>
  18. #include <cguid.h>
  19. #include <stdarg.h>
  20. #include <tchar.h>
  21.  
  22. #if defined(DEBUG)
  23. #include <ocidl.h>
  24. #if sizeof(QACONTAINER) != 64
  25. #error sizeof(QACONTAINER) is off!! 
  26. #endif
  27. #if sizeof(TLIBATTR) != 32
  28. #error sizeof(TLIBATTR) is off !!
  29. #endif
  30. #endif  // DEBUG
  31.  
  32.  
  33. // Typedefs to avoid 'simple type expected' error from compiler 
  34. //
  35. typedef signed   char    signed_char;
  36. typedef unsigned char    unsigned_char;
  37. typedef unsigned short   unsigned_short;
  38. typedef unsigned long    unsigned_long;
  39. typedef unsigned __int64 unsigned_int64;
  40.  
  41. // Forward ref.
  42. //
  43. template <class DISPINTF = IDispatch>
  44. class TAutoDriver;
  45. template <class DISPINTF = IDispatch>
  46. class TDispId;
  47.  
  48. //////////////////////////////////////////////////////////////////////////////
  49. // Macros
  50. //////////////////////////////////////////////////////////////////////////////
  51.  
  52. // Until Compiler supports __declspec(uuid(....)) [and __uuidof(...)]
  53. //
  54. #if !defined(DECLSPEC_UUID)
  55. #define DECLSPEC_UUID(guid)
  56. #endif
  57.  
  58. // CONNECTIONPOINT_ARRAY_SIZE is used by the Fire_xxxx Event templates generated for
  59. // outgoing interfaces in the xxxx_TLB.H file.
  60. //
  61. #if !defined(CONNECTIONPOINT_ARRAY_SIZE)
  62. #define CONNECTIONPOINT_ARRAY_SIZE  5
  63. #endif
  64.  
  65. #if !defined(OLETEXT)
  66. #define OLETEXT(x)  L ## x
  67. #endif
  68.  
  69. #if !defined(NO_PROMPT_ON_ASSSERTE_FAILURE)
  70. #define PROMPT_ON_ASSERTE_FAILURE 1
  71. #endif
  72. #if !defined(NO_PROMPT_ON_HRCHECK_FAILURE)
  73. #define PROMPT_ON_HRCHECK_FAILURE 1
  74. #endif
  75.  
  76. // Implementation of TRACE_HLPR
  77. //
  78. template <class T>
  79. class TDebugHlpr
  80. {
  81. public:
  82.   static void __cdecl TRACE_HLPR(T* szFormat, ...);   
  83. };
  84.  
  85. // Implementation of OLECHECK - Throw an exception if !SUCCEEDED(hr)
  86. //
  87. template <class T>
  88. HRESULT DebugHlpr_HRCHECK(HRESULT hr, T* expr, T* file, int line)
  89. {
  90.   if (!SUCCEEDED(hr))
  91.   {
  92.     TCHAR szMsg[_MAX_PATH*2];
  93.  
  94.     if (!file)
  95.       file = _T("");
  96.  
  97.     LPVOID msg = 0;
  98.     if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, hr,
  99.                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), LPTSTR(&msg), 0, 0) && (msg != 0))
  100.     {
  101.       ::wsprintf(szMsg, _T("'%s': %s @ %s/%d"), expr, LPTSTR(msg), file, line);
  102.       ::LocalFree(msg);
  103.     }
  104.     else
  105.       ::wsprintf(szMsg, _T("(%s) Error: %lX (%ld) @ %s/%d"), expr, LONG(hr), LONG(hr), file, line);
  106.  
  107. #if !defined(PROMPT_ON_HRCHECK_FAILURE)
  108.     int i = IDYES;
  109. #else
  110.     int i = DebugHlpr_PROMPT(_T("HRCHECK: "), szMsg);
  111. #endif
  112.     if (i == IDYES)
  113.       DebugHlpr_THROW(szMsg);
  114.     else if (i == IDCANCEL)
  115.       ::DebugBreak();
  116.     // NOTE: IDNO - implies we keep chugging along
  117.   }
  118.  
  119.   return hr;
  120. }
  121.  
  122. // _ASSERTE helper return MB_YES, MB_NO or MB_CANCEL
  123. //
  124. template <class T>
  125. int DebugHlpr_ASSERTE(T* expr, T* file, int line)
  126. {
  127.   TCHAR msg[_MAX_PATH*2];
  128.   ::wsprintf(msg, _T("%s @ %s/%d"), LPTSTR(expr), file, line);
  129.  
  130. #if !defined(PROMPT_ON_ASSERTE_FAILURE)
  131.   int i = IDYES;
  132. #else
  133.   int i = DebugHlpr_PROMPT(_T("_ASSERTE: "), msg);
  134. #endif
  135.  
  136.   if (i == IDYES)
  137.   {
  138.     ::wsprintf(msg, _T("%s failed - %s/%d"), expr, file, line);
  139.     DebugHlpr_THROW(msg);
  140.   }
  141.   return i;
  142. }
  143.  
  144. // Helper used to throw an exception
  145. //
  146. template <class T>
  147. void DebugHlpr_THROW(T* msg)
  148. {
  149.   /* THROW SOMETHING BETTER */
  150.   throw msg;
  151. }
  152.  
  153. // Helper used to display a MessageBox
  154. //
  155. template <class T>
  156. int DebugHlpr_PROMPT(T* caption, T* msg)
  157. {
  158.   TCHAR szMsg[_MAX_PATH*2];
  159.   wsprintf(szMsg, _T("%s\nPress [Y]es to terminate, [N]o to continue and [C]ancel to Debug"), msg);
  160.   return ::MessageBox(0, szMsg, caption, MB_TASKMODAL|MB_ICONQUESTION|MB_YESNOCANCEL);
  161. }
  162.  
  163.  
  164. #if !defined(OLETRACE)
  165. #define OLETRACE  TDebugHlpr<TCHAR>::TRACE_HLPR
  166. #endif
  167.  
  168. #if !defined(OLECHECK)
  169. #define OLECHECK(hrexpr) DebugHlpr_HRCHECK(hrexpr, #hrexpr, __FILE__, __LINE__)
  170. #endif
  171.  
  172. #if !defined(_ASSERTE)
  173. #define  _ASSERTE(expr) do {                                                            \
  174.   if (!(expr) && DebugHlpr_ASSERTE(#expr, __FILE__, __LINE__) == IDCANCEL)              \
  175.     ::DebugBreak();                                                                     \
  176. } while (0)
  177. #endif
  178.  
  179.  
  180. // Version of _ASSERTE usable within inline functions
  181. // i.e. Does not have do/while construct which is not allowed in inline functions currently
  182. //
  183. #if !defined(_ASSERTE_)
  184. #define _ASSERTE_(expr)   ((expr) ? (0) : DebugHlpr_ASSERTE(#expr, __FILE__, __LINE__))
  185. #endif
  186.  
  187. template <class T>
  188. void __cdecl TDebugHlpr<T>::TRACE_HLPR(T* szFormat, ...)
  189. {
  190.   va_list args;
  191.   va_start(args, szFormat);
  192.   int   bufSize;
  193.   TCHAR szBuffer[_MAX_PATH*2];
  194.   bufSize = wvsprintf(szBuffer, szFormat, args);
  195.   _ASSERTE(bufSize < sizeof(szBuffer));
  196.   ::OutputDebugString(szBuffer);
  197.   va_end(args);
  198. }
  199.  
  200.  
  201. // Template to 'hide' some functions for string conversions
  202. //
  203. template <class T = TCHAR>
  204. class TStringConverter
  205. {
  206. public:
  207.   static  LPSTR     WideToAnsi(LPCWSTR    src);
  208.   static  LPWSTR    AnsiToWide(LPCSTR     src);
  209.   static  LPWSTR    AnsiToOLESTR(LPCSTR   src);
  210.   static  LPWSTR    WideToOLESTR(LPCWSTR  src);
  211.   static  TCHAR*    strnewdup(const T*    src);
  212. };
  213.  
  214.  
  215. // String Helper conversion routines
  216. // NOTE: Return value must be deleted[]
  217. //
  218. template <class T> LPSTR
  219. TStringConverter<T>::WideToAnsi(LPCWSTR src)
  220. {
  221.    int size = ::WideCharToMultiByte(CP_ACP, 0, src, -1, 0, 0, 0, 0);
  222.    LPSTR dst = new char[size];
  223.    size = ::WideCharToMultiByte(CP_ACP, 0, src, -1, dst, size, 0, 0);
  224.    _ASSERTE(size != 0);
  225.    return dst;
  226. }
  227.  
  228. // NOTE: Return value must be passed to '::SysFreeString'
  229. //
  230. template <class T> OLECHAR*
  231. TStringConverter<T>::AnsiToOLESTR(LPCSTR src)
  232. {
  233.    int size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, 0, 0);
  234.    LPWSTR dst = ::SysAllocStringLen(0, size);
  235.    size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, dst, size);
  236.    _ASSERTE(size != 0);
  237.    return dst;
  238. }
  239.  
  240. // NOTE: Return value must be deleted[]
  241. //
  242. template <class T> LPWSTR
  243. TStringConverter<T>::AnsiToWide(LPCSTR src)
  244. {
  245.    int size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, 0, 0);
  246.    LPWSTR dst = new wchar_t[size];
  247.    size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, dst, size);
  248.    _ASSERTE(size != 0);
  249.    return dst;
  250. }
  251.  
  252. // NOTE: Return value must be  passed to '::SysFreeString'
  253. //
  254. template <class T> OLECHAR*
  255. TStringConverter<T>::WideToOLESTR(LPCWSTR src)
  256. {
  257.    return ::SysAllocString(src);
  258. }
  259.  
  260. // NOTE: Return value must be deleted[]
  261. //
  262. template <class T> TCHAR*
  263. TStringConverter<T>::strnewdup(const T* str)
  264. {
  265.    _ASSERTE(str);
  266.    return lstrcpy(new TCHAR[lstrlen(str)+1], str);
  267. }
  268.  
  269.  
  270. // Return value must be deleted[]
  271. //
  272. inline LPSTR WideToAnsi(LPCWSTR src)
  273. {
  274.   return TStringConverter<TCHAR>::WideToAnsi(src);
  275. }
  276.  
  277. // NOTE: Return value must be passed to '::SysFreeString'
  278. //
  279. inline OLECHAR* AnsiToOLESTR(LPCSTR src)
  280. {
  281.   return TStringConverter<TCHAR>::AnsiToOLESTR(src);
  282. }
  283.  
  284. // NOTE: Return value must be '::SysFreeString'
  285. //
  286. inline OLECHAR* WideToOLESTR(LPCWSTR src)
  287. {
  288.   return TStringConverter<TCHAR>::WideToOLESTR(src);
  289. }
  290.  
  291. // NOTE: Return value must be delete[]
  292. //
  293. inline TCHAR* strnewdup(LPCSTR str)
  294. {
  295.    _ASSERTE_(str);
  296.    return TStringConverter<TCHAR>::strnewdup(str);
  297. }
  298.  
  299.  
  300. // Wrapper for freeing BSTRs
  301. //
  302. class TOleString
  303. {
  304. public:
  305.   TOleString(BSTR bstr) : m_bstr(bstr) {}
  306.   TOleString(const CHAR *str) : m_bstr(str ? AnsiToOLESTR(str) : 0) {}
  307.  ~TOleString() { ::SysFreeString(m_bstr); }
  308.  
  309.   operator BSTR() const { return m_bstr;}
  310.  
  311. protected:
  312.   BSTR     m_bstr;
  313. };
  314.  
  315.  
  316. // Cheap coder's quick buffer wrapper...
  317. //
  318. template <int LEN>
  319. class TCharBuff
  320. {
  321. public:
  322.   TCharBuff() : m_Data(new TCHAR[LEN])            { m_Data[0] = 0;   }
  323.   TCharBuff(LPCTSTR src) : m_Data(new TCHAR[LEN]) { *this = src;     }
  324.   TCharBuff(const TCharBuff& src)                 { *this = src;     }
  325.  ~TCharBuff()                                     { delete[] m_Data; }
  326.  
  327.   operator LPCTSTR() const                        { return m_Data;      }
  328.   int      Len()     const                        { return LEN;         }
  329.   bool  operator !() const                        { return m_Data[0]==0;}
  330.  
  331.   LPTSTR   Copy(LPCTSTR src)                      { return lstrcpyn(m_Data, src, LEN); }
  332.   LPTSTR   Cat (LPCTSTR src)                      { return lstrcat(m_Data, src);       }
  333.  
  334.   TCharBuff& operator =(LPCTSTR src)              { Copy(src); return *this; }
  335.   TCharBuff& operator =(const TCharBuff& src)     { Copy(src); return *this; }
  336.   TCharBuff& operator+=(LPCTSTR src)              { Cat(src);  return *this; }
  337.  
  338. protected:
  339.   LPTSTR    m_Data;
  340. };
  341.  
  342.  
  343. // TPtrBase
  344. // Base class for automation pointer management. Provides basic implementation for
  345. // smart pointer object.
  346. //
  347. template<class T>
  348. class TPtrBase
  349. {
  350. public:
  351.   // Methods implementing pointer semantics
  352.   //
  353.   T&  operator *  ()    const { _ASSERTE_(m_ptr); return *m_ptr; }
  354.       operator T* ()    const { return m_ptr;}
  355.       bool operator !() const { return m_ptr == 0; }
  356.   T*   operator->()    const  { _ASSERTE_(m_ptr); return m_ptr;  }
  357.   T**  operator &()/*const*/  { return &m_ptr; }
  358.  
  359.   // Comparison operators
  360.   //
  361.   bool operator == (T                 *rhs) const { return m_ptr == rhs;}
  362.   bool operator == (const TPtrBase<T> &rhs) const { return m_ptr == rhs.m_ptr; }
  363.   bool operator != (T                 *rhs) const { return m_ptr != rhs;}
  364.   bool operator != (const TPtrBase<T> &rhs) const { return m_ptr != rhs.m_ptr; }
  365.  
  366. protected:
  367.    TPtrBase()     : m_ptr(0) {}
  368.    TPtrBase(T* p) : m_ptr(p) {}
  369.  
  370.    T* get        () const   { return m_ptr;    }
  371.    T* release    ()         { return reset(0); }
  372.    T* reset      (T* p = 0) { T* tmp = m_ptr; m_ptr = p; return tmp; }
  373.  
  374.    // Actual data
  375.    //
  376.    T* m_ptr;
  377.  
  378. private:
  379.     // Prevent new/delete
  380.     //
  381.     void* operator new(size_t);
  382.     void  operator delete(void*/*p*/){/*::delete p;*/};
  383. };
  384.  
  385.  
  386. // TPtr: Smart pointer object for non-array pointers
  387. //
  388. template<class T>
  389. class TPtr : public TPtrBase<T>
  390. {
  391. public:
  392.   TPtr()             : TPtrBase<T>()              {}
  393.   TPtr(T*       src) : TPtrBase<T>(src)           {}
  394.   TPtr(TPtr<T>& src) : TPtrBase<T>(src.release()) {}
  395.  ~TPtr()                                          {clear(0);}
  396.  
  397.   // Assignment operators
  398.   //
  399.   TPtr& operator = (TPtr<T>& src)
  400.   {
  401.     // Transfer ownership of pointer to receiver
  402.     //
  403.     reset(src.release());
  404.     return *this;
  405.   }
  406.   TPtr& operator = (T* src)
  407.   {
  408.     clear(src);
  409.     return *this;
  410.   }
  411.   T*  operator& () const
  412.   {
  413.     return get();
  414.   }
  415.  
  416.   // Clear object - free pointer
  417.   //
  418.   void clear(T *src)
  419.   {
  420.     if (m_ptr)
  421.       delete m_ptr;
  422.     m_ptr = src;
  423.   }
  424. };
  425.  
  426.  
  427. // TAPtr: Smart pointer object for array new'ed memory
  428. //
  429. template<class T>
  430. class TAPtr : public TPtrBase<T>
  431. {
  432. public:
  433.   TAPtr()             : TPtrBase<T>()              {}
  434.   TAPtr(T      src[]) : TPtrBase<T>(src)           {}
  435.   TAPtr(TPtr<T>& src) : TPtrBase<T>(src.release()) {}
  436.  ~TAPtr()                                          {clear(0);}
  437.  
  438.   // Assignment operators
  439.   //
  440.   TAPtr& operator = (TAPtr<T>& src)
  441.   {
  442.     // Transfer ownership of pointer to receiver
  443.     //
  444.     reset(src.release());
  445.     return *this;
  446.   }
  447.   TAPtr& operator = (T src[])
  448.   {
  449.     clear(src);
  450.     return *this;
  451.   }
  452.  
  453.   // Subscript operator (for array)
  454.   //
  455.   T& operator [](int i) const
  456.   {
  457.     _ASSERTE_(m_ptr);
  458.     return m_ptr[i];
  459.   }
  460.  
  461.   // Clear object - free pointer
  462.   //
  463.   void clear(T src[])
  464.   {
  465.     if (m_ptr)
  466.       delete []m_ptr;
  467.     m_ptr = src;
  468.   }
  469. };
  470.  
  471.  
  472. // TInitOle: Simple object to initialize and unintialize Ole in a safe fashion
  473. //
  474. template <class T>
  475. class TInitOleT
  476. {
  477. public:
  478.   TInitOleT(COINIT initFlag = m_DefaultInitFlag)
  479.   {
  480.     HRESULT hr_Initializing_OLE = ::CoInitializeEx(0, initFlag);
  481.     /* OLECHECK(hr_Initializing_OLE); */
  482.     init = SUCCEEDED(hr_Initializing_OLE);
  483.   }
  484.  ~TInitOleT()
  485.   {
  486.     if (init)
  487.       ::CoUninitialize();
  488.   }
  489.  
  490.   // Methods to test whether initialization was succcessful
  491.   //
  492.   operator bool  () const { return init;          }
  493.   int operator ! () const { return init == false; }
  494.  
  495.   // static members
  496.   //
  497.   static  COINIT  m_DefaultInitFlag;
  498.   static  void    Init();
  499.  
  500. protected:
  501.   // Flags if initialization was successful
  502.   //
  503.   bool init;
  504.  
  505. private:
  506.   // Prevent accidental copy to ensure equal numbers of Init/UnInit
  507.   //
  508.   TInitOleT(const TInitOleT<T>&);
  509.   TInitOleT<T>& operator = (const TInitOleT<T>&);
  510. };
  511.  
  512. // Default flag when initializing OLE
  513. //
  514. #if !defined(_ATL_COINIT_MULTITHREADED)
  515. template <class T> COINIT 
  516. TInitOleT<T>::m_DefaultInitFlag = COINIT_APARTMENTTHREADED;
  517. #else
  518. template <class T> COINIT 
  519. TInitOleT<T>::m_DefaultInitFlag = COINIT_MULTITHREADED;
  520. #endif                    
  521.  
  522.  
  523. // Creates a single instance that initializes OLE
  524. //
  525. template <class T> void 
  526. TInitOleT<T>::Init()
  527. {
  528.   static TInitOle<T> instance(m_DefaultInitFlag);
  529. }
  530.  
  531. // TInitOle is backward compatible with v3.0's TInitOle
  532. //
  533. typedef TInitOleT</*Pick a type*/int> TInitOle;
  534.  
  535. // Helper class used to create Default Interface Wrapper of CoClasses
  536. // (Used by Code generated by TLIBIMP)
  537. //
  538. class CoClassCreator
  539. {
  540. public:
  541.   // Enhanced version of CoCreateInstance that handles failure due to CLSCTX_REMOTESERVER Flag
  542.   //
  543.   static HRESULT CoCreateInstance(REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
  544.   {
  545.     HRESULT hr;
  546.  
  547.   // Define NO_REMOTE_BINDING if you do not want to try to bind to a remote server
  548.   //
  549. #if !defined(NO_REMOTE_BINDING)
  550.     hr = ::CoCreateInstance(rclsid, 0, CLSCTX_SERVER, riid, ppv);
  551.  
  552.     // If succeeded, or failed for reasons other than invalid arguments
  553.     //
  554.     if (SUCCEEDED(hr)  || hr != E_INVALIDARG)
  555.       return hr;
  556. #endif
  557.  
  558.     // Call CoCreateInstance, this time masking off CLSCTX_REMOTE_SERVER
  559.     //
  560.     hr = ::CoCreateInstance(rclsid, 0, CLSCTX_SERVER & ~CLSCTX_REMOTE_SERVER, riid, ppv);
  561.     return hr;
  562.   }
  563. };
  564.  
  565. // Generic COM Interface wrapper
  566. // Performs proper AddRef/Release when object is copied, assigned to and deleted
  567. //
  568. template <class T>
  569. class TComInterface
  570. {
  571. public:
  572.   TComInterface() : intf(0)
  573.   {}
  574.  
  575.   // NOTE: The default behaviour of the constructor is not to AddRef the interface
  576.   //       pointer parameter. This is appropriate if the interface was obtained
  577.   //       has already been addRef'ed - as when retrieving a Font property.
  578.   //
  579.   TComInterface(T* p, bool addRef = false)
  580.   {
  581.     if (((intf = p) != 0) && addRef)
  582.       intf->AddRef();
  583.   }
  584.  
  585.   TComInterface(const TComInterface<T>& src)
  586.   {
  587.     if ((intf = src.intf) != 0)
  588.       intf->AddRef();
  589.   }
  590.  
  591.  ~TComInterface()
  592.   {
  593.     Reset();
  594.   }
  595.  
  596.   operator T* () const
  597.   {
  598.     return intf;
  599.   }
  600.  
  601.   T& operator*()
  602.   {
  603.     _ASSERTE_(intf!=0);
  604.     return *intf;
  605.   }
  606.  
  607.   // NOTE: You must explicitly Reset() any held interface pointers before invoking
  608.   //       the &operator (presumably to store another interface in the object)
  609.   //
  610.   T** operator & ()
  611.   {
  612.     _ASSERTE_(intf==0);
  613.     return &intf;
  614.   }
  615.  
  616.   T* operator->() const
  617.   {
  618.     _ASSERTE_(intf != 0);
  619.     return intf;
  620.   }
  621.  
  622.   T* operator->()
  623.   {
  624.     _ASSERTE_(intf != 0);
  625.     return intf;
  626.   }
  627.  
  628.   void Reset(T* p = 0)
  629.   {
  630.     if (intf)
  631.       intf->Release();
  632.     intf=p;
  633.   }
  634.  
  635.   void Bind(T* p, bool addRef = false)
  636.   {
  637.     if (p && addRef)
  638.       p->AddRef();
  639.     Reset(p);
  640.   }
  641.  
  642.   void Unbind()             { Reset(0); }
  643.  
  644.   // NOTE: The assignment operator does *NOT* addRef the interface pointer being
  645.   //       assigned to this object.
  646.   //
  647.   TComInterface<T>& operator=(T* p)
  648.   {
  649.     Bind(p);
  650.     return *this;
  651.   }
  652.  
  653.   TComInterface<T>& operator=(const TComInterface<T>& src)
  654.   {
  655.     if (src.intf != 0)
  656.       src.intf->AddRef();
  657.     Reset(src.intf);
  658.     return *this;
  659.   }
  660.  
  661.   bool operator ! () const  {   return (intf == 0); }
  662.   operator bool   () const  {   return (intf != 0); }
  663.   bool IsBound()     const  {   return !!(*this);   }
  664.  
  665. protected:
  666.   T* intf;
  667. };
  668.  
  669. // Typedefs for standard interfaces
  670. //
  671. typedef TComInterface<IUnknown>  TCOMIUnknown;
  672. typedef TComInterface<IDispatch> TCOMIDispatch;
  673.  
  674. // Just in case this class is used solely for helper objects and
  675. // not for Automation
  676. //
  677. #if !defined(UTILCLS_NO_AUTOMATION)
  678.  
  679. // VARIANT_BOOL is really just a short. Therefore it's not distinguishable from a
  680. // VT_I2. Most servers will take VT_I2 in a VARIANT when expecting a BOOLEAN.
  681. // However, some (such as Excel97) won't. So to distinguish, we'll expose VT_BOOL
  682. // as TOLEBOOL instead of VARIANT_BOOL.
  683. //
  684. class TOLEBOOL
  685. {
  686. public:
  687.   TOLEBOOL(bool flag = false)   : m_VariantBool(flag ? VARIANT_TRUE : VARIANT_FALSE) {}
  688.   TOLEBOOL(VARIANT_BOOL flag)   : m_VariantBool(flag ? VARIANT_TRUE : VARIANT_FALSE) {}
  689.   TOLEBOOL(int flag)            : m_VariantBool(flag ? VARIANT_TRUE : VARIANT_FALSE) {}
  690.   TOLEBOOL(const TOLEBOOL& src) : m_VariantBool(src.m_VariantBool)                   {}
  691.  
  692.   TOLEBOOL& operator=(const TOLEBOOL& src)
  693.   {
  694.     m_VariantBool = src.m_VariantBool;
  695.     return *this;
  696.   }
  697.   TOLEBOOL& operator=(bool flag)
  698.   {
  699.     m_VariantBool = flag ? VARIANT_TRUE : VARIANT_FALSE;
  700.     return *this;
  701.   }
  702.   TOLEBOOL& operator=(VARIANT_BOOL flag)
  703.   {
  704.     m_VariantBool = flag ? VARIANT_TRUE : VARIANT_FALSE;
  705.     return *this;
  706.   }
  707.   TOLEBOOL& operator=(int flag)
  708.   {
  709.     m_VariantBool = flag ? VARIANT_TRUE : VARIANT_FALSE;
  710.     return *this;
  711.   }
  712.  
  713.   bool operator==(bool val)         { return val ? (m_VariantBool != VARIANT_FALSE) : (m_VariantBool == VARIANT_FALSE); }
  714.   bool operator==(VARIANT_BOOL val) { return m_VariantBool == val; }
  715.  
  716.   operator bool () const          { return m_VariantBool != VARIANT_FALSE;  }
  717.   operator VARIANT_BOOL () const  { return (m_VariantBool != VARIANT_FALSE) ? VARIANT_TRUE : VARIANT_FALSE; }
  718.  
  719. protected:
  720.   VARIANT_BOOL  m_VariantBool;
  721. };
  722.  
  723.  
  724. ///////////////////////////////////////////////////////////////////////////////
  725. // The following macros utilize the Variant access macros defined in OLEAUTO.H
  726. // to set the VARTYPE (vt) and the related variable at once. For example:
  727. //
  728. //    V_TYPE_VAR(CY, amount) expands to           vt         = VT_CY;
  729. //                                                V_CY(this) = amount;
  730. ///////////////////////////////////////////////////////////////////////////////
  731. #if !defined(SET_VTYPE_AND_VAR)
  732. #define SET_VTYPE_AND_VAR(type, val)    vt = VT_ ## type ;            \
  733.                                         V_ ## type (this) = val;
  734. #endif
  735. #if !defined(SET_VTYPE_AND_VARREF)
  736. #define SET_VTYPE_AND_VARREF(type, val) vt = VT_ ## type | VT_BYREF;  \
  737.                                         V_ ## type ## REF (this) = val;
  738. #endif
  739.  
  740.  
  741. ///////////////////////////////////////////////////////////////////////////////
  742. // TVariantT
  743. // ========
  744. // Templatized VARIANT support. T must be a VARIANT or VARIANT-derived type
  745. ///////////////////////////////////////////////////////////////////////////////
  746. template <class T>
  747. class TVariantT : public T
  748. {
  749. public:
  750.   TVariantT()
  751.   {
  752.     ::VariantInit(this);
  753.   }
  754.  ~TVariantT()
  755.   {
  756.     ::VariantClear(this);
  757.   }
  758.  
  759.   TVariantT(const TVariantT& src)
  760.   {
  761.     ::VariantInit(this);
  762.     ::VariantCopy(this, (VARIANT*)&src);
  763.   }
  764.  
  765.   // Ctr - From basic C++ types
  766.   TVariantT(bool src)
  767.   {
  768.     ::VariantInit(this);
  769.     SET_VTYPE_AND_VAR(BOOL, src ? VARIANT_TRUE : VARIANT_FALSE);
  770.   }
  771.   TVariantT(const TOLEBOOL& src)
  772.   {
  773.     ::VariantInit(this);
  774.     SET_VTYPE_AND_VAR(BOOL, src ? VARIANT_TRUE : VARIANT_FALSE);
  775.   }
  776.   TVariantT(char src)
  777.   {
  778.     ::VariantInit(this);
  779.     SET_VTYPE_AND_VAR(I1, src);
  780.   }
  781.   TVariantT(signed char src)
  782.   {
  783.     ::VariantInit(this);
  784.     SET_VTYPE_AND_VAR(I1, src);
  785.   }
  786.   TVariantT(unsigned char src)
  787.   {
  788.     ::VariantInit(this);
  789.     SET_VTYPE_AND_VAR(UI1, src);
  790.   }
  791.   TVariantT(short src)
  792.   {
  793.     ::VariantInit(this);
  794.     SET_VTYPE_AND_VAR(I2, src);
  795.   }
  796.   TVariantT(unsigned short src, bool isBoolean = false)
  797.   {
  798.     ::VariantInit(this);
  799.     if (isBoolean)
  800.     {
  801.       SET_VTYPE_AND_VAR(BOOL, src);
  802.     }
  803.     else
  804.     {
  805.       SET_VTYPE_AND_VAR(UI2, src);
  806.     }
  807.   }
  808.   TVariantT(int src)
  809.   {
  810.     ::VariantInit(this);
  811.     SET_VTYPE_AND_VAR(I4, src);
  812.   }
  813.   TVariantT(unsigned int src)
  814.   {
  815.     ::VariantInit(this);
  816.     SET_VTYPE_AND_VAR(UI4, src);
  817.   }
  818.   TVariantT(long src, bool isError = false)
  819.   {
  820.     ::VariantInit(this);
  821.     if (isError)
  822.     {
  823.       SET_VTYPE_AND_VAR(ERROR, src);
  824.     }
  825.     else
  826.     {
  827.       SET_VTYPE_AND_VAR(I4, src);
  828.     }
  829.   }
  830.   TVariantT(unsigned long src)
  831.   {
  832.     ::VariantInit(this);
  833.     SET_VTYPE_AND_VAR(UI4, src);
  834.   }
  835.   TVariantT(float src)
  836.   {
  837.     ::VariantInit(this);
  838.     SET_VTYPE_AND_VAR(R4, src);
  839.   }
  840.   TVariantT(double src, bool isDate = false)
  841.   {
  842.     ::VariantInit(this);
  843.     if (isDate)
  844.     {
  845.       SET_VTYPE_AND_VAR(DATE, src);
  846.     }
  847.     else
  848.     {
  849.       SET_VTYPE_AND_VAR(R8, src);
  850.     }
  851.   }
  852.   TVariantT(long double src)
  853.   {
  854.     ::VariantInit(this);
  855.     SET_VTYPE_AND_VAR(R8, double(src));
  856.   }
  857.  
  858.   // Ctr - From OLE structures
  859.   TVariantT(const CURRENCY& src)
  860.   {
  861.     ::VariantInit(this);
  862.     SET_VTYPE_AND_VAR(CY, src);
  863.   }
  864.   TVariantT(SAFEARRAY& src)
  865.   {
  866.     ::VariantInit(this);
  867.     SetSAFEARRAY(&src);
  868.   }
  869.   TVariantT(SAFEARRAY* src)
  870.   {
  871.     ::VariantInit(this);
  872.     SetSAFEARRAY(src);
  873.   }
  874.   TVariantT(const VARIANT& src)
  875.   {
  876.     ::VariantInit(this);
  877.     ::VariantCopy(this, const_cast<VARIANTARG*>(&src));
  878.   }
  879.   TVariantT(VARIANT* src)
  880.   {
  881.     ::VariantInit(this);
  882.     ::VariantCopy(this, src);
  883.   }
  884.  
  885.   // Ctr - From VCL utility classes (Members are exposed only of VCL headers have been included)
  886.   //
  887. #if defined(DSTRING_H)
  888.   TVariantT(const AnsiString& src)
  889.   {
  890.     ::VariantInit(this);
  891.     *this = src.c_str();
  892.   }
  893. #endif
  894. #if defined(SYSCURR_H)
  895.   TVariantT(const Currency& src)
  896.   {
  897.     ::VariantInit(this);
  898.     SET_VTYPE_AND_VAR(CY, *(reinterpret_cast<tagCY*>(&(const_cast<Currency&>(src).Val))))
  899.   }
  900.   TVariantT(Currency* src)
  901.   {
  902.     ::VariantInit(this);
  903.       SET_VTYPE_AND_VARREF(CY, reinterpret_cast<tagCY*>(&(src->Val)));
  904.   }
  905. #endif
  906. #if defined(SYSTDATE_H)
  907.   TVariantT(const TDateTime& src)
  908.   {
  909.     ::VariantInit(this);
  910.     SET_VTYPE_AND_VAR(DATE, src);
  911.   }
  912.   TVariantT(TDateTime* src)
  913.   {
  914.     ::VariantInit(this);
  915.     SET_VTYPE_AND_VARREF(DATE, reinterpret_cast<DATE*>(src));
  916.   }
  917. #endif
  918. #if defined(WSTRING_H)
  919.   TVariantT(const WideString& src)
  920.   {
  921.     ::VariantInit(this);
  922.     SET_VTYPE_AND_VAR(BSTR, src.Copy());
  923.   }
  924. #endif
  925. #if defined(SYSTOBJ_H)
  926.   // Ref-counted Dispatch interface object
  927.   TVariantT(const System::DelphiInterface<IDispatch>& src)
  928.   {
  929.     ::VariantInit(this);
  930.     if (!!src)
  931.       src->AddRef();
  932.     SET_VTYPE_AND_VAR(DISPATCH, src);
  933.   }
  934. #endif
  935.  
  936.   // Asciiz pointer
  937.   TVariantT(const char* src)             // Treated as pointer Asciiz string
  938.   {
  939.     ::VariantInit(this);
  940.     int size = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, 0, 0);
  941.     LPWSTR dst = ::SysAllocStringLen(0, size);
  942.     ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, -1, dst, size);
  943.     SET_VTYPE_AND_VAR(BSTR, dst);
  944.   }
  945.  
  946.   // Ctr - OLE ptrs
  947.   // Set isSysString to False if TVariantT must allocate a copy of the WCHAR* passed in.
  948.   // Otherwise, this constructor assumes that the WCHAR* was allocated via 'SysAlloc...'
  949.   // and it takes ownership of the pointer.
  950.   TVariantT(wchar_t* src, bool isSysString = true)                // BSTR support
  951.   {
  952.     ::VariantInit(this);
  953.     SET_VTYPE_AND_VAR(BSTR, isSysString ? src : ::SysAllocString(src));
  954.   }
  955.   TVariantT(IUnknown* src)
  956.   {
  957.     ::VariantInit(this);
  958.     if (src)
  959.       src->AddRef();
  960.     SET_VTYPE_AND_VAR(UNKNOWN, src);
  961.   }
  962.   TVariantT(IDispatch* src)
  963.   {
  964.     ::VariantInit(this);
  965.     if (src)
  966.       src->AddRef();
  967.     SET_VTYPE_AND_VAR(DISPATCH, src);
  968.   }
  969.  
  970.  
  971.   //By ref constructors
  972.  
  973.   // NOTE: We cannot take a bool* since the sizes of VARIANT_BOOL and bool
  974.   //       differ. Instead we'll take a TOLEBOOL. Taking a VARIANT_BOOL*
  975.   //       is not distinguishable from a short pointer.
  976.   //
  977.   TVariantT(TOLEBOOL* src)
  978.   {
  979.     ::VariantInit(this);
  980.     SET_VTYPE_AND_VARREF(BOOL, src);
  981.   }
  982.   TVariantT(signed char* src)
  983.   {
  984.     ::VariantInit(this);
  985.     SET_VTYPE_AND_VARREF(I1, src);
  986.   }
  987.   TVariantT(unsigned char* src)
  988.   {
  989.     ::VariantInit(this);
  990.     SET_VTYPE_AND_VARREF(UI1, src);
  991.   }
  992.   TVariantT(short* src)
  993.   {
  994.     ::VariantInit(this);
  995.     SET_VTYPE_AND_VARREF(I2, src);
  996.   }
  997.   TVariantT(unsigned short* src)
  998.   {
  999.     ::VariantInit(this);
  1000.     SET_VTYPE_AND_VARREF(UI2, src);
  1001.   }
  1002.   TVariantT(int* src)
  1003.   {
  1004.     ::VariantInit(this);
  1005.     SET_VTYPE_AND_VARREF(I4, src);
  1006.   }
  1007.   TVariantT(unsigned int* src)
  1008.   {
  1009.     ::VariantInit(this);
  1010.     SET_VTYPE_AND_VARREF(UI4, src);
  1011.   }
  1012.   TVariantT(long* src)
  1013.   {
  1014.     ::VariantInit(this);
  1015.     SET_VTYPE_AND_VARREF(I4, src);
  1016.   }
  1017.   TVariantT(unsigned long* src)
  1018.   {
  1019.     ::VariantInit(this);
  1020.     SET_VTYPE_AND_VARREF(UI4, src);
  1021.   }
  1022.   TVariantT(float* src)
  1023.   {
  1024.     ::VariantInit(this);
  1025.     SET_VTYPE_AND_VARREF(R4, src);
  1026.   }
  1027.   TVariantT(double* src, bool isDate = false)
  1028.   {
  1029.     ::VariantInit(this);
  1030.     if (isDate)
  1031.     {
  1032.       SET_VTYPE_AND_VARREF(DATE, src);
  1033.     }
  1034.     else
  1035.     {
  1036.       SET_VTYPE_AND_VARREF(R8, src);
  1037.     }
  1038.   }
  1039.   TVariantT(CURRENCY* src)
  1040.   {
  1041.     ::VariantInit(this);
  1042.     SET_VTYPE_AND_VARREF(CY, src);
  1043.   }
  1044.   TVariantT(SAFEARRAY** src)
  1045.   {
  1046.     ::VariantInit(this);
  1047.     SetSAFEARRAY(src);
  1048.   }
  1049.   TVariantT(wchar_t** src)               // VT_BSTR|VT_BYREF
  1050.   {
  1051.     ::VariantInit(this);
  1052.     SET_VTYPE_AND_VARREF(BSTR, src);
  1053.   }
  1054.  
  1055.   // Helper for SAFEARRAY
  1056.   void SetSAFEARRAY(SAFEARRAY *psa)
  1057.   {
  1058.     VARTYPE _vt;
  1059.     ::SafeArrayGetVartype(psa, &_vt);
  1060.     vt = VT_ARRAY|_vt;
  1061.     V_ARRAY(this) = psa;
  1062.   }
  1063.   void SetSAFEARRAY(SAFEARRAY **ppsa)
  1064.   {
  1065.     VARTYPE _vt;
  1066.     ::SafeArrayGetVartype(*ppsa, &_vt);
  1067.     vt = VT_ARRAY|VT_BYREF|_vt;
  1068.     V_ARRAYREF(this) = ppsa;
  1069.   }
  1070.  
  1071.   // Assignments
  1072.   TVariantT& operator =(const TVariantT& rhs)
  1073.   {
  1074.     ::VariantClear(this);
  1075.     ::VariantCopy(this, &(const_cast<TVariantT&>(rhs)));
  1076.     return *this;
  1077.   }
  1078.   TVariantT& operator =(bool src)
  1079.   {
  1080.     ::VariantClear(this);
  1081.     SET_VTYPE_AND_VAR(BOOL, src ? VARIANT_TRUE : VARIANT_FALSE);
  1082.     return *this;
  1083.   }
  1084.   TVariantT& operator =(const TOLEBOOL& src)
  1085.   {
  1086.     ::VariantClear(this);
  1087.     SET_VTYPE_AND_VAR(BOOL, src ? VARIANT_TRUE : VARIANT_FALSE);
  1088.     return *this;
  1089.   }
  1090.   TVariantT& operator =(char src)
  1091.   {
  1092.     ::VariantClear(this);
  1093.     SET_VTYPE_AND_VAR(I1, src);
  1094.     return *this;
  1095.   }
  1096.   TVariantT& operator =(signed char src)
  1097.   {
  1098.     ::VariantClear(this);
  1099.     SET_VTYPE_AND_VAR(I1, src);
  1100.     return *this;
  1101.   }
  1102.   TVariantT& operator =(unsigned char src)
  1103.   {
  1104.     ::VariantClear(this);
  1105.     SET_VTYPE_AND_VAR(UI1, src);
  1106.     return *this;
  1107.   }
  1108.   TVariantT& operator =(short src)
  1109.   {
  1110.     ::VariantClear(this);
  1111.     SET_VTYPE_AND_VAR(I2, src);
  1112.     return *this;
  1113.   }
  1114.   TVariantT& operator =(unsigned short src)
  1115.   {
  1116.     ::VariantClear(this);
  1117.     SET_VTYPE_AND_VAR(UI2, src);
  1118.     return *this;
  1119.   }
  1120.   TVariantT& operator =(int src)
  1121.   {
  1122.     ::VariantClear(this);
  1123.     SET_VTYPE_AND_VAR(I4, src);
  1124.     return *this;
  1125.   }
  1126.   TVariantT& operator =(unsigned int src)
  1127.   {
  1128.     ::VariantClear(this);
  1129.     SET_VTYPE_AND_VAR(UI4, src);
  1130.     return *this;
  1131.   }
  1132.   TVariantT& operator =(long src)
  1133.   {
  1134.     ::VariantClear(this);
  1135.     SET_VTYPE_AND_VAR(I4, src);
  1136.     return *this;
  1137.   }
  1138.   TVariantT& operator =(unsigned long src)
  1139.   {
  1140.     ::VariantClear(this);
  1141.     SET_VTYPE_AND_VAR(UI4, src);
  1142.     return *this;
  1143.   }
  1144.   TVariantT& operator =(float src)
  1145.   {
  1146.     ::VariantClear(this);
  1147.     SET_VTYPE_AND_VAR(R4, src);
  1148.     return *this;
  1149.   }
  1150.   TVariantT& operator =(double src)
  1151.   {
  1152.     ::VariantClear(this);
  1153.     SET_VTYPE_AND_VAR(R8, src);
  1154.     return *this;
  1155.   }
  1156.   TVariantT& operator =(const CURRENCY& src)
  1157.   {
  1158.     ::VariantClear(this);
  1159.     SET_VTYPE_AND_VAR(CY, src);
  1160.     return *this;
  1161.   }
  1162.   TVariantT& operator =(SAFEARRAY* src)
  1163.   {
  1164.     ::VariantClear(this);
  1165.     SetSAFEARRAY(src);
  1166.     return *this;
  1167.   }
  1168.   TVariantT& operator =(SAFEARRAY& src)
  1169.   {
  1170.     ::VariantClear(this);
  1171.     SetSAFEARRAY(&src);
  1172.     return *this;
  1173.   }
  1174.   TVariantT& operator =(VARIANT& rhs)
  1175.   {
  1176.     ::VariantClear(this);
  1177.     ::VariantCopy(this, &rhs);
  1178.     return *this;
  1179.   }
  1180.   TVariantT& operator =(VARIANT* rhs)
  1181.   {
  1182.     ::VariantClear(this);
  1183.     // Can only have one level of indirection with VT_VARIANT
  1184.     //
  1185.     if (rhs && rhs->vt != VT_VARIANT && rhs->vt != (VT_VARIANT|VT_BYREF))
  1186.     {
  1187.       SET_VTYPE_AND_VARREF(VARIANT, rhs);
  1188.     }
  1189.     else
  1190.     {
  1191.       ::VariantCopy(this, rhs);
  1192.     }
  1193.     return *this;
  1194.   }
  1195. #if defined(DSTRING_H)
  1196.   TVariantT& operator=(const AnsiString& src)
  1197.   {
  1198.     *this = src.c_str();
  1199.     return *this;
  1200.   }
  1201. #endif
  1202. #if defined(SYSCURR_H)
  1203.   TVariantT& operator=(const Currency& src)
  1204.   {
  1205.     ::VariantClear(this);
  1206.     SET_VTYPE_AND_VAR(CY, *(reinterpret_cast<tagCY*>(&(const_cast<Currency&>(src).Val))))
  1207.     return *this;
  1208.   }
  1209. #endif
  1210. #if defined(SYSTDATE_H)
  1211.   TVariantT& operator=(const TDateTime& src)
  1212.   {
  1213.     ::VariantClear(this);
  1214.     SET_VTYPE_AND_VAR(DATE, src);
  1215.     return *this;
  1216.   }
  1217. #endif
  1218. #if defined(WSTRING_H)
  1219.   TVariantT& operator=(const WideString& src)
  1220.   {
  1221.     ::VariantClear(this);
  1222.     SET_VTYPE_AND_VAR(BSTR, src.Copy());
  1223.     return *this;
  1224.   }
  1225. #endif
  1226. #if defined(SYSTOBJ_H)
  1227.   TVariantT& operator=(const System::DelphiInterface<IDispatch>& src)
  1228.   {
  1229.     ::VariantClear(this);
  1230.     if (!!src)
  1231.       src->AddRef();      
  1232.     SET_VTYPE_AND_VAR(DISPATCH, src);
  1233.     return *this;
  1234.   }
  1235. #endif
  1236.  
  1237.   TVariantT& operator =(wchar_t* src)              // BSTR support
  1238.   {
  1239.     ::VariantClear(this);
  1240.     SET_VTYPE_AND_VAR(BSTR, src);
  1241.     return *this;
  1242.   }
  1243.   TVariantT& operator =(IUnknown* src)
  1244.   {
  1245.     ::VariantClear(this);
  1246.     if (src)
  1247.       src->AddRef();
  1248.     SET_VTYPE_AND_VAR(UNKNOWN, src);
  1249.     return *this;
  1250.   }
  1251.   TVariantT& operator =(IDispatch* src)
  1252.   {
  1253.     ::VariantClear(this);
  1254.     if (src)
  1255.       src->AddRef();
  1256.     SET_VTYPE_AND_VAR(DISPATCH, src);
  1257.     return *this;
  1258.   }
  1259.  
  1260.  
  1261.   // By ref Assignment
  1262.   // NOTE: We cannot take a 'bool*' - the size of VARIANT_BOOL and bool differ
  1263.   TVariantT& operator =(TOLEBOOL* src)
  1264.   {
  1265.     ::VariantClear(this);
  1266.     SET_VTYPE_AND_VARREF(BOOL, (VARIANT_BOOL*)src);
  1267.     return *this;
  1268.   }
  1269.   TVariantT& operator =(const char* src)           // Treated as pointer Asciiz string
  1270.   {
  1271.     ::VariantClear(this);
  1272.     SET_VTYPE_AND_VAR(BSTR, AnsiToOLESTR(src));
  1273.     return *this;
  1274.   }
  1275.   TVariantT& operator =(signed char* src)
  1276.   {
  1277.     ::VariantClear(this);
  1278.     SET_VTYPE_AND_VARREF(I1, reinterpret_cast<char*>(src));
  1279.     return *this;
  1280.   }
  1281.   TVariantT& operator =(unsigned char* src)
  1282.   {
  1283.     ::VariantClear(this);
  1284.     SET_VTYPE_AND_VARREF(UI1, src);
  1285.     return *this;
  1286.   }
  1287.   TVariantT& operator =(short* src)
  1288.   {
  1289.     ::VariantClear(this);
  1290.     SET_VTYPE_AND_VARREF(I2, src);
  1291.     return *this;
  1292.   }
  1293.   TVariantT& operator =(unsigned short* src)
  1294.   {
  1295.     ::VariantClear(this);
  1296.     SET_VTYPE_AND_VARREF(UI2, src);
  1297.     return *this;
  1298.   }
  1299.   TVariantT& operator =(int* src)
  1300.   {
  1301.     ::VariantClear(this);
  1302.     SET_VTYPE_AND_VARREF(I4, (long*)src);
  1303.     return *this;
  1304.   }
  1305.   TVariantT& operator =(unsigned int* src)
  1306.   {
  1307.     ::VariantClear(this);
  1308.     SET_VTYPE_AND_VARREF(UI4, reinterpret_cast<unsigned long*>(src));
  1309.     return *this;
  1310.   }
  1311.   TVariantT& operator =(long* src)
  1312.   {
  1313.     ::VariantClear(this);
  1314.     SET_VTYPE_AND_VARREF(I4, src);
  1315.     return *this;
  1316.   }
  1317.   TVariantT& operator =(unsigned long* src)
  1318.   {
  1319.     ::VariantClear(this);
  1320.     SET_VTYPE_AND_VARREF(UI4, src);
  1321.     return *this;
  1322.   }
  1323.   TVariantT& operator =(float* src)
  1324.   {
  1325.     ::VariantClear(this);
  1326.     SET_VTYPE_AND_VARREF(R4, src);
  1327.     return *this;
  1328.   }
  1329.   TVariantT& operator =(double* src)
  1330.   {
  1331.     ::VariantClear(this);
  1332.     SET_VTYPE_AND_VARREF(R8, src);
  1333.     return *this;
  1334.   }
  1335.   TVariantT& operator =(CURRENCY* src)
  1336.   {
  1337.     ::VariantClear(this);
  1338.     SET_VTYPE_AND_VARREF(CY, src);
  1339.     return *this;
  1340.   }
  1341.   TVariantT& operator =(SAFEARRAY** src)
  1342.   {
  1343.     ::VariantClear(this);
  1344.     SetSAFEARRAY(src);
  1345.     return *this;
  1346.   }
  1347.   TVariantT& operator =(wchar_t** src)             // VT_BSTR|VT_BYREF
  1348.   {
  1349.     ::VariantClear(this);
  1350.     SET_VTYPE_AND_VARREF(BSTR, src);
  1351.     return *this;
  1352.   }
  1353.   TVariantT& operator =(IUnknown** src)
  1354.   {
  1355.     ::VariantClear(this);
  1356.     SET_VTYPE_AND_VARREF(UNKNOWN, src);
  1357.     return *this;
  1358.   }
  1359.   TVariantT& operator =(IDispatch** src)
  1360.   {
  1361.     ::VariantClear(this);
  1362.     SET_VTYPE_AND_VARREF(DISPATCH, src);
  1363.     return *this;
  1364.   }
  1365.  
  1366. #if defined(SYSCURR_H)
  1367.   TVariantT& operator=(Currency* src)
  1368.   {
  1369.     ::VariantClear(this);
  1370.     if(! (src==NULL))
  1371.       SET_VTYPE_AND_VARREF(CY, reinterpret_cast<tagCY*>(&(src->Val)));
  1372.     // else fail silently
  1373.     return* this;
  1374.   }
  1375. #endif
  1376. #if defined(SYSTDATE_H)
  1377.   TVariantT& operator=(TDateTime* src)
  1378.   {
  1379.     ::VariantClear(this);
  1380.     SET_VTYPE_AND_VARREF(DATE, src);
  1381.     return *this;
  1382.   }
  1383. #endif
  1384. #if defined(SYSTOBJ_H)
  1385.   TVariantT& operator=(const System::DelphiInterface<IDispatch>* src)
  1386.   {
  1387.     ::VariantClear(this);
  1388.     if (!!src)
  1389.     SET_VTYPE_AND_VARREF(DISPATCH, src);         
  1390.     return *this;
  1391.   }
  1392. #endif
  1393.  
  1394.   HRESULT   ChangeType(VARTYPE vtNew, const VARIANT& src)
  1395.   {
  1396.     return ::VariantChangeType(this, &src, 0, vtNew);
  1397.   }
  1398.   HRESULT   ChangeType(VARTYPE vtNew)
  1399.   {
  1400.     return ::VariantChangeType(this, this, 0, vtNew);
  1401.   }
  1402.  
  1403.   // Returns pointer to base Variant type when Variant holds other Variant
  1404.   //
  1405.   TVariantT* GetBaseVariant();
  1406.  
  1407.   // Conversion operators
  1408.   operator bool() const
  1409.   {
  1410.     TVariantT v(*this);
  1411.     v.ChangeType(VT_BOOL);
  1412.     return V_BOOL(&v) != VARIANT_FALSE;
  1413.   }
  1414.   operator TOLEBOOL() const
  1415.   {
  1416.     return TOLEBOOL(bool(*this));
  1417.   }
  1418.   operator char() const
  1419.   {
  1420.     TVariantT v(*this);
  1421.     v.ChangeType(VT_I1);
  1422.     return V_I1(&v);
  1423.   }
  1424.   operator signed char() const
  1425.   {
  1426.     TVariantT v(*this);
  1427.     v.ChangeType(VT_I1);
  1428.     return V_I1(&v);
  1429.   }
  1430.   operator unsigned char() const
  1431.   {
  1432.     TVariantT v(*this);
  1433.     v.ChangeType(VT_UI1);
  1434.     return V_UI1(&v);
  1435.   }
  1436.   operator short() const
  1437.   {
  1438.     TVariantT v(*this);
  1439.     v.ChangeType(VT_I2);
  1440.     return V_I2(&v);
  1441.   }
  1442.   operator unsigned short() const
  1443.   {
  1444.     TVariantT v(*this);
  1445.     v.ChangeType(VT_UI2);
  1446.     return V_UI2(&v);
  1447.   }
  1448.   operator int() const
  1449.   {
  1450.     TVariantT v(*this);
  1451.     v.ChangeType(VT_I4);
  1452.     return V_I4(&v);
  1453.   }
  1454.   operator unsigned int() const
  1455.   {
  1456.     TVariantT v(*this);
  1457.     v.ChangeType(VT_UI4);
  1458.     return V_UI4(&v);
  1459.   }
  1460.   operator long() const
  1461.   {
  1462.     TVariantT v(*this);
  1463.     v.ChangeType(VT_I4);
  1464.     return V_I4(&v);
  1465.   }
  1466.   operator unsigned long() const
  1467.   {
  1468.     TVariantT v(*this);
  1469.     v.ChangeType(VT_UI4);
  1470.     return V_UI4(&v);
  1471.   }
  1472.   operator float() const
  1473.   {
  1474.     TVariantT v(*this);
  1475.     v.ChangeType(VT_R4);
  1476.     return V_R4(&v);
  1477.   }
  1478.   operator double() const
  1479.   {
  1480.     TVariantT v(*this);
  1481.     v.ChangeType(VT_R8);
  1482.     return V_R8(&v);
  1483.   }
  1484. #if defined(DSTRING_H)
  1485.   operator AnsiString() const
  1486.   {
  1487.     TVariantT v(*this);
  1488.     v.ChangeType(VT_BSTR);
  1489.     WideString temp(V_BSTR(&v));
  1490.    AnsiString retval(temp);
  1491.     return retval;
  1492.   }
  1493. #endif
  1494. #if defined(SYSCURR_H)
  1495.   operator Currency() const
  1496.   {
  1497.     TVariantT v(*this);
  1498.     v.ChangeType(VT_CY);
  1499.     Currency retval;
  1500.     retval.val = *v;
  1501.     return retval;
  1502.   }
  1503. #endif
  1504. #if defined(SYSTDATE_H)
  1505.   operator TDateTime() const
  1506.  {
  1507.     TVariantT v(*this);
  1508.     v.ChangeType(VT_DATE);
  1509.     TDateTime retval(v.date);
  1510.     return retval;
  1511. }
  1512. #endif
  1513. #if defined(WSTRING_H)
  1514.   operator WideString() const
  1515.   {
  1516.     TVariantT v(*this);
  1517.     v.ChangeType(VT_BSTR);
  1518.     return WideString(::SysAllocString(V_BSTR(&v)));
  1519. }
  1520. #endif
  1521.  
  1522.   operator CURRENCY() const
  1523.   {
  1524.     TVariantT v(*this);
  1525.     v.ChangeType(VT_CY);
  1526.     return V_CY(&v);
  1527.   }
  1528.   operator VARIANT() const
  1529.   {
  1530.     TVariantT v(*this);
  1531.     return v;
  1532.   }
  1533.  
  1534.   // NOTE: Caller must free SysString
  1535.   operator wchar_t*() const
  1536.   {
  1537.     TVariantT v(*this);
  1538.     v.ChangeType(VT_BSTR);
  1539.     return ::SysAllocString(V_BSTR(&v));
  1540.   }
  1541.  
  1542.   operator IUnknown*();
  1543.   operator IDispatch*();
  1544.  
  1545.   // by ref conversion operators
  1546.   /* operator char*(); */  // Dangerous - easily used as string instead of VT_I1|VT_BYREF
  1547.  
  1548.   operator signed char*()
  1549.   {
  1550.     if (vt == (VT_I1|VT_BYREF))
  1551.       return (signed char*)V_I1REF(this);
  1552.     else if (vt == VT_I1)
  1553.       return (signed char*)&(V_I1(this));
  1554.   }
  1555.   operator unsigned char*()
  1556.   {
  1557.     if (vt == (VT_UI1 | VT_BYREF))
  1558.       return V_UI1REF(this);
  1559.     else if (vt == VT_UI1)
  1560.       return &(V_UI1(this));
  1561.   }
  1562.   operator short*()
  1563.   {
  1564.     if (vt == (VT_I2|VT_BYREF))
  1565.       return V_I2REF(this);
  1566.     else if (vt == VT_I2)
  1567.       return &(V_I2(this));
  1568.     return NULL;
  1569.   }
  1570.   operator unsigned short*()
  1571.   {
  1572.     if (vt == (VT_UI2|VT_BYREF))
  1573.       return V_UI2REF(this);
  1574.     else if (vt == VT_UI2)
  1575.       return &(V_UI2(this));
  1576.     return NULL;
  1577.   }
  1578.   operator int*()
  1579.   {
  1580.     if (vt == (VT_I4|VT_BYREF))
  1581.       return (int*)V_I4REF(this);
  1582.     else if (vt == VT_I4)
  1583.       return (int*)&(V_I4(this));
  1584.     return NULL;
  1585.   }
  1586.   operator unsigned int*()
  1587.   {
  1588.     if (vt == (VT_UI4|VT_BYREF))
  1589.       return (unsigned int*)V_UI4REF(this);
  1590.     else if (vt == VT_UI4)
  1591.       return (unsigned int*)&(V_UI4(this));
  1592.     return NULL;
  1593.   }
  1594.   operator float*()
  1595.   {
  1596.     if (vt == (VT_R4|VT_BYREF))
  1597.       return V_R4REF(this);
  1598.     else if (vt == VT_R4)
  1599.       return &(V_R4(this));
  1600.     return NULL;
  1601.   }
  1602.   operator double*()
  1603.   {
  1604.     if (vt == (VT_R8|VT_BYREF))
  1605.       return V_R8REF(this);
  1606.     else if (vt == VT_R8)
  1607.       return &(V_R8(this));
  1608.     return NULL;
  1609.   }
  1610.   operator wchar_t**()
  1611.   {
  1612.     if (vt == (VT_BSTR|VT_BYREF))
  1613.       return V_BSTRREF(this);
  1614.     else if (vt == VT_BSTR)
  1615.       return V_BSTR(this);
  1616.     return NULL;
  1617.   }
  1618.   operator VARIANT*()
  1619.   {
  1620.     return reinterpret_cast<VARIANT*>(GetBaseVariant());
  1621.   }
  1622.  
  1623.   // NOTE: Caller must destroy SAFEARRAY*
  1624.   operator SAFEARRAY*()
  1625.   {
  1626.     SAFEARRAY *pSAOut = 0;
  1627.     if (vt & (VT_ARRAY|VT_BYREF))
  1628.       ::SafeArrayCopy(*V_ARRAYREF(this), &pSAOut);
  1629.     else if (vt & VT_ARRAY)
  1630.       ::SafeArrayCopy(V_ARRAY(this), &pSAOut);
  1631.     return pSAOut;
  1632.   }
  1633.  
  1634.   /*operator CURRENCY*()       const;*/
  1635.   /*operator SAFEARRAY**()     const;*/
  1636.  
  1637. #if defined(SYSCURR_H)
  1638.   operator Currency*()
  1639.   {
  1640.     if (vt==(VT_CY|VT_BYREF))
  1641.       return reinterpret_cast<Currency*>(pcyVal);
  1642.     else if (vt==VT_CY)
  1643.       return reinterpret_cast<Currency*>(&cyVal);
  1644.     return NULL;
  1645.   }
  1646. #endif
  1647. #if defined(SYSTDATE_H)
  1648.   operator TDateTime*()
  1649.   {
  1650.     if (vt==(VT_DATE|VT_BYREF))
  1651.       return reinterpret_cast<TDateTime*>(pdate);
  1652.     else if (vt==VT_DATE)
  1653.       return reinterpret_cast<TDateTime*>(&date);
  1654.     return NULL;
  1655.   }
  1656. #endif
  1657.  
  1658.   // Generic == operator (NOTE: Relies on conversion operator for TYPE)
  1659.   //
  1660.   template <class TYPE>
  1661.   bool operator == (TYPE rhs)
  1662.   {
  1663.     TVariant tmp(*this);
  1664.     return TYPE(tmp) == rhs;
  1665.   }
  1666. };
  1667.  
  1668. // Returns 'base-most' VARIANT pointed to by a TVariantT instance
  1669. // (i.e. skip cases where VARIANT points to other VARIANT - VT_VARIANT)
  1670. //
  1671. template <class T>
  1672. TVariantT<T>* TVariantT<T>::GetBaseVariant()
  1673. {
  1674.   TVariantT *pVar = this;
  1675.  
  1676.   // NOTE: Technically there could only be one level of indirection for VT_VARIANT
  1677.   //       Additionally, VT_VARIANT should always be used in combination with VT_BYREF
  1678.   //       However, it does not hurt to catch multiple indirection or check a simple
  1679.   //       VT_VARIANT VARTYPE. Never know what's being packed and sent down out there
  1680.   //
  1681.   while (((pVar->vt == VT_VARIANT) || (pVar->vt == (VT_VARIANT|VT_BYREF))) && (V_VARIANTREF(pVar)))
  1682.     pVar = reinterpret_cast<TVariantT*>(V_VARIANTREF(pVar));
  1683.   return pVar;
  1684. }
  1685.  
  1686.  
  1687. // Extracts an IUnknown* from the TVariantT instance.
  1688. // NOTE: Caller must 'Release' interface.
  1689. //
  1690. template <class T>
  1691. TVariantT<T>::operator IUnknown*()
  1692. {
  1693.   // Handle easy case right away
  1694.   //
  1695.   if (vt==VT_NULL || vt==VT_EMPTY)
  1696.     return 0;
  1697.  
  1698.   IDispatch* disp;
  1699.   IUnknown*  punk = 0;
  1700.   TVariantT*  pVar = GetBaseVariant();
  1701.  
  1702.   // Get Data out of Variant
  1703.   //
  1704.   switch(pVar->vt)
  1705.   {
  1706.     case VT_UNKNOWN:
  1707.     case VT_UNKNOWN|VT_BYREF:
  1708.       punk = (vt==VT_UNKNOWN ? V_UNKNOWN(pVar) : (*(V_UNKNOWNREF(pVar))));
  1709.       punk->AddRef();
  1710.       return punk;
  1711.  
  1712.     case VT_DISPATCH:
  1713.     case VT_DISPATCH|VT_BYREF:
  1714.       disp = (vt==VT_DISPATCH ? V_DISPATCH(pVar) : (*(V_DISPATCHREF(pVar))));
  1715.       if (disp)
  1716.         disp->QueryInterface(IID_IUnknown, (LPVOID*)&punk);
  1717.       return punk;
  1718.  
  1719.     // Hopefully, we'll never get here, but as last resort
  1720.     //
  1721.     default:
  1722.       TVariantT v(*this);
  1723.       v.ChangeType(VT_UNKNOWN);
  1724.       V_UNKNOWN(&v)->AddRef();
  1725.       return V_UNKNOWN(&v);
  1726.   }
  1727. }
  1728.  
  1729.  
  1730. // Extracts an IDispatch* from the TVariantT instance.
  1731. // NOTE: Caller must 'Release' interface.
  1732. //
  1733. template <class T>
  1734. TVariantT<T>::operator IDispatch*()
  1735. {
  1736.   // Handle easy case right away
  1737.   //
  1738.   if (vt==VT_NULL || vt==VT_EMPTY)
  1739.     return 0;
  1740.  
  1741.   IUnknown*  punk;
  1742.   IDispatch* disp= 0;
  1743.   TVariantT*  pVar= GetBaseVariant();
  1744.  
  1745.   // Get data out of Variant
  1746.   //
  1747.   switch(pVar->vt)
  1748.   {
  1749.     case VT_DISPATCH:
  1750.     case VT_DISPATCH|VT_BYREF:
  1751.       disp = (vt==VT_DISPATCH ? V_DISPATCH(pVar) : (*(V_DISPATCHREF(pVar))));
  1752.       if (disp)
  1753.         disp->AddRef();
  1754.       return disp;
  1755.  
  1756.     case VT_UNKNOWN:
  1757.     case VT_UNKNOWN|VT_BYREF:
  1758.       punk = (vt==VT_UNKNOWN ? V_UNKNOWN(pVar) : (*(V_UNKNOWNREF(pVar))));
  1759.       punk->QueryInterface(IID_IDispatch, (LPVOID*)&disp);
  1760.       return disp;
  1761.  
  1762.     default:
  1763.       TVariantT v(*pVar);
  1764.       v.ChangeType(VT_DISPATCH);
  1765.       V_DISPATCH(&v)->AddRef();
  1766.       return V_DISPATCH(&v);
  1767.   }
  1768. }
  1769.  
  1770.  
  1771. // Default VARIANT wrapper used by TAutoArgs
  1772. //
  1773. typedef TVariantT<VARIANT> TVariant;
  1774. typedef TVariantT<VARIANT> VARIANTOBJ;
  1775.  
  1776.  
  1777. // Template used to expose 'factory-like' Create/CreateRemote routines for Clients
  1778. //
  1779. template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
  1780. class TCoClassCreatorT : public CoClassCreator
  1781. {
  1782. public:
  1783.   static TOBJ    Create();
  1784.   static HRESULT Create(TOBJ& intfObj);
  1785.   static HRESULT Create(INTF** ppintf);
  1786.  
  1787.   static TOBJ    CreateRemote(LPCWSTR machineName);
  1788.   static HRESULT CreateRemote(LPCWSTR machineName, TOBJ& intfObj);
  1789.   static HRESULT CreateRemote(LPCWSTR machineName, INTF** ppIntf);
  1790. };
  1791.  
  1792. template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid> 
  1793. TOBJ TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create()
  1794. {
  1795.   TOBJ intfObj;
  1796.   OLECHECK(Create(intfObj));
  1797.   return intfObj;
  1798. }
  1799.  
  1800. template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid> 
  1801. HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create(TOBJ& intfObj)
  1802. {
  1803.   INTF* pintf;
  1804.   HRESULT hr = Create(&pintf);
  1805.   if (SUCCEEDED(hr))
  1806.     intfObj = pintf;
  1807.   return hr;
  1808. }
  1809.  
  1810. template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid> 
  1811. HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::Create(INTF **ppIntf)
  1812. {
  1813.   static TInitOle initOle;
  1814.   return CoCreateInstance(*clsid, *iid, (LPVOID*)ppIntf);
  1815. }
  1816.  
  1817. template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
  1818. TOBJ TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName)
  1819. {
  1820.   TOBJ intfObj;
  1821.   OLECHECK(CreateRemote(machineName, intfObj));
  1822.   return intfObj;
  1823. }
  1824.  
  1825. template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
  1826. HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName, INTF **ppIntf)
  1827. {
  1828.   static TInitOle initOle;
  1829.   COSERVERINFO serverInfo = {0, const_cast<LPWSTR>(machineName), 0, 0};
  1830.   MULTI_QI     mqi        = {iid, 0, 0};
  1831.   HRESULT hr = ::CoCreateInstanceEx(*clsid, 0, 
  1832.                                     CLSCTX_REMOTE_SERVER,
  1833.                                     &serverInfo, 1, &mqi);
  1834.   if (SUCCEEDED(hr))
  1835.     *ppIntf = (INTF*)mqi.pItf;
  1836.   return hr;
  1837. }
  1838.  
  1839. template <class TOBJ, class INTF, const CLSID* clsid, const IID* iid>
  1840. HRESULT TCoClassCreatorT<TOBJ, INTF, clsid, iid>::CreateRemote(LPCWSTR machineName, TOBJ& intfObj)
  1841. {
  1842.   INTF* pintf= 0;
  1843.   HRESULT hr = CreateRemote(machineName, &pintf);
  1844.   if (SUCCEEDED(hr))
  1845.     intfObj = pintf;
  1846.   return hr;
  1847. }
  1848.  
  1849.  
  1850. // Helper class for cases where VARIANT* or VARIANT& is expected for optional parameters
  1851. //
  1852. class TNoParam
  1853. {
  1854. public:
  1855.   TNoParam()
  1856.   {
  1857.     m_Variant.vt = VT_ERROR;
  1858.     V_ERROR(&m_Variant) = DISP_E_PARAMNOTFOUND;
  1859.   }
  1860.  
  1861.   operator VARIANT*  ()         { return &m_Variant;}
  1862.   operator VARIANT&  ()         { return m_Variant; }
  1863.   operator TVariant* ()         { return &m_Variant;}
  1864.   operator TVariant& ()         { return m_Variant; }
  1865.  
  1866. private:
  1867.   TVariant m_Variant;
  1868. };
  1869.  
  1870. // Helper class for default LOCALE values
  1871. //
  1872. class TDefLCID
  1873. {
  1874. public:
  1875.   TDefLCID(LCID lcid = LOCALE_SYSTEM_DEFAULT) : m_Lcid(lcid) {}
  1876.   operator LCID () const { return m_Lcid; }
  1877.  
  1878. protected:
  1879.   LCID  m_Lcid;
  1880. };
  1881.  
  1882.  
  1883. // Base class that exposes basic behaviour of our array of Variants
  1884. //
  1885. class TAutoArgsBase
  1886. {
  1887. protected:
  1888.   TAutoArgsBase(VARIANTOBJ *pVariant, int count) : m_Variant(pVariant), m_Count(count)
  1889.   {}
  1890.  
  1891. public:
  1892.   VARIANTOBJ& operator[](int index) const
  1893.   {
  1894.     // NOTE: It's OK to use Count - there's an extra Variant for return result
  1895.     //       Zero'th entry's reserved for return value.
  1896.     //
  1897.     _ASSERTE_(index <= m_Count);
  1898.     _ASSERTE_(index >= 0);
  1899.  
  1900.     // Make up for C++ vs. Basic reverse indexing
  1901.     //
  1902.     return m_Variant[index ? (m_Count+1-index) : 0];
  1903.   }
  1904.  
  1905.   VARIANT* GetRetVal() const
  1906.   {
  1907.     return (VARIANT*)(m_Variant);
  1908.   }
  1909.  
  1910.   VARIANTOBJ& GetRetVariant()
  1911.   {
  1912.     return *m_Variant;
  1913.   }
  1914.  
  1915.   VARIANT* GetArgs() const
  1916.   {
  1917.     return (VARIANT*)(m_Variant+1);
  1918.   }
  1919.  
  1920.   int GetCount() const
  1921.   {
  1922.     return m_Count;
  1923.   }
  1924.  
  1925. private:
  1926.   TAutoArgsBase(const TAutoArgsBase&);
  1927.   TAutoArgsBase& operator=(const TAutoArgsBase&);
  1928.  
  1929.   VARIANTOBJ *m_Variant;
  1930.   int         m_Count;
  1931. };
  1932.  
  1933.  
  1934. // TAutoArgs - Encapsulates array of Variants. Use for Invoke calls
  1935. //
  1936. template <int Count>
  1937. class TAutoArgs : public TAutoArgsBase
  1938. {
  1939. public:
  1940.   TAutoArgs();
  1941.  ~TAutoArgs();
  1942.  
  1943. private:
  1944.   // Allocate an extra Variant. It's the first entry  and
  1945.   // it is reserved for return result. The rest are for parameters
  1946.   //
  1947.   VARIANTOBJ m_Array[Count+1];
  1948. };
  1949.  
  1950.  
  1951. // Build an array of Count (actualy Count+1, extra one for return value)
  1952. // of VARIANTs.
  1953. //
  1954. template <int Count>
  1955. TAutoArgs<Count>::TAutoArgs() : TAutoArgsBase(m_Array, Count)
  1956. {}
  1957.  
  1958. // Cleanup array of Variants
  1959. //
  1960. template <int Count>
  1961. TAutoArgs<Count>::~TAutoArgs()
  1962. {}
  1963.  
  1964. // Enumeration describing DISPATCH type
  1965. //
  1966. enum DispatchFlag
  1967. {
  1968.   dfMethod    = DISPATCH_METHOD,
  1969.   dfPropGet   = DISPATCH_PROPERTYGET,
  1970.   dfPropPut   = DISPATCH_PROPERTYPUT,
  1971.   dfPropPutRef= DISPATCH_PROPERTYPUTREF
  1972. };
  1973.  
  1974. // Sets the value in the returnVariant to the retVal variable if SUCCEEDED(hr)
  1975. // Used by DispInterface Code Generated by TLIBIMP
  1976. //
  1977. template <class T>
  1978. HRESULT OutRetValSetterPtr(T* retVal, TAutoArgsBase& args, HRESULT hr)
  1979. {
  1980.   if (SUCCEEDED(hr))
  1981.     *retVal = T(args.GetRetVariant());
  1982.   return hr;
  1983. }
  1984.  
  1985. // Sets the value in the returnVariant to the retVal variable if SUCCEEDED(hr)
  1986. // Used by DispInterface Code Generated by TLIBIMP
  1987. template <class T>
  1988. HRESULT OutRetValSetterRef(T& retVal, TAutoArgsBase& args, HRESULT hr)
  1989. {
  1990.   if (SUCCEEDED(hr))
  1991.     retVal = T(args.GetRetVariant());
  1992.   return hr;
  1993. }
  1994.  
  1995.  
  1996. // Base class of smart interface wrappers - provides an optional parameter
  1997. //
  1998. template <class INTF>
  1999. class TComInterfaceBase
  2000. {
  2001. public:
  2002.   static TNoParam     OptParam;
  2003.   static LCID         lcid;
  2004.   static VARIANT_BOOL Variant_False;
  2005.   static VARIANT_BOOL Variant_True;
  2006. };
  2007.  
  2008. // Static/shared instance of 'Optional parameter' and 'lcid' settings
  2009. //
  2010. template <class T>
  2011. TNoParam TComInterfaceBase<T>::OptParam;
  2012. template <class T>
  2013. LCID     TComInterfaceBase<T>::lcid = LOCALE_SYSTEM_DEFAULT;
  2014. template <class T>
  2015. VARIANT_BOOL TComInterfaceBase<T>::Variant_False = VARIANT_FALSE;
  2016. template <class T>
  2017. VARIANT_BOOL TComInterfaceBase<T>::Variant_True  = VARIANT_TRUE;
  2018.  
  2019. // Base class of AutoDrivers - provides an optional parameter
  2020. //
  2021. template <class DISPINTF>
  2022. class TAutoDriverBase
  2023. {
  2024. public:
  2025.   static TNoParam OptParam;
  2026.   static VARIANT_BOOL Variant_False;
  2027.   static VARIANT_BOOL Variant_True;
  2028.   static TInitOle     InitOle;
  2029. };
  2030.  
  2031. // Static/shared instance of 'Optional Parameter'
  2032. //
  2033. template <class T>
  2034. TNoParam TAutoDriverBase<T>::OptParam;
  2035. template <class T>
  2036. VARIANT_BOOL TAutoDriverBase<T>::Variant_False = VARIANT_FALSE;
  2037. template <class T>
  2038. VARIANT_BOOL TAutoDriverBase<T>::Variant_True  = VARIANT_TRUE;
  2039. template <class T>
  2040. TInitOle TAutoDriverBase<T>::InitOle;
  2041.  
  2042. // TAutoDriver - DispInterface Automation Proxy Driver
  2043. //
  2044. template <class DISPINTF>
  2045. class TAutoDriver : public TAutoDriverBase<IDispatch>
  2046. {
  2047. public:
  2048.   TAutoDriver(LCID lcid = LOCALE_SYSTEM_DEFAULT);
  2049.   TAutoDriver(const TAutoDriver<DISPINTF>  &src);
  2050.  ~TAutoDriver();
  2051.  
  2052.   // Bind via various mechanisms & Unbind
  2053.   // NOTE: Does *NOT* AddRef interface by default
  2054.   //
  2055.   void    Bind(DISPINTF *pintf, bool addRef = false);
  2056.   HRESULT Bind(LPUNKNOWN punk);
  2057.   HRESULT Bind(const GUID& guid);
  2058.   HRESULT Bind(LPCWSTR progid);
  2059.  
  2060.   // Bind to running copy of Server
  2061.   //
  2062.   HRESULT BindToActive(const GUID& guid);
  2063.   HRESULT BindToActive(LPCWSTR propid);
  2064.  
  2065.   // Bind to remote server
  2066.   //
  2067.   HRESULT BindToRemote(LPCWSTR machineName, const CLSID& clsid);
  2068.  
  2069.   // Unbind from DispInterface
  2070.   //
  2071.   void    Unbind(bool release = true);
  2072.  
  2073.   // Assignment of interface to object implies Bind to interface
  2074.   //
  2075.   TAutoDriver<DISPINTF>& operator =(DISPINTF *pintf)
  2076.   {
  2077.     Bind(pintf);
  2078.     return *this;
  2079.   }
  2080.  
  2081.   // Return Dispatch Interface
  2082.   //
  2083.   operator DISPINTF*()  const;
  2084.  
  2085.   // Bound or not?
  2086.   //
  2087.   bool     IsBound()    const;
  2088.   bool operator ! ()    const { return m_Dispatch == 0; }
  2089.   operator bool   ()    const { return m_Dispatch != 0; }
  2090.  
  2091.   // Allows access to interface being held
  2092.   // NOTE: Useful when dealing with dual interfaces
  2093.   //       Using '->' yields Vtable call while '.' yields Invoke call
  2094.   DISPINTF* operator -> ()
  2095.   {
  2096.     return m_Dispatch;
  2097.   }
  2098.  
  2099.   // Return address of interface
  2100.   //
  2101.   DISPINTF** operator & ()
  2102.   {
  2103.     // Can take address (to presumably stuff new interface pointer) only if
  2104.     // not currently Bound;
  2105.     _ASSERTE_(m_Dispatch==0);
  2106.     return &m_Dispatch;
  2107.   }
  2108.  
  2109.   // Wrappers of IDispatch methods
  2110.   //
  2111.   HRESULT GetIDsOfNames(LPCWSTR name, DISPID &id);
  2112.   HRESULT Invoke(DispatchFlag dFlags, LPCWSTR name, TAutoArgsBase* args, bool hasRetVal = true);
  2113.   HRESULT Invoke(DispatchFlag dFlags, DISPID dispId, TAutoArgsBase* args, bool hasRetVal = true);
  2114.  
  2115.   // Access to LCID settings
  2116.   //
  2117.   LCID get_lcid() const { return m_lcid;}
  2118.   void set_lcid(LCID l) { m_lcid = l;   }
  2119.  
  2120.   // Access to EXCEPINFO
  2121.   //
  2122.   EXCEPINFO& get_excepinfo() const { return m_ExcepInfo; }
  2123.  
  2124.   // Properties
  2125.   //
  2126.   __property LCID lcid = { read = get_lcid, write = set_lcid };
  2127.   __property EXCEPINFO excepinfo = { read = get_excepinfo    };
  2128.  
  2129.   // Procedures with/without parameters
  2130.   //
  2131.   HRESULT OleProcedure(DISPID dispId, TAutoArgsBase& args)
  2132.   {
  2133.     return Invoke(dfMethod, dispId, &args, false);
  2134.   }
  2135.   HRESULT OleProcedure(DISPID dispid)
  2136.   {
  2137.     return Invoke(dfMethod, dispid, 0, false);
  2138.   }
  2139.  
  2140.   // FUnctions with/without parameters
  2141.   HRESULT OleFunction(DISPID dispid, TAutoArgsBase& args)
  2142.   {
  2143.     return Invoke(dfMethod, dispid, &args, true);
  2144.   }
  2145.   HRESULT OleFunction(DISPID dispid)
  2146.   {
  2147.     return Invoke(dfMethod, dispid, 0, false);
  2148.   }
  2149.  
  2150.   // Property put (always has parameters)
  2151.   HRESULT OlePropertyPut(DISPID dispid, TAutoArgsBase& args)
  2152.   {
  2153.     return Invoke(dfPropPut, dispid, &args, false);
  2154.   }
  2155.  
  2156.   // Property get (always has parameters, even if just TAutoArgs<0>)
  2157.   HRESULT OlePropertyGet(DISPID dispid, TAutoArgsBase& args)
  2158.   {
  2159.     return Invoke(dfPropGet, dispid, &args, true);
  2160.   }
  2161.  
  2162.   // Property get that returns VARIANT
  2163.   VARIANTOBJ OlePropertyGet(DISPID dispid);
  2164.  
  2165. protected:
  2166.  
  2167.   typedef TDispId<DISPINTF> _TDispID;
  2168.  
  2169.   // Functions hold and let go of interface (no AddRef or Releases)
  2170.   // Used by Events interface wrappers
  2171.   //
  2172.   void        Attach(DISPINTF *pintf) { m_Dispatch = pintf;}
  2173.   void        Detach()                { m_Dispatch = 0;    }
  2174.  
  2175.   DISPINTF   *m_Dispatch;           // Disp Interface Pointer
  2176.   LCID        m_lcid;               // Locale for DispId lookup & Invoke
  2177.   EXCEPINFO   m_ExcepInfo;          // Exception Structure
  2178.   UINT        m_ErrArg;             // Index of erroneous argument
  2179. };
  2180.  
  2181.  
  2182. // TDispIdBase - Base class used by TDispId; allows us to have only one copy of the
  2183. //               flag governing whether DISPID should be looked up
  2184. template <class T>
  2185. class TDispIdBase
  2186. {
  2187. public:
  2188.   static  bool m_AlwaysGetDispid;
  2189. };
  2190.  
  2191. // This flag triggers a lookup even if the object was pass a valid (non -1) dispid!
  2192. // (Be careful if you enable this: Source interfaces do not typically expect a GetIDsofNames call)
  2193. //
  2194. template <class T>
  2195. bool TDispIdBase<T>::m_AlwaysGetDispid = false;
  2196.  
  2197. // TDispId - Class used to retrieve and cache a DISPID
  2198. //
  2199. template<class DISPINTF>
  2200. class TDispId : public TDispIdBase<DISPINTF>
  2201. {
  2202. public:
  2203.   TDispId(TAutoDriver<DISPINTF>& dispatch, LPCWSTR pName, DISPID id= DISPID_UNKNOWN) : m_DispId(id),
  2204.                                                                                        m_HResult(S_OK)
  2205.   {
  2206.     if (id == DISPID_UNKNOWN || m_AlwaysGetDispid)
  2207.       m_HResult = GetID(dispatch, pName);
  2208.   }
  2209.  
  2210.   TDispId(DISPID id) : m_DispId(id), m_HResult(S_OK)
  2211.   {}
  2212.  
  2213.   HRESULT GetID(TAutoDriver<DISPINTF>& dispatch, LPCWSTR pName)
  2214.   {
  2215.     return dispatch.GetIDsOfNames(pName, m_DispId);
  2216.   }
  2217.  
  2218.   operator DISPID() const
  2219.   {
  2220.     return  m_DispId;
  2221.   }
  2222.  
  2223.   HRESULT GetResult() const
  2224.   {
  2225.     return m_HResult;
  2226.   }
  2227.  
  2228.  
  2229. protected:
  2230.   DISPID    m_DispId;
  2231.   HRESULT   m_HResult;
  2232. };
  2233.  
  2234.  
  2235. // Ctr & Dtr of Automation Driver class
  2236. //
  2237. template <class DISPINTF>
  2238. TAutoDriver<DISPINTF>::TAutoDriver(LCID lcid) : m_Dispatch(0), m_lcid(lcid)
  2239. {}
  2240.  
  2241. //
  2242. template <class DISPINTF>
  2243. TAutoDriver<DISPINTF>::TAutoDriver(const TAutoDriver<DISPINTF>  &src)
  2244. {
  2245.   // NOTE: We do not copy the Exception, ErrArg or InitOle object
  2246.   //       We simply clear them out
  2247.   m_ErrArg = 0;
  2248.   ::ZeroMemory(&m_ExcepInfo, sizeof(m_ExcepInfo));
  2249.  
  2250.   // Copy Interface and AddRefCount
  2251.   m_Dispatch = src.m_Dispatch;
  2252.   if (m_Dispatch)
  2253.     m_Dispatch->AddRef();
  2254.  
  2255.   // Copy Locale
  2256.   m_lcid = src.m_lcid;
  2257. }
  2258.  
  2259. template <class DISPINTF>
  2260. TAutoDriver<DISPINTF>::~TAutoDriver()
  2261. {
  2262.   Unbind();
  2263. }
  2264.  
  2265. // Bind via Dispatch Interface
  2266. // NOTE: Does *NOT* AddRef interface
  2267. //
  2268. template <class DISPINTF> void
  2269. TAutoDriver<DISPINTF>::Bind(DISPINTF *pintf, bool addRef)
  2270. {
  2271.   Unbind();
  2272.   m_Dispatch = pintf;
  2273.   if (m_Dispatch && addRef)
  2274.     m_Dispatch->AddRef();
  2275. }
  2276.  
  2277. // Bind via IUnknown
  2278. //
  2279. template <class DISPINTF> HRESULT
  2280. TAutoDriver<DISPINTF>::Bind(LPUNKNOWN punk)
  2281. {
  2282.   _ASSERTE(punk);
  2283.   HRESULT hr = E_POINTER;
  2284.   if (punk)
  2285.   {
  2286.     DISPINTF *disp;
  2287.     hr = punk->QueryInterface(/* __uuidof(DISPINTF) */ IID_IDispatch, (LPVOID*)&disp);
  2288.     if (SUCCEEDED(hr))
  2289.       Bind(disp, false /* Don't AddRef */);
  2290.   }
  2291.   return hr;
  2292. }
  2293.  
  2294. // Bind via GUID
  2295. //
  2296. template <class DISPINTF> HRESULT
  2297. TAutoDriver<DISPINTF>::Bind(const GUID& clsid)
  2298. {
  2299.   static TInitOle initOle;
  2300.  
  2301.   LPUNKNOWN punk = 0;
  2302.   HRESULT hr = CoClassCreator::CoCreateInstance(clsid, IID_IUnknown, (LPVOID*)&punk);
  2303.   if (SUCCEEDED(hr))
  2304.   {
  2305.     // We should have a valid interface pointer
  2306.     //
  2307.     _ASSERTE(punk);
  2308.  
  2309.     // Run Object - just in case
  2310.     //
  2311.     hr = ::OleRun(punk);
  2312.  
  2313.     // Bind to running IUnknown
  2314.     //
  2315.     if (SUCCEEDED(hr))
  2316.       hr = Bind(punk);
  2317.  
  2318.     // Release IUnknown
  2319.     //
  2320.     punk->Release();
  2321.   }
  2322.   return hr;
  2323. }
  2324.  
  2325. // Bind via ProgId
  2326. //
  2327. template <class DISPINTF> HRESULT
  2328. TAutoDriver<DISPINTF>::Bind(LPCWSTR progid)
  2329. {
  2330.   GUID clsid;
  2331.   HRESULT hr = ::CLSIDFromProgID(progid, &clsid);
  2332.   if (SUCCEEDED(hr))
  2333.     return Bind(clsid);
  2334.   return hr;
  2335. }
  2336.  
  2337. // Bind to running copy of Object of this CLSID
  2338. //
  2339. template <class DISPINTF> HRESULT
  2340. TAutoDriver<DISPINTF>::BindToActive(const GUID& guid)
  2341. {
  2342.   LPUNKNOWN punk = 0;
  2343.   HRESULT hr = ::GetActiveObject(guid, 0, &punk);
  2344.   if (SUCCEEDED(hr))
  2345.     return Bind(punk);
  2346.   return hr;
  2347. }
  2348.  
  2349. // Bind to running copy of object with the specified progId
  2350. //
  2351. template <class DISPINTF> HRESULT
  2352. TAutoDriver<DISPINTF>::BindToActive(LPCWSTR progid)
  2353. {
  2354.   CLSID clsid;
  2355.   HRESULT hr = ::CLSIDFromProgID(progid, &clsid);
  2356.   if (SUCCEEDED(hr))
  2357.     return BindToActive(clsid);
  2358.   return hr;
  2359. }
  2360.  
  2361. // Bind to remote server on specified machine 
  2362. //
  2363. template <class DISPINTF> HRESULT
  2364. TAutoDriver<DISPINTF>::BindToRemote(LPCWSTR machineName, const CLSID& clsid)
  2365. {
  2366.   // Must unbind before binding to remote server
  2367.   //
  2368.   _ASSERTE(!IsBound());
  2369.   DISPINTF *pIntf;
  2370.   HRESULT hr = TCoClassCreatorT< TAutoDriver<DISPINTF>, DISPINTF, 
  2371.                                  clsid, 
  2372.                                  IID_IDispatch>::CreateRemote(machineName, &pIntf);
  2373.   if (SUCCEEDED(hr))
  2374.     Bind(pIntf);
  2375.   return hr;
  2376. }
  2377.  
  2378. // Release Dispatch Interface
  2379. //
  2380. template <class DISPINTF> void
  2381. TAutoDriver<DISPINTF>::Unbind(bool release)
  2382. {
  2383.   if (release && m_Dispatch)
  2384.     m_Dispatch->Release();
  2385.   m_Dispatch = 0;
  2386. }
  2387.  
  2388. // Return Dispatch Interface
  2389. //
  2390. template <class DISPINTF>
  2391. TAutoDriver<DISPINTF>::operator DISPINTF* () const
  2392. {
  2393.   return m_Dispatch;
  2394. }
  2395.  
  2396. // Returns Boolean indicating whether we're currently bound to the Server
  2397. //
  2398. template <class DISPINTF> bool
  2399. TAutoDriver<DISPINTF>::IsBound() const
  2400. {
  2401.   return m_Dispatch != 0;
  2402. }
  2403.  
  2404. // Encapsulation of IDispatch->GetIDsOfNames
  2405. //
  2406. template <class DISPINTF> HRESULT
  2407. TAutoDriver<DISPINTF>::GetIDsOfNames(LPCWSTR name, DISPID &id)
  2408. {
  2409.   _ASSERTE(name);
  2410.   _ASSERTE(IsBound());
  2411.   return m_Dispatch->GetIDsOfNames(IID_NULL, (LPWSTR*)(&name), 1, m_lcid, &id);
  2412. }
  2413.  
  2414. // Invoke specified 'name'
  2415. //
  2416. template <class DISPINTF> HRESULT
  2417. TAutoDriver<DISPINTF>::Invoke(DispatchFlag dFlags, LPCWSTR name, TAutoArgsBase* args, bool hasRetVal)
  2418. {
  2419.   DISPID dispid;
  2420.   HRESULT hr = GetIDsOfNames(name, dispId);
  2421.   if (SUCCEEDED(hr))
  2422.     hr = Invoke(dFlags, dispid, args);
  2423.   return hr;
  2424. }
  2425.  
  2426. // Invoke specified 'DispId'
  2427. //
  2428. template <class DISPINTF> HRESULT
  2429. TAutoDriver<DISPINTF>::Invoke(DispatchFlag dFlags, DISPID dispid, TAutoArgsBase* args, bool hasRetVal)
  2430. {
  2431.   _ASSERTE(IsBound());
  2432.  
  2433.   VARIANT* retVal = 0;
  2434.  
  2435.   // Having return value implies an Args array (even if it contains only one
  2436.   // variant for the return value).
  2437.   //
  2438.   _ASSERTE((hasRetVal==false && args==0) ||
  2439.            (hasRetVal==false && args!=0) ||
  2440.            (hasRetVal==true  && args!=0));
  2441.  
  2442.   // Setup return VARIANT
  2443.   // NOTE: PROPERTYPUTs do not return a result
  2444.   //
  2445.   if (!(dFlags & (dfPropPut|dfPropPutRef)) && hasRetVal)
  2446.     retVal = args->GetRetVal();
  2447.  
  2448.   // Special DispId for Property Puts
  2449.   //
  2450.   static DISPID DispIdPropertyPut = DISPID_PROPERTYPUT;
  2451.  
  2452.   // Setup DISPATCH parameters
  2453.   //
  2454.   DISPPARAMS params;
  2455.   ::ZeroMemory(¶ms, sizeof(params));
  2456.  
  2457.   // Set parameters (Note: PropPut[Ref] expected to have Count)
  2458.   if (args && args->GetCount())
  2459.   {
  2460.     params.cArgs = args->GetCount();
  2461.     params.rgvarg= args->GetArgs();
  2462.  
  2463.     // Handle PROPERTYPUT
  2464.     // NOTE: Assumes no named-arguments params have been setup
  2465.     //
  2466.     if (dFlags & (dfPropPut|dfPropPutRef))
  2467.     {
  2468.       params.cNamedArgs = 1;
  2469.       params.rgdispidNamedArgs = &DispIdPropertyPut;
  2470.     }
  2471.   }
  2472.  
  2473.   // Reset Error Information
  2474.   m_ErrArg = 0;
  2475.   ::ZeroMemory(&m_ExcepInfo, sizeof(m_ExcepInfo));
  2476.  
  2477.   // Invoke
  2478.   HRESULT hr = m_Dispatch->Invoke(dispid, IID_NULL, m_lcid, WORD(dFlags), ¶ms,
  2479.                                   retVal, &m_ExcepInfo, &m_ErrArg);
  2480.  
  2481.   // Check for deferred EXCEPTION fill-in
  2482.   if (hr == DISP_E_EXCEPTION)
  2483.     if (m_ExcepInfo.pfnDeferredFillIn)
  2484.       (*(m_ExcepInfo.pfnDeferredFillIn))(&m_ExcepInfo);
  2485.  
  2486.   // Turn on '__CHECKHR_ON_INVOKE' when you're debugging calls using the DISP wrappers
  2487.   //
  2488. #if defined(__CHECKHR_ON_INVOKE)
  2489.   OLECHECK(hr);
  2490. #endif
  2491.  
  2492.   // Output a little trace
  2493.   OLETRACE("Inv(%d) %s, 0x%lX, retVT(0x%X), ErrArg(%d)\n",
  2494.            dispid, SUCCEEDED(hr) ? "OK" : "FL", LONG(hr),
  2495.            retVal ? retVal->vt : VT_NULL, m_ErrArg);
  2496.  
  2497.   // Return result
  2498.   return hr;
  2499. }
  2500.  
  2501. // Property Get that returns a Variant (takes no parameters)
  2502. //
  2503. template <class DISPINTF> VARIANTOBJ
  2504. TAutoDriver<DISPINTF>::OlePropertyGet(DISPID dispid)
  2505. {
  2506.   TAutoArgs<0> args;
  2507.   OlePropertyGet(dispid, args);
  2508.   return args.GetRetVariant();
  2509. }
  2510.  
  2511. #endif    //  UTILCLS_NO_AUTOMATION
  2512.  
  2513. // Wrapper class encapsulating a DLL
  2514. //
  2515. class TDll
  2516. {
  2517. public:
  2518.   TDll(LPCTSTR name) : m_Hinstance(::LoadLibrary(name)) {}
  2519.  ~TDll() 
  2520.   {
  2521.     if (m_Hinstance)
  2522.       ::FreeLibrary(m_Hinstance);
  2523.   }
  2524.  
  2525.   operator HINSTANCE() const                      { return m_Hinstance; }
  2526.   FARPROC  GetProcAddress(LPCTSTR funcName) const { return ::GetProcAddress(*this, funcName); }
  2527.  
  2528. protected:
  2529.   HINSTANCE   m_Hinstance;
  2530.  
  2531. private:
  2532.   TDll(const TDll&);
  2533.   const TDll& operator=(const TDll&);
  2534. };
  2535.  
  2536. // TDllProc: Encapsulates a DLL EntryPoint/FARPROC
  2537. //
  2538. class TDllProc
  2539. {
  2540. public:
  2541.   TDllProc(const TDll& dll, LPCTSTR funcName)
  2542.   {
  2543.     m_Proc = dll.GetProcAddress(funcName);
  2544.   }
  2545.   operator bool() { return m_Proc != 0; }
  2546. protected:
  2547.   FARPROC   m_Proc;
  2548. };
  2549.  
  2550. // FARPROC that's CDECL, returns HRESULT and takes one parameter
  2551. //
  2552. template <class P1> 
  2553. class TDllProc1 : public TDllProc
  2554. {
  2555. public:
  2556.   TDllProc1(const TDll& dll , LPCTSTR funcName) : TDllProc(dll, funcName) {};
  2557.   HRESULT operator ()(P1 erste)
  2558.   {
  2559.     typedef HRESULT (__cdecl* outproc)(P1 erste);
  2560.     return ((outproc)m_Proc)(erste);
  2561.   }
  2562. };
  2563.  
  2564. // FARPROC that's STDCALL, returns HRESULT and take two parameters
  2565. // 
  2566. template <class P1, class P2>
  2567. class TDllStdProc2 : public TDllProc
  2568. {
  2569. public:
  2570.   TDllStdProc2(const TDll& dll, LPCTSTR funcName) : TDllProc(dll, funcName) {}
  2571.   HRESULT operator () (P1 p1, P2 p2)
  2572.   {
  2573.     typedef HRESULT (__stdcall* outproc)(P1 p1, P2 p2);
  2574.     return ((outproc)m_Proc)(p1, p2);
  2575.   }
  2576. };
  2577.  
  2578. #endif  __UTILCLS_H
  2579.