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