Hans Leidekker : ole32: Use existing MTA in CoGetContextToken and CoGetObjectContext.

Alexandre Julliard julliard at winehq.org
Fri Jul 3 09:31:10 CDT 2009


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri Jul  3 11:32:08 2009 +0200

ole32: Use existing MTA in CoGetContextToken and CoGetObjectContext.

---

 dlls/ole32/compobj.c       |   18 +++++++++--
 dlls/ole32/tests/compobj.c |   70 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 739c86d..7403b95 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -4050,8 +4050,12 @@ HRESULT WINAPI CoGetObjectContext(REFIID riid, void **ppv)
     *ppv = NULL;
     if (!apt)
     {
-        ERR("apartment not initialised\n");
-        return CO_E_NOTINITIALIZED;
+        if (!(apt = apartment_find_multi_threaded()))
+        {
+            ERR("apartment not initialised\n");
+            return CO_E_NOTINITIALIZED;
+        }
+        apartment_release(apt);
     }
 
     context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context));
@@ -4089,7 +4093,15 @@ HRESULT WINAPI CoGetContextToken( ULONG_PTR *token )
         return E_OUTOFMEMORY;
 
     if (!info->apt)
-        return CO_E_NOTINITIALIZED;
+    {
+        APARTMENT *apt;
+        if (!(apt = apartment_find_multi_threaded()))
+        {
+            ERR("apartment not initialised\n");
+            return CO_E_NOTINITIALIZED;
+        }
+        apartment_release(apt);
+    }
 
     if (!token)
         return E_POINTER;
diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c
index ff2462f..1435984 100644
--- a/dlls/ole32/tests/compobj.c
+++ b/dlls/ole32/tests/compobj.c
@@ -1082,6 +1082,9 @@ static void test_CoGetObjectContext(void)
     IObjContext *pObjContext;
     APTTYPE apttype;
     THDTYPE thdtype;
+    struct info info;
+    HANDLE thread;
+    DWORD tid, exitcode;
 
     if (!pCoGetObjectContext)
     {
@@ -1093,6 +1096,36 @@ static void test_CoGetObjectContext(void)
     ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
     ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
 
+    /* show that COM doesn't have to be initialized for multi-threaded apartments if another
+       thread has already done so */
+
+    info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
+
+    info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
+
+    thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
+    ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
+
+    WaitForSingleObject(info.wait, INFINITE);
+
+    pComThreadingInfo = NULL;
+    hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
+    ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
+    IComThreadingInfo_Release(pComThreadingInfo);
+
+    SetEvent(info.stop);
+    WaitForSingleObject(thread, INFINITE);
+
+    GetExitCodeThread(thread, &exitcode);
+    hr = exitcode;
+    ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
+
+    CloseHandle(thread);
+    CloseHandle(info.wait);
+    CloseHandle(info.stop);
+
     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 
     hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
@@ -1260,6 +1293,9 @@ static void test_CoGetContextToken(void)
     ULONG refs;
     ULONG_PTR token;
     IObjContext *ctx;
+    struct info info;
+    HANDLE thread;
+    DWORD tid, exitcode;
 
     if (!pCoGetContextToken)
     {
@@ -1272,6 +1308,36 @@ 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);
 
+    /* show that COM doesn't have to be initialized for multi-threaded apartments if another
+       thread has already done so */
+
+    info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
+
+    info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
+
+    thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
+    ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
+
+    WaitForSingleObject(info.wait, INFINITE);
+
+    token = 0;
+    hr = pCoGetContextToken(&token);
+    ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
+    IUnknown_Release((IUnknown *)token);
+
+    SetEvent(info.stop);
+    WaitForSingleObject(thread, INFINITE);
+
+    GetExitCodeThread(thread, &exitcode);
+    hr = exitcode;
+    ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
+
+    CloseHandle(thread);
+    CloseHandle(info.wait);
+    CloseHandle(info.stop);
+
     CoInitialize(NULL);
 
     hr = pCoGetContextToken(NULL);
@@ -1283,10 +1349,10 @@ static void test_CoGetContextToken(void)
     ok(token, "Expected token != 0\n");
 
     refs = IUnknown_AddRef((IUnknown *)token);
-    todo_wine ok(refs == 1, "Expected 1, got %u\n", refs);
+    ok(refs == 1, "Expected 1, got %u\n", refs);
 
     refs = IUnknown_Release((IUnknown *)token);
-    todo_wine ok(refs == 0, "Expected 0, got %u\n", refs);
+    ok(refs == 0, "Expected 0, got %u\n", refs);
 
     hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);




More information about the wine-cvs mailing list