advapi32: Make rpcrt4 a delayed import to work around circular dependencies with...
[wine/testsucceed.git] / dlls / shlwapi / tests / thread.c
blob24d5be158025d670260065ccd10c3e49767a7088
1 /* Tests for Thread and SHGlobalCounter functions
3 * Copyright 2010 Detlef Riekenberg
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.
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.
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
20 #include <stdio.h>
21 #include <stdarg.h>
23 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "ole2.h"
28 #include "shlwapi.h"
30 #include "wine/test.h"
32 static HRESULT (WINAPI *pSHCreateThreadRef)(LONG*, IUnknown**);
33 static HRESULT (WINAPI *pSHGetThreadRef)(IUnknown**);
34 static HRESULT (WINAPI *pSHSetThreadRef)(IUnknown*);
36 static DWORD AddRef_called;
38 typedef struct
40 const IUnknownVtbl* lpVtbl;
41 LONG *ref;
42 } threadref;
44 static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
46 threadref * This = (threadref *)iface;
48 trace("unexpected QueryInterface(%p, %p, %p) called\n", This, riid, ppvObj);
49 *ppvObj = NULL;
50 return E_NOINTERFACE;
53 static ULONG WINAPI threadref_AddRef(IUnknown *iface)
55 threadref * This = (threadref *)iface;
57 AddRef_called++;
58 return InterlockedIncrement(This->ref);
61 static ULONG WINAPI threadref_Release(IUnknown *iface)
63 threadref * This = (threadref *)iface;
65 trace("unexpected Release(%p) called\n", This);
66 return InterlockedDecrement(This->ref);
69 /* VTable */
70 static const IUnknownVtbl threadref_vt =
72 threadref_QueryInterface,
73 threadref_AddRef,
74 threadref_Release
77 static void init_threadref(threadref* iface, LONG *refcount)
79 iface->lpVtbl = &threadref_vt;
80 iface->ref = refcount;
83 /* ##### */
85 static void test_SHCreateThreadRef(void)
87 IUnknown *pobj;
88 IUnknown *punk;
89 LONG refcount;
90 HRESULT hr;
92 /* Not present before IE 6_XP_sp2 */
93 if (!pSHCreateThreadRef) {
94 win_skip("SHCreateThreadRef not found\n");
95 return;
98 /* start with a clean state */
99 hr = pSHSetThreadRef(NULL);
100 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
102 pobj = NULL;
103 refcount = 0xdeadbeef;
104 hr = pSHCreateThreadRef(&refcount, &pobj);
105 ok((hr == S_OK) && pobj && (refcount == 1),
106 "got 0x%x and %p with %d (expected S_OK and '!= NULL' with 1)\n",
107 hr, pobj, refcount);
109 /* the object is not automatic set as ThreadRef */
110 punk = NULL;
111 hr = pSHGetThreadRef(&punk);
112 ok( (hr == E_NOINTERFACE) && (punk == NULL),
113 "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
115 /* set the object */
116 hr = pSHSetThreadRef(pobj);
117 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
119 /* read back */
120 punk = NULL;
121 hr = pSHGetThreadRef(&punk);
122 ok( (hr == S_OK) && (punk == pobj) && (refcount == 2),
123 "got 0x%x and %p with %d (expected S_OK and %p with 2)\n",
124 hr, punk, refcount, pobj);
126 /* free the ref from SHGetThreadRef */
127 if (SUCCEEDED(hr)) {
128 hr = IUnknown_Release(pobj);
129 ok((hr == 1) && (hr == refcount),
130 "got %d with %d (expected 1 with 1)\n", hr, refcount);
133 /* free the object */
134 if (pobj) {
135 hr = IUnknown_Release(pobj);
136 ok((hr == 0) && (hr == refcount),
137 "got %d with %d (expected 0 with 0)\n", hr, refcount);
140 if (0) {
141 /* the ThreadRef has still the pointer,
142 but the object no longer exist after the *_Release */
143 punk = NULL;
144 hr = pSHGetThreadRef(&punk);
145 trace("got 0x%x and %p with %d\n", hr, punk, refcount);
148 /* remove the dead object pointer */
149 hr = pSHSetThreadRef(NULL);
150 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
152 /* parameter check */
153 if (0) {
154 /* vista: E_INVALIDARG, XP: crash */
155 pobj = NULL;
156 hr = pSHCreateThreadRef(NULL, &pobj);
157 ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
159 refcount = 0xdeadbeef;
160 /* vista: E_INVALIDARG, XP: crash */
161 hr = pSHCreateThreadRef(&refcount, NULL);
162 ok( (hr == E_INVALIDARG) && (refcount == 0xdeadbeef),
163 "got 0x%x with 0x%x (expected E_INVALIDARG and oxdeadbeef)\n",
164 hr, refcount);
169 static void test_SHGetThreadRef(void)
171 IUnknown *punk;
172 HRESULT hr;
174 /* Not present before IE 5 */
175 if (!pSHGetThreadRef) {
176 win_skip("SHGetThreadRef not found\n");
177 return;
180 punk = NULL;
181 hr = pSHGetThreadRef(&punk);
182 ok( (hr == E_NOINTERFACE) && (punk == NULL),
183 "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
185 if (0) {
186 /* this crash on Windows */
187 hr = pSHGetThreadRef(NULL);
191 static void test_SHSetThreadRef(void)
193 threadref ref;
194 IUnknown *punk;
195 HRESULT hr;
196 LONG refcount;
198 /* Not present before IE 5 */
199 if (!pSHSetThreadRef) {
200 win_skip("SHSetThreadRef not found\n");
201 return;
204 /* start with a clean state */
205 hr = pSHSetThreadRef(NULL);
206 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
208 /* build and set out object */
209 init_threadref(&ref, &refcount);
210 AddRef_called = 0;
211 refcount = 1;
212 hr = pSHSetThreadRef( (IUnknown *)&ref);
213 ok( (hr == S_OK) && (refcount == 1) && (!AddRef_called),
214 "got 0x%x with %d, %d (expected S_OK with 1, 0)\n",
215 hr, refcount, AddRef_called);
217 /* read back our object */
218 AddRef_called = 0;
219 refcount = 1;
220 punk = NULL;
221 hr = pSHGetThreadRef(&punk);
222 ok( (hr == S_OK) && (punk == (IUnknown *)&ref) && (refcount == 2) && (AddRef_called == 1),
223 "got 0x%x and %p with %d, %d (expected S_OK and %p with 2, 1)\n",
224 hr, punk, refcount, AddRef_called, &ref);
226 /* clear the object pointer */
227 hr = pSHSetThreadRef(NULL);
228 ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
230 /* verify, that our object is no longer known as ThreadRef */
231 hr = pSHGetThreadRef(&punk);
232 ok( (hr == E_NOINTERFACE) && (punk == NULL),
233 "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
237 START_TEST(thread)
239 HMODULE hshlwapi = GetModuleHandleA("shlwapi.dll");
241 pSHCreateThreadRef = (void *) GetProcAddress(hshlwapi, "SHCreateThreadRef");
242 pSHGetThreadRef = (void *) GetProcAddress(hshlwapi, "SHGetThreadRef");
243 pSHSetThreadRef = (void *) GetProcAddress(hshlwapi, "SHSetThreadRef");
245 test_SHCreateThreadRef();
246 test_SHGetThreadRef();
247 test_SHSetThreadRef();