Reactos

[ATL] Add OBJECT_ENTRY_AUTO for simpler com object registration

Of course gcc needs a nasty hack to include the symbol.
CORE-18936

+216 -19
+158 -19
sdk/lib/atl/atlbase.h
··· 59 59 __declspec(selectany) CAtlModule *_pAtlModule = NULL; 60 60 __declspec(selectany) CComModule *_pModule = NULL; 61 61 62 + template <bool isDll, typename T> struct CAtlValidateModuleConfiguration 63 + { 64 + #if !defined(_WINDLL) && !defined(_USRDLL) 65 + static_assert(!isDll, "_WINDLL or _USRDLL must be defined when 'CAtlDllModuleT<T>' is used"); 66 + #else 67 + static_assert(isDll, "_WINDLL or _USRDLL must be defined when 'CAtlExeModuleT<T>' is used"); 68 + #endif 69 + }; 70 + 62 71 63 72 struct _ATL_CATMAP_ENTRY 64 73 { ··· 172 181 #endif 173 182 }; 174 183 typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE; 184 + 185 + 186 + // Auto object map 187 + 188 + #if defined(_MSC_VER) 189 + #pragma section("ATL$__a", read, write) 190 + #pragma section("ATL$__z", read, write) 191 + #pragma section("ATL$__m", read, write) 192 + #define _ATLALLOC(x) __declspec(allocate(x)) 193 + 194 + #if defined(_M_IX86) 195 + #define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pobjMap_" #class)); 196 + #elif defined(_M_IA64) || defined(_M_AMD64) || (_M_ARM) || defined(_M_ARM64) 197 + #define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pobjMap_" #class)); 198 + #else 199 + #error Your platform is not supported. 200 + #endif 201 + 202 + #elif defined(__GNUC__) 203 + 204 + // GCC completely ignores __attribute__((unused)) on the __pobjMap_ pointer, so we pass it to a function that is not allowed to be optimized.... 205 + static int __attribute__((optimize("O0"), unused)) hack_for_gcc(const _ATL_OBJMAP_ENTRY * const *) 206 + { 207 + return 1; 208 + } 209 + 210 + #define _ATLALLOC(x) __attribute__((section(x))) 211 + #define OBJECT_ENTRY_PRAGMA(class) static int __pobjMap_hack_##class = hack_for_gcc(&__pobjMap_##class); 212 + 213 + #else 214 + #error Your compiler is not supported. 215 + #endif 216 + 217 + 218 + extern "C" 219 + { 220 + __declspec(selectany) _ATLALLOC("ATL$__a") _ATL_OBJMAP_ENTRY *__pobjMapEntryFirst = NULL; 221 + __declspec(selectany) _ATLALLOC("ATL$__z") _ATL_OBJMAP_ENTRY *__pobjMapEntryLast = NULL; 222 + } 223 + 175 224 176 225 struct _ATL_REGMAP_ENTRY 177 226 { ··· 551 600 CAtlComModule() 552 601 { 553 602 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)this, &m_hInstTypeLib); 554 - m_ppAutoObjMapFirst = NULL; 555 - m_ppAutoObjMapLast = NULL; 603 + 604 + m_ppAutoObjMapFirst = &__pobjMapEntryFirst + 1; 605 + m_ppAutoObjMapLast = &__pobjMapEntryLast; 556 606 if (FAILED(m_csObjMap.Init())) 557 607 { 558 608 ATLASSERT(0); ··· 577 627 return AtlComModuleUnregisterServer(this, bUnRegTypeLib, pCLSID); 578 628 } 579 629 580 - 581 630 void Term() 582 631 { 583 632 if (cbSize != 0) 584 633 { 585 - ATLASSERT(m_ppAutoObjMapFirst == NULL); 586 - ATLASSERT(m_ppAutoObjMapLast == NULL); 634 + for (_ATL_OBJMAP_ENTRY **iter = m_ppAutoObjMapFirst; iter < m_ppAutoObjMapLast; iter++) 635 + { 636 + _ATL_OBJMAP_ENTRY *ptr = *iter; 637 + if (!ptr) 638 + continue; 639 + 640 + if (!ptr->pCF) 641 + continue; 642 + 643 + ptr->pCF->Release(); 644 + ptr->pCF = NULL; 645 + } 587 646 m_csObjMap.Term(); 588 647 cbSize = 0; 589 648 } 590 649 } 650 + 651 + void ExecuteObjectMain(bool bStarting) 652 + { 653 + for (_ATL_OBJMAP_ENTRY **iter = m_ppAutoObjMapFirst; iter < m_ppAutoObjMapLast; iter++) 654 + { 655 + if (!*iter) 656 + continue; 657 + 658 + (*iter)->pfnObjectMain(bStarting); 659 + } 660 + } 591 661 }; 592 662 593 663 __declspec(selectany) CAtlComModule _AtlComModule; ··· 606 676 } 607 677 608 678 template <class T> 609 - class CAtlDllModuleT : public CAtlModuleT<T> 679 + class CAtlDllModuleT 680 + : public CAtlModuleT<T> 681 + , private CAtlValidateModuleConfiguration<true, T> 682 + 610 683 { 611 684 public: 612 685 CAtlDllModuleT() 613 686 { 687 + _AtlComModule.ExecuteObjectMain(true); 688 + } 689 + 690 + ~CAtlDllModuleT() 691 + { 692 + _AtlComModule.ExecuteObjectMain(false); 614 693 } 615 694 616 695 HRESULT DllCanUnloadNow() ··· 659 738 660 739 661 740 template <class T> 662 - class CAtlExeModuleT : public CAtlModuleT<T> 741 + class CAtlExeModuleT 742 + : public CAtlModuleT<T> 743 + , private CAtlValidateModuleConfiguration<false, T> 663 744 { 664 745 public: 665 746 DWORD m_dwMainThreadID; ··· 670 751 CAtlExeModuleT() 671 752 :m_dwMainThreadID(::GetCurrentThreadId()) 672 753 { 754 + _AtlComModule.ExecuteObjectMain(true); 673 755 } 674 756 675 757 ~CAtlExeModuleT() 676 758 { 759 + _AtlComModule.ExecuteObjectMain(false); 677 760 } 678 761 679 762 int WinMain(int nShowCmd) ··· 815 898 } 816 899 } 817 900 } 901 + 902 + for (_ATL_OBJMAP_ENTRY **iter = _AtlComModule.m_ppAutoObjMapFirst; iter < _AtlComModule.m_ppAutoObjMapLast; iter++) 903 + { 904 + if (*iter != NULL) 905 + (*iter)->pfnObjectMain(true); 906 + } 907 + 818 908 return S_OK; 819 909 } 820 910 821 911 void Term() 822 912 { 823 - _ATL_OBJMAP_ENTRY *objectMapEntry; 913 + _ATL_OBJMAP_ENTRY *objectMapEntry; 824 914 825 915 if (m_pObjMap != NULL) 826 916 { ··· 834 924 objectMapEntry++; 835 925 } 836 926 } 927 + 928 + for (_ATL_OBJMAP_ENTRY **iter = _AtlComModule.m_ppAutoObjMapFirst; iter < _AtlComModule.m_ppAutoObjMapLast; iter++) 929 + { 930 + if (*iter != NULL) 931 + (*iter)->pfnObjectMain(false); 932 + } 933 + 837 934 } 838 935 839 936 HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 840 937 { 841 - _ATL_OBJMAP_ENTRY *objectMapEntry; 842 - HRESULT hResult; 938 + _ATL_OBJMAP_ENTRY *objectMapEntry; 939 + HRESULT hResult; 843 940 844 941 ATLASSERT(ppv != NULL); 845 942 if (ppv == NULL) ··· 869 966 } 870 967 if (hResult == S_OK && *ppv == NULL) 871 968 { 872 - // FIXME: call AtlComModuleGetClassObject 873 - hResult = CLASS_E_CLASSNOTAVAILABLE; 969 + hResult = AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); 874 970 } 875 971 return hResult; 876 972 } ··· 1480 1576 1481 1577 inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw) 1482 1578 { 1483 - CComPtr<IConnectionPointContainer> container; 1484 - CComPtr<IConnectionPoint> connectionPoint; 1485 - HRESULT hResult; 1579 + CComPtr<IConnectionPointContainer> container; 1580 + CComPtr<IConnectionPoint> connectionPoint; 1581 + HRESULT hResult; 1486 1582 1487 1583 if (pUnkCP == NULL) 1488 1584 return E_INVALIDARG; ··· 1809 1905 1810 1906 for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) 1811 1907 { 1812 - if (!(*iter)->pfnGetClassObject) 1908 + _ATL_OBJMAP_ENTRY *ptr = *iter; 1909 + if (!ptr) 1910 + continue; 1911 + 1912 + if (!ptr->pfnGetClassObject) 1813 1913 continue; 1814 1914 1815 - hr = (*iter)->pfnGetClassObject((void*)(*iter)->pfnCreateInstance, IID_IUnknown, (void**)&unk); 1915 + hr = ptr->pfnGetClassObject((void*)ptr->pfnCreateInstance, IID_IUnknown, (void**)&unk); 1816 1916 if (FAILED(hr)) 1817 1917 return hr; 1818 1918 1819 - hr = CoRegisterClassObject(*(*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister); 1919 + hr = CoRegisterClassObject(*ptr->pclsid, unk, context, flags, &ptr->dwRegister); 1820 1920 unk->Release(); 1821 1921 if (FAILED(hr)) 1822 1922 return hr; ··· 1837 1937 1838 1938 for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) 1839 1939 { 1840 - hr = CoRevokeClassObject((*iter)->dwRegister); 1940 + _ATL_OBJMAP_ENTRY *ptr = *iter; 1941 + if (!ptr) 1942 + continue; 1943 + 1944 + hr = CoRevokeClassObject(ptr->dwRegister); 1841 1945 if (FAILED(hr)) 1842 1946 return hr; 1843 1947 } 1844 1948 1845 1949 return S_OK; 1846 1950 } 1951 + 1952 + // Adapted from dll/win32/atl/atl.c 1953 + inline HRESULT WINAPI 1954 + AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv) 1955 + { 1956 + if (!pm) 1957 + return E_INVALIDARG; 1958 + 1959 + for (_ATL_OBJMAP_ENTRY **iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) 1960 + { 1961 + _ATL_OBJMAP_ENTRY *ptr = *iter; 1962 + if (!ptr) 1963 + continue; 1964 + 1965 + if (IsEqualCLSID(*ptr->pclsid, rclsid) && ptr->pfnGetClassObject) 1966 + { 1967 + HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; 1968 + 1969 + if (!ptr->pCF) 1970 + { 1971 + CComCritSecLock<CComCriticalSection> lock(_AtlComModule.m_csObjMap, true); 1972 + if (!ptr->pCF) 1973 + { 1974 + hr = ptr->pfnGetClassObject((void *)ptr->pfnCreateInstance, IID_IUnknown, (void **)&ptr->pCF); 1975 + } 1976 + } 1977 + if (ptr->pCF) 1978 + hr = ptr->pCF->QueryInterface(riid, ppv); 1979 + return hr; 1980 + } 1981 + } 1982 + 1983 + return CLASS_E_CLASSNOTAVAILABLE; 1984 + } 1985 + 1847 1986 1848 1987 }; // namespace ATL 1849 1988
+58
sdk/lib/atl/atlcom.h
··· 30 30 template <class Base, const IID *piid, class T, class Copy, class ThreadModel = CComObjectThreadModel> 31 31 class CComEnum; 32 32 33 + #if defined(_WINDLL) | defined(_USRDLL) 33 34 #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectCached<cf> > _ClassFactoryCreatorClass; 35 + #else 36 + // Class factory should not change lock count 37 + #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectNoLock<cf>> _ClassFactoryCreatorClass; 38 + #endif 34 39 #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory) 35 40 #define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton<obj>) 36 41 ··· 539 544 } 540 545 }; 541 546 547 + 548 + template <class Base> 549 + class CComObjectNoLock : public Base 550 + { 551 + public: 552 + CComObjectNoLock(void* = NULL) 553 + { 554 + } 555 + 556 + virtual ~CComObjectNoLock() 557 + { 558 + this->FinalRelease(); 559 + } 560 + 561 + STDMETHOD_(ULONG, AddRef)() 562 + { 563 + return this->InternalAddRef(); 564 + } 565 + 566 + STDMETHOD_(ULONG, Release)() 567 + { 568 + ULONG newRefCount = this->InternalRelease(); 569 + if (newRefCount == 0) 570 + delete this; 571 + return newRefCount; 572 + } 573 + 574 + STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) 575 + { 576 + return this->_InternalQueryInterface(iid, ppvObject); 577 + } 578 + }; 579 + 580 + 542 581 #define BEGIN_COM_MAP(x) \ 543 582 public: \ 544 583 typedef x _ComMapClass; \ ··· 663 702 class::GetCategoryMap, \ 664 703 class::ObjectMain }, 665 704 705 + 706 + 707 + #define OBJECT_ENTRY_AUTO(clsid, class) \ 708 + ATL::_ATL_OBJMAP_ENTRY __objMap_##class = { \ 709 + &clsid, \ 710 + class ::UpdateRegistry, \ 711 + class ::_ClassFactoryCreatorClass::CreateInstance, \ 712 + class ::_CreatorClass::CreateInstance, \ 713 + NULL, \ 714 + 0, \ 715 + class ::GetObjectDescription, \ 716 + class ::GetCategoryMap, \ 717 + class ::ObjectMain}; \ 718 + extern "C" _ATLALLOC("ATL$__m") ATL::_ATL_OBJMAP_ENTRY *const __pobjMap_##class = &__objMap_##class; \ 719 + OBJECT_ENTRY_PRAGMA(class) 720 + 721 + 722 + 666 723 class CComClassFactory : 667 724 public IClassFactory, 668 725 public CComObjectRootEx<CComGlobalsThreadModel> ··· 772 829 { 773 830 public: 774 831 DECLARE_CLASSFACTORY() 832 + //DECLARE_AGGREGATABLE(T) // This should be here, but gcc... 775 833 776 834 static LPCTSTR WINAPI GetObjectDescription() 777 835 {