Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / sdk / lib / atl / atlbase.h
1 /*
2 * ReactOS ATL
3 *
4 * Copyright 2009 Andrew Hill <ash77@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #pragma once
22
23 #include "atlcore.h"
24 #include "statreg.h"
25 #include "atlcomcli.h"
26 #include "atlalloc.h"
27 #include "comcat.h"
28 #include "tchar.h"
29
30 #ifdef _MSC_VER
31 // It is common to use this in ATL constructors. They only store this for later use, so the usage is safe.
32 #pragma warning(disable:4355)
33 #endif
34
35 #ifndef _ATL_PACKING
36 #define _ATL_PACKING 8
37 #endif
38
39 #ifndef _ATL_FREE_THREADED
40 #ifndef _ATL_APARTMENT_THREADED
41 #ifndef _ATL_SINGLE_THREADED
42 #define _ATL_FREE_THREADED
43 #endif
44 #endif
45 #endif
46
47 #ifndef ATLTRY
48 #define ATLTRY(x) x;
49 #endif
50
51 #ifdef _ATL_DISABLE_NO_VTABLE
52 #define ATL_NO_VTABLE
53 #else
54 #define ATL_NO_VTABLE __declspec(novtable)
55 #endif
56
57 #ifndef ATL_DEPRECATED
58 #define ATL_DEPRECATED __declspec(deprecated)
59 #endif
60
61 #define offsetofclass(base, derived) (reinterpret_cast<DWORD_PTR>(static_cast<base *>(reinterpret_cast<derived *>(_ATL_PACKING))) - _ATL_PACKING)
62
63 namespace ATL
64 {
65
66 class CAtlModule;
67 class CComModule;
68 class CAtlComModule;
69 __declspec(selectany) CAtlModule *_pAtlModule = NULL;
70 __declspec(selectany) CComModule *_pModule = NULL;
71 extern CAtlComModule _AtlComModule;
72
73
74 struct _ATL_CATMAP_ENTRY
75 {
76 int iType;
77 const GUID* pcatid;
78 };
79
80 #define _ATL_CATMAP_ENTRY_END 0
81 #define _ATL_CATMAP_ENTRY_IMPLEMENTED 1
82 #define _ATL_CATMAP_ENTRY_REQUIRED 2
83
84
85 typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void *pv, REFIID riid, LPVOID *ppv);
86 typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC)();
87 typedef const struct _ATL_CATMAP_ENTRY * (_ATL_CATMAPFUNC)();
88
89 struct _ATL_OBJMAP_ENTRY30
90 {
91 const CLSID *pclsid;
92 HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);
93 _ATL_CREATORFUNC *pfnGetClassObject;
94 _ATL_CREATORFUNC *pfnCreateInstance;
95 IUnknown *pCF;
96 DWORD dwRegister;
97 _ATL_DESCRIPTIONFUNC *pfnGetObjectDescription;
98 _ATL_CATMAPFUNC *pfnGetCategoryMap;
99 void (WINAPI *pfnObjectMain)(bool bStarting);
100
101 HRESULT WINAPI RevokeClassObject()
102 {
103 if (dwRegister == 0)
104 return S_OK;
105 return CoRevokeClassObject(dwRegister);
106 }
107
108 HRESULT WINAPI RegisterClassObject(DWORD dwClsContext, DWORD dwFlags)
109 {
110 IUnknown *p;
111 HRESULT hResult;
112
113 p = NULL;
114 if (pfnGetClassObject == NULL)
115 return S_OK;
116
117 hResult = pfnGetClassObject(reinterpret_cast<LPVOID *>(pfnCreateInstance), IID_IUnknown, reinterpret_cast<LPVOID *>(&p));
118 if (SUCCEEDED(hResult))
119 hResult = CoRegisterClassObject(*pclsid, p, dwClsContext, dwFlags, &dwRegister);
120
121 if (p != NULL)
122 p->Release();
123
124 return hResult;
125 }
126 };
127
128 typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY;
129
130 typedef void (__stdcall _ATL_TERMFUNC)(DWORD_PTR dw);
131
132 struct _ATL_TERMFUNC_ELEM
133 {
134 _ATL_TERMFUNC *pFunc;
135 DWORD_PTR dw;
136 _ATL_TERMFUNC_ELEM *pNext;
137 };
138
139 struct _ATL_MODULE70
140 {
141 UINT cbSize;
142 LONG m_nLockCnt;
143 _ATL_TERMFUNC_ELEM *m_pTermFuncs;
144 CComCriticalSection m_csStaticDataInitAndTypeInfo;
145 };
146 typedef _ATL_MODULE70 _ATL_MODULE;
147
148 typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void *pv, REFIID riid, LPVOID *ppv, DWORD_PTR dw);
149
150 #define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC *)1)
151
152 struct _ATL_INTMAP_ENTRY
153 {
154 const IID *piid;
155 DWORD_PTR dw;
156 _ATL_CREATORARGFUNC *pFunc;
157 };
158
159 struct _AtlCreateWndData
160 {
161 void *m_pThis;
162 DWORD m_dwThreadID;
163 _AtlCreateWndData *m_pNext;
164 };
165
166 struct _ATL_COM_MODULE70
167 {
168 UINT cbSize;
169 HINSTANCE m_hInstTypeLib;
170 _ATL_OBJMAP_ENTRY **m_ppAutoObjMapFirst;
171 _ATL_OBJMAP_ENTRY **m_ppAutoObjMapLast;
172 CComCriticalSection m_csObjMap;
173 };
174 typedef _ATL_COM_MODULE70 _ATL_COM_MODULE;
175
176 struct _ATL_WIN_MODULE70
177 {
178 UINT cbSize;
179 CComCriticalSection m_csWindowCreate;
180 _AtlCreateWndData *m_pCreateWndList;
181 #ifdef NOTYET
182 CSimpleArray<ATOM> m_rgWindowClassAtoms;
183 #endif
184 };
185 typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE;
186
187 struct _ATL_REGMAP_ENTRY
188 {
189 LPCOLESTR szKey;
190 LPCOLESTR szData;
191 };
192
193 HRESULT __stdcall AtlWinModuleInit(_ATL_WIN_MODULE *pWinModule);
194 HRESULT __stdcall AtlWinModuleTerm(_ATL_WIN_MODULE *pWinModule, HINSTANCE hInst);
195 HRESULT __stdcall AtlInternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject);
196 void __stdcall AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pWinModule, _AtlCreateWndData *pData, void *pObject);
197 void *__stdcall AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *pWinModule);
198 HRESULT __stdcall AtlComModuleGetClassObject(_ATL_COM_MODULE *pComModule, REFCLSID rclsid, REFIID riid, LPVOID *ppv);
199
200 HRESULT __stdcall AtlComModuleRegisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid);
201 HRESULT __stdcall AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid);
202
203
204 template<class TLock>
205 class CComCritSecLock
206 {
207 private:
208 bool m_bLocked;
209 TLock &m_cs;
210 public:
211 CComCritSecLock(TLock &cs, bool bInitialLock = true) : m_cs(cs)
212 {
213 HRESULT hResult;
214
215 m_bLocked = false;
216 if (bInitialLock)
217 {
218 hResult = Lock();
219 if (FAILED(hResult))
220 {
221 ATLASSERT(false);
222 }
223 }
224 }
225
226 ~CComCritSecLock()
227 {
228 if (m_bLocked)
229 Unlock();
230 }
231
232 HRESULT Lock()
233 {
234 HRESULT hResult;
235
236 ATLASSERT(!m_bLocked);
237 hResult = m_cs.Lock();
238 if (FAILED(hResult))
239 return hResult;
240 m_bLocked = true;
241
242 return S_OK;
243 }
244
245 void Unlock()
246 {
247 HRESULT hResult;
248
249 ATLASSERT(m_bLocked);
250 hResult = m_cs.Unlock();
251 if (FAILED(hResult))
252 {
253 ATLASSERT(false);
254 }
255 m_bLocked = false;
256 }
257 };
258
259
260 class CHandle
261 {
262 public:
263 HANDLE m_handle;
264
265 public:
266 CHandle() :
267 m_handle(NULL)
268 {
269 }
270
271 CHandle(_Inout_ CHandle& handle) :
272 m_handle(NULL)
273 {
274 Attach(handle.Detach());
275 }
276
277 explicit CHandle(_In_ HANDLE handle) :
278 m_handle(handle)
279 {
280 }
281
282 ~CHandle()
283 {
284 if (m_handle)
285 {
286 Close();
287 }
288 }
289
290 CHandle& operator=(_Inout_ CHandle& handle)
291 {
292 if (this != &handle)
293 {
294 if (m_handle)
295 {
296 Close();
297 }
298 Attach(handle.Detach());
299 }
300
301 return *this;
302 }
303
304 operator HANDLE() const
305 {
306 return m_handle;
307 }
308
309 void Attach(_In_ HANDLE handle)
310 {
311 ATLASSERT(m_handle == NULL);
312 m_handle = handle;
313 }
314
315 HANDLE Detach()
316 {
317 HANDLE handle = m_handle;
318 m_handle = NULL;
319 return handle;
320 }
321
322 void Close()
323 {
324 if (m_handle)
325 {
326 ::CloseHandle(m_handle);
327 m_handle = NULL;
328 }
329 }
330 };
331
332
333 inline BOOL WINAPI InlineIsEqualUnknown(REFGUID rguid1)
334 {
335 return (
336 ((unsigned long *)&rguid1)[0] == 0 &&
337 ((unsigned long *)&rguid1)[1] == 0 &&
338 ((unsigned long *)&rguid1)[2] == 0x000000C0 &&
339 ((unsigned long *)&rguid1)[3] == 0x46000000);
340 }
341
342 class CComMultiThreadModelNoCS
343 {
344 public:
345 typedef CComFakeCriticalSection AutoCriticalSection;
346 typedef CComFakeCriticalSection CriticalSection;
347 typedef CComMultiThreadModelNoCS ThreadModelNoCS;
348 typedef CComFakeCriticalSection AutoDeleteCriticalSection;
349
350 static ULONG WINAPI Increment(LPLONG p)
351 {
352 return InterlockedIncrement(p);
353 }
354
355 static ULONG WINAPI Decrement(LPLONG p)
356 {
357 return InterlockedDecrement(p);
358 }
359 };
360
361 class CComMultiThreadModel
362 {
363 public:
364 typedef CComAutoCriticalSection AutoCriticalSection;
365 typedef CComCriticalSection CriticalSection;
366 typedef CComMultiThreadModelNoCS ThreadModelNoCS;
367 typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection;
368
369 static ULONG WINAPI Increment(LPLONG p)
370 {
371 return InterlockedIncrement(p);
372 }
373
374 static ULONG WINAPI Decrement(LPLONG p)
375 {
376 return InterlockedDecrement(p);
377 }
378 };
379
380 class CComSingleThreadModel
381 {
382 public:
383 typedef CComFakeCriticalSection AutoCriticalSection;
384 typedef CComFakeCriticalSection CriticalSection;
385 typedef CComSingleThreadModel ThreadModelNoCS;
386 typedef CComFakeCriticalSection AutoDeleteCriticalSection;
387
388 static ULONG WINAPI Increment(LPLONG p)
389 {
390 return ++*p;
391 }
392
393 static ULONG WINAPI Decrement(LPLONG p)
394 {
395 return --*p;
396 }
397 };
398
399 #if defined(_ATL_FREE_THREADED)
400
401 typedef CComMultiThreadModel CComObjectThreadModel;
402 typedef CComMultiThreadModel CComGlobalsThreadModel;
403
404 #elif defined(_ATL_APARTMENT_THREADED)
405
406 typedef CComSingleThreadModel CComObjectThreadModel;
407 typedef CComMultiThreadModel CComGlobalsThreadModel;
408
409 #elif defined(_ATL_SINGLE_THREADED)
410
411 typedef CComSingleThreadModel CComObjectThreadModel;
412 typedef CComSingleThreadModel CComGlobalsThreadModel;
413
414 #else
415 #error No threading model
416 #endif
417
418 class CAtlModule : public _ATL_MODULE
419 {
420 public:
421 static GUID m_libid;
422
423 CAtlModule()
424 {
425 ATLASSERT(_pAtlModule == NULL);
426 _pAtlModule = this;
427 cbSize = sizeof(_ATL_MODULE);
428 m_nLockCnt = 0;
429 }
430
431 virtual LONG GetLockCount()
432 {
433 return m_nLockCnt;
434 }
435
436 virtual LONG Lock()
437 {
438 return CComGlobalsThreadModel::Increment(&m_nLockCnt);
439 }
440
441 virtual LONG Unlock()
442 {
443 return CComGlobalsThreadModel::Decrement(&m_nLockCnt);
444 }
445
446 virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* /*pRegistrar*/) = 0;
447
448 HRESULT WINAPI UpdateRegistryFromResource(LPCTSTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY *pMapEntries = NULL)
449 {
450 CRegObject registrar;
451 WCHAR modulePath[MAX_PATH];
452 HRESULT hResult;
453 PCWSTR lpwszRes;
454
455 hResult = CommonInitRegistrar(registrar, modulePath, sizeof(modulePath) / sizeof(modulePath[0]), pMapEntries);
456 if (FAILED(hResult))
457 return hResult;
458 #ifdef UNICODE
459 lpwszRes = lpszRes;
460 #else
461 /* FIXME: this is a bit of a hack, need to re-evaluate */
462 WCHAR resid[MAX_PATH];
463 MultiByteToWideChar(CP_ACP, 0, lpszRes, -1, resid, MAX_PATH);
464 lpwszRes = resid;
465 #endif
466 if (bRegister != FALSE)
467 hResult = registrar.ResourceRegisterSz(modulePath, lpwszRes, L"REGISTRY");
468 else
469 hResult = registrar.ResourceUnregisterSz(modulePath, lpwszRes, L"REGISTRY");
470
471 return hResult;
472 }
473
474 HRESULT WINAPI UpdateRegistryFromResource(UINT nResID, BOOL bRegister, struct _ATL_REGMAP_ENTRY *pMapEntries = NULL)
475 {
476 CRegObject registrar;
477 WCHAR modulePath[MAX_PATH];
478 HRESULT hResult;
479
480 hResult = CommonInitRegistrar(registrar, modulePath, sizeof(modulePath) / sizeof(modulePath[0]), pMapEntries);
481 if (FAILED(hResult))
482 return hResult;
483
484 if (bRegister != FALSE)
485 hResult = registrar.ResourceRegister(modulePath, nResID, L"REGISTRY");
486 else
487 hResult = registrar.ResourceUnregister(modulePath, nResID, L"REGISTRY");
488
489 return hResult;
490 }
491
492 private:
493 HRESULT CommonInitRegistrar(CRegObject &registrar, WCHAR *modulePath, DWORD modulePathCount, struct _ATL_REGMAP_ENTRY *pMapEntries)
494 {
495 HINSTANCE hInstance;
496 DWORD dwFLen;
497 HRESULT hResult;
498
499 hInstance = _AtlBaseModule.GetModuleInstance();
500 dwFLen = GetModuleFileNameW(hInstance, modulePath, modulePathCount);
501 if (dwFLen == modulePathCount)
502 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
503 else if (dwFLen == 0)
504 return HRESULT_FROM_WIN32(GetLastError());
505
506 if (pMapEntries != NULL)
507 {
508 while (pMapEntries->szKey != NULL)
509 {
510 ATLASSERT(pMapEntries->szData != NULL);
511 hResult = registrar.AddReplacement(pMapEntries->szKey, pMapEntries->szData);
512 if (FAILED(hResult))
513 return hResult;
514 pMapEntries++;
515 }
516 }
517
518 hResult = AddCommonRGSReplacements(&registrar);
519 if (FAILED(hResult))
520 return hResult;
521
522 hResult = registrar.AddReplacement(L"Module", modulePath);
523 if (FAILED(hResult))
524 return hResult;
525
526 hResult = registrar.AddReplacement(L"Module_Raw", modulePath);
527 if (FAILED(hResult))
528 return hResult;
529
530 return S_OK;
531 }
532 };
533
534 __declspec(selectany) GUID CAtlModule::m_libid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
535
536 template <class T>
537 class CAtlModuleT : public CAtlModule
538 {
539 public:
540
541 HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL);
542 HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL);
543
544
545 virtual HRESULT AddCommonRGSReplacements(IRegistrarBase *pRegistrar)
546 {
547 return pRegistrar->AddReplacement(L"APPID", T::GetAppId());
548 }
549
550 static LPCOLESTR GetAppId()
551 {
552 return L"";
553 }
554 };
555
556 class CAtlComModule : public _ATL_COM_MODULE
557 {
558 public:
559 CAtlComModule()
560 {
561 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)this, &m_hInstTypeLib);
562 m_ppAutoObjMapFirst = NULL;
563 m_ppAutoObjMapLast = NULL;
564 if (FAILED(m_csObjMap.Init()))
565 {
566 ATLASSERT(0);
567 CAtlBaseModule::m_bInitFailed = true;
568 return;
569 }
570 cbSize = sizeof(_ATL_COM_MODULE);
571 }
572
573 ~CAtlComModule()
574 {
575 Term();
576 }
577
578 HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL)
579 {
580 return AtlComModuleRegisterServer(this, bRegTypeLib, pCLSID);
581 }
582
583 HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL)
584 {
585 return AtlComModuleUnregisterServer(this, bUnRegTypeLib, pCLSID);
586 }
587
588
589 void Term()
590 {
591 if (cbSize != 0)
592 {
593 ATLASSERT(m_ppAutoObjMapFirst == NULL);
594 ATLASSERT(m_ppAutoObjMapLast == NULL);
595 m_csObjMap.Term();
596 cbSize = 0;
597 }
598 }
599 };
600
601 template <class T>
602 HRESULT CAtlModuleT<T>::RegisterServer(BOOL bRegTypeLib, const CLSID *pCLSID)
603 {
604 return _AtlComModule.RegisterServer(bRegTypeLib, pCLSID);
605 }
606
607 template <class T>
608 HRESULT CAtlModuleT<T>::UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID)
609 {
610 return _AtlComModule.UnregisterServer(bUnRegTypeLib, pCLSID);
611 }
612
613 template <class T>
614 class CAtlDllModuleT : public CAtlModuleT<T>
615 {
616 public:
617 CAtlDllModuleT()
618 {
619 }
620
621 HRESULT DllCanUnloadNow()
622 {
623 T *pThis;
624
625 pThis = static_cast<T *>(this);
626 if (pThis->GetLockCount() == 0)
627 return S_OK;
628 return S_FALSE;
629 }
630
631 HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
632 {
633 T *pThis;
634
635 pThis = static_cast<T *>(this);
636 return pThis->GetClassObject(rclsid, riid, ppv);
637 }
638
639 HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE)
640 {
641 T *pThis;
642 HRESULT hResult;
643
644 pThis = static_cast<T *>(this);
645 hResult = pThis->RegisterServer(bRegTypeLib);
646 return hResult;
647 }
648
649 HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE)
650 {
651 T *pThis;
652 HRESULT hResult;
653
654 pThis = static_cast<T *>(this);
655 hResult = pThis->UnregisterServer(bUnRegTypeLib);
656 return hResult;
657 }
658
659 HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
660 {
661 return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv);
662 }
663 };
664
665 class CComModule : public CAtlModuleT<CComModule>
666 {
667 public:
668 _ATL_OBJMAP_ENTRY *m_pObjMap;
669 public:
670 CComModule()
671 {
672 ATLASSERT(_pModule == NULL);
673 _pModule = this;
674 _pModule->m_pObjMap = NULL;
675 }
676
677 ~CComModule()
678 {
679 _pModule = NULL;
680 }
681
682 HRESULT Init(_ATL_OBJMAP_ENTRY *p, HINSTANCE /* h */, const GUID *plibid)
683 {
684 _ATL_OBJMAP_ENTRY *objectMapEntry;
685
686 if (plibid != NULL)
687 m_libid = *plibid;
688
689 if (p != reinterpret_cast<_ATL_OBJMAP_ENTRY *>(-1))
690 {
691 m_pObjMap = p;
692 if (p != NULL)
693 {
694 objectMapEntry = p;
695 while (objectMapEntry->pclsid != NULL)
696 {
697 objectMapEntry->pfnObjectMain(true);
698 objectMapEntry++;
699 }
700 }
701 }
702 return S_OK;
703 }
704
705 void Term()
706 {
707 _ATL_OBJMAP_ENTRY *objectMapEntry;
708
709 if (m_pObjMap != NULL)
710 {
711 objectMapEntry = m_pObjMap;
712 while (objectMapEntry->pclsid != NULL)
713 {
714 if (objectMapEntry->pCF != NULL)
715 objectMapEntry->pCF->Release();
716 objectMapEntry->pCF = NULL;
717 objectMapEntry->pfnObjectMain(false);
718 objectMapEntry++;
719 }
720 }
721 }
722
723 HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
724 {
725 _ATL_OBJMAP_ENTRY *objectMapEntry;
726 HRESULT hResult;
727
728 ATLASSERT(ppv != NULL);
729 if (ppv == NULL)
730 return E_POINTER;
731 *ppv = NULL;
732 hResult = S_OK;
733 if (m_pObjMap != NULL)
734 {
735 objectMapEntry = m_pObjMap;
736 while (objectMapEntry->pclsid != NULL)
737 {
738 if (objectMapEntry->pfnGetClassObject != NULL && InlineIsEqualGUID(rclsid, *objectMapEntry->pclsid) != FALSE)
739 {
740 if (objectMapEntry->pCF == NULL)
741 {
742 CComCritSecLock<CComCriticalSection> lock(_AtlComModule.m_csObjMap, true);
743
744 if (objectMapEntry->pCF == NULL)
745 hResult = objectMapEntry->pfnGetClassObject(reinterpret_cast<void *>(objectMapEntry->pfnCreateInstance), IID_IUnknown, reinterpret_cast<LPVOID *>(&objectMapEntry->pCF));
746 }
747 if (objectMapEntry->pCF != NULL)
748 hResult = objectMapEntry->pCF->QueryInterface(riid, ppv);
749 break;
750 }
751 objectMapEntry++;
752 }
753 }
754 if (hResult == S_OK && *ppv == NULL)
755 {
756 // FIXME: call AtlComModuleGetClassObject
757 hResult = CLASS_E_CLASSNOTAVAILABLE;
758 }
759 return hResult;
760 }
761
762 HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL)
763 {
764 _ATL_OBJMAP_ENTRY *objectMapEntry;
765 HRESULT hResult;
766
767 hResult = S_OK;
768 objectMapEntry = m_pObjMap;
769 if (objectMapEntry != NULL)
770 {
771 while (objectMapEntry->pclsid != NULL)
772 {
773 if (pCLSID == NULL || IsEqualGUID(*pCLSID, *objectMapEntry->pclsid) != FALSE)
774 {
775 hResult = objectMapEntry->pfnUpdateRegistry(TRUE);
776 if (FAILED(hResult))
777 break;
778 }
779 objectMapEntry++;
780 }
781 }
782 if (SUCCEEDED(hResult))
783 hResult = CAtlModuleT<CComModule>::RegisterServer(bRegTypeLib, pCLSID);
784 return hResult;
785 }
786
787 HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL)
788 {
789 _ATL_OBJMAP_ENTRY *objectMapEntry;
790 HRESULT hResult;
791
792 hResult = S_OK;
793 objectMapEntry = m_pObjMap;
794 if (objectMapEntry != NULL)
795 {
796 while (objectMapEntry->pclsid != NULL)
797 {
798 if (pCLSID == NULL || IsEqualGUID(*pCLSID, *objectMapEntry->pclsid) != FALSE)
799 {
800 hResult = objectMapEntry->pfnUpdateRegistry(FALSE); //unregister
801 if (FAILED(hResult))
802 break;
803 }
804 objectMapEntry++;
805 }
806 }
807 if (SUCCEEDED(hResult))
808 hResult = CAtlModuleT<CComModule>::UnregisterServer(bUnRegTypeLib, pCLSID);
809
810 return hResult;
811 }
812
813 HRESULT DllCanUnloadNow()
814 {
815 if (GetLockCount() == 0)
816 return S_OK;
817 return S_FALSE;
818 }
819
820 HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
821 {
822 return GetClassObject(rclsid, riid, ppv);
823 }
824
825 HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE)
826 {
827 return RegisterServer(bRegTypeLib);
828 }
829
830 HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE)
831 {
832 return UnregisterServer(bUnRegTypeLib);
833 }
834
835 };
836
837 class CAtlWinModule : public _ATL_WIN_MODULE
838 {
839 public:
840 CAtlWinModule()
841 {
842 HRESULT hResult;
843
844 hResult = AtlWinModuleInit(this);
845 if (FAILED(hResult))
846 {
847 CAtlBaseModule::m_bInitFailed = true;
848 ATLASSERT(0);
849 }
850 }
851
852 ~CAtlWinModule()
853 {
854 Term();
855 }
856
857 void Term()
858 {
859 AtlWinModuleTerm(this, _AtlBaseModule.GetModuleInstance());
860 }
861
862 void AddCreateWndData(_AtlCreateWndData *pData, void *pObject)
863 {
864 AtlWinModuleAddCreateWndData(this, pData, pObject);
865 }
866
867 void *ExtractCreateWndData()
868 {
869 return AtlWinModuleExtractCreateWndData(this);
870 }
871 };
872
873 extern CAtlWinModule _AtlWinModule;
874
875 class CComAllocator
876 {
877 public:
878 static void* Allocate(_In_ size_t size)
879 {
880 return ::CoTaskMemAlloc(size);
881 }
882
883 static void* Reallocate(_In_opt_ void* ptr, _In_ size_t size)
884 {
885 return ::CoTaskMemRealloc(ptr, size);
886 }
887
888 static void Free(_In_opt_ void* ptr)
889 {
890 ::CoTaskMemFree(ptr);
891 }
892 };
893
894 class CRegKey
895 {
896 public:
897 HKEY m_hKey;
898 #if 0
899 // FIXME & TODO:
900 CAtlTransactionManager* m_pTM;
901 #endif
902
903 public:
904
905 CRegKey() throw()
906 : m_hKey(NULL)
907 {
908 }
909
910 CRegKey(CRegKey& key) throw()
911 : m_hKey(key.Detach())
912 {
913 }
914
915 explicit CRegKey(HKEY hKey) throw()
916 : m_hKey(hKey)
917 {
918 }
919
920 #if 0
921 // FIXME & TODO:
922 CRegKey(CAtlTransactionManager* pTM) throw()
923 {
924 ...
925 }
926 #endif
927
928 ~CRegKey() throw()
929 {
930 }
931
932 void Attach(HKEY hKey) throw()
933 {
934 m_hKey = hKey;
935 }
936
937 LONG Close() throw()
938 {
939 if (m_hKey)
940 {
941 HKEY hKey = Detach();
942 return ::RegCloseKey(hKey);
943 }
944 return ERROR_SUCCESS;
945 }
946
947 HKEY Detach() throw()
948 {
949 HKEY hKey = m_hKey;
950 m_hKey = NULL;
951 return hKey;
952 }
953
954 LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName,
955 REGSAM samDesired = KEY_READ | KEY_WRITE) throw()
956 {
957 ATLASSERT(hKeyParent);
958 ATLASSERT(lpszKeyName);
959
960 HKEY hKey = NULL;
961 LONG lRes = ::RegOpenKeyEx(hKeyParent, lpszKeyName, NULL, samDesired, &hKey);
962 if (lRes != ERROR_SUCCESS)
963 {
964 samDesired |= KEY_WOW64_64KEY;
965 lRes = ::RegOpenKeyEx(hKeyParent, lpszKeyName, NULL, samDesired, &hKey);
966 }
967 if (lRes == ERROR_SUCCESS)
968 {
969 Close();
970 m_hKey = hKey;
971 }
972 return lRes;
973 }
974
975 LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName,
976 LPTSTR lpszClass = REG_NONE,
977 DWORD dwOptions = REG_OPTION_NON_VOLATILE,
978 REGSAM samDesired = KEY_READ | KEY_WRITE,
979 LPSECURITY_ATTRIBUTES lpSecAttr = NULL,
980 LPDWORD lpdwDisposition = NULL) throw()
981 {
982 ATLASSERT(hKeyParent);
983 ATLASSERT(lpszKeyName);
984
985 HKEY hKey = NULL;
986 LONG lRes = ::RegCreateKeyEx(hKeyParent, lpszKeyName, NULL, lpszClass,
987 dwOptions, samDesired, lpSecAttr, &hKey,
988 lpdwDisposition);
989 if (lRes != ERROR_SUCCESS)
990 {
991 samDesired |= KEY_WOW64_64KEY;
992 lRes = ::RegCreateKeyEx(hKeyParent, lpszKeyName, NULL, lpszClass,
993 dwOptions, samDesired, lpSecAttr, &hKey,
994 lpdwDisposition);
995 }
996 if (lRes == ERROR_SUCCESS)
997 {
998 Close();
999 m_hKey = hKey;
1000 }
1001 return lRes;
1002 }
1003
1004 LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw()
1005 {
1006 ATLASSERT(m_hKey);
1007 return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, (LPBYTE)pData, pnBytes);
1008 }
1009
1010 LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw()
1011 {
1012 ULONG size = sizeof(DWORD);
1013 DWORD type = 0;
1014 LONG lRet = QueryValue(pszValueName, &type, &dwValue, &size);
1015
1016 if (lRet == ERROR_SUCCESS && type != REG_DWORD)
1017 lRet = ERROR_INVALID_DATA;
1018
1019 return lRet;
1020 }
1021
1022 LONG QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw()
1023 {
1024 DWORD type = 0;
1025 LONG lRet = QueryValue(pszValueName, &type, pValue, pnBytes);
1026
1027 if (lRet == ERROR_SUCCESS && type != REG_BINARY)
1028 lRet = ERROR_INVALID_DATA;
1029
1030 return lRet;
1031 }
1032
1033 LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw()
1034 {
1035 ULONG size = (*pnChars) * sizeof(TCHAR);
1036 DWORD type = 0;
1037 LONG lRet = QueryValue(pszValueName, &type, pszValue, &size);
1038
1039 if (lRet == ERROR_SUCCESS && type != REG_SZ && type != REG_EXPAND_SZ)
1040 lRet = ERROR_INVALID_DATA;
1041
1042 *pnChars = size / sizeof(TCHAR);
1043 return lRet;
1044 }
1045
1046 LONG QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue) throw()
1047 {
1048 OLECHAR buf[40] = {0};
1049 ULONG nChars = 39;
1050 LONG lRet;
1051
1052 #ifdef UNICODE
1053 lRet = QueryStringValue(pszValueName, buf, &nChars);
1054 #else
1055 CHAR bufA[40] = {0};
1056 lRet = QueryStringValue(pszValueName, bufA, &nChars);
1057 if (lRet != ERROR_SUCCESS)
1058 return lRet;
1059 if (!::MultiByteToWideChar(CP_THREAD_ACP, 0, bufA, -1, buf, 39))
1060 lRet = ERROR_INVALID_DATA;
1061 #endif
1062 if (lRet != ERROR_SUCCESS)
1063 return lRet;
1064
1065 if (!SUCCEEDED(::CLSIDFromString(buf, &guidValue)))
1066 return ERROR_INVALID_DATA;
1067
1068 return lRet;
1069 }
1070
1071 LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw()
1072 {
1073 ULONG size = sizeof(ULONGLONG);
1074 DWORD type = 0;
1075 LONG lRet = QueryValue(pszValueName, &type, &qwValue, &size);
1076
1077 if (lRet == ERROR_SUCCESS && type != REG_QWORD)
1078 lRet = ERROR_INVALID_DATA;
1079
1080 return lRet;
1081 }
1082
1083 LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue,
1084 ULONG* pnChars) throw()
1085 {
1086 ULONG size = (*pnChars) * sizeof(TCHAR);
1087 DWORD type;
1088 LONG lRet = QueryValue(pszValueName, &type, pszValue, &size);
1089
1090 if (lRet == ERROR_SUCCESS && type != REG_MULTI_SZ)
1091 lRet = ERROR_INVALID_DATA;
1092
1093 *pnChars = size / sizeof(TCHAR);
1094 return lRet;
1095 }
1096
1097 LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw()
1098 {
1099 ATLASSERT(m_hKey);
1100 return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, (const BYTE*)pValue, nBytes);
1101 }
1102
1103 LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw()
1104 {
1105 return SetValue(pszValueName, REG_DWORD, &dwValue, sizeof(DWORD));
1106 }
1107
1108 LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ) throw()
1109 {
1110 ULONG length;
1111 switch (dwType)
1112 {
1113 case REG_SZ:
1114 case REG_EXPAND_SZ:
1115 length = (_tcslen(pszValue) + 1) * sizeof(TCHAR);
1116 return SetValue(pszValueName, dwType, pszValue, length);
1117 case REG_MULTI_SZ:
1118 return SetMultiStringValue(pszValueName, pszValue);
1119 default:
1120 return ERROR_INVALID_DATA;
1121 }
1122 }
1123
1124 LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw()
1125 {
1126 OLECHAR buf[40] = {0};
1127 ::StringFromGUID2(guidValue, buf, 39);
1128 #ifdef UNICODE
1129 return SetStringValue(pszValueName, buf);
1130 #else
1131 CHAR bufA[40] = {0};
1132 ::WideCharToMultiByte(CP_THREAD_ACP, 0, buf, -1, bufA, 40, NULL, NULL);
1133 return SetStringValue(pszValueName, bufA);
1134 #endif
1135 }
1136
1137 LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes) throw()
1138 {
1139 return SetValue(pszValueName, REG_BINARY, pValue, nBytes);
1140 }
1141
1142 LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw()
1143 {
1144 ULONG dwSize = CRegKey::_GetMultiStringSize(pszValue);
1145 return SetValue(pszValueName, REG_MULTI_SZ, pszValue, dwSize);
1146 }
1147
1148 LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw()
1149 {
1150 ULONG dwSize = sizeof(ULONGLONG);
1151 return SetValue(pszValueName, REG_QWORD, &qwValue, dwSize);
1152 }
1153
1154 LONG NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter,
1155 HANDLE hEvent, BOOL bAsync = TRUE) throw()
1156 {
1157 ATLASSERT(m_hKey);
1158 LONG ret = ::RegNotifyChangeKeyValue(m_hKey, bWatchSubtree,
1159 dwNotifyFilter, hEvent, bAsync);
1160 return ret;
1161 }
1162
1163 LONG Flush() throw()
1164 {
1165 ATLASSERT(m_hKey);
1166 LONG ret = ::RegFlushKey(m_hKey);
1167 return ret;
1168 }
1169
1170 static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName,
1171 LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL)
1172 {
1173 CRegKey key;
1174 LONG lRet = key.Create(hKeyParent, lpszKeyName);
1175 if (lRet == ERROR_SUCCESS)
1176 {
1177 lRet = key.SetStringValue(lpszValueName, lpszValue);
1178 }
1179 return lRet;
1180 }
1181
1182 LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue,
1183 LPCTSTR lpszValueName = NULL) throw()
1184 {
1185 CRegKey key;
1186 LONG lRet = key.Create(m_hKey, lpszKeyName);
1187 if (lRet == ERROR_SUCCESS)
1188 {
1189 lRet = key.SetStringValue(lpszValueName, lpszValue);
1190 }
1191 return lRet;
1192 }
1193
1194 LONG DeleteValue(LPCTSTR lpszValue) throw()
1195 {
1196 ATLASSERT(m_hKey);
1197 return ::RegDeleteValue(m_hKey, lpszValue);
1198 }
1199
1200 LONG DeleteSubKey(LPCTSTR lpszSubKey) throw()
1201 {
1202 ATLASSERT(m_hKey);
1203 ATLASSERT(lpszSubKey);
1204 return ::RegDeleteKey(m_hKey, lpszSubKey);
1205 }
1206
1207 LONG RecurseDeleteKey(LPCTSTR lpszKey) throw()
1208 {
1209 ATLASSERT(m_hKey);
1210 ATLASSERT(lpszKey);
1211 return CRegKey::_DoDeleteKeyTree(m_hKey, lpszKey);
1212 }
1213
1214 LONG EnumKey(DWORD iIndex, LPTSTR pszName, LPDWORD pnNameLength,
1215 FILETIME* pftLastWriteTime = NULL) throw()
1216 {
1217 ATLASSERT(m_hKey);
1218 LONG ret = ::RegEnumKeyEx(m_hKey, iIndex, pszName, pnNameLength, NULL,
1219 NULL, NULL, pftLastWriteTime);
1220 return ret;
1221 }
1222
1223 LONG GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd,
1224 LPDWORD pnBytes) throw()
1225 {
1226 ATLASSERT(m_hKey);
1227 LONG ret = ::RegGetKeySecurity(m_hKey, si, psd, pnBytes);
1228 return ret;
1229 }
1230
1231 LONG SetKeySecurity(SECURITY_INFORMATION si,
1232 PSECURITY_DESCRIPTOR psd) throw()
1233 {
1234 ATLASSERT(m_hKey);
1235 LONG ret = ::RegSetKeySecurity(m_hKey, si, psd);
1236 return ret;
1237 }
1238
1239 operator HKEY() const throw()
1240 {
1241 return m_hKey;
1242 }
1243
1244 CRegKey& operator=(CRegKey& key) throw()
1245 {
1246 Attach(key.Detach());
1247 return *this;
1248 }
1249
1250 protected:
1251 // get the total size of a multistring
1252 static ULONG _GetMultiStringSize(LPCTSTR pszz)
1253 {
1254 int count = 0;
1255 do
1256 {
1257 int len = _tcslen(pszz);
1258 count += len + 1;
1259 pszz += len + 1;
1260 } while (*pszz != TEXT('\0'));
1261 ++count;
1262 return count * sizeof(TCHAR);
1263 }
1264
1265 // delete key recursively
1266 static LONG _DoDeleteKeyTree(HKEY hParentKey, LPCTSTR lpszKey)
1267 {
1268 ATLASSERT(hParentKey);
1269 ATLASSERT(lpszKey);
1270
1271 // open the key
1272 CRegKey key;
1273 LONG ret = key.Open(hParentKey, lpszKey);
1274 if (ret != ERROR_SUCCESS)
1275 {
1276 return ret; // failure
1277 }
1278
1279 // get the longest length of subkey names
1280 DWORD NameMax;
1281 ret = ::RegQueryInfoKey(key, NULL, NULL, NULL, NULL, &NameMax, NULL,
1282 NULL, NULL, NULL, NULL, NULL);
1283 if (ret != ERROR_SUCCESS)
1284 {
1285 return ret; // failure
1286 }
1287 ++NameMax; // for NUL
1288
1289 // allocate the string buffer for names if necessary
1290 TCHAR szNameBuf[MAX_PATH], *pszName;
1291 if (NameMax > MAX_PATH)
1292 {
1293 pszName = (TCHAR *)malloc(NameMax * sizeof(TCHAR));
1294 ATLASSERT(pszName);
1295 if (pszName == NULL)
1296 {
1297 return ERROR_OUTOFMEMORY; // failure
1298 }
1299 }
1300 else
1301 {
1302 NameMax = MAX_PATH;
1303 pszName = szNameBuf;
1304 }
1305
1306 // enumerate every subkey and delete
1307 for (;;)
1308 {
1309 DWORD Count = NameMax;
1310 ret = key.EnumKey(0, pszName, &Count);
1311 if (ret != ERROR_SUCCESS)
1312 {
1313 if (ret == ERROR_NO_MORE_ITEMS)
1314 ret = ERROR_SUCCESS;
1315 break;
1316 }
1317
1318 ret = CRegKey::_DoDeleteKeyTree(key, pszName);
1319 if (ret != ERROR_SUCCESS)
1320 break;
1321 }
1322
1323 // close key
1324 key.Close();
1325
1326 // delete the subkey
1327 if (ret == ERROR_SUCCESS)
1328 ret = ::RegDeleteKey(hParentKey, lpszKey);
1329
1330 // delete the buffer if any
1331 if (pszName != szNameBuf)
1332 free(pszName);
1333
1334 return ret;
1335 }
1336 };
1337
1338 template<class T>
1339 class CComHeapPtr : public CHeapPtr<T, CComAllocator>
1340 {
1341 public:
1342 CComHeapPtr()
1343 {
1344 }
1345
1346 explicit CComHeapPtr(T *lp) :
1347 CHeapPtr<T, CComAllocator>(lp)
1348 {
1349 }
1350 };
1351
1352
1353 inline HRESULT __stdcall AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID &iid, LPDWORD pdw)
1354 {
1355 CComPtr<IConnectionPointContainer> container;
1356 CComPtr<IConnectionPoint> connectionPoint;
1357 HRESULT hResult;
1358
1359 if (pUnkCP == NULL)
1360 return E_INVALIDARG;
1361 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container);
1362 if (FAILED(hResult))
1363 return hResult;
1364 hResult = container->FindConnectionPoint(iid, &connectionPoint);
1365 if (FAILED(hResult))
1366 return hResult;
1367 return connectionPoint->Advise(pUnk, pdw);
1368 }
1369
1370 inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw)
1371 {
1372 CComPtr<IConnectionPointContainer> container;
1373 CComPtr<IConnectionPoint> connectionPoint;
1374 HRESULT hResult;
1375
1376 if (pUnkCP == NULL)
1377 return E_INVALIDARG;
1378 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container);
1379 if (FAILED(hResult))
1380 return hResult;
1381 hResult = container->FindConnectionPoint(iid, &connectionPoint);
1382 if (FAILED(hResult))
1383 return hResult;
1384 return connectionPoint->Unadvise(dw);
1385 }
1386
1387 inline HRESULT __stdcall AtlInternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject)
1388 {
1389 int i;
1390 IUnknown *resultInterface;
1391 HRESULT hResult;
1392
1393 ATLASSERT(pThis != NULL && pEntries != NULL);
1394 if (pThis == NULL || pEntries == NULL)
1395 return E_INVALIDARG;
1396 ATLASSERT(ppvObject != NULL);
1397 if (ppvObject == NULL)
1398 return E_POINTER;
1399
1400 if (InlineIsEqualUnknown(iid))
1401 {
1402 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[0].dw);
1403 *ppvObject = resultInterface;
1404 resultInterface->AddRef();
1405 return S_OK;
1406 }
1407
1408 i = 0;
1409 while (pEntries[i].pFunc != 0)
1410 {
1411 if (pEntries[i].piid == NULL || InlineIsEqualGUID(iid, *pEntries[i].piid))
1412 {
1413 if (pEntries[i].pFunc == reinterpret_cast<_ATL_CREATORARGFUNC *>(1))
1414 {
1415 ATLASSERT(pEntries[i].piid != NULL);
1416 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[i].dw);
1417 *ppvObject = resultInterface;
1418 resultInterface->AddRef();
1419 return S_OK;
1420 }
1421 else
1422 {
1423 hResult = pEntries[i].pFunc(pThis, iid, ppvObject, 0);
1424 if (hResult == S_OK || (FAILED(hResult) && pEntries[i].piid != NULL))
1425 return hResult;
1426 }
1427 break;
1428 }
1429 i++;
1430 }
1431 *ppvObject = NULL;
1432 return E_NOINTERFACE;
1433 }
1434
1435 inline HRESULT __stdcall AtlWinModuleInit(_ATL_WIN_MODULE *pWinModule)
1436 {
1437 if (pWinModule == NULL)
1438 return E_INVALIDARG;
1439 pWinModule->m_pCreateWndList = NULL;
1440 return pWinModule->m_csWindowCreate.Init();
1441 }
1442
1443 inline HRESULT __stdcall AtlWinModuleTerm(_ATL_WIN_MODULE *pWinModule, HINSTANCE hInst)
1444 {
1445 if (pWinModule == NULL)
1446 return E_INVALIDARG;
1447 pWinModule->m_csWindowCreate.Term();
1448 return S_OK;
1449 }
1450
1451 inline void __stdcall AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pWinModule, _AtlCreateWndData *pData, void *pObject)
1452 {
1453 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true);
1454
1455 ATLASSERT(pWinModule != NULL);
1456 ATLASSERT(pObject != NULL);
1457
1458 pData->m_pThis = pObject;
1459 pData->m_dwThreadID = ::GetCurrentThreadId();
1460 pData->m_pNext = pWinModule->m_pCreateWndList;
1461 pWinModule->m_pCreateWndList = pData;
1462 }
1463
1464 inline void *__stdcall AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *pWinModule)
1465 {
1466 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true);
1467 void *result;
1468 _AtlCreateWndData *currentEntry;
1469 _AtlCreateWndData **previousLink;
1470 DWORD threadID;
1471
1472 ATLASSERT(pWinModule != NULL);
1473
1474 result = NULL;
1475 threadID = GetCurrentThreadId();
1476 currentEntry = pWinModule->m_pCreateWndList;
1477 previousLink = &pWinModule->m_pCreateWndList;
1478 while (currentEntry != NULL)
1479 {
1480 if (currentEntry->m_dwThreadID == threadID)
1481 {
1482 *previousLink = currentEntry->m_pNext;
1483 result = currentEntry->m_pThis;
1484 break;
1485 }
1486 previousLink = &currentEntry->m_pNext;
1487 currentEntry = currentEntry->m_pNext;
1488 }
1489 return result;
1490 }
1491
1492 // Adapted from dll/win32/atl/atl.c
1493 inline HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
1494 BSTR *pbstrPath, ITypeLib **ppTypeLib)
1495 {
1496 size_t index_len = lpszIndex ? wcslen(lpszIndex) : 0;
1497 CComHeapPtr<WCHAR> path;
1498 path.Allocate(MAX_PATH + index_len + wcslen(L".tlb"));
1499
1500 if (!path)
1501 return E_OUTOFMEMORY;
1502
1503 size_t path_len = GetModuleFileNameW(inst, path, MAX_PATH);
1504 if (!path_len)
1505 return HRESULT_FROM_WIN32(GetLastError());
1506
1507 if (index_len)
1508 wcscat(path, lpszIndex);
1509
1510 CComPtr<ITypeLib> typelib;
1511 HRESULT hResult = LoadTypeLib(path, &typelib);
1512 if (FAILED(hResult))
1513 {
1514 WCHAR *ptr;
1515 for (ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--)
1516 ;
1517 if (*ptr != '.')
1518 ptr = (WCHAR*)path + path_len;
1519 wcscpy(ptr, L".tlb");
1520
1521 hResult = LoadTypeLib(path, &typelib);
1522 }
1523
1524 if (SUCCEEDED(hResult))
1525 {
1526 *pbstrPath = SysAllocString(path);
1527 if (!*pbstrPath)
1528 {
1529 typelib.Release();
1530 hResult = E_OUTOFMEMORY;
1531 }
1532 }
1533
1534 if (FAILED(hResult))
1535 return hResult;
1536
1537 *ppTypeLib = typelib.Detach();
1538 return S_OK;
1539 }
1540
1541 // Adapted from dll/win32/atl/atl.c
1542 inline HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index)
1543 {
1544 CComBSTR path;
1545 CComPtr<ITypeLib> typelib;
1546 HRESULT hResult = AtlLoadTypeLib(inst, index, &path, &typelib);
1547 if (FAILED(hResult))
1548 return hResult;
1549
1550 return RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */
1551 }
1552
1553 // Adapted from dll/win32/atl/atl.c
1554 inline HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const _ATL_CATMAP_ENTRY *catmap, BOOL reg)
1555 {
1556 if (!catmap)
1557 return S_OK;
1558
1559 CComPtr<ICatRegister> catreg;
1560
1561 HRESULT hResult = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&catreg);
1562 if (FAILED(hResult))
1563 return hResult;
1564
1565 for (const _ATL_CATMAP_ENTRY *iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++)
1566 {
1567 CATID catid = *iter->pcatid;
1568
1569 if (iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED)
1570 {
1571 if (reg)
1572 hResult = catreg->RegisterClassImplCategories(clsid, 1, &catid);
1573 else
1574 hResult = catreg->UnRegisterClassImplCategories(clsid, 1, &catid);
1575 }
1576 else
1577 {
1578 if (reg)
1579 hResult = catreg->RegisterClassReqCategories(clsid, 1, &catid);
1580 else
1581 hResult = catreg->UnRegisterClassReqCategories(clsid, 1, &catid);
1582 }
1583 if (FAILED(hResult))
1584 return hResult;
1585 }
1586
1587 if (!reg)
1588 {
1589 WCHAR reg_path[256] = L"CLSID\\";
1590
1591 StringFromGUID2(clsid, reg_path + wcslen(reg_path), 64);
1592 wcscat(reg_path, L"\\");
1593 WCHAR* ptr = reg_path + wcslen(reg_path);
1594
1595 wcscpy(ptr, L"Implemented Categories");
1596 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
1597
1598 wcscpy(ptr, L"Required Categories");
1599 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
1600 }
1601
1602 return hResult;
1603 }
1604
1605
1606 // Adapted from dll/win32/atl80/atl80.c
1607 inline HRESULT __stdcall AtlComModuleRegisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
1608 {
1609 HRESULT hResult = S_OK;
1610
1611 for (_ATL_OBJMAP_ENTRY ** iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++)
1612 {
1613 if (!*iter)
1614 continue;
1615 _ATL_OBJMAP_ENTRY* entry = *iter;
1616 if (clsid && !IsEqualCLSID(*entry->pclsid, *clsid))
1617 continue;
1618
1619 hResult = entry->pfnUpdateRegistry(TRUE);
1620 if (FAILED(hResult))
1621 return hResult;
1622
1623 const _ATL_CATMAP_ENTRY *catmap = entry->pfnGetCategoryMap();
1624 if (catmap)
1625 {
1626 hResult = AtlRegisterClassCategoriesHelper(*entry->pclsid, catmap, TRUE);
1627 if (FAILED(hResult))
1628 return hResult;
1629 }
1630 }
1631
1632 if (bRegTypeLib)
1633 {
1634 hResult = AtlRegisterTypeLib(mod->m_hInstTypeLib, NULL);
1635 }
1636
1637 return hResult;
1638 }
1639
1640 // Adapted from dll/win32/atl/atl.c
1641 inline HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bUnRegTypeLib, const CLSID *clsid)
1642 {
1643 HRESULT hResult = S_OK;
1644
1645 for (_ATL_OBJMAP_ENTRY **iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++)
1646 {
1647 if (!*iter)
1648 continue;
1649 _ATL_OBJMAP_ENTRY* entry = *iter;
1650 if (clsid && !IsEqualCLSID(*entry->pclsid, *clsid))
1651 continue;
1652
1653 const _ATL_CATMAP_ENTRY *catmap = entry->pfnGetCategoryMap();
1654 if (catmap)
1655 {
1656 hResult = AtlRegisterClassCategoriesHelper(*entry->pclsid, catmap, FALSE);
1657 if (FAILED(hResult))
1658 return hResult;
1659 }
1660
1661 hResult = entry->pfnUpdateRegistry(FALSE);
1662 if (FAILED(hResult))
1663 return hResult;
1664 }
1665
1666 if (bUnRegTypeLib)
1667 {
1668 CComPtr<ITypeLib> typelib;
1669 TLIBATTR *attr;
1670 CComBSTR path;
1671
1672 hResult = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
1673 if (FAILED(hResult))
1674 return hResult;
1675
1676 hResult = typelib->GetLibAttr(&attr);
1677 if (SUCCEEDED(hResult))
1678 {
1679 hResult = UnRegisterTypeLib(attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
1680 typelib->ReleaseTLibAttr(attr);
1681 }
1682 }
1683
1684 return hResult;
1685 }
1686
1687
1688 }; // namespace ATL
1689
1690 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
1691 using namespace ATL;
1692 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE