[atlnew]
[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 class CComMultiThreadModelNoCS
248 {
249 public:
250 typedef CComFakeCriticalSection AutoCriticalSection;
251 typedef CComFakeCriticalSection CriticalSection;
252 typedef CComMultiThreadModelNoCS ThreadModelNoCS;
253 typedef CComFakeCriticalSection AutoDeleteCriticalSection;
254
255 static ULONG WINAPI Increment(LPLONG p)
256 {
257 return InterlockedIncrement(p);
258 }
259
260 static ULONG WINAPI Decrement(LPLONG p)
261 {
262 return InterlockedDecrement(p);
263 }
264 };
265
266 class CComMultiThreadModel
267 {
268 public:
269 typedef CComAutoCriticalSection AutoCriticalSection;
270 typedef CComCriticalSection CriticalSection;
271 typedef CComMultiThreadModelNoCS ThreadModelNoCS;
272 typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection;
273
274 static ULONG WINAPI Increment(LPLONG p)
275 {
276 return InterlockedIncrement(p);
277 }
278
279 static ULONG WINAPI Decrement(LPLONG p)
280 {
281 return InterlockedDecrement(p);
282 }
283 };
284
285 class CComSingleThreadModel
286 {
287 public:
288 typedef CComFakeCriticalSection AutoCriticalSection;
289 typedef CComFakeCriticalSection CriticalSection;
290 typedef CComSingleThreadModel ThreadModelNoCS;
291 typedef CComFakeCriticalSection AutoDeleteCriticalSection;
292
293 static ULONG WINAPI Increment(LPLONG p)
294 {
295 return ++*p;
296 }
297
298 static ULONG WINAPI Decrement(LPLONG p)
299 {
300 return --*p;
301 }
302 };
303
304 #if defined(_ATL_FREE_THREADED)
305
306 typedef CComMultiThreadModel CComObjectThreadModel;
307 typedef CComMultiThreadModel CComGlobalsThreadModel;
308
309 #elif defined(_ATL_APARTMENT_THREADED)
310
311 typedef CComSingleThreadModel CComObjectThreadModel;
312 typedef CComMultiThreadModel CComGlobalsThreadModel;
313
314 #elif defined(_ATL_SINGLE_THREADED)
315
316 typedef CComSingleThreadModel CComObjectThreadModel;
317 typedef CComSingleThreadModel CComGlobalsThreadModel;
318
319 #else
320 #error No threading model
321 #endif
322
323 class CAtlModule : public _ATL_MODULE
324 {
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 template <class T>
430 class CAtlModuleT : public CAtlModule
431 {
432 public:
433
434 virtual HRESULT AddCommonRGSReplacements(IRegistrarBase *pRegistrar)
435 {
436 return pRegistrar->AddReplacement(L"APPID", T::GetAppId());
437 }
438
439 static LPCOLESTR GetAppId()
440 {
441 return L"";
442 }
443 };
444
445 class CAtlComModule : public _ATL_COM_MODULE
446 {
447 public:
448 CAtlComModule()
449 {
450 m_hInstTypeLib = reinterpret_cast<HINSTANCE>(&__ImageBase);
451 m_ppAutoObjMapFirst = NULL;
452 m_ppAutoObjMapLast = NULL;
453 if (FAILED(m_csObjMap.Init()))
454 {
455 ATLASSERT(0);
456 CAtlBaseModule::m_bInitFailed = true;
457 return;
458 }
459 cbSize = sizeof(_ATL_COM_MODULE);
460 }
461
462 ~CAtlComModule()
463 {
464 Term();
465 }
466
467 void Term()
468 {
469 if (cbSize != 0)
470 {
471 ATLASSERT(m_ppAutoObjMapFirst == NULL);
472 ATLASSERT(m_ppAutoObjMapLast == NULL);
473 m_csObjMap.Term();
474 cbSize = 0;
475 }
476 }
477 };
478
479 template <class T>
480 class CAtlDllModuleT : public CAtlModuleT<T>
481 {
482 public:
483 CAtlDllModuleT()
484 {
485 }
486
487 HRESULT DllCanUnloadNow()
488 {
489 T *pThis;
490
491 pThis = static_cast<T *>(this);
492 if (pThis->GetLockCount() == 0)
493 return S_OK;
494 return S_FALSE;
495 }
496
497 HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
498 {
499 T *pThis;
500
501 pThis = static_cast<T *>(this);
502 return pThis->GetClassObject(rclsid, riid, ppv);
503 }
504
505 HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE)
506 {
507 T *pThis;
508 HRESULT hResult;
509
510 pThis = static_cast<T *>(this);
511 hResult = pThis->RegisterServer(bRegTypeLib);
512 return hResult;
513 }
514
515 HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE)
516 {
517 T *pThis;
518 HRESULT hResult;
519
520 pThis = static_cast<T *>(this);
521 hResult = pThis->UnregisterServer(bUnRegTypeLib);
522 return hResult;
523 }
524
525 HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
526 {
527 return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv);
528 }
529 };
530
531 class CComModule : public CAtlModuleT<CComModule>
532 {
533 public:
534 _ATL_OBJMAP_ENTRY *m_pObjMap;
535 public:
536 CComModule()
537 {
538 ATLASSERT(_pModule == NULL);
539 _pModule = this;
540 }
541
542 ~CComModule()
543 {
544 _pModule = NULL;
545 }
546
547 HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
548 {
549 _ATL_OBJMAP_ENTRY *objectMapEntry;
550 HRESULT hResult;
551
552 ATLASSERT(ppv != NULL);
553 if (ppv == NULL)
554 return E_POINTER;
555 hResult = S_OK;
556 if (m_pObjMap != NULL)
557 {
558 objectMapEntry = m_pObjMap;
559 while (objectMapEntry->pclsid != NULL)
560 {
561 if (objectMapEntry->pfnGetClassObject != NULL && InlineIsEqualGUID(rclsid, *objectMapEntry->pclsid) != FALSE)
562 {
563 if (objectMapEntry->pCF == NULL)
564 {
565 CComCritSecLock<CComCriticalSection> lock(_AtlComModule.m_csObjMap, true);
566
567 if (objectMapEntry->pCF == NULL)
568 hResult = objectMapEntry->pfnGetClassObject(reinterpret_cast<void *>(objectMapEntry->pfnCreateInstance), IID_IUnknown, reinterpret_cast<LPVOID *>(&objectMapEntry->pCF));
569 }
570 if (objectMapEntry->pCF != NULL)
571 hResult = objectMapEntry->pCF->QueryInterface(riid, ppv);
572 break;
573 }
574 objectMapEntry++;
575 }
576 }
577 return hResult;
578 }
579
580 HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL)
581 {
582 _ATL_OBJMAP_ENTRY *objectMapEntry;
583 HRESULT hResult;
584
585 hResult = S_OK;
586 objectMapEntry = m_pObjMap;
587 if (objectMapEntry != NULL)
588 {
589 while (objectMapEntry->pclsid != NULL)
590 {
591 if (pCLSID == NULL || IsEqualGUID(*pCLSID, *objectMapEntry->pclsid) != FALSE)
592 {
593 hResult = objectMapEntry->pfnUpdateRegistry(TRUE);
594 if (FAILED(hResult))
595 break;
596 }
597 objectMapEntry++;
598 }
599 }
600 return hResult;
601 }
602
603 HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL)
604 {
605 _ATL_OBJMAP_ENTRY *objectMapEntry;
606 HRESULT hResult;
607
608 hResult = S_OK;
609 objectMapEntry = m_pObjMap;
610 if (objectMapEntry != NULL)
611 {
612 while (objectMapEntry->pclsid != NULL)
613 {
614 if (pCLSID == NULL || IsEqualGUID(*pCLSID, *objectMapEntry->pclsid) != FALSE)
615 {
616 hResult = objectMapEntry->pfnUpdateRegistry(FALSE); //unregister
617 if (FAILED(hResult))
618 break;
619 }
620 objectMapEntry++;
621 }
622 }
623 return hResult;
624 }
625
626 HRESULT DllCanUnloadNow()
627 {
628 if (GetLockCount() == 0)
629 return S_OK;
630 return S_FALSE;
631 }
632
633 HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
634 {
635 return GetClassObject(rclsid, riid, ppv);
636 }
637
638 HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE)
639 {
640 return RegisterServer(bRegTypeLib);
641 }
642
643 HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE)
644 {
645 return UnregisterServer(bUnRegTypeLib);
646 }
647
648 };
649
650 class CAtlWinModule : public _ATL_WIN_MODULE
651 {
652 public:
653 CAtlWinModule()
654 {
655 HRESULT hResult;
656
657 hResult = AtlWinModuleInit(this);
658 if (FAILED(hResult))
659 {
660 CAtlBaseModule::m_bInitFailed = true;
661 ATLASSERT(0);
662 }
663 }
664
665 ~CAtlWinModule()
666 {
667 Term();
668 }
669
670 void Term()
671 {
672 AtlWinModuleTerm(this, _AtlBaseModule.GetModuleInstance());
673 }
674
675 void AddCreateWndData(_AtlCreateWndData *pData, void *pObject)
676 {
677 AtlWinModuleAddCreateWndData(this, pData, pObject);
678 }
679
680 void *ExtractCreateWndData()
681 {
682 return AtlWinModuleExtractCreateWndData(this);
683 }
684 };
685
686 extern CAtlWinModule _AtlWinModule;
687
688 template<class T>
689 class CComPtr
690 {
691 public:
692 T *p;
693 public:
694 CComPtr()
695 {
696 p = NULL;
697 }
698
699 CComPtr(T *lp)
700 {
701 p = lp;
702 if (p != NULL)
703 p->AddRef();
704 }
705
706 CComPtr(const CComPtr<T> &lp)
707 {
708 p = lp.p;
709 if (p != NULL)
710 p->AddRef();
711 }
712
713 ~CComPtr()
714 {
715 if (p != NULL)
716 p->Release();
717 }
718
719 T *operator = (T *lp)
720 {
721 if (p != NULL)
722 p->Release();
723 p = lp;
724 if (p != NULL)
725 p->AddRef();
726 return *this;
727 }
728
729 T *operator = (const CComPtr<T> &lp)
730 {
731 if (p != NULL)
732 p->Release();
733 p = lp.p;
734 if (p != NULL)
735 p->AddRef();
736 return *this;
737 }
738
739 void Release()
740 {
741 if (p != NULL)
742 {
743 p->Release();
744 p = NULL;
745 }
746 }
747
748 void Attach(T *lp)
749 {
750 if (p != NULL)
751 p->Release();
752 p = lp;
753 }
754
755 T *Detach()
756 {
757 T *saveP;
758
759 saveP = p;
760 p = NULL;
761 return saveP;
762 }
763
764 T **operator & ()
765 {
766 ATLASSERT(p == NULL);
767 return &p;
768 }
769
770 operator T * ()
771 {
772 return p;
773 }
774
775 T *operator -> ()
776 {
777 ATLASSERT(p != NULL);
778 return p;
779 }
780 };
781
782 class CComBSTR
783 {
784 public:
785 BSTR m_str;
786 public:
787 CComBSTR(LPCOLESTR pSrc)
788 {
789 if (pSrc == NULL)
790 m_str = NULL;
791 else
792 m_str = ::SysAllocString(pSrc);
793 }
794 ~CComBSTR()
795 {
796 ::SysFreeString(m_str);
797 m_str = NULL;
798 }
799 };
800
801 class CComVariant : public tagVARIANT
802 {
803 public:
804 CComVariant()
805 {
806 ::VariantInit(this);
807 }
808
809 ~CComVariant()
810 {
811 Clear();
812 }
813
814 HRESULT Clear()
815 {
816 return ::VariantClear(this);
817 }
818 };
819
820 inline HRESULT __stdcall AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID &iid, LPDWORD pdw)
821 {
822 CComPtr<IConnectionPointContainer> container;
823 CComPtr<IConnectionPoint> connectionPoint;
824 HRESULT hResult;
825
826 if (pUnkCP == NULL)
827 return E_INVALIDARG;
828 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container);
829 if (FAILED(hResult))
830 return hResult;
831 hResult = container->FindConnectionPoint(iid, &connectionPoint);
832 if (FAILED(hResult))
833 return hResult;
834 return connectionPoint->Advise(pUnk, pdw);
835 }
836
837 inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw)
838 {
839 CComPtr<IConnectionPointContainer> container;
840 CComPtr<IConnectionPoint> connectionPoint;
841 HRESULT hResult;
842
843 if (pUnkCP == NULL)
844 return E_INVALIDARG;
845 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container);
846 if (FAILED(hResult))
847 return hResult;
848 hResult = container->FindConnectionPoint(iid, &connectionPoint);
849 if (FAILED(hResult))
850 return hResult;
851 return connectionPoint->Unadvise(dw);
852 }
853
854 inline HRESULT __stdcall AtlInternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject)
855 {
856 int i;
857 IUnknown *resultInterface;
858 HRESULT hResult;
859
860 ATLASSERT(pThis != NULL && pEntries != NULL);
861 if (pThis == NULL || pEntries == NULL)
862 return E_INVALIDARG;
863 ATLASSERT(ppvObject != NULL);
864 if (ppvObject == NULL)
865 return E_POINTER;
866
867 if (InlineIsEqualUnknown(iid))
868 {
869 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[0].dw);
870 *ppvObject = resultInterface;
871 resultInterface->AddRef();
872 return S_OK;
873 }
874
875 i = 0;
876 while (pEntries[i].pFunc != 0)
877 {
878 if (pEntries[i].piid == NULL || InlineIsEqualGUID(iid, *pEntries[i].piid))
879 {
880 if (pEntries[i].pFunc == reinterpret_cast<_ATL_CREATORARGFUNC *>(1))
881 {
882 ATLASSERT(pEntries[i].piid != NULL);
883 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[i].dw);
884 *ppvObject = resultInterface;
885 resultInterface->AddRef();
886 return S_OK;
887 }
888 else
889 {
890 hResult = pEntries[i].pFunc(pThis, iid, ppvObject, 0);
891 if (hResult == S_OK || (FAILED(hResult) && pEntries[i].piid != NULL))
892 return hResult;
893 }
894 break;
895 }
896 i++;
897 }
898 *ppvObject = NULL;
899 return E_NOINTERFACE;
900 }
901
902 inline HRESULT __stdcall AtlWinModuleInit(_ATL_WIN_MODULE *pWinModule)
903 {
904 if (pWinModule == NULL)
905 return E_INVALIDARG;
906 pWinModule->m_pCreateWndList = NULL;
907 return pWinModule->m_csWindowCreate.Init();
908 }
909
910 inline HRESULT __stdcall AtlWinModuleTerm(_ATL_WIN_MODULE *pWinModule, HINSTANCE hInst)
911 {
912 if (pWinModule == NULL)
913 return E_INVALIDARG;
914 pWinModule->m_csWindowCreate.Term();
915 return S_OK;
916 }
917
918 inline void __stdcall AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pWinModule, _AtlCreateWndData *pData, void *pObject)
919 {
920 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true);
921
922 ATLASSERT(pWinModule != NULL);
923 ATLASSERT(pObject != NULL);
924
925 pData->m_pThis = pObject;
926 pData->m_dwThreadID = ::GetCurrentThreadId();
927 pData->m_pNext = pWinModule->m_pCreateWndList;
928 pWinModule->m_pCreateWndList = pData;
929 }
930
931 inline void *__stdcall AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *pWinModule)
932 {
933 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true);
934 void *result;
935 _AtlCreateWndData *currentEntry;
936 _AtlCreateWndData **previousLink;
937 DWORD threadID;
938
939 ATLASSERT(pWinModule != NULL);
940
941 result = NULL;
942 threadID = GetCurrentThreadId();
943 currentEntry = pWinModule->m_pCreateWndList;
944 previousLink = &pWinModule->m_pCreateWndList;
945 while (currentEntry != NULL)
946 {
947 if (currentEntry->m_dwThreadID == threadID)
948 {
949 *previousLink = currentEntry->m_pNext;
950 result = currentEntry->m_pThis;
951 break;
952 }
953 previousLink = &currentEntry->m_pNext;
954 currentEntry = currentEntry->m_pNext;
955 }
956 return result;
957 }
958
959 }; // namespace ATL
960
961 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
962 using namespace ATL;
963 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE
964
965 #endif // _atlbase_h