shlwapi/tests: Add tests for SHCreateThreadRef.
This commit is contained in:
parent
bb1ca6e08d
commit
1b67da3566
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue