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