From 1b67da35662944a3eb9e3fbf9e3de7b7dad3a22b Mon Sep 17 00:00:00 2001 From: Detlef Riekenberg Date: Mon, 19 Apr 2010 23:26:49 +0200 Subject: [PATCH] shlwapi/tests: Add tests for SHCreateThreadRef. --- dlls/shlwapi/tests/thread.c | 105 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 6 deletions(-) diff --git a/dlls/shlwapi/tests/thread.c b/dlls/shlwapi/tests/thread.c index cb880360168..24d5be15802 100644 --- a/dlls/shlwapi/tests/thread.c +++ b/dlls/shlwapi/tests/thread.c @@ -29,6 +29,7 @@ #include "wine/test.h" +static HRESULT (WINAPI *pSHCreateThreadRef)(LONG*, IUnknown**); static HRESULT (WINAPI *pSHGetThreadRef)(IUnknown**); static HRESULT (WINAPI *pSHSetThreadRef)(IUnknown*); @@ -36,31 +37,37 @@ static DWORD AddRef_called; typedef struct { - void* lpVtbl; + const IUnknownVtbl* lpVtbl; LONG *ref; } threadref; -static HRESULT WINAPI threadref_QueryInterface(threadref *This, REFIID riid, LPVOID *ppvObj) +static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj) { + threadref * This = (threadref *)iface; + trace("unexpected QueryInterface(%p, %p, %p) called\n", This, riid, ppvObj); *ppvObj = NULL; return E_NOINTERFACE; } -static ULONG WINAPI threadref_AddRef(threadref *This) +static ULONG WINAPI threadref_AddRef(IUnknown *iface) { + threadref * This = (threadref *)iface; + AddRef_called++; return InterlockedIncrement(This->ref); } -static ULONG WINAPI threadref_Release(threadref *This) +static ULONG WINAPI threadref_Release(IUnknown *iface) { + threadref * This = (threadref *)iface; + trace("unexpected Release(%p) called\n", This); return InterlockedDecrement(This->ref); } /* VTable */ -static void* threadref_vt[] = +static const IUnknownVtbl threadref_vt = { threadref_QueryInterface, threadref_AddRef, @@ -69,12 +76,96 @@ static void* threadref_vt[] = static void init_threadref(threadref* iface, LONG *refcount) { - iface->lpVtbl = (void*)threadref_vt; + iface->lpVtbl = &threadref_vt; iface->ref = refcount; } /* ##### */ +static void test_SHCreateThreadRef(void) +{ + IUnknown *pobj; + IUnknown *punk; + LONG refcount; + HRESULT hr; + + /* Not present before IE 6_XP_sp2 */ + if (!pSHCreateThreadRef) { + win_skip("SHCreateThreadRef not found\n"); + return; + } + + /* start with a clean state */ + hr = pSHSetThreadRef(NULL); + ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr); + + pobj = NULL; + refcount = 0xdeadbeef; + hr = pSHCreateThreadRef(&refcount, &pobj); + ok((hr == S_OK) && pobj && (refcount == 1), + "got 0x%x and %p with %d (expected S_OK and '!= NULL' with 1)\n", + hr, pobj, refcount); + + /* the object is not automatic set as ThreadRef */ + punk = NULL; + hr = pSHGetThreadRef(&punk); + ok( (hr == E_NOINTERFACE) && (punk == NULL), + "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk); + + /* set the object */ + hr = pSHSetThreadRef(pobj); + ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr); + + /* read back */ + punk = NULL; + hr = pSHGetThreadRef(&punk); + ok( (hr == S_OK) && (punk == pobj) && (refcount == 2), + "got 0x%x and %p with %d (expected S_OK and %p with 2)\n", + hr, punk, refcount, pobj); + + /* free the ref from SHGetThreadRef */ + if (SUCCEEDED(hr)) { + hr = IUnknown_Release(pobj); + ok((hr == 1) && (hr == refcount), + "got %d with %d (expected 1 with 1)\n", hr, refcount); + } + + /* free the object */ + if (pobj) { + hr = IUnknown_Release(pobj); + ok((hr == 0) && (hr == refcount), + "got %d with %d (expected 0 with 0)\n", hr, refcount); + } + + if (0) { + /* the ThreadRef has still the pointer, + but the object no longer exist after the *_Release */ + punk = NULL; + hr = pSHGetThreadRef(&punk); + trace("got 0x%x and %p with %d\n", hr, punk, refcount); + } + + /* remove the dead object pointer */ + hr = pSHSetThreadRef(NULL); + ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr); + + /* parameter check */ + if (0) { + /* vista: E_INVALIDARG, XP: crash */ + pobj = NULL; + hr = pSHCreateThreadRef(NULL, &pobj); + ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr); + + refcount = 0xdeadbeef; + /* vista: E_INVALIDARG, XP: crash */ + hr = pSHCreateThreadRef(&refcount, NULL); + ok( (hr == E_INVALIDARG) && (refcount == 0xdeadbeef), + "got 0x%x with 0x%x (expected E_INVALIDARG and oxdeadbeef)\n", + hr, refcount); + } +} + + static void test_SHGetThreadRef(void) { IUnknown *punk; @@ -147,9 +238,11 @@ START_TEST(thread) { HMODULE hshlwapi = GetModuleHandleA("shlwapi.dll"); + pSHCreateThreadRef = (void *) GetProcAddress(hshlwapi, "SHCreateThreadRef"); pSHGetThreadRef = (void *) GetProcAddress(hshlwapi, "SHGetThreadRef"); pSHSetThreadRef = (void *) GetProcAddress(hshlwapi, "SHSetThreadRef"); + test_SHCreateThreadRef(); test_SHGetThreadRef(); test_SHSetThreadRef(); -- 2.11.4.GIT