Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2278 lines
54 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-2001 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. #ifndef __ATLBASE_H__
  11. #define __ATLBASE_H__
  12. #pragma once
  13. #ifdef _ATL_ALL_WARNINGS
  14. #pragma warning( push )
  15. #endif
  16. #pragma warning(disable: 4127) // constant expression
  17. #pragma warning(disable: 4097) // typedef name used as synonym for class-name
  18. #pragma warning(disable: 4786) // identifier was truncated in the debug information
  19. #pragma warning(disable: 4291) // allow placement new
  20. #pragma warning(disable: 4201) // nameless unions are part of C++
  21. #pragma warning(disable: 4103) // pragma pack
  22. #pragma warning(disable: 4268) // const static/global data initialized to zeros
  23. #pragma warning (push)
  24. #ifndef __cplusplus
  25. #error ATL requires C++ compilation (use a .cpp suffix)
  26. #endif
  27. #include <atldef.h>
  28. #ifndef _WINSOCKAPI_
  29. #include <winsock2.h>
  30. #endif
  31. #include <windows.h>
  32. #include <winnls.h>
  33. #include <ole2.h>
  34. #include <oleauto.h>
  35. #include <comcat.h>
  36. #include <stddef.h>
  37. #include <winsvc.h>
  38. #include <tchar.h>
  39. #include <malloc.h>
  40. #include <limits.h>
  41. #include <errno.h>
  42. //REVIEW: Lame definition of InterlockedExchangePointer in system headers
  43. #ifdef _M_IX86
  44. #undef InterlockedExchangePointer
  45. inline void* InterlockedExchangePointer(void** pp, void* pNew) throw()
  46. {
  47. return( reinterpret_cast<void*>(static_cast<LONG_PTR>(::InterlockedExchange(reinterpret_cast<LONG*>(pp), static_cast<LONG>(reinterpret_cast<LONG_PTR>(pNew))))) );
  48. }
  49. #endif
  50. #ifndef _ATL_NO_DEBUG_CRT
  51. // Warning: if you define the above symbol, you will have
  52. // to provide your own definition of the ATLASSERT(x) macro
  53. // in order to compile ATL
  54. #include <crtdbg.h>
  55. #endif
  56. #include <olectl.h>
  57. #include <winreg.h>
  58. #include <atliface.h>
  59. #include <errno.h>
  60. #include <process.h> // for _beginthreadex, _endthreadex
  61. #ifdef _DEBUG
  62. #include <stdio.h>
  63. #include <stdarg.h>
  64. #endif
  65. #include <atlconv.h>
  66. #include <shlwapi.h>
  67. #include <atlsimpcoll.h>
  68. #pragma pack(push, _ATL_PACKING)
  69. #ifndef _ATL_NO_DEFAULT_LIBS
  70. #ifdef _DEBUG
  71. #pragma comment(lib, "atlsd.lib")
  72. #else
  73. #pragma comment(lib, "atls.lib")
  74. #endif
  75. #endif // !_ATL_NO_DEFAULT_LIBS
  76. // {394C3DE0-3C6F-11d2-817B-00C04F797AB7}
  77. _declspec(selectany) GUID GUID_ATLVer70 = { 0x394c3de0, 0x3c6f, 0x11d2, { 0x81, 0x7b, 0x0, 0xc0, 0x4f, 0x79, 0x7a, 0xb7 } };
  78. namespace ATL
  79. {
  80. struct _ATL_CATMAP_ENTRY
  81. {
  82. int iType;
  83. const CATID* pcatid;
  84. };
  85. #define _ATL_CATMAP_ENTRY_END 0
  86. #define _ATL_CATMAP_ENTRY_IMPLEMENTED 1
  87. #define _ATL_CATMAP_ENTRY_REQUIRED 2
  88. typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void* pv, REFIID riid, LPVOID* ppv);
  89. typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw);
  90. typedef HRESULT (WINAPI _ATL_MODULEFUNC)(DWORD_PTR dw);
  91. typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC)();
  92. typedef const struct _ATL_CATMAP_ENTRY* (_ATL_CATMAPFUNC)();
  93. typedef void (__stdcall _ATL_TERMFUNC)(DWORD_PTR dw);
  94. // perfmon registration/unregistration function definitions
  95. typedef HRESULT (*_ATL_PERFREGFUNC)(HINSTANCE hDllInstance);
  96. typedef HRESULT (*_ATL_PERFUNREGFUNC)();
  97. __declspec(selectany) _ATL_PERFREGFUNC _pPerfRegFunc = NULL;
  98. __declspec(selectany) _ATL_PERFUNREGFUNC _pPerfUnRegFunc = NULL;
  99. struct _ATL_TERMFUNC_ELEM
  100. {
  101. _ATL_TERMFUNC* pFunc;
  102. DWORD_PTR dw;
  103. _ATL_TERMFUNC_ELEM* pNext;
  104. };
  105. // Can't inherit from _ATL_OBJMAP_ENTRY20
  106. // because it messes up the OBJECT_MAP macros
  107. struct _ATL_OBJMAP_ENTRY30
  108. {
  109. const CLSID* pclsid;
  110. HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);
  111. _ATL_CREATORFUNC* pfnGetClassObject;
  112. _ATL_CREATORFUNC* pfnCreateInstance;
  113. IUnknown* pCF;
  114. DWORD dwRegister;
  115. _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription;
  116. _ATL_CATMAPFUNC* pfnGetCategoryMap;
  117. // Added in ATL 3.0
  118. void (WINAPI *pfnObjectMain)(bool bStarting);
  119. };
  120. typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY;
  121. #if defined(_M_IA64) || defined(_M_IX86)
  122. #pragma data_seg(push)
  123. #pragma data_seg("ATL$__a")
  124. __declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL;
  125. #pragma data_seg("ATL$__z")
  126. __declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL;
  127. #pragma data_seg("ATL$__m")
  128. #if !defined(_M_IA64)
  129. #pragma comment(linker, "/merge:ATL=.data")
  130. #endif
  131. #pragma data_seg(pop)
  132. #else
  133. //REVIEW: data_seg(push/pop)?
  134. __declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL;
  135. __declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL;
  136. #endif // defined(_M_IA64) || defined(_M_IX86)
  137. struct _ATL_REGMAP_ENTRY
  138. {
  139. LPCOLESTR szKey;
  140. LPCOLESTR szData;
  141. };
  142. /////////////////////////////////////////////////////////////////////////////
  143. // Threading Model Support
  144. class CComCriticalSection
  145. {
  146. public:
  147. CComCriticalSection() throw()
  148. {
  149. memset(&m_sec, 0, sizeof(CRITICAL_SECTION));
  150. }
  151. HRESULT Lock() throw()
  152. {
  153. EnterCriticalSection(&m_sec);
  154. return S_OK;
  155. }
  156. HRESULT Unlock() throw()
  157. {
  158. LeaveCriticalSection(&m_sec);
  159. return S_OK;
  160. }
  161. HRESULT Init() throw()
  162. {
  163. HRESULT hRes = S_OK;
  164. __try
  165. {
  166. InitializeCriticalSection(&m_sec);
  167. }
  168. // structured exception may be raised in low memory situations
  169. __except(EXCEPTION_EXECUTE_HANDLER)
  170. {
  171. if (STATUS_NO_MEMORY == GetExceptionCode())
  172. hRes = E_OUTOFMEMORY;
  173. else
  174. hRes = E_FAIL;
  175. }
  176. return hRes;
  177. }
  178. HRESULT Term() throw()
  179. {
  180. DeleteCriticalSection(&m_sec);
  181. return S_OK;
  182. }
  183. CRITICAL_SECTION m_sec;
  184. };
  185. // Module
  186. // Used by any project that uses ATL
  187. struct _ATL_BASE_MODULE70
  188. {
  189. UINT cbSize;
  190. HINSTANCE m_hInst;
  191. HINSTANCE m_hInstResource;
  192. DWORD dwAtlBuildVer;
  193. GUID* pguidVer;
  194. CComCriticalSection m_csResource;
  195. };
  196. typedef _ATL_BASE_MODULE70 _ATL_BASE_MODULE;
  197. // Used by COM related code in ATL
  198. struct _ATL_COM_MODULE70
  199. {
  200. UINT cbSize;
  201. HINSTANCE m_hInstTypeLib;
  202. _ATL_OBJMAP_ENTRY** m_ppAutoObjMapFirst;
  203. _ATL_OBJMAP_ENTRY** m_ppAutoObjMapLast;
  204. CComCriticalSection m_csObjMap;
  205. };
  206. typedef _ATL_COM_MODULE70 _ATL_COM_MODULE;
  207. // Used by Windowing code in ATL
  208. struct _ATL_WIN_MODULE70
  209. {
  210. UINT cbSize;
  211. CComCriticalSection m_csWindowCreate;
  212. ATOM m_rgWindowClassAtoms[128];
  213. int m_nAtomIndex;
  214. };
  215. typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE;
  216. struct _ATL_MODULE70
  217. {
  218. UINT cbSize;
  219. LONG m_nLockCnt;
  220. _ATL_TERMFUNC_ELEM* m_pTermFuncs;
  221. CComCriticalSection m_csStaticDataInitAndTypeInfo;
  222. };
  223. typedef _ATL_MODULE70 _ATL_MODULE;
  224. /////////////////////////////////////////////////////////////////////////////
  225. //This define makes debugging asserts easier.
  226. #define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC*)1)
  227. struct _ATL_INTMAP_ENTRY
  228. {
  229. const IID* piid; // the interface id (IID)
  230. DWORD_PTR dw;
  231. _ATL_CREATORARGFUNC* pFunc; //NULL:end, 1:offset, n:ptr
  232. };
  233. /////////////////////////////////////////////////////////////////////////////
  234. // QI Support
  235. ATLAPI AtlInternalQueryInterface(void* pThis,
  236. const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject);
  237. /////////////////////////////////////////////////////////////////////////////
  238. // Smart Pointer helpers
  239. ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp);
  240. ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid);
  241. /////////////////////////////////////////////////////////////////////////////
  242. // IDispatch Error handling
  243. ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc,
  244. DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes,
  245. HINSTANCE hInst);
  246. /////////////////////////////////////////////////////////////////////////////
  247. // Module
  248. ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv);
  249. ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID = NULL);
  250. ATLAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE* pComModule, BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL);
  251. ATLAPI AtlRegisterClassCategoriesHelper( REFCLSID clsid, const struct _ATL_CATMAP_ENTRY* pCatMap, BOOL bRegister );
  252. ATLAPI AtlRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex);
  253. ATLAPI AtlUnRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex);
  254. ATLAPI AtlLoadTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib);
  255. ATLAPI AtlModuleAddTermFunc(_ATL_MODULE* pModule, _ATL_TERMFUNC* pFunc, DWORD_PTR dw);
  256. ATLAPI_(void) AtlCallTermFunc(_ATL_MODULE* pModule);
  257. }; //namespace ATL
  258. /////////////////////////////////////////////////////////////////////////////
  259. // GUID comparison
  260. namespace ATL
  261. {
  262. inline BOOL InlineIsEqualUnknown(REFGUID rguid1)
  263. {
  264. return (
  265. ((PLONG) &rguid1)[0] == 0 &&
  266. ((PLONG) &rguid1)[1] == 0 &&
  267. ((PLONG) &rguid1)[2] == 0x000000C0 &&
  268. ((PLONG) &rguid1)[3] == 0x46000000);
  269. }
  270. }; // namespace ATL
  271. namespace ATL
  272. {
  273. ATL_NOINLINE inline HRESULT AtlHresultFromLastError() throw()
  274. {
  275. DWORD dwErr = ::GetLastError();
  276. return HRESULT_FROM_WIN32(dwErr);
  277. }
  278. ATL_NOINLINE inline HRESULT AtlHresultFromWin32(DWORD nError) throw()
  279. {
  280. return( HRESULT_FROM_WIN32( nError ) );
  281. }
  282. }; // namespace ATL
  283. #include <atlexcept.h>
  284. namespace ATL
  285. {
  286. template <class T>
  287. class _NoAddRefReleaseOnCComPtr : public T
  288. {
  289. private:
  290. STDMETHOD_(ULONG, AddRef)()=0;
  291. STDMETHOD_(ULONG, Release)()=0;
  292. };
  293. template< typename T >
  294. class CAutoVectorPtr
  295. {
  296. public:
  297. CAutoVectorPtr() throw() :
  298. m_p( NULL )
  299. {
  300. }
  301. CAutoVectorPtr( CAutoVectorPtr< T >& p ) throw()
  302. {
  303. m_p = p.Detach(); // Transfer ownership
  304. }
  305. explicit CAutoVectorPtr( T* p ) throw() :
  306. m_p( p )
  307. {
  308. }
  309. ~CAutoVectorPtr() throw()
  310. {
  311. Free();
  312. }
  313. operator T*() const throw()
  314. {
  315. return( m_p );
  316. }
  317. CAutoVectorPtr< T >& operator=( CAutoVectorPtr< T >& p ) throw()
  318. {
  319. Free();
  320. Attach( p.Detach() ); // Transfer ownership
  321. return( *this );
  322. }
  323. // Allocate the vector
  324. bool Allocate( size_t nElements ) throw()
  325. {
  326. ATLASSERT( m_p == NULL );
  327. ATLTRY( m_p = new T[nElements] );
  328. if( m_p == NULL )
  329. {
  330. return( false );
  331. }
  332. return( true );
  333. }
  334. // Attach to an existing pointer (takes ownership)
  335. void Attach( T* p ) throw()
  336. {
  337. ATLASSERT( m_p == NULL );
  338. m_p = p;
  339. }
  340. // Detach the pointer (releases ownership)
  341. T* Detach() throw()
  342. {
  343. T* p;
  344. p = m_p;
  345. m_p = NULL;
  346. return( p );
  347. }
  348. // Delete the vector pointed to, and set the pointer to NULL
  349. void Free() throw()
  350. {
  351. delete[] m_p;
  352. m_p = NULL;
  353. }
  354. public:
  355. T* m_p;
  356. };
  357. //CComPtrBase provides the basis for all other smart pointers
  358. //The other smartpointers add their own constructors and operators
  359. template <class T>
  360. class CComPtrBase
  361. {
  362. protected:
  363. CComPtrBase() throw()
  364. {
  365. p = NULL;
  366. }
  367. CComPtrBase(int nNull) throw()
  368. {
  369. ATLASSERT(nNull == 0);
  370. (void)nNull;
  371. p = NULL;
  372. }
  373. CComPtrBase(T* lp) throw()
  374. {
  375. p = lp;
  376. if (p != NULL)
  377. p->AddRef();
  378. }
  379. public:
  380. typedef T _PtrClass;
  381. ~CComPtrBase() throw()
  382. {
  383. if (p)
  384. p->Release();
  385. }
  386. operator T*() const throw()
  387. {
  388. return p;
  389. }
  390. T& operator*() const throw()
  391. {
  392. ATLASSERT(p!=NULL);
  393. return *p;
  394. }
  395. //The assert on operator& usually indicates a bug. If this is really
  396. //what is needed, however, take the address of the p member explicitly.
  397. T** operator&() throw()
  398. {
  399. ATLASSERT(p==NULL);
  400. return &p;
  401. }
  402. _NoAddRefReleaseOnCComPtr<T>* operator->() const throw()
  403. {
  404. ATLASSERT(p!=NULL);
  405. return (_NoAddRefReleaseOnCComPtr<T>*)p;
  406. }
  407. bool operator!() const throw()
  408. {
  409. return (p == NULL);
  410. }
  411. bool operator<(T* pT) const throw()
  412. {
  413. return p < pT;
  414. }
  415. bool operator==(T* pT) const throw()
  416. {
  417. return p == pT;
  418. }
  419. // Release the interface and set to NULL
  420. void Release() throw()
  421. {
  422. T* pTemp = p;
  423. if (pTemp)
  424. {
  425. p = NULL;
  426. pTemp->Release();
  427. }
  428. }
  429. // Compare two objects for equivalence
  430. bool IsEqualObject(IUnknown* pOther) throw()
  431. {
  432. if (p == pOther)
  433. return true;
  434. if (p == NULL || pOther == NULL)
  435. return false; // One is NULL the other is not
  436. CComPtr<IUnknown> punk1;
  437. CComPtr<IUnknown> punk2;
  438. p->QueryInterface(__uuidof(IUnknown), (void**)&punk1);
  439. pOther->QueryInterface(__uuidof(IUnknown), (void**)&punk2);
  440. return punk1 == punk2;
  441. }
  442. // Attach to an existing interface (does not AddRef)
  443. void Attach(T* p2) throw()
  444. {
  445. if (p)
  446. p->Release();
  447. p = p2;
  448. }
  449. // Detach the interface (does not Release)
  450. T* Detach() throw()
  451. {
  452. T* pt = p;
  453. p = NULL;
  454. return pt;
  455. }
  456. HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw()
  457. {
  458. ATLASSERT(p == NULL);
  459. return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);
  460. }
  461. HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw()
  462. {
  463. CLSID clsid;
  464. HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
  465. ATLASSERT(p == NULL);
  466. if (SUCCEEDED(hr))
  467. hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);
  468. return hr;
  469. }
  470. template <class Q>
  471. HRESULT QueryInterface(Q** pp) const throw()
  472. {
  473. ATLASSERT(pp != NULL);
  474. return p->QueryInterface(__uuidof(Q), (void**)pp);
  475. }
  476. T* p;
  477. };
  478. template <class T>
  479. class CComPtr : public CComPtrBase<T>
  480. {
  481. public:
  482. CComPtr() throw()
  483. {
  484. }
  485. CComPtr(int nNull) throw() :
  486. CComPtrBase<T>(nNull)
  487. {
  488. }
  489. CComPtr(T* lp) throw() :
  490. CComPtrBase<T>(lp)
  491. {
  492. }
  493. CComPtr(const CComPtr<T>& lp) throw() :
  494. CComPtrBase<T>(lp.p)
  495. {
  496. }
  497. template <typename Q>
  498. T* operator=(const CComPtr<Q>& lp) throw()
  499. {
  500. return static_cast<T*>(AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(T)));
  501. }
  502. };
  503. template <class T, const IID* piid = &__uuidof(T)>
  504. class CComQIPtr : public CComPtr<T>
  505. {
  506. public:
  507. CComQIPtr() throw()
  508. {
  509. }
  510. CComQIPtr(T* lp) throw() :
  511. CComPtr<T>(lp)
  512. {
  513. }
  514. CComQIPtr(const CComQIPtr<T,piid>& lp) throw() :
  515. CComPtr<T>(lp.p)
  516. {
  517. }
  518. CComQIPtr(IUnknown* lp) throw()
  519. {
  520. if (lp != NULL)
  521. lp->QueryInterface(*piid, (void **)&p);
  522. }
  523. T* operator=(T* lp) throw()
  524. {
  525. return static_cast<T*>(AtlComPtrAssign((IUnknown**)&p, lp));
  526. }
  527. T* operator=(const CComQIPtr<T,piid>& lp) throw()
  528. {
  529. return static_cast<T*>(AtlComPtrAssign((IUnknown**)&p, lp.p));
  530. }
  531. T* operator=(IUnknown* lp) throw()
  532. {
  533. return static_cast<T*>(AtlComQIPtrAssign((IUnknown**)&p, lp, *piid));
  534. }
  535. };
  536. //Specialization to make it work
  537. template<>
  538. class CComQIPtr<IUnknown, &IID_IUnknown> : public CComPtr<IUnknown>
  539. {
  540. public:
  541. CComQIPtr() throw()
  542. {
  543. }
  544. CComQIPtr(IUnknown* lp) throw()
  545. {
  546. //Actually do a QI to get identity
  547. if (lp != NULL)
  548. lp->QueryInterface(__uuidof(IUnknown), (void **)&p);
  549. }
  550. CComQIPtr(const CComQIPtr<IUnknown,&IID_IUnknown>& lp) throw() :
  551. CComPtr<IUnknown>(lp.p)
  552. {
  553. }
  554. IUnknown* operator=(IUnknown* lp) throw()
  555. {
  556. //Actually do a QI to get identity
  557. return AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(IUnknown));
  558. }
  559. IUnknown* operator=(const CComQIPtr<IUnknown,&IID_IUnknown>& lp) throw()
  560. {
  561. return AtlComPtrAssign((IUnknown**)&p, lp.p);
  562. }
  563. };
  564. /////////////////////////////////////////////////////////////////////////////
  565. // Threading Model Support
  566. class CComAutoCriticalSection : public CComCriticalSection
  567. {
  568. public:
  569. CComAutoCriticalSection()
  570. {
  571. HRESULT hr = CComCriticalSection::Init();
  572. if (FAILED(hr))
  573. AtlThrow(hr);
  574. }
  575. ~CComAutoCriticalSection() throw()
  576. {
  577. CComCriticalSection::Term();
  578. }
  579. private :
  580. HRESULT Init(); // Not implemented. CComAutoCriticalSection::Init should never be called
  581. HRESULT Term(); // Not implemented. CComAutoCriticalSection::Term should never be called
  582. };
  583. class CComFakeCriticalSection
  584. {
  585. public:
  586. HRESULT Lock() throw() { return S_OK; }
  587. HRESULT Unlock() throw() { return S_OK; }
  588. HRESULT Init() throw() { return S_OK; }
  589. HRESULT Term() throw() { return S_OK; }
  590. };
  591. template< class TLock >
  592. class CComCritSecLock
  593. {
  594. public:
  595. CComCritSecLock( TLock& cs, bool bInitialLock = true );
  596. ~CComCritSecLock() throw();
  597. HRESULT Lock() throw();
  598. void Unlock() throw();
  599. // Implementation
  600. private:
  601. TLock& m_cs;
  602. bool m_bLocked;
  603. // Private to avoid accidental use
  604. CComCritSecLock( const CComCritSecLock& ) throw();
  605. CComCritSecLock& operator=( const CComCritSecLock& ) throw();
  606. };
  607. template< class TLock >
  608. inline CComCritSecLock< TLock >::CComCritSecLock( TLock& cs, bool bInitialLock ) :
  609. m_cs( cs ),
  610. m_bLocked( false )
  611. {
  612. if( bInitialLock )
  613. {
  614. HRESULT hr;
  615. hr = Lock();
  616. if( FAILED( hr ) )
  617. {
  618. AtlThrow( hr );
  619. }
  620. }
  621. }
  622. template< class TLock >
  623. inline CComCritSecLock< TLock >::~CComCritSecLock() throw()
  624. {
  625. if( m_bLocked )
  626. {
  627. Unlock();
  628. }
  629. }
  630. template< class TLock >
  631. inline HRESULT CComCritSecLock< TLock >::Lock() throw()
  632. {
  633. HRESULT hr;
  634. ATLASSERT( !m_bLocked );
  635. hr = m_cs.Lock();
  636. if( FAILED( hr ) )
  637. {
  638. return( hr );
  639. }
  640. m_bLocked = true;
  641. return( S_OK );
  642. }
  643. template< class TLock >
  644. inline void CComCritSecLock< TLock >::Unlock() throw()
  645. {
  646. ATLASSERT( m_bLocked );
  647. m_cs.Unlock();
  648. m_bLocked = false;
  649. }
  650. class CComMultiThreadModelNoCS
  651. {
  652. public:
  653. static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);}
  654. static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);}
  655. typedef CComFakeCriticalSection AutoCriticalSection;
  656. typedef CComFakeCriticalSection CriticalSection;
  657. typedef CComMultiThreadModelNoCS ThreadModelNoCS;
  658. };
  659. class CComMultiThreadModel
  660. {
  661. public:
  662. static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);}
  663. static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);}
  664. typedef CComAutoCriticalSection AutoCriticalSection;
  665. typedef CComCriticalSection CriticalSection;
  666. typedef CComMultiThreadModelNoCS ThreadModelNoCS;
  667. };
  668. class CComSingleThreadModel
  669. {
  670. public:
  671. static ULONG WINAPI Increment(LPLONG p) throw() {return ++(*p);}
  672. static ULONG WINAPI Decrement(LPLONG p) throw() {return --(*p);}
  673. typedef CComFakeCriticalSection AutoCriticalSection;
  674. typedef CComFakeCriticalSection CriticalSection;
  675. typedef CComSingleThreadModel ThreadModelNoCS;
  676. };
  677. #if defined(_ATL_APARTMENT_THREADED)
  678. #if defined(_ATL_SINGLE_THREADED) || defined(_ATL_FREE_THREADED)
  679. #pragma message ("More than one global threading model defined.")
  680. #endif
  681. typedef CComSingleThreadModel CComObjectThreadModel;
  682. typedef CComMultiThreadModel CComGlobalsThreadModel;
  683. #elif defined(_ATL_FREE_THREADED)
  684. #if defined(_ATL_SINGLE_THREADED) || defined(_ATL_APARTMENT_THREADED)
  685. #pragma message ("More than one global threading model defined.")
  686. #endif
  687. typedef CComMultiThreadModel CComObjectThreadModel;
  688. typedef CComMultiThreadModel CComGlobalsThreadModel;
  689. #else
  690. #pragma message ("No global threading model defined")
  691. #endif
  692. }; // namespace ATL
  693. namespace ATL
  694. {
  695. /////////////////////////////////////////////////////////////////////////////
  696. // Dual argument helper classes
  697. #define UpdateRegistryFromResource UpdateRegistryFromResourceS
  698. #ifndef _delayimp_h
  699. extern "C" IMAGE_DOS_HEADER __ImageBase;
  700. #endif
  701. class CAtlBaseModule : public _ATL_BASE_MODULE
  702. {
  703. public :
  704. static bool m_bInitFailed;
  705. CAtlBaseModule() throw()
  706. {
  707. cbSize = sizeof(_ATL_BASE_MODULE);
  708. m_hInst = m_hInstResource = reinterpret_cast<HINSTANCE>(&__ImageBase);
  709. dwAtlBuildVer = _ATL_VER;
  710. pguidVer = &GUID_ATLVer70;
  711. if (FAILED(m_csResource.Init()))
  712. {
  713. ATLASSERT(0);
  714. CAtlBaseModule::m_bInitFailed = true;
  715. }
  716. }
  717. ~CAtlBaseModule() throw ()
  718. {
  719. }
  720. HINSTANCE GetModuleInstance() throw()
  721. {
  722. return m_hInst;
  723. }
  724. HINSTANCE GetResourceInstance() throw()
  725. {
  726. return m_hInstResource;
  727. }
  728. };
  729. __declspec(selectany) bool CAtlBaseModule::m_bInitFailed = false;
  730. extern CAtlBaseModule _AtlBaseModule;
  731. class CAtlComModule : public _ATL_COM_MODULE
  732. {
  733. public:
  734. CAtlComModule() throw()
  735. {
  736. cbSize = sizeof(_ATL_COM_MODULE);
  737. m_hInstTypeLib = reinterpret_cast<HINSTANCE>(&__ImageBase);
  738. m_ppAutoObjMapFirst = &__pobjMapEntryFirst + 1;
  739. m_ppAutoObjMapLast = &__pobjMapEntryLast;
  740. if (FAILED(m_csObjMap.Init()))
  741. {
  742. ATLASSERT(0);
  743. CAtlBaseModule::m_bInitFailed = true;
  744. }
  745. }
  746. ~CAtlComModule()
  747. {
  748. Term();
  749. }
  750. // Called from ~CAtlComModule or from ~CAtlExeModule.
  751. void Term()
  752. {
  753. if (cbSize == 0)
  754. return;
  755. for (_ATL_OBJMAP_ENTRY** ppEntry = m_ppAutoObjMapFirst; ppEntry < m_ppAutoObjMapLast; ppEntry++)
  756. {
  757. if (*ppEntry != NULL)
  758. {
  759. _ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
  760. if (pEntry->pCF != NULL)
  761. pEntry->pCF->Release();
  762. pEntry->pCF = NULL;
  763. }
  764. }
  765. // Set to 0 to indicate that this function has been called
  766. // At this point no one should be concerned about cbsize
  767. // having the correct value
  768. cbSize = 0;
  769. }
  770. // RegisterServer walks the ATL Autogenerated object map and registers each object in the map
  771. // If pCLSID is not NULL then only the object referred to by pCLSID is registered (The default case)
  772. // otherwise all the objects are registered
  773. HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL)
  774. {
  775. return AtlComModuleRegisterServer(this, bRegTypeLib, pCLSID);
  776. }
  777. // UnregisterServer walks the ATL Autogenerated object map and unregisters each object in the map
  778. // If pCLSID is not NULL then only the object referred to by pCLSID is unregistered (The default case)
  779. // otherwise all the objects are unregistered.
  780. HRESULT UnregisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL)
  781. {
  782. return AtlComModuleUnregisterServer(this, bRegTypeLib, pCLSID);
  783. }
  784. };
  785. class CAtlModule;
  786. __declspec(selectany) CAtlModule* _pAtlModule = NULL;
  787. class CRegObject;
  788. class ATL_NO_VTABLE CAtlModule : public _ATL_MODULE
  789. {
  790. public :
  791. static GUID m_libid;
  792. IGlobalInterfaceTable* m_pGIT;
  793. CAtlModule() throw()
  794. {
  795. // Should have only one instance of a class
  796. // derived from CAtlModule in a project.
  797. ATLASSERT(_pAtlModule == NULL);
  798. cbSize = sizeof(_ATL_MODULE);
  799. m_pTermFuncs = NULL;
  800. m_nLockCnt = 0;
  801. _pAtlModule = this;
  802. if (FAILED(m_csStaticDataInitAndTypeInfo.Init()))
  803. {
  804. ATLASSERT(0);
  805. CAtlBaseModule::m_bInitFailed = true;
  806. }
  807. m_pGIT = NULL;
  808. }
  809. void Term() throw()
  810. {
  811. // cbSize == 0 indicates that Term has already been called
  812. if (cbSize == 0)
  813. return;
  814. // Call term functions
  815. if (m_pTermFuncs != NULL)
  816. {
  817. AtlCallTermFunc(this);
  818. m_pTermFuncs = NULL;
  819. }
  820. if (m_pGIT != NULL)
  821. m_pGIT->Release();
  822. cbSize = 0;
  823. }
  824. ~CAtlModule() throw()
  825. {
  826. Term();
  827. }
  828. virtual LONG Lock() throw()
  829. {
  830. return CComGlobalsThreadModel::Increment(&m_nLockCnt);
  831. }
  832. virtual LONG Unlock() throw()
  833. {
  834. return CComGlobalsThreadModel::Decrement(&m_nLockCnt);
  835. }
  836. virtual LONG GetLockCount() throw()
  837. {
  838. return m_nLockCnt;
  839. }
  840. HRESULT AddTermFunc(_ATL_TERMFUNC* pFunc, DWORD_PTR dw) throw()
  841. {
  842. return AtlModuleAddTermFunc(this, pFunc, dw);
  843. }
  844. virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* /*pRegistrar*/) throw()
  845. {
  846. return S_OK;
  847. }
  848. // Statically linking to Registry component
  849. HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister,
  850. struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw();
  851. HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister,
  852. struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw();
  853. // Implementation
  854. static void EscapeSingleQuote(LPOLESTR lpDest, LPCOLESTR lp) throw()
  855. {
  856. while (*lp)
  857. {
  858. *lpDest++ = *lp;
  859. if (*lp == '\'')
  860. *lpDest++ = *lp;
  861. lp++;
  862. }
  863. *lpDest = NULL;
  864. }
  865. };
  866. __declspec(selectany) GUID CAtlModule::m_libid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
  867. template <class T>
  868. class ATL_NO_VTABLE CAtlModuleT : public CAtlModule
  869. {
  870. public :
  871. CAtlModuleT() throw()
  872. {
  873. T::InitLibId();
  874. }
  875. static void InitLibId() throw()
  876. {
  877. }
  878. HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw();
  879. HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw();
  880. };
  881. class CComModule;
  882. __declspec(selectany) CComModule* _pModule = NULL;
  883. class CComModule : public CAtlModuleT<CComModule>
  884. {
  885. public :
  886. CComModule()
  887. {
  888. // Should have only one instance of a class
  889. // derived from CComModule in a project.
  890. ATLASSERT(_pModule == NULL);
  891. _pModule = this;
  892. }
  893. HINSTANCE m_hInst;
  894. HINSTANCE m_hInstTypeLib;
  895. // For Backward compatibility
  896. _ATL_OBJMAP_ENTRY* m_pObjMap;
  897. HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL) throw();
  898. void Term() throw();
  899. HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw();
  900. // Registry support (helpers)
  901. HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw();
  902. HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw();
  903. HRESULT UnregisterServer(const CLSID* pCLSID = NULL) throw();
  904. // Statically linking to Registry Ponent
  905. virtual HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister,
  906. struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw()
  907. {
  908. return CAtlModuleT<CComModule>::UpdateRegistryFromResourceS(lpszRes, bRegister, pMapEntries);
  909. }
  910. virtual HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister,
  911. struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw()
  912. {
  913. return CAtlModuleT<CComModule>::UpdateRegistryFromResourceS(nResID, bRegister, pMapEntries);
  914. }
  915. };
  916. #define ATL_VARIANT_TRUE VARIANT_BOOL( -1 )
  917. #define ATL_VARIANT_FALSE VARIANT_BOOL( 0 )
  918. /////////////////////////////////////////////////////////////////////////////
  919. // CComBSTR
  920. class CComBSTR
  921. {
  922. public:
  923. BSTR m_str;
  924. CComBSTR() throw()
  925. {
  926. m_str = NULL;
  927. }
  928. CComBSTR(int nSize)
  929. {
  930. if (nSize == 0)
  931. m_str = NULL;
  932. else
  933. {
  934. m_str = ::SysAllocStringLen(NULL, nSize);
  935. if (m_str == NULL)
  936. AtlThrow(E_OUTOFMEMORY);
  937. }
  938. }
  939. CComBSTR(LPCOLESTR pSrc)
  940. {
  941. if (pSrc == NULL)
  942. m_str = NULL;
  943. else
  944. {
  945. m_str = ::SysAllocString(pSrc);
  946. if (m_str == NULL)
  947. AtlThrow(E_OUTOFMEMORY);
  948. }
  949. }
  950. CComBSTR(const CComBSTR& src)
  951. {
  952. m_str = src.Copy();
  953. if (!!src && m_str == NULL)
  954. AtlThrow(E_OUTOFMEMORY);
  955. }
  956. CComBSTR& operator=(const CComBSTR& src)
  957. {
  958. if (m_str != src.m_str)
  959. {
  960. ::SysFreeString(m_str);
  961. m_str = src.Copy();
  962. if (!!src && m_str == NULL)
  963. AtlThrow(E_OUTOFMEMORY);
  964. }
  965. return *this;
  966. }
  967. CComBSTR& operator=(LPCOLESTR pSrc)
  968. {
  969. ::SysFreeString(m_str);
  970. if (pSrc != NULL)
  971. {
  972. m_str = ::SysAllocString(pSrc);
  973. if (m_str == NULL)
  974. AtlThrow(E_OUTOFMEMORY);
  975. }
  976. else
  977. m_str = NULL;
  978. return *this;
  979. }
  980. ~CComBSTR() throw()
  981. {
  982. ::SysFreeString(m_str);
  983. }
  984. unsigned int Length() const throw()
  985. {
  986. return (m_str == NULL)? 0 : SysStringLen(m_str);
  987. }
  988. unsigned int ByteLength() const throw()
  989. {
  990. return (m_str == NULL)? 0 : SysStringByteLen(m_str);
  991. }
  992. operator BSTR() const throw()
  993. {
  994. return m_str;
  995. }
  996. BSTR* operator&() throw()
  997. {
  998. return &m_str;
  999. }
  1000. BSTR Copy() const throw()
  1001. {
  1002. if (m_str == NULL)
  1003. return NULL;
  1004. return ::SysAllocStringByteLen((char*)m_str, ::SysStringByteLen(m_str));
  1005. }
  1006. void Attach(BSTR src) throw()
  1007. {
  1008. ::SysFreeString(m_str);
  1009. m_str = src;
  1010. }
  1011. BSTR Detach() throw()
  1012. {
  1013. BSTR s = m_str;
  1014. m_str = NULL;
  1015. return s;
  1016. }
  1017. void Empty() throw()
  1018. {
  1019. ::SysFreeString(m_str);
  1020. m_str = NULL;
  1021. }
  1022. bool operator!() const throw()
  1023. {
  1024. return (m_str == NULL);
  1025. }
  1026. HRESULT Append(LPCOLESTR lpsz) throw()
  1027. {
  1028. return Append(lpsz, UINT(lstrlenW(lpsz)));
  1029. }
  1030. // a BSTR is just a LPCOLESTR so we need a special version to signify
  1031. // that we are appending a BSTR
  1032. HRESULT AppendBSTR(BSTR p) throw()
  1033. {
  1034. if (p == NULL)
  1035. return S_OK;
  1036. BSTR bstrNew = NULL;
  1037. HRESULT hr;
  1038. hr = VarBstrCat(m_str, p, &bstrNew);
  1039. if (SUCCEEDED(hr))
  1040. {
  1041. ::SysFreeString(m_str);
  1042. m_str = bstrNew;
  1043. }
  1044. return hr;
  1045. }
  1046. HRESULT Append(LPCOLESTR lpsz, int nLen) throw()
  1047. {
  1048. if (lpsz == NULL || (m_str != NULL && nLen == 0))
  1049. return S_OK;
  1050. int n1 = Length();
  1051. BSTR b;
  1052. b = ::SysAllocStringLen(NULL, n1+nLen);
  1053. if (b == NULL)
  1054. return E_OUTOFMEMORY;
  1055. memcpy(b, m_str, n1*sizeof(OLECHAR));
  1056. memcpy(b+n1, lpsz, nLen*sizeof(OLECHAR));
  1057. b[n1+nLen] = NULL;
  1058. SysFreeString(m_str);
  1059. m_str = b;
  1060. return S_OK;
  1061. }
  1062. CComBSTR& operator+=(LPCOLESTR pszSrc)
  1063. {
  1064. HRESULT hr;
  1065. hr = Append(pszSrc);
  1066. if (FAILED(hr))
  1067. AtlThrow(hr);
  1068. return *this;
  1069. }
  1070. bool operator<(const CComBSTR& bstrSrc) const throw()
  1071. {
  1072. return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == VARCMP_LT;
  1073. }
  1074. bool operator<(LPCOLESTR pszSrc) const
  1075. {
  1076. CComBSTR bstr2(pszSrc);
  1077. return operator<(bstr2);
  1078. }
  1079. bool operator>(const CComBSTR& bstrSrc) const throw()
  1080. {
  1081. return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == VARCMP_GT;
  1082. }
  1083. bool operator>(LPCOLESTR pszSrc) const
  1084. {
  1085. CComBSTR bstr2(pszSrc);
  1086. return operator>(bstr2);
  1087. }
  1088. bool operator==(const CComBSTR& bstrSrc) const throw()
  1089. {
  1090. return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == VARCMP_EQ;
  1091. }
  1092. bool operator==(LPCOLESTR pszSrc) const
  1093. {
  1094. CComBSTR bstr2(pszSrc);
  1095. return operator==(bstr2);
  1096. }
  1097. };
  1098. /////////////////////////////////////////////////////////////////////////////
  1099. // CComVariant
  1100. class CComVariant : public tagVARIANT
  1101. {
  1102. // Constructors
  1103. public:
  1104. CComVariant() throw()
  1105. {
  1106. ::VariantInit(this);
  1107. }
  1108. ~CComVariant() throw()
  1109. {
  1110. Clear();
  1111. }
  1112. CComVariant(LPCOLESTR lpszSrc)
  1113. {
  1114. vt = VT_EMPTY;
  1115. *this = lpszSrc;
  1116. }
  1117. // Assignment Operators
  1118. public:
  1119. CComVariant& operator=(const VARIANT& varSrc)
  1120. {
  1121. InternalCopy(&varSrc);
  1122. return *this;
  1123. }
  1124. CComVariant& operator=(LPCOLESTR lpszSrc)
  1125. {
  1126. Clear();
  1127. vt = VT_BSTR;
  1128. bstrVal = ::SysAllocString(lpszSrc);
  1129. if (bstrVal == NULL && lpszSrc != NULL)
  1130. {
  1131. vt = VT_ERROR;
  1132. scode = E_OUTOFMEMORY;
  1133. }
  1134. return *this;
  1135. }
  1136. CComVariant& operator=(long nSrc) throw()
  1137. {
  1138. if (vt != VT_I4)
  1139. {
  1140. Clear();
  1141. vt = VT_I4;
  1142. }
  1143. lVal = nSrc;
  1144. return *this;
  1145. }
  1146. CComVariant& operator=(unsigned long nSrc) throw()
  1147. {
  1148. if (vt != VT_UI4)
  1149. {
  1150. Clear();
  1151. vt = VT_UI4;
  1152. }
  1153. ulVal = nSrc;
  1154. return *this;
  1155. }
  1156. // Operations
  1157. public:
  1158. HRESULT Clear() { return ::VariantClear(this); }
  1159. HRESULT Copy(const VARIANT* pSrc) { return ::VariantCopy(this, const_cast<VARIANT*>(pSrc)); }
  1160. HRESULT Detach(VARIANT* pDest)
  1161. {
  1162. ATLASSERT(pDest != NULL);
  1163. // Clear out the variant
  1164. HRESULT hr = ::VariantClear(pDest);
  1165. if (!FAILED(hr))
  1166. {
  1167. // Copy the contents and remove control from CComVariant
  1168. memcpy(pDest, this, sizeof(VARIANT));
  1169. vt = VT_EMPTY;
  1170. hr = S_OK;
  1171. }
  1172. return hr;
  1173. }
  1174. // Implementation
  1175. private:
  1176. void InternalCopy(const VARIANT* pSrc)
  1177. {
  1178. HRESULT hr = Copy(pSrc);
  1179. if (FAILED(hr))
  1180. {
  1181. vt = VT_ERROR;
  1182. scode = hr;
  1183. }
  1184. }
  1185. };
  1186. /////////////////////////////////////////////////////////////////////////////
  1187. // CRegKey
  1188. class CRegKey
  1189. {
  1190. public:
  1191. CRegKey() throw();
  1192. ~CRegKey() throw();
  1193. // Attributes
  1194. public:
  1195. operator HKEY() const throw();
  1196. HKEY m_hKey;
  1197. // Operations
  1198. public:
  1199. LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw();
  1200. LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw();
  1201. LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ) throw();
  1202. LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw();
  1203. LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw();
  1204. LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw();
  1205. LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw();
  1206. // Create a new registry key (or open an existing one).
  1207. LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName,
  1208. LPTSTR lpszClass = REG_NONE, DWORD dwOptions = REG_OPTION_NON_VOLATILE,
  1209. REGSAM samDesired = KEY_READ | KEY_WRITE,
  1210. LPSECURITY_ATTRIBUTES lpSecAttr = NULL,
  1211. LPDWORD lpdwDisposition = NULL) throw();
  1212. // Open an existing registry key.
  1213. LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName,
  1214. REGSAM samDesired = KEY_READ | KEY_WRITE) throw();
  1215. // Close the registry key.
  1216. LONG Close() throw();
  1217. // Detach the CRegKey object from its HKEY. Releases ownership.
  1218. HKEY Detach() throw();
  1219. // Attach the CRegKey object to an existing HKEY. Takes ownership.
  1220. void Attach(HKEY hKey) throw();
  1221. LONG DeleteSubKey(LPCTSTR lpszSubKey) throw();
  1222. LONG RecurseDeleteKey(LPCTSTR lpszKey) throw();
  1223. LONG DeleteValue(LPCTSTR lpszValue) throw();
  1224. };
  1225. inline CRegKey::CRegKey() :
  1226. m_hKey( NULL )
  1227. {
  1228. }
  1229. inline CRegKey::~CRegKey()
  1230. {
  1231. Close();
  1232. }
  1233. inline CRegKey::operator HKEY() const
  1234. {
  1235. return m_hKey;
  1236. }
  1237. inline HKEY CRegKey::Detach()
  1238. {
  1239. HKEY hKey = m_hKey;
  1240. m_hKey = NULL;
  1241. return hKey;
  1242. }
  1243. inline void CRegKey::Attach(HKEY hKey)
  1244. {
  1245. ATLASSERT(m_hKey == NULL);
  1246. m_hKey = hKey;
  1247. }
  1248. inline LONG CRegKey::DeleteSubKey(LPCTSTR lpszSubKey)
  1249. {
  1250. ATLASSERT(m_hKey != NULL);
  1251. return RegDeleteKey(m_hKey, lpszSubKey);
  1252. }
  1253. inline LONG CRegKey::DeleteValue(LPCTSTR lpszValue)
  1254. {
  1255. ATLASSERT(m_hKey != NULL);
  1256. return RegDeleteValue(m_hKey, (LPTSTR)lpszValue);
  1257. }
  1258. inline LONG CRegKey::Close()
  1259. {
  1260. LONG lRes = ERROR_SUCCESS;
  1261. if (m_hKey != NULL)
  1262. {
  1263. lRes = RegCloseKey(m_hKey);
  1264. m_hKey = NULL;
  1265. }
  1266. return lRes;
  1267. }
  1268. inline LONG CRegKey::Create(HKEY hKeyParent, LPCTSTR lpszKeyName,
  1269. LPTSTR lpszClass, DWORD dwOptions, REGSAM samDesired,
  1270. LPSECURITY_ATTRIBUTES lpSecAttr, LPDWORD lpdwDisposition)
  1271. {
  1272. ATLASSERT(hKeyParent != NULL);
  1273. DWORD dw;
  1274. HKEY hKey = NULL;
  1275. LONG lRes = RegCreateKeyEx(hKeyParent, lpszKeyName, 0,
  1276. lpszClass, dwOptions, samDesired, lpSecAttr, &hKey, &dw);
  1277. if (lpdwDisposition != NULL)
  1278. *lpdwDisposition = dw;
  1279. if (lRes == ERROR_SUCCESS)
  1280. {
  1281. lRes = Close();
  1282. m_hKey = hKey;
  1283. }
  1284. return lRes;
  1285. }
  1286. inline LONG CRegKey::Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired)
  1287. {
  1288. ATLASSERT(hKeyParent != NULL);
  1289. HKEY hKey = NULL;
  1290. LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey);
  1291. if (lRes == ERROR_SUCCESS)
  1292. {
  1293. lRes = Close();
  1294. ATLASSERT(lRes == ERROR_SUCCESS);
  1295. m_hKey = hKey;
  1296. }
  1297. return lRes;
  1298. }
  1299. inline LONG CRegKey::QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw()
  1300. {
  1301. ATLASSERT(m_hKey != NULL);
  1302. return( ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, static_cast< LPBYTE >( pData ), pnBytes) );
  1303. }
  1304. inline LONG CRegKey::QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue)
  1305. {
  1306. LONG lRes;
  1307. ULONG nBytes;
  1308. DWORD dwType;
  1309. ATLASSERT(m_hKey != NULL);
  1310. nBytes = sizeof(DWORD);
  1311. lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(&dwValue),
  1312. &nBytes);
  1313. if (lRes != ERROR_SUCCESS)
  1314. return lRes;
  1315. if (dwType != REG_DWORD)
  1316. return ERROR_INVALID_DATA;
  1317. return ERROR_SUCCESS;
  1318. }
  1319. inline LONG CRegKey::QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars)
  1320. {
  1321. LONG lRes;
  1322. DWORD dwType;
  1323. ULONG nBytes;
  1324. ATLASSERT(m_hKey != NULL);
  1325. ATLASSERT(pnChars != NULL);
  1326. nBytes = (*pnChars)*sizeof(TCHAR);
  1327. *pnChars = 0;
  1328. lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(pszValue),
  1329. &nBytes);
  1330. if (lRes != ERROR_SUCCESS)
  1331. return lRes;
  1332. if (dwType != REG_SZ)
  1333. return ERROR_INVALID_DATA;
  1334. *pnChars = nBytes/sizeof(TCHAR);
  1335. return ERROR_SUCCESS;
  1336. }
  1337. inline LONG CRegKey::SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw()
  1338. {
  1339. ATLASSERT(m_hKey != NULL);
  1340. return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, static_cast<const BYTE*>(pValue), nBytes);
  1341. }
  1342. inline LONG CRegKey::SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue)
  1343. {
  1344. ATLASSERT(m_hKey != NULL);
  1345. return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_DWORD, reinterpret_cast<const BYTE*>(&dwValue), sizeof(DWORD));
  1346. }
  1347. inline LONG CRegKey::SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType)
  1348. {
  1349. ATLASSERT(m_hKey != NULL);
  1350. ATLASSERT(pszValue != NULL);
  1351. ATLASSERT((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ));
  1352. return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, reinterpret_cast<const BYTE*>(pszValue), (lstrlen(pszValue)+1)*sizeof(TCHAR));
  1353. }
  1354. inline LONG CRegKey::SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue)
  1355. {
  1356. LPCTSTR pszTemp;
  1357. ULONG nBytes;
  1358. ULONG nLength;
  1359. ATLASSERT(m_hKey != NULL);
  1360. ATLASSERT(pszValue != NULL);
  1361. // Find the total length (in bytes) of all of the strings, including the
  1362. // terminating '\0' of each string, and the second '\0' that terminates
  1363. // the list.
  1364. nBytes = 0;
  1365. pszTemp = pszValue;
  1366. do
  1367. {
  1368. nLength = lstrlen(pszTemp)+1;
  1369. pszTemp += nLength;
  1370. nBytes += nLength*sizeof(TCHAR);
  1371. } while (nLength != 1);
  1372. return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_MULTI_SZ, reinterpret_cast<const BYTE*>(pszValue),
  1373. nBytes);
  1374. }
  1375. inline LONG CRegKey::RecurseDeleteKey(LPCTSTR lpszKey)
  1376. {
  1377. CRegKey key;
  1378. LONG lRes = key.Open(m_hKey, lpszKey, KEY_READ | KEY_WRITE);
  1379. if (lRes != ERROR_SUCCESS)
  1380. {
  1381. return lRes;
  1382. }
  1383. FILETIME time;
  1384. DWORD dwSize = 256;
  1385. TCHAR szBuffer[256];
  1386. while (RegEnumKeyEx(key.m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL,
  1387. &time)==ERROR_SUCCESS)
  1388. {
  1389. lRes = key.RecurseDeleteKey(szBuffer);
  1390. if (lRes != ERROR_SUCCESS)
  1391. return lRes;
  1392. dwSize = 256;
  1393. }
  1394. key.Close();
  1395. return DeleteSubKey(lpszKey);
  1396. }
  1397. #ifdef _ATL_STATIC_REGISTRY
  1398. }; //namespace ATL
  1399. #include <statreg.h>
  1400. namespace ATL
  1401. {
  1402. // Statically linking to Registry Ponent
  1403. inline HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister,
  1404. struct _ATL_REGMAP_ENTRY* pMapEntries /*= NULL*/) throw()
  1405. {
  1406. CRegObject ro;
  1407. if (pMapEntries != NULL)
  1408. {
  1409. while (pMapEntries->szKey != NULL)
  1410. {
  1411. ATLASSERT(NULL != pMapEntries->szData);
  1412. ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData);
  1413. pMapEntries++;
  1414. }
  1415. }
  1416. HRESULT hr = AddCommonRGSReplacements(&ro);
  1417. if (FAILED(hr))
  1418. return hr;
  1419. USES_CONVERSION;
  1420. TCHAR szModule[_MAX_PATH];
  1421. GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, _MAX_PATH);
  1422. szModule[_MAX_PATH - 1] = TEXT('\0');
  1423. LPOLESTR pszModule;
  1424. pszModule = szModule;
  1425. OLECHAR pszModuleQuote[_MAX_PATH * 2];
  1426. EscapeSingleQuote(pszModuleQuote, pszModule);
  1427. ro.AddReplacement(OLESTR("Module"), pszModuleQuote);
  1428. LPCOLESTR szType = OLESTR("REGISTRY");
  1429. hr = (bRegister) ? ro.ResourceRegisterSz(pszModule, lpszRes, szType) :
  1430. ro.ResourceUnregisterSz(pszModule, lpszRes, szType);
  1431. return hr;
  1432. }
  1433. inline HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister,
  1434. struct _ATL_REGMAP_ENTRY* pMapEntries /*= NULL*/) throw()
  1435. {
  1436. CRegObject ro;
  1437. if (pMapEntries != NULL)
  1438. {
  1439. while (pMapEntries->szKey != NULL)
  1440. {
  1441. ATLASSERT(NULL != pMapEntries->szData);
  1442. ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData);
  1443. pMapEntries++;
  1444. }
  1445. }
  1446. HRESULT hr = AddCommonRGSReplacements(&ro);
  1447. if (FAILED(hr))
  1448. return hr;
  1449. USES_CONVERSION;
  1450. TCHAR szModule[_MAX_PATH];
  1451. GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, _MAX_PATH);
  1452. szModule[_MAX_PATH - 1] = TEXT('\0');
  1453. LPOLESTR pszModule;
  1454. pszModule = szModule;
  1455. OLECHAR pszModuleQuote[_MAX_PATH * 2];
  1456. EscapeSingleQuote(pszModuleQuote, pszModule);
  1457. ro.AddReplacement(OLESTR("Module"), pszModuleQuote);
  1458. LPCOLESTR szType = OLESTR("REGISTRY");
  1459. hr = (bRegister) ? ro.ResourceRegister(pszModule, nResID, szType) :
  1460. ro.ResourceUnregister(pszModule, nResID, szType);
  1461. return hr;
  1462. }
  1463. #endif //_ATL_STATIC_REGISTRY
  1464. #pragma pack(pop)
  1465. }; //namespace ATL
  1466. #include <atlbase.inl>
  1467. #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
  1468. using namespace ATL;
  1469. #endif //!_ATL_NO_AUTOMATIC_NAMESPACE
  1470. //only suck in definition if static linking
  1471. #ifndef _ATL_DLL_IMPL
  1472. #ifndef _ATL_DLL
  1473. #define _ATLBASE_IMPL
  1474. #endif
  1475. #endif
  1476. #ifdef _ATL_ATTRIBUTES
  1477. #include <atlplus.h>
  1478. #endif
  1479. //All exports go here
  1480. #ifdef _ATLBASE_IMPL
  1481. namespace ATL
  1482. {
  1483. /////////////////////////////////////////////////////////////////////////////
  1484. // statics
  1485. static UINT WINAPI AtlGetDirLen(LPCOLESTR lpszPathName)
  1486. {
  1487. ATLASSERT(lpszPathName != NULL);
  1488. // always capture the complete file name including extension (if present)
  1489. LPCOLESTR lpszTemp = lpszPathName;
  1490. for (LPCOLESTR lpsz = lpszPathName; *lpsz != NULL; )
  1491. {
  1492. LPCOLESTR lp = CharNextW(lpsz);
  1493. // remember last directory/drive separator
  1494. if (*lpsz == OLESTR('\\') || *lpsz == OLESTR('/') || *lpsz == OLESTR(':'))
  1495. lpszTemp = lp;
  1496. lpsz = lp;
  1497. }
  1498. return UINT( lpszTemp-lpszPathName );
  1499. }
  1500. /////////////////////////////////////////////////////////////////////////////
  1501. // QI support
  1502. ATLINLINE ATLAPI AtlInternalQueryInterface(void* pThis,
  1503. const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
  1504. {
  1505. ATLASSERT(pThis != NULL);
  1506. // First entry in the com map should be a simple map entry
  1507. ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY);
  1508. if (ppvObject == NULL)
  1509. return E_POINTER;
  1510. *ppvObject = NULL;
  1511. if (InlineIsEqualUnknown(iid)) // use first interface
  1512. {
  1513. IUnknown* pUnk = (IUnknown*)((INT_PTR)pThis+pEntries->dw);
  1514. pUnk->AddRef();
  1515. *ppvObject = pUnk;
  1516. return S_OK;
  1517. }
  1518. while (pEntries->pFunc != NULL)
  1519. {
  1520. BOOL bBlind = (pEntries->piid == NULL);
  1521. if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid))
  1522. {
  1523. if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset
  1524. {
  1525. ATLASSERT(!bBlind);
  1526. IUnknown* pUnk = (IUnknown*)((INT_PTR)pThis+pEntries->dw);
  1527. pUnk->AddRef();
  1528. *ppvObject = pUnk;
  1529. return S_OK;
  1530. }
  1531. else //actual function call
  1532. {
  1533. HRESULT hRes = pEntries->pFunc(pThis,
  1534. iid, ppvObject, pEntries->dw);
  1535. if (hRes == S_OK || (!bBlind && FAILED(hRes)))
  1536. return hRes;
  1537. }
  1538. }
  1539. pEntries++;
  1540. }
  1541. return E_NOINTERFACE;
  1542. }
  1543. ATLINLINE ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid)
  1544. {
  1545. IUnknown* pTemp = *pp;
  1546. *pp = NULL;
  1547. if (lp != NULL)
  1548. lp->QueryInterface(riid, (void**)pp);
  1549. if (pTemp)
  1550. pTemp->Release();
  1551. return *pp;
  1552. }
  1553. /////////////////////////////////////////////////////////////////////////////
  1554. // IDispatch Error handling
  1555. ATLINLINE ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  1556. LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst)
  1557. {
  1558. USES_CONVERSION;
  1559. TCHAR szDesc[1024];
  1560. szDesc[0] = NULL;
  1561. // For a valid HRESULT the id should be in the range [0x0200, 0xffff]
  1562. if (IS_INTRESOURCE(lpszDesc)) //id
  1563. {
  1564. UINT nID = LOWORD((DWORD_PTR)lpszDesc);
  1565. ATLASSERT((nID >= 0x0200 && nID <= 0xffff) || hRes != 0);
  1566. if (LoadString(hInst, nID, szDesc, 1024) == 0)
  1567. {
  1568. ATLASSERT(FALSE);
  1569. lstrcpy(szDesc, _T("Unknown Error"));
  1570. }
  1571. lpszDesc = szDesc;
  1572. if (hRes == 0)
  1573. hRes = MAKE_HRESULT(3, FACILITY_ITF, nID);
  1574. }
  1575. CComPtr<ICreateErrorInfo> pICEI;
  1576. if (SUCCEEDED(CreateErrorInfo(&pICEI)))
  1577. {
  1578. CComPtr<IErrorInfo> pErrorInfo;
  1579. pICEI->SetGUID(iid);
  1580. LPOLESTR lpsz;
  1581. ProgIDFromCLSID(clsid, &lpsz);
  1582. if (lpsz != NULL)
  1583. pICEI->SetSource(lpsz);
  1584. if (dwHelpID != 0 && lpszHelpFile != NULL)
  1585. {
  1586. pICEI->SetHelpContext(dwHelpID);
  1587. pICEI->SetHelpFile(const_cast<LPOLESTR>(lpszHelpFile));
  1588. }
  1589. CoTaskMemFree(lpsz);
  1590. pICEI->SetDescription((LPOLESTR)lpszDesc);
  1591. if (SUCCEEDED(pICEI->QueryInterface(__uuidof(IErrorInfo), (void**)&pErrorInfo)))
  1592. SetErrorInfo(0, pErrorInfo);
  1593. }
  1594. return (hRes == 0) ? DISP_E_EXCEPTION : hRes;
  1595. }
  1596. /////////////////////////////////////////////////////////////////////////////
  1597. // Module
  1598. //Although these functions are big, they are only used once in a module
  1599. //so we should make them inline.
  1600. ATLINLINE ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  1601. {
  1602. ATLASSERT(pComModule != NULL);
  1603. if (pComModule == NULL)
  1604. return E_INVALIDARG;
  1605. #ifndef _ATL_OLEDB_CONFORMANCE_TESTS
  1606. ATLASSERT(ppv != NULL);
  1607. #endif
  1608. if (ppv == NULL)
  1609. return E_POINTER;
  1610. *ppv = NULL;
  1611. HRESULT hr = S_OK;
  1612. for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++)
  1613. {
  1614. if (*ppEntry != NULL)
  1615. {
  1616. _ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
  1617. if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid))
  1618. {
  1619. if (pEntry->pCF == NULL)
  1620. {
  1621. CComCritSecLock<CComCriticalSection> lock(pComModule->m_csObjMap, false);
  1622. hr = lock.Lock();
  1623. if (FAILED(hr))
  1624. {
  1625. ATLASSERT(0);
  1626. break;
  1627. }
  1628. if (pEntry->pCF == NULL)
  1629. hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF);
  1630. }
  1631. if (pEntry->pCF != NULL)
  1632. hr = pEntry->pCF->QueryInterface(riid, ppv);
  1633. break;
  1634. }
  1635. }
  1636. }
  1637. if (*ppv == NULL && hr == S_OK)
  1638. hr = CLASS_E_CLASSNOTAVAILABLE;
  1639. return hr;
  1640. }
  1641. ATLINLINE ATLAPI AtlModuleAddTermFunc(_ATL_MODULE* pModule, _ATL_TERMFUNC* pFunc, DWORD_PTR dw)
  1642. {
  1643. HRESULT hr = S_OK;
  1644. _ATL_TERMFUNC_ELEM* pNew = NULL;
  1645. ATLTRY(pNew = new _ATL_TERMFUNC_ELEM);
  1646. if (pNew == NULL)
  1647. hr = E_OUTOFMEMORY;
  1648. else
  1649. {
  1650. pNew->pFunc = pFunc;
  1651. pNew->dw = dw;
  1652. CComCritSecLock<CComCriticalSection> lock(pModule->m_csStaticDataInitAndTypeInfo, false);
  1653. hr = lock.Lock();
  1654. if (SUCCEEDED(hr))
  1655. {
  1656. pNew->pNext = pModule->m_pTermFuncs;
  1657. pModule->m_pTermFuncs = pNew;
  1658. }
  1659. else
  1660. {
  1661. delete pNew;
  1662. ATLASSERT(0);
  1663. }
  1664. }
  1665. return hr;
  1666. }
  1667. ATLINLINE ATLAPI_(void) AtlCallTermFunc(_ATL_MODULE* pModule)
  1668. {
  1669. _ATL_TERMFUNC_ELEM* pElem = pModule->m_pTermFuncs;
  1670. _ATL_TERMFUNC_ELEM* pNext = NULL;
  1671. while (pElem != NULL)
  1672. {
  1673. pElem->pFunc(pElem->dw);
  1674. pNext = pElem->pNext;
  1675. delete pElem;
  1676. pElem = pNext;
  1677. }
  1678. pModule->m_pTermFuncs = NULL;
  1679. }
  1680. ATLINLINE ATLAPI AtlRegisterClassCategoriesHelper( REFCLSID clsid,
  1681. const struct _ATL_CATMAP_ENTRY* pCatMap, BOOL bRegister )
  1682. {
  1683. CComPtr< ICatRegister > pCatRegister;
  1684. HRESULT hResult;
  1685. const struct _ATL_CATMAP_ENTRY* pEntry;
  1686. CATID catid;
  1687. if( pCatMap == NULL )
  1688. {
  1689. return( S_OK );
  1690. }
  1691. if (InlineIsEqualGUID(clsid, GUID_NULL))
  1692. {
  1693. ATLASSERT(0 && _T("Use OBJECT_ENTRY_NON_CREATEABLE_EX macro if you want to register class categories for non creatable objects."));
  1694. return S_OK;
  1695. }
  1696. hResult = CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL,
  1697. CLSCTX_INPROC_SERVER, __uuidof(ICatRegister), (void**)&pCatRegister );
  1698. if( FAILED( hResult ) )
  1699. {
  1700. // Since not all systems have the category manager installed, we'll allow
  1701. // the registration to succeed even though we didn't register our
  1702. // categories. If you really want to register categories on a system
  1703. // without the category manager, you can either manually add the
  1704. // appropriate entries to your registry script (.rgs), or you can
  1705. // redistribute comcat.dll.
  1706. return( S_OK );
  1707. }
  1708. hResult = S_OK;
  1709. pEntry = pCatMap;
  1710. while( pEntry->iType != _ATL_CATMAP_ENTRY_END )
  1711. {
  1712. catid = *pEntry->pcatid;
  1713. if( bRegister )
  1714. {
  1715. if( pEntry->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED )
  1716. {
  1717. hResult = pCatRegister->RegisterClassImplCategories( clsid, 1,
  1718. &catid );
  1719. }
  1720. else
  1721. {
  1722. ATLASSERT( pEntry->iType == _ATL_CATMAP_ENTRY_REQUIRED );
  1723. hResult = pCatRegister->RegisterClassReqCategories( clsid, 1,
  1724. &catid );
  1725. }
  1726. if( FAILED( hResult ) )
  1727. {
  1728. return( hResult );
  1729. }
  1730. }
  1731. else
  1732. {
  1733. if( pEntry->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED )
  1734. {
  1735. pCatRegister->UnRegisterClassImplCategories( clsid, 1, &catid );
  1736. }
  1737. else
  1738. {
  1739. ATLASSERT( pEntry->iType == _ATL_CATMAP_ENTRY_REQUIRED );
  1740. pCatRegister->UnRegisterClassReqCategories( clsid, 1, &catid );
  1741. }
  1742. }
  1743. pEntry++;
  1744. }
  1745. // When unregistering remove "Implemented Categories" and "Required Categories" subkeys if they are empty.
  1746. if (!bRegister)
  1747. {
  1748. OLECHAR szGUID[64];
  1749. ::StringFromGUID2(clsid, szGUID, 64);
  1750. USES_CONVERSION;
  1751. TCHAR* pszGUID = szGUID;
  1752. if (pszGUID != NULL)
  1753. {
  1754. TCHAR szKey[128];
  1755. lstrcpy(szKey, _T("CLSID\\"));
  1756. lstrcat(szKey, pszGUID);
  1757. lstrcat(szKey, _T("\\Required Categories"));
  1758. HKEY key;
  1759. DWORD cbSubKeys = 0;
  1760. LRESULT lRes = RegOpenKeyEx(HKEY_CLASSES_ROOT,
  1761. szKey,
  1762. 0,
  1763. KEY_READ,
  1764. &key);
  1765. if (lRes == ERROR_SUCCESS)
  1766. {
  1767. lRes = RegQueryInfoKey(key, NULL, NULL, NULL, &cbSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  1768. RegCloseKey(key);
  1769. if (lRes == ERROR_SUCCESS && cbSubKeys == 0)
  1770. {
  1771. RegDeleteKey(HKEY_CLASSES_ROOT, szKey);
  1772. }
  1773. }
  1774. lstrcpy(szKey, _T("CLSID\\"));
  1775. lstrcat(szKey, pszGUID);
  1776. lstrcat(szKey, _T("\\Implemented Categories"));
  1777. lRes = RegOpenKeyEx(HKEY_CLASSES_ROOT,
  1778. szKey,
  1779. 0,
  1780. KEY_READ,
  1781. &key);
  1782. if (lRes == ERROR_SUCCESS)
  1783. {
  1784. lRes = RegQueryInfoKey(key, NULL, NULL, NULL, &cbSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  1785. RegCloseKey(key);
  1786. if (lRes == ERROR_SUCCESS && cbSubKeys == 0)
  1787. {
  1788. RegDeleteKey(HKEY_CLASSES_ROOT, szKey);
  1789. }
  1790. }
  1791. }
  1792. }
  1793. return( S_OK );
  1794. }
  1795. // AtlComModuleRegisterServer walks the ATL Autogenerated Object Map and registers each object in the map
  1796. // If pCLSID is not NULL then only the object referred to by pCLSID is registered (The default case)
  1797. // otherwise all the objects are registered
  1798. ATLINLINE ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID)
  1799. {
  1800. ATLASSERT(pComModule != NULL);
  1801. if (pComModule == NULL)
  1802. return E_INVALIDARG;
  1803. ATLASSERT(pComModule->m_hInstTypeLib != NULL);
  1804. HRESULT hr = S_OK;
  1805. for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++)
  1806. {
  1807. if (*ppEntry != NULL)
  1808. {
  1809. _ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
  1810. if (pCLSID != NULL)
  1811. {
  1812. if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
  1813. continue;
  1814. }
  1815. hr = pEntry->pfnUpdateRegistry(TRUE);
  1816. if (FAILED(hr))
  1817. break;
  1818. hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid,
  1819. pEntry->pfnGetCategoryMap(), TRUE );
  1820. if (FAILED(hr))
  1821. break;
  1822. }
  1823. }
  1824. if (SUCCEEDED(hr) && bRegTypeLib)
  1825. hr = AtlRegisterTypeLib(pComModule->m_hInstTypeLib, 0);
  1826. return hr;
  1827. }
  1828. // AtlComUnregisterServer walks the ATL Object Map and unregisters each object in the map
  1829. // If pCLSID is not NULL then only the object referred to by pCLSID is unregistered (The default case)
  1830. // otherwise all the objects are unregistered.
  1831. ATLINLINE ATLAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE* pComModule, BOOL bUnRegTypeLib, const CLSID* pCLSID)
  1832. {
  1833. ATLASSERT(pComModule != NULL);
  1834. if (pComModule == NULL)
  1835. return E_INVALIDARG;
  1836. HRESULT hr = S_OK;
  1837. for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++)
  1838. {
  1839. if (*ppEntry != NULL)
  1840. {
  1841. _ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
  1842. if (pCLSID != NULL)
  1843. {
  1844. if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
  1845. continue;
  1846. }
  1847. hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, pEntry->pfnGetCategoryMap(), FALSE );
  1848. if (FAILED(hr))
  1849. break;
  1850. hr = pEntry->pfnUpdateRegistry(FALSE); //unregister
  1851. if (FAILED(hr))
  1852. break;
  1853. }
  1854. }
  1855. if (SUCCEEDED(hr) && bUnRegTypeLib)
  1856. hr = AtlUnRegisterTypeLib(pComModule->m_hInstTypeLib, 0);
  1857. return hr;
  1858. }
  1859. /////////////////////////////////////////////////////////////////////////////
  1860. // TypeLib Support
  1861. ATLINLINE ATLAPI AtlLoadTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib)
  1862. {
  1863. ATLASSERT(pbstrPath != NULL && ppTypeLib != NULL);
  1864. if (pbstrPath == NULL || ppTypeLib == NULL)
  1865. return E_POINTER;
  1866. *pbstrPath = NULL;
  1867. *ppTypeLib = NULL;
  1868. USES_CONVERSION;
  1869. ATLASSERT(hInstTypeLib != NULL);
  1870. TCHAR szModule[_MAX_PATH+10];
  1871. ATLVERIFY( GetModuleFileName(hInstTypeLib, szModule, _MAX_PATH) != 0 );
  1872. // get the extension pointer in case of fail
  1873. LPTSTR lpszExt = NULL;
  1874. lpszExt = PathFindExtension(szModule);
  1875. if (lpszIndex != NULL)
  1876. lstrcat(szModule, lpszIndex);
  1877. LPOLESTR lpszModule = szModule;
  1878. HRESULT hr = LoadTypeLib(lpszModule, ppTypeLib);
  1879. if (!SUCCEEDED(hr))
  1880. {
  1881. // typelib not in module, try <module>.tlb instead
  1882. lstrcpy(lpszExt, _T(".tlb"));
  1883. lpszModule = szModule;
  1884. hr = LoadTypeLib(lpszModule, ppTypeLib);
  1885. }
  1886. if (SUCCEEDED(hr))
  1887. {
  1888. *pbstrPath = ::SysAllocString(lpszModule);
  1889. if (*pbstrPath == NULL)
  1890. hr = E_OUTOFMEMORY;
  1891. }
  1892. return hr;
  1893. }
  1894. ATLINLINE ATLAPI AtlUnRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex)
  1895. {
  1896. CComBSTR bstrPath;
  1897. CComPtr<ITypeLib> pTypeLib;
  1898. HRESULT hr = AtlLoadTypeLib(hInstTypeLib, lpszIndex, &bstrPath, &pTypeLib);
  1899. if (SUCCEEDED(hr))
  1900. {
  1901. TLIBATTR* ptla;
  1902. hr = pTypeLib->GetLibAttr(&ptla);
  1903. if (SUCCEEDED(hr))
  1904. {
  1905. hr = UnRegisterTypeLib(ptla->guid, ptla->wMajorVerNum, ptla->wMinorVerNum, ptla->lcid, ptla->syskind);
  1906. pTypeLib->ReleaseTLibAttr(ptla);
  1907. }
  1908. }
  1909. return hr;
  1910. }
  1911. ATLINLINE ATLAPI AtlRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex)
  1912. {
  1913. CComBSTR bstrPath;
  1914. CComPtr<ITypeLib> pTypeLib;
  1915. HRESULT hr = AtlLoadTypeLib(hInstTypeLib, lpszIndex, &bstrPath, &pTypeLib);
  1916. if (SUCCEEDED(hr))
  1917. {
  1918. OLECHAR szDir[_MAX_PATH];
  1919. lstrcpyW(szDir, bstrPath);
  1920. // If index is specified remove it from the path
  1921. if (lpszIndex != NULL)
  1922. {
  1923. size_t nLenPath = lstrlenW(szDir);
  1924. size_t nLenIndex = lstrlenW(lpszIndex);
  1925. if (memcmp(szDir + nLenPath - nLenIndex, lpszIndex, nLenIndex) == 0)
  1926. szDir[nLenPath - nLenIndex] = 0;
  1927. }
  1928. szDir[AtlGetDirLen(szDir)] = 0;
  1929. hr = ::RegisterTypeLib(pTypeLib, bstrPath, szDir);
  1930. }
  1931. return hr;
  1932. }
  1933. }; //namespace ATL
  1934. #endif // _ATLBASE_IMPL
  1935. #pragma warning( pop )
  1936. #ifdef _ATL_ALL_WARNINGS
  1937. #pragma warning( pop )
  1938. #endif
  1939. /////////////////////////////////////////////////////////////////////////////
  1940. #endif // __ATLBASE_H__