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 Close(); 1047 } 1048 1049 void Attach(HKEY hKey) throw() 1050 { 1051 m_hKey = hKey; 1052 } 1053 1054 LONG Close() throw() 1055 { 1056 if (m_hKey) 1057 { 1058 HKEY hKey = Detach(); 1059 return ::RegCloseKey(hKey); 1060 } 1061 return ERROR_SUCCESS; 1062 } 1063 1064 HKEY Detach() throw() 1065 { 1066 HKEY hKey = m_hKey; 1067 m_hKey = NULL; 1068 return hKey; 1069 } 1070 1071 LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, 1072 REGSAM samDesired = KEY_READ | KEY_WRITE) throw() 1073 { 1074 ATLASSERT(hKeyParent); 1075 ATLASSERT(lpszKeyName); 1076 1077 HKEY hKey = NULL; 1078 LONG lRes = ::RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey); 1079 if (lRes != ERROR_SUCCESS) 1080 { 1081 samDesired |= KEY_WOW64_64KEY; 1082 lRes = ::RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey); 1083 } 1084 if (lRes == ERROR_SUCCESS) 1085 { 1086 Close(); 1087 m_hKey = hKey; 1088 } 1089 return lRes; 1090 } 1091 1092 LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName, 1093 LPTSTR lpszClass = REG_NONE, 1094 DWORD dwOptions = REG_OPTION_NON_VOLATILE, 1095 REGSAM samDesired = KEY_READ | KEY_WRITE, 1096 LPSECURITY_ATTRIBUTES lpSecAttr = NULL, 1097 LPDWORD lpdwDisposition = NULL) throw() 1098 { 1099 ATLASSERT(hKeyParent); 1100 ATLASSERT(lpszKeyName); 1101 1102 HKEY hKey = NULL; 1103 LONG lRes = ::RegCreateKeyEx(hKeyParent, lpszKeyName, 0, lpszClass, 1104 dwOptions, samDesired, lpSecAttr, &hKey, 1105 lpdwDisposition); 1106 if (lRes != ERROR_SUCCESS) 1107 { 1108 samDesired |= KEY_WOW64_64KEY; 1109 lRes = ::RegCreateKeyEx(hKeyParent, lpszKeyName, 0, lpszClass, 1110 dwOptions, samDesired, lpSecAttr, &hKey, 1111 lpdwDisposition); 1112 } 1113 if (lRes == ERROR_SUCCESS) 1114 { 1115 Close(); 1116 m_hKey = hKey; 1117 } 1118 return lRes; 1119 } 1120 1121 LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw() 1122 { 1123 ATLASSERT(m_hKey); 1124 return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, (LPBYTE)pData, pnBytes); 1125 } 1126 1127 LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw() 1128 { 1129 ULONG size = sizeof(DWORD); 1130 DWORD type = 0; 1131 LONG lRet = QueryValue(pszValueName, &type, &dwValue, &size); 1132 1133 if (lRet == ERROR_SUCCESS && type != REG_DWORD) 1134 lRet = ERROR_INVALID_DATA; 1135 1136 return lRet; 1137 } 1138 1139 LONG QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw() 1140 { 1141 DWORD type = 0; 1142 LONG lRet = QueryValue(pszValueName, &type, pValue, pnBytes); 1143 1144 if (lRet == ERROR_SUCCESS && type != REG_BINARY) 1145 lRet = ERROR_INVALID_DATA; 1146 1147 return lRet; 1148 } 1149 1150 LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw() 1151 { 1152 ULONG size = (*pnChars) * sizeof(TCHAR); 1153 DWORD type = 0; 1154 LONG lRet = QueryValue(pszValueName, &type, pszValue, &size); 1155 1156 if (lRet == ERROR_SUCCESS && type != REG_SZ && type != REG_EXPAND_SZ) 1157 lRet = ERROR_INVALID_DATA; 1158 1159 *pnChars = size / sizeof(TCHAR); 1160 return lRet; 1161 } 1162 1163 LONG QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue) throw() 1164 { 1165 OLECHAR buf[40] = {0}; 1166 ULONG nChars = 39; 1167 LONG lRet; 1168 1169 #ifdef UNICODE 1170 lRet = QueryStringValue(pszValueName, buf, &nChars); 1171 #else 1172 CHAR bufA[40] = {0}; 1173 lRet = QueryStringValue(pszValueName, bufA, &nChars); 1174 if (lRet != ERROR_SUCCESS) 1175 return lRet; 1176 if (!::MultiByteToWideChar(CP_THREAD_ACP, 0, bufA, -1, buf, 39)) 1177 lRet = ERROR_INVALID_DATA; 1178 #endif 1179 if (lRet != ERROR_SUCCESS) 1180 return lRet; 1181 1182 if (!SUCCEEDED(::CLSIDFromString(buf, &guidValue))) 1183 return ERROR_INVALID_DATA; 1184 1185 return lRet; 1186 } 1187 1188 LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw() 1189 { 1190 ULONG size = sizeof(ULONGLONG); 1191 DWORD type = 0; 1192 LONG lRet = QueryValue(pszValueName, &type, &qwValue, &size); 1193 1194 if (lRet == ERROR_SUCCESS && type != REG_QWORD) 1195 lRet = ERROR_INVALID_DATA; 1196 1197 return lRet; 1198 } 1199 1200 LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, 1201 ULONG* pnChars) throw() 1202 { 1203 ULONG size = (*pnChars) * sizeof(TCHAR); 1204 DWORD type; 1205 LONG lRet = QueryValue(pszValueName, &type, pszValue, &size); 1206 1207 if (lRet == ERROR_SUCCESS && type != REG_MULTI_SZ) 1208 lRet = ERROR_INVALID_DATA; 1209 1210 *pnChars = size / sizeof(TCHAR); 1211 return lRet; 1212 } 1213 1214 LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw() 1215 { 1216 ATLASSERT(m_hKey); 1217 return ::RegSetValueEx(m_hKey, pszValueName, 0, dwType, (const BYTE*)pValue, nBytes); 1218 } 1219 1220 LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw() 1221 { 1222 return SetValue(pszValueName, REG_DWORD, &dwValue, sizeof(DWORD)); 1223 } 1224 1225 LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ) throw() 1226 { 1227 SIZE_T length; 1228 switch (dwType) 1229 { 1230 case REG_SZ: 1231 case REG_EXPAND_SZ: 1232 length = (_tcslen(pszValue) + 1) * sizeof(TCHAR); 1233 return SetValue(pszValueName, dwType, pszValue, length); 1234 case REG_MULTI_SZ: 1235 return SetMultiStringValue(pszValueName, pszValue); 1236 default: 1237 return ERROR_INVALID_DATA; 1238 } 1239 } 1240 1241 LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw() 1242 { 1243 OLECHAR buf[40] = {0}; 1244 ::StringFromGUID2(guidValue, buf, 39); 1245 #ifdef UNICODE 1246 return SetStringValue(pszValueName, buf); 1247 #else 1248 CHAR bufA[40] = {0}; 1249 ::WideCharToMultiByte(CP_THREAD_ACP, 0, buf, -1, bufA, 40, NULL, NULL); 1250 return SetStringValue(pszValueName, bufA); 1251 #endif 1252 } 1253 1254 LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes) throw() 1255 { 1256 return SetValue(pszValueName, REG_BINARY, pValue, nBytes); 1257 } 1258 1259 LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw() 1260 { 1261 ULONG dwSize = CRegKey::_GetMultiStringSize(pszValue); 1262 return SetValue(pszValueName, REG_MULTI_SZ, pszValue, dwSize); 1263 } 1264 1265 LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw() 1266 { 1267 ULONG dwSize = sizeof(ULONGLONG); 1268 return SetValue(pszValueName, REG_QWORD, &qwValue, dwSize); 1269 } 1270 1271 LONG NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter, 1272 HANDLE hEvent, BOOL bAsync = TRUE) throw() 1273 { 1274 ATLASSERT(m_hKey); 1275 LONG ret = ::RegNotifyChangeKeyValue(m_hKey, bWatchSubtree, 1276 dwNotifyFilter, hEvent, bAsync); 1277 return ret; 1278 } 1279 1280 LONG Flush() throw() 1281 { 1282 ATLASSERT(m_hKey); 1283 LONG ret = ::RegFlushKey(m_hKey); 1284 return ret; 1285 } 1286 1287 static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, 1288 LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL) 1289 { 1290 CRegKey key; 1291 LONG lRet = key.Create(hKeyParent, lpszKeyName); 1292 if (lRet == ERROR_SUCCESS) 1293 { 1294 lRet = key.SetStringValue(lpszValueName, lpszValue); 1295 } 1296 return lRet; 1297 } 1298 1299 LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, 1300 LPCTSTR lpszValueName = NULL) throw() 1301 { 1302 CRegKey key; 1303 LONG lRet = key.Create(m_hKey, lpszKeyName); 1304 if (lRet == ERROR_SUCCESS) 1305 { 1306 lRet = key.SetStringValue(lpszValueName, lpszValue); 1307 } 1308 return lRet; 1309 } 1310 1311 LONG DeleteValue(LPCTSTR lpszValue) throw() 1312 { 1313 ATLASSERT(m_hKey); 1314 return ::RegDeleteValue(m_hKey, lpszValue); 1315 } 1316 1317 LONG DeleteSubKey(LPCTSTR lpszSubKey) throw() 1318 { 1319 ATLASSERT(m_hKey); 1320 ATLASSERT(lpszSubKey); 1321 return ::RegDeleteKey(m_hKey, lpszSubKey); 1322 } 1323 1324 LONG RecurseDeleteKey(LPCTSTR lpszKey) throw() 1325 { 1326 ATLASSERT(m_hKey); 1327 ATLASSERT(lpszKey); 1328 return CRegKey::_DoDeleteKeyTree(m_hKey, lpszKey); 1329 } 1330 1331 LONG EnumKey(DWORD iIndex, LPTSTR pszName, LPDWORD pnNameLength, 1332 FILETIME* pftLastWriteTime = NULL) throw() 1333 { 1334 ATLASSERT(m_hKey); 1335 LONG ret = ::RegEnumKeyEx(m_hKey, iIndex, pszName, pnNameLength, NULL, 1336 NULL, NULL, pftLastWriteTime); 1337 return ret; 1338 } 1339 1340 LONG GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd, 1341 LPDWORD pnBytes) throw() 1342 { 1343 ATLASSERT(m_hKey); 1344 LONG ret = ::RegGetKeySecurity(m_hKey, si, psd, pnBytes); 1345 return ret; 1346 } 1347 1348 LONG SetKeySecurity(SECURITY_INFORMATION si, 1349 PSECURITY_DESCRIPTOR psd) throw() 1350 { 1351 ATLASSERT(m_hKey); 1352 LONG ret = ::RegSetKeySecurity(m_hKey, si, psd); 1353 return ret; 1354 } 1355 1356 operator HKEY() const throw() 1357 { 1358 return m_hKey; 1359 } 1360 1361 CRegKey& operator=(CRegKey& key) throw() 1362 { 1363 if (m_hKey != key.m_hKey) 1364 { 1365 Close(); 1366 Attach(key.Detach()); 1367 } 1368 return *this; 1369 } 1370 1371 protected: 1372 // get the total size of a multistring 1373 static ULONG _GetMultiStringSize(LPCTSTR pszz) 1374 { 1375 size_t count = 0; 1376 do 1377 { 1378 size_t len = _tcslen(pszz); 1379 count += len + 1; 1380 pszz += len + 1; 1381 } while (*pszz != TEXT('\0')); 1382 ++count; 1383 ATLASSERT(count * sizeof(TCHAR) <= ULONG_MAX); 1384 return (ULONG)count * sizeof(TCHAR); 1385 } 1386 1387 // delete key recursively 1388 static LONG _DoDeleteKeyTree(HKEY hParentKey, LPCTSTR lpszKey) 1389 { 1390 ATLASSERT(hParentKey); 1391 ATLASSERT(lpszKey); 1392 1393 // open the key 1394 CRegKey key; 1395 LONG ret = key.Open(hParentKey, lpszKey); 1396 if (ret != ERROR_SUCCESS) 1397 { 1398 return ret; // failure 1399 } 1400 1401 // get the longest length of subkey names 1402 DWORD NameMax; 1403 ret = ::RegQueryInfoKey(key, NULL, NULL, NULL, NULL, &NameMax, NULL, 1404 NULL, NULL, NULL, NULL, NULL); 1405 if (ret != ERROR_SUCCESS) 1406 { 1407 return ret; // failure 1408 } 1409 ++NameMax; // for NUL 1410 1411 // allocate the string buffer for names if necessary 1412 TCHAR szNameBuf[MAX_PATH], *pszName; 1413 if (NameMax > MAX_PATH) 1414 { 1415 pszName = (TCHAR *)malloc(NameMax * sizeof(TCHAR)); 1416 ATLASSERT(pszName); 1417 if (pszName == NULL) 1418 { 1419 return ERROR_OUTOFMEMORY; // failure 1420 } 1421 } 1422 else 1423 { 1424 NameMax = MAX_PATH; 1425 pszName = szNameBuf; 1426 } 1427 1428 // enumerate every subkey and delete 1429 for (;;) 1430 { 1431 DWORD Count = NameMax; 1432 ret = key.EnumKey(0, pszName, &Count); 1433 if (ret != ERROR_SUCCESS) 1434 { 1435 if (ret == ERROR_NO_MORE_ITEMS) 1436 ret = ERROR_SUCCESS; 1437 break; 1438 } 1439 1440 ret = CRegKey::_DoDeleteKeyTree(key, pszName); 1441 if (ret != ERROR_SUCCESS) 1442 break; 1443 } 1444 1445 // close key 1446 key.Close(); 1447 1448 // delete the subkey 1449 if (ret == ERROR_SUCCESS) 1450 ret = ::RegDeleteKey(hParentKey, lpszKey); 1451 1452 // delete the buffer if any 1453 if (pszName != szNameBuf) 1454 free(pszName); 1455 1456 return ret; 1457 } 1458 }; 1459 1460 template<class T> 1461 class CComHeapPtr : public CHeapPtr<T, CComAllocator> 1462 { 1463 public: 1464 CComHeapPtr() 1465 { 1466 } 1467 1468 explicit CComHeapPtr(T *lp) : 1469 CHeapPtr<T, CComAllocator>(lp) 1470 { 1471 } 1472 }; 1473 1474 1475 inline HRESULT __stdcall AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID &iid, LPDWORD pdw) 1476 { 1477 CComPtr<IConnectionPointContainer> container; 1478 CComPtr<IConnectionPoint> connectionPoint; 1479 HRESULT hResult; 1480 1481 if (pUnkCP == NULL) 1482 return E_INVALIDARG; 1483 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container); 1484 if (FAILED(hResult)) 1485 return hResult; 1486 hResult = container->FindConnectionPoint(iid, &connectionPoint); 1487 if (FAILED(hResult)) 1488 return hResult; 1489 return connectionPoint->Advise(pUnk, pdw); 1490 } 1491 1492 inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw) 1493 { 1494 CComPtr<IConnectionPointContainer> container; 1495 CComPtr<IConnectionPoint> connectionPoint; 1496 HRESULT hResult; 1497 1498 if (pUnkCP == NULL) 1499 return E_INVALIDARG; 1500 hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container); 1501 if (FAILED(hResult)) 1502 return hResult; 1503 hResult = container->FindConnectionPoint(iid, &connectionPoint); 1504 if (FAILED(hResult)) 1505 return hResult; 1506 return connectionPoint->Unadvise(dw); 1507 } 1508 1509 inline HRESULT __stdcall AtlInternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject) 1510 { 1511 int i; 1512 IUnknown *resultInterface; 1513 HRESULT hResult; 1514 1515 ATLASSERT(pThis != NULL && pEntries != NULL); 1516 if (pThis == NULL || pEntries == NULL) 1517 return E_INVALIDARG; 1518 ATLASSERT(ppvObject != NULL); 1519 if (ppvObject == NULL) 1520 return E_POINTER; 1521 1522 if (InlineIsEqualUnknown(iid)) 1523 { 1524 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[0].dw); 1525 *ppvObject = resultInterface; 1526 resultInterface->AddRef(); 1527 return S_OK; 1528 } 1529 1530 i = 0; 1531 while (pEntries[i].pFunc != 0) 1532 { 1533 if (pEntries[i].piid == NULL || InlineIsEqualGUID(iid, *pEntries[i].piid)) 1534 { 1535 if (pEntries[i].pFunc == reinterpret_cast<_ATL_CREATORARGFUNC *>(1)) 1536 { 1537 ATLASSERT(pEntries[i].piid != NULL); 1538 resultInterface = reinterpret_cast<IUnknown *>(reinterpret_cast<char *>(pThis) + pEntries[i].dw); 1539 *ppvObject = resultInterface; 1540 resultInterface->AddRef(); 1541 return S_OK; 1542 } 1543 else 1544 { 1545 hResult = pEntries[i].pFunc(pThis, iid, ppvObject, 0); 1546 if (hResult == S_OK) 1547 return hResult; 1548 if (FAILED(hResult) && pEntries[i].piid != NULL) 1549 break; 1550 } 1551 } 1552 i++; 1553 } 1554 *ppvObject = NULL; 1555 return E_NOINTERFACE; 1556 } 1557 1558 inline HRESULT __stdcall AtlWinModuleInit(_ATL_WIN_MODULE *pWinModule) 1559 { 1560 if (pWinModule == NULL) 1561 return E_INVALIDARG; 1562 pWinModule->m_pCreateWndList = NULL; 1563 return pWinModule->m_csWindowCreate.Init(); 1564 } 1565 1566 inline HRESULT __stdcall AtlWinModuleTerm(_ATL_WIN_MODULE *pWinModule, HINSTANCE hInst) 1567 { 1568 if (pWinModule == NULL) 1569 return E_INVALIDARG; 1570 pWinModule->m_csWindowCreate.Term(); 1571 return S_OK; 1572 } 1573 1574 inline void __stdcall AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pWinModule, _AtlCreateWndData *pData, void *pObject) 1575 { 1576 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true); 1577 1578 ATLASSERT(pWinModule != NULL); 1579 ATLASSERT(pObject != NULL); 1580 1581 pData->m_pThis = pObject; 1582 pData->m_dwThreadID = ::GetCurrentThreadId(); 1583 pData->m_pNext = pWinModule->m_pCreateWndList; 1584 pWinModule->m_pCreateWndList = pData; 1585 } 1586 1587 inline void *__stdcall AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *pWinModule) 1588 { 1589 CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, true); 1590 void *result; 1591 _AtlCreateWndData *currentEntry; 1592 _AtlCreateWndData **previousLink; 1593 DWORD threadID; 1594 1595 ATLASSERT(pWinModule != NULL); 1596 1597 result = NULL; 1598 threadID = GetCurrentThreadId(); 1599 currentEntry = pWinModule->m_pCreateWndList; 1600 previousLink = &pWinModule->m_pCreateWndList; 1601 while (currentEntry != NULL) 1602 { 1603 if (currentEntry->m_dwThreadID == threadID) 1604 { 1605 *previousLink = currentEntry->m_pNext; 1606 result = currentEntry->m_pThis; 1607 break; 1608 } 1609 previousLink = ¤tEntry->m_pNext; 1610 currentEntry = currentEntry->m_pNext; 1611 } 1612 return result; 1613 } 1614 1615 // Adapted from dll/win32/atl/atl.c 1616 inline HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex, 1617 BSTR *pbstrPath, ITypeLib **ppTypeLib) 1618 { 1619 size_t index_len = lpszIndex ? wcslen(lpszIndex) : 0; 1620 CComHeapPtr<WCHAR> path; 1621 path.Allocate(MAX_PATH + index_len + wcslen(L".tlb")); 1622 1623 if (!path) 1624 return E_OUTOFMEMORY; 1625 1626 size_t path_len = GetModuleFileNameW(inst, path, MAX_PATH); 1627 if (!path_len) 1628 return HRESULT_FROM_WIN32(GetLastError()); 1629 1630 if (index_len) 1631 wcscat(path, lpszIndex); 1632 1633 CComPtr<ITypeLib> typelib; 1634 HRESULT hResult = LoadTypeLib(path, &typelib); 1635 if (FAILED(hResult)) 1636 { 1637 WCHAR *ptr; 1638 for (ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--) 1639 ; 1640 if (*ptr != '.') 1641 ptr = (WCHAR*)path + path_len; 1642 wcscpy(ptr, L".tlb"); 1643 1644 hResult = LoadTypeLib(path, &typelib); 1645 } 1646 1647 if (SUCCEEDED(hResult)) 1648 { 1649 *pbstrPath = SysAllocString(path); 1650 if (!*pbstrPath) 1651 { 1652 typelib.Release(); 1653 hResult = E_OUTOFMEMORY; 1654 } 1655 } 1656 1657 if (FAILED(hResult)) 1658 return hResult; 1659 1660 *ppTypeLib = typelib.Detach(); 1661 return S_OK; 1662 } 1663 1664 // Adapted from dll/win32/atl/atl.c 1665 inline HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index) 1666 { 1667 CComBSTR path; 1668 CComPtr<ITypeLib> typelib; 1669 HRESULT hResult = AtlLoadTypeLib(inst, index, &path, &typelib); 1670 if (FAILED(hResult)) 1671 return hResult; 1672 1673 return RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */ 1674 } 1675 1676 // Adapted from dll/win32/atl/atl.c 1677 inline HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const _ATL_CATMAP_ENTRY *catmap, BOOL reg) 1678 { 1679 if (!catmap) 1680 return S_OK; 1681 1682 CComPtr<ICatRegister> catreg; 1683 1684 HRESULT hResult = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&catreg); 1685 if (FAILED(hResult)) 1686 return hResult; 1687 1688 for (const _ATL_CATMAP_ENTRY *iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) 1689 { 1690 CATID catid = *iter->pcatid; 1691 1692 if (iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) 1693 { 1694 if (reg) 1695 hResult = catreg->RegisterClassImplCategories(clsid, 1, &catid); 1696 else 1697 hResult = catreg->UnRegisterClassImplCategories(clsid, 1, &catid); 1698 } 1699 else 1700 { 1701 if (reg) 1702 hResult = catreg->RegisterClassReqCategories(clsid, 1, &catid); 1703 else 1704 hResult = catreg->UnRegisterClassReqCategories(clsid, 1, &catid); 1705 } 1706 if (FAILED(hResult)) 1707 return hResult; 1708 } 1709 1710 if (!reg) 1711 { 1712 WCHAR reg_path[256] = L"CLSID\\"; 1713 1714 StringFromGUID2(clsid, reg_path + wcslen(reg_path), 64); 1715 wcscat(reg_path, L"\\"); 1716 WCHAR* ptr = reg_path + wcslen(reg_path); 1717 1718 wcscpy(ptr, L"Implemented Categories"); 1719 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); 1720 1721 wcscpy(ptr, L"Required Categories"); 1722 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); 1723 } 1724 1725 return hResult; 1726 } 1727 1728 1729 // Adapted from dll/win32/atl80/atl80.c 1730 inline HRESULT __stdcall AtlComModuleRegisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid) 1731 { 1732 HRESULT hResult = S_OK; 1733 1734 for (_ATL_OBJMAP_ENTRY ** iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) 1735 { 1736 if (!*iter) 1737 continue; 1738 _ATL_OBJMAP_ENTRY* entry = *iter; 1739 if (clsid && !IsEqualCLSID(*entry->pclsid, *clsid)) 1740 continue; 1741 1742 hResult = entry->pfnUpdateRegistry(TRUE); 1743 if (FAILED(hResult)) 1744 return hResult; 1745 1746 const _ATL_CATMAP_ENTRY *catmap = entry->pfnGetCategoryMap(); 1747 if (catmap) 1748 { 1749 hResult = AtlRegisterClassCategoriesHelper(*entry->pclsid, catmap, TRUE); 1750 if (FAILED(hResult)) 1751 return hResult; 1752 } 1753 } 1754 1755 if (bRegTypeLib) 1756 { 1757 hResult = AtlRegisterTypeLib(mod->m_hInstTypeLib, NULL); 1758 } 1759 1760 return hResult; 1761 } 1762 1763 // Adapted from dll/win32/atl/atl.c 1764 inline HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bUnRegTypeLib, const CLSID *clsid) 1765 { 1766 HRESULT hResult = S_OK; 1767 1768 for (_ATL_OBJMAP_ENTRY **iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) 1769 { 1770 if (!*iter) 1771 continue; 1772 _ATL_OBJMAP_ENTRY* entry = *iter; 1773 if (clsid && !IsEqualCLSID(*entry->pclsid, *clsid)) 1774 continue; 1775 1776 const _ATL_CATMAP_ENTRY *catmap = entry->pfnGetCategoryMap(); 1777 if (catmap) 1778 { 1779 hResult = AtlRegisterClassCategoriesHelper(*entry->pclsid, catmap, FALSE); 1780 if (FAILED(hResult)) 1781 return hResult; 1782 } 1783 1784 hResult = entry->pfnUpdateRegistry(FALSE); 1785 if (FAILED(hResult)) 1786 return hResult; 1787 } 1788 1789 if (bUnRegTypeLib) 1790 { 1791 CComPtr<ITypeLib> typelib; 1792 TLIBATTR *attr; 1793 CComBSTR path; 1794 1795 hResult = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib); 1796 if (FAILED(hResult)) 1797 return hResult; 1798 1799 hResult = typelib->GetLibAttr(&attr); 1800 if (SUCCEEDED(hResult)) 1801 { 1802 hResult = UnRegisterTypeLib(attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind); 1803 typelib->ReleaseTLibAttr(attr); 1804 } 1805 } 1806 1807 return hResult; 1808 } 1809 1810 1811 // Adapted from dll/win32/atl/atl.c 1812 inline HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags) 1813 { 1814 _ATL_OBJMAP_ENTRY **iter; 1815 IUnknown* unk = NULL; 1816 HRESULT hr; 1817 1818 if (!module) 1819 return E_INVALIDARG; 1820 1821 for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) 1822 { 1823 if (!(*iter)->pfnGetClassObject) 1824 continue; 1825 1826 hr = (*iter)->pfnGetClassObject((void*)(*iter)->pfnCreateInstance, IID_IUnknown, (void**)&unk); 1827 if (FAILED(hr)) 1828 return hr; 1829 1830 hr = CoRegisterClassObject(*(*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister); 1831 unk->Release(); 1832 if (FAILED(hr)) 1833 return hr; 1834 } 1835 1836 return S_OK; 1837 } 1838 1839 1840 // Adapted from dll/win32/atl/atl.c 1841 inline HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module) 1842 { 1843 _ATL_OBJMAP_ENTRY **iter; 1844 HRESULT hr; 1845 1846 if (!module) 1847 return E_INVALIDARG; 1848 1849 for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) 1850 { 1851 hr = CoRevokeClassObject((*iter)->dwRegister); 1852 if (FAILED(hr)) 1853 return hr; 1854 } 1855 1856 return S_OK; 1857 } 1858 1859 1860 }; // namespace ATL 1861 1862 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE 1863 using namespace ATL; 1864 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE 1865