From b46eafe3d29889a30904b5dfaa5c4ef35155766d Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 12 Sep 2023 12:53:27 -0600 Subject: [PATCH] combase: Ensure MTA existence in RoGetActivationFactory(). --- dlls/combase/apartment.c | 31 +++++++++++++++++++++++++++++++ dlls/combase/combase.c | 3 +++ dlls/combase/combase_private.h | 2 ++ dlls/combase/roapi.c | 5 +++++ dlls/combase/tests/roapi.c | 12 ++++++------ dlls/ole32/compobj_private.h | 1 + 6 files changed, 48 insertions(+), 6 deletions(-) diff --git a/dlls/combase/apartment.c b/dlls/combase/apartment.c index d679ef3407a..92f1e32c502 100644 --- a/dlls/combase/apartment.c +++ b/dlls/combase/apartment.c @@ -1157,6 +1157,11 @@ void leave_apartment(struct tlsdata *data) if (data->ole_inits) WARN( "Uninitializing apartment while Ole is still initialized\n" ); apartment_release(data->apt); + if (data->implicit_mta_cookie) + { + apartment_decrement_mta_usage(data->implicit_mta_cookie); + data->implicit_mta_cookie = NULL; + } data->apt = NULL; data->flags &= ~(OLETLS_DISABLE_OLE1DDE | OLETLS_APARTMENTTHREADED | OLETLS_MULTITHREADED); } @@ -1288,3 +1293,29 @@ void apartment_global_cleanup(void) apartment_release_dlls(); DeleteCriticalSection(&apt_cs); } + +HRESULT ensure_mta(void) +{ + struct apartment *apt; + struct tlsdata *data; + HRESULT hr; + + if (FAILED(hr = com_get_tlsdata(&data))) + return hr; + if ((apt = data->apt) && (data->implicit_mta_cookie || apt->multi_threaded)) + return S_OK; + + EnterCriticalSection(&apt_cs); + if (apt || mta) + hr = apartment_increment_mta_usage(&data->implicit_mta_cookie); + else + hr = CO_E_NOTINITIALIZED; + LeaveCriticalSection(&apt_cs); + + if (FAILED(hr)) + { + ERR("Failed, hr %#lx.\n", hr); + return hr; + } + return S_OK; +} diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index f1b5828e0f8..e072c169953 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -407,6 +407,9 @@ static void com_cleanup_tlsdata(void) if (tlsdata->apt) apartment_release(tlsdata->apt); + if (tlsdata->implicit_mta_cookie) + apartment_decrement_mta_usage(tlsdata->implicit_mta_cookie); + if (tlsdata->errorinfo) IErrorInfo_Release(tlsdata->errorinfo); if (tlsdata->state) diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index 53932e9a357..04d251962ec 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -92,6 +92,7 @@ struct tlsdata struct list spies; /* Spies installed with CoRegisterInitializeSpy */ DWORD spies_lock; DWORD cancelcount; + CO_MTA_USAGE_COOKIE implicit_mta_cookie; /* mta referenced by roapi from sta thread */ }; extern HRESULT WINAPI InternalTlsAllocData(struct tlsdata **data); @@ -161,6 +162,7 @@ void apartment_release(struct apartment *apt); struct apartment * apartment_get_current_or_mta(void); HRESULT apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie); void apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie); +HRESULT ensure_mta(void); struct apartment * apartment_get_mta(void); HRESULT apartment_get_inproc_class_object(struct apartment *apt, const struct class_reg_data *regdata, REFCLSID rclsid, REFIID riid, DWORD class_context, void **ppv); diff --git a/dlls/combase/roapi.c b/dlls/combase/roapi.c index b80ca2e8325..e1017f1f3fd 100644 --- a/dlls/combase/roapi.c +++ b/dlls/combase/roapi.c @@ -24,6 +24,8 @@ #include "roerrorapi.h" #include "winstring.h" +#include "combase_private.h" + #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(combase); @@ -154,6 +156,9 @@ HRESULT WINAPI RoGetActivationFactory(HSTRING classid, REFIID iid, void **class_ if (!iid || !class_factory) return E_INVALIDARG; + if (FAILED(hr = ensure_mta())) + return hr; + hr = get_library_for_classid(WindowsGetStringRawBuffer(classid, NULL), &library); if (FAILED(hr)) { diff --git a/dlls/combase/tests/roapi.c b/dlls/combase/tests/roapi.c index 4887cb60ef6..abc03176db0 100644 --- a/dlls/combase/tests/roapi.c +++ b/dlls/combase/tests/roapi.c @@ -211,7 +211,7 @@ static void test_implicit_mta(void) ok(hr == S_OK, "got %#lx.\n", hr); /* RoGetActivationFactory doesn't implicitly initialize COM. */ hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); - todo_wine ok(hr == CO_E_NOTINITIALIZED, "got %#lx.\n", hr); + ok(hr == CO_E_NOTINITIALIZED, "got %#lx.\n", hr); check_thread_apartment(CO_E_NOTINITIALIZED); @@ -227,10 +227,10 @@ static void test_implicit_mta(void) check_thread_apartment(tests[i].mta ? S_OK : CO_E_NOTINITIALIZED); hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); ok(hr == REGDB_E_CLASSNOTREG, "got %#lx.\n", hr); - todo_wine_if(!tests[i].mta) check_thread_apartment_broken(S_OK); /* Broken on Win8. */ + check_thread_apartment_broken(S_OK); /* Broken on Win8. */ hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); ok(hr == REGDB_E_CLASSNOTREG, "got %#lx.\n", hr); - todo_wine_if(!tests[i].mta) check_thread_apartment_broken(S_OK); /* Broken on Win8. */ + check_thread_apartment_broken(S_OK); /* Broken on Win8. */ if (tests[i].ro_init) RoUninitialize(); else @@ -270,7 +270,7 @@ static void test_implicit_mta(void) SetEvent(mta_init_thread_done_event); WaitForSingleObject(thread, INFINITE); CloseHandle(thread); - todo_wine check_thread_apartment_broken(S_OK); /* Broken on Win8. */ + check_thread_apartment_broken(S_OK); /* Broken on Win8. */ CoUninitialize(); check_thread_apartment(CO_E_NOTINITIALIZED); @@ -292,7 +292,7 @@ static void test_implicit_mta(void) SetEvent(mta_init_thread_done_event); WaitForSingleObject(thread, INFINITE); CloseHandle(thread); - todo_wine check_thread_apartment_broken(S_OK); /* Broken on Win8. */ + check_thread_apartment_broken(S_OK); /* Broken on Win8. */ CoUninitialize(); check_thread_apartment(CO_E_NOTINITIALIZED); @@ -300,7 +300,7 @@ static void test_implicit_mta(void) thread = CreateThread(NULL, 0, mta_init_implicit_thread, NULL, 0, NULL); ok(!!thread, "failed.\n"); WaitForSingleObject(mta_init_thread_init_done_event, INFINITE); - todo_wine check_thread_apartment_broken(S_OK); /* Broken on Win8. */ + check_thread_apartment_broken(S_OK); /* Broken on Win8. */ SetEvent(mta_init_thread_done_event); WaitForSingleObject(thread, INFINITE); CloseHandle(thread); diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index eae1a5998c0..2daadb617c5 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -63,6 +63,7 @@ struct oletls struct list spies; /* Spies installed with CoRegisterInitializeSpy */ DWORD spies_lock; DWORD cancelcount; + CO_MTA_USAGE_COOKIE implicit_mta_cookie; /* mta referenced by roapi from sta thread */ }; /* Global Interface Table Functions */ -- 2.11.4.GIT