4 * Copyright 2009 Andrew Hill <ash77@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "atlcomcli.h"
28 #include "atlexcept.h"
33 // It is common to use this in ATL constructors. They only store this for later use, so the usage is safe.
34 #pragma warning(disable:4355)
41 #ifdef _ATL_DISABLE_NO_VTABLE
44 #define ATL_NO_VTABLE __declspec(novtable)
47 #ifndef ATL_DEPRECATED
48 #define ATL_DEPRECATED __declspec(deprecated)
58 __declspec(selectany
) CAtlModule
*_pAtlModule
= NULL
;
59 __declspec(selectany
) CComModule
*_pModule
= NULL
;
62 struct _ATL_CATMAP_ENTRY
68 #define _ATL_CATMAP_ENTRY_END 0
69 #define _ATL_CATMAP_ENTRY_IMPLEMENTED 1
70 #define _ATL_CATMAP_ENTRY_REQUIRED 2
73 typedef HRESULT (WINAPI _ATL_CREATORFUNC
)(void *pv
, REFIID riid
, LPVOID
*ppv
);
74 typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC
)();
75 typedef const struct _ATL_CATMAP_ENTRY
* (_ATL_CATMAPFUNC
)();
77 struct _ATL_OBJMAP_ENTRY30
80 HRESULT (WINAPI
*pfnUpdateRegistry
)(BOOL bRegister
);
81 _ATL_CREATORFUNC
*pfnGetClassObject
;
82 _ATL_CREATORFUNC
*pfnCreateInstance
;
85 _ATL_DESCRIPTIONFUNC
*pfnGetObjectDescription
;
86 _ATL_CATMAPFUNC
*pfnGetCategoryMap
;
87 void (WINAPI
*pfnObjectMain
)(bool bStarting
);
89 HRESULT WINAPI
RevokeClassObject()
93 return CoRevokeClassObject(dwRegister
);
96 HRESULT WINAPI
RegisterClassObject(DWORD dwClsContext
, DWORD dwFlags
)
102 if (pfnGetClassObject
== NULL
)
105 hResult
= pfnGetClassObject(reinterpret_cast<LPVOID
*>(pfnCreateInstance
), IID_IUnknown
, reinterpret_cast<LPVOID
*>(&p
));
106 if (SUCCEEDED(hResult
))
107 hResult
= CoRegisterClassObject(*pclsid
, p
, dwClsContext
, dwFlags
, &dwRegister
);
116 typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY
;
118 typedef void (__stdcall _ATL_TERMFUNC
)(DWORD_PTR dw
);
120 struct _ATL_TERMFUNC_ELEM
122 _ATL_TERMFUNC
*pFunc
;
124 _ATL_TERMFUNC_ELEM
*pNext
;
131 _ATL_TERMFUNC_ELEM
*m_pTermFuncs
;
132 CComCriticalSection m_csStaticDataInitAndTypeInfo
;
134 typedef _ATL_MODULE70 _ATL_MODULE
;
136 typedef HRESULT (WINAPI _ATL_CREATORARGFUNC
)(void *pv
, REFIID riid
, LPVOID
*ppv
, DWORD_PTR dw
);
138 #define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC *)1)
140 struct _ATL_INTMAP_ENTRY
144 _ATL_CREATORARGFUNC
*pFunc
;
147 struct _AtlCreateWndData
151 _AtlCreateWndData
*m_pNext
;
154 struct _ATL_COM_MODULE70
157 HINSTANCE m_hInstTypeLib
;
158 _ATL_OBJMAP_ENTRY
**m_ppAutoObjMapFirst
;
159 _ATL_OBJMAP_ENTRY
**m_ppAutoObjMapLast
;
160 CComCriticalSection m_csObjMap
;
162 typedef _ATL_COM_MODULE70 _ATL_COM_MODULE
;
164 struct _ATL_WIN_MODULE70
167 CComCriticalSection m_csWindowCreate
;
168 _AtlCreateWndData
*m_pCreateWndList
;
170 CSimpleArray
<ATOM
> m_rgWindowClassAtoms
;
173 typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE
;
175 struct _ATL_REGMAP_ENTRY
181 HRESULT WINAPI
AtlWinModuleInit(_ATL_WIN_MODULE
*pWinModule
);
182 HRESULT WINAPI
AtlWinModuleTerm(_ATL_WIN_MODULE
*pWinModule
, HINSTANCE hInst
);
183 HRESULT WINAPI
AtlInternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
);
184 void WINAPI
AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE
*pWinModule
, _AtlCreateWndData
*pData
, void *pObject
);
185 void *WINAPI
AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE
*pWinModule
);
186 HRESULT WINAPI
AtlComModuleGetClassObject(_ATL_COM_MODULE
*pComModule
, REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
);
188 HRESULT WINAPI
AtlComModuleRegisterServer(_ATL_COM_MODULE
*mod
, BOOL bRegTypeLib
, const CLSID
*clsid
);
189 HRESULT WINAPI
AtlComModuleUnregisterServer(_ATL_COM_MODULE
*mod
, BOOL bRegTypeLib
, const CLSID
*clsid
);
191 HRESULT WINAPI
AtlComModuleRegisterClassObjects(_ATL_COM_MODULE
*module
, DWORD context
, DWORD flags
);
192 HRESULT WINAPI
AtlComModuleRevokeClassObjects(_ATL_COM_MODULE
*module
);
195 template<class TLock
>
196 class CComCritSecLock
202 CComCritSecLock(TLock
&cs
, bool bInitialLock
= true) : m_cs(cs
)
227 ATLASSERT(!m_bLocked
);
228 hResult
= m_cs
.Lock();
240 ATLASSERT(m_bLocked
);
241 hResult
= m_cs
.Unlock();
262 CHandle(_Inout_ CHandle
& handle
) :
265 Attach(handle
.Detach());
268 explicit CHandle(_In_ HANDLE handle
) :
281 CHandle
& operator=(_Inout_ CHandle
& handle
)
289 Attach(handle
.Detach());
295 operator HANDLE() const
300 void Attach(_In_ HANDLE handle
)
302 ATLASSERT(m_handle
== NULL
);
308 HANDLE handle
= m_handle
;
317 ::CloseHandle(m_handle
);
324 inline BOOL WINAPI
InlineIsEqualUnknown(REFGUID rguid1
)
327 ((unsigned long *)&rguid1
)[0] == 0 &&
328 ((unsigned long *)&rguid1
)[1] == 0 &&
329 ((unsigned long *)&rguid1
)[2] == 0x000000C0 &&
330 ((unsigned long *)&rguid1
)[3] == 0x46000000);
333 class CComMultiThreadModelNoCS
336 typedef CComFakeCriticalSection AutoCriticalSection
;
337 typedef CComFakeCriticalSection CriticalSection
;
338 typedef CComMultiThreadModelNoCS ThreadModelNoCS
;
339 typedef CComFakeCriticalSection AutoDeleteCriticalSection
;
341 static ULONG WINAPI
Increment(LPLONG p
)
343 return InterlockedIncrement(p
);
346 static ULONG WINAPI
Decrement(LPLONG p
)
348 return InterlockedDecrement(p
);
352 class CComMultiThreadModel
355 typedef CComAutoCriticalSection AutoCriticalSection
;
356 typedef CComCriticalSection CriticalSection
;
357 typedef CComMultiThreadModelNoCS ThreadModelNoCS
;
358 typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection
;
360 static ULONG WINAPI
Increment(LPLONG p
)
362 return InterlockedIncrement(p
);
365 static ULONG WINAPI
Decrement(LPLONG p
)
367 return InterlockedDecrement(p
);
371 class CComSingleThreadModel
374 typedef CComFakeCriticalSection AutoCriticalSection
;
375 typedef CComFakeCriticalSection CriticalSection
;
376 typedef CComSingleThreadModel ThreadModelNoCS
;
377 typedef CComFakeCriticalSection AutoDeleteCriticalSection
;
379 static ULONG WINAPI
Increment(LPLONG p
)
384 static ULONG WINAPI
Decrement(LPLONG p
)
390 #if defined(_ATL_FREE_THREADED)
392 typedef CComMultiThreadModel CComObjectThreadModel
;
393 typedef CComMultiThreadModel CComGlobalsThreadModel
;
395 #elif defined(_ATL_APARTMENT_THREADED)
397 typedef CComSingleThreadModel CComObjectThreadModel
;
398 typedef CComMultiThreadModel CComGlobalsThreadModel
;
400 #elif defined(_ATL_SINGLE_THREADED)
402 typedef CComSingleThreadModel CComObjectThreadModel
;
403 typedef CComSingleThreadModel CComGlobalsThreadModel
;
406 #error No threading model
409 class CAtlModule
: public _ATL_MODULE
416 ATLASSERT(_pAtlModule
== NULL
);
418 cbSize
= sizeof(_ATL_MODULE
);
422 virtual LONG
GetLockCount()
429 return CComGlobalsThreadModel::Increment(&m_nLockCnt
);
432 virtual LONG
Unlock()
434 return CComGlobalsThreadModel::Decrement(&m_nLockCnt
);
437 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
* /*pRegistrar*/) = 0;
439 HRESULT WINAPI
UpdateRegistryFromResource(LPCTSTR lpszRes
, BOOL bRegister
, struct _ATL_REGMAP_ENTRY
*pMapEntries
= NULL
)
441 CRegObject registrar
;
442 WCHAR modulePath
[MAX_PATH
];
446 hResult
= CommonInitRegistrar(registrar
, modulePath
, sizeof(modulePath
) / sizeof(modulePath
[0]), pMapEntries
);
452 /* FIXME: this is a bit of a hack, need to re-evaluate */
453 WCHAR resid
[MAX_PATH
];
454 MultiByteToWideChar(CP_ACP
, 0, lpszRes
, -1, resid
, MAX_PATH
);
457 if (bRegister
!= FALSE
)
458 hResult
= registrar
.ResourceRegisterSz(modulePath
, lpwszRes
, L
"REGISTRY");
460 hResult
= registrar
.ResourceUnregisterSz(modulePath
, lpwszRes
, L
"REGISTRY");
465 HRESULT WINAPI
UpdateRegistryFromResource(UINT nResID
, BOOL bRegister
, struct _ATL_REGMAP_ENTRY
*pMapEntries
= NULL
)
467 CRegObject registrar
;
468 WCHAR modulePath
[MAX_PATH
];
471 hResult
= CommonInitRegistrar(registrar
, modulePath
, sizeof(modulePath
) / sizeof(modulePath
[0]), pMapEntries
);
475 if (bRegister
!= FALSE
)
476 hResult
= registrar
.ResourceRegister(modulePath
, nResID
, L
"REGISTRY");
478 hResult
= registrar
.ResourceUnregister(modulePath
, nResID
, L
"REGISTRY");
484 HRESULT
CommonInitRegistrar(CRegObject
®istrar
, WCHAR
*modulePath
, DWORD modulePathCount
, struct _ATL_REGMAP_ENTRY
*pMapEntries
)
490 hInstance
= _AtlBaseModule
.GetModuleInstance();
491 dwFLen
= GetModuleFileNameW(hInstance
, modulePath
, modulePathCount
);
492 if (dwFLen
== modulePathCount
)
493 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
494 else if (dwFLen
== 0)
495 return HRESULT_FROM_WIN32(GetLastError());
497 if (pMapEntries
!= NULL
)
499 while (pMapEntries
->szKey
!= NULL
)
501 ATLASSERT(pMapEntries
->szData
!= NULL
);
502 hResult
= registrar
.AddReplacement(pMapEntries
->szKey
, pMapEntries
->szData
);
509 hResult
= AddCommonRGSReplacements(®istrar
);
513 hResult
= registrar
.AddReplacement(L
"Module", modulePath
);
517 hResult
= registrar
.AddReplacement(L
"Module_Raw", modulePath
);
525 __declspec(selectany
) GUID
CAtlModule::m_libid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
528 class CAtlModuleT
: public CAtlModule
532 HRESULT
RegisterServer(BOOL bRegTypeLib
= FALSE
, const CLSID
*pCLSID
= NULL
);
533 HRESULT
UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
= NULL
);
536 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
*pRegistrar
)
538 return pRegistrar
->AddReplacement(L
"APPID", T::GetAppId());
541 static LPCOLESTR
GetAppId()
547 class CAtlComModule
: public _ATL_COM_MODULE
552 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
, (LPCWSTR
)this, &m_hInstTypeLib
);
553 m_ppAutoObjMapFirst
= NULL
;
554 m_ppAutoObjMapLast
= NULL
;
555 if (FAILED(m_csObjMap
.Init()))
558 CAtlBaseModule::m_bInitFailed
= true;
561 cbSize
= sizeof(_ATL_COM_MODULE
);
569 HRESULT
RegisterServer(BOOL bRegTypeLib
= FALSE
, const CLSID
*pCLSID
= NULL
)
571 return AtlComModuleRegisterServer(this, bRegTypeLib
, pCLSID
);
574 HRESULT
UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
= NULL
)
576 return AtlComModuleUnregisterServer(this, bUnRegTypeLib
, pCLSID
);
584 ATLASSERT(m_ppAutoObjMapFirst
== NULL
);
585 ATLASSERT(m_ppAutoObjMapLast
== NULL
);
592 __declspec(selectany
) CAtlComModule _AtlComModule
;
596 HRESULT CAtlModuleT
<T
>::RegisterServer(BOOL bRegTypeLib
, const CLSID
*pCLSID
)
598 return _AtlComModule
.RegisterServer(bRegTypeLib
, pCLSID
);
602 HRESULT CAtlModuleT
<T
>::UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
)
604 return _AtlComModule
.UnregisterServer(bUnRegTypeLib
, pCLSID
);
608 class CAtlDllModuleT
: public CAtlModuleT
<T
>
615 HRESULT
DllCanUnloadNow()
619 pThis
= static_cast<T
*>(this);
620 if (pThis
->GetLockCount() == 0)
625 HRESULT
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
629 pThis
= static_cast<T
*>(this);
630 return pThis
->GetClassObject(rclsid
, riid
, ppv
);
633 HRESULT
DllRegisterServer(BOOL bRegTypeLib
= TRUE
)
638 pThis
= static_cast<T
*>(this);
639 hResult
= pThis
->RegisterServer(bRegTypeLib
);
643 HRESULT
DllUnregisterServer(BOOL bUnRegTypeLib
= TRUE
)
648 pThis
= static_cast<T
*>(this);
649 hResult
= pThis
->UnregisterServer(bUnRegTypeLib
);
653 HRESULT
GetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
655 return AtlComModuleGetClassObject(&_AtlComModule
, rclsid
, riid
, ppv
);
661 class CAtlExeModuleT
: public CAtlModuleT
<T
>
664 DWORD m_dwMainThreadID
;
667 //bool m_bDelayShutdown;
670 :m_dwMainThreadID(::GetCurrentThreadId())
678 int WinMain(int nShowCmd
)
680 HRESULT hr
= T::InitializeCom();
684 T
* pThis
= static_cast<T
*>(this);
686 LPCTSTR lpCommandLine
= GetCommandLine();
687 if (pThis
->ParseCommandLine(lpCommandLine
, &hr
))
689 hr
= pThis
->Run(nShowCmd
);
692 T::UninitializeCom();
697 HRESULT
Run(int nShowCmd
= SW_HIDE
)
701 T
* pThis
= static_cast<T
*>(this);
702 hr
= pThis
->PreMessageLoop(nShowCmd
);
706 pThis
->RunMessageLoop();
707 hr
= pThis
->PostMessageLoop();
715 return CoAddRefServerProcess();
720 LONG lRet
= CoReleaseServerProcess();
723 ::PostThreadMessage(m_dwMainThreadID
, WM_QUIT
, 0, 0);
728 bool ParseCommandLine(LPCTSTR lpCmdLine
, HRESULT
* pnRetCode
)
734 HRESULT
PreMessageLoop(int nShowCmd
)
736 T
* pThis
= static_cast<T
*>(this);
737 return pThis
->RegisterClassObjects(CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
);
740 void RunMessageLoop()
743 while (GetMessage(&msg
, 0, 0, 0) > 0)
745 TranslateMessage(&msg
);
746 DispatchMessage(&msg
);
750 HRESULT
PostMessageLoop()
752 T
* pThis
= static_cast<T
*>(this);
753 return pThis
->RevokeClassObjects();
756 HRESULT
RegisterClassObjects(DWORD dwClsContext
, DWORD dwFlags
)
758 return AtlComModuleRegisterClassObjects(&_AtlComModule
, dwClsContext
, dwFlags
);
761 HRESULT
RevokeClassObjects()
763 return AtlComModuleRevokeClassObjects(&_AtlComModule
);
766 static HRESULT
InitializeCom()
768 return ::CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
771 static void UninitializeCom()
780 class CComModule
: public CAtlModuleT
<CComModule
>
783 _ATL_OBJMAP_ENTRY
*m_pObjMap
;
787 ATLASSERT(_pModule
== NULL
);
789 _pModule
->m_pObjMap
= NULL
;
797 HRESULT
Init(_ATL_OBJMAP_ENTRY
*p
, HINSTANCE
/* h */, const GUID
*plibid
)
799 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
804 if (p
!= reinterpret_cast<_ATL_OBJMAP_ENTRY
*>(-1))
810 while (objectMapEntry
->pclsid
!= NULL
)
812 objectMapEntry
->pfnObjectMain(true);
822 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
824 if (m_pObjMap
!= NULL
)
826 objectMapEntry
= m_pObjMap
;
827 while (objectMapEntry
->pclsid
!= NULL
)
829 if (objectMapEntry
->pCF
!= NULL
)
830 objectMapEntry
->pCF
->Release();
831 objectMapEntry
->pCF
= NULL
;
832 objectMapEntry
->pfnObjectMain(false);
838 HRESULT
GetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
840 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
843 ATLASSERT(ppv
!= NULL
);
848 if (m_pObjMap
!= NULL
)
850 objectMapEntry
= m_pObjMap
;
851 while (objectMapEntry
->pclsid
!= NULL
)
853 if (objectMapEntry
->pfnGetClassObject
!= NULL
&& InlineIsEqualGUID(rclsid
, *objectMapEntry
->pclsid
) != FALSE
)
855 if (objectMapEntry
->pCF
== NULL
)
857 CComCritSecLock
<CComCriticalSection
> lock(_AtlComModule
.m_csObjMap
, true);
859 if (objectMapEntry
->pCF
== NULL
)
860 hResult
= objectMapEntry
->pfnGetClassObject(reinterpret_cast<void *>(objectMapEntry
->pfnCreateInstance
), IID_IUnknown
, reinterpret_cast<LPVOID
*>(&objectMapEntry
->pCF
));
862 if (objectMapEntry
->pCF
!= NULL
)
863 hResult
= objectMapEntry
->pCF
->QueryInterface(riid
, ppv
);
869 if (hResult
== S_OK
&& *ppv
== NULL
)
871 // FIXME: call AtlComModuleGetClassObject
872 hResult
= CLASS_E_CLASSNOTAVAILABLE
;
877 HRESULT
RegisterServer(BOOL bRegTypeLib
= FALSE
, const CLSID
*pCLSID
= NULL
)
879 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
883 objectMapEntry
= m_pObjMap
;
884 if (objectMapEntry
!= NULL
)
886 while (objectMapEntry
->pclsid
!= NULL
)
888 if (pCLSID
== NULL
|| IsEqualGUID(*pCLSID
, *objectMapEntry
->pclsid
) != FALSE
)
890 hResult
= objectMapEntry
->pfnUpdateRegistry(TRUE
);
897 if (SUCCEEDED(hResult
))
898 hResult
= CAtlModuleT
<CComModule
>::RegisterServer(bRegTypeLib
, pCLSID
);
902 HRESULT
UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
= NULL
)
904 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
908 objectMapEntry
= m_pObjMap
;
909 if (objectMapEntry
!= NULL
)
911 while (objectMapEntry
->pclsid
!= NULL
)
913 if (pCLSID
== NULL
|| IsEqualGUID(*pCLSID
, *objectMapEntry
->pclsid
) != FALSE
)
915 hResult
= objectMapEntry
->pfnUpdateRegistry(FALSE
); //unregister
922 if (SUCCEEDED(hResult
))
923 hResult
= CAtlModuleT
<CComModule
>::UnregisterServer(bUnRegTypeLib
, pCLSID
);
928 HRESULT
DllCanUnloadNow()
930 if (GetLockCount() == 0)
935 HRESULT
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
937 return GetClassObject(rclsid
, riid
, ppv
);
940 HRESULT
DllRegisterServer(BOOL bRegTypeLib
= TRUE
)
942 return RegisterServer(bRegTypeLib
);
945 HRESULT
DllUnregisterServer(BOOL bUnRegTypeLib
= TRUE
)
947 return UnregisterServer(bUnRegTypeLib
);
952 class CAtlWinModule
: public _ATL_WIN_MODULE
959 hResult
= AtlWinModuleInit(this);
962 CAtlBaseModule::m_bInitFailed
= true;
974 AtlWinModuleTerm(this, _AtlBaseModule
.GetModuleInstance());
977 void AddCreateWndData(_AtlCreateWndData
*pData
, void *pObject
)
979 AtlWinModuleAddCreateWndData(this, pData
, pObject
);
982 void *ExtractCreateWndData()
984 return AtlWinModuleExtractCreateWndData(this);
988 __declspec(selectany
) CAtlWinModule _AtlWinModule
;
994 static void* Allocate(_In_
size_t size
)
996 return ::CoTaskMemAlloc(size
);
999 static void* Reallocate(_In_opt_
void* ptr
, _In_
size_t size
)
1001 return ::CoTaskMemRealloc(ptr
, size
);
1004 static void Free(_In_opt_
void* ptr
)
1006 ::CoTaskMemFree(ptr
);
1016 CAtlTransactionManager
* m_pTM
;
1026 CRegKey(CRegKey
& key
) throw()
1027 : m_hKey(key
.Detach())
1031 explicit CRegKey(HKEY hKey
) throw()
1038 CRegKey(CAtlTransactionManager
* pTM
) throw()
1048 void Attach(HKEY hKey
) throw()
1053 LONG
Close() throw()
1057 HKEY hKey
= Detach();
1058 return ::RegCloseKey(hKey
);
1060 return ERROR_SUCCESS
;
1063 HKEY
Detach() throw()
1070 LONG
Open(HKEY hKeyParent
, LPCTSTR lpszKeyName
,
1071 REGSAM samDesired
= KEY_READ
| KEY_WRITE
) throw()
1073 ATLASSERT(hKeyParent
);
1074 ATLASSERT(lpszKeyName
);
1077 LONG lRes
= ::RegOpenKeyEx(hKeyParent
, lpszKeyName
, 0, samDesired
, &hKey
);
1078 if (lRes
!= ERROR_SUCCESS
)
1080 samDesired
|= KEY_WOW64_64KEY
;
1081 lRes
= ::RegOpenKeyEx(hKeyParent
, lpszKeyName
, 0, samDesired
, &hKey
);
1083 if (lRes
== ERROR_SUCCESS
)
1091 LONG
Create(HKEY hKeyParent
, LPCTSTR lpszKeyName
,
1092 LPTSTR lpszClass
= REG_NONE
,
1093 DWORD dwOptions
= REG_OPTION_NON_VOLATILE
,
1094 REGSAM samDesired
= KEY_READ
| KEY_WRITE
,
1095 LPSECURITY_ATTRIBUTES lpSecAttr
= NULL
,
1096 LPDWORD lpdwDisposition
= NULL
) throw()
1098 ATLASSERT(hKeyParent
);
1099 ATLASSERT(lpszKeyName
);
1102 LONG lRes
= ::RegCreateKeyEx(hKeyParent
, lpszKeyName
, 0, lpszClass
,
1103 dwOptions
, samDesired
, lpSecAttr
, &hKey
,
1105 if (lRes
!= ERROR_SUCCESS
)
1107 samDesired
|= KEY_WOW64_64KEY
;
1108 lRes
= ::RegCreateKeyEx(hKeyParent
, lpszKeyName
, 0, lpszClass
,
1109 dwOptions
, samDesired
, lpSecAttr
, &hKey
,
1112 if (lRes
== ERROR_SUCCESS
)
1120 LONG
QueryValue(LPCTSTR pszValueName
, DWORD
* pdwType
, void* pData
, ULONG
* pnBytes
) throw()
1123 return ::RegQueryValueEx(m_hKey
, pszValueName
, NULL
, pdwType
, (LPBYTE
)pData
, pnBytes
);
1126 LONG
QueryDWORDValue(LPCTSTR pszValueName
, DWORD
& dwValue
) throw()
1128 ULONG size
= sizeof(DWORD
);
1130 LONG lRet
= QueryValue(pszValueName
, &type
, &dwValue
, &size
);
1132 if (lRet
== ERROR_SUCCESS
&& type
!= REG_DWORD
)
1133 lRet
= ERROR_INVALID_DATA
;
1138 LONG
QueryBinaryValue(LPCTSTR pszValueName
, void* pValue
, ULONG
* pnBytes
) throw()
1141 LONG lRet
= QueryValue(pszValueName
, &type
, pValue
, pnBytes
);
1143 if (lRet
== ERROR_SUCCESS
&& type
!= REG_BINARY
)
1144 lRet
= ERROR_INVALID_DATA
;
1149 LONG
QueryStringValue(LPCTSTR pszValueName
, LPTSTR pszValue
, ULONG
* pnChars
) throw()
1151 ULONG size
= (*pnChars
) * sizeof(TCHAR
);
1153 LONG lRet
= QueryValue(pszValueName
, &type
, pszValue
, &size
);
1155 if (lRet
== ERROR_SUCCESS
&& type
!= REG_SZ
&& type
!= REG_EXPAND_SZ
)
1156 lRet
= ERROR_INVALID_DATA
;
1158 *pnChars
= size
/ sizeof(TCHAR
);
1162 LONG
QueryGUIDValue(LPCTSTR pszValueName
, GUID
& guidValue
) throw()
1164 OLECHAR buf
[40] = {0};
1169 lRet
= QueryStringValue(pszValueName
, buf
, &nChars
);
1171 CHAR bufA
[40] = {0};
1172 lRet
= QueryStringValue(pszValueName
, bufA
, &nChars
);
1173 if (lRet
!= ERROR_SUCCESS
)
1175 if (!::MultiByteToWideChar(CP_THREAD_ACP
, 0, bufA
, -1, buf
, 39))
1176 lRet
= ERROR_INVALID_DATA
;
1178 if (lRet
!= ERROR_SUCCESS
)
1181 if (!SUCCEEDED(::CLSIDFromString(buf
, &guidValue
)))
1182 return ERROR_INVALID_DATA
;
1187 LONG
QueryQWORDValue(LPCTSTR pszValueName
, ULONGLONG
& qwValue
) throw()
1189 ULONG size
= sizeof(ULONGLONG
);
1191 LONG lRet
= QueryValue(pszValueName
, &type
, &qwValue
, &size
);
1193 if (lRet
== ERROR_SUCCESS
&& type
!= REG_QWORD
)
1194 lRet
= ERROR_INVALID_DATA
;
1199 LONG
QueryMultiStringValue(LPCTSTR pszValueName
, LPTSTR pszValue
,
1200 ULONG
* pnChars
) throw()
1202 ULONG size
= (*pnChars
) * sizeof(TCHAR
);
1204 LONG lRet
= QueryValue(pszValueName
, &type
, pszValue
, &size
);
1206 if (lRet
== ERROR_SUCCESS
&& type
!= REG_MULTI_SZ
)
1207 lRet
= ERROR_INVALID_DATA
;
1209 *pnChars
= size
/ sizeof(TCHAR
);
1213 LONG
SetValue(LPCTSTR pszValueName
, DWORD dwType
, const void* pValue
, ULONG nBytes
) throw()
1216 return ::RegSetValueEx(m_hKey
, pszValueName
, 0, dwType
, (const BYTE
*)pValue
, nBytes
);
1219 LONG
SetDWORDValue(LPCTSTR pszValueName
, DWORD dwValue
) throw()
1221 return SetValue(pszValueName
, REG_DWORD
, &dwValue
, sizeof(DWORD
));
1224 LONG
SetStringValue(LPCTSTR pszValueName
, LPCTSTR pszValue
, DWORD dwType
= REG_SZ
) throw()
1231 length
= (_tcslen(pszValue
) + 1) * sizeof(TCHAR
);
1232 return SetValue(pszValueName
, dwType
, pszValue
, length
);
1234 return SetMultiStringValue(pszValueName
, pszValue
);
1236 return ERROR_INVALID_DATA
;
1240 LONG
SetGUIDValue(LPCTSTR pszValueName
, REFGUID guidValue
) throw()
1242 OLECHAR buf
[40] = {0};
1243 ::StringFromGUID2(guidValue
, buf
, 39);
1245 return SetStringValue(pszValueName
, buf
);
1247 CHAR bufA
[40] = {0};
1248 ::WideCharToMultiByte(CP_THREAD_ACP
, 0, buf
, -1, bufA
, 40, NULL
, NULL
);
1249 return SetStringValue(pszValueName
, bufA
);
1253 LONG
SetBinaryValue(LPCTSTR pszValueName
, const void* pValue
, ULONG nBytes
) throw()
1255 return SetValue(pszValueName
, REG_BINARY
, pValue
, nBytes
);
1258 LONG
SetMultiStringValue(LPCTSTR pszValueName
, LPCTSTR pszValue
) throw()
1260 ULONG dwSize
= CRegKey::_GetMultiStringSize(pszValue
);
1261 return SetValue(pszValueName
, REG_MULTI_SZ
, pszValue
, dwSize
);
1264 LONG
SetQWORDValue(LPCTSTR pszValueName
, ULONGLONG qwValue
) throw()
1266 ULONG dwSize
= sizeof(ULONGLONG
);
1267 return SetValue(pszValueName
, REG_QWORD
, &qwValue
, dwSize
);
1270 LONG
NotifyChangeKeyValue(BOOL bWatchSubtree
, DWORD dwNotifyFilter
,
1271 HANDLE hEvent
, BOOL bAsync
= TRUE
) throw()
1274 LONG ret
= ::RegNotifyChangeKeyValue(m_hKey
, bWatchSubtree
,
1275 dwNotifyFilter
, hEvent
, bAsync
);
1279 LONG
Flush() throw()
1282 LONG ret
= ::RegFlushKey(m_hKey
);
1286 static LONG WINAPI
SetValue(HKEY hKeyParent
, LPCTSTR lpszKeyName
,
1287 LPCTSTR lpszValue
, LPCTSTR lpszValueName
= NULL
)
1290 LONG lRet
= key
.Create(hKeyParent
, lpszKeyName
);
1291 if (lRet
== ERROR_SUCCESS
)
1293 lRet
= key
.SetStringValue(lpszValueName
, lpszValue
);
1298 LONG
SetKeyValue(LPCTSTR lpszKeyName
, LPCTSTR lpszValue
,
1299 LPCTSTR lpszValueName
= NULL
) throw()
1302 LONG lRet
= key
.Create(m_hKey
, lpszKeyName
);
1303 if (lRet
== ERROR_SUCCESS
)
1305 lRet
= key
.SetStringValue(lpszValueName
, lpszValue
);
1310 LONG
DeleteValue(LPCTSTR lpszValue
) throw()
1313 return ::RegDeleteValue(m_hKey
, lpszValue
);
1316 LONG
DeleteSubKey(LPCTSTR lpszSubKey
) throw()
1319 ATLASSERT(lpszSubKey
);
1320 return ::RegDeleteKey(m_hKey
, lpszSubKey
);
1323 LONG
RecurseDeleteKey(LPCTSTR lpszKey
) throw()
1327 return CRegKey::_DoDeleteKeyTree(m_hKey
, lpszKey
);
1330 LONG
EnumKey(DWORD iIndex
, LPTSTR pszName
, LPDWORD pnNameLength
,
1331 FILETIME
* pftLastWriteTime
= NULL
) throw()
1334 LONG ret
= ::RegEnumKeyEx(m_hKey
, iIndex
, pszName
, pnNameLength
, NULL
,
1335 NULL
, NULL
, pftLastWriteTime
);
1339 LONG
GetKeySecurity(SECURITY_INFORMATION si
, PSECURITY_DESCRIPTOR psd
,
1340 LPDWORD pnBytes
) throw()
1343 LONG ret
= ::RegGetKeySecurity(m_hKey
, si
, psd
, pnBytes
);
1347 LONG
SetKeySecurity(SECURITY_INFORMATION si
,
1348 PSECURITY_DESCRIPTOR psd
) throw()
1351 LONG ret
= ::RegSetKeySecurity(m_hKey
, si
, psd
);
1355 operator HKEY() const throw()
1360 CRegKey
& operator=(CRegKey
& key
) throw()
1362 Attach(key
.Detach());
1367 // get the total size of a multistring
1368 static ULONG
_GetMultiStringSize(LPCTSTR pszz
)
1373 int len
= _tcslen(pszz
);
1376 } while (*pszz
!= TEXT('\0'));
1378 return count
* sizeof(TCHAR
);
1381 // delete key recursively
1382 static LONG
_DoDeleteKeyTree(HKEY hParentKey
, LPCTSTR lpszKey
)
1384 ATLASSERT(hParentKey
);
1389 LONG ret
= key
.Open(hParentKey
, lpszKey
);
1390 if (ret
!= ERROR_SUCCESS
)
1392 return ret
; // failure
1395 // get the longest length of subkey names
1397 ret
= ::RegQueryInfoKey(key
, NULL
, NULL
, NULL
, NULL
, &NameMax
, NULL
,
1398 NULL
, NULL
, NULL
, NULL
, NULL
);
1399 if (ret
!= ERROR_SUCCESS
)
1401 return ret
; // failure
1403 ++NameMax
; // for NUL
1405 // allocate the string buffer for names if necessary
1406 TCHAR szNameBuf
[MAX_PATH
], *pszName
;
1407 if (NameMax
> MAX_PATH
)
1409 pszName
= (TCHAR
*)malloc(NameMax
* sizeof(TCHAR
));
1411 if (pszName
== NULL
)
1413 return ERROR_OUTOFMEMORY
; // failure
1419 pszName
= szNameBuf
;
1422 // enumerate every subkey and delete
1425 DWORD Count
= NameMax
;
1426 ret
= key
.EnumKey(0, pszName
, &Count
);
1427 if (ret
!= ERROR_SUCCESS
)
1429 if (ret
== ERROR_NO_MORE_ITEMS
)
1430 ret
= ERROR_SUCCESS
;
1434 ret
= CRegKey::_DoDeleteKeyTree(key
, pszName
);
1435 if (ret
!= ERROR_SUCCESS
)
1442 // delete the subkey
1443 if (ret
== ERROR_SUCCESS
)
1444 ret
= ::RegDeleteKey(hParentKey
, lpszKey
);
1446 // delete the buffer if any
1447 if (pszName
!= szNameBuf
)
1455 class CComHeapPtr
: public CHeapPtr
<T
, CComAllocator
>
1462 explicit CComHeapPtr(T
*lp
) :
1463 CHeapPtr
<T
, CComAllocator
>(lp
)
1469 inline HRESULT __stdcall
AtlAdvise(IUnknown
*pUnkCP
, IUnknown
*pUnk
, const IID
&iid
, LPDWORD pdw
)
1471 CComPtr
<IConnectionPointContainer
> container
;
1472 CComPtr
<IConnectionPoint
> connectionPoint
;
1476 return E_INVALIDARG
;
1477 hResult
= pUnkCP
->QueryInterface(IID_IConnectionPointContainer
, (void **)&container
);
1478 if (FAILED(hResult
))
1480 hResult
= container
->FindConnectionPoint(iid
, &connectionPoint
);
1481 if (FAILED(hResult
))
1483 return connectionPoint
->Advise(pUnk
, pdw
);
1486 inline HRESULT __stdcall
AtlUnadvise(IUnknown
*pUnkCP
, const IID
&iid
, DWORD dw
)
1488 CComPtr
<IConnectionPointContainer
> container
;
1489 CComPtr
<IConnectionPoint
> connectionPoint
;
1493 return E_INVALIDARG
;
1494 hResult
= pUnkCP
->QueryInterface(IID_IConnectionPointContainer
, (void **)&container
);
1495 if (FAILED(hResult
))
1497 hResult
= container
->FindConnectionPoint(iid
, &connectionPoint
);
1498 if (FAILED(hResult
))
1500 return connectionPoint
->Unadvise(dw
);
1503 inline HRESULT __stdcall
AtlInternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
)
1506 IUnknown
*resultInterface
;
1509 ATLASSERT(pThis
!= NULL
&& pEntries
!= NULL
);
1510 if (pThis
== NULL
|| pEntries
== NULL
)
1511 return E_INVALIDARG
;
1512 ATLASSERT(ppvObject
!= NULL
);
1513 if (ppvObject
== NULL
)
1516 if (InlineIsEqualUnknown(iid
))
1518 resultInterface
= reinterpret_cast<IUnknown
*>(reinterpret_cast<char *>(pThis
) + pEntries
[0].dw
);
1519 *ppvObject
= resultInterface
;
1520 resultInterface
->AddRef();
1525 while (pEntries
[i
].pFunc
!= 0)
1527 if (pEntries
[i
].piid
== NULL
|| InlineIsEqualGUID(iid
, *pEntries
[i
].piid
))
1529 if (pEntries
[i
].pFunc
== reinterpret_cast<_ATL_CREATORARGFUNC
*>(1))
1531 ATLASSERT(pEntries
[i
].piid
!= NULL
);
1532 resultInterface
= reinterpret_cast<IUnknown
*>(reinterpret_cast<char *>(pThis
) + pEntries
[i
].dw
);
1533 *ppvObject
= resultInterface
;
1534 resultInterface
->AddRef();
1539 hResult
= pEntries
[i
].pFunc(pThis
, iid
, ppvObject
, 0);
1540 if (hResult
== S_OK
)
1542 if (FAILED(hResult
) && pEntries
[i
].piid
!= NULL
)
1549 return E_NOINTERFACE
;
1552 inline HRESULT __stdcall
AtlWinModuleInit(_ATL_WIN_MODULE
*pWinModule
)
1554 if (pWinModule
== NULL
)
1555 return E_INVALIDARG
;
1556 pWinModule
->m_pCreateWndList
= NULL
;
1557 return pWinModule
->m_csWindowCreate
.Init();
1560 inline HRESULT __stdcall
AtlWinModuleTerm(_ATL_WIN_MODULE
*pWinModule
, HINSTANCE hInst
)
1562 if (pWinModule
== NULL
)
1563 return E_INVALIDARG
;
1564 pWinModule
->m_csWindowCreate
.Term();
1568 inline void __stdcall
AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE
*pWinModule
, _AtlCreateWndData
*pData
, void *pObject
)
1570 CComCritSecLock
<CComCriticalSection
> lock(pWinModule
->m_csWindowCreate
, true);
1572 ATLASSERT(pWinModule
!= NULL
);
1573 ATLASSERT(pObject
!= NULL
);
1575 pData
->m_pThis
= pObject
;
1576 pData
->m_dwThreadID
= ::GetCurrentThreadId();
1577 pData
->m_pNext
= pWinModule
->m_pCreateWndList
;
1578 pWinModule
->m_pCreateWndList
= pData
;
1581 inline void *__stdcall
AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE
*pWinModule
)
1583 CComCritSecLock
<CComCriticalSection
> lock(pWinModule
->m_csWindowCreate
, true);
1585 _AtlCreateWndData
*currentEntry
;
1586 _AtlCreateWndData
**previousLink
;
1589 ATLASSERT(pWinModule
!= NULL
);
1592 threadID
= GetCurrentThreadId();
1593 currentEntry
= pWinModule
->m_pCreateWndList
;
1594 previousLink
= &pWinModule
->m_pCreateWndList
;
1595 while (currentEntry
!= NULL
)
1597 if (currentEntry
->m_dwThreadID
== threadID
)
1599 *previousLink
= currentEntry
->m_pNext
;
1600 result
= currentEntry
->m_pThis
;
1603 previousLink
= ¤tEntry
->m_pNext
;
1604 currentEntry
= currentEntry
->m_pNext
;
1609 // Adapted from dll/win32/atl/atl.c
1610 inline HRESULT WINAPI
AtlLoadTypeLib(HINSTANCE inst
, LPCOLESTR lpszIndex
,
1611 BSTR
*pbstrPath
, ITypeLib
**ppTypeLib
)
1613 size_t index_len
= lpszIndex
? wcslen(lpszIndex
) : 0;
1614 CComHeapPtr
<WCHAR
> path
;
1615 path
.Allocate(MAX_PATH
+ index_len
+ wcslen(L
".tlb"));
1618 return E_OUTOFMEMORY
;
1620 size_t path_len
= GetModuleFileNameW(inst
, path
, MAX_PATH
);
1622 return HRESULT_FROM_WIN32(GetLastError());
1625 wcscat(path
, lpszIndex
);
1627 CComPtr
<ITypeLib
> typelib
;
1628 HRESULT hResult
= LoadTypeLib(path
, &typelib
);
1629 if (FAILED(hResult
))
1632 for (ptr
= path
+path_len
-1; ptr
> path
&& *ptr
!= '\\' && *ptr
!= '.'; ptr
--)
1635 ptr
= (WCHAR
*)path
+ path_len
;
1636 wcscpy(ptr
, L
".tlb");
1638 hResult
= LoadTypeLib(path
, &typelib
);
1641 if (SUCCEEDED(hResult
))
1643 *pbstrPath
= SysAllocString(path
);
1647 hResult
= E_OUTOFMEMORY
;
1651 if (FAILED(hResult
))
1654 *ppTypeLib
= typelib
.Detach();
1658 // Adapted from dll/win32/atl/atl.c
1659 inline HRESULT WINAPI
AtlRegisterTypeLib(HINSTANCE inst
, const WCHAR
*index
)
1662 CComPtr
<ITypeLib
> typelib
;
1663 HRESULT hResult
= AtlLoadTypeLib(inst
, index
, &path
, &typelib
);
1664 if (FAILED(hResult
))
1667 return RegisterTypeLib(typelib
, path
, NULL
); /* FIXME: pass help directory */
1670 // Adapted from dll/win32/atl/atl.c
1671 inline HRESULT WINAPI
AtlRegisterClassCategoriesHelper(REFCLSID clsid
, const _ATL_CATMAP_ENTRY
*catmap
, BOOL reg
)
1676 CComPtr
<ICatRegister
> catreg
;
1678 HRESULT hResult
= CoCreateInstance(CLSID_StdComponentCategoriesMgr
, NULL
, CLSCTX_INPROC_SERVER
, IID_ICatRegister
, (void**)&catreg
);
1679 if (FAILED(hResult
))
1682 for (const _ATL_CATMAP_ENTRY
*iter
= catmap
; iter
->iType
!= _ATL_CATMAP_ENTRY_END
; iter
++)
1684 CATID catid
= *iter
->pcatid
;
1686 if (iter
->iType
== _ATL_CATMAP_ENTRY_IMPLEMENTED
)
1689 hResult
= catreg
->RegisterClassImplCategories(clsid
, 1, &catid
);
1691 hResult
= catreg
->UnRegisterClassImplCategories(clsid
, 1, &catid
);
1696 hResult
= catreg
->RegisterClassReqCategories(clsid
, 1, &catid
);
1698 hResult
= catreg
->UnRegisterClassReqCategories(clsid
, 1, &catid
);
1700 if (FAILED(hResult
))
1706 WCHAR reg_path
[256] = L
"CLSID\\";
1708 StringFromGUID2(clsid
, reg_path
+ wcslen(reg_path
), 64);
1709 wcscat(reg_path
, L
"\\");
1710 WCHAR
* ptr
= reg_path
+ wcslen(reg_path
);
1712 wcscpy(ptr
, L
"Implemented Categories");
1713 RegDeleteKeyW(HKEY_CLASSES_ROOT
, reg_path
);
1715 wcscpy(ptr
, L
"Required Categories");
1716 RegDeleteKeyW(HKEY_CLASSES_ROOT
, reg_path
);
1723 // Adapted from dll/win32/atl80/atl80.c
1724 inline HRESULT __stdcall
AtlComModuleRegisterServer(_ATL_COM_MODULE
*mod
, BOOL bRegTypeLib
, const CLSID
*clsid
)
1726 HRESULT hResult
= S_OK
;
1728 for (_ATL_OBJMAP_ENTRY
** iter
= mod
->m_ppAutoObjMapFirst
; iter
< mod
->m_ppAutoObjMapLast
; iter
++)
1732 _ATL_OBJMAP_ENTRY
* entry
= *iter
;
1733 if (clsid
&& !IsEqualCLSID(*entry
->pclsid
, *clsid
))
1736 hResult
= entry
->pfnUpdateRegistry(TRUE
);
1737 if (FAILED(hResult
))
1740 const _ATL_CATMAP_ENTRY
*catmap
= entry
->pfnGetCategoryMap();
1743 hResult
= AtlRegisterClassCategoriesHelper(*entry
->pclsid
, catmap
, TRUE
);
1744 if (FAILED(hResult
))
1751 hResult
= AtlRegisterTypeLib(mod
->m_hInstTypeLib
, NULL
);
1757 // Adapted from dll/win32/atl/atl.c
1758 inline HRESULT WINAPI
AtlComModuleUnregisterServer(_ATL_COM_MODULE
*mod
, BOOL bUnRegTypeLib
, const CLSID
*clsid
)
1760 HRESULT hResult
= S_OK
;
1762 for (_ATL_OBJMAP_ENTRY
**iter
= mod
->m_ppAutoObjMapFirst
; iter
< mod
->m_ppAutoObjMapLast
; iter
++)
1766 _ATL_OBJMAP_ENTRY
* entry
= *iter
;
1767 if (clsid
&& !IsEqualCLSID(*entry
->pclsid
, *clsid
))
1770 const _ATL_CATMAP_ENTRY
*catmap
= entry
->pfnGetCategoryMap();
1773 hResult
= AtlRegisterClassCategoriesHelper(*entry
->pclsid
, catmap
, FALSE
);
1774 if (FAILED(hResult
))
1778 hResult
= entry
->pfnUpdateRegistry(FALSE
);
1779 if (FAILED(hResult
))
1785 CComPtr
<ITypeLib
> typelib
;
1789 hResult
= AtlLoadTypeLib(mod
->m_hInstTypeLib
, NULL
, &path
, &typelib
);
1790 if (FAILED(hResult
))
1793 hResult
= typelib
->GetLibAttr(&attr
);
1794 if (SUCCEEDED(hResult
))
1796 hResult
= UnRegisterTypeLib(attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, attr
->lcid
, attr
->syskind
);
1797 typelib
->ReleaseTLibAttr(attr
);
1805 // Adapted from dll/win32/atl/atl.c
1806 inline HRESULT WINAPI
AtlComModuleRegisterClassObjects(_ATL_COM_MODULE
*module
, DWORD context
, DWORD flags
)
1808 _ATL_OBJMAP_ENTRY
**iter
;
1809 IUnknown
* unk
= NULL
;
1813 return E_INVALIDARG
;
1815 for (iter
= module
->m_ppAutoObjMapFirst
; iter
< module
->m_ppAutoObjMapLast
; iter
++)
1817 if (!(*iter
)->pfnGetClassObject
)
1820 hr
= (*iter
)->pfnGetClassObject((void*)(*iter
)->pfnCreateInstance
, IID_IUnknown
, (void**)&unk
);
1824 hr
= CoRegisterClassObject(*(*iter
)->pclsid
, unk
, context
, flags
, &(*iter
)->dwRegister
);
1834 // Adapted from dll/win32/atl/atl.c
1835 inline HRESULT WINAPI
AtlComModuleRevokeClassObjects(_ATL_COM_MODULE
*module
)
1837 _ATL_OBJMAP_ENTRY
**iter
;
1841 return E_INVALIDARG
;
1843 for (iter
= module
->m_ppAutoObjMapFirst
; iter
< module
->m_ppAutoObjMapLast
; iter
++)
1845 hr
= CoRevokeClassObject((*iter
)->dwRegister
);
1856 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
1857 using namespace ATL
;
1858 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE