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