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