[PATCH] ole32: Correctly track the number of inits when auto-joining the MTA.

Huw Davies huw at codeweavers.com
Fri Nov 10 06:56:05 CST 2017


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/ole32/compobj.c         | 70 +++++++++++++++++++++++---------------------
 dlls/ole32/compobj_private.h |  4 +--
 dlls/ole32/rpc.c             |  9 +++---
 dlls/ole32/tests/marshal.c   |  8 ++++-
 4 files changed, 51 insertions(+), 40 deletions(-)

diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 6fb07bf2ba..d136ee623a 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -1724,12 +1724,6 @@ HWND apartment_getwindow(const struct apartment *apt)
     return apt->win;
 }
 
-void apartment_joinmta(void)
-{
-    apartment_addref(MTA);
-    COM_CurrentInfo()->apt = MTA;
-}
-
 static void COM_TlsDestroy(void)
 {
     struct oletls *info = NtCurrentTeb()->ReservedForOle;
@@ -1834,6 +1828,40 @@ HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie)
     return S_OK;
 }
 
+HRESULT enter_apartment( struct oletls *info, DWORD model )
+{
+    HRESULT hr = S_OK;
+
+    if (!info->apt)
+    {
+        if (!apartment_get_or_create( model ))
+            return E_OUTOFMEMORY;
+    }
+    else if (!apartment_is_model( info->apt, model ))
+    {
+        WARN( "Attempt to change threading model of this apartment from %s to %s\n",
+              info->apt->multi_threaded ? "multi-threaded" : "apartment threaded",
+              model & COINIT_APARTMENTTHREADED ? "apartment threaded" : "multi-threaded" );
+        return RPC_E_CHANGED_MODE;
+    }
+    else
+        hr = S_FALSE;
+
+    info->inits++;
+
+    return hr;
+}
+
+void leave_apartment( struct oletls *info )
+{
+    if (!--info->inits)
+    {
+        if (info->ole_inits)
+            WARN( "Uninitializing apartment while Ole is still initialized\n" );
+        apartment_release( info->apt );
+        info->apt = NULL;
+    }
+}
 
 /******************************************************************************
  *		CoInitialize	[OLE32.@]
@@ -1892,8 +1920,7 @@ HRESULT WINAPI CoInitialize(LPVOID lpReserved)
 HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
 {
   struct oletls *info = COM_CurrentInfo();
-  HRESULT hr = S_OK;
-  APARTMENT *apt;
+  HRESULT hr;
 
   TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit);
 
@@ -1922,24 +1949,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoIni
   if (info->spy)
       IInitializeSpy_PreInitialize(info->spy, dwCoInit, info->inits);
 
-  if (!(apt = info->apt))
-  {
-    apt = apartment_get_or_create(dwCoInit);
-    if (!apt) return E_OUTOFMEMORY;
-  }
-  else if (!apartment_is_model(apt, dwCoInit))
-  {
-    /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine
-       code then we are probably using the wrong threading model to implement that API. */
-    ERR("Attempt to change threading model of this apartment from %s to %s\n",
-        apt->multi_threaded ? "multi-threaded" : "apartment threaded",
-        dwCoInit & COINIT_APARTMENTTHREADED ? "apartment threaded" : "multi-threaded");
-    return RPC_E_CHANGED_MODE;
-  }
-  else
-    hr = S_FALSE;
-
-  info->inits++;
+  hr = enter_apartment( info, dwCoInit );
 
   if (info->spy)
       IInitializeSpy_PostInitialize(info->spy, hr, dwCoInit, info->inits);
@@ -1986,13 +1996,7 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
     return;
   }
 
-  if (!--info->inits)
-  {
-    if (info->ole_inits)
-      WARN("uninitializing apartment while Ole is still initialized\n");
-    apartment_release(info->apt);
-    info->apt = NULL;
-  }
+  leave_apartment( info );
 
   /*
    * Decrease the reference count.
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index fd88ed981b..0f10a7c0c4 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -244,8 +244,8 @@ static inline HRESULT apartment_getoxid(const struct apartment *apt, OXID *oxid)
 }
 HRESULT apartment_createwindowifneeded(struct apartment *apt) DECLSPEC_HIDDEN;
 HWND apartment_getwindow(const struct apartment *apt) DECLSPEC_HIDDEN;
-void apartment_joinmta(void) DECLSPEC_HIDDEN;
-
+HRESULT enter_apartment(struct oletls *info, DWORD model) DECLSPEC_HIDDEN;
+void leave_apartment(struct oletls *info) 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/rpc.c b/dlls/ole32/rpc.c
index ec5dc598b7..8d8276e0cb 100644
--- a/dlls/ole32/rpc.c
+++ b/dlls/ole32/rpc.c
@@ -1495,16 +1495,17 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
     else
     {
         BOOL joined = FALSE;
-        if (!COM_CurrentInfo()->apt)
+        struct oletls *info = COM_CurrentInfo();
+
+        if (!info->apt)
         {
-            apartment_joinmta();
+            enter_apartment(info, COINIT_MULTITHREADED);
             joined = TRUE;
         }
         RPC_ExecuteCall(params);
         if (joined)
         {
-            apartment_release(COM_CurrentInfo()->apt);
-            COM_CurrentInfo()->apt = NULL;
+            leave_apartment(info);
         }
     }
 
diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c
index e43439c5a6..12c46e92df 100644
--- a/dlls/ole32/tests/marshal.c
+++ b/dlls/ole32/tests/marshal.c
@@ -2968,6 +2968,12 @@ static HRESULT WINAPI local_server_GetClassID(IPersist *iface, CLSID *clsid)
     hr = CoDisconnectObject((IUnknown *)iface, 0);
     ok(hr == S_OK, "got %08x\n", hr);
 
+    /* Initialize and uninitialize the apartment to show that we
+     * remain in the autojoined mta */
+    hr = pCoInitializeEx( NULL, COINIT_MULTITHREADED );
+    ok( hr == S_FALSE, "got %08x\n", hr );
+    CoUninitialize();
+
     return S_OK;
 }
 
@@ -3749,7 +3755,7 @@ START_TEST(marshal)
     argc = winetest_get_mainargs( &argv );
     if (argc > 2 && (!strcmp(argv[2], "-Embedding")))
     {
-        pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+        pCoInitializeEx(NULL, COINIT_MULTITHREADED);
         test_register_local_server();
         CoUninitialize();
 
-- 
2.12.0




More information about the wine-patches mailing list