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
25 #include "atlcomcli.h"
31 // It is common to use this in ATL constructors. They only store this for later use, so the usage is safe.
32 #pragma warning(disable:4355)
36 #define _ATL_PACKING 8
39 #ifndef _ATL_FREE_THREADED
40 #ifndef _ATL_APARTMENT_THREADED
41 #ifndef _ATL_SINGLE_THREADED
42 #define _ATL_FREE_THREADED
51 #ifdef _ATL_DISABLE_NO_VTABLE
54 #define ATL_NO_VTABLE __declspec(novtable)
57 #ifndef ATL_DEPRECATED
58 #define ATL_DEPRECATED __declspec(deprecated)
61 #define offsetofclass(base, derived) (reinterpret_cast<DWORD_PTR>(static_cast<base *>(reinterpret_cast<derived *>(_ATL_PACKING))) - _ATL_PACKING)
69 __declspec(selectany
) CAtlModule
*_pAtlModule
= NULL
;
70 __declspec(selectany
) CComModule
*_pModule
= NULL
;
71 extern CAtlComModule _AtlComModule
;
74 struct _ATL_CATMAP_ENTRY
80 #define _ATL_CATMAP_ENTRY_END 0
81 #define _ATL_CATMAP_ENTRY_IMPLEMENTED 1
82 #define _ATL_CATMAP_ENTRY_REQUIRED 2
85 typedef HRESULT (WINAPI _ATL_CREATORFUNC
)(void *pv
, REFIID riid
, LPVOID
*ppv
);
86 typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC
)();
87 typedef const struct _ATL_CATMAP_ENTRY
* (_ATL_CATMAPFUNC
)();
89 struct _ATL_OBJMAP_ENTRY30
92 HRESULT (WINAPI
*pfnUpdateRegistry
)(BOOL bRegister
);
93 _ATL_CREATORFUNC
*pfnGetClassObject
;
94 _ATL_CREATORFUNC
*pfnCreateInstance
;
97 _ATL_DESCRIPTIONFUNC
*pfnGetObjectDescription
;
98 _ATL_CATMAPFUNC
*pfnGetCategoryMap
;
99 void (WINAPI
*pfnObjectMain
)(bool bStarting
);
101 HRESULT WINAPI
RevokeClassObject()
105 return CoRevokeClassObject(dwRegister
);
108 HRESULT WINAPI
RegisterClassObject(DWORD dwClsContext
, DWORD dwFlags
)
114 if (pfnGetClassObject
== NULL
)
117 hResult
= pfnGetClassObject(reinterpret_cast<LPVOID
*>(pfnCreateInstance
), IID_IUnknown
, reinterpret_cast<LPVOID
*>(&p
));
118 if (SUCCEEDED(hResult
))
119 hResult
= CoRegisterClassObject(*pclsid
, p
, dwClsContext
, dwFlags
, &dwRegister
);
128 typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY
;
130 typedef void (__stdcall _ATL_TERMFUNC
)(DWORD_PTR dw
);
132 struct _ATL_TERMFUNC_ELEM
134 _ATL_TERMFUNC
*pFunc
;
136 _ATL_TERMFUNC_ELEM
*pNext
;
143 _ATL_TERMFUNC_ELEM
*m_pTermFuncs
;
144 CComCriticalSection m_csStaticDataInitAndTypeInfo
;
146 typedef _ATL_MODULE70 _ATL_MODULE
;
148 typedef HRESULT (WINAPI _ATL_CREATORARGFUNC
)(void *pv
, REFIID riid
, LPVOID
*ppv
, DWORD_PTR dw
);
150 #define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC *)1)
152 struct _ATL_INTMAP_ENTRY
156 _ATL_CREATORARGFUNC
*pFunc
;
159 struct _AtlCreateWndData
163 _AtlCreateWndData
*m_pNext
;
166 struct _ATL_COM_MODULE70
169 HINSTANCE m_hInstTypeLib
;
170 _ATL_OBJMAP_ENTRY
**m_ppAutoObjMapFirst
;
171 _ATL_OBJMAP_ENTRY
**m_ppAutoObjMapLast
;
172 CComCriticalSection m_csObjMap
;
174 typedef _ATL_COM_MODULE70 _ATL_COM_MODULE
;
176 struct _ATL_WIN_MODULE70
179 CComCriticalSection m_csWindowCreate
;
180 _AtlCreateWndData
*m_pCreateWndList
;
182 CSimpleArray
<ATOM
> m_rgWindowClassAtoms
;
185 typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE
;
187 struct _ATL_REGMAP_ENTRY
193 HRESULT __stdcall
AtlWinModuleInit(_ATL_WIN_MODULE
*pWinModule
);
194 HRESULT __stdcall
AtlWinModuleTerm(_ATL_WIN_MODULE
*pWinModule
, HINSTANCE hInst
);
195 HRESULT __stdcall
AtlInternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
);
196 void __stdcall
AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE
*pWinModule
, _AtlCreateWndData
*pData
, void *pObject
);
197 void *__stdcall
AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE
*pWinModule
);
198 HRESULT __stdcall
AtlComModuleGetClassObject(_ATL_COM_MODULE
*pComModule
, REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
);
200 HRESULT __stdcall
AtlComModuleRegisterServer(_ATL_COM_MODULE
*mod
, BOOL bRegTypeLib
, const CLSID
*clsid
);
201 HRESULT __stdcall
AtlComModuleUnregisterServer(_ATL_COM_MODULE
*mod
, BOOL bRegTypeLib
, const CLSID
*clsid
);
204 template<class TLock
>
205 class CComCritSecLock
211 CComCritSecLock(TLock
&cs
, bool bInitialLock
= true) : m_cs(cs
)
236 ATLASSERT(!m_bLocked
);
237 hResult
= m_cs
.Lock();
249 ATLASSERT(m_bLocked
);
250 hResult
= m_cs
.Unlock();
271 CHandle(_Inout_ CHandle
& handle
) :
274 Attach(handle
.Detach());
277 explicit CHandle(_In_ HANDLE handle
) :
290 CHandle
& operator=(_Inout_ CHandle
& handle
)
298 Attach(handle
.Detach());
304 operator HANDLE() const
309 void Attach(_In_ HANDLE handle
)
311 ATLASSERT(m_handle
== NULL
);
317 HANDLE handle
= m_handle
;
326 ::CloseHandle(m_handle
);
333 inline BOOL WINAPI
InlineIsEqualUnknown(REFGUID rguid1
)
336 ((unsigned long *)&rguid1
)[0] == 0 &&
337 ((unsigned long *)&rguid1
)[1] == 0 &&
338 ((unsigned long *)&rguid1
)[2] == 0x000000C0 &&
339 ((unsigned long *)&rguid1
)[3] == 0x46000000);
342 class CComMultiThreadModelNoCS
345 typedef CComFakeCriticalSection AutoCriticalSection
;
346 typedef CComFakeCriticalSection CriticalSection
;
347 typedef CComMultiThreadModelNoCS ThreadModelNoCS
;
348 typedef CComFakeCriticalSection AutoDeleteCriticalSection
;
350 static ULONG WINAPI
Increment(LPLONG p
)
352 return InterlockedIncrement(p
);
355 static ULONG WINAPI
Decrement(LPLONG p
)
357 return InterlockedDecrement(p
);
361 class CComMultiThreadModel
364 typedef CComAutoCriticalSection AutoCriticalSection
;
365 typedef CComCriticalSection CriticalSection
;
366 typedef CComMultiThreadModelNoCS ThreadModelNoCS
;
367 typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection
;
369 static ULONG WINAPI
Increment(LPLONG p
)
371 return InterlockedIncrement(p
);
374 static ULONG WINAPI
Decrement(LPLONG p
)
376 return InterlockedDecrement(p
);
380 class CComSingleThreadModel
383 typedef CComFakeCriticalSection AutoCriticalSection
;
384 typedef CComFakeCriticalSection CriticalSection
;
385 typedef CComSingleThreadModel ThreadModelNoCS
;
386 typedef CComFakeCriticalSection AutoDeleteCriticalSection
;
388 static ULONG WINAPI
Increment(LPLONG p
)
393 static ULONG WINAPI
Decrement(LPLONG p
)
399 #if defined(_ATL_FREE_THREADED)
401 typedef CComMultiThreadModel CComObjectThreadModel
;
402 typedef CComMultiThreadModel CComGlobalsThreadModel
;
404 #elif defined(_ATL_APARTMENT_THREADED)
406 typedef CComSingleThreadModel CComObjectThreadModel
;
407 typedef CComMultiThreadModel CComGlobalsThreadModel
;
409 #elif defined(_ATL_SINGLE_THREADED)
411 typedef CComSingleThreadModel CComObjectThreadModel
;
412 typedef CComSingleThreadModel CComGlobalsThreadModel
;
415 #error No threading model
418 class CAtlModule
: public _ATL_MODULE
425 ATLASSERT(_pAtlModule
== NULL
);
427 cbSize
= sizeof(_ATL_MODULE
);
431 virtual LONG
GetLockCount()
438 return CComGlobalsThreadModel::Increment(&m_nLockCnt
);
441 virtual LONG
Unlock()
443 return CComGlobalsThreadModel::Decrement(&m_nLockCnt
);
446 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
* /*pRegistrar*/) = 0;
448 HRESULT WINAPI
UpdateRegistryFromResource(LPCTSTR lpszRes
, BOOL bRegister
, struct _ATL_REGMAP_ENTRY
*pMapEntries
= NULL
)
450 CRegObject registrar
;
451 WCHAR modulePath
[MAX_PATH
];
455 hResult
= CommonInitRegistrar(registrar
, modulePath
, sizeof(modulePath
) / sizeof(modulePath
[0]), pMapEntries
);
461 /* FIXME: this is a bit of a hack, need to re-evaluate */
462 WCHAR resid
[MAX_PATH
];
463 MultiByteToWideChar(CP_ACP
, 0, lpszRes
, -1, resid
, MAX_PATH
);
466 if (bRegister
!= FALSE
)
467 hResult
= registrar
.ResourceRegisterSz(modulePath
, lpwszRes
, L
"REGISTRY");
469 hResult
= registrar
.ResourceUnregisterSz(modulePath
, lpwszRes
, L
"REGISTRY");
474 HRESULT WINAPI
UpdateRegistryFromResource(UINT nResID
, BOOL bRegister
, struct _ATL_REGMAP_ENTRY
*pMapEntries
= NULL
)
476 CRegObject registrar
;
477 WCHAR modulePath
[MAX_PATH
];
480 hResult
= CommonInitRegistrar(registrar
, modulePath
, sizeof(modulePath
) / sizeof(modulePath
[0]), pMapEntries
);
484 if (bRegister
!= FALSE
)
485 hResult
= registrar
.ResourceRegister(modulePath
, nResID
, L
"REGISTRY");
487 hResult
= registrar
.ResourceUnregister(modulePath
, nResID
, L
"REGISTRY");
493 HRESULT
CommonInitRegistrar(CRegObject
®istrar
, WCHAR
*modulePath
, DWORD modulePathCount
, struct _ATL_REGMAP_ENTRY
*pMapEntries
)
499 hInstance
= _AtlBaseModule
.GetModuleInstance();
500 dwFLen
= GetModuleFileNameW(hInstance
, modulePath
, modulePathCount
);
501 if (dwFLen
== modulePathCount
)
502 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
503 else if (dwFLen
== 0)
504 return HRESULT_FROM_WIN32(GetLastError());
506 if (pMapEntries
!= NULL
)
508 while (pMapEntries
->szKey
!= NULL
)
510 ATLASSERT(pMapEntries
->szData
!= NULL
);
511 hResult
= registrar
.AddReplacement(pMapEntries
->szKey
, pMapEntries
->szData
);
518 hResult
= AddCommonRGSReplacements(®istrar
);
522 hResult
= registrar
.AddReplacement(L
"Module", modulePath
);
526 hResult
= registrar
.AddReplacement(L
"Module_Raw", modulePath
);
534 __declspec(selectany
) GUID
CAtlModule::m_libid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
537 class CAtlModuleT
: public CAtlModule
541 HRESULT
RegisterServer(BOOL bRegTypeLib
= FALSE
, const CLSID
*pCLSID
= NULL
);
542 HRESULT
UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
= NULL
);
545 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
*pRegistrar
)
547 return pRegistrar
->AddReplacement(L
"APPID", T::GetAppId());
550 static LPCOLESTR
GetAppId()
556 class CAtlComModule
: public _ATL_COM_MODULE
561 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
, (LPCWSTR
)this, &m_hInstTypeLib
);
562 m_ppAutoObjMapFirst
= NULL
;
563 m_ppAutoObjMapLast
= NULL
;
564 if (FAILED(m_csObjMap
.Init()))
567 CAtlBaseModule::m_bInitFailed
= true;
570 cbSize
= sizeof(_ATL_COM_MODULE
);
578 HRESULT
RegisterServer(BOOL bRegTypeLib
= FALSE
, const CLSID
*pCLSID
= NULL
)
580 return AtlComModuleRegisterServer(this, bRegTypeLib
, pCLSID
);
583 HRESULT
UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
= NULL
)
585 return AtlComModuleUnregisterServer(this, bUnRegTypeLib
, pCLSID
);
593 ATLASSERT(m_ppAutoObjMapFirst
== NULL
);
594 ATLASSERT(m_ppAutoObjMapLast
== NULL
);
602 HRESULT CAtlModuleT
<T
>::RegisterServer(BOOL bRegTypeLib
, const CLSID
*pCLSID
)
604 return _AtlComModule
.RegisterServer(bRegTypeLib
, pCLSID
);
608 HRESULT CAtlModuleT
<T
>::UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
)
610 return _AtlComModule
.UnregisterServer(bUnRegTypeLib
, pCLSID
);
614 class CAtlDllModuleT
: public CAtlModuleT
<T
>
621 HRESULT
DllCanUnloadNow()
625 pThis
= static_cast<T
*>(this);
626 if (pThis
->GetLockCount() == 0)
631 HRESULT
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
635 pThis
= static_cast<T
*>(this);
636 return pThis
->GetClassObject(rclsid
, riid
, ppv
);
639 HRESULT
DllRegisterServer(BOOL bRegTypeLib
= TRUE
)
644 pThis
= static_cast<T
*>(this);
645 hResult
= pThis
->RegisterServer(bRegTypeLib
);
649 HRESULT
DllUnregisterServer(BOOL bUnRegTypeLib
= TRUE
)
654 pThis
= static_cast<T
*>(this);
655 hResult
= pThis
->UnregisterServer(bUnRegTypeLib
);
659 HRESULT
GetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
661 return AtlComModuleGetClassObject(&_AtlComModule
, rclsid
, riid
, ppv
);
665 class CComModule
: public CAtlModuleT
<CComModule
>
668 _ATL_OBJMAP_ENTRY
*m_pObjMap
;
672 ATLASSERT(_pModule
== NULL
);
674 _pModule
->m_pObjMap
= NULL
;
682 HRESULT
Init(_ATL_OBJMAP_ENTRY
*p
, HINSTANCE
/* h */, const GUID
*plibid
)
684 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
689 if (p
!= reinterpret_cast<_ATL_OBJMAP_ENTRY
*>(-1))
695 while (objectMapEntry
->pclsid
!= NULL
)
697 objectMapEntry
->pfnObjectMain(true);
707 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
709 if (m_pObjMap
!= NULL
)
711 objectMapEntry
= m_pObjMap
;
712 while (objectMapEntry
->pclsid
!= NULL
)
714 if (objectMapEntry
->pCF
!= NULL
)
715 objectMapEntry
->pCF
->Release();
716 objectMapEntry
->pCF
= NULL
;
717 objectMapEntry
->pfnObjectMain(false);
723 HRESULT
GetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
725 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
728 ATLASSERT(ppv
!= NULL
);
733 if (m_pObjMap
!= NULL
)
735 objectMapEntry
= m_pObjMap
;
736 while (objectMapEntry
->pclsid
!= NULL
)
738 if (objectMapEntry
->pfnGetClassObject
!= NULL
&& InlineIsEqualGUID(rclsid
, *objectMapEntry
->pclsid
) != FALSE
)
740 if (objectMapEntry
->pCF
== NULL
)
742 CComCritSecLock
<CComCriticalSection
> lock(_AtlComModule
.m_csObjMap
, true);
744 if (objectMapEntry
->pCF
== NULL
)
745 hResult
= objectMapEntry
->pfnGetClassObject(reinterpret_cast<void *>(objectMapEntry
->pfnCreateInstance
), IID_IUnknown
, reinterpret_cast<LPVOID
*>(&objectMapEntry
->pCF
));
747 if (objectMapEntry
->pCF
!= NULL
)
748 hResult
= objectMapEntry
->pCF
->QueryInterface(riid
, ppv
);
754 if (hResult
== S_OK
&& *ppv
== NULL
)
756 // FIXME: call AtlComModuleGetClassObject
757 hResult
= CLASS_E_CLASSNOTAVAILABLE
;
762 HRESULT
RegisterServer(BOOL bRegTypeLib
= FALSE
, const CLSID
*pCLSID
= NULL
)
764 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
768 objectMapEntry
= m_pObjMap
;
769 if (objectMapEntry
!= NULL
)
771 while (objectMapEntry
->pclsid
!= NULL
)
773 if (pCLSID
== NULL
|| IsEqualGUID(*pCLSID
, *objectMapEntry
->pclsid
) != FALSE
)
775 hResult
= objectMapEntry
->pfnUpdateRegistry(TRUE
);
782 if (SUCCEEDED(hResult
))
783 hResult
= CAtlModuleT
<CComModule
>::RegisterServer(bRegTypeLib
, pCLSID
);
787 HRESULT
UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
= NULL
)
789 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
793 objectMapEntry
= m_pObjMap
;
794 if (objectMapEntry
!= NULL
)
796 while (objectMapEntry
->pclsid
!= NULL
)
798 if (pCLSID
== NULL
|| IsEqualGUID(*pCLSID
, *objectMapEntry
->pclsid
) != FALSE
)
800 hResult
= objectMapEntry
->pfnUpdateRegistry(FALSE
); //unregister
807 if (SUCCEEDED(hResult
))
808 hResult
= CAtlModuleT
<CComModule
>::UnregisterServer(bUnRegTypeLib
, pCLSID
);
813 HRESULT
DllCanUnloadNow()
815 if (GetLockCount() == 0)
820 HRESULT
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
822 return GetClassObject(rclsid
, riid
, ppv
);
825 HRESULT
DllRegisterServer(BOOL bRegTypeLib
= TRUE
)
827 return RegisterServer(bRegTypeLib
);
830 HRESULT
DllUnregisterServer(BOOL bUnRegTypeLib
= TRUE
)
832 return UnregisterServer(bUnRegTypeLib
);
837 class CAtlWinModule
: public _ATL_WIN_MODULE
844 hResult
= AtlWinModuleInit(this);
847 CAtlBaseModule::m_bInitFailed
= true;
859 AtlWinModuleTerm(this, _AtlBaseModule
.GetModuleInstance());
862 void AddCreateWndData(_AtlCreateWndData
*pData
, void *pObject
)
864 AtlWinModuleAddCreateWndData(this, pData
, pObject
);
867 void *ExtractCreateWndData()
869 return AtlWinModuleExtractCreateWndData(this);
873 extern CAtlWinModule _AtlWinModule
;
878 static void* Allocate(_In_
size_t size
)
880 return ::CoTaskMemAlloc(size
);
883 static void* Reallocate(_In_opt_
void* ptr
, _In_
size_t size
)
885 return ::CoTaskMemRealloc(ptr
, size
);
888 static void Free(_In_opt_
void* ptr
)
890 ::CoTaskMemFree(ptr
);
900 CAtlTransactionManager
* m_pTM
;
910 CRegKey(CRegKey
& key
) throw()
911 : m_hKey(key
.Detach())
915 explicit CRegKey(HKEY hKey
) throw()
922 CRegKey(CAtlTransactionManager
* pTM
) throw()
932 void Attach(HKEY hKey
) throw()
941 HKEY hKey
= Detach();
942 return ::RegCloseKey(hKey
);
944 return ERROR_SUCCESS
;
947 HKEY
Detach() throw()
954 LONG
Open(HKEY hKeyParent
, LPCTSTR lpszKeyName
,
955 REGSAM samDesired
= KEY_READ
| KEY_WRITE
) throw()
957 ATLASSERT(hKeyParent
);
958 ATLASSERT(lpszKeyName
);
961 LONG lRes
= ::RegOpenKeyEx(hKeyParent
, lpszKeyName
, NULL
, samDesired
, &hKey
);
962 if (lRes
!= ERROR_SUCCESS
)
964 samDesired
|= KEY_WOW64_64KEY
;
965 lRes
= ::RegOpenKeyEx(hKeyParent
, lpszKeyName
, NULL
, samDesired
, &hKey
);
967 if (lRes
== ERROR_SUCCESS
)
975 LONG
Create(HKEY hKeyParent
, LPCTSTR lpszKeyName
,
976 LPTSTR lpszClass
= REG_NONE
,
977 DWORD dwOptions
= REG_OPTION_NON_VOLATILE
,
978 REGSAM samDesired
= KEY_READ
| KEY_WRITE
,
979 LPSECURITY_ATTRIBUTES lpSecAttr
= NULL
,
980 LPDWORD lpdwDisposition
= NULL
) throw()
982 ATLASSERT(hKeyParent
);
983 ATLASSERT(lpszKeyName
);
986 LONG lRes
= ::RegCreateKeyEx(hKeyParent
, lpszKeyName
, NULL
, lpszClass
,
987 dwOptions
, samDesired
, lpSecAttr
, &hKey
,
989 if (lRes
!= ERROR_SUCCESS
)
991 samDesired
|= KEY_WOW64_64KEY
;
992 lRes
= ::RegCreateKeyEx(hKeyParent
, lpszKeyName
, NULL
, lpszClass
,
993 dwOptions
, samDesired
, lpSecAttr
, &hKey
,
996 if (lRes
== ERROR_SUCCESS
)
1004 LONG
QueryValue(LPCTSTR pszValueName
, DWORD
* pdwType
, void* pData
, ULONG
* pnBytes
) throw()
1007 return ::RegQueryValueEx(m_hKey
, pszValueName
, NULL
, pdwType
, (LPBYTE
)pData
, pnBytes
);
1010 LONG
QueryDWORDValue(LPCTSTR pszValueName
, DWORD
& dwValue
) throw()
1012 ULONG size
= sizeof(DWORD
);
1014 LONG lRet
= QueryValue(pszValueName
, &type
, &dwValue
, &size
);
1016 if (lRet
== ERROR_SUCCESS
&& type
!= REG_DWORD
)
1017 lRet
= ERROR_INVALID_DATA
;
1022 LONG
QueryBinaryValue(LPCTSTR pszValueName
, void* pValue
, ULONG
* pnBytes
) throw()
1025 LONG lRet
= QueryValue(pszValueName
, &type
, pValue
, pnBytes
);
1027 if (lRet
== ERROR_SUCCESS
&& type
!= REG_BINARY
)
1028 lRet
= ERROR_INVALID_DATA
;
1033 LONG
QueryStringValue(LPCTSTR pszValueName
, LPTSTR pszValue
, ULONG
* pnChars
) throw()
1035 ULONG size
= (*pnChars
) * sizeof(TCHAR
);
1037 LONG lRet
= QueryValue(pszValueName
, &type
, pszValue
, &size
);
1039 if (lRet
== ERROR_SUCCESS
&& type
!= REG_SZ
&& type
!= REG_EXPAND_SZ
)
1040 lRet
= ERROR_INVALID_DATA
;
1042 *pnChars
= size
/ sizeof(TCHAR
);
1046 LONG
QueryGUIDValue(LPCTSTR pszValueName
, GUID
& guidValue
) throw()
1048 OLECHAR buf
[40] = {0};
1053 lRet
= QueryStringValue(pszValueName
, buf
, &nChars
);
1055 CHAR bufA
[40] = {0};
1056 lRet
= QueryStringValue(pszValueName
, bufA
, &nChars
);
1057 if (lRet
!= ERROR_SUCCESS
)
1059 if (!::MultiByteToWideChar(CP_THREAD_ACP
, 0, bufA
, -1, buf
, 39))
1060 lRet
= ERROR_INVALID_DATA
;
1062 if (lRet
!= ERROR_SUCCESS
)
1065 if (!SUCCEEDED(::CLSIDFromString(buf
, &guidValue
)))
1066 return ERROR_INVALID_DATA
;
1071 LONG
QueryQWORDValue(LPCTSTR pszValueName
, ULONGLONG
& qwValue
) throw()
1073 ULONG size
= sizeof(ULONGLONG
);
1075 LONG lRet
= QueryValue(pszValueName
, &type
, &qwValue
, &size
);
1077 if (lRet
== ERROR_SUCCESS
&& type
!= REG_QWORD
)
1078 lRet
= ERROR_INVALID_DATA
;
1083 LONG
QueryMultiStringValue(LPCTSTR pszValueName
, LPTSTR pszValue
,
1084 ULONG
* pnChars
) throw()
1086 ULONG size
= (*pnChars
) * sizeof(TCHAR
);
1088 LONG lRet
= QueryValue(pszValueName
, &type
, pszValue
, &size
);
1090 if (lRet
== ERROR_SUCCESS
&& type
!= REG_MULTI_SZ
)
1091 lRet
= ERROR_INVALID_DATA
;
1093 *pnChars
= size
/ sizeof(TCHAR
);
1097 LONG
SetValue(LPCTSTR pszValueName
, DWORD dwType
, const void* pValue
, ULONG nBytes
) throw()
1100 return ::RegSetValueEx(m_hKey
, pszValueName
, NULL
, dwType
, (const BYTE
*)pValue
, nBytes
);
1103 LONG
SetDWORDValue(LPCTSTR pszValueName
, DWORD dwValue
) throw()
1105 return SetValue(pszValueName
, REG_DWORD
, &dwValue
, sizeof(DWORD
));
1108 LONG
SetStringValue(LPCTSTR pszValueName
, LPCTSTR pszValue
, DWORD dwType
= REG_SZ
) throw()
1115 length
= (_tcslen(pszValue
) + 1) * sizeof(TCHAR
);
1116 return SetValue(pszValueName
, dwType
, pszValue
, length
);
1118 return SetMultiStringValue(pszValueName
, pszValue
);
1120 return ERROR_INVALID_DATA
;
1124 LONG
SetGUIDValue(LPCTSTR pszValueName
, REFGUID guidValue
) throw()
1126 OLECHAR buf
[40] = {0};
1127 ::StringFromGUID2(guidValue
, buf
, 39);
1129 return SetStringValue(pszValueName
, buf
);
1131 CHAR bufA
[40] = {0};
1132 ::WideCharToMultiByte(CP_THREAD_ACP
, 0, buf
, -1, bufA
, 40, NULL
, NULL
);
1133 return SetStringValue(pszValueName
, bufA
);
1137 LONG
SetBinaryValue(LPCTSTR pszValueName
, const void* pValue
, ULONG nBytes
) throw()
1139 return SetValue(pszValueName
, REG_BINARY
, pValue
, nBytes
);
1142 LONG
SetMultiStringValue(LPCTSTR pszValueName
, LPCTSTR pszValue
) throw()
1144 ULONG dwSize
= CRegKey::_GetMultiStringSize(pszValue
);
1145 return SetValue(pszValueName
, REG_MULTI_SZ
, pszValue
, dwSize
);
1148 LONG
SetQWORDValue(LPCTSTR pszValueName
, ULONGLONG qwValue
) throw()
1150 ULONG dwSize
= sizeof(ULONGLONG
);
1151 return SetValue(pszValueName
, REG_QWORD
, &qwValue
, dwSize
);
1154 LONG
NotifyChangeKeyValue(BOOL bWatchSubtree
, DWORD dwNotifyFilter
,
1155 HANDLE hEvent
, BOOL bAsync
= TRUE
) throw()
1158 LONG ret
= ::RegNotifyChangeKeyValue(m_hKey
, bWatchSubtree
,
1159 dwNotifyFilter
, hEvent
, bAsync
);
1163 LONG
Flush() throw()
1166 LONG ret
= ::RegFlushKey(m_hKey
);
1170 static LONG WINAPI
SetValue(HKEY hKeyParent
, LPCTSTR lpszKeyName
,
1171 LPCTSTR lpszValue
, LPCTSTR lpszValueName
= NULL
)
1174 LONG lRet
= key
.Create(hKeyParent
, lpszKeyName
);
1175 if (lRet
== ERROR_SUCCESS
)
1177 lRet
= key
.SetStringValue(lpszValueName
, lpszValue
);
1182 LONG
SetKeyValue(LPCTSTR lpszKeyName
, LPCTSTR lpszValue
,
1183 LPCTSTR lpszValueName
= NULL
) throw()
1186 LONG lRet
= key
.Create(m_hKey
, lpszKeyName
);
1187 if (lRet
== ERROR_SUCCESS
)
1189 lRet
= key
.SetStringValue(lpszValueName
, lpszValue
);
1194 LONG
DeleteValue(LPCTSTR lpszValue
) throw()
1197 return ::RegDeleteValue(m_hKey
, lpszValue
);
1200 LONG
DeleteSubKey(LPCTSTR lpszSubKey
) throw()
1203 ATLASSERT(lpszSubKey
);
1204 return ::RegDeleteKey(m_hKey
, lpszSubKey
);
1207 LONG
RecurseDeleteKey(LPCTSTR lpszKey
) throw()
1211 return CRegKey::_DoDeleteKeyTree(m_hKey
, lpszKey
);
1214 LONG
EnumKey(DWORD iIndex
, LPTSTR pszName
, LPDWORD pnNameLength
,
1215 FILETIME
* pftLastWriteTime
= NULL
) throw()
1218 LONG ret
= ::RegEnumKeyEx(m_hKey
, iIndex
, pszName
, pnNameLength
, NULL
,
1219 NULL
, NULL
, pftLastWriteTime
);
1223 LONG
GetKeySecurity(SECURITY_INFORMATION si
, PSECURITY_DESCRIPTOR psd
,
1224 LPDWORD pnBytes
) throw()
1227 LONG ret
= ::RegGetKeySecurity(m_hKey
, si
, psd
, pnBytes
);
1231 LONG
SetKeySecurity(SECURITY_INFORMATION si
,
1232 PSECURITY_DESCRIPTOR psd
) throw()
1235 LONG ret
= ::RegSetKeySecurity(m_hKey
, si
, psd
);
1239 operator HKEY() const throw()
1244 CRegKey
& operator=(CRegKey
& key
) throw()
1246 Attach(key
.Detach());
1251 // get the total size of a multistring
1252 static ULONG
_GetMultiStringSize(LPCTSTR pszz
)
1257 int len
= _tcslen(pszz
);
1260 } while (*pszz
!= TEXT('\0'));
1262 return count
* sizeof(TCHAR
);
1265 // delete key recursively
1266 static LONG
_DoDeleteKeyTree(HKEY hParentKey
, LPCTSTR lpszKey
)
1268 ATLASSERT(hParentKey
);
1273 LONG ret
= key
.Open(hParentKey
, lpszKey
);
1274 if (ret
!= ERROR_SUCCESS
)
1276 return ret
; // failure
1279 // get the longest length of subkey names
1281 ret
= ::RegQueryInfoKey(key
, NULL
, NULL
, NULL
, NULL
, &NameMax
, NULL
,
1282 NULL
, NULL
, NULL
, NULL
, NULL
);
1283 if (ret
!= ERROR_SUCCESS
)
1285 return ret
; // failure
1287 ++NameMax
; // for NUL
1289 // allocate the string buffer for names if necessary
1290 TCHAR szNameBuf
[MAX_PATH
], *pszName
;
1291 if (NameMax
> MAX_PATH
)
1293 pszName
= (TCHAR
*)malloc(NameMax
* sizeof(TCHAR
));
1295 if (pszName
== NULL
)
1297 return ERROR_OUTOFMEMORY
; // failure
1303 pszName
= szNameBuf
;
1306 // enumerate every subkey and delete
1309 DWORD Count
= NameMax
;
1310 ret
= key
.EnumKey(0, pszName
, &Count
);
1311 if (ret
!= ERROR_SUCCESS
)
1313 if (ret
== ERROR_NO_MORE_ITEMS
)
1314 ret
= ERROR_SUCCESS
;
1318 ret
= CRegKey::_DoDeleteKeyTree(key
, pszName
);
1319 if (ret
!= ERROR_SUCCESS
)
1326 // delete the subkey
1327 if (ret
== ERROR_SUCCESS
)
1328 ret
= ::RegDeleteKey(hParentKey
, lpszKey
);
1330 // delete the buffer if any
1331 if (pszName
!= szNameBuf
)
1339 class CComHeapPtr
: public CHeapPtr
<T
, CComAllocator
>
1346 explicit CComHeapPtr(T
*lp
) :
1347 CHeapPtr
<T
, CComAllocator
>(lp
)
1353 inline HRESULT __stdcall
AtlAdvise(IUnknown
*pUnkCP
, IUnknown
*pUnk
, const IID
&iid
, LPDWORD pdw
)
1355 CComPtr
<IConnectionPointContainer
> container
;
1356 CComPtr
<IConnectionPoint
> connectionPoint
;
1360 return E_INVALIDARG
;
1361 hResult
= pUnkCP
->QueryInterface(IID_IConnectionPointContainer
, (void **)&container
);
1362 if (FAILED(hResult
))
1364 hResult
= container
->FindConnectionPoint(iid
, &connectionPoint
);
1365 if (FAILED(hResult
))
1367 return connectionPoint
->Advise(pUnk
, pdw
);
1370 inline HRESULT __stdcall
AtlUnadvise(IUnknown
*pUnkCP
, const IID
&iid
, DWORD dw
)
1372 CComPtr
<IConnectionPointContainer
> container
;
1373 CComPtr
<IConnectionPoint
> connectionPoint
;
1377 return E_INVALIDARG
;
1378 hResult
= pUnkCP
->QueryInterface(IID_IConnectionPointContainer
, (void **)&container
);
1379 if (FAILED(hResult
))
1381 hResult
= container
->FindConnectionPoint(iid
, &connectionPoint
);
1382 if (FAILED(hResult
))
1384 return connectionPoint
->Unadvise(dw
);
1387 inline HRESULT __stdcall
AtlInternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
)
1390 IUnknown
*resultInterface
;
1393 ATLASSERT(pThis
!= NULL
&& pEntries
!= NULL
);
1394 if (pThis
== NULL
|| pEntries
== NULL
)
1395 return E_INVALIDARG
;
1396 ATLASSERT(ppvObject
!= NULL
);
1397 if (ppvObject
== NULL
)
1400 if (InlineIsEqualUnknown(iid
))
1402 resultInterface
= reinterpret_cast<IUnknown
*>(reinterpret_cast<char *>(pThis
) + pEntries
[0].dw
);
1403 *ppvObject
= resultInterface
;
1404 resultInterface
->AddRef();
1409 while (pEntries
[i
].pFunc
!= 0)
1411 if (pEntries
[i
].piid
== NULL
|| InlineIsEqualGUID(iid
, *pEntries
[i
].piid
))
1413 if (pEntries
[i
].pFunc
== reinterpret_cast<_ATL_CREATORARGFUNC
*>(1))
1415 ATLASSERT(pEntries
[i
].piid
!= NULL
);
1416 resultInterface
= reinterpret_cast<IUnknown
*>(reinterpret_cast<char *>(pThis
) + pEntries
[i
].dw
);
1417 *ppvObject
= resultInterface
;
1418 resultInterface
->AddRef();
1423 hResult
= pEntries
[i
].pFunc(pThis
, iid
, ppvObject
, 0);
1424 if (hResult
== S_OK
|| (FAILED(hResult
) && pEntries
[i
].piid
!= NULL
))
1432 return E_NOINTERFACE
;
1435 inline HRESULT __stdcall
AtlWinModuleInit(_ATL_WIN_MODULE
*pWinModule
)
1437 if (pWinModule
== NULL
)
1438 return E_INVALIDARG
;
1439 pWinModule
->m_pCreateWndList
= NULL
;
1440 return pWinModule
->m_csWindowCreate
.Init();
1443 inline HRESULT __stdcall
AtlWinModuleTerm(_ATL_WIN_MODULE
*pWinModule
, HINSTANCE hInst
)
1445 if (pWinModule
== NULL
)
1446 return E_INVALIDARG
;
1447 pWinModule
->m_csWindowCreate
.Term();
1451 inline void __stdcall
AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE
*pWinModule
, _AtlCreateWndData
*pData
, void *pObject
)
1453 CComCritSecLock
<CComCriticalSection
> lock(pWinModule
->m_csWindowCreate
, true);
1455 ATLASSERT(pWinModule
!= NULL
);
1456 ATLASSERT(pObject
!= NULL
);
1458 pData
->m_pThis
= pObject
;
1459 pData
->m_dwThreadID
= ::GetCurrentThreadId();
1460 pData
->m_pNext
= pWinModule
->m_pCreateWndList
;
1461 pWinModule
->m_pCreateWndList
= pData
;
1464 inline void *__stdcall
AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE
*pWinModule
)
1466 CComCritSecLock
<CComCriticalSection
> lock(pWinModule
->m_csWindowCreate
, true);
1468 _AtlCreateWndData
*currentEntry
;
1469 _AtlCreateWndData
**previousLink
;
1472 ATLASSERT(pWinModule
!= NULL
);
1475 threadID
= GetCurrentThreadId();
1476 currentEntry
= pWinModule
->m_pCreateWndList
;
1477 previousLink
= &pWinModule
->m_pCreateWndList
;
1478 while (currentEntry
!= NULL
)
1480 if (currentEntry
->m_dwThreadID
== threadID
)
1482 *previousLink
= currentEntry
->m_pNext
;
1483 result
= currentEntry
->m_pThis
;
1486 previousLink
= ¤tEntry
->m_pNext
;
1487 currentEntry
= currentEntry
->m_pNext
;
1492 // Adapted from dll/win32/atl/atl.c
1493 inline HRESULT WINAPI
AtlLoadTypeLib(HINSTANCE inst
, LPCOLESTR lpszIndex
,
1494 BSTR
*pbstrPath
, ITypeLib
**ppTypeLib
)
1496 size_t index_len
= lpszIndex
? wcslen(lpszIndex
) : 0;
1497 CComHeapPtr
<WCHAR
> path
;
1498 path
.Allocate(MAX_PATH
+ index_len
+ wcslen(L
".tlb"));
1501 return E_OUTOFMEMORY
;
1503 size_t path_len
= GetModuleFileNameW(inst
, path
, MAX_PATH
);
1505 return HRESULT_FROM_WIN32(GetLastError());
1508 wcscat(path
, lpszIndex
);
1510 CComPtr
<ITypeLib
> typelib
;
1511 HRESULT hResult
= LoadTypeLib(path
, &typelib
);
1512 if (FAILED(hResult
))
1515 for (ptr
= path
+path_len
-1; ptr
> path
&& *ptr
!= '\\' && *ptr
!= '.'; ptr
--)
1518 ptr
= (WCHAR
*)path
+ path_len
;
1519 wcscpy(ptr
, L
".tlb");
1521 hResult
= LoadTypeLib(path
, &typelib
);
1524 if (SUCCEEDED(hResult
))
1526 *pbstrPath
= SysAllocString(path
);
1530 hResult
= E_OUTOFMEMORY
;
1534 if (FAILED(hResult
))
1537 *ppTypeLib
= typelib
.Detach();
1541 // Adapted from dll/win32/atl/atl.c
1542 inline HRESULT WINAPI
AtlRegisterTypeLib(HINSTANCE inst
, const WCHAR
*index
)
1545 CComPtr
<ITypeLib
> typelib
;
1546 HRESULT hResult
= AtlLoadTypeLib(inst
, index
, &path
, &typelib
);
1547 if (FAILED(hResult
))
1550 return RegisterTypeLib(typelib
, path
, NULL
); /* FIXME: pass help directory */
1553 // Adapted from dll/win32/atl/atl.c
1554 inline HRESULT WINAPI
AtlRegisterClassCategoriesHelper(REFCLSID clsid
, const _ATL_CATMAP_ENTRY
*catmap
, BOOL reg
)
1559 CComPtr
<ICatRegister
> catreg
;
1561 HRESULT hResult
= CoCreateInstance(CLSID_StdComponentCategoriesMgr
, NULL
, CLSCTX_INPROC_SERVER
, IID_ICatRegister
, (void**)&catreg
);
1562 if (FAILED(hResult
))
1565 for (const _ATL_CATMAP_ENTRY
*iter
= catmap
; iter
->iType
!= _ATL_CATMAP_ENTRY_END
; iter
++)
1567 CATID catid
= *iter
->pcatid
;
1569 if (iter
->iType
== _ATL_CATMAP_ENTRY_IMPLEMENTED
)
1572 hResult
= catreg
->RegisterClassImplCategories(clsid
, 1, &catid
);
1574 hResult
= catreg
->UnRegisterClassImplCategories(clsid
, 1, &catid
);
1579 hResult
= catreg
->RegisterClassReqCategories(clsid
, 1, &catid
);
1581 hResult
= catreg
->UnRegisterClassReqCategories(clsid
, 1, &catid
);
1583 if (FAILED(hResult
))
1589 WCHAR reg_path
[256] = L
"CLSID\\";
1591 StringFromGUID2(clsid
, reg_path
+ wcslen(reg_path
), 64);
1592 wcscat(reg_path
, L
"\\");
1593 WCHAR
* ptr
= reg_path
+ wcslen(reg_path
);
1595 wcscpy(ptr
, L
"Implemented Categories");
1596 RegDeleteKeyW(HKEY_CLASSES_ROOT
, reg_path
);
1598 wcscpy(ptr
, L
"Required Categories");
1599 RegDeleteKeyW(HKEY_CLASSES_ROOT
, reg_path
);
1606 // Adapted from dll/win32/atl80/atl80.c
1607 inline HRESULT __stdcall
AtlComModuleRegisterServer(_ATL_COM_MODULE
*mod
, BOOL bRegTypeLib
, const CLSID
*clsid
)
1609 HRESULT hResult
= S_OK
;
1611 for (_ATL_OBJMAP_ENTRY
** iter
= mod
->m_ppAutoObjMapFirst
; iter
< mod
->m_ppAutoObjMapLast
; iter
++)
1615 _ATL_OBJMAP_ENTRY
* entry
= *iter
;
1616 if (clsid
&& !IsEqualCLSID(*entry
->pclsid
, *clsid
))
1619 hResult
= entry
->pfnUpdateRegistry(TRUE
);
1620 if (FAILED(hResult
))
1623 const _ATL_CATMAP_ENTRY
*catmap
= entry
->pfnGetCategoryMap();
1626 hResult
= AtlRegisterClassCategoriesHelper(*entry
->pclsid
, catmap
, TRUE
);
1627 if (FAILED(hResult
))
1634 hResult
= AtlRegisterTypeLib(mod
->m_hInstTypeLib
, NULL
);
1640 // Adapted from dll/win32/atl/atl.c
1641 inline HRESULT WINAPI
AtlComModuleUnregisterServer(_ATL_COM_MODULE
*mod
, BOOL bUnRegTypeLib
, const CLSID
*clsid
)
1643 HRESULT hResult
= S_OK
;
1645 for (_ATL_OBJMAP_ENTRY
**iter
= mod
->m_ppAutoObjMapFirst
; iter
< mod
->m_ppAutoObjMapLast
; iter
++)
1649 _ATL_OBJMAP_ENTRY
* entry
= *iter
;
1650 if (clsid
&& !IsEqualCLSID(*entry
->pclsid
, *clsid
))
1653 const _ATL_CATMAP_ENTRY
*catmap
= entry
->pfnGetCategoryMap();
1656 hResult
= AtlRegisterClassCategoriesHelper(*entry
->pclsid
, catmap
, FALSE
);
1657 if (FAILED(hResult
))
1661 hResult
= entry
->pfnUpdateRegistry(FALSE
);
1662 if (FAILED(hResult
))
1668 CComPtr
<ITypeLib
> typelib
;
1672 hResult
= AtlLoadTypeLib(mod
->m_hInstTypeLib
, NULL
, &path
, &typelib
);
1673 if (FAILED(hResult
))
1676 hResult
= typelib
->GetLibAttr(&attr
);
1677 if (SUCCEEDED(hResult
))
1679 hResult
= UnRegisterTypeLib(attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, attr
->lcid
, attr
->syskind
);
1680 typelib
->ReleaseTLibAttr(attr
);
1690 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
1691 using namespace ATL
;
1692 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE