mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 00:50:23 +00:00
[ATL] Add OBJECT_ENTRY_AUTO for simpler com object registration
Of course gcc needs a nasty hack to include the symbol. CORE-18936
This commit is contained in:
parent
bf29d98a54
commit
d12880829f
2 changed files with 216 additions and 19 deletions
|
@ -59,6 +59,15 @@ class CAtlComModule;
|
||||||
__declspec(selectany) CAtlModule *_pAtlModule = NULL;
|
__declspec(selectany) CAtlModule *_pAtlModule = NULL;
|
||||||
__declspec(selectany) CComModule *_pModule = NULL;
|
__declspec(selectany) CComModule *_pModule = NULL;
|
||||||
|
|
||||||
|
template <bool isDll, typename T> struct CAtlValidateModuleConfiguration
|
||||||
|
{
|
||||||
|
#if !defined(_WINDLL) && !defined(_USRDLL)
|
||||||
|
static_assert(!isDll, "_WINDLL or _USRDLL must be defined when 'CAtlDllModuleT<T>' is used");
|
||||||
|
#else
|
||||||
|
static_assert(isDll, "_WINDLL or _USRDLL must be defined when 'CAtlExeModuleT<T>' is used");
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct _ATL_CATMAP_ENTRY
|
struct _ATL_CATMAP_ENTRY
|
||||||
{
|
{
|
||||||
|
@ -173,6 +182,46 @@ struct _ATL_WIN_MODULE70
|
||||||
};
|
};
|
||||||
typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE;
|
typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE;
|
||||||
|
|
||||||
|
|
||||||
|
// Auto object map
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma section("ATL$__a", read, write)
|
||||||
|
#pragma section("ATL$__z", read, write)
|
||||||
|
#pragma section("ATL$__m", read, write)
|
||||||
|
#define _ATLALLOC(x) __declspec(allocate(x))
|
||||||
|
|
||||||
|
#if defined(_M_IX86)
|
||||||
|
#define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pobjMap_" #class));
|
||||||
|
#elif defined(_M_IA64) || defined(_M_AMD64) || (_M_ARM) || defined(_M_ARM64)
|
||||||
|
#define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pobjMap_" #class));
|
||||||
|
#else
|
||||||
|
#error Your platform is not supported.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
|
||||||
|
// GCC completely ignores __attribute__((unused)) on the __pobjMap_ pointer, so we pass it to a function that is not allowed to be optimized....
|
||||||
|
static int __attribute__((optimize("O0"), unused)) hack_for_gcc(const _ATL_OBJMAP_ENTRY * const *)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _ATLALLOC(x) __attribute__((section(x)))
|
||||||
|
#define OBJECT_ENTRY_PRAGMA(class) static int __pobjMap_hack_##class = hack_for_gcc(&__pobjMap_##class);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error Your compiler is not supported.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
__declspec(selectany) _ATLALLOC("ATL$__a") _ATL_OBJMAP_ENTRY *__pobjMapEntryFirst = NULL;
|
||||||
|
__declspec(selectany) _ATLALLOC("ATL$__z") _ATL_OBJMAP_ENTRY *__pobjMapEntryLast = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct _ATL_REGMAP_ENTRY
|
struct _ATL_REGMAP_ENTRY
|
||||||
{
|
{
|
||||||
LPCOLESTR szKey;
|
LPCOLESTR szKey;
|
||||||
|
@ -551,8 +600,9 @@ public:
|
||||||
CAtlComModule()
|
CAtlComModule()
|
||||||
{
|
{
|
||||||
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)this, &m_hInstTypeLib);
|
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)this, &m_hInstTypeLib);
|
||||||
m_ppAutoObjMapFirst = NULL;
|
|
||||||
m_ppAutoObjMapLast = NULL;
|
m_ppAutoObjMapFirst = &__pobjMapEntryFirst + 1;
|
||||||
|
m_ppAutoObjMapLast = &__pobjMapEntryLast;
|
||||||
if (FAILED(m_csObjMap.Init()))
|
if (FAILED(m_csObjMap.Init()))
|
||||||
{
|
{
|
||||||
ATLASSERT(0);
|
ATLASSERT(0);
|
||||||
|
@ -577,17 +627,37 @@ public:
|
||||||
return AtlComModuleUnregisterServer(this, bUnRegTypeLib, pCLSID);
|
return AtlComModuleUnregisterServer(this, bUnRegTypeLib, pCLSID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Term()
|
void Term()
|
||||||
{
|
{
|
||||||
if (cbSize != 0)
|
if (cbSize != 0)
|
||||||
{
|
{
|
||||||
ATLASSERT(m_ppAutoObjMapFirst == NULL);
|
for (_ATL_OBJMAP_ENTRY **iter = m_ppAutoObjMapFirst; iter < m_ppAutoObjMapLast; iter++)
|
||||||
ATLASSERT(m_ppAutoObjMapLast == NULL);
|
{
|
||||||
|
_ATL_OBJMAP_ENTRY *ptr = *iter;
|
||||||
|
if (!ptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!ptr->pCF)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ptr->pCF->Release();
|
||||||
|
ptr->pCF = NULL;
|
||||||
|
}
|
||||||
m_csObjMap.Term();
|
m_csObjMap.Term();
|
||||||
cbSize = 0;
|
cbSize = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExecuteObjectMain(bool bStarting)
|
||||||
|
{
|
||||||
|
for (_ATL_OBJMAP_ENTRY **iter = m_ppAutoObjMapFirst; iter < m_ppAutoObjMapLast; iter++)
|
||||||
|
{
|
||||||
|
if (!*iter)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
(*iter)->pfnObjectMain(bStarting);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
__declspec(selectany) CAtlComModule _AtlComModule;
|
__declspec(selectany) CAtlComModule _AtlComModule;
|
||||||
|
@ -606,11 +676,20 @@ HRESULT CAtlModuleT<T>::UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class CAtlDllModuleT : public CAtlModuleT<T>
|
class CAtlDllModuleT
|
||||||
|
: public CAtlModuleT<T>
|
||||||
|
, private CAtlValidateModuleConfiguration<true, T>
|
||||||
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CAtlDllModuleT()
|
CAtlDllModuleT()
|
||||||
{
|
{
|
||||||
|
_AtlComModule.ExecuteObjectMain(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CAtlDllModuleT()
|
||||||
|
{
|
||||||
|
_AtlComModule.ExecuteObjectMain(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT DllCanUnloadNow()
|
HRESULT DllCanUnloadNow()
|
||||||
|
@ -659,7 +738,9 @@ public:
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class CAtlExeModuleT : public CAtlModuleT<T>
|
class CAtlExeModuleT
|
||||||
|
: public CAtlModuleT<T>
|
||||||
|
, private CAtlValidateModuleConfiguration<false, T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DWORD m_dwMainThreadID;
|
DWORD m_dwMainThreadID;
|
||||||
|
@ -670,10 +751,12 @@ public:
|
||||||
CAtlExeModuleT()
|
CAtlExeModuleT()
|
||||||
:m_dwMainThreadID(::GetCurrentThreadId())
|
:m_dwMainThreadID(::GetCurrentThreadId())
|
||||||
{
|
{
|
||||||
|
_AtlComModule.ExecuteObjectMain(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CAtlExeModuleT()
|
~CAtlExeModuleT()
|
||||||
{
|
{
|
||||||
|
_AtlComModule.ExecuteObjectMain(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int WinMain(int nShowCmd)
|
int WinMain(int nShowCmd)
|
||||||
|
@ -815,12 +898,19 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (_ATL_OBJMAP_ENTRY **iter = _AtlComModule.m_ppAutoObjMapFirst; iter < _AtlComModule.m_ppAutoObjMapLast; iter++)
|
||||||
|
{
|
||||||
|
if (*iter != NULL)
|
||||||
|
(*iter)->pfnObjectMain(true);
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Term()
|
void Term()
|
||||||
{
|
{
|
||||||
_ATL_OBJMAP_ENTRY *objectMapEntry;
|
_ATL_OBJMAP_ENTRY *objectMapEntry;
|
||||||
|
|
||||||
if (m_pObjMap != NULL)
|
if (m_pObjMap != NULL)
|
||||||
{
|
{
|
||||||
|
@ -834,12 +924,19 @@ public:
|
||||||
objectMapEntry++;
|
objectMapEntry++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (_ATL_OBJMAP_ENTRY **iter = _AtlComModule.m_ppAutoObjMapFirst; iter < _AtlComModule.m_ppAutoObjMapLast; iter++)
|
||||||
|
{
|
||||||
|
if (*iter != NULL)
|
||||||
|
(*iter)->pfnObjectMain(false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
||||||
{
|
{
|
||||||
_ATL_OBJMAP_ENTRY *objectMapEntry;
|
_ATL_OBJMAP_ENTRY *objectMapEntry;
|
||||||
HRESULT hResult;
|
HRESULT hResult;
|
||||||
|
|
||||||
ATLASSERT(ppv != NULL);
|
ATLASSERT(ppv != NULL);
|
||||||
if (ppv == NULL)
|
if (ppv == NULL)
|
||||||
|
@ -869,8 +966,7 @@ public:
|
||||||
}
|
}
|
||||||
if (hResult == S_OK && *ppv == NULL)
|
if (hResult == S_OK && *ppv == NULL)
|
||||||
{
|
{
|
||||||
// FIXME: call AtlComModuleGetClassObject
|
hResult = AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv);
|
||||||
hResult = CLASS_E_CLASSNOTAVAILABLE;
|
|
||||||
}
|
}
|
||||||
return hResult;
|
return hResult;
|
||||||
}
|
}
|
||||||
|
@ -1480,9 +1576,9 @@ inline HRESULT __stdcall AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID &
|
||||||
|
|
||||||
inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw)
|
inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw)
|
||||||
{
|
{
|
||||||
CComPtr<IConnectionPointContainer> container;
|
CComPtr<IConnectionPointContainer> container;
|
||||||
CComPtr<IConnectionPoint> connectionPoint;
|
CComPtr<IConnectionPoint> connectionPoint;
|
||||||
HRESULT hResult;
|
HRESULT hResult;
|
||||||
|
|
||||||
if (pUnkCP == NULL)
|
if (pUnkCP == NULL)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
@ -1809,14 +1905,18 @@ inline HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module,
|
||||||
|
|
||||||
for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++)
|
for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++)
|
||||||
{
|
{
|
||||||
if (!(*iter)->pfnGetClassObject)
|
_ATL_OBJMAP_ENTRY *ptr = *iter;
|
||||||
|
if (!ptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
hr = (*iter)->pfnGetClassObject((void*)(*iter)->pfnCreateInstance, IID_IUnknown, (void**)&unk);
|
if (!ptr->pfnGetClassObject)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hr = ptr->pfnGetClassObject((void*)ptr->pfnCreateInstance, IID_IUnknown, (void**)&unk);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
hr = CoRegisterClassObject(*(*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister);
|
hr = CoRegisterClassObject(*ptr->pclsid, unk, context, flags, &ptr->dwRegister);
|
||||||
unk->Release();
|
unk->Release();
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -1837,7 +1937,11 @@ inline HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
|
||||||
|
|
||||||
for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++)
|
for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++)
|
||||||
{
|
{
|
||||||
hr = CoRevokeClassObject((*iter)->dwRegister);
|
_ATL_OBJMAP_ENTRY *ptr = *iter;
|
||||||
|
if (!ptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hr = CoRevokeClassObject(ptr->dwRegister);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -1845,6 +1949,41 @@ inline HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adapted from dll/win32/atl/atl.c
|
||||||
|
inline HRESULT WINAPI
|
||||||
|
AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
|
||||||
|
{
|
||||||
|
if (!pm)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
for (_ATL_OBJMAP_ENTRY **iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++)
|
||||||
|
{
|
||||||
|
_ATL_OBJMAP_ENTRY *ptr = *iter;
|
||||||
|
if (!ptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (IsEqualCLSID(*ptr->pclsid, rclsid) && ptr->pfnGetClassObject)
|
||||||
|
{
|
||||||
|
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
|
||||||
|
if (!ptr->pCF)
|
||||||
|
{
|
||||||
|
CComCritSecLock<CComCriticalSection> lock(_AtlComModule.m_csObjMap, true);
|
||||||
|
if (!ptr->pCF)
|
||||||
|
{
|
||||||
|
hr = ptr->pfnGetClassObject((void *)ptr->pfnCreateInstance, IID_IUnknown, (void **)&ptr->pCF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ptr->pCF)
|
||||||
|
hr = ptr->pCF->QueryInterface(riid, ppv);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}; // namespace ATL
|
}; // namespace ATL
|
||||||
|
|
||||||
#ifndef _ATL_NO_AUTOMATIC_NAMESPACE
|
#ifndef _ATL_NO_AUTOMATIC_NAMESPACE
|
||||||
|
|
|
@ -30,7 +30,12 @@ namespace ATL
|
||||||
template <class Base, const IID *piid, class T, class Copy, class ThreadModel = CComObjectThreadModel>
|
template <class Base, const IID *piid, class T, class Copy, class ThreadModel = CComObjectThreadModel>
|
||||||
class CComEnum;
|
class CComEnum;
|
||||||
|
|
||||||
|
#if defined(_WINDLL) | defined(_USRDLL)
|
||||||
#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectCached<cf> > _ClassFactoryCreatorClass;
|
#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectCached<cf> > _ClassFactoryCreatorClass;
|
||||||
|
#else
|
||||||
|
// Class factory should not change lock count
|
||||||
|
#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectNoLock<cf>> _ClassFactoryCreatorClass;
|
||||||
|
#endif
|
||||||
#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
|
#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
|
||||||
#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton<obj>)
|
#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton<obj>)
|
||||||
|
|
||||||
|
@ -539,6 +544,40 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
class CComObjectNoLock : public Base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CComObjectNoLock(void* = NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~CComObjectNoLock()
|
||||||
|
{
|
||||||
|
this->FinalRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHOD_(ULONG, AddRef)()
|
||||||
|
{
|
||||||
|
return this->InternalAddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHOD_(ULONG, Release)()
|
||||||
|
{
|
||||||
|
ULONG newRefCount = this->InternalRelease();
|
||||||
|
if (newRefCount == 0)
|
||||||
|
delete this;
|
||||||
|
return newRefCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
|
||||||
|
{
|
||||||
|
return this->_InternalQueryInterface(iid, ppvObject);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define BEGIN_COM_MAP(x) \
|
#define BEGIN_COM_MAP(x) \
|
||||||
public: \
|
public: \
|
||||||
typedef x _ComMapClass; \
|
typedef x _ComMapClass; \
|
||||||
|
@ -663,6 +702,24 @@ public:
|
||||||
class::GetCategoryMap, \
|
class::GetCategoryMap, \
|
||||||
class::ObjectMain },
|
class::ObjectMain },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define OBJECT_ENTRY_AUTO(clsid, class) \
|
||||||
|
ATL::_ATL_OBJMAP_ENTRY __objMap_##class = { \
|
||||||
|
&clsid, \
|
||||||
|
class ::UpdateRegistry, \
|
||||||
|
class ::_ClassFactoryCreatorClass::CreateInstance, \
|
||||||
|
class ::_CreatorClass::CreateInstance, \
|
||||||
|
NULL, \
|
||||||
|
0, \
|
||||||
|
class ::GetObjectDescription, \
|
||||||
|
class ::GetCategoryMap, \
|
||||||
|
class ::ObjectMain}; \
|
||||||
|
extern "C" _ATLALLOC("ATL$__m") ATL::_ATL_OBJMAP_ENTRY *const __pobjMap_##class = &__objMap_##class; \
|
||||||
|
OBJECT_ENTRY_PRAGMA(class)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CComClassFactory :
|
class CComClassFactory :
|
||||||
public IClassFactory,
|
public IClassFactory,
|
||||||
public CComObjectRootEx<CComGlobalsThreadModel>
|
public CComObjectRootEx<CComGlobalsThreadModel>
|
||||||
|
@ -772,6 +829,7 @@ class CComCoClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DECLARE_CLASSFACTORY()
|
DECLARE_CLASSFACTORY()
|
||||||
|
//DECLARE_AGGREGATABLE(T) // This should be here, but gcc...
|
||||||
|
|
||||||
static LPCTSTR WINAPI GetObjectDescription()
|
static LPCTSTR WINAPI GetObjectDescription()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue