Module: wine Branch: master Commit: b4b0c138fe6e5058270f4de7e2a9144a431335ce URL: http://source.winehq.org/git/wine.git/?a=commit;h=b4b0c138fe6e5058270f4de7e2...
Author: Paul Gofman gofmanp@gmail.com Date: Fri Jan 15 13:29:31 2016 +0300
ole32: Fix behaviour of OLE init/uninit.
Signed-off-by: Paul Gofman gofmanp@gmail.com Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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();