home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 May / PCP163A.iso / Runimage / Cbuilder4 / Include / Atl / ATLBASE.H next >
Encoding:
C/C++ Source or Header  |  1999-01-26  |  29.6 KB  |  1,087 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef __ATLBASE_H__
  12. #define __ATLBASE_H__
  13.  
  14. #ifndef __cplusplus
  15.   #error ATL requires C++ compilation (use a .cpp suffix)
  16. #endif
  17.  
  18. #ifdef _UNICODE
  19. #ifndef UNICODE
  20. #define UNICODE         // UNICODE is used by Windows headers
  21. #endif
  22. #endif
  23.  
  24. #ifdef UNICODE
  25. #ifndef _UNICODE
  26. #define _UNICODE        // _UNICODE is used by C-runtime/MFC headers
  27. #endif
  28. #endif
  29.  
  30. #ifdef _DEBUG
  31. #ifndef DEBUG
  32. #define DEBUG
  33. #endif
  34. #endif
  35.  
  36. // namespace and our templates don't quite work with earlier compiler
  37. // Can turn off namespace support directly, also
  38. #if _MSC_VER<1100
  39. #ifndef ATL_NO_NAMESPACE
  40. #define ATL_NO_NAMESPACE
  41. #endif
  42. #endif
  43.  
  44. ///////////////////////////////////////////////////////////////////////////////
  45. // __declspec(novtable) is used on a class declaration to prevent the vtable
  46. // pointer from being initialized in the constructor and destructor for the
  47. // class.  This has many benefits because the linker can now eliminate the
  48. // vtable and all the functions pointed to by the vtable.  Also, the actual
  49. // constructor and destructor code are now smaller.
  50. ///////////////////////////////////////////////////////////////////////////////
  51. // This should only be used on a class that is not directly createable but is
  52. // rather only used as a base class.  Additionally, the constructor and
  53. // destructor (if provided by the user) should not call anything that may cause
  54. // a virtual function call to occur back on the object.
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // By default, the wizards will generate new ATL object classes with this
  57. // attribute (through the ATL_NO_VTABLE macro).  This is normally safe as long
  58. // the restriction mentioned above is followed.  It is always safe to remove
  59. // this macro from your class, so if in doubt, remove it.
  60. ///////////////////////////////////////////////////////////////////////////////
  61.  
  62. // Define MACRO to allow detection of Borland's Compiler
  63. //
  64. #if defined(__BORLANDC__)       // Detect Borland C++
  65. #define BCC32_COMPAT            // BCC32_COMPAT flags the Borland Compiler
  66. #define _ATL_NO_FORCE_LIBS      // Eliminate #pragma comment(lib, xxxx)
  67. #define _ATL_NO_DEBUG_CRT       // Avoid including <CRTDBG.H>
  68. #endif  //  __BORLANDC__
  69.  
  70. #if (_MSC_VER<1100) && !defined(BCC32_COMPAT)
  71. #define ATL_NO_VTABLE
  72. #else
  73. #ifdef _ATL_DISABLE_NO_VTABLE
  74. #define ATL_NO_VTABLE
  75. #else
  76. #define ATL_NO_VTABLE __declspec(novtable)
  77. #endif
  78. #endif
  79.  
  80. #ifndef _ATL_NO_PRAGMA_WARNINGS
  81. #pragma warning(disable: 4201) // nameless unions are part of C++
  82. #pragma warning(disable: 4127) // constant expression
  83. #pragma warning(disable: 4512) // can't generate assignment operator (so what?)
  84. #pragma warning(disable: 4514) // unreferenced inlines are common
  85. #pragma warning(disable: 4103) // pragma pack
  86. #pragma warning(disable: 4702) // unreachable code
  87. #pragma warning(disable: 4237) // bool
  88. #pragma warning(disable: 4710) // function couldn't be inlined
  89. #pragma warning(disable: 4355) // 'this' : used in base member initializer list
  90. #pragma warning(disable: 4097) // typedef name used as synonym for class-name
  91.  
  92. #if defined(BCC32_COMPAT)      // Additional warnings for Borland's Compiler
  93. #pragma warn -aus              // xxx is assigned a value that is never used
  94. #pragma warn -rch              // unreachable code (usually a break after a return)
  95. #endif // BCC32_COMPAT
  96.  
  97. #endif //!_ATL_NO_PRAGMA_WARNINGS
  98.  
  99. #include <windows.h>
  100. #include <winnls.h>
  101. #include <ole2.h>
  102.  
  103. #include <stddef.h>
  104. #include <tchar.h>
  105. #include <malloc.h>
  106. #ifndef _ATL_NO_DEBUG_CRT
  107. // Warning: if you define the above symbol, you will have
  108. // to provide your own definition of the _ASSERTE(x) macro
  109. // in order to compile ATL
  110.   #include <crtdbg.h>
  111. #endif
  112.  
  113. #include <olectl.h>
  114. #include <winreg.h>
  115. #include "atliface.h"
  116.  
  117. #ifndef _ATL_PACKING
  118. #define _ATL_PACKING 8
  119. #endif
  120. #pragma pack(push, _ATL_PACKING)
  121.  
  122. #include "atlconv.h"
  123.  
  124. #if defined(_ATL_DLL)
  125.   #pragma comment(lib, "atl.lib")
  126.   #define ATLAPI extern "C" HRESULT __stdcall
  127.   #define ATLAPI_(x) extern "C" x __stdcall
  128. #elif defined(_ATL_DLL_IMPL)
  129.   #define ATLAPI extern "C" HRESULT __declspec(dllexport) __stdcall
  130.   #define ATLAPI_(x) extern "C" x __declspec(dllexport) __stdcall
  131. #else
  132.   #define ATLAPI HRESULT __stdcall
  133.   #define ATLAPI_(x) x __stdcall
  134. #endif
  135.  
  136. #ifndef ATL_NO_NAMESPACE
  137. #ifndef _ATL_DLL_IMPL
  138. namespace ATL
  139. {
  140. #endif
  141. #endif
  142.  
  143. typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void* pv, REFIID riid, LPVOID* ppv);
  144. typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void* pv, REFIID riid, LPVOID* ppv, DWORD dw);
  145. typedef HRESULT (WINAPI _ATL_MODULEFUNC)(DWORD dw);
  146. typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC)();
  147.  
  148. struct _ATL_OBJMAP_ENTRY
  149. {
  150.   const CLSID* pclsid;
  151.   HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);
  152.   _ATL_CREATORFUNC* pfnGetClassObject;
  153.   _ATL_CREATORFUNC* pfnCreateInstance;
  154.   IUnknown* pCF;
  155.   DWORD dwRegister;
  156.   _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription;
  157.   HRESULT WINAPI RevokeClassObject()
  158.   {
  159.     return CoRevokeClassObject(dwRegister);
  160.   }
  161.   HRESULT WINAPI RegisterClassObject(DWORD dwClsContext, DWORD dwFlags)
  162.   {
  163.     IUnknown* p = NULL;
  164.     HRESULT hRes = pfnGetClassObject(pfnCreateInstance, IID_IUnknown, (LPVOID*) &p);
  165.     if (SUCCEEDED(hRes))
  166.       hRes = CoRegisterClassObject(*pclsid, p, dwClsContext, dwFlags, &dwRegister);
  167.     if (p != NULL)
  168.       p->Release();
  169.     return hRes;
  170.   }
  171. };
  172.  
  173. struct _ATL_REGMAP_ENTRY
  174. {
  175.   LPCOLESTR     szKey;
  176.   LPCOLESTR     szData;
  177. };
  178.  
  179. struct _ATL_MODULE
  180. {
  181. // Attributes
  182. public:
  183.   UINT cbSize;
  184.   HINSTANCE m_hInst;
  185.   HINSTANCE m_hInstResource;
  186.   HINSTANCE m_hInstTypeLib;
  187.   _ATL_OBJMAP_ENTRY* m_pObjMap;
  188.   LONG m_nLockCnt;
  189.   HANDLE m_hHeap;
  190.   CRITICAL_SECTION m_csTypeInfoHolder;
  191.   CRITICAL_SECTION m_csWindowCreate;
  192.   CRITICAL_SECTION m_csObjMap;
  193. };
  194.  
  195. //This define makes debugging asserts easier.
  196. #define _ATL_SIMPLEMAPENTRY ((_ATL_CREATORARGFUNC*)1)
  197.  
  198. struct _ATL_INTMAP_ENTRY
  199. {
  200.   const IID* piid;       // the interface id (IID)
  201.   DWORD dw;
  202.   _ATL_CREATORARGFUNC* pFunc; //NULL:end, 1:offset, n:ptr
  203. };
  204.  
  205. /////////////////////////////////////////////////////////////////////////////
  206. // QI Support
  207.  
  208. ATLAPI AtlInternalQueryInterface(void* pThis,
  209.   const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject);
  210.  
  211. /////////////////////////////////////////////////////////////////////////////
  212. // Smart Pointer helpers
  213.  
  214. ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp);
  215. ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid);
  216.  
  217. /////////////////////////////////////////////////////////////////////////////
  218. // Inproc Marshaling helpers
  219. ATLAPI AtlFreeMarshalStream(IStream* pStream);
  220. ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream);
  221. ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk);
  222.  
  223. ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent);
  224.  
  225. /////////////////////////////////////////////////////////////////////////////
  226. // Connection Point Helpers
  227.  
  228. ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw);
  229. ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw);
  230.  
  231. /////////////////////////////////////////////////////////////////////////////
  232. // IDispatch Error handling
  233.  
  234. ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc,
  235.   DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes,
  236.   HINSTANCE hInst);
  237.  
  238. /////////////////////////////////////////////////////////////////////////////
  239. // Module
  240.  
  241. ATLAPI AtlModuleInit(_ATL_MODULE* pM, _ATL_OBJMAP_ENTRY* p, HINSTANCE h);
  242. ATLAPI AtlModuleRegisterClassObjects(_ATL_MODULE* pM, DWORD dwClsContext, DWORD dwFlags);
  243. ATLAPI AtlModuleRevokeClassObjects(_ATL_MODULE* pM);
  244. ATLAPI AtlModuleGetClassObject(_ATL_MODULE* pM, REFCLSID rclsid, REFIID riid, LPVOID* ppv);
  245. ATLAPI AtlModuleTerm(_ATL_MODULE* pM);
  246. ATLAPI AtlModuleRegisterServer(_ATL_MODULE* pM, BOOL bRegTypeLib, const CLSID* pCLSID = NULL);
  247. ATLAPI AtlModuleUnregisterServer(_ATL_MODULE* pM, const CLSID* pCLSID = NULL);
  248. ATLAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE*pM, LPCOLESTR lpszRes,
  249.   BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg = NULL);
  250. ATLAPI AtlModuleRegisterTypeLib(_ATL_MODULE* pM, LPCOLESTR lpszIndex);
  251.  
  252. #ifndef ATL_NO_NAMESPACE
  253. #ifndef _ATL_DLL_IMPL
  254. }; //namespace ATL
  255. #endif
  256. #endif
  257.  
  258. #ifndef ATL_NO_NAMESPACE
  259. namespace ATL
  260. {
  261. #endif
  262.  
  263. #if defined (_CPPUNWIND) & (defined(_ATL_EXCEPTIONS) | defined(_AFX))
  264. #define ATLTRY(x) try{x;} catch(...) {}
  265. #else
  266. #define ATLTRY(x) x;
  267. #endif
  268.  
  269. #ifdef _DEBUG
  270. void _cdecl AtlTrace(LPCTSTR lpszFormat, ...);
  271. #ifndef ATLTRACE
  272. #define ATLTRACE            AtlTrace
  273. #endif
  274. #define ATLTRACENOTIMPL(funcname)   ATLTRACE(_T("%s not implemented.\n"), funcname); return E_NOTIMPL
  275. #else
  276. inline void _cdecl AtlTrace(LPCTSTR , ...){}
  277. #ifndef ATLTRACE
  278. #define ATLTRACE            1 ? (void)0 : AtlTrace
  279. #endif
  280. #define ATLTRACENOTIMPL(funcname)   return E_NOTIMPL
  281. #endif //_DEBUG
  282.  
  283. #define offsetofclass(base, derived) ((DWORD)(static_cast<base*>((derived*)8))-8)
  284.  
  285. /////////////////////////////////////////////////////////////////////////////
  286. // Master version numbers
  287.  
  288. #define _ATL     1      // Active Template Library
  289. #define _ATL_VER 0x0200 // Active Template Library version 2.00
  290.  
  291. /////////////////////////////////////////////////////////////////////////////
  292. // Win32 libraries
  293.  
  294. #ifndef _ATL_NO_FORCE_LIBS
  295.   #pragma comment(lib, "kernel32.lib")
  296.   #pragma comment(lib, "user32.lib")
  297.   #pragma comment(lib, "ole32.lib")
  298.   #pragma comment(lib, "oleaut32.lib")
  299.   #pragma comment(lib, "olepro32.lib")
  300.   #pragma comment(lib, "uuid.lib")
  301.   #pragma comment(lib, "advapi32.lib")
  302. #endif // _ATL_NO_FORCE_LIBS
  303.  
  304. template <class T>
  305. class CComPtr
  306. {
  307. public:
  308.   typedef T _PtrClass;
  309.   CComPtr() {p=NULL;}
  310.   CComPtr(T* lp)
  311.   {
  312.     if ((p = lp) != NULL)
  313.       p->AddRef();
  314.   }
  315.   CComPtr(const CComPtr<T>& lp)
  316.   {
  317.     if ((p = lp.p) != NULL)
  318.       p->AddRef();
  319.   }
  320.   ~CComPtr() {if (p) p->Release();}
  321.   void Release() {if (p) p->Release(); p=NULL;}
  322.   operator T*() {return (T*)p;}
  323.   T& operator*() {_ASSERTE(p!=NULL); return *p; }
  324.   //The assert on operator& usually indicates a bug.  If this is really
  325.   //what is needed, however, take the address of the p member explicitly.
  326.   T** operator&() { _ASSERTE(p==NULL); return &p; }
  327.   T* operator->() { _ASSERTE(p!=NULL); return p; }
  328.   T* operator=(T* lp){return (T*)AtlComPtrAssign((IUnknown**)&p, lp);}
  329.   T* operator=(const CComPtr<T>& lp)
  330.   {
  331.     return (T*)AtlComPtrAssign((IUnknown**)&p, lp.p);
  332.   }
  333. #if _MSC_VER>1020
  334.   bool operator!(){return (p == NULL);}
  335. #else
  336.   BOOL operator!(){return (p == NULL) ? TRUE : FALSE;}
  337. #endif
  338.   T* p;
  339. };
  340.  
  341. //Note: CComQIPtr<IUnknown, &IID_IUnknown> is not meaningful
  342. //      Use CComPtr<IUnknown>
  343. template <class T, const IID* piid>
  344. class CComQIPtr
  345. {
  346. public:
  347.   typedef T _PtrClass;
  348.   CComQIPtr() {p=NULL;}
  349.   CComQIPtr(T* lp)
  350.   {
  351.     if ((p = lp) != NULL)
  352.       p->AddRef();
  353.   }
  354.   CComQIPtr(const CComQIPtr<T,piid>& lp)
  355.   {
  356.     if ((p = lp.p) != NULL)
  357.       p->AddRef();
  358.   }
  359.   // If you get an error that this member is already defined, you are probably
  360.   // using a CComQIPtr<IUnknown, &IID_IUnknown>.  This is not necessary.
  361.   // Use CComPtr<IUnknown>
  362.   CComQIPtr(IUnknown* lp)
  363.   {
  364.     p=NULL;
  365.     if (lp != NULL)
  366.       lp->QueryInterface(*piid, (void **)&p);
  367.   }
  368.   ~CComQIPtr() {if (p) p->Release();}
  369.   void Release() {if (p) p->Release(); p=NULL;}
  370.   operator T*() {return p;}
  371.   T& operator*() {_ASSERTE(p!=NULL); return *p; }
  372.   //The assert on operator& usually indicates a bug.  If this is really
  373.   //what is needed, however, take the address of the p member explicitly.
  374.   T** operator&() { _ASSERTE(p==NULL); return &p; }
  375.   T* operator->() {_ASSERTE(p!=NULL); return p; }
  376.   T* operator=(T* lp){return (T*)AtlComPtrAssign((IUnknown**)&p, lp);}
  377.   T* operator=(const CComQIPtr<T,piid>& lp)
  378.   {
  379.     return (T*)AtlComPtrAssign((IUnknown**)&p, lp.p);
  380.   }
  381.   T* operator=(IUnknown* lp)
  382.   {
  383.     return (T*)AtlComQIPtrAssign((IUnknown**)&p, lp, *piid);
  384.   }
  385. #if _MSC_VER>1020
  386.   bool operator!(){return (p == NULL);}
  387. #else
  388.   BOOL operator!(){return (p == NULL) ? TRUE : FALSE;}
  389. #endif
  390.   T* p;
  391. };
  392.  
  393. /////////////////////////////////////////////////////////////////////////////
  394. // CComBSTR
  395. class CComBSTR
  396. {
  397. public:
  398.   BSTR m_str;
  399.   CComBSTR()
  400.   {
  401.     m_str = NULL;
  402.   }
  403.   /*explicit*/ CComBSTR(int nSize, LPCOLESTR sz = NULL)
  404.   {
  405.     m_str = ::SysAllocStringLen(sz, nSize);
  406.   }
  407.   /*explicit*/ CComBSTR(LPCOLESTR pSrc)
  408.   {
  409.     m_str = ::SysAllocString(pSrc);
  410.   }
  411.   /*explicit*/ CComBSTR(const CComBSTR& src)
  412.   {
  413.     m_str = src.Copy();
  414.   }
  415.   CComBSTR& operator=(const CComBSTR& src);
  416.   CComBSTR& operator=(LPCOLESTR pSrc);
  417.   ~CComBSTR()
  418.   {
  419.     ::SysFreeString(m_str);
  420.   }
  421.   unsigned int Length() const
  422.   {
  423.     return SysStringLen(m_str);
  424.   }
  425.   operator BSTR() const
  426.   {
  427.     return m_str;
  428.   }
  429.   BSTR* operator&()
  430.   {
  431.     return &m_str;
  432.   }
  433.   BSTR Copy() const
  434.   {
  435.     return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
  436.   }
  437.   void Attach(BSTR src)
  438.   {
  439.     _ASSERTE(m_str == NULL);
  440.     m_str = src;
  441.   }
  442.   BSTR Detach()
  443.   {
  444.     BSTR s = m_str;
  445.     m_str = NULL;
  446.     return s;
  447.   }
  448.   void Empty()
  449.   {
  450.     ::SysFreeString(m_str);
  451.     m_str = NULL;
  452.   }
  453. #if _MSC_VER>1020
  454.   bool operator!()
  455.   {
  456.     return (m_str == NULL);
  457.   }
  458. #else
  459.   BOOL operator!()
  460.   {
  461.     return (m_str == NULL) ? TRUE : FALSE;
  462.   }
  463. #endif
  464.   void Append(const CComBSTR& bstrSrc)
  465.   {
  466.     Append(bstrSrc.m_str, SysStringLen(bstrSrc.m_str));
  467.   }
  468.   void Append(LPCOLESTR lpsz)
  469.   {
  470.     Append(lpsz, ocslen(lpsz));
  471.   }
  472.   // a BSTR is just a LPCOLESTR so we need a special version to signify
  473.   // that we are appending a BSTR
  474.   void AppendBSTR(BSTR p)
  475.   {
  476.     Append(p, SysStringLen(p));
  477.   }
  478.   void Append(LPCOLESTR lpsz, int nLen);
  479.  
  480.   CComBSTR& operator+=(const CComBSTR& bstrSrc)
  481.   {
  482.     AppendBSTR(bstrSrc.m_str);
  483.     return *this;
  484.   }
  485. #ifndef OLE2ANSI
  486.   /*explicit*/ CComBSTR(LPCSTR pSrc);
  487.   /*explicit*/ CComBSTR(int nSize, LPCSTR sz = NULL);
  488.   CComBSTR& operator=(LPCSTR pSrc);
  489.   void Append(LPCSTR);
  490. #endif
  491.   HRESULT WriteToStream(IStream* pStream);
  492.   HRESULT ReadFromStream(IStream* pStream);
  493. };
  494.  
  495. /////////////////////////////////////////////////////////////////////////////
  496. // CComVariant
  497.  
  498. class CComVariant : public tagVARIANT
  499. {
  500. // Constructors
  501. public:
  502.   CComVariant()
  503.   {
  504.     ::VariantInit(this);
  505.   }
  506.   ~CComVariant()
  507.   {
  508.     Clear();
  509.   }
  510.  
  511.   CComVariant(const VARIANT& varSrc)
  512.   {
  513.     ::VariantInit(this);
  514.     InternalCopy(&varSrc);
  515.   }
  516.  
  517.   CComVariant(const CComVariant& varSrc)
  518.   {
  519.     ::VariantInit(this);
  520.     InternalCopy(&varSrc);
  521.   }
  522.  
  523.   CComVariant(BSTR bstrSrc)
  524.   {
  525.     ::VariantInit(this);
  526.     *this = bstrSrc;
  527.   }
  528.   CComVariant(LPCOLESTR lpszSrc)
  529.   {
  530.     ::VariantInit(this);
  531.     *this = lpszSrc;
  532.   }
  533.  
  534. #ifndef OLE2ANSI
  535.   CComVariant(LPCSTR lpszSrc)
  536.   {
  537.     ::VariantInit(this);
  538.     *this = lpszSrc;}
  539. #endif
  540.  
  541. #if _MSC_VER>1020
  542.   CComVariant(bool bSrc)
  543.   {
  544.     ::VariantInit(this);
  545.     vt = VT_BOOL;
  546. #pragma warning(disable: 4310) // cast truncates constant value
  547.     boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
  548. #pragma warning(default: 4310) // cast truncates constant value
  549.   }
  550. #endif
  551.  
  552.   CComVariant(int nSrc)
  553.   {
  554.     ::VariantInit(this);
  555.     vt = VT_I4;
  556.     lVal = nSrc;
  557.   }
  558.   CComVariant(BYTE nSrc)
  559.   {
  560.     ::VariantInit(this);
  561.     vt = VT_UI1;
  562.     bVal = nSrc;
  563.   }
  564.   CComVariant(short nSrc)
  565.   {
  566.     ::VariantInit(this);
  567.     vt = VT_I2;
  568.     iVal = nSrc;
  569.   }
  570.   CComVariant(long nSrc, VARTYPE vtSrc = VT_I4)
  571.   {
  572.     _ASSERTE(vtSrc == VT_I4 || vtSrc == VT_ERROR);
  573.     ::VariantInit(this);
  574.     vt = vtSrc;
  575.     lVal = nSrc;
  576.   }
  577.   CComVariant(float fltSrc)
  578.   {
  579.     ::VariantInit(this);
  580.     vt = VT_R4;
  581.     fltVal = fltSrc;
  582.   }
  583.   CComVariant(double dblSrc)
  584.   {
  585.     ::VariantInit(this);
  586.     vt = VT_R8;
  587.     dblVal = dblSrc;
  588.   }
  589.   CComVariant(CY cySrc)
  590.   {
  591.     ::VariantInit(this);
  592.     vt = VT_CY;
  593.     cyVal.Hi = cySrc.Hi;
  594.     cyVal.Lo = cySrc.Lo;
  595.   }
  596.   CComVariant(IDispatch* pSrc)
  597.   {
  598.     ::VariantInit(this);
  599.     vt = VT_DISPATCH;
  600.     pdispVal = pSrc;
  601.     // Need to AddRef as VariantClear will Release
  602.     if (pdispVal != NULL)
  603.       pdispVal->AddRef();
  604.   }
  605.   CComVariant(IUnknown* pSrc)
  606.   {
  607.     ::VariantInit(this);
  608.     vt = VT_UNKNOWN;
  609.     punkVal = pSrc;
  610.     // Need to AddRef as VariantClear will Release
  611.     if (punkVal != NULL)
  612.       punkVal->AddRef();
  613.   }
  614.  
  615. // Assignment Operators
  616. public:
  617.   CComVariant& operator=(const CComVariant& varSrc)
  618.   {
  619.     InternalCopy(&varSrc);
  620.     return *this;
  621.   }
  622.   CComVariant& operator=(const VARIANT& varSrc)
  623.   {
  624.     InternalCopy(&varSrc);
  625.     return *this;
  626.   }
  627.  
  628.   CComVariant& operator=(BSTR bstrSrc);
  629.   CComVariant& operator=(LPCOLESTR lpszSrc);
  630.  
  631. #ifndef OLE2ANSI
  632.   CComVariant& operator=(LPCSTR lpszSrc);
  633. #endif
  634.  
  635. #if _MSC_VER>1020
  636.   CComVariant& operator=(bool bSrc);
  637. #endif
  638.   CComVariant& operator=(int nSrc);
  639.   CComVariant& operator=(BYTE nSrc);
  640.   CComVariant& operator=(short nSrc);
  641.   CComVariant& operator=(long nSrc);
  642.   CComVariant& operator=(float fltSrc);
  643.   CComVariant& operator=(double dblSrc);
  644.   CComVariant& operator=(CY cySrc);
  645.  
  646.   CComVariant& operator=(IDispatch* pSrc);
  647.   CComVariant& operator=(IUnknown* pSrc);
  648.  
  649. // Comparison Operators
  650. public:
  651. #if _MSC_VER>1020
  652.   bool operator==(const VARIANT& varSrc);
  653.   bool operator!=(const VARIANT& varSrc) {return !operator==(varSrc);}
  654. #else
  655.   BOOL operator==(const VARIANT& varSrc);
  656.   BOOL operator!=(const VARIANT& varSrc) {return !operator==(varSrc);}
  657. #endif
  658.  
  659. // Operations
  660. public:
  661.   HRESULT Clear() { return ::VariantClear(this); }
  662.   HRESULT Copy(const VARIANT* pSrc) { return ::VariantCopy(this, const_cast<VARIANT*>(pSrc)); }
  663.   HRESULT Attach(VARIANT* pSrc);
  664.   HRESULT Detach(VARIANT* pDest);
  665.   HRESULT ChangeType(VARTYPE vtNew, const VARIANT* pSrc = NULL);
  666.   HRESULT WriteToStream(IStream* pStream);
  667.   HRESULT ReadFromStream(IStream* pStream);
  668.  
  669. // Implementation
  670. public:
  671.   HRESULT InternalClear();
  672.   void InternalCopy(const VARIANT* pSrc);
  673. };
  674. /////////////////////////////////////////////////////////////////////////////
  675. // GUID comparison
  676.  
  677. inline BOOL InlineIsEqualGUID(REFGUID rguid1, REFGUID rguid2)
  678. {
  679.    return (
  680.     ((PLONG) &rguid1)[0] == ((PLONG) &rguid2)[0] &&
  681.     ((PLONG) &rguid1)[1] == ((PLONG) &rguid2)[1] &&
  682.     ((PLONG) &rguid1)[2] == ((PLONG) &rguid2)[2] &&
  683.     ((PLONG) &rguid1)[3] == ((PLONG) &rguid2)[3]);
  684. }
  685.  
  686. inline BOOL InlineIsEqualUnknown(REFGUID rguid1)
  687. {
  688.    return (
  689.     ((PLONG) &rguid1)[0] == 0 &&
  690.     ((PLONG) &rguid1)[1] == 0 &&
  691. #ifdef _MAC
  692.     ((PLONG) &rguid1)[2] == 0xC0000000 &&
  693.     ((PLONG) &rguid1)[3] == 0x00000046);
  694. #else
  695.     ((PLONG) &rguid1)[2] == 0x000000C0 &&
  696.     ((PLONG) &rguid1)[3] == 0x46000000);
  697. #endif
  698. }
  699.  
  700. /////////////////////////////////////////////////////////////////////////////
  701. // Threading Model Support
  702.  
  703. class CComCriticalSection
  704. {
  705. public:
  706.   void Lock() {EnterCriticalSection(&m_sec);}
  707.   void Unlock() {LeaveCriticalSection(&m_sec);}
  708.   void Init() {InitializeCriticalSection(&m_sec);}
  709.   void Term() {DeleteCriticalSection(&m_sec);}
  710.   CRITICAL_SECTION m_sec;
  711. };
  712.  
  713. class CComAutoCriticalSection
  714. {
  715. public:
  716.   void Lock() {EnterCriticalSection(&m_sec);}
  717.   void Unlock() {LeaveCriticalSection(&m_sec);}
  718.   CComAutoCriticalSection() {InitializeCriticalSection(&m_sec);}
  719.   ~CComAutoCriticalSection() {DeleteCriticalSection(&m_sec);}
  720.   CRITICAL_SECTION m_sec;
  721. };
  722.  
  723. class CComFakeCriticalSection
  724. {
  725. public:
  726.   void Lock() {}
  727.   void Unlock() {}
  728.   void Init() {}
  729.   void Term() {}
  730. };
  731.  
  732. class CComMultiThreadModelNoCS
  733. {
  734. public:
  735.   static ULONG WINAPI Increment(LPLONG p) {return InterlockedIncrement(p);}
  736.   static ULONG WINAPI Decrement(LPLONG p) {return InterlockedDecrement(p);}
  737.   typedef CComFakeCriticalSection AutoCriticalSection;
  738.   typedef CComFakeCriticalSection CriticalSection;
  739.   typedef CComMultiThreadModelNoCS ThreadModelNoCS;
  740. };
  741.  
  742. class CComMultiThreadModel
  743. {
  744. public:
  745.   static ULONG WINAPI Increment(LPLONG p) {return InterlockedIncrement(p);}
  746.   static ULONG WINAPI Decrement(LPLONG p) {return InterlockedDecrement(p);}
  747.   typedef CComAutoCriticalSection AutoCriticalSection;
  748.   typedef CComCriticalSection CriticalSection;
  749.   typedef CComMultiThreadModelNoCS ThreadModelNoCS;
  750. };
  751.  
  752. class CComSingleThreadModel
  753. {
  754. public:
  755.   static ULONG WINAPI Increment(LPLONG p) {return ++(*p);}
  756.   static ULONG WINAPI Decrement(LPLONG p) {return --(*p);}
  757.   typedef CComFakeCriticalSection AutoCriticalSection;
  758.   typedef CComFakeCriticalSection CriticalSection;
  759.   typedef CComSingleThreadModel ThreadModelNoCS;
  760. };
  761.  
  762. #ifndef _ATL_SINGLE_THREADED
  763. #ifndef _ATL_APARTMENT_THREADED
  764. #ifndef _ATL_FREE_THREADED
  765. #define _ATL_FREE_THREADED
  766. #endif
  767. #endif
  768. #endif
  769.  
  770. #if defined(_ATL_SINGLE_THREADED)
  771.   typedef CComSingleThreadModel CComObjectThreadModel;
  772.   typedef CComSingleThreadModel CComGlobalsThreadModel;
  773. #elif defined(_ATL_APARTMENT_THREADED)
  774.   typedef CComSingleThreadModel CComObjectThreadModel;
  775.   typedef CComMultiThreadModel CComGlobalsThreadModel;
  776. #else
  777.   typedef CComMultiThreadModel CComObjectThreadModel;
  778.   typedef CComMultiThreadModel CComGlobalsThreadModel;
  779. #endif
  780.  
  781. /////////////////////////////////////////////////////////////////////////////
  782. // CComModule
  783.  
  784. #define THREADFLAGS_APARTMENT 0x1
  785. #define THREADFLAGS_BOTH 0x2
  786. #define AUTPRXFLAG 0x4
  787.  
  788. struct _AtlCreateWndData
  789. {
  790.   void* m_pThis;
  791.   DWORD m_dwThreadID;
  792.   _AtlCreateWndData* m_pNext;
  793. };
  794.  
  795. class CComModule : public _ATL_MODULE
  796. {
  797. // Operations
  798. public:
  799.   _AtlCreateWndData* m_pCreateWndList;
  800.  
  801.   void AddCreateWndData(_AtlCreateWndData* pData, void* pObject);
  802.   void* ExtractCreateWndData();
  803.  
  804.   void Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h)
  805.   {
  806.     cbSize = sizeof(_ATL_MODULE);
  807.     m_pCreateWndList = NULL;
  808.     AtlModuleInit(this, p, h);
  809.   }
  810.   void Term()
  811.   {
  812.     AtlModuleTerm(this);
  813.   }
  814.  
  815.   LONG Lock() {return CComGlobalsThreadModel::Increment(&m_nLockCnt);}
  816.   LONG Unlock() {return CComGlobalsThreadModel::Decrement(&m_nLockCnt);}
  817.   LONG GetLockCount() {return m_nLockCnt;}
  818.  
  819.   HINSTANCE GetModuleInstance() {return m_hInst;}
  820.   HINSTANCE GetResourceInstance() {return m_hInstResource;}
  821.   HINSTANCE GetTypeLibInstance() {return m_hInstTypeLib;}
  822.  
  823.   // Registry support (helpers)
  824.   HRESULT RegisterTypeLib()
  825.   {
  826.     return AtlModuleRegisterTypeLib(this, NULL);
  827.   }
  828.   HRESULT RegisterTypeLib(LPCTSTR lpszIndex)
  829.   {
  830.     USES_CONVERSION;
  831.     return AtlModuleRegisterTypeLib(this, T2COLE(lpszIndex));
  832.   }
  833.   HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL)
  834.   {
  835.     return AtlModuleRegisterServer(this, bRegTypeLib, pCLSID);
  836.   }
  837.  
  838.   HRESULT UnregisterServer(const CLSID* pCLSID = NULL)
  839.   {
  840.     return AtlModuleUnregisterServer(this, pCLSID);
  841.   }
  842.  
  843.   // Resource-based Registration
  844.   HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes, BOOL bRegister,
  845.     struct _ATL_REGMAP_ENTRY* pMapEntries = NULL)
  846.   {
  847.     USES_CONVERSION;
  848.     return AtlModuleUpdateRegistryFromResourceD(this, T2COLE(lpszRes), bRegister,
  849.       pMapEntries);
  850.   }
  851.   HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID, BOOL bRegister,
  852.     struct _ATL_REGMAP_ENTRY* pMapEntries = NULL)
  853.   {
  854.     return AtlModuleUpdateRegistryFromResourceD(this,
  855.       (LPCOLESTR)MAKEINTRESOURCE(nResID), bRegister, pMapEntries);
  856.   }
  857.  
  858.   #ifdef _ATL_STATIC_REGISTRY
  859.   // Statically linking to Registry Ponent
  860.   HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister,
  861.     struct _ATL_REGMAP_ENTRY* pMapEntries = NULL);
  862.   HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister,
  863.     struct _ATL_REGMAP_ENTRY* pMapEntries = NULL);
  864.   #endif //_ATL_STATIC_REGISTRY
  865.  
  866.   // Standard Registration
  867.   HRESULT WINAPI UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID,
  868.     LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister);
  869.   HRESULT WINAPI RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID,
  870.     LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags);
  871.   HRESULT WINAPI UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID,
  872.     LPCTSTR lpszVerIndProgID);
  873.  
  874.   // Register/Revoke All Class Factories with the OS (EXE only)
  875.   HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags)
  876.   {
  877.     return AtlModuleRegisterClassObjects(this, dwClsContext, dwFlags);
  878.   }
  879.   HRESULT RevokeClassObjects()
  880.   {
  881.     return AtlModuleRevokeClassObjects(this);
  882.   }
  883.  
  884.   // Obtain a Class Factory (DLL only)
  885.   HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  886.   {
  887.     return AtlModuleGetClassObject(this, rclsid, riid, ppv);
  888.   }
  889.  
  890.   // Only used in CComAutoThreadModule
  891.   HRESULT CreateInstance(void* /*pfnCreateInstance*/, REFIID /*riid*/, void** /*ppvObj*/)
  892.   {
  893.     return S_OK;
  894.   }
  895. };
  896.  
  897. /////////////////////////////////////////////////////////////////////////////////////////////
  898. // Thread Pooling classes
  899.  
  900. class _AtlAptCreateObjData
  901. {
  902. public:
  903.   _ATL_CREATORFUNC* pfnCreateInstance;
  904.   const IID* piid;
  905.   HANDLE hEvent;
  906.   LPSTREAM pStream;
  907.   HRESULT hRes;
  908. };
  909.  
  910. class CComApartment
  911. {
  912. public:
  913.   static UINT ATL_CREATE_OBJECT;
  914.   static DWORD WINAPI _Apartment(void* pv)
  915.   {
  916.     return ((CComApartment*)pv)->Apartment();
  917.   }
  918.   DWORD Apartment()
  919.   {
  920.     CoInitialize(NULL);
  921.     MSG msg;
  922.     while(GetMessage(&msg, 0, 0, 0))
  923.     {
  924.       if (msg.message == ATL_CREATE_OBJECT)
  925.       {
  926.         _AtlAptCreateObjData* pdata = (_AtlAptCreateObjData*)msg.lParam;
  927.         IUnknown* pUnk = NULL;
  928.         pdata->hRes = pdata->pfnCreateInstance(NULL, IID_IUnknown, (void**)&pUnk);
  929.         if (SUCCEEDED(pdata->hRes))
  930.           pdata->hRes = CoMarshalInterThreadInterfaceInStream(*pdata->piid, pUnk, &pdata->pStream);
  931.         if (SUCCEEDED(pdata->hRes))
  932.         {
  933.           pUnk->Release();
  934.           ATLTRACE(_T("Object created on thread = %d\n"), GetCurrentThreadId());
  935.         }
  936.         SetEvent(pdata->hEvent);
  937.       }
  938.       DispatchMessage(&msg);
  939.     }
  940.     CoUninitialize();
  941.     return 0;
  942.   }
  943.   LONG Lock() {return CComGlobalsThreadModel::Increment(&m_nLockCnt);}
  944.   LONG Unlock(){return CComGlobalsThreadModel::Decrement(&m_nLockCnt);
  945.   }
  946.   LONG GetLockCount() {return m_nLockCnt;}
  947.  
  948.   DWORD m_dwThreadID;
  949.   HANDLE m_hThread;
  950.   LONG m_nLockCnt;
  951. };
  952.  
  953. class CComSimpleThreadAllocator
  954. {
  955. public:
  956.   CComSimpleThreadAllocator()
  957.   {
  958.     m_nThread = 0;
  959.   }
  960.   int GetThread(CComApartment* /*pApt*/, int nThreads)
  961.   {
  962.     if (++m_nThread == nThreads)
  963.       m_nThread = 0;
  964.     return m_nThread;
  965.   }
  966.   int m_nThread;
  967. };
  968.  
  969. #if _MSC_VER>1020
  970. template <class ThreadAllocator = CComSimpleThreadAllocator>
  971. #else
  972. template <class ThreadAllocator>
  973. #endif
  974. class CComAutoThreadModule : public CComModule
  975. {
  976. public:
  977.   void Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, int nThreads = GetDefaultThreads());
  978.   ~CComAutoThreadModule();
  979.   HRESULT CreateInstance(void* pfnCreateInstance, REFIID riid, void** ppvObj);
  980.   LONG Lock();
  981.   LONG Unlock();
  982.   DWORD dwThreadID;
  983.   int m_nThreads;
  984.   CComApartment* m_pApartments;
  985.   ThreadAllocator m_Allocator;
  986.   static int GetDefaultThreads()
  987.   {
  988.     SYSTEM_INFO si;
  989.     GetSystemInfo(&si);
  990.     return si.dwNumberOfProcessors * 4;
  991.   }
  992. };
  993.  
  994.  
  995.  
  996.  
  997. #ifdef _ATL_STATIC_REGISTRY
  998. #define UpdateRegistryFromResource UpdateRegistryFromResourceS
  999. #else
  1000. #define UpdateRegistryFromResource UpdateRegistryFromResourceD
  1001. #endif
  1002.  
  1003. /////////////////////////////////////////////////////////////////////////////
  1004. // CRegKey
  1005.  
  1006. class CRegKey
  1007. {
  1008. public:
  1009.   CRegKey();
  1010.   ~CRegKey();
  1011.  
  1012. // Attributes
  1013. public:
  1014.   operator HKEY() const;
  1015.   HKEY m_hKey;
  1016.  
  1017. // Operations
  1018. public:
  1019.   LONG SetValue(DWORD dwValue, LPCTSTR lpszValueName);
  1020.   LONG QueryValue(DWORD& dwValue, LPCTSTR lpszValueName);
  1021.   LONG QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount);
  1022.   LONG SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL);
  1023.  
  1024.   LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL);
  1025.   static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName,
  1026.     LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL);
  1027.  
  1028.   LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName,
  1029.     LPTSTR lpszClass = REG_NONE, DWORD dwOptions = REG_OPTION_NON_VOLATILE,
  1030.     REGSAM samDesired = KEY_ALL_ACCESS,
  1031.     LPSECURITY_ATTRIBUTES lpSecAttr = NULL,
  1032.     LPDWORD lpdwDisposition = NULL);
  1033.   LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName,
  1034.     REGSAM samDesired = KEY_ALL_ACCESS);
  1035.   LONG Close();
  1036.   HKEY Detach();
  1037.   void Attach(HKEY hKey);
  1038.   LONG DeleteSubKey(LPCTSTR lpszSubKey);
  1039.   LONG RecurseDeleteKey(LPCTSTR lpszKey);
  1040.   LONG DeleteValue(LPCTSTR lpszValue);
  1041. };
  1042.  
  1043. inline CRegKey::CRegKey()
  1044. {m_hKey = NULL;}
  1045.  
  1046. inline CRegKey::~CRegKey()
  1047. {Close();}
  1048.  
  1049. inline CRegKey::operator HKEY() const
  1050. {return m_hKey;}
  1051.  
  1052. inline HKEY CRegKey::Detach()
  1053. {
  1054.   HKEY hKey = m_hKey;
  1055.   m_hKey = NULL;
  1056.   return hKey;
  1057. }
  1058.  
  1059. inline void CRegKey::Attach(HKEY hKey)
  1060. {
  1061.   _ASSERTE(m_hKey == NULL);
  1062.   m_hKey = hKey;
  1063. }
  1064.  
  1065. inline LONG CRegKey::DeleteSubKey(LPCTSTR lpszSubKey)
  1066. {
  1067.   _ASSERTE(m_hKey != NULL);
  1068.   return RegDeleteKey(m_hKey, lpszSubKey);
  1069. }
  1070.  
  1071. inline LONG CRegKey::DeleteValue(LPCTSTR lpszValue)
  1072. {
  1073.   _ASSERTE(m_hKey != NULL);
  1074.   return RegDeleteValue(m_hKey, (LPTSTR)lpszValue);
  1075. }
  1076.  
  1077. #pragma pack(pop)
  1078.  
  1079. #ifndef ATL_NO_NAMESPACE
  1080. }; //namespace ATL
  1081. using namespace ATL;
  1082. #endif
  1083.  
  1084. #endif // __ATLBASE_H__
  1085.  
  1086. /////////////////////////////////////////////////////////////////////////////
  1087.