ReactOS 0.4.15-dev-8145-ga541a46
thread.c File Reference
#include <stdio.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "ole2.h"
#include "shlwapi.h"
#include "wine/test.h"
Include dependency graph for thread.c:

Go to the source code of this file.

Classes

struct  threadref
 

Macros

#define COBJMACROS
 
#define CONST_VTABLE
 

Functions

static HRESULT (WINAPI *pSHCreateThreadRef)(LONG *
 
static threadrefimpl_from_IUnknown (IUnknown *iface)
 
static HRESULT WINAPI threadref_QueryInterface (IUnknown *iface, REFIID riid, LPVOID *ppvObj)
 
static ULONG WINAPI threadref_AddRef (IUnknown *iface)
 
static ULONG WINAPI threadref_Release (IUnknown *iface)
 
static void init_threadref (threadref *iface, LONG *refcount)
 
static void test_SHCreateThreadRef (void)
 
static void test_SHGetThreadRef (void)
 
static void test_SHSetThreadRef (void)
 
 START_TEST (thread)
 

Variables

static DWORD AddRef_called
 
static const IUnknownVtbl threadref_vt
 

Macro Definition Documentation

◆ COBJMACROS

#define COBJMACROS

Definition at line 23 of file thread.c.

◆ CONST_VTABLE

#define CONST_VTABLE

Definition at line 24 of file thread.c.

Function Documentation

◆ HRESULT()

static HRESULT ( WINAPI pSHCreateThreadRef)
static

◆ impl_from_IUnknown()

static threadref * impl_from_IUnknown ( IUnknown iface)
inlinestatic

Definition at line 46 of file thread.c.

47{
48 return CONTAINING_RECORD(iface, threadref, IUnknown_iface);
49}
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

◆ init_threadref()

static void init_threadref ( threadref iface,
LONG refcount 
)
static

Definition at line 84 of file thread.c.

85{
86 iface->IUnknown_iface.lpVtbl = &threadref_vt;
87 iface->ref = refcount;
88}
static const IUnknownVtbl threadref_vt
Definition: thread.c:178
LONG * ref
Definition: thread.c:126
IUnknown IUnknown_iface
Definition: thread.c:125

Referenced by test_SHSetThreadRef().

◆ START_TEST()

START_TEST ( thread  )

Definition at line 244 of file thread.c.

245{
246 HMODULE hshlwapi = GetModuleHandleA("shlwapi.dll");
247
248 pSHCreateThreadRef = (void *) GetProcAddress(hshlwapi, "SHCreateThreadRef");
249 pSHGetThreadRef = (void *) GetProcAddress(hshlwapi, "SHGetThreadRef");
250 pSHSetThreadRef = (void *) GetProcAddress(hshlwapi, "SHSetThreadRef");
251
255
256}
#define GetProcAddress(x, y)
Definition: compat.h:753
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
static void test_SHCreateThreadRef(void)
Definition: thread.c:92
static void test_SHSetThreadRef(void)
Definition: thread.c:198
static void test_SHGetThreadRef(void)
Definition: thread.c:176
static HMODULE hshlwapi
Definition: shreg.c:35

◆ test_SHCreateThreadRef()

static void test_SHCreateThreadRef ( void  )
static

Definition at line 92 of file thread.c.

93{
94 IUnknown *pobj;
95 IUnknown *punk;
96 LONG refcount;
97 HRESULT hr;
98
99 /* Not present before IE 6_XP_sp2 */
100 if (!pSHCreateThreadRef) {
101 win_skip("SHCreateThreadRef not found\n");
102 return;
103 }
104
105 /* start with a clean state */
106 hr = pSHSetThreadRef(NULL);
107 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
108
109 pobj = NULL;
110 refcount = 0xdeadbeef;
111 hr = pSHCreateThreadRef(&refcount, &pobj);
112 ok((hr == S_OK) && pobj && (refcount == 1),
113 "got 0x%x and %p with %d (expected S_OK and '!= NULL' with 1)\n",
114 hr, pobj, refcount);
115
116 /* the object is not automatic set as ThreadRef */
117 punk = NULL;
118 hr = pSHGetThreadRef(&punk);
119 ok( (hr == E_NOINTERFACE) && (punk == NULL),
120 "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
121
122 /* set the object */
123 hr = pSHSetThreadRef(pobj);
124 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
125
126 /* read back */
127 punk = NULL;
128 hr = pSHGetThreadRef(&punk);
129 ok( (hr == S_OK) && (punk == pobj) && (refcount == 2),
130 "got 0x%x and %p with %d (expected S_OK and %p with 2)\n",
131 hr, punk, refcount, pobj);
132
133 /* free the ref from SHGetThreadRef */
134 if (SUCCEEDED(hr)) {
135 hr = IUnknown_Release(pobj);
136 ok((hr == 1) && (hr == refcount),
137 "got %d with %d (expected 1 with 1)\n", hr, refcount);
138 }
139
140 /* free the object */
141 if (pobj) {
142 hr = IUnknown_Release(pobj);
143 ok((hr == 0) && (hr == refcount),
144 "got %d with %d (expected 0 with 0)\n", hr, refcount);
145 }
146
147 if (0) {
148 /* the ThreadRef has still the pointer,
149 but the object no longer exist after the *_Release */
150 punk = NULL;
151 hr = pSHGetThreadRef(&punk);
152 trace("got 0x%x and %p with %d\n", hr, punk, refcount);
153 }
154
155 /* remove the dead object pointer */
156 hr = pSHSetThreadRef(NULL);
157 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
158
159 /* parameter check */
160 if (0) {
161 /* vista: E_INVALIDARG, XP: crash */
162 pobj = NULL;
163 hr = pSHCreateThreadRef(NULL, &pobj);
164 ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
165
166 refcount = 0xdeadbeef;
167 /* vista: E_INVALIDARG, XP: crash */
168 hr = pSHCreateThreadRef(&refcount, NULL);
169 ok( (hr == E_INVALIDARG) && (refcount == 0xdeadbeef),
170 "got 0x%x with 0x%x (expected E_INVALIDARG and oxdeadbeef)\n",
171 hr, refcount);
172 }
173}
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define E_INVALIDARG
Definition: ddrawi.h:101
#define NULL
Definition: types.h:112
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
long LONG
Definition: pedump.c:60
#define win_skip
Definition: test.h:163
HRESULT hr
Definition: shlfolder.c:183
#define E_NOINTERFACE
Definition: winerror.h:2364

Referenced by START_TEST().

◆ test_SHGetThreadRef()

static void test_SHGetThreadRef ( void  )
static

Definition at line 176 of file thread.c.

177{
178 IUnknown *punk;
179 HRESULT hr;
180
181 /* Not present before IE 5 */
182 if (!pSHGetThreadRef) {
183 win_skip("SHGetThreadRef not found\n");
184 return;
185 }
186
187 punk = NULL;
188 hr = pSHGetThreadRef(&punk);
189 ok( (hr == E_NOINTERFACE) && (punk == NULL),
190 "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
191
192 if (0) {
193 /* this crash on Windows */
194 pSHGetThreadRef(NULL);
195 }
196}

Referenced by START_TEST().

◆ test_SHSetThreadRef()

static void test_SHSetThreadRef ( void  )
static

Definition at line 198 of file thread.c.

199{
201 IUnknown *punk;
202 HRESULT hr;
203 LONG refcount;
204
205 /* Not present before IE 5 */
206 if (!pSHSetThreadRef) {
207 win_skip("SHSetThreadRef not found\n");
208 return;
209 }
210
211 /* start with a clean state */
212 hr = pSHSetThreadRef(NULL);
213 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
214
215 /* build and set out object */
216 init_threadref(&ref, &refcount);
217 AddRef_called = 0;
218 refcount = 1;
219 hr = pSHSetThreadRef(&ref.IUnknown_iface);
220 ok( (hr == S_OK) && (refcount == 1) && (!AddRef_called),
221 "got 0x%x with %d, %d (expected S_OK with 1, 0)\n",
222 hr, refcount, AddRef_called);
223
224 /* read back our object */
225 AddRef_called = 0;
226 refcount = 1;
227 punk = NULL;
228 hr = pSHGetThreadRef(&punk);
229 ok( (hr == S_OK) && (punk == &ref.IUnknown_iface) && (refcount == 2) && (AddRef_called == 1),
230 "got 0x%x and %p with %d, %d (expected S_OK and %p with 2, 1)\n",
231 hr, punk, refcount, AddRef_called, &ref);
232
233 /* clear the object pointer */
234 hr = pSHSetThreadRef(NULL);
235 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
236
237 /* verify, that our object is no longer known as ThreadRef */
238 hr = pSHGetThreadRef(&punk);
239 ok( (hr == E_NOINTERFACE) && (punk == NULL),
240 "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
241
242}
static void init_threadref(threadref *iface, LONG *refcount)
Definition: thread.c:84
static DWORD AddRef_called
Definition: thread.c:38
Definition: send.c:48

Referenced by START_TEST().

◆ threadref_AddRef()

static ULONG WINAPI threadref_AddRef ( IUnknown iface)
static

Definition at line 60 of file thread.c.

61{
63
65 return InterlockedIncrement(This->ref);
66}
#define InterlockedIncrement
Definition: armddk.h:53
static threadref * impl_from_IUnknown(IUnknown *iface)
Definition: thread.c:129

◆ threadref_QueryInterface()

static HRESULT WINAPI threadref_QueryInterface ( IUnknown iface,
REFIID  riid,
LPVOID ppvObj 
)
static

Definition at line 51 of file thread.c.

52{
54
55 trace("unexpected QueryInterface(%p, %s, %p) called\n", This, wine_dbgstr_guid(riid), ppvObj);
56 *ppvObj = NULL;
57 return E_NOINTERFACE;
58}
REFIID riid
Definition: atlbase.h:39
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197

◆ threadref_Release()

static ULONG WINAPI threadref_Release ( IUnknown iface)
static

Definition at line 68 of file thread.c.

69{
71
72 trace("unexpected Release(%p) called\n", This);
73 return InterlockedDecrement(This->ref);
74}
#define InterlockedDecrement
Definition: armddk.h:52

Variable Documentation

◆ AddRef_called

DWORD AddRef_called
static

Definition at line 38 of file thread.c.

Referenced by test_SHSetThreadRef(), and threadref_AddRef().

◆ threadref_vt

const IUnknownVtbl threadref_vt
static
Initial value:
=
{
}
static ULONG WINAPI threadref_Release(IUnknown *iface)
Definition: thread.c:163
static ULONG WINAPI threadref_AddRef(IUnknown *iface)
Definition: thread.c:155
static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
Definition: thread.c:134

Definition at line 77 of file thread.c.