diff --git a/patches/ole32-Implicit_MTA/0001-ole32-Always-grab-a-reference-to-apt-in-CoGetClassOb.patch b/patches/ole32-Implicit_MTA/0001-ole32-Always-grab-a-reference-to-apt-in-CoGetClassOb.patch new file mode 100644 index 00000000..46b945dd --- /dev/null +++ b/patches/ole32-Implicit_MTA/0001-ole32-Always-grab-a-reference-to-apt-in-CoGetClassOb.patch @@ -0,0 +1,128 @@ +From 46aa3907c61a91e1f6199088a129b838e3b900fe Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Wed, 28 Mar 2018 20:15:55 -0500 +Subject: [PATCH 1/7] ole32: Always grab a reference to apt in + CoGetClassObject(). + +This necessitates tracking whether the apartment is currently being destroyed +(or something similar), but this would become necessary anyway. + +Signed-off-by: Zebediah Figura +--- + dlls/ole32/compobj.c | 26 +++++++++++++++++--------- + dlls/ole32/compobj_private.h | 1 + + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c +index a317bf7..1c7645b 100644 +--- a/dlls/ole32/compobj.c ++++ b/dlls/ole32/compobj.c +@@ -1162,9 +1162,17 @@ DWORD apartment_release(struct apartment *apt) + + ret = InterlockedDecrement(&apt->refs); + TRACE("%s: after = %d\n", wine_dbgstr_longlong(apt->oxid), ret); ++ ++ if (apt->being_destroyed) ++ { ++ LeaveCriticalSection(&csApartment); ++ return ret; ++ } ++ + /* destruction stuff that needs to happen under csApartment CS */ + if (ret == 0) + { ++ apt->being_destroyed = TRUE; + if (apt == MTA) MTA = NULL; + else if (apt == MainApartment) MainApartment = NULL; + list_remove(&apt->entry); +@@ -2981,7 +2989,6 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( + IUnknown *regClassObject; + HRESULT hres = E_UNEXPECTED; + APARTMENT *apt; +- BOOL release_apt = FALSE; + + TRACE("CLSID: %s,IID: %s\n", debugstr_guid(rclsid), debugstr_guid(iid)); + +@@ -2990,14 +2997,15 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( + + *ppv = NULL; + +- if (!(apt = COM_CurrentApt())) ++ if ((apt = COM_CurrentApt())) ++ apartment_addref(apt); ++ else + { + if (!(apt = apartment_find_mta())) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } +- release_apt = TRUE; + } + + if (pServerInfo) { +@@ -3009,7 +3017,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( + { + if (IsEqualCLSID(rclsid, &CLSID_InProcFreeMarshaler)) + { +- if (release_apt) apartment_release(apt); ++ apartment_release(apt); + return FTMarshalCF_Create(iid, ppv); + } + if (IsEqualCLSID(rclsid, &CLSID_GlobalOptions)) +@@ -3035,7 +3043,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( + + hres = get_inproc_class_object(apt, &clsreg, &comclass->clsid, iid, !(dwClsContext & WINE_CLSCTX_DONT_HOST), ppv); + ReleaseActCtx(data.hActCtx); +- if (release_apt) apartment_release(apt); ++ apartment_release(apt); + return hres; + } + } +@@ -3056,7 +3064,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( + * is good since we are not returning it in the "out" parameter. + */ + IUnknown_Release(regClassObject); +- if (release_apt) apartment_release(apt); ++ apartment_release(apt); + return hres; + } + +@@ -3091,7 +3099,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( + * other types */ + if (SUCCEEDED(hres)) + { +- if (release_apt) apartment_release(apt); ++ apartment_release(apt); + return hres; + } + } +@@ -3127,11 +3135,11 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( + * other types */ + if (SUCCEEDED(hres)) + { +- if (release_apt) apartment_release(apt); ++ apartment_release(apt); + return hres; + } + } +- if (release_apt) apartment_release(apt); ++ apartment_release(apt); + + /* Next try out of process */ + if (CLSCTX_LOCAL_SERVER & dwClsContext) +diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h +index 9e65c3e..12413f7 100644 +--- a/dlls/ole32/compobj_private.h ++++ b/dlls/ole32/compobj_private.h +@@ -142,6 +142,7 @@ struct apartment + DWORD host_apt_tid; /* thread ID of apartment hosting objects of differing threading model (CS cs) */ + HWND host_apt_hwnd; /* handle to apartment window of host apartment (CS cs) */ + LocalServer *local_server; /* A marshallable object exposing local servers (CS cs) */ ++ BOOL being_destroyed; /* is currently being destroyed */ + + /* FIXME: OIDs should be given out by RPCSS */ + OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */ +-- +2.7.4 + diff --git a/patches/ole32-Implicit_MTA/0002-ole32-Add-a-helper-for-grabbing-the-current-apartmen.patch b/patches/ole32-Implicit_MTA/0002-ole32-Add-a-helper-for-grabbing-the-current-apartmen.patch new file mode 100644 index 00000000..1b5c4ee9 --- /dev/null +++ b/patches/ole32-Implicit_MTA/0002-ole32-Add-a-helper-for-grabbing-the-current-apartmen.patch @@ -0,0 +1,105 @@ +From e2f80faaee4be9b8c2477d6b6039a69c7a73403f Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Wed, 28 Mar 2018 20:24:35 -0500 +Subject: [PATCH 2/7] ole32: Add a helper for grabbing the current apartment or + MTA. + +Signed-off-by: Zebediah Figura +--- + dlls/ole32/compobj.c | 48 +++++++++++++++++++++++++----------------------- + 1 file changed, 25 insertions(+), 23 deletions(-) + +diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c +index 1c7645b..a3b4598 100644 +--- a/dlls/ole32/compobj.c ++++ b/dlls/ole32/compobj.c +@@ -734,6 +734,19 @@ static APARTMENT *apartment_find_mta(void) + return apt; + } + ++/* Return the current apartment if it exists, or, failing that, the MTA. Caller ++ * must free the returned apartment in either case. */ ++static APARTMENT *apartment_get_current_or_mta(void) ++{ ++ APARTMENT *apt = COM_CurrentApt(); ++ if (apt) ++ { ++ apartment_addref(apt); ++ return apt; ++ } ++ return apartment_find_mta(); ++} ++ + static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass) + { + list_remove(&curClass->entry); +@@ -2997,15 +3010,10 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject( + + *ppv = NULL; + +- if ((apt = COM_CurrentApt())) +- apartment_addref(apt); +- else ++ if (!(apt = apartment_get_current_or_mta())) + { +- if (!(apt = apartment_find_mta())) +- { +- ERR("apartment not initialised\n"); +- return CO_E_NOTINITIALIZED; +- } ++ ERR("apartment not initialised\n"); ++ return CO_E_NOTINITIALIZED; + } + + if (pServerInfo) { +@@ -3298,15 +3306,12 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstanceEx( + if(FAILED(hres)) + clsid = *rclsid; + +- if (!(apt = COM_CurrentApt())) ++ if (!(apt = apartment_get_current_or_mta())) + { +- if (!(apt = apartment_find_mta())) +- { +- ERR("apartment not initialised\n"); +- return CO_E_NOTINITIALIZED; +- } +- apartment_release(apt); ++ ERR("apartment not initialised\n"); ++ return CO_E_NOTINITIALIZED; + } ++ apartment_release(apt); + + /* + * The Standard Global Interface Table (GIT) object is a process-wide singleton. +@@ -4998,22 +5003,19 @@ HRESULT WINAPI CoGetObjectContext(REFIID riid, void **ppv) + HRESULT WINAPI CoGetContextToken( ULONG_PTR *token ) + { + struct oletls *info = COM_CurrentInfo(); ++ APARTMENT *apt; + + TRACE("(%p)\n", token); + + if (!info) + return E_OUTOFMEMORY; + +- if (!info->apt) ++ if (!(apt = apartment_get_current_or_mta())) + { +- APARTMENT *apt; +- if (!(apt = apartment_find_mta())) +- { +- ERR("apartment not initialised\n"); +- return CO_E_NOTINITIALIZED; +- } +- apartment_release(apt); ++ ERR("apartment not initialised\n"); ++ return CO_E_NOTINITIALIZED; + } ++ apartment_release(apt); + + if (!token) + return E_POINTER; +-- +2.7.4 + diff --git a/patches/ole32-Implicit_MTA/0003-ole32-Allow-more-functions-to-use-the-implicit-MTA.patch b/patches/ole32-Implicit_MTA/0003-ole32-Allow-more-functions-to-use-the-implicit-MTA.patch new file mode 100644 index 00000000..be9e1baa --- /dev/null +++ b/patches/ole32-Implicit_MTA/0003-ole32-Allow-more-functions-to-use-the-implicit-MTA.patch @@ -0,0 +1,225 @@ +From 2f75a3115d6377d4c6a707990755354b80c948af Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Wed, 28 Mar 2018 20:27:45 -0500 +Subject: [PATCH 3/7] ole32: Allow more functions to use the implicit MTA. + +Signed-off-by: Zebediah Figura +--- + dlls/ole32/compobj.c | 43 ++++++++++++++++++++++++++++++------------- + dlls/ole32/tests/compobj.c | 24 ++++++++++++++++++++++++ + 2 files changed, 54 insertions(+), 13 deletions(-) + +diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c +index a3b4598..ca91848 100644 +--- a/dlls/ole32/compobj.c ++++ b/dlls/ole32/compobj.c +@@ -1089,8 +1089,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject( + + TRACE("(%08x)\n",dwRegister); + +- apt = COM_CurrentApt(); +- if (!apt) ++ if (!(apt = apartment_get_current_or_mta())) + { + ERR("COM was not initialized\n"); + return CO_E_NOTINITIALIZED; +@@ -1121,7 +1120,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject( + } + + LeaveCriticalSection( &csRegisteredClassList ); +- ++ apartment_release(apt); + return hr; + } + +@@ -2072,9 +2071,11 @@ HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved ) + return hr; + } + +- apt = COM_CurrentApt(); +- if (!apt) ++ if (!(apt = apartment_get_current_or_mta())) ++ { ++ ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; ++ } + + manager = get_stub_manager_from_object(apt, lpUnk, FALSE); + if (manager) { +@@ -2089,6 +2090,7 @@ HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved ) + * not found, making apps think that the object was disconnected, when + * it actually wasn't */ + ++ apartment_release(apt); + return S_OK; + } + +@@ -2596,7 +2598,7 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid) + static const WCHAR wszInterface[] = {'I','n','t','e','r','f','a','c','e','\\',0}; + static const WCHAR wszPSC[] = {'\\','P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0}; + WCHAR path[ARRAYSIZE(wszInterface) - 1 + CHARS_IN_GUID - 1 + ARRAYSIZE(wszPSC)]; +- APARTMENT *apt = COM_CurrentApt(); ++ APARTMENT *apt; + struct registered_psclsid *registered_psclsid; + ACTCTX_SECTION_KEYED_DATA data; + HRESULT hr; +@@ -2605,11 +2607,12 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid) + + TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid); + +- if (!apt) ++ if (!(apt = apartment_get_current_or_mta())) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } ++ apartment_release(apt); + + if (!pclsid) + return E_INVALIDARG; +@@ -2680,16 +2683,17 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid) + */ + HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid) + { +- APARTMENT *apt = COM_CurrentApt(); ++ APARTMENT *apt; + struct registered_psclsid *registered_psclsid; + + TRACE("(%s, %s)\n", debugstr_guid(riid), debugstr_guid(rclsid)); + +- if (!apt) ++ if (!(apt = apartment_get_current_or_mta())) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } ++ apartment_release(apt); + + EnterCriticalSection(&cs_registered_psclsid_list); + +@@ -2815,8 +2819,7 @@ HRESULT WINAPI CoRegisterClassObject( + if ( (lpdwRegister==0) || (pUnk==0) ) + return E_INVALIDARG; + +- apt = COM_CurrentApt(); +- if (!apt) ++ if (!(apt = apartment_get_current_or_mta())) + { + ERR("COM was not initialized\n"); + return CO_E_NOTINITIALIZED; +@@ -2839,16 +2842,21 @@ HRESULT WINAPI CoRegisterClassObject( + if (dwClsContext & CLSCTX_LOCAL_SERVER) + hr = CoLockObjectExternal(foundObject, TRUE, FALSE); + IUnknown_Release(foundObject); ++ apartment_release(apt); + return hr; + } + IUnknown_Release(foundObject); + ERR("object already registered for class %s\n", debugstr_guid(rclsid)); ++ apartment_release(apt); + return CO_E_OBJISREG; + } + + newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass)); + if ( newClass == NULL ) ++ { ++ apartment_release(apt); + return E_OUTOFMEMORY; ++ } + + newClass->classIdentifier = *rclsid; + newClass->apartment_id = apt->oxid; +@@ -2877,7 +2885,10 @@ HRESULT WINAPI CoRegisterClassObject( + + hr = get_local_server_stream(apt, &marshal_stream); + if(FAILED(hr)) ++ { ++ apartment_release(apt); + return hr; ++ } + + hr = RPC_StartLocalServer(&newClass->classIdentifier, + marshal_stream, +@@ -2885,6 +2896,7 @@ HRESULT WINAPI CoRegisterClassObject( + &newClass->RpcRegistration); + IStream_Release(marshal_stream); + } ++ apartment_release(apt); + return S_OK; + } + +@@ -3645,8 +3657,11 @@ HRESULT WINAPI CoLockObjectExternal( + TRACE("pUnk=%p, fLock=%s, fLastUnlockReleases=%s\n", + pUnk, fLock ? "TRUE" : "FALSE", fLastUnlockReleases ? "TRUE" : "FALSE"); + +- apt = COM_CurrentApt(); +- if (!apt) return CO_E_NOTINITIALIZED; ++ if (!(apt = apartment_get_current_or_mta())) ++ { ++ ERR("apartment not initialised\n"); ++ return CO_E_NOTINITIALIZED; ++ } + + stubmgr = get_stub_manager_from_object(apt, pUnk, fLock); + if (!stubmgr) +@@ -3655,6 +3670,7 @@ HRESULT WINAPI CoLockObjectExternal( + /* Note: native is pretty broken here because it just silently + * fails, without returning an appropriate error code, making apps + * think that the object was disconnected, when it actually wasn't */ ++ apartment_release(apt); + return S_OK; + } + +@@ -3664,6 +3680,7 @@ HRESULT WINAPI CoLockObjectExternal( + stub_manager_ext_release(stubmgr, 1, FALSE, fLastUnlockReleases); + + stub_manager_int_release(stubmgr); ++ apartment_release(apt); + return S_OK; + } + +diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c +index 0ce941b..ecfbac8 100644 +--- a/dlls/ole32/tests/compobj.c ++++ b/dlls/ole32/tests/compobj.c +@@ -3701,6 +3701,8 @@ static DWORD CALLBACK implicit_mta_proc(void *param) + IComThreadingInfo *threading_info; + ULONG_PTR token; + IUnknown *unk; ++ DWORD cookie; ++ CLSID clsid; + HRESULT hr; + + test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA, TRUE, TRUE); +@@ -3720,6 +3722,28 @@ static DWORD CALLBACK implicit_mta_proc(void *param) + hr = CoGetContextToken(&token); + ok_ole_success(hr, "CoGetContextToken"); + ++ hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); ++ ok_ole_success(hr, "CoRegisterPSClsid"); ++ ++ hr = CoGetPSClsid(&IID_IClassFactory, &clsid); ++ ok_ole_success(hr, "CoGetPSClsid"); ++ ++ hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, ++ CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); ++ ok_ole_success(hr, "CoRegisterClassObject"); ++ ++ hr = CoRevokeClassObject(cookie); ++ ok_ole_success(hr, "CoRevokeClassObject"); ++ ++ hr = CoRegisterMessageFilter(NULL, NULL); ++ ok(hr == CO_E_NOT_SUPPORTED, "got %#x\n", hr); ++ ++ hr = CoLockObjectExternal((IUnknown *)&Test_Unknown, TRUE, TRUE); ++ ok_ole_success(hr, "CoLockObjectExternal"); ++ ++ hr = CoDisconnectObject((IUnknown *)&Test_Unknown, 0); ++ ok_ole_success(hr, "CoDisconnectObject"); ++ + return 0; + } + +-- +2.7.4 + diff --git a/patches/ole32-Implicit_MTA/0004-ole32-Report-the-implicit-MTA-in-CoGetApartmentType.patch b/patches/ole32-Implicit_MTA/0004-ole32-Report-the-implicit-MTA-in-CoGetApartmentType.patch new file mode 100644 index 00000000..725aa013 --- /dev/null +++ b/patches/ole32-Implicit_MTA/0004-ole32-Report-the-implicit-MTA-in-CoGetApartmentType.patch @@ -0,0 +1,119 @@ +From 8a5c262f21cd3caedae8f83a471cd5491ba9dde2 Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Fri, 23 Mar 2018 22:59:32 -0500 +Subject: [PATCH 4/7] ole32: Report the implicit MTA in CoGetApartmentType(). + +Signed-off-by: Zebediah Figura +--- + dlls/ole32/compobj.c | 10 +++++++++- + dlls/ole32/tests/compobj.c | 19 ++++++++----------- + 2 files changed, 17 insertions(+), 12 deletions(-) + +diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c +index ca91848..9cbfaee 100644 +--- a/dlls/ole32/compobj.c ++++ b/dlls/ole32/compobj.c +@@ -5108,8 +5108,9 @@ HRESULT Handler_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) + HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier) + { + struct oletls *info = COM_CurrentInfo(); ++ APARTMENT *apt; + +- FIXME("(%p, %p): semi-stub\n", type, qualifier); ++ TRACE("(%p, %p)\n", type, qualifier); + + if (!type || !qualifier) + return E_INVALIDARG; +@@ -5128,6 +5129,13 @@ HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier) + + *qualifier = APTTYPEQUALIFIER_NONE; + ++ if (!info->apt && (apt = apartment_find_mta())) ++ { ++ apartment_release(apt); ++ *type = APTTYPE_MTA; ++ *qualifier = APTTYPEQUALIFIER_IMPLICIT_MTA; ++ } ++ + return info->apt ? S_OK : CO_E_NOTINITIALIZED; + } + +diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c +index ecfbac8..b9b7be0 100644 +--- a/dlls/ole32/tests/compobj.c ++++ b/dlls/ole32/tests/compobj.c +@@ -602,9 +602,8 @@ static void test_StringFromGUID2(void) + ok(len == 0, "len: %d (expected 0)\n", len); + } + +-#define test_apt_type(t, q, t_t, t_q) _test_apt_type(t, q, t_t, t_q, __LINE__) +-static void _test_apt_type(APTTYPE expected_type, APTTYPEQUALIFIER expected_qualifier, BOOL todo_type, +- BOOL todo_qualifier, int line) ++#define test_apt_type(t, q) _test_apt_type(t, q, __LINE__) ++static void _test_apt_type(APTTYPE expected_type, APTTYPEQUALIFIER expected_qualifier, int line) + { + APTTYPEQUALIFIER qualifier = ~0u; + APTTYPE type = ~0u; +@@ -615,9 +614,7 @@ static void _test_apt_type(APTTYPE expected_type, APTTYPEQUALIFIER expected_qual + + hr = pCoGetApartmentType(&type, &qualifier); + ok_(__FILE__, line)(hr == S_OK || hr == CO_E_NOTINITIALIZED, "Unexpected return code: 0x%08x\n", hr); +-todo_wine_if(todo_type) + ok_(__FILE__, line)(type == expected_type, "Wrong apartment type %d, expected %d\n", type, expected_type); +-todo_wine_if(todo_qualifier) + ok_(__FILE__, line)(qualifier == expected_qualifier, "Wrong apartment qualifier %d, expected %d\n", qualifier, + expected_qualifier); + } +@@ -660,7 +657,7 @@ static void test_CoCreateInstance(void) + hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk); + ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr); + +- test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE); ++ test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE); + } + + static void test_CoGetClassObject(void) +@@ -682,7 +679,7 @@ static void test_CoGetClassObject(void) + broken(hr == CO_E_NOTINITIALIZED), /* win9x */ + "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr); + +- test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE); ++ test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE); + + if (!pRegOverridePredefKey) + { +@@ -1797,7 +1794,7 @@ static void test_CoGetObjectContext(void) + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + +- test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE, FALSE, FALSE); ++ test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE); + + hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo); + ok_ole_success(hr, "CoGetObjectContext"); +@@ -1993,11 +1990,11 @@ static void test_CoGetContextToken(void) + ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr); + ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token); + +- test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE, FALSE, FALSE); ++ test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE); + + CoInitialize(NULL); + +- test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE, FALSE, FALSE); ++ test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE); + + hr = pCoGetContextToken(NULL); + ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr); +@@ -3705,7 +3702,7 @@ static DWORD CALLBACK implicit_mta_proc(void *param) + CLSID clsid; + HRESULT hr; + +- test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA, TRUE, TRUE); ++ test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA); + + hr = CoCreateInstance(&CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); + ok_ole_success(hr, "CoCreateInstance"); +-- +2.7.4 + diff --git a/patches/ole32-Implicit_MTA/0005-ole32-tests-Test-CoWaitForMultipleHandles-in-an-unin.patch b/patches/ole32-Implicit_MTA/0005-ole32-tests-Test-CoWaitForMultipleHandles-in-an-unin.patch new file mode 100644 index 00000000..985ff3fc --- /dev/null +++ b/patches/ole32-Implicit_MTA/0005-ole32-tests-Test-CoWaitForMultipleHandles-in-an-unin.patch @@ -0,0 +1,57 @@ +From 52ec26e3aaeeada37c42f78ba5f01df49464147d Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Sat, 24 Mar 2018 08:34:52 -0500 +Subject: [PATCH 5/7] ole32/tests: Test CoWaitForMultipleHandles() in an + uninitialized or MTA apartment. + +Signed-off-by: Zebediah Figura +--- + dlls/ole32/tests/compobj.c | 26 ++++++++++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c +index b9b7be0..c43e86c 100644 +--- a/dlls/ole32/tests/compobj.c ++++ b/dlls/ole32/tests/compobj.c +@@ -2998,14 +2998,36 @@ static void test_CoWaitForMultipleHandles(void) + ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); + CloseHandle(thread); + ++ CoUninitialize(); ++ ++ /* If COM was not initialized, messages are neither pumped nor peeked at */ ++ PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); ++ hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); ++ ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr); ++ success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE); ++ ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success); ++ success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); ++ ok(success, "PeekMessage failed: %u\n", GetLastError()); ++ ++ /* same in an MTA */ ++ CoInitializeEx(NULL, COINIT_MULTITHREADED); ++ ++ PostMessageA(hWnd, WM_DDE_FIRST, 0, 0); ++ hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index); ++ ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr); ++ success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE); ++ ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success); ++ success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); ++ ok(success, "PeekMessage failed: %u\n", GetLastError()); ++ ++ CoUninitialize(); ++ + CloseHandle(handles[0]); + CloseHandle(handles[1]); + DestroyWindow(hWnd); + + success = UnregisterClassA(cls_name, GetModuleHandleA(0)); + ok(success, "UnregisterClass failed %u\n", GetLastError()); +- +- CoUninitialize(); + } + + static void test_CoGetMalloc(void) +-- +2.7.4 + diff --git a/patches/ole32-Implicit_MTA/0006-ole32-Allow-unmarshalling-objects-into-an-implicit-M.patch b/patches/ole32-Implicit_MTA/0006-ole32-Allow-unmarshalling-objects-into-an-implicit-M.patch new file mode 100644 index 00000000..4686241d --- /dev/null +++ b/patches/ole32-Implicit_MTA/0006-ole32-Allow-unmarshalling-objects-into-an-implicit-M.patch @@ -0,0 +1,365 @@ +From e3eb56f31aab40fcf5c20afa0d712cc77373e989 Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Sat, 24 Mar 2018 22:14:43 -0500 +Subject: [PATCH 6/7] ole32: Allow unmarshalling objects into an implicit MTA. + +Signed-off-by: Zebediah Figura +--- + dlls/ole32/compobj.c | 2 +- + dlls/ole32/compobj_private.h | 3 +- + dlls/ole32/marshal.c | 32 ++++++++---- + dlls/ole32/rpc.c | 12 +++-- + dlls/ole32/tests/marshal.c | 114 +++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 148 insertions(+), 15 deletions(-) + +diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c +index 9cbfaee..fd5cbde 100644 +--- a/dlls/ole32/compobj.c ++++ b/dlls/ole32/compobj.c +@@ -736,7 +736,7 @@ static APARTMENT *apartment_find_mta(void) + + /* Return the current apartment if it exists, or, failing that, the MTA. Caller + * must free the returned apartment in either case. */ +-static APARTMENT *apartment_get_current_or_mta(void) ++APARTMENT *apartment_get_current_or_mta(void) + { + APARTMENT *apt = COM_CurrentApt(); + if (apt) +diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h +index 12413f7..dc09d20 100644 +--- a/dlls/ole32/compobj_private.h ++++ b/dlls/ole32/compobj_private.h +@@ -212,7 +212,7 @@ void RPC_StartRemoting(struct apartment *apt) DECLSPEC_HIDDEN; + HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, + const OXID_INFO *oxid_info, + DWORD dest_context, void *dest_context_data, +- IRpcChannelBuffer **chan) DECLSPEC_HIDDEN; ++ IRpcChannelBuffer **chan, APARTMENT *apt) DECLSPEC_HIDDEN; + HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN; + void RPC_ExecuteCall(struct dispatch_params *params) DECLSPEC_HIDDEN; + HRESULT RPC_RegisterInterface(REFIID riid) DECLSPEC_HIDDEN; +@@ -248,6 +248,7 @@ HRESULT apartment_createwindowifneeded(struct apartment *apt) DECLSPEC_HIDDEN; + HWND apartment_getwindow(const struct apartment *apt) DECLSPEC_HIDDEN; + HRESULT enter_apartment(struct oletls *info, DWORD model) DECLSPEC_HIDDEN; + void leave_apartment(struct oletls *info) DECLSPEC_HIDDEN; ++APARTMENT *apartment_get_current_or_mta(void) DECLSPEC_HIDDEN; + + /* DCOM messages used by the apartment window (not compatible with native) */ + #define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = 0, LPARAM = (struct dispatch_params *) */ +diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c +index b39dac0..822d06e 100644 +--- a/dlls/ole32/marshal.c ++++ b/dlls/ole32/marshal.c +@@ -313,13 +313,15 @@ static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, UL + * the interfaces were returned */ + if (SUCCEEDED(hr)) + { ++ APARTMENT *apt = apartment_get_current_or_mta(); ++ + /* try to unmarshal each object returned to us */ + for (i = 0; i < nonlocal_mqis; i++) + { + ULONG index = mapping[i]; + HRESULT hrobj = qiresults[i].hResult; + if (hrobj == S_OK) +- hrobj = unmarshal_object(&qiresults[i].std, COM_CurrentApt(), ++ hrobj = unmarshal_object(&qiresults[i].std, apt, + This->dest_context, + This->dest_context_data, + pMQIs[index].pIID, &This->oxid_info, +@@ -331,6 +333,8 @@ static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, UL + ERR("Failed to get pointer to interface %s\n", debugstr_guid(pMQIs[index].pIID)); + pMQIs[index].hr = hrobj; + } ++ ++ apartment_release(apt); + } + + /* free the memory allocated by the proxy */ +@@ -1010,8 +1014,7 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk + if (This->sorflags & SORFP_NOLIFETIMEMGMT) + return S_FALSE; + +- apt = COM_CurrentApt(); +- if (!apt) ++ if (!(apt = apartment_get_current_or_mta())) + return CO_E_NOTINITIALIZED; + + called_in_original_apt = This->parent && (This->parent->oxid == apt->oxid); +@@ -1046,7 +1049,7 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk + stdobjref.ipid = This->oxid_info.ipidRemUnknown; + + /* do the unmarshal */ +- hr = unmarshal_object(&stdobjref, COM_CurrentApt(), This->dest_context, ++ hr = unmarshal_object(&stdobjref, apt, This->dest_context, + This->dest_context_data, &IID_IRemUnknown, + &This->oxid_info, (void**)remunk); + if (hr == S_OK && called_in_original_apt) +@@ -1056,6 +1059,7 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk + } + } + LeaveCriticalSection(&This->cs); ++ apartment_release(apt); + + TRACE("got IRemUnknown* pointer %p, hr = 0x%08x\n", *remunk, hr); + +@@ -1288,7 +1292,7 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, + &proxy_manager->oxid_info, + proxy_manager->dest_context, + proxy_manager->dest_context_data, +- &chanbuf); ++ &chanbuf, apt); + if (hr == S_OK) + hr = proxy_manager_create_ifproxy(proxy_manager, stdobjref, + riid, chanbuf, &ifproxy); +@@ -1324,14 +1328,14 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v + STDOBJREF stdobjref; + ULONG res; + HRESULT hres; +- APARTMENT *apt = COM_CurrentApt(); ++ APARTMENT *apt; + APARTMENT *stub_apt; + OXID oxid; + + TRACE("(...,%s,....)\n", debugstr_guid(riid)); + + /* we need an apartment to unmarshal into */ +- if (!apt) ++ if (!(apt = apartment_get_current_or_mta())) + { + ERR("Apartment not initialized\n"); + return CO_E_NOTINITIALIZED; +@@ -1339,10 +1343,18 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v + + /* read STDOBJREF from wire */ + hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res); +- if (hres != S_OK) return STG_E_READFAULT; ++ if (hres != S_OK) ++ { ++ apartment_release(apt); ++ return STG_E_READFAULT; ++ } + + hres = apartment_getoxid(apt, &oxid); +- if (hres != S_OK) return hres; ++ if (hres != S_OK) ++ { ++ apartment_release(apt); ++ return hres; ++ } + + /* check if we're marshalling back to ourselves */ + if ((oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid))) +@@ -1357,6 +1369,7 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v + stub_manager_ext_release(stubmgr, stdobjref.cPublicRefs, stdobjref.flags & SORFP_TABLEWEAK, FALSE); + + stub_manager_int_release(stubmgr); ++ apartment_release(apt); + return hres; + } + +@@ -1395,6 +1408,7 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v + if (hres != S_OK) WARN("Failed with error 0x%08x\n", hres); + else TRACE("Successfully created proxy %p\n", *ppv); + ++ apartment_release(apt); + return hres; + } + +diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c +index 8d8276e..5a7626b 100644 +--- a/dlls/ole32/rpc.c ++++ b/dlls/ole32/rpc.c +@@ -830,14 +830,16 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac + ORPC_EXTENT_ARRAY orpc_ext_array; + WIRE_ORPC_EXTENT *first_wire_orpc_extent = NULL; + HRESULT hrFault = S_OK; ++ APARTMENT *apt = apartment_get_current_or_mta(); + + TRACE("(%p) iMethod=%d\n", olemsg, olemsg->iMethod); + +- hr = ClientRpcChannelBuffer_IsCorrectApartment(This, COM_CurrentApt()); ++ hr = ClientRpcChannelBuffer_IsCorrectApartment(This, apt); + if (hr != S_OK) + { + ERR("called from wrong apartment, should have been 0x%s\n", + wine_dbgstr_longlong(This->oxid)); ++ if (apt) apartment_release(apt); + return RPC_E_WRONG_THREAD; + } + /* This situation should be impossible in multi-threaded apartments, +@@ -845,11 +847,12 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac + * Note: doing a COM call during the processing of a sent message is + * only disallowed if a client call is already being waited for + * completion */ +- if (!COM_CurrentApt()->multi_threaded && ++ if (!apt->multi_threaded && + COM_CurrentInfo()->pending_call_count_client && + InSendMessage()) + { + ERR("can't make an outgoing COM call in response to a sent message\n"); ++ apartment_release(apt); + return RPC_E_CANTCALLOUT_ININPUTSYNCCALL; + } + +@@ -967,6 +970,7 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac + + TRACE("-- 0x%08x\n", hr); + ++ apartment_release(apt); + return hr; + } + +@@ -1094,7 +1098,7 @@ static const IRpcChannelBufferVtbl ServerRpcChannelBufferVtbl = + HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, + const OXID_INFO *oxid_info, + DWORD dest_context, void *dest_context_data, +- IRpcChannelBuffer **chan) ++ IRpcChannelBuffer **chan, APARTMENT *apt) + { + ClientRpcChannelBuffer *This; + WCHAR endpoint[200]; +@@ -1148,7 +1152,7 @@ HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, + This->super.dest_context = dest_context; + This->super.dest_context_data = dest_context_data; + This->bind = bind; +- apartment_getoxid(COM_CurrentApt(), &This->oxid); ++ apartment_getoxid(apt, &This->oxid); + This->server_pid = oxid_info->dwPid; + This->event = NULL; + +diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c +index 12c46e9..c5c69f0 100644 +--- a/dlls/ole32/tests/marshal.c ++++ b/dlls/ole32/tests/marshal.c +@@ -3419,6 +3419,119 @@ static void test_manualresetevent(void) + ok(!ref, "Got nonzero ref: %d\n", ref); + } + ++static DWORD CALLBACK implicit_mta_unmarshal_proc(void *param) ++{ ++ IStream *stream = param; ++ IClassFactory *cf; ++ IUnknown *proxy; ++ HRESULT hr; ++ ++ IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); ++ hr = CoUnmarshalInterface(stream, &IID_IClassFactory, (void **)&cf); ++ ok_ole_success(hr, CoUnmarshalInterface); ++ ++ hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); ++ ok_ole_success(hr, IClassFactory_CreateInstance); ++ ++ IUnknown_Release(proxy); ++ ++ /* But if we initialize an STA in this apartment, it becomes the wrong one. */ ++ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); ++ ++ hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); ++ ok(hr == RPC_E_WRONG_THREAD, "got %#x\n", hr); ++ ++ CoUninitialize(); ++ ++ ok_more_than_one_lock(); ++ ok_non_zero_external_conn(); ++ ++ IClassFactory_Release(cf); ++ ++ ok_no_locks(); ++ ok_zero_external_conn(); ++ ok_last_release_closes(TRUE); ++ return 0; ++} ++ ++static DWORD CALLBACK implicit_mta_use_proc(void *param) ++{ ++ IClassFactory *cf = param; ++ IUnknown *proxy; ++ HRESULT hr; ++ ++ hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); ++ ok_ole_success(hr, IClassFactory_CreateInstance); ++ ++ IUnknown_Release(proxy); ++ ++ /* But if we initialize an STA in this apartment, it becomes the wrong one. */ ++ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); ++ ++ hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); ++ ok(hr == RPC_E_WRONG_THREAD, "got %#x\n", hr); ++ ++ CoUninitialize(); ++ return 0; ++} ++ ++static void test_implicit_mta(void) ++{ ++ HANDLE host_thread, thread; ++ IClassFactory *cf; ++ IStream *stream; ++ HRESULT hr; ++ DWORD tid; ++ ++ cLocks = 0; ++ external_connections = 0; ++ ++ CoInitializeEx(NULL, COINIT_MULTITHREADED); ++ ++ /* Firstly: we can unmarshal and use an object while in the implicit MTA. */ ++ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); ++ ok_ole_success(hr, CreateStreamOnHGlobal); ++ tid = start_host_object(stream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); ++ ++ ok_more_than_one_lock(); ++ ok_non_zero_external_conn(); ++ ++ thread = CreateThread(NULL, 0, implicit_mta_unmarshal_proc, stream, 0, NULL); ++ ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); ++ CloseHandle(thread); ++ ++ IStream_Release(stream); ++ end_host_object(tid, host_thread); ++ ++ /* Secondly: we can unmarshal an object into the real MTA and then use it ++ * from the implicit MTA. */ ++ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); ++ ok_ole_success(hr, CreateStreamOnHGlobal); ++ tid = start_host_object(stream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); ++ ++ ok_more_than_one_lock(); ++ ok_non_zero_external_conn(); ++ ++ IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); ++ hr = CoUnmarshalInterface(stream, &IID_IClassFactory, (void **)&cf); ++ ok_ole_success(hr, CoUnmarshalInterface); ++ ++ thread = CreateThread(NULL, 0, implicit_mta_use_proc, cf, 0, NULL); ++ ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); ++ CloseHandle(thread); ++ ++ IClassFactory_Release(cf); ++ IStream_Release(stream); ++ ++ ok_no_locks(); ++ ok_non_zero_external_conn(); ++ ok_last_release_closes(TRUE); ++ ++ end_host_object(tid, host_thread); ++ ++ CoUninitialize(); ++} ++ + static const char *debugstr_iid(REFIID riid) + { + static char name[256]; +@@ -3765,6 +3878,7 @@ START_TEST(marshal) + register_test_window(); + + test_cocreateinstance_proxy(); ++ test_implicit_mta(); + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + +-- +2.7.4 + diff --git a/patches/ole32-Implicit_MTA/0007-ole32-Allow-marshalling-objects-from-an-implicit-MTA.patch b/patches/ole32-Implicit_MTA/0007-ole32-Allow-marshalling-objects-from-an-implicit-MTA.patch new file mode 100644 index 00000000..61f0cae8 --- /dev/null +++ b/patches/ole32-Implicit_MTA/0007-ole32-Allow-marshalling-objects-from-an-implicit-MTA.patch @@ -0,0 +1,158 @@ +From f10ef429a65d47df792d67d5c54248eac1921a41 Mon Sep 17 00:00:00 2001 +From: Zebediah Figura +Date: Sat, 24 Mar 2018 22:44:56 -0500 +Subject: [PATCH 7/7] ole32: Allow marshalling objects from an implicit MTA. + +Signed-off-by: Zebediah Figura +--- + dlls/ole32/compobj_private.h | 2 +- + dlls/ole32/marshal.c | 5 +++-- + dlls/ole32/rpc.c | 2 +- + dlls/ole32/stubmanager.c | 3 +-- + dlls/ole32/tests/marshal.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 56 insertions(+), 6 deletions(-) + +diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h +index dc09d20..212d328 100644 +--- a/dlls/ole32/compobj_private.h ++++ b/dlls/ole32/compobj_private.h +@@ -200,7 +200,7 @@ void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const + void stub_manager_disconnect(struct stub_manager *m) DECLSPEC_HIDDEN; + HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **manager, IRpcStubBuffer **stub, + IRpcChannelBuffer **chan, IID *iid, IUnknown **iface) DECLSPEC_HIDDEN; +-HRESULT start_apartment_remote_unknown(void) DECLSPEC_HIDDEN; ++HRESULT start_apartment_remote_unknown(APARTMENT *apt) DECLSPEC_HIDDEN; + + HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags) DECLSPEC_HIDDEN; + +diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c +index 822d06e..7c0f541 100644 +--- a/dlls/ole32/marshal.c ++++ b/dlls/ole32/marshal.c +@@ -1225,11 +1225,11 @@ StdMarshalImpl_MarshalInterface( + STDOBJREF stdobjref; + ULONG res; + HRESULT hres; +- APARTMENT *apt = COM_CurrentApt(); ++ APARTMENT *apt; + + TRACE("(...,%s,...)\n", debugstr_guid(riid)); + +- if (!apt) ++ if (!(apt = apartment_get_current_or_mta())) + { + ERR("Apartment not initialized\n"); + return CO_E_NOTINITIALIZED; +@@ -1239,6 +1239,7 @@ StdMarshalImpl_MarshalInterface( + RPC_StartRemoting(apt); + + hres = marshal_object(apt, &stdobjref, riid, pv, dest_context, dest_context_data, mshlflags); ++ apartment_release(apt); + if (hres != S_OK) + { + ERR("Failed to create ifstub, hres=0x%x\n", hres); +diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c +index 5a7626b..a73d23c 100644 +--- a/dlls/ole32/rpc.c ++++ b/dlls/ole32/rpc.c +@@ -1648,7 +1648,7 @@ void RPC_StartRemoting(struct apartment *apt) + + /* FIXME: move remote unknown exporting into this function */ + } +- start_apartment_remote_unknown(); ++ start_apartment_remote_unknown(apt); + } + + +diff --git a/dlls/ole32/stubmanager.c b/dlls/ole32/stubmanager.c +index 57048c6..75c4b04 100644 +--- a/dlls/ole32/stubmanager.c ++++ b/dlls/ole32/stubmanager.c +@@ -812,11 +812,10 @@ static const IRemUnknownVtbl RemUnknown_Vtbl = + }; + + /* starts the IRemUnknown listener for the current apartment */ +-HRESULT start_apartment_remote_unknown(void) ++HRESULT start_apartment_remote_unknown(APARTMENT *apt) + { + IRemUnknown *pRemUnknown; + HRESULT hr = S_OK; +- APARTMENT *apt = COM_CurrentApt(); + + EnterCriticalSection(&apt->cs); + if (!apt->remunk_exported) +diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c +index c5c69f0..e8558dd 100644 +--- a/dlls/ole32/tests/marshal.c ++++ b/dlls/ole32/tests/marshal.c +@@ -3475,10 +3475,34 @@ static DWORD CALLBACK implicit_mta_use_proc(void *param) + return 0; + } + ++struct implicit_mta_marshal_data ++{ ++ IStream *stream; ++ HANDLE start; ++ HANDLE stop; ++}; ++ ++static DWORD CALLBACK implicit_mta_marshal_proc(void *param) ++{ ++ struct implicit_mta_marshal_data *data = param; ++ HRESULT hr; ++ ++ hr = CoMarshalInterface(data->stream, &IID_IClassFactory, ++ (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); ++ ok_ole_success(hr, CoMarshalInterface); ++ ++ SetEvent(data->start); ++ ++ ok(!WaitForSingleObject(data->stop, 1000), "wait failed\n"); ++ return 0; ++} ++ + static void test_implicit_mta(void) + { ++ struct implicit_mta_marshal_data data; + HANDLE host_thread, thread; + IClassFactory *cf; ++ IUnknown *proxy; + IStream *stream; + HRESULT hr; + DWORD tid; +@@ -3529,6 +3553,32 @@ static void test_implicit_mta(void) + + end_host_object(tid, host_thread); + ++ /* Thirdly: we can marshal an object from the implicit MTA and then ++ * unmarshal it into the real one. */ ++ data.start = CreateEventA(NULL, FALSE, FALSE, NULL); ++ data.stop = CreateEventA(NULL, FALSE, FALSE, NULL); ++ ++ hr = CreateStreamOnHGlobal(NULL, TRUE, &data.stream); ++ ok_ole_success(hr, CreateStreamOnHGlobal); ++ ++ thread = CreateThread(NULL, 0, implicit_mta_marshal_proc, &data, 0, NULL); ++ ok(!WaitForSingleObject(data.start, 1000), "wait failed\n"); ++ ++ IStream_Seek(data.stream, ullZero, STREAM_SEEK_SET, NULL); ++ hr = CoUnmarshalInterface(data.stream, &IID_IClassFactory, (void **)&cf); ++ ok_ole_success(hr, CoUnmarshalInterface); ++ ++ hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); ++ ok_ole_success(hr, IClassFactory_CreateInstance); ++ ++ IUnknown_Release(proxy); ++ ++ SetEvent(data.stop); ++ ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); ++ CloseHandle(thread); ++ ++ IStream_Release(data.stream); ++ + CoUninitialize(); + } + +-- +2.7.4 + diff --git a/patches/ole32-Implicit_MTA/definition b/patches/ole32-Implicit_MTA/definition new file mode 100644 index 00000000..6fd1e37f --- /dev/null +++ b/patches/ole32-Implicit_MTA/definition @@ -0,0 +1,2 @@ +# This patchset doesn't fix any known bugs. It's indirectly for bug 18070. +# It might be useful, however. \ No newline at end of file diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index e6c807a1..258f99cb 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -269,6 +269,7 @@ patch_enable_all () enable_nvcuvid_CUDA_Video_Support="$1" enable_nvencodeapi_Video_Encoder="$1" enable_ole32_HGLOBALStream="$1" + enable_ole32_Implicit_MTA="$1" enable_ole32_STGPROP="$1" enable_oleaut32_CreateTypeLib="$1" enable_oleaut32_DispCallFunc="$1" @@ -1004,6 +1005,9 @@ patch_enable () ole32-HGLOBALStream) enable_ole32_HGLOBALStream="$2" ;; + ole32-Implicit_MTA) + enable_ole32_Implicit_MTA="$2" + ;; ole32-STGPROP) enable_ole32_STGPROP="$2" ;; @@ -5944,6 +5948,31 @@ if test "$enable_ole32_HGLOBALStream" -eq 1; then ) >> "$patchlist" fi +# Patchset ole32-Implicit_MTA +# | +# | Modified files: +# | * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, dlls/ole32/marshal.c, dlls/ole32/rpc.c, dlls/ole32/stubmanager.c, +# | dlls/ole32/tests/compobj.c, dlls/ole32/tests/marshal.c +# | +if test "$enable_ole32_Implicit_MTA" -eq 1; then + patch_apply ole32-Implicit_MTA/0001-ole32-Always-grab-a-reference-to-apt-in-CoGetClassOb.patch + patch_apply ole32-Implicit_MTA/0002-ole32-Add-a-helper-for-grabbing-the-current-apartmen.patch + patch_apply ole32-Implicit_MTA/0003-ole32-Allow-more-functions-to-use-the-implicit-MTA.patch + patch_apply ole32-Implicit_MTA/0004-ole32-Report-the-implicit-MTA-in-CoGetApartmentType.patch + patch_apply ole32-Implicit_MTA/0005-ole32-tests-Test-CoWaitForMultipleHandles-in-an-unin.patch + patch_apply ole32-Implicit_MTA/0006-ole32-Allow-unmarshalling-objects-into-an-implicit-M.patch + patch_apply ole32-Implicit_MTA/0007-ole32-Allow-marshalling-objects-from-an-implicit-MTA.patch + ( + printf '%s\n' '+ { "Zebediah Figura", "ole32: Always grab a reference to apt in CoGetClassObject().", 1 },'; + printf '%s\n' '+ { "Zebediah Figura", "ole32: Add a helper for grabbing the current apartment or MTA.", 1 },'; + printf '%s\n' '+ { "Zebediah Figura", "ole32: Allow more functions to use the implicit MTA.", 1 },'; + printf '%s\n' '+ { "Zebediah Figura", "ole32: Report the implicit MTA in CoGetApartmentType().", 1 },'; + printf '%s\n' '+ { "Zebediah Figura", "ole32/tests: Test CoWaitForMultipleHandles() in an uninitialized or MTA apartment.", 1 },'; + printf '%s\n' '+ { "Zebediah Figura", "ole32: Allow unmarshalling objects into an implicit MTA.", 1 },'; + printf '%s\n' '+ { "Zebediah Figura", "ole32: Allow marshalling objects from an implicit MTA.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ole32-STGPROP # | # | This patchset fixes the following Wine bugs: