Commit 1b67da35 authored by Detlef Riekenberg's avatar Detlef Riekenberg Committed by Alexandre Julliard

shlwapi/tests: Add tests for SHCreateThreadRef.

parent bb1ca6e0
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "wine/test.h" #include "wine/test.h"
static HRESULT (WINAPI *pSHCreateThreadRef)(LONG*, IUnknown**);
static HRESULT (WINAPI *pSHGetThreadRef)(IUnknown**); static HRESULT (WINAPI *pSHGetThreadRef)(IUnknown**);
static HRESULT (WINAPI *pSHSetThreadRef)(IUnknown*); static HRESULT (WINAPI *pSHSetThreadRef)(IUnknown*);
...@@ -36,31 +37,37 @@ static DWORD AddRef_called; ...@@ -36,31 +37,37 @@ static DWORD AddRef_called;
typedef struct typedef struct
{ {
void* lpVtbl; const IUnknownVtbl* lpVtbl;
LONG *ref; LONG *ref;
} threadref; } 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); trace("unexpected QueryInterface(%p, %p, %p) called\n", This, riid, ppvObj);
*ppvObj = NULL; *ppvObj = NULL;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
static ULONG WINAPI threadref_AddRef(threadref *This) static ULONG WINAPI threadref_AddRef(IUnknown *iface)
{ {
threadref * This = (threadref *)iface;
AddRef_called++; AddRef_called++;
return InterlockedIncrement(This->ref); 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); trace("unexpected Release(%p) called\n", This);
return InterlockedDecrement(This->ref); return InterlockedDecrement(This->ref);
} }
/* VTable */ /* VTable */
static void* threadref_vt[] = static const IUnknownVtbl threadref_vt =
{ {
threadref_QueryInterface, threadref_QueryInterface,
threadref_AddRef, threadref_AddRef,
...@@ -69,12 +76,96 @@ static void* threadref_vt[] = ...@@ -69,12 +76,96 @@ static void* threadref_vt[] =
static void init_threadref(threadref* iface, LONG *refcount) static void init_threadref(threadref* iface, LONG *refcount)
{ {
iface->lpVtbl = (void*)threadref_vt; iface->lpVtbl = &threadref_vt;
iface->ref = refcount; 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) static void test_SHGetThreadRef(void)
{ {
IUnknown *punk; IUnknown *punk;
...@@ -147,9 +238,11 @@ START_TEST(thread) ...@@ -147,9 +238,11 @@ START_TEST(thread)
{ {
HMODULE hshlwapi = GetModuleHandleA("shlwapi.dll"); HMODULE hshlwapi = GetModuleHandleA("shlwapi.dll");
pSHCreateThreadRef = (void *) GetProcAddress(hshlwapi, "SHCreateThreadRef");
pSHGetThreadRef = (void *) GetProcAddress(hshlwapi, "SHGetThreadRef"); pSHGetThreadRef = (void *) GetProcAddress(hshlwapi, "SHGetThreadRef");
pSHSetThreadRef = (void *) GetProcAddress(hshlwapi, "SHSetThreadRef"); pSHSetThreadRef = (void *) GetProcAddress(hshlwapi, "SHSetThreadRef");
test_SHCreateThreadRef();
test_SHGetThreadRef(); test_SHGetThreadRef();
test_SHSetThreadRef(); test_SHSetThreadRef();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment