ReactOS  0.4.15-dev-2703-g05fb0f1
thread.c
Go to the documentation of this file.
1 /* Tests for Thread and SHGlobalCounter functions
2  *
3  * Copyright 2010 Detlef Riekenberg
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include <stdio.h>
21 #include <stdarg.h>
22 
23 #define COBJMACROS
24 #define CONST_VTABLE
25 
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "ole2.h"
30 #include "shlwapi.h"
31 
32 #include "wine/test.h"
33 
34 static HRESULT (WINAPI *pSHCreateThreadRef)(LONG*, IUnknown**);
35 static HRESULT (WINAPI *pSHGetThreadRef)(IUnknown**);
36 static HRESULT (WINAPI *pSHSetThreadRef)(IUnknown*);
37 
39 
40 typedef struct
41 {
42  IUnknown IUnknown_iface;
43  LONG *ref;
44 } threadref;
45 
46 static inline threadref *impl_from_IUnknown(IUnknown *iface)
47 {
48  return CONTAINING_RECORD(iface, threadref, IUnknown_iface);
49 }
50 
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 }
59 
61 {
63 
64  AddRef_called++;
65  return InterlockedIncrement(This->ref);
66 }
67 
69 {
71 
72  trace("unexpected Release(%p) called\n", This);
73  return InterlockedDecrement(This->ref);
74 }
75 
76 /* VTable */
77 static const IUnknownVtbl threadref_vt =
78 {
82 };
83 
84 static void init_threadref(threadref* iface, LONG *refcount)
85 {
86  iface->IUnknown_iface.lpVtbl = &threadref_vt;
87  iface->ref = refcount;
88 }
89 
90 /* ##### */
91 
92 static void test_SHCreateThreadRef(void)
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 }
174 
175 
176 static void test_SHGetThreadRef(void)
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 }
197 
198 static void test_SHSetThreadRef(void)
199 {
200  threadref ref;
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 }
243 
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 REFIID
Definition: guiddef.h:118
#define E_NOINTERFACE
Definition: winerror.h:2364
HRESULT hr
Definition: shlfolder.c:183
REFIID riid
Definition: precomp.h:44
static const IUnknownVtbl threadref_vt
Definition: thread.c:77
const char * wine_dbgstr_guid(const GUID *guid)
LONG * ref
Definition: thread.c:126
static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
Definition: thread.c:51
static HMODULE hshlwapi
Definition: shreg.c:35
Definition: send.c:48
static void test_SHCreateThreadRef(void)
Definition: thread.c:92
long LONG
Definition: pedump.c:60
if SUCCEEDED(hr)
GLenum GLint ref
Definition: glext.h:6028
IUnknown IUnknown_iface
Definition: thread.c:125
#define E_INVALIDARG
Definition: ddrawi.h:101
static ULONG WINAPI threadref_Release(IUnknown *iface)
Definition: thread.c:68
static HRESULT(WINAPI *pSHCreateThreadRef)(LONG *
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define trace
Definition: atltest.h:70
LONG HRESULT
Definition: typedefs.h:79
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
static HANDLE thread
Definition: service.c:33
#define InterlockedDecrement
Definition: armddk.h:52
static threadref * impl_from_IUnknown(IUnknown *iface)
Definition: thread.c:46
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
START_TEST(thread)
Definition: thread.c:2115
#define S_OK
Definition: intsafe.h:51
#define InterlockedIncrement
Definition: armddk.h:53
static void test_SHGetThreadRef(void)
Definition: thread.c:176
#define ok(value,...)
Definition: atltest.h:57
static ULONG WINAPI threadref_AddRef(IUnknown *iface)
Definition: thread.c:60
#define NULL
Definition: types.h:112
static void test_SHSetThreadRef(void)
Definition: thread.c:198
unsigned int ULONG
Definition: retypes.h:1
static void init_threadref(threadref *iface, LONG *refcount)
Definition: thread.c:84
#define GetProcAddress(x, y)
Definition: compat.h:612
#define win_skip
Definition: test.h:151
static DWORD AddRef_called
Definition: thread.c:38