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"
29 // It is common to use this in ATL constructors. They only store this for later use, so the usage is safe.
30 #pragma warning(disable:4355)
34 #define _ATL_PACKING 8
37 #ifndef _ATL_FREE_THREADED
38 #ifndef _ATL_APARTMENT_THREADED
39 #ifndef _ATL_SINGLE_THREADED
40 #define _ATL_FREE_THREADED
49 #ifdef _ATL_DISABLE_NO_VTABLE
52 #define ATL_NO_VTABLE __declspec(novtable)
55 #define offsetofclass(base, derived) (reinterpret_cast<DWORD_PTR>(static_cast<base *>(reinterpret_cast<derived *>(_ATL_PACKING))) - _ATL_PACKING)
63 __declspec(selectany
) CAtlModule
*_pAtlModule
= NULL
;
64 __declspec(selectany
) CComModule
*_pModule
= NULL
;
65 extern CAtlComModule _AtlComModule
;
67 typedef HRESULT (WINAPI _ATL_CREATORFUNC
)(void *pv
, REFIID riid
, LPVOID
*ppv
);
68 typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC
)();
69 typedef const struct _ATL_CATMAP_ENTRY
* (_ATL_CATMAPFUNC
)();
71 struct _ATL_OBJMAP_ENTRY30
74 HRESULT (WINAPI
*pfnUpdateRegistry
)(BOOL bRegister
);
75 _ATL_CREATORFUNC
*pfnGetClassObject
;
76 _ATL_CREATORFUNC
*pfnCreateInstance
;
79 _ATL_DESCRIPTIONFUNC
*pfnGetObjectDescription
;
80 _ATL_CATMAPFUNC
*pfnGetCategoryMap
;
81 void (WINAPI
*pfnObjectMain
)(bool bStarting
);
83 HRESULT WINAPI
RevokeClassObject()
87 return CoRevokeClassObject(dwRegister
);
90 HRESULT WINAPI
RegisterClassObject(DWORD dwClsContext
, DWORD dwFlags
)
96 if (pfnGetClassObject
== NULL
)
99 hResult
= pfnGetClassObject(reinterpret_cast<LPVOID
*>(pfnCreateInstance
), IID_IUnknown
, reinterpret_cast<LPVOID
*>(&p
));
100 if (SUCCEEDED(hResult
))
101 hResult
= CoRegisterClassObject(*pclsid
, p
, dwClsContext
, dwFlags
, &dwRegister
);
110 typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY
;
112 typedef void (__stdcall _ATL_TERMFUNC
)(DWORD_PTR dw
);
114 struct _ATL_TERMFUNC_ELEM
116 _ATL_TERMFUNC
*pFunc
;
118 _ATL_TERMFUNC_ELEM
*pNext
;
125 _ATL_TERMFUNC_ELEM
*m_pTermFuncs
;
126 CComCriticalSection m_csStaticDataInitAndTypeInfo
;
128 typedef _ATL_MODULE70 _ATL_MODULE
;
130 typedef HRESULT (WINAPI _ATL_CREATORARGFUNC
)(void *pv
, REFIID riid
, LPVOID
*ppv
, DWORD_PTR dw
);
132 #define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC *)1)
134 struct _ATL_INTMAP_ENTRY
138 _ATL_CREATORARGFUNC
*pFunc
;
141 struct _AtlCreateWndData
145 _AtlCreateWndData
*m_pNext
;
148 struct _ATL_COM_MODULE70
151 HINSTANCE m_hInstTypeLib
;
152 _ATL_OBJMAP_ENTRY
**m_ppAutoObjMapFirst
;
153 _ATL_OBJMAP_ENTRY
**m_ppAutoObjMapLast
;
154 CComCriticalSection m_csObjMap
;
156 typedef _ATL_COM_MODULE70 _ATL_COM_MODULE
;
158 struct _ATL_WIN_MODULE70
161 CComCriticalSection m_csWindowCreate
;
162 _AtlCreateWndData
*m_pCreateWndList
;
164 CSimpleArray
<ATOM
> m_rgWindowClassAtoms
;
167 typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE
;
169 struct _ATL_REGMAP_ENTRY
175 HRESULT __stdcall
AtlWinModuleInit(_ATL_WIN_MODULE
*pWinModule
);
176 HRESULT __stdcall
AtlWinModuleTerm(_ATL_WIN_MODULE
*pWinModule
, HINSTANCE hInst
);
177 HRESULT __stdcall
AtlInternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
);
178 void __stdcall
AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE
*pWinModule
, _AtlCreateWndData
*pData
, void *pObject
);
179 void *__stdcall
AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE
*pWinModule
);
180 HRESULT __stdcall
AtlComModuleGetClassObject(_ATL_COM_MODULE
*pComModule
, REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
);
182 template<class TLock
>
183 class CComCritSecLock
189 CComCritSecLock(TLock
&cs
, bool bInitialLock
= true) : m_cs(cs
)
214 ATLASSERT(!m_bLocked
);
215 hResult
= m_cs
.Lock();
227 ATLASSERT(m_bLocked
);
228 hResult
= m_cs
.Unlock();
249 CHandle(_Inout_ CHandle
& handle
) :
252 Attach(handle
.Detach());
255 explicit CHandle(_In_ HANDLE handle
) :
268 CHandle
& operator=(_Inout_ CHandle
& handle
)
276 Attach(handle
.Detach());
282 operator HANDLE() const
287 void Attach(_In_ HANDLE handle
)
289 ATLASSERT(m_handle
== NULL
);
295 HANDLE handle
= m_handle
;
304 ::CloseHandle(m_handle
);
311 inline BOOL WINAPI
InlineIsEqualUnknown(REFGUID rguid1
)
314 ((unsigned long *)&rguid1
)[0] == 0 &&
315 ((unsigned long *)&rguid1
)[1] == 0 &&
316 ((unsigned long *)&rguid1
)[2] == 0x000000C0 &&
317 ((unsigned long *)&rguid1
)[3] == 0x46000000);
320 class CComMultiThreadModelNoCS
323 typedef CComFakeCriticalSection AutoCriticalSection
;
324 typedef CComFakeCriticalSection CriticalSection
;
325 typedef CComMultiThreadModelNoCS ThreadModelNoCS
;
326 typedef CComFakeCriticalSection AutoDeleteCriticalSection
;
328 static ULONG WINAPI
Increment(LPLONG p
)
330 return InterlockedIncrement(p
);
333 static ULONG WINAPI
Decrement(LPLONG p
)
335 return InterlockedDecrement(p
);
339 class CComMultiThreadModel
342 typedef CComAutoCriticalSection AutoCriticalSection
;
343 typedef CComCriticalSection CriticalSection
;
344 typedef CComMultiThreadModelNoCS ThreadModelNoCS
;
345 typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection
;
347 static ULONG WINAPI
Increment(LPLONG p
)
349 return InterlockedIncrement(p
);
352 static ULONG WINAPI
Decrement(LPLONG p
)
354 return InterlockedDecrement(p
);
358 class CComSingleThreadModel
361 typedef CComFakeCriticalSection AutoCriticalSection
;
362 typedef CComFakeCriticalSection CriticalSection
;
363 typedef CComSingleThreadModel ThreadModelNoCS
;
364 typedef CComFakeCriticalSection AutoDeleteCriticalSection
;
366 static ULONG WINAPI
Increment(LPLONG p
)
371 static ULONG WINAPI
Decrement(LPLONG p
)
377 #if defined(_ATL_FREE_THREADED)
379 typedef CComMultiThreadModel CComObjectThreadModel
;
380 typedef CComMultiThreadModel CComGlobalsThreadModel
;
382 #elif defined(_ATL_APARTMENT_THREADED)
384 typedef CComSingleThreadModel CComObjectThreadModel
;
385 typedef CComMultiThreadModel CComGlobalsThreadModel
;
387 #elif defined(_ATL_SINGLE_THREADED)
389 typedef CComSingleThreadModel CComObjectThreadModel
;
390 typedef CComSingleThreadModel CComGlobalsThreadModel
;
393 #error No threading model
396 class CAtlModule
: public _ATL_MODULE
403 ATLASSERT(_pAtlModule
== NULL
);
405 cbSize
= sizeof(_ATL_MODULE
);
409 virtual LONG
GetLockCount()
416 return CComGlobalsThreadModel::Increment(&m_nLockCnt
);
419 virtual LONG
Unlock()
421 return CComGlobalsThreadModel::Decrement(&m_nLockCnt
);
424 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
* /*pRegistrar*/) = 0;
426 HRESULT WINAPI
UpdateRegistryFromResource(LPCTSTR lpszRes
, BOOL bRegister
, struct _ATL_REGMAP_ENTRY
*pMapEntries
= NULL
)
428 CRegObject registrar
;
429 WCHAR modulePath
[MAX_PATH
];
433 hResult
= CommonInitRegistrar(registrar
, modulePath
, sizeof(modulePath
) / sizeof(modulePath
[0]), pMapEntries
);
439 /* FIXME: this is a bit of a hack, need to re-evaluate */
440 WCHAR resid
[MAX_PATH
];
441 MultiByteToWideChar(CP_ACP
, 0, lpszRes
, -1, resid
, MAX_PATH
);
444 if (bRegister
!= FALSE
)
445 hResult
= registrar
.ResourceRegisterSz(modulePath
, lpwszRes
, L
"REGISTRY");
447 hResult
= registrar
.ResourceUnregisterSz(modulePath
, lpwszRes
, L
"REGISTRY");
452 HRESULT WINAPI
UpdateRegistryFromResource(UINT nResID
, BOOL bRegister
, struct _ATL_REGMAP_ENTRY
*pMapEntries
= NULL
)
454 CRegObject registrar
;
455 WCHAR modulePath
[MAX_PATH
];
458 hResult
= CommonInitRegistrar(registrar
, modulePath
, sizeof(modulePath
) / sizeof(modulePath
[0]), pMapEntries
);
462 if (bRegister
!= FALSE
)
463 hResult
= registrar
.ResourceRegister(modulePath
, nResID
, L
"REGISTRY");
465 hResult
= registrar
.ResourceUnregister(modulePath
, nResID
, L
"REGISTRY");
471 HRESULT
CommonInitRegistrar(CRegObject
®istrar
, WCHAR
*modulePath
, DWORD modulePathCount
, struct _ATL_REGMAP_ENTRY
*pMapEntries
)
477 hInstance
= _AtlBaseModule
.GetModuleInstance();
478 dwFLen
= GetModuleFileNameW(hInstance
, modulePath
, modulePathCount
);
479 if (dwFLen
== modulePathCount
)
480 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
481 else if (dwFLen
== 0)
482 return HRESULT_FROM_WIN32(GetLastError());
484 if (pMapEntries
!= NULL
)
486 while (pMapEntries
->szKey
!= NULL
)
488 ATLASSERT(pMapEntries
->szData
!= NULL
);
489 hResult
= registrar
.AddReplacement(pMapEntries
->szKey
, pMapEntries
->szData
);
496 hResult
= AddCommonRGSReplacements(®istrar
);
500 hResult
= registrar
.AddReplacement(L
"Module", modulePath
);
504 hResult
= registrar
.AddReplacement(L
"Module_Raw", modulePath
);
512 __declspec(selectany
) GUID
CAtlModule::m_libid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
515 class CAtlModuleT
: public CAtlModule
519 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
*pRegistrar
)
521 return pRegistrar
->AddReplacement(L
"APPID", T::GetAppId());
524 static LPCOLESTR
GetAppId()
530 class CAtlComModule
: public _ATL_COM_MODULE
535 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
, (LPCWSTR
)this, &m_hInstTypeLib
);
536 m_ppAutoObjMapFirst
= NULL
;
537 m_ppAutoObjMapLast
= NULL
;
538 if (FAILED(m_csObjMap
.Init()))
541 CAtlBaseModule::m_bInitFailed
= true;
544 cbSize
= sizeof(_ATL_COM_MODULE
);
556 ATLASSERT(m_ppAutoObjMapFirst
== NULL
);
557 ATLASSERT(m_ppAutoObjMapLast
== NULL
);
565 class CAtlDllModuleT
: public CAtlModuleT
<T
>
572 HRESULT
DllCanUnloadNow()
576 pThis
= static_cast<T
*>(this);
577 if (pThis
->GetLockCount() == 0)
582 HRESULT
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
586 pThis
= static_cast<T
*>(this);
587 return pThis
->GetClassObject(rclsid
, riid
, ppv
);
590 HRESULT
DllRegisterServer(BOOL bRegTypeLib
= TRUE
)
595 pThis
= static_cast<T
*>(this);
596 hResult
= pThis
->RegisterServer(bRegTypeLib
);
600 HRESULT
DllUnregisterServer(BOOL bUnRegTypeLib
= TRUE
)
605 pThis
= static_cast<T
*>(this);
606 hResult
= pThis
->UnregisterServer(bUnRegTypeLib
);
610 HRESULT
GetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
612 return AtlComModuleGetClassObject(&_AtlComModule
, rclsid
, riid
, ppv
);
616 class CComModule
: public CAtlModuleT
<CComModule
>
619 _ATL_OBJMAP_ENTRY
*m_pObjMap
;
623 ATLASSERT(_pModule
== NULL
);
625 _pModule
->m_pObjMap
= NULL
;
633 HRESULT
Init(_ATL_OBJMAP_ENTRY
*p
, HINSTANCE
/* h */, const GUID
*plibid
)
635 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
640 if (p
!= reinterpret_cast<_ATL_OBJMAP_ENTRY
*>(-1))
646 while (objectMapEntry
->pclsid
!= NULL
)
648 objectMapEntry
->pfnObjectMain(true);
658 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
660 if (m_pObjMap
!= NULL
)
662 objectMapEntry
= m_pObjMap
;
663 while (objectMapEntry
->pclsid
!= NULL
)
665 if (objectMapEntry
->pCF
!= NULL
)
666 objectMapEntry
->pCF
->Release();
667 objectMapEntry
->pCF
= NULL
;
668 objectMapEntry
->pfnObjectMain(false);
674 HRESULT
GetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
676 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
679 ATLASSERT(ppv
!= NULL
);
684 if (m_pObjMap
!= NULL
)
686 objectMapEntry
= m_pObjMap
;
687 while (objectMapEntry
->pclsid
!= NULL
)
689 if (objectMapEntry
->pfnGetClassObject
!= NULL
&& InlineIsEqualGUID(rclsid
, *objectMapEntry
->pclsid
) != FALSE
)
691 if (objectMapEntry
->pCF
== NULL
)
693 CComCritSecLock
<CComCriticalSection
> lock(_AtlComModule
.m_csObjMap
, true);
695 if (objectMapEntry
->pCF
== NULL
)
696 hResult
= objectMapEntry
->pfnGetClassObject(reinterpret_cast<void *>(objectMapEntry
->pfnCreateInstance
), IID_IUnknown
, reinterpret_cast<LPVOID
*>(&objectMapEntry
->pCF
));
698 if (objectMapEntry
->pCF
!= NULL
)
699 hResult
= objectMapEntry
->pCF
->QueryInterface(riid
, ppv
);
705 if (hResult
== S_OK
&& *ppv
== NULL
)
707 // FIXME: call AtlComModuleGetClassObject
708 hResult
= CLASS_E_CLASSNOTAVAILABLE
;
713 HRESULT
RegisterServer(BOOL bRegTypeLib
= FALSE
, const CLSID
*pCLSID
= NULL
)
715 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
719 objectMapEntry
= m_pObjMap
;
720 if (objectMapEntry
!= NULL
)
722 while (objectMapEntry
->pclsid
!= NULL
)
724 if (pCLSID
== NULL
|| IsEqualGUID(*pCLSID
, *objectMapEntry
->pclsid
) != FALSE
)
726 hResult
= objectMapEntry
->pfnUpdateRegistry(TRUE
);
736 HRESULT
UnregisterServer(BOOL bUnRegTypeLib
, const CLSID
*pCLSID
= NULL
)
738 _ATL_OBJMAP_ENTRY
*objectMapEntry
;
742 objectMapEntry
= m_pObjMap
;
743 if (objectMapEntry
!= NULL
)
745 while (objectMapEntry
->pclsid
!= NULL
)
747 if (pCLSID
== NULL
|| IsEqualGUID(*pCLSID
, *objectMapEntry
->pclsid
) != FALSE
)
749 hResult
= objectMapEntry
->pfnUpdateRegistry(FALSE
); //unregister
759 HRESULT
DllCanUnloadNow()
761 if (GetLockCount() == 0)
766 HRESULT
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
768 return GetClassObject(rclsid
, riid
, ppv
);
771 HRESULT
DllRegisterServer(BOOL bRegTypeLib
= TRUE
)
773 return RegisterServer(bRegTypeLib
);
776 HRESULT
DllUnregisterServer(BOOL bUnRegTypeLib
= TRUE
)
778 return UnregisterServer(bUnRegTypeLib
);
783 class CAtlWinModule
: public _ATL_WIN_MODULE
790 hResult
= AtlWinModuleInit(this);
793 CAtlBaseModule::m_bInitFailed
= true;
805 AtlWinModuleTerm(this, _AtlBaseModule
.GetModuleInstance());
808 void AddCreateWndData(_AtlCreateWndData
*pData
, void *pObject
)
810 AtlWinModuleAddCreateWndData(this, pData
, pObject
);
813 void *ExtractCreateWndData()
815 return AtlWinModuleExtractCreateWndData(this);
819 extern CAtlWinModule _AtlWinModule
;
824 static void* Allocate(_In_
size_t size
)
826 return ::CoTaskMemAlloc(size
);
829 static void* Reallocate(_In_opt_
void* ptr
, _In_
size_t size
)
831 return ::CoTaskMemRealloc(ptr
, size
);
834 static void Free(_In_opt_
void* ptr
)
836 ::CoTaskMemFree(ptr
);
842 class CComHeapPtr
: public CHeapPtr
<T
, CComAllocator
>
849 explicit CComHeapPtr(T
*lp
) :
850 CHeapPtr
<T
, CComAllocator
>(lp
)
856 inline HRESULT __stdcall
AtlAdvise(IUnknown
*pUnkCP
, IUnknown
*pUnk
, const IID
&iid
, LPDWORD pdw
)
858 CComPtr
<IConnectionPointContainer
> container
;
859 CComPtr
<IConnectionPoint
> connectionPoint
;
864 hResult
= pUnkCP
->QueryInterface(IID_IConnectionPointContainer
, (void **)&container
);
867 hResult
= container
->FindConnectionPoint(iid
, &connectionPoint
);
870 return connectionPoint
->Advise(pUnk
, pdw
);
873 inline HRESULT __stdcall
AtlUnadvise(IUnknown
*pUnkCP
, const IID
&iid
, DWORD dw
)
875 CComPtr
<IConnectionPointContainer
> container
;
876 CComPtr
<IConnectionPoint
> connectionPoint
;
881 hResult
= pUnkCP
->QueryInterface(IID_IConnectionPointContainer
, (void **)&container
);
884 hResult
= container
->FindConnectionPoint(iid
, &connectionPoint
);
887 return connectionPoint
->Unadvise(dw
);
890 inline HRESULT __stdcall
AtlInternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
)
893 IUnknown
*resultInterface
;
896 ATLASSERT(pThis
!= NULL
&& pEntries
!= NULL
);
897 if (pThis
== NULL
|| pEntries
== NULL
)
899 ATLASSERT(ppvObject
!= NULL
);
900 if (ppvObject
== NULL
)
903 if (InlineIsEqualUnknown(iid
))
905 resultInterface
= reinterpret_cast<IUnknown
*>(reinterpret_cast<char *>(pThis
) + pEntries
[0].dw
);
906 *ppvObject
= resultInterface
;
907 resultInterface
->AddRef();
912 while (pEntries
[i
].pFunc
!= 0)
914 if (pEntries
[i
].piid
== NULL
|| InlineIsEqualGUID(iid
, *pEntries
[i
].piid
))
916 if (pEntries
[i
].pFunc
== reinterpret_cast<_ATL_CREATORARGFUNC
*>(1))
918 ATLASSERT(pEntries
[i
].piid
!= NULL
);
919 resultInterface
= reinterpret_cast<IUnknown
*>(reinterpret_cast<char *>(pThis
) + pEntries
[i
].dw
);
920 *ppvObject
= resultInterface
;
921 resultInterface
->AddRef();
926 hResult
= pEntries
[i
].pFunc(pThis
, iid
, ppvObject
, 0);
927 if (hResult
== S_OK
|| (FAILED(hResult
) && pEntries
[i
].piid
!= NULL
))
935 return E_NOINTERFACE
;
938 inline HRESULT __stdcall
AtlWinModuleInit(_ATL_WIN_MODULE
*pWinModule
)
940 if (pWinModule
== NULL
)
942 pWinModule
->m_pCreateWndList
= NULL
;
943 return pWinModule
->m_csWindowCreate
.Init();
946 inline HRESULT __stdcall
AtlWinModuleTerm(_ATL_WIN_MODULE
*pWinModule
, HINSTANCE hInst
)
948 if (pWinModule
== NULL
)
950 pWinModule
->m_csWindowCreate
.Term();
954 inline void __stdcall
AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE
*pWinModule
, _AtlCreateWndData
*pData
, void *pObject
)
956 CComCritSecLock
<CComCriticalSection
> lock(pWinModule
->m_csWindowCreate
, true);
958 ATLASSERT(pWinModule
!= NULL
);
959 ATLASSERT(pObject
!= NULL
);
961 pData
->m_pThis
= pObject
;
962 pData
->m_dwThreadID
= ::GetCurrentThreadId();
963 pData
->m_pNext
= pWinModule
->m_pCreateWndList
;
964 pWinModule
->m_pCreateWndList
= pData
;
967 inline void *__stdcall
AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE
*pWinModule
)
969 CComCritSecLock
<CComCriticalSection
> lock(pWinModule
->m_csWindowCreate
, true);
971 _AtlCreateWndData
*currentEntry
;
972 _AtlCreateWndData
**previousLink
;
975 ATLASSERT(pWinModule
!= NULL
);
978 threadID
= GetCurrentThreadId();
979 currentEntry
= pWinModule
->m_pCreateWndList
;
980 previousLink
= &pWinModule
->m_pCreateWndList
;
981 while (currentEntry
!= NULL
)
983 if (currentEntry
->m_dwThreadID
== threadID
)
985 *previousLink
= currentEntry
->m_pNext
;
986 result
= currentEntry
->m_pThis
;
989 previousLink
= ¤tEntry
->m_pNext
;
990 currentEntry
= currentEntry
->m_pNext
;
997 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
999 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE