ole32: Implement MTA pinning with CoIncrementMTAUsage()/CoDecrementMTAUsage().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2020-02-13 13:50:13 +03:00 committed by Alexandre Julliard
parent b7047b5ae9
commit 03a7c25abe
8 changed files with 122 additions and 6 deletions

View File

@ -10,7 +10,7 @@
@ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr) ole32.CoCreateInstanceEx
@ stub CoCreateInstanceFromApp
@ stub CoDecodeProxy
@ stub CoDecrementMTAUsage
@ stdcall CoDecrementMTAUsage(ptr) ole32.CoDecrementMTAUsage
@ stdcall CoDisableCallCancellation(ptr) ole32.CoDisableCallCancellation
@ stub CoDisconnectContext
@ stdcall CoDisconnectObject(ptr long) ole32.CoDisconnectObject
@ -35,7 +35,7 @@
@ stub CoGetStdMarshalEx
@ stdcall CoGetTreatAsClass(ptr ptr) ole32.CoGetTreatAsClass
@ stdcall CoImpersonateClient() ole32.CoImpersonateClient
@ stub CoIncrementMTAUsage
@ stdcall CoIncrementMTAUsage(ptr) ole32.CoIncrementMTAUsage
@ stdcall CoInitializeEx(ptr long) ole32.CoInitializeEx
@ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) ole32.CoInitializeSecurity
@ stub CoInvalidateRemoteMachineBindings

View File

@ -10,7 +10,7 @@
@ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr) ole32.CoCreateInstanceEx
@ stub CoCreateInstanceFromApp
@ stub CoDecodeProxy
@ stub CoDecrementMTAUsage
@ stdcall CoDecrementMTAUsage(ptr) ole32.CoDecrementMTAUsage
@ stdcall CoDisableCallCancellation(ptr) ole32.CoDisableCallCancellation
@ stub CoDisconnectContext
@ stdcall CoDisconnectObject(ptr long) ole32.CoDisconnectObject
@ -35,7 +35,7 @@
@ stub CoGetStdMarshalEx
@ stdcall CoGetTreatAsClass(ptr ptr) ole32.CoGetTreatAsClass
@ stdcall CoImpersonateClient() ole32.CoImpersonateClient
@ stub CoIncrementMTAUsage
@ stdcall CoIncrementMTAUsage(ptr) ole32.CoIncrementMTAUsage
@ stdcall CoInitializeEx(ptr long) ole32.CoInitializeEx
@ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) ole32.CoInitializeSecurity
@ stub CoInvalidateRemoteMachineBindings

View File

@ -81,7 +81,7 @@
@ stub CoCreateObjectInContext
@ stub CoDeactivateObject
@ stub CoDecodeProxy
@ stub CoDecrementMTAUsage
@ stdcall CoDecrementMTAUsage(ptr) ole32.CoDecrementMTAUsage
@ stdcall CoDisableCallCancellation(ptr) ole32.CoDisableCallCancellation
@ stub CoDisconnectContext
@ stdcall CoDisconnectObject(ptr long) ole32.CoDisconnectObject
@ -116,7 +116,7 @@
@ stub CoGetSystemSecurityPermissions
@ stdcall CoGetTreatAsClass(ptr ptr) ole32.CoGetTreatAsClass
@ stdcall CoImpersonateClient() ole32.CoImpersonateClient
@ stub CoIncrementMTAUsage
@ stdcall CoIncrementMTAUsage(ptr) ole32.CoIncrementMTAUsage
@ stdcall CoInitializeEx(ptr long) ole32.CoInitializeEx
@ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) ole32.CoInitializeSecurity
@ stdcall CoInitializeWOW(long long) ole32.CoInitializeWOW

View File

@ -637,6 +637,7 @@ static APARTMENT *apartment_construct(DWORD model)
list_init(&apt->proxies);
list_init(&apt->stubmgrs);
list_init(&apt->loaded_dlls);
list_init(&apt->usage_cookies);
apt->ipidc = 0;
apt->refs = 1;
apt->remunk_exported = FALSE;
@ -5268,6 +5269,72 @@ HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier)
return info->apt ? S_OK : CO_E_NOTINITIALIZED;
}
struct mta_cookie
{
struct list entry;
};
/***********************************************************************
* CoIncrementMTAUsage [OLE32.@]
*/
HRESULT WINAPI CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE *cookie)
{
struct mta_cookie *mta_cookie;
TRACE("%p\n", cookie);
*cookie = NULL;
if (!(mta_cookie = heap_alloc(sizeof(*mta_cookie))))
return E_OUTOFMEMORY;
EnterCriticalSection(&csApartment);
if (MTA)
apartment_addref(MTA);
else
MTA = apartment_construct(COINIT_MULTITHREADED);
list_add_head(&MTA->usage_cookies, &mta_cookie->entry);
LeaveCriticalSection(&csApartment);
*cookie = (CO_MTA_USAGE_COOKIE)mta_cookie;
return S_OK;
}
/***********************************************************************
* CoDecrementMTAUsage [OLE32.@]
*/
HRESULT WINAPI CoDecrementMTAUsage(CO_MTA_USAGE_COOKIE cookie)
{
struct mta_cookie *mta_cookie = (struct mta_cookie *)cookie;
TRACE("%p\n", cookie);
EnterCriticalSection(&csApartment);
if (MTA)
{
struct mta_cookie *cur;
LIST_FOR_EACH_ENTRY(cur, &MTA->usage_cookies, struct mta_cookie, entry)
{
if (mta_cookie == cur)
{
list_remove(&cur->entry);
heap_free(cur);
apartment_release(MTA);
break;
}
}
}
LeaveCriticalSection(&csApartment);
return S_OK;
}
/***********************************************************************
* CoDisableCallCancellation [OLE32.@]
*/

View File

@ -151,6 +151,8 @@ struct apartment
HWND win; /* message window (LOCK) */
LPMESSAGEFILTER filter; /* message filter (CS cs) */
BOOL main; /* is this a main-threaded-apartment? (RO) */
/* MTA-only */
struct list usage_cookies; /* Used for refcount control with CoIncrementMTAUsage()/CoDecrementMTAUsage(). */
};
struct init_spy

View File

@ -14,6 +14,7 @@
@ stdcall CoCreateGuid(ptr)
@ stdcall CoCreateInstance(ptr ptr long ptr ptr)
@ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr)
@ stdcall CoDecrementMTAUsage(ptr)
@ stdcall CoDisableCallCancellation(ptr)
@ stdcall CoDisconnectObject(ptr long)
@ stdcall CoDosDateTimeToFileTime(long long ptr) kernel32.DosDateTimeToFileTime
@ -47,6 +48,7 @@
@ stub CoGetTIDFromIPID
@ stdcall CoGetTreatAsClass(ptr ptr)
@ stdcall CoImpersonateClient()
@ stdcall CoIncrementMTAUsage(ptr)
@ stdcall CoInitialize(ptr)
@ stdcall CoInitializeEx(ptr long)
@ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr)

View File

@ -76,6 +76,8 @@ static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNe
static HRESULT (WINAPI * pCoTreatAsClass)(REFCLSID clsidOld, REFCLSID pClsidNew);
static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
static HRESULT (WINAPI * pCoGetApartmentType)(APTTYPE *type, APTTYPEQUALIFIER *qualifier);
static HRESULT (WINAPI * pCoIncrementMTAUsage)(CO_MTA_USAGE_COOKIE *cookie);
static HRESULT (WINAPI * pCoDecrementMTAUsage)(CO_MTA_USAGE_COOKIE cookie);
static LONG (WINAPI * pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
@ -3818,6 +3820,8 @@ static void init_funcs(void)
pCoTreatAsClass = (void*)GetProcAddress(hOle32,"CoTreatAsClass");
pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
pCoGetApartmentType = (void*)GetProcAddress(hOle32, "CoGetApartmentType");
pCoIncrementMTAUsage = (void*)GetProcAddress(hOle32, "CoIncrementMTAUsage");
pCoDecrementMTAUsage = (void*)GetProcAddress(hOle32, "CoDecrementMTAUsage");
pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
@ -3916,6 +3920,42 @@ static void test_CoGetCurrentProcess(void)
ok(id2 && id2 != id, "Unexpected id from another thread.\n");
}
static void test_mta_usage(void)
{
CO_MTA_USAGE_COOKIE cookie, cookie2;
HRESULT hr;
if (!pCoIncrementMTAUsage)
{
win_skip("CoIncrementMTAUsage() is not available.\n");
return;
}
test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
cookie = 0;
hr = pCoIncrementMTAUsage(&cookie);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(cookie != NULL, "Unexpected cookie %p.\n", cookie);
cookie2 = 0;
hr = pCoIncrementMTAUsage(&cookie2);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(cookie2 != NULL && cookie2 != cookie, "Unexpected cookie %p.\n", cookie2);
test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA);
hr = pCoDecrementMTAUsage(cookie);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA);
hr = pCoDecrementMTAUsage(cookie2);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
}
START_TEST(compobj)
{
init_funcs();
@ -3967,6 +4007,7 @@ START_TEST(compobj)
test_GlobalOptions();
test_implicit_mta();
test_CoGetCurrentProcess();
test_mta_usage();
DeleteFileA( testlib );
}

View File

@ -287,12 +287,16 @@ typedef enum tagCOINIT
COINIT_SPEED_OVER_MEMORY = 0x8 /* Trade memory for speed */
} COINIT;
DECLARE_HANDLE(CO_MTA_USAGE_COOKIE);
HRESULT WINAPI CoInitialize(LPVOID lpReserved);
HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit);
void WINAPI CoUninitialize(void);
DWORD WINAPI CoGetCurrentProcess(void);
HRESULT WINAPI CoGetCurrentLogicalThreadId(GUID *id);
HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier);
HRESULT WINAPI CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE *cookie);
HRESULT WINAPI CoDecrementMTAUsage(CO_MTA_USAGE_COOKIE cookie);
HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
void WINAPI CoFreeAllLibraries(void);