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