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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 // It is common to use this in ATL constructors. They only store this for later use, so the usage is safe.
29 #pragma warning(disable:4355)
33 #define _ATL_PACKING 8
36 #ifndef _ATL_FREE_THREADED
37 #ifndef _ATL_APARTMENT_THREADED
38 #ifndef _ATL_SINGLE_THREADED
39 #define _ATL_FREE_THREADED
48 #ifdef _ATL_DISABLE_NO_VTABLE
51 #define ATL_NO_VTABLE __declspec(novtable)
54 #define offsetofclass(base, derived) (reinterpret_cast<DWORD_PTR>(static_cast<base *>(reinterpret_cast<derived *>(_ATL_PACKING))) - _ATL_PACKING)
56 extern "C" IMAGE_DOS_HEADER __ImageBase
;
64 __declspec(selectany
) CAtlModule
*_pAtlModule
= NULL
;
65 __declspec(selectany
) CComModule
*_pModule
= NULL
;
66 extern CAtlComModule _AtlComModule
;
68 typedef HRESULT (WINAPI _ATL_CREATORFUNC
)(void *pv
, REFIID riid
, LPVOID
*ppv
);
69 typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC
)();
70 typedef const struct _ATL_CATMAP_ENTRY
* (_ATL_CATMAPFUNC
)();
72 struct _ATL_OBJMAP_ENTRY30
75 HRESULT (WINAPI
*pfnUpdateRegistry
)(BOOL bRegister
);
76 _ATL_CREATORFUNC
*pfnGetClassObject
;
77 _ATL_CREATORFUNC
*pfnCreateInstance
;
80 _ATL_DESCRIPTIONFUNC
*pfnGetObjectDescription
;
81 _ATL_CATMAPFUNC
*pfnGetCategoryMap
;
82 void (WINAPI
*pfnObjectMain
)(bool bStarting
);
84 HRESULT WINAPI
RevokeClassObject()
88 return CoRevokeClassObject(dwRegister
);
91 HRESULT WINAPI
RegisterClassObject(DWORD dwClsContext
, DWORD dwFlags
)
97 if (pfnGetClassObject
== NULL
)
100 hResult
= pfnGetClassObject(reinterpret_cast<LPVOID
*>(pfnCreateInstance
), IID_IUnknown
, reinterpret_cast<LPVOID
*>(&p
));
101 if (SUCCEEDED(hResult
))
102 hResult
= CoRegisterClassObject(*pclsid
, p
, dwClsContext
, dwFlags
, &dwRegister
);
111 typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY
;
113 typedef void (__stdcall _ATL_TERMFUNC
)(DWORD_PTR dw
);
115 struct _ATL_TERMFUNC_ELEM
117 _ATL_TERMFUNC
*pFunc
;
119 _ATL_TERMFUNC_ELEM
*pNext
;
126 _ATL_TERMFUNC_ELEM
*m_pTermFuncs
;
127 CComCriticalSection m_csStaticDataInitAndTypeInfo
;
129 typedef _ATL_MODULE70 _ATL_MODULE
;
131 typedef HRESULT (WINAPI _ATL_CREATORARGFUNC
)(void *pv
, REFIID riid
, LPVOID
*ppv
, DWORD_PTR dw
);
133 #define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC *)1)
135 struct _ATL_INTMAP_ENTRY
139 _ATL_CREATORARGFUNC
*pFunc
;
142 struct _AtlCreateWndData
146 _AtlCreateWndData
*m_pNext
;
149 struct _ATL_COM_MODULE70
152 HINSTANCE m_hInstTypeLib
;
153 _ATL_OBJMAP_ENTRY
**m_ppAutoObjMapFirst
;
154 _ATL_OBJMAP_ENTRY
**m_ppAutoObjMapLast
;
155 CComCriticalSection m_csObjMap
;
157 typedef _ATL_COM_MODULE70 _ATL_COM_MODULE
;
159 struct _ATL_WIN_MODULE70
162 CComCriticalSection m_csWindowCreate
;
163 _AtlCreateWndData
*m_pCreateWndList
;
165 CSimpleArray
<ATOM
> m_rgWindowClassAtoms
;
168 typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE
;
170 struct _ATL_REGMAP_ENTRY
176 HRESULT __stdcall
AtlWinModuleInit(_ATL_WIN_MODULE
*pWinModule
);
177 HRESULT __stdcall
AtlWinModuleTerm(_ATL_WIN_MODULE
*pWinModule
, HINSTANCE hInst
);
178 HRESULT __stdcall
AtlInternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
);
179 void __stdcall
AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE
*pWinModule
, _AtlCreateWndData
*pData
, void *pObject
);
180 void *__stdcall
AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE
*pWinModule
);
181 HRESULT __stdcall
AtlComModuleGetClassObject(_ATL_COM_MODULE
*pComModule
, REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
);
183 template<class TLock
>
184 class CComCritSecLock
190 CComCritSecLock(TLock
&cs
, bool bInitialLock
= true) : m_cs(cs
)
215 ATLASSERT(!m_bLocked
);
216 hResult
= m_cs
.Lock();
228 ATLASSERT(m_bLocked
);
229 hResult
= m_cs
.Unlock();
238 inline BOOL WINAPI
InlineIsEqualUnknown(REFGUID rguid1
)
241 ((unsigned long *)&rguid1
)[0] == 0 &&
242 ((unsigned long *)&rguid1
)[1] == 0 &&
243 ((unsigned long *)&rguid1
)[2] == 0x000000C0 &&
244 ((unsigned long *)&rguid1
)[3] == 0x46000000);
247 inline BOOL WINAPI
InlineIsEqualGUID(REFGUID rguid1
, REFGUID rguid2
)
250 ((unsigned long *)&rguid1
)[0] == ((unsigned long *)&rguid2
)[0] &&
251 ((unsigned long *)&rguid1
)[1] == ((unsigned long *)&rguid2
)[1] &&
252 ((unsigned long *)&rguid1
)[2] == ((unsigned long *)&rguid2
)[2] &&
253 ((unsigned long *)&rguid1
)[3] == ((unsigned long *)&rguid2
)[3]);
256 class CComMultiThreadModelNoCS
259 typedef CComFakeCriticalSection AutoCriticalSection
;
260 typedef CComFakeCriticalSection CriticalSection
;
261 typedef CComMultiThreadModelNoCS ThreadModelNoCS
;
262 typedef CComFakeCriticalSection AutoDeleteCriticalSection
;
264 static ULONG WINAPI
Increment(LPLONG p
)
266 return InterlockedIncrement(p
);
269 static ULONG WINAPI
Decrement(LPLONG p
)
271 return InterlockedDecrement(p
);
275 class CComMultiThreadModel
278 typedef CComAutoCriticalSection AutoCriticalSection
;
279 typedef CComCriticalSection CriticalSection
;
280 typedef CComMultiThreadModelNoCS ThreadModelNoCS
;
281 typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection
;
283 static ULONG WINAPI
Increment(LPLONG p
)
285 return InterlockedIncrement(p
);
288 static ULONG WINAPI
Decrement(LPLONG p
)
290 return InterlockedDecrement(p
);
294 class CComSingleThreadModel
297 typedef CComFakeCriticalSection AutoCriticalSection
;
298 typedef CComFakeCriticalSection CriticalSection
;
299 typedef CComSingleThreadModel ThreadModelNoCS
;
300 typedef CComFakeCriticalSection AutoDeleteCriticalSection
;
302 static ULONG WINAPI
Increment(LPLONG p
)
307 static ULONG WINAPI
Decrement(LPLONG p
)
313 #if defined(_ATL_FREE_THREADED)
315 typedef CComMultiThreadModel CComObjectThreadModel
;
316 typedef CComMultiThreadModel CComGlobalsThreadModel
;
318 #elif defined(_ATL_APARTMENT_THREADED)
320 typedef CComSingleThreadModel CComObjectThreadModel
;
321 typedef CComMultiThreadModel CComGlobalsThreadModel
;
323 #elif defined(_ATL_SINGLE_THREADED)
325 typedef CComSingleThreadModel CComObjectThreadModel
;
326 typedef CComSingleThreadModel CComGlobalsThreadModel
;
329 #error No threading model
332 class CAtlModule
: public _ATL_MODULE
337 ATLASSERT(_pAtlModule
== NULL
);
339 cbSize
= sizeof(_ATL_MODULE
);
343 virtual LONG
GetLockCount()
350 return CComGlobalsThreadModel::Increment(&m_nLockCnt
);
353 virtual LONG
Unlock()
355 return CComGlobalsThreadModel::Decrement(&m_nLockCnt
);
358 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
* /*pRegistrar*/) = 0;
360 HRESULT WINAPI
UpdateRegistryFromResource(LPCTSTR lpszRes
, BOOL bRegister
, struct _ATL_REGMAP_ENTRY
*pMapEntries
= NULL
)
362 CRegObject registrar
;
363 TCHAR modulePath
[MAX_PATH
];
366 hResult
= CommonInitRegistrar(registrar
, modulePath
, sizeof(modulePath
) / sizeof(modulePath
[0]), pMapEntries
);
370 if (bRegister
!= FALSE
)
371 hResult
= registrar
.ResourceRegisterSz(modulePath
, lpszRes
, _T("REGISTRY"));
373 hResult
= registrar
.ResourceUnregisterSz(modulePath
, lpszRes
, _T("REGISTRY"));
378 HRESULT WINAPI
UpdateRegistryFromResource(UINT nResID
, BOOL bRegister
, struct _ATL_REGMAP_ENTRY
*pMapEntries
= NULL
)
380 CRegObject registrar
;
381 TCHAR modulePath
[MAX_PATH
];
384 hResult
= CommonInitRegistrar(registrar
, modulePath
, sizeof(modulePath
) / sizeof(modulePath
[0]), pMapEntries
);
388 if (bRegister
!= FALSE
)
389 hResult
= registrar
.ResourceRegister(modulePath
, nResID
, _T("REGISTRY"));
391 hResult
= registrar
.ResourceRegister(modulePath
, nResID
, _T("REGISTRY"));
397 HRESULT
CommonInitRegistrar(CRegObject
®istrar
, TCHAR
*modulePath
, DWORD modulePathCount
, struct _ATL_REGMAP_ENTRY
*pMapEntries
)
403 hInstance
= _AtlBaseModule
.GetModuleInstance();
404 dwFLen
= GetModuleFileName(hInstance
, modulePath
, modulePathCount
);
405 if (dwFLen
== modulePathCount
)
406 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
407 else if (dwFLen
== 0)
408 return HRESULT_FROM_WIN32(GetLastError());
410 if (pMapEntries
!= NULL
)
412 while (pMapEntries
->szKey
!= NULL
)
414 ATLASSERT(pMapEntries
->szData
!= NULL
);
415 hResult
= registrar
.AddReplacement(pMapEntries
->szKey
, pMapEntries
->szData
);
422 hResult
= AddCommonRGSReplacements(®istrar
);
426 hResult
= registrar
.AddReplacement(_T("Module"), modulePath
);
430 hResult
= registrar
.AddReplacement(_T("Module_Raw"), modulePath
);
439 class CAtlModuleT
: public CAtlModule
443 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
*pRegistrar
)
445 return pRegistrar
->AddReplacement(L
"APPID", T::GetAppId());
448 static LPCOLESTR
GetAppId()
454 class CAtlComModule
: public _ATL_COM_MODULE
459 m_hInstTypeLib
= reinterpret_cast<HINSTANCE
>(&__ImageBase
);
460 m_ppAutoObjMapFirst
= NULL
;
461 m_ppAutoObjMapLast
= NULL
;
462 if (FAILED(m_csObjMap
.Init()))
465 CAtlBaseModule::m_bInitFailed
= true;
468 cbSize
= sizeof(_ATL_COM_MODULE
);
480 ATLASSERT(m_ppAutoObjMapFirst
== NULL
);
481 ATLASSERT(m_ppAutoObjMapLast
== NULL
);
489 class CAtlDllModuleT
: public CAtlModuleT
<T
>
496 HRESULT
DllCanUnloadNow()
500 pThis
= static_cast<T
*>(this);
501 if (pThis
->GetLockCount() == 0)
506 HRESULT
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
510 pThis
= static_cast<T
*>(this);
511 return pThis
->GetClassObject(rclsid
, riid
, ppv
);
514 HRESULT
DllRegisterServer(BOOL bRegTypeLib
= TRUE
)
519 pThis
= static_cast<T
*>(this);
520 hResult
= pThis
->RegisterServer(bRegTypeLib
);
524 HRESULT
DllUnregisterServer(BOOL bUnRegTypeLib
= TRUE
)
529 pThis
= static_cast<T
*>(this);
530 hResult
= pThis
->UnregisterServer(bUnRegTypeLib
);
534 HRESULT
GetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
536 return AtlComModuleGetClassObject(&_AtlComModule
, rclsid
, riid
, ppv
);
540 class CComModule
: public CAtlModuleT
<CComModule
>
543 _ATL_OBJMAP_ENTRY
*m_pObjMap
;
547 ATLASSERT(_pModule
== NULL
);
556 HRESULT
GetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
558 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
561 ATLASSERT(ppv
!= NULL
);
565 if (m_pObjMap
!= NULL
)
567 objectMapEntry
= m_pObjMap
;
568 while (objectMapEntry
->pclsid
!= NULL
)
570 if (objectMapEntry
->pfnGetClassObject
!= NULL
&& InlineIsEqualGUID(rclsid
, *objectMapEntry
->pclsid
) != FALSE
)
572 if (objectMapEntry
->pCF
== NULL
)
574 CComCritSecLock
<CComCriticalSection
> lock(_AtlComModule
.m_csObjMap
, true);
576 if (objectMapEntry
->pCF
== NULL
)
577 hResult
= objectMapEntry
->pfnGetClassObject(reinterpret_cast<void *>(objectMapEntry
->pfnCreateInstance
), IID_IUnknown
, reinterpret_cast<LPVOID
*>(&objectMapEntry
->pCF
));
579 if (objectMapEntry
->pCF
!= NULL
)
580 hResult
= objectMapEntry
->pCF
->QueryInterface(riid
, ppv
);
589 HRESULT
RegisterServer(BOOL bRegTypeLib
= FALSE
, const CLSID
*pCLSID
= NULL
)
591 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
595 objectMapEntry
= m_pObjMap
;
596 if (objectMapEntry
!= NULL
)
598 while (objectMapEntry
->pclsid
!= NULL
)
600 if (pCLSID
== NULL
|| IsEqualGUID(*pCLSID
, *objectMapEntry
->pclsid
) != FALSE
)
602 hResult
= objectMapEntry
->pfnUpdateRegistry(TRUE
);
612 HRESULT
UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
= NULL
)
614 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
618 objectMapEntry
= m_pObjMap
;
619 if (objectMapEntry
!= NULL
)
621 while (objectMapEntry
->pclsid
!= NULL
)
623 if (pCLSID
== NULL
|| IsEqualGUID(*pCLSID
, *objectMapEntry
->pclsid
) != FALSE
)
625 hResult
= objectMapEntry
->pfnUpdateRegistry(FALSE
); //unregister
635 HRESULT
DllCanUnloadNow()
637 if (GetLockCount() == 0)
642 HRESULT
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
644 return GetClassObject(rclsid
, riid
, ppv
);
647 HRESULT
DllRegisterServer(BOOL bRegTypeLib
= TRUE
)
649 return RegisterServer(bRegTypeLib
);
652 HRESULT
DllUnregisterServer(BOOL bUnRegTypeLib
= TRUE
)
654 return UnregisterServer(bUnRegTypeLib
);
659 class CAtlWinModule
: public _ATL_WIN_MODULE
666 hResult
= AtlWinModuleInit(this);
669 CAtlBaseModule::m_bInitFailed
= true;
681 AtlWinModuleTerm(this, _AtlBaseModule
.GetModuleInstance());
684 void AddCreateWndData(_AtlCreateWndData
*pData
, void *pObject
)
686 AtlWinModuleAddCreateWndData(this, pData
, pObject
);
689 void *ExtractCreateWndData()
691 return AtlWinModuleExtractCreateWndData(this);
695 extern CAtlWinModule _AtlWinModule
;
715 CComPtr(const CComPtr
<T
> &lp
)
728 T
*operator = (T
*lp
)
738 T
*operator = (const CComPtr
<T
> &lp
)
775 ATLASSERT(p
== NULL
);
786 ATLASSERT(p
!= NULL
);
796 CComBSTR(LPCOLESTR pSrc
)
801 m_str
= ::SysAllocString(pSrc
);
805 ::SysFreeString(m_str
);
810 class CComVariant
: public tagVARIANT
825 return ::VariantClear(this);
829 inline HRESULT __stdcall
AtlAdvise(IUnknown
*pUnkCP
, IUnknown
*pUnk
, const IID
&iid
, LPDWORD pdw
)
831 CComPtr
<IConnectionPointContainer
> container
;
832 CComPtr
<IConnectionPoint
> connectionPoint
;
837 hResult
= pUnkCP
->QueryInterface(IID_IConnectionPointContainer
, (void **)&container
);
840 hResult
= container
->FindConnectionPoint(iid
, &connectionPoint
);
843 return connectionPoint
->Advise(pUnk
, pdw
);
846 inline HRESULT __stdcall
AtlUnadvise(IUnknown
*pUnkCP
, const IID
&iid
, DWORD dw
)
848 CComPtr
<IConnectionPointContainer
> container
;
849 CComPtr
<IConnectionPoint
> connectionPoint
;
854 hResult
= pUnkCP
->QueryInterface(IID_IConnectionPointContainer
, (void **)&container
);
857 hResult
= container
->FindConnectionPoint(iid
, &connectionPoint
);
860 return connectionPoint
->Unadvise(dw
);
863 inline HRESULT __stdcall
AtlInternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
)
866 IUnknown
*resultInterface
;
869 ATLASSERT(pThis
!= NULL
&& pEntries
!= NULL
);
870 if (pThis
== NULL
|| pEntries
== NULL
)
872 ATLASSERT(ppvObject
!= NULL
);
873 if (ppvObject
== NULL
)
876 if (InlineIsEqualUnknown(iid
))
878 resultInterface
= reinterpret_cast<IUnknown
*>(reinterpret_cast<char *>(pThis
) + pEntries
[0].dw
);
879 *ppvObject
= resultInterface
;
880 resultInterface
->AddRef();
885 while (pEntries
[i
].pFunc
!= 0)
887 if (pEntries
[i
].piid
== NULL
|| InlineIsEqualGUID(iid
, *pEntries
[i
].piid
))
889 if (pEntries
[i
].pFunc
== reinterpret_cast<_ATL_CREATORARGFUNC
*>(1))
891 ATLASSERT(pEntries
[i
].piid
!= NULL
);
892 resultInterface
= reinterpret_cast<IUnknown
*>(reinterpret_cast<char *>(pThis
) + pEntries
[i
].dw
);
893 *ppvObject
= resultInterface
;
894 resultInterface
->AddRef();
899 hResult
= pEntries
[i
].pFunc(pThis
, iid
, ppvObject
, 0);
900 if (hResult
== S_OK
|| (FAILED(hResult
) && pEntries
[i
].piid
!= NULL
))
908 return E_NOINTERFACE
;
911 inline HRESULT __stdcall
AtlWinModuleInit(_ATL_WIN_MODULE
*pWinModule
)
913 if (pWinModule
== NULL
)
915 pWinModule
->m_pCreateWndList
= NULL
;
916 return pWinModule
->m_csWindowCreate
.Init();
919 inline HRESULT __stdcall
AtlWinModuleTerm(_ATL_WIN_MODULE
*pWinModule
, HINSTANCE hInst
)
921 if (pWinModule
== NULL
)
923 pWinModule
->m_csWindowCreate
.Term();
927 inline void __stdcall
AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE
*pWinModule
, _AtlCreateWndData
*pData
, void *pObject
)
929 CComCritSecLock
<CComCriticalSection
> lock(pWinModule
->m_csWindowCreate
, true);
931 ATLASSERT(pWinModule
!= NULL
);
932 ATLASSERT(pObject
!= NULL
);
934 pData
->m_pThis
= pObject
;
935 pData
->m_dwThreadID
= ::GetCurrentThreadId();
936 pData
->m_pNext
= pWinModule
->m_pCreateWndList
;
937 pWinModule
->m_pCreateWndList
= pData
;
940 inline void *__stdcall
AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE
*pWinModule
)
942 CComCritSecLock
<CComCriticalSection
> lock(pWinModule
->m_csWindowCreate
, true);
944 _AtlCreateWndData
*currentEntry
;
945 _AtlCreateWndData
**previousLink
;
948 ATLASSERT(pWinModule
!= NULL
);
951 threadID
= GetCurrentThreadId();
952 currentEntry
= pWinModule
->m_pCreateWndList
;
953 previousLink
= &pWinModule
->m_pCreateWndList
;
954 while (currentEntry
!= NULL
)
956 if (currentEntry
->m_dwThreadID
== threadID
)
958 *previousLink
= currentEntry
->m_pNext
;
959 result
= currentEntry
->m_pThis
;
962 previousLink
= ¤tEntry
->m_pNext
;
963 currentEntry
= currentEntry
->m_pNext
;
970 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
972 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE