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