Paul Gofman : ole32: Fix behaviour of OLE init/uninit.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jan 15 10:48:55 CST 2016


Module: wine
Branch: master
Commit: b4b0c138fe6e5058270f4de7e2a9144a431335ce
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b4b0c138fe6e5058270f4de7e2a9144a431335ce

Author: Paul Gofman <gofmanp at gmail.com>
Date:   Fri Jan 15 13:29:31 2016 +0300

ole32: Fix behaviour of OLE init/uninit.

Signed-off-by: Paul Gofman <gofmanp at gmail.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ole32/compobj.c       |  2 ++
 dlls/ole32/ole2.c          |  7 +++++
 dlls/ole32/tests/compobj.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 90b049a..080940e 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -1972,6 +1972,8 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
 
   if (!--info->inits)
   {
+    if (info->ole_inits)
+      WARN("uninitializing apartment while Ole is still initialized\n");
     apartment_release(info->apt);
     info->apt = NULL;
   }
diff --git a/dlls/ole32/ole2.c b/dlls/ole32/ole2.c
index 7929d3d..f078fb6 100644
--- a/dlls/ole32/ole2.c
+++ b/dlls/ole32/ole2.c
@@ -186,6 +186,8 @@ HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
 
   if (!COM_CurrentInfo()->ole_inits)
     hr = S_OK;
+  else
+    hr = S_FALSE;
 
   /*
    * Then, it has to initialize the OLE specific modules.
@@ -229,6 +231,11 @@ void WINAPI DECLSPEC_HOTPATCH OleUninitialize(void)
 {
   TRACE("()\n");
 
+  if (COM_CurrentInfo()->ole_inits == 0)
+  {
+    WARN("ole_inits is already 0\n");
+    return ;
+  }
   /*
    * If we hit the bottom of the lock stack, free the libraries.
    */
diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c
index 5fe9876..6fa6dfc 100644
--- a/dlls/ole32/tests/compobj.c
+++ b/dlls/ole32/tests/compobj.c
@@ -2181,6 +2181,73 @@ static void test_CoInitializeEx(void)
     OleUninitialize();
 }
 
+static void test_OleInitialize_InitCounting(void)
+{
+    HRESULT hr;
+    IUnknown *pUnk;
+    REFCLSID rclsid = &CLSID_InternetZoneManager;
+
+    /* 1. OleInitialize fails but OleUnintialize is still called: apartment stays inited */
+    hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
+    ok(hr == S_OK, "CoInitializeEx(COINIT_MULTITHREADED) failed with error 0x%08x\n", hr);
+
+    hr = OleInitialize(NULL);
+    ok(hr == RPC_E_CHANGED_MODE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", RPC_E_CHANGED_MODE, hr);
+    OleUninitialize();
+
+    pUnk = (IUnknown *)0xdeadbeef;
+    hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
+    ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
+    if (pUnk) IUnknown_Release(pUnk);
+
+    CoUninitialize();
+
+    /* 2. Extra multiple OleUninitialize: apartment stays inited until CoUnitialize */
+    hr = CoInitialize(NULL);
+    ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
+
+    hr = OleInitialize(NULL);
+    ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
+    OleUninitialize();
+    OleUninitialize();
+    OleUninitialize();
+
+    pUnk = (IUnknown *)0xdeadbeef;
+    hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
+    ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
+    if (pUnk) IUnknown_Release(pUnk);
+
+    CoUninitialize();
+
+    pUnk = (IUnknown *)0xdeadbeef;
+    hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
+    ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
+    if (pUnk) IUnknown_Release(pUnk);
+
+    /* 3. CoUninitialize does not formally deinit Ole */
+    hr = CoInitialize(NULL);
+    ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
+
+    hr = OleInitialize(NULL);
+    ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
+
+    CoUninitialize();
+    CoUninitialize();
+
+    pUnk = (IUnknown *)0xdeadbeef;
+    hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
+    ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
+      /* COM is not initialized anymore */
+    if (pUnk) IUnknown_Release(pUnk);
+
+    hr = OleInitialize(NULL);
+    ok(hr == S_FALSE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_FALSE, hr);
+      /* ... but native OleInit returns S_FALSE as if Ole is considered initialized */
+
+    OleUninitialize();
+
+}
+
 static void test_OleRegGetMiscStatus(void)
 {
     ULONG_PTR cookie;
@@ -2871,6 +2938,7 @@ START_TEST(compobj)
     test_CoGetContextToken();
     test_TreatAsClass();
     test_CoInitializeEx();
+    test_OleInitialize_InitCounting();
     test_OleRegGetMiscStatus();
     test_CoCreateGuid();
     test_CoWaitForMultipleHandles();




More information about the wine-cvs mailing list