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