2cb7a10e5851cd3f7df545a5ddba97a860d4ea95
[reactos.git] / reactos / lib / atl / atlbase.h
1 /*
2 * ReactOS ATL
3 *
4 * Copyright 2009 Andrew Hill <ash77@reactos.org>
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #pragma once
22
23 #include "atlcore.h"
24 #include "statreg.h"
25 #include "atlcomcli.h"
26 #include "atlalloc.h"
27
28 #ifdef _MSC_VER
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)
31 #endif
32
33 #ifndef _ATL_PACKING
34 #define _ATL_PACKING 8
35 #endif
36
37 #ifndef _ATL_FREE_THREADED
38 #ifndef _ATL_APARTMENT_THREADED
39 #ifndef _ATL_SINGLE_THREADED
40 #define _ATL_FREE_THREADED
41 #endif
42 #endif
43 #endif
44
45 #ifndef ATLTRY
46 #define ATLTRY(x) x;
47 #endif
48
49 #ifdef _ATL_DISABLE_NO_VTABLE
50 #define ATL_NO_VTABLE
51 #else
52 #define ATL_NO_VTABLE __declspec(novtable)
53 #endif
54
55 #define offsetofclass(base, derived) (reinterpret_cast<DWORD_PTR>(static_cast<base *>(reinterpret_cast<derived *>(_ATL_PACKING))) - _ATL_PACKING)
56
57 namespace ATL
58 {
59
60 class CAtlModule;
61 class CComModule;
62 class CAtlComModule;
63 __declspec(selectany) CAtlModule *_pAtlModule = NULL;
64 __declspec(selectany) CComModule *_pModule = NULL;
65 extern CAtlComModule _AtlComModule;
66
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)();
70
71 struct _ATL_OBJMAP_ENTRY30
72 {
73 const CLSID *pclsid;
74 HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);
75 _ATL_CREATORFUNC *pfnGetClassObject;
76 _ATL_CREATORFUNC *pfnCreateInstance;
77 IUnknown *pCF;
78 DWORD dwRegister;
79 _ATL_DESCRIPTIONFUNC *pfnGetObjectDescription;
80 _ATL_CATMAPFUNC *pfnGetCategoryMap;
81 void (WINAPI *pfnObjectMain)(bool bStarting);
82
83 HRESULT WINAPI RevokeClassObject()
84 {
85 if (dwRegister == 0)
86 return S_OK;
87 return CoRevokeClassObject(dwRegister);
88 }
89
90 HRESULT WINAPI RegisterClassObject(DWORD dwClsContext, DWORD dwFlags)
91 {
92 IUnknown *p;
93 HRESULT hResult;
94
95 p = NULL;
96 if (pfnGetClassObject == NULL)
97 return S_OK;
98
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);
102
103 if (p != NULL)
104 p->Release();
105
106 return hResult;
107 }
108 };
109
110 typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY;
111
112 typedef void (__stdcall _ATL_TERMFUNC)(DWORD_PTR dw);
113
114 struct _ATL_TERMFUNC_ELEM
115 {
116 _ATL_TERMFUNC *pFunc;
117 DWORD_PTR dw;
118 _ATL_TERMFUNC_ELEM *pNext;
119 };
120
121 struct _ATL_MODULE70
122 {
123 UINT cbSize;
124 LONG m_nLockCnt;
125 _ATL_TERMFUNC_ELEM *m_pTermFuncs;
126 CComCriticalSection m_csStaticDataInitAndTypeInfo;
127 };
128 typedef _ATL_MODULE70 _ATL_MODULE;
129
130 typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void *pv, REFIID riid, LPVOID *ppv, DWORD_PTR dw);
131
132 #define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC *)1)
133
134 struct _ATL_INTMAP_ENTRY
135 {
136 const IID *piid;
137 DWORD_PTR dw;
138 _ATL_CREATORARGFUNC *pFunc;
139 };
140
141 struct _AtlCreateWndData
142 {
143 void *m_pThis;
144 DWORD m_dwThreadID;
145 _AtlCreateWndData *m_pNext;
146 };
147
148 struct _ATL_COM_MODULE70
149 {
150 UINT cbSize;
151 HINSTANCE m_hInstTypeLib;
152 _ATL_OBJMAP_ENTRY **m_ppAutoObjMapFirst;
153 _ATL_OBJMAP_ENTRY **m_ppAutoObjMapLast;
154 CComCriticalSection m_csObjMap;
155 };
156 typedef _ATL_COM_MODULE70 _ATL_COM_MODULE;
157
158 struct _ATL_WIN_MODULE70
159 {
160 UINT cbSize;
161 CComCriticalSection m_csWindowCreate;
162 _AtlCreateWndData *m_pCreateWndList;
163 #ifdef NOTYET
164 CSimpleArray<ATOM> m_rgWindowClassAtoms;
165 #endif
166 };
167 typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE;
168
169 struct _ATL_REGMAP_ENTRY
170 {
171 LPCOLESTR szKey;
172 LPCOLESTR szData;
173 };
174
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);
181
182 template<class TLock>
183 class CComCritSecLock
184 {
185 private:
186 bool m_bLocked;
187 TLock &m_cs;
188 public:
189 CComCritSecLock(TLock &cs, bool bInitialLock = true) : m_cs(cs)
190 {
191 HRESULT hResult;
192
193 m_bLocked = false;
194 if (bInitialLock)
195 {
196 hResult = Lock();
197 if (FAILED(hResult))
198 {
199 ATLASSERT(false);
200 }
201 }
202 }
203
204 ~CComCritSecLock()
205 {
206 if (m_bLocked)
207 Unlock();
208 }
209
210 HRESULT Lock()
211 {
212 HRESULT hResult;
213
214 ATLASSERT(!m_bLocked);
215 hResult = m_cs.Lock();
216 if (FAILED(hResult))
217 return hResult;
218 m_bLocked = true;
219
220 return S_OK;
221 }
222
223 void Unlock()
224 {
225 HRESULT hResult;
226
227 ATLASSERT(m_bLocked);
228 hResult = m_cs.Unlock();
229 if (FAILED(hResult))
230 {
231 ATLASSERT(false);
232 }
233 m_bLocked = false;
234 }
235 };
236
237
238 class CHandle
239 {
240 public:
241 HANDLE m_handle;
242
243 public:
244 CHandle() :
245 m_handle(NULL)
246 {
247 }
248
249 CHandle(_Inout_ CHandle& handle) :
250 m_handle(NULL)
251 {
252 Attach(handle.Detach());
253 }
254
255 explicit CHandle(_In_ HANDLE handle) :
256 m_handle(handle)
257 {
258 }
259
260 ~CHandle()
261 {
262 if (m_handle)
263 {
264 Close();
265 }
266 }
267
268 CHandle& operator=(_Inout_ CHandle& handle)
269 {
270 if (this != &handle)
271 {
272 if (m_handle)
273 {
274 Close();
275 }
276 Attach(handle.Detach());
277 }
278
279 return *this;
280 }
281
282 operator HANDLE() const
283 {
284 return m_handle;
285 }
286
287 void Attach(_In_ HANDLE handle)
288 {
289 ATLASSERT(m_handle == NULL);
290 m_handle = handle;
291 }
292
293 HANDLE Detach()
294 {
295 HANDLE handle = m_handle;
296 m_handle = NULL;
297 return handle;
298 }
299
300 void Close()
301 {
302 if (m_handle)
303 {
304 ::CloseHandle(m_handle);
305 m_handle = NULL;
306 }
307 }
308 };
309
310
311 inline BOOL WINAPI InlineIsEqualUnknown(REFGUID rguid1)
312 {
313 return (
314 ((unsigned long *)&rguid1)[0] == 0 &&
315 ((unsigned long *)&rguid1)[1] == 0 &&
316 ((unsigned long *)&rguid1)[2] == 0x000000C0 &&
317 ((unsigned long *)&rguid1)[3] == 0x46000000);
318 }
319
320 class CComMultiThreadModelNoCS
321 {
322 public:
323 typedef CComFakeCriticalSection AutoCriticalSection;
324 typedef CComFakeCriticalSection CriticalSection;
325 typedef CComMultiThreadModelNoCS ThreadModelNoCS;
326 typedef CComFakeCriticalSection AutoDeleteCriticalSection;
327
328 static ULONG WINAPI Increment(LPLONG p)
329 {
330 return InterlockedIncrement(p);
331 }
332
333 static ULONG WINAPI Decrement(LPLONG p)
334 {
335 return InterlockedDecrement(p);
336 }
337 };
338
339 class CComMultiThreadModel
340 {
341 public:
342 typedef CComAutoCriticalSection AutoCriticalSection;
343 typedef CComCriticalSection CriticalSection;
344 typedef CComMultiThreadModelNoCS ThreadModelNoCS;
345 typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection;
346
347 static ULONG WINAPI Increment(LPLONG p)
348 {
349 return InterlockedIncrement(p);
350 }
351
352 static ULONG WINAPI Decrement(LPLONG p)
353 {
354 return InterlockedDecrement(p);
355 }
356 };
357
358 class CComSingleThreadModel
359 {
360 public:
361 typedef CComFakeCriticalSection AutoCriticalSection;
362 typedef CComFakeCriticalSection CriticalSection;
363 typedef CComSingleThreadModel ThreadModelNoCS;
364 typedef CComFakeCriticalSection AutoDeleteCriticalSection;
365
366 static ULONG WINAPI Increment(LPLONG p)
367 {
368 return ++*p;
369 }
370
371 static ULONG WINAPI Decrement(LPLONG p)
372 {
373 return --*p;
374 }
375 };
376
377 #if defined(_ATL_FREE_THREADED)
378
379 typedef CComMultiThreadModel CComObjectThreadModel;
380 typedef CComMultiThreadModel CComGlobalsThreadModel;
381
382 #elif defined(_ATL_APARTMENT_THREADED)
383
384 typedef CComSingleThreadModel CComObjectThreadModel;
385 typedef CComMultiThreadModel CComGlobalsThreadModel;
386
387 #elif defined(_ATL_SINGLE_THREADED)
388
389 typedef CComSingleThreadModel CComObjectThreadModel;
390 typedef CComSingleThreadModel CComGlobalsThreadModel;
391
392 #else
393 #error No threading model
394 #endif
395
396 class CAtlModule : public _ATL_MODULE
397 {
398 public:
399 static GUID m_libid;
400
401 CAtlModule()
402 {
403 ATLASSERT(_pAtlModule == NULL);
404 _pAtlModule = this;
405 cbSize = sizeof(_ATL_MODULE);
406 m_nLockCnt = 0;
407 }
408
409 virtual LONG GetLockCount()
410 {
411 return m_nLockCnt;
412 }
413
414 virtual LONG Lock()
415 {
416 return CComGlobalsThreadModel::Increment(&m_nLockCnt);
417 }
418
419 virtual LONG Unlock()
420 {
421 return CComGlobalsThreadModel::Decrement(&m_nLockCnt);
422 }
423
424 virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* /*pRegistrar*/) = 0;
425
426 HRESULT WINAPI UpdateRegistryFromResource(LPCTSTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY *pMapEntries = NULL)
427 {
428 CRegObject registrar;
429 WCHAR modulePath[MAX_PATH];
430 HRESULT hResult;
431 PCWSTR lpwszRes;
432
433 hResult = CommonInitRegistrar(registrar, modulePath, sizeof(modulePath) / sizeof(modulePath[0]), pMapEntries);
434 if (FAILED(hResult))
435 return hResult;
436 #ifdef UNICODE
437 lpwszRes = lpszRes;
438 #else
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);
442 lpwszRes = resid;
443 #endif
444 if (bRegister != FALSE)
445 hResult = registrar.ResourceRegisterSz(modulePath, lpwszRes, L"REGISTRY");
446 else
447 hResult = registrar.ResourceUnregisterSz(modulePath, lpwszRes, L"REGISTRY");
448
449 return hResult;
450 }
451
452 HRESULT WINAPI UpdateRegistryFromResource(UINT nResID, BOOL bRegister, struct _ATL_REGMAP_ENTRY *pMapEntries = NULL)
453 {
454 CRegObject registrar;
455 WCHAR modulePath[MAX_PATH];
456 HRESULT hResult;
457
458 hResult = CommonInitRegistrar(registrar, modulePath, sizeof(modulePath) / sizeof(modulePath[0]), pMapEntries);
459 if (FAILED(hResult))
460 return hResult;
461
462 if (bRegister != FALSE)
463 hResult = registrar.ResourceRegister(modulePath, nResID, L"REGISTRY");
464 else
465 hResult = registrar.ResourceUnregister(modulePath, nResID, L"REGISTRY");
466
467 return hResult;
468 }
469
470 private:
471 HRESULT CommonInitRegistrar(CRegObject &registrar, WCHAR *modulePath, DWORD modulePathCount, struct _ATL_REGMAP_ENTRY *pMapEntries)
472 {
473 HINSTANCE hInstance;
474 DWORD dwFLen;
475 HRESULT hResult;
476
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());
483
484 if (pMapEntries != NULL)
485 {
486 while (pMapEntries->szKey != NULL)
487 {
488 ATLASSERT(pMapEntries->szData != NULL);
489 hResult = registrar.AddReplacement(pMapEntries->szKey, pMapEntries->szData);
490 if (FAILED(hResult))
491 return hResult;
492 pMapEntries++;
493 }
494 }
495
496 hResult = AddCommonRGSReplacements(&registrar);
497 if (FAILED(hResult))
498 return hResult;
499
500 hResult = registrar.AddReplacement(L"Module", modulePath);
501 if (FAILED(hResult))
502 return hResult;
503
504 hResult = registrar.AddReplacement(L"Module_Raw", modulePath);
505 if (FAILED(hResult))
506 return hResult;
507
508 return S_OK;
509 }
510 };
511
512 __declspec(selectany) GUID CAtlModule::m_libid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
513
514 template <class T>
515 class CAtlModuleT : public CAtlModule
516 {
517 public:
518
519 virtual HRESULT AddCommonRGSReplacements(IRegistrarBase *pRegistrar)
520 {
521 return pRegistrar->AddReplacement(L"APPID", T::GetAppId());
522 }
523
524 static LPCOLESTR GetAppId()
525 {
526 return L"";
527 }
528 };
529
530 class CAtlComModule : public _ATL_COM_MODULE
531 {
532 public:
533 CAtlComModule()
534 {
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()))
539 {
540 ATLASSERT(0);
541 CAtlBaseModule::m_bInitFailed = true;
542 return;
543 }
544 cbSize = sizeof(_ATL_COM_MODULE);
545 }
546
547 ~CAtlComModule()
548 {
549 Term();
550 }
551
552 void Term()
553 {
554 if (cbSize != 0)
555 {
556 ATLASSERT(m_ppAutoObjMapFirst == NULL);
557 ATLASSERT(m_ppAutoObjMapLast == NULL);
558 m_csObjMap.Term();
559 cbSize = 0;
560 }
561 }
562 };
563
564 template <class T>
565 class CAtlDllModuleT : public CAtlModuleT<T>
566 {
567 public:
568 CAtlDllModuleT()
569 {
570 }
571
572 HRESULT DllCanUnloadNow()
573 {
574 T *pThis;
575
576 pThis = static_cast<T *>(this);
577 if (pThis->GetLockCount() == 0)
578 return S_OK;
579 return S_FALSE;
580 }
581
582 HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
583 {
584 T *pThis;
585
586 pThis = static_cast<T *>(this);
587 return pThis->GetClassObject(rclsid, riid, ppv);
588 }
589
590 HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE)
591 {
592 T *pThis;
593 HRESULT hResult;
594
595 pThis = static_cast<T *>(this);
596 hResult = pThis->RegisterServer(bRegTypeLib);
597 return hResult;
598 }
599
600 HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE)
601 {
602 T *pThis;
603 HRESULT hResult;
604
605 pThis = static_cast<T *>(this);
606 hResult = pThis->UnregisterServer(bUnRegTypeLib);
607 return hResult;
608 }
609
610 HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
611 {
612 return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv);
613 }
614 };
615
616 class CComModule : public CAtlModuleT<CComModule>
617 {
618 public:
619 _ATL_OBJMAP_ENTRY *m_pObjMap;
620 public:
621 CComModule()
622 {
623 ATLASSERT(_pModule == NULL);
624 _pModule = this;
625 _pModule->m_pObjMap = NULL;
626 }
627
628 ~CComModule()
629 {
630 _pModule = NULL;
631 }
632
633 HRESULT Init(_ATL_OBJMAP_ENTRY *p, HINSTANCE /* h */, const GUID *plibid)
634 {
635 _ATL_OBJMAP_ENTRY *objectMapEntry;
636
637 if (plibid != NULL)
638 m_libid = *plibid;
639
640 if (p != reinterpret_cast<_ATL_OBJMAP_ENTRY *>(-1))
641 {
642 m_pObjMap = p;
643 if (p != NULL)
644 {
645 objectMapEntry = p;
646 while (objectMapEntry->pclsid != NULL)
647 {
648 objectMapEntry->pfnObjectMain(true);
649 objectMapEntry++;
650 }
651 }
652 }
653 return S_OK;
654 }
655
656 void Term()
657 {
658 _ATL_OBJMAP_ENTRY *objectMapEntry;
659
660 if (m_pObjMap != NULL)
661 {
662 objectMapEntry = m_pObjMap;
663 while (objectMapEntry->pclsid != NULL)
664 {
665 if (objectMapEntry->pCF != NULL)
666 objectMapEntry->pCF->Release();
667 objectMapEntry->pCF = NULL;
668 objectMapEntry->pfnObjectMain(false);
669 objectMapEntry++;
670 }
671 }
672 }
673
674 HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
675 {
676 _ATL_OBJMAP_ENTRY *objectMapEntry;
677 HRESULT hResult;
678
679 ATLASSERT(ppv != NULL);
680 if (ppv == NULL)
681 return E_POINTER;
682 *ppv = NULL;
683 hResult = S_OK;
684 if (m_pObjMap != NULL)
685 {
686 objectMapEntry = m_pObjMap;
687 while (objectMapEntry->pclsid != NULL)
688 {
689 if (objectMapEntry->pfnGetClassObject != NULL && InlineIsEqualGUID(rclsid, *objectMapEntry->pclsid) != FALSE)
690 {
691 if (objectMapEntry->pCF == NULL)
692 {
693 CComCritSecLock<CComCriticalSection> lock(_AtlComModule.m_csObjMap, true);
694
695 if (objectMapEntry->pCF == NULL)
696 hResult = objectMapEntry->pfnGetClassObject(reinterpret_cast<void *>(objectMapEntry->pfnCreateInstance), IID_IUnknown, reinterpret_cast<LPVOID *>(&objectMapEntry->pCF));
697 }
698 if (objectMapEntry->pCF != NULL)
699 hResult = objectMapEntry->pCF->QueryInterface(riid, ppv);
700 break;
701 }
702 objectMapEntry++;
703 }
704 }
705 if (hResult == S_OK && *ppv == NULL)
706 {
707 // FIXME: call AtlComModuleGetClassObject
708 hResult = CLASS_E_CLASSNOTAVAILABLE;
709 }
710 return hResult;
711 }
712
713 HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL)
714 {
715 _ATL_OBJMAP_ENTRY *objectMapEntry;
716 HRESULT hResult;
717
718 hResult = S_OK;
719 objectMapEntry = m_pObjMap;
720 if (objectMapEntry != NULL)
721 {
722 while (objectMapEntry->pclsid != NULL)
723 {
724 if (pCLSID == NULL || IsEqualGUID(*pCLSID, *objectMapEntry->pclsid) != FALSE)
725 {
726 hResult = objectMapEntry->pfnUpdateRegistry(TRUE);
727 if (FAILED(hResult))
728 break;
729 }
730 objectMapEntry++;
731 }
732 }
733 return hResult;
734 }
735
736 HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL)
737 {
738 _ATL_OBJMAP_ENTRY *objectMapEntry;
739 HRESULT hResult;
740
741 hResult = S_OK;
742 objectMapEntry = m_pObjMap;
743 if (objectMapEntry != NULL)
744 {
745 while (objectMapEntry->pclsid != NULL)
746 {
747 if (pCLSID == NULL || IsEqualGUID(*pCLSID, *objectMapEntry->pclsid) != FALSE)
748 {
749 hResult = objectMapEntry->pfnUpdateRegistry(FALSE); //unregister
750 if (FAILED(hResult))
751 break;
752 }
753 objectMapEntry++;
754 }
755 }
756 return hResult;
757 }
758
759 HRESULT DllCanUnloadNow()
760 {
761 if (GetLockCount() == 0)
762 return S_OK;
763 return S_FALSE;
764 }
765
766 HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
767 {
768 return GetClassObject(rclsid, riid, ppv);
769 }
770
771 HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE)
772 {
773 return RegisterServer(bRegTypeLib);
774 }
775
776 HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE)
777 {
778 return UnregisterServer(bUnRegTypeLib);
779 }
780
781 };
782
783 class CAtlWinModule : public _ATL_WIN_MODULE
784 {
785 public:
786 CAtlWinModule()
787 {
788 HRESULT hResult;
789
790 hResult = AtlWinModuleInit(this);
791 if (FAILED(hResult))
792 {
793 CAtlBaseModule::m_bInitFailed = true;
794 ATLASSERT(0);
795 }
796 }
797
798 ~CAtlWinModule()
799 {
800 Term();
801 }
802
803 void Term()
804 {
805 AtlWinModuleTerm(this, _AtlBaseModule.GetModuleInstance());
806 }
807
808 void AddCreateWndData(_AtlCreateWndData *pData, void *pObject)
809 {
810 AtlWinModuleAddCreateWndData(this, pData, pObject);
811 }
812
813 void *ExtractCreateWndData()
814 {
815 return AtlWinModuleExtractCreateWndData(this);
816 }
817 };
818
819 extern CAtlWinModule _AtlWinModule;
820
821 class CComAllocator
822 {
823 public:
824 static void* Allocate(_In_ size_t size)
825 {
826 return ::CoTaskMemAlloc(size);
827 }
828
829 static void* Reallocate(_In_opt_ void* ptr, _In_ size_t size)
830 {
831 return ::CoTaskMemRealloc(ptr, size);
832 }
833
834 static void Free(_In_opt_ void* ptr)
835 {
836 ::CoTaskMemFree(ptr);
837 }
838 };
839
840
841 template<class T>
842 class CComHeapPtr : public CHeapPtr<T, CComAllocator>
843 {
844 public:
845 CComHeapPtr()
846 {
847 }
848
849 explicit CComHeapPtr(T *lp) :
850 CHeapPtr<T, CComAllocator>(lp)
851 {
852 }
853 };
854
855
856 inline HRESULT __stdcall AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID &iid, LPDWORD pdw)
857 {
858 CComPtr<IConnectionPointContainer> container;
859 CComPtr<IConnectionPoint> connectionPoint;
860 HRESULT hResult;
861
862 if (pUnkCP == NULL)
863 return E_INVALIDARG;
864 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container);
865 if (FAILED(hResult))
866 return hResult;
867 hResult = container->FindConnectionPoint(iid, &connectionPoint);
868 if (FAILED(hResult))
869 return hResult;
870 return connectionPoint->Advise(pUnk, pdw);
871 }
872
873 inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw)
874 {
875 CComPtr<IConnectionPointContainer> container;
876 CComPtr<IConnectionPoint> connectionPoint;
877 HRESULT hResult;
878
879 if (pUnkCP == NULL)
880 return E_INVALIDARG;
881 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container);
882 if (FAILED(hResult))
883 return hResult;
884 hResult = container->FindConnectionPoint(iid, &connectionPoint);
885 if (FAILED(hResult))
886 return hResult;
887 return connectionPoint->Unadvise(dw);
888 }
889
890 inline HRESULT __stdcall AtlInternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject)
891 {
892 int i;
893 IUnknown *resultInterface;
894 HRESULT hResult;
895
896 ATLASSERT(pThis != NULL && pEntries != NULL);
897 if (pThis == NULL || pEntries == NULL)
898 return E_INVALIDARG;
899 ATLASSERT(ppvObject != NULL);
900 if (ppvObject == NULL)
901 return E_POINTER;
902
903 if (InlineIsEqualUnknown(iid))
904 {
905 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[0].dw);
906 *ppvObject = resultInterface;
907 resultInterface->AddRef();
908 return S_OK;
909 }
910
911 i = 0;
912 while (pEntries[i].pFunc != 0)
913 {
914 if (pEntries[i].piid == NULL || InlineIsEqualGUID(iid, *pEntries[i].piid))
915 {
916 if (pEntries[i].pFunc == reinterpret_cast<_ATL_CREATORARGFUNC *>(1))
917 {
918 ATLASSERT(pEntries[i].piid != NULL);
919 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[i].dw);
920 *ppvObject = resultInterface;
921 resultInterface->AddRef();
922 return S_OK;
923 }
924 else
925 {
926 hResult = pEntries[i].pFunc(pThis, iid, ppvObject, 0);
927 if (hResult == S_OK || (FAILED(hResult) && pEntries[i].piid != NULL))
928 return hResult;
929 }
930 break;
931 }
932 i++;
933 }
934 *ppvObject = NULL;
935 return E_NOINTERFACE;
936 }
937
938 inline HRESULT __stdcall AtlWinModuleInit(_ATL_WIN_MODULE *pWinModule)
939 {
940 if (pWinModule == NULL)
941 return E_INVALIDARG;
942 pWinModule->m_pCreateWndList = NULL;
943 return pWinModule->m_csWindowCreate.Init();
944 }
945
946 inline HRESULT __stdcall AtlWinModuleTerm(_ATL_WIN_MODULE *pWinModule, HINSTANCE hInst)
947 {
948 if (pWinModule == NULL)
949 return E_INVALIDARG;
950 pWinModule->m_csWindowCreate.Term();
951 return S_OK;
952 }
953
954 inline void __stdcall AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pWinModule, _AtlCreateWndData *pData, void *pObject)
955 {
956 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true);
957
958 ATLASSERT(pWinModule != NULL);
959 ATLASSERT(pObject != NULL);
960
961 pData->m_pThis = pObject;
962 pData->m_dwThreadID = ::GetCurrentThreadId();
963 pData->m_pNext = pWinModule->m_pCreateWndList;
964 pWinModule->m_pCreateWndList = pData;
965 }
966
967 inline void *__stdcall AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *pWinModule)
968 {
969 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true);
970 void *result;
971 _AtlCreateWndData *currentEntry;
972 _AtlCreateWndData **previousLink;
973 DWORD threadID;
974
975 ATLASSERT(pWinModule != NULL);
976
977 result = NULL;
978 threadID = GetCurrentThreadId();
979 currentEntry = pWinModule->m_pCreateWndList;
980 previousLink = &pWinModule->m_pCreateWndList;
981 while (currentEntry != NULL)
982 {
983 if (currentEntry->m_dwThreadID == threadID)
984 {
985 *previousLink = currentEntry->m_pNext;
986 result = currentEntry->m_pThis;
987 break;
988 }
989 previousLink = &currentEntry->m_pNext;
990 currentEntry = currentEntry->m_pNext;
991 }
992 return result;
993 }
994
995 }; // namespace ATL
996
997 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
998 using namespace ATL;
999 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE