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 size_t count = 0; 1371 do 1372 { 1373 size_t len = _tcslen(pszz); 1374 count += len + 1; 1375 pszz += len + 1; 1376 } while (*pszz != TEXT('\0')); 1377 ++count; 1378 ATLASSERT(count * sizeof(TCHAR) <= ULONG_MAX); 1379 return (ULONG)count * sizeof(TCHAR); 1380 } 1381 1382 // delete key recursively 1383 static LONG _DoDeleteKeyTree(HKEY hParentKey, LPCTSTR lpszKey) 1384 { 1385 ATLASSERT(hParentKey); 1386 ATLASSERT(lpszKey); 1387 1388 // open the key 1389 CRegKey key; 1390 LONG ret = key.Open(hParentKey, lpszKey); 1391 if (ret != ERROR_SUCCESS) 1392 { 1393 return ret; // failure 1394 } 1395 1396 // get the longest length of subkey names 1397 DWORD NameMax; 1398 ret = ::RegQueryInfoKey(key, NULL, NULL, NULL, NULL, &NameMax, NULL, 1399 NULL, NULL, NULL, NULL, NULL); 1400 if (ret != ERROR_SUCCESS) 1401 { 1402 return ret; // failure 1403 } 1404 ++NameMax; // for NUL 1405 1406 // allocate the string buffer for names if necessary 1407 TCHAR szNameBuf[MAX_PATH], *pszName; 1408 if (NameMax > MAX_PATH) 1409 { 1410 pszName = (TCHAR *)malloc(NameMax * sizeof(TCHAR)); 1411 ATLASSERT(pszName); 1412 if (pszName == NULL) 1413 { 1414 return ERROR_OUTOFMEMORY; // failure 1415 } 1416 } 1417 else 1418 { 1419 NameMax = MAX_PATH; 1420 pszName = szNameBuf; 1421 } 1422 1423 // enumerate every subkey and delete 1424 for (;;) 1425 { 1426 DWORD Count = NameMax; 1427 ret = key.EnumKey(0, pszName, &Count); 1428 if (ret != ERROR_SUCCESS) 1429 { 1430 if (ret == ERROR_NO_MORE_ITEMS) 1431 ret = ERROR_SUCCESS; 1432 break; 1433 } 1434 1435 ret = CRegKey::_DoDeleteKeyTree(key, pszName); 1436 if (ret != ERROR_SUCCESS) 1437 break; 1438 } 1439 1440 // close key 1441 key.Close(); 1442 1443 // delete the subkey 1444 if (ret == ERROR_SUCCESS) 1445 ret = ::RegDeleteKey(hParentKey, lpszKey); 1446 1447 // delete the buffer if any 1448 if (pszName != szNameBuf) 1449 free(pszName); 1450 1451 return ret; 1452 } 1453 }; 1454 1455 template<class T> 1456 class CComHeapPtr : public CHeapPtr<T, CComAllocator> 1457 { 1458 public: 1459 CComHeapPtr() 1460 { 1461 } 1462 1463 explicit CComHeapPtr(T *lp) : 1464 CHeapPtr<T, CComAllocator>(lp) 1465 { 1466 } 1467 }; 1468 1469 1470 inline HRESULT __stdcall AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID &iid, LPDWORD pdw) 1471 { 1472 CComPtr<IConnectionPointContainer> container; 1473 CComPtr<IConnectionPoint> connectionPoint; 1474 HRESULT hResult; 1475 1476 if (pUnkCP == NULL) 1477 return E_INVALIDARG; 1478 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container); 1479 if (FAILED(hResult)) 1480 return hResult; 1481 hResult = container->FindConnectionPoint(iid, &connectionPoint); 1482 if (FAILED(hResult)) 1483 return hResult; 1484 return connectionPoint->Advise(pUnk, pdw); 1485 } 1486 1487 inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw) 1488 { 1489 CComPtr<IConnectionPointContainer> container; 1490 CComPtr<IConnectionPoint> connectionPoint; 1491 HRESULT hResult; 1492 1493 if (pUnkCP == NULL) 1494 return E_INVALIDARG; 1495 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container); 1496 if (FAILED(hResult)) 1497 return hResult; 1498 hResult = container->FindConnectionPoint(iid, &connectionPoint); 1499 if (FAILED(hResult)) 1500 return hResult; 1501 return connectionPoint->Unadvise(dw); 1502 } 1503 1504 inline HRESULT __stdcall AtlInternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject) 1505 { 1506 int i; 1507 IUnknown *resultInterface; 1508 HRESULT hResult; 1509 1510 ATLASSERT(pThis != NULL && pEntries != NULL); 1511 if (pThis == NULL || pEntries == NULL) 1512 return E_INVALIDARG; 1513 ATLASSERT(ppvObject != NULL); 1514 if (ppvObject == NULL) 1515 return E_POINTER; 1516 1517 if (InlineIsEqualUnknown(iid)) 1518 { 1519 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[0].dw); 1520 *ppvObject = resultInterface; 1521 resultInterface->AddRef(); 1522 return S_OK; 1523 } 1524 1525 i = 0; 1526 while (pEntries[i].pFunc != 0) 1527 { 1528 if (pEntries[i].piid == NULL || InlineIsEqualGUID(iid, *pEntries[i].piid)) 1529 { 1530 if (pEntries[i].pFunc == reinterpret_cast<_ATL_CREATORARGFUNC *>(1)) 1531 { 1532 ATLASSERT(pEntries[i].piid != NULL); 1533 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[i].dw); 1534 *ppvObject = resultInterface; 1535 resultInterface->AddRef(); 1536 return S_OK; 1537 } 1538 else 1539 { 1540 hResult = pEntries[i].pFunc(pThis, iid, ppvObject, 0); 1541 if (hResult == S_OK) 1542 return hResult; 1543 if (FAILED(hResult) && pEntries[i].piid != NULL) 1544 break; 1545 } 1546 } 1547 i++; 1548 } 1549 *ppvObject = NULL; 1550 return E_NOINTERFACE; 1551 } 1552 1553 inline HRESULT __stdcall AtlWinModuleInit(_ATL_WIN_MODULE *pWinModule) 1554 { 1555 if (pWinModule == NULL) 1556 return E_INVALIDARG; 1557 pWinModule->m_pCreateWndList = NULL; 1558 return pWinModule->m_csWindowCreate.Init(); 1559 } 1560 1561 inline HRESULT __stdcall AtlWinModuleTerm(_ATL_WIN_MODULE *pWinModule, HINSTANCE hInst) 1562 { 1563 if (pWinModule == NULL) 1564 return E_INVALIDARG; 1565 pWinModule->m_csWindowCreate.Term(); 1566 return S_OK; 1567 } 1568 1569 inline void __stdcall AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pWinModule, _AtlCreateWndData *pData, void *pObject) 1570 { 1571 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true); 1572 1573 ATLASSERT(pWinModule != NULL); 1574 ATLASSERT(pObject != NULL); 1575 1576 pData->m_pThis = pObject; 1577 pData->m_dwThreadID = ::GetCurrentThreadId(); 1578 pData->m_pNext = pWinModule->m_pCreateWndList; 1579 pWinModule->m_pCreateWndList = pData; 1580 } 1581 1582 inline void *__stdcall AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *pWinModule) 1583 { 1584 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true); 1585 void *result; 1586 _AtlCreateWndData *currentEntry; 1587 _AtlCreateWndData **previousLink; 1588 DWORD threadID; 1589 1590 ATLASSERT(pWinModule != NULL); 1591 1592 result = NULL; 1593 threadID = GetCurrentThreadId(); 1594 currentEntry = pWinModule->m_pCreateWndList; 1595 previousLink = &pWinModule->m_pCreateWndList; 1596 while (currentEntry != NULL) 1597 { 1598 if (currentEntry->m_dwThreadID == threadID) 1599 { 1600 *previousLink = currentEntry->m_pNext; 1601 result = currentEntry->m_pThis; 1602 break; 1603 } 1604 previousLink = ¤tEntry->m_pNext; 1605 currentEntry = currentEntry->m_pNext; 1606 } 1607 return result; 1608 } 1609 1610 // Adapted from dll/win32/atl/atl.c 1611 inline HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex, 1612 BSTR *pbstrPath, ITypeLib **ppTypeLib) 1613 { 1614 size_t index_len = lpszIndex ? wcslen(lpszIndex) : 0; 1615 CComHeapPtr<WCHAR> path; 1616 path.Allocate(MAX_PATH + index_len + wcslen(L".tlb")); 1617 1618 if (!path) 1619 return E_OUTOFMEMORY; 1620 1621 size_t path_len = GetModuleFileNameW(inst, path, MAX_PATH); 1622 if (!path_len) 1623 return HRESULT_FROM_WIN32(GetLastError()); 1624 1625 if (index_len) 1626 wcscat(path, lpszIndex); 1627 1628 CComPtr<ITypeLib> typelib; 1629 HRESULT hResult = LoadTypeLib(path, &typelib); 1630 if (FAILED(hResult)) 1631 { 1632 WCHAR *ptr; 1633 for (ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--) 1634 ; 1635 if (*ptr != '.') 1636 ptr = (WCHAR*)path + path_len; 1637 wcscpy(ptr, L".tlb"); 1638 1639 hResult = LoadTypeLib(path, &typelib); 1640 } 1641 1642 if (SUCCEEDED(hResult)) 1643 { 1644 *pbstrPath = SysAllocString(path); 1645 if (!*pbstrPath) 1646 { 1647 typelib.Release(); 1648 hResult = E_OUTOFMEMORY; 1649 } 1650 } 1651 1652 if (FAILED(hResult)) 1653 return hResult; 1654 1655 *ppTypeLib = typelib.Detach(); 1656 return S_OK; 1657 } 1658 1659 // Adapted from dll/win32/atl/atl.c 1660 inline HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index) 1661 { 1662 CComBSTR path; 1663 CComPtr<ITypeLib> typelib; 1664 HRESULT hResult = AtlLoadTypeLib(inst, index, &path, &typelib); 1665 if (FAILED(hResult)) 1666 return hResult; 1667 1668 return RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */ 1669 } 1670 1671 // Adapted from dll/win32/atl/atl.c 1672 inline HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const _ATL_CATMAP_ENTRY *catmap, BOOL reg) 1673 { 1674 if (!catmap) 1675 return S_OK; 1676 1677 CComPtr<ICatRegister> catreg; 1678 1679 HRESULT hResult = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&catreg); 1680 if (FAILED(hResult)) 1681 return hResult; 1682 1683 for (const _ATL_CATMAP_ENTRY *iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) 1684 { 1685 CATID catid = *iter->pcatid; 1686 1687 if (iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) 1688 { 1689 if (reg) 1690 hResult = catreg->RegisterClassImplCategories(clsid, 1, &catid); 1691 else 1692 hResult = catreg->UnRegisterClassImplCategories(clsid, 1, &catid); 1693 } 1694 else 1695 { 1696 if (reg) 1697 hResult = catreg->RegisterClassReqCategories(clsid, 1, &catid); 1698 else 1699 hResult = catreg->UnRegisterClassReqCategories(clsid, 1, &catid); 1700 } 1701 if (FAILED(hResult)) 1702 return hResult; 1703 } 1704 1705 if (!reg) 1706 { 1707 WCHAR reg_path[256] = L"CLSID\\"; 1708 1709 StringFromGUID2(clsid, reg_path + wcslen(reg_path), 64); 1710 wcscat(reg_path, L"\\"); 1711 WCHAR* ptr = reg_path + wcslen(reg_path); 1712 1713 wcscpy(ptr, L"Implemented Categories"); 1714 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); 1715 1716 wcscpy(ptr, L"Required Categories"); 1717 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); 1718 } 1719 1720 return hResult; 1721 } 1722 1723 1724 // Adapted from dll/win32/atl80/atl80.c 1725 inline HRESULT __stdcall AtlComModuleRegisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid) 1726 { 1727 HRESULT hResult = S_OK; 1728 1729 for (_ATL_OBJMAP_ENTRY ** iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) 1730 { 1731 if (!*iter) 1732 continue; 1733 _ATL_OBJMAP_ENTRY* entry = *iter; 1734 if (clsid && !IsEqualCLSID(*entry->pclsid, *clsid)) 1735 continue; 1736 1737 hResult = entry->pfnUpdateRegistry(TRUE); 1738 if (FAILED(hResult)) 1739 return hResult; 1740 1741 const _ATL_CATMAP_ENTRY *catmap = entry->pfnGetCategoryMap(); 1742 if (catmap) 1743 { 1744 hResult = AtlRegisterClassCategoriesHelper(*entry->pclsid, catmap, TRUE); 1745 if (FAILED(hResult)) 1746 return hResult; 1747 } 1748 } 1749 1750 if (bRegTypeLib) 1751 { 1752 hResult = AtlRegisterTypeLib(mod->m_hInstTypeLib, NULL); 1753 } 1754 1755 return hResult; 1756 } 1757 1758 // Adapted from dll/win32/atl/atl.c 1759 inline HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bUnRegTypeLib, const CLSID *clsid) 1760 { 1761 HRESULT hResult = S_OK; 1762 1763 for (_ATL_OBJMAP_ENTRY **iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) 1764 { 1765 if (!*iter) 1766 continue; 1767 _ATL_OBJMAP_ENTRY* entry = *iter; 1768 if (clsid && !IsEqualCLSID(*entry->pclsid, *clsid)) 1769 continue; 1770 1771 const _ATL_CATMAP_ENTRY *catmap = entry->pfnGetCategoryMap(); 1772 if (catmap) 1773 { 1774 hResult = AtlRegisterClassCategoriesHelper(*entry->pclsid, catmap, FALSE); 1775 if (FAILED(hResult)) 1776 return hResult; 1777 } 1778 1779 hResult = entry->pfnUpdateRegistry(FALSE); 1780 if (FAILED(hResult)) 1781 return hResult; 1782 } 1783 1784 if (bUnRegTypeLib) 1785 { 1786 CComPtr<ITypeLib> typelib; 1787 TLIBATTR *attr; 1788 CComBSTR path; 1789 1790 hResult = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib); 1791 if (FAILED(hResult)) 1792 return hResult; 1793 1794 hResult = typelib->GetLibAttr(&attr); 1795 if (SUCCEEDED(hResult)) 1796 { 1797 hResult = UnRegisterTypeLib(attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind); 1798 typelib->ReleaseTLibAttr(attr); 1799 } 1800 } 1801 1802 return hResult; 1803 } 1804 1805 1806 // Adapted from dll/win32/atl/atl.c 1807 inline HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags) 1808 { 1809 _ATL_OBJMAP_ENTRY **iter; 1810 IUnknown* unk = NULL; 1811 HRESULT hr; 1812 1813 if (!module) 1814 return E_INVALIDARG; 1815 1816 for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) 1817 { 1818 if (!(*iter)->pfnGetClassObject) 1819 continue; 1820 1821 hr = (*iter)->pfnGetClassObject((void*)(*iter)->pfnCreateInstance, IID_IUnknown, (void**)&unk); 1822 if (FAILED(hr)) 1823 return hr; 1824 1825 hr = CoRegisterClassObject(*(*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister); 1826 unk->Release(); 1827 if (FAILED(hr)) 1828 return hr; 1829 } 1830 1831 return S_OK; 1832 } 1833 1834 1835 // Adapted from dll/win32/atl/atl.c 1836 inline HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module) 1837 { 1838 _ATL_OBJMAP_ENTRY **iter; 1839 HRESULT hr; 1840 1841 if (!module) 1842 return E_INVALIDARG; 1843 1844 for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) 1845 { 1846 hr = CoRevokeClassObject((*iter)->dwRegister); 1847 if (FAILED(hr)) 1848 return hr; 1849 } 1850 1851 return S_OK; 1852 } 1853 1854 1855 }; // namespace ATL 1856 1857 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE 1858 using namespace ATL; 1859 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE 1860