[PATCH 2/2] ole32: Fix refcounting of IObjContext per-thread instance
Nikolay Sivov
nsivov at codeweavers.com
Mon Mar 14 00:10:00 CDT 2016
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/ole32/compobj.c | 57 +++++++++++++++++++---------------------------
dlls/ole32/tests/compobj.c | 46 ++++++++++++++++++++++---------------
2 files changed, 51 insertions(+), 52 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index b095aeb..1081f98 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -4683,10 +4683,13 @@ static ULONG Context_AddRef(Context *This)
static ULONG Context_Release(Context *This)
{
- ULONG refs = InterlockedDecrement(&This->refs);
- if (!refs)
+ if (!This->refs)
+ {
HeapFree(GetProcessHeap(), 0, This);
- return refs;
+ return 0;
+ }
+
+ return InterlockedDecrement(&This->refs);
}
static HRESULT WINAPI Context_CTI_QueryInterface(IComThreadingInfo *iface, REFIID riid, LPVOID *ppv)
@@ -4924,39 +4927,19 @@ static const IObjContextVtbl Context_Object_Vtbl =
*/
HRESULT WINAPI CoGetObjectContext(REFIID riid, void **ppv)
{
- APARTMENT *apt = COM_CurrentApt();
- Context *context;
+ IObjContext *context;
HRESULT hr;
TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
*ppv = NULL;
- if (!apt)
- {
- if (!(apt = apartment_find_multi_threaded()))
- {
- ERR("apartment not initialised\n");
- return CO_E_NOTINITIALIZED;
- }
- apartment_release(apt);
- }
-
- context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context));
- if (!context)
- return E_OUTOFMEMORY;
-
- context->IComThreadingInfo_iface.lpVtbl = &Context_Threading_Vtbl;
- context->IContextCallback_iface.lpVtbl = &Context_Callback_Vtbl;
- context->IObjContext_iface.lpVtbl = &Context_Object_Vtbl;
- context->refs = 1;
-
- hr = IComThreadingInfo_QueryInterface(&context->IComThreadingInfo_iface, riid, ppv);
- IComThreadingInfo_Release(&context->IComThreadingInfo_iface);
+ hr = CoGetContextToken((ULONG_PTR*)&context);
+ if (FAILED(hr))
+ return hr;
- return hr;
+ return IObjContext_QueryInterface(context, riid, ppv);
}
-
/***********************************************************************
* CoGetContextToken [OLE32.@]
*/
@@ -4985,16 +4968,22 @@ HRESULT WINAPI CoGetContextToken( ULONG_PTR *token )
if (!info->context_token)
{
- HRESULT hr;
- IObjContext *ctx;
+ Context *context;
+
+ context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context));
+ if (!context)
+ return E_OUTOFMEMORY;
+
+ context->IComThreadingInfo_iface.lpVtbl = &Context_Threading_Vtbl;
+ context->IContextCallback_iface.lpVtbl = &Context_Callback_Vtbl;
+ context->IObjContext_iface.lpVtbl = &Context_Object_Vtbl;
+ context->refs = 0;
- hr = CoGetObjectContext(&IID_IObjContext, (void **)&ctx);
- if (FAILED(hr)) return hr;
- info->context_token = ctx;
+ info->context_token = &context->IObjContext_iface;
}
*token = (ULONG_PTR)info->context_token;
- TRACE("apt->context_token=%p\n", info->context_token);
+ TRACE("context_token=%p\n", info->context_token);
return S_OK;
}
diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c
index d684e33..1af24b6 100644
--- a/dlls/ole32/tests/compobj.c
+++ b/dlls/ole32/tests/compobj.c
@@ -1774,7 +1774,7 @@ static void test_CoGetObjectContext(void)
{
HRESULT hr;
ULONG refs;
- IComThreadingInfo *pComThreadingInfo;
+ IComThreadingInfo *pComThreadingInfo, *threadinginfo2;
IContextCallback *pContextCallback;
IObjContext *pObjContext;
APTTYPE apttype;
@@ -1786,7 +1786,7 @@ static void test_CoGetObjectContext(void)
if (!pCoGetObjectContext)
{
- skip("CoGetObjectContext not present\n");
+ win_skip("CoGetObjectContext not present\n");
return;
}
@@ -1812,6 +1812,12 @@ static void test_CoGetObjectContext(void)
hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
+ threadinginfo2 = NULL;
+ hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&threadinginfo2);
+ ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
+ ok(pComThreadingInfo == threadinginfo2, "got different instance\n");
+ IComThreadingInfo_Release(threadinginfo2);
+
hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, NULL);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
@@ -1854,11 +1860,8 @@ static void test_CoGetObjectContext(void)
hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
- if (hr == S_OK)
- {
- refs = IContextCallback_Release(pContextCallback);
- ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
- }
+ refs = IContextCallback_Release(pContextCallback);
+ ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
CoUninitialize();
@@ -1881,11 +1884,8 @@ static void test_CoGetObjectContext(void)
hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
- if (hr == S_OK)
- {
- refs = IContextCallback_Release(pContextCallback);
- ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
- }
+ refs = IContextCallback_Release(pContextCallback);
+ ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
ok_ole_success(hr, "CoGetObjectContext");
@@ -2007,7 +2007,7 @@ static void test_CoGetContextToken(void)
{
HRESULT hr;
ULONG refs;
- ULONG_PTR token;
+ ULONG_PTR token, token2;
IObjContext *ctx;
struct info info;
HANDLE thread;
@@ -2042,6 +2042,11 @@ static void test_CoGetContextToken(void)
hr = pCoGetContextToken(&token);
ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
+ token2 = 0;
+ hr = pCoGetContextToken(&token2);
+ ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
+ ok(token == token2, "got different token\n");
+
SetEvent(info.stop);
ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
@@ -2063,18 +2068,23 @@ static void test_CoGetContextToken(void)
ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
ok(token, "Expected token != 0\n");
+ token2 = 0;
+ hr = pCoGetContextToken(&token2);
+ ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
+ ok(token2 == token, "got different token\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);
hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
- todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
+ ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
refs = IObjContext_AddRef(ctx);
- todo_wine ok(refs == 3, "Expected 3, got %u\n", refs);
+ ok(refs == 3, "Expected 3, got %u\n", refs);
refs = IObjContext_Release(ctx);
- todo_wine ok(refs == 2, "Expected 2, got %u\n", refs);
+ ok(refs == 2, "Expected 2, got %u\n", refs);
refs = IUnknown_Release((IUnknown *)token);
ok(refs == 1, "Expected 1, got %u\n", refs);
@@ -2084,7 +2094,7 @@ static void test_CoGetContextToken(void)
hr = pCoGetContextToken(&token);
ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
ok(token, "Expected token != 0\n");
- todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
+ ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
refs = IObjContext_AddRef(ctx);
ok(refs == 2, "Expected 1, got %u\n", refs);
--
2.7.0
More information about the wine-patches
mailing list