shlwapi/tests: Enable compilation with long types.
[wine.git] / dlls / shlwapi / tests / thread.c
blob65a13a3ef498d8a5b2fac74c79a1c86ca8d53027
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 #define CONST_VTABLE
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "ole2.h"
30 #include "shlwapi.h"
32 #include "wine/test.h"
34 static HRESULT (WINAPI *pSHCreateThreadRef)(LONG*, IUnknown**);
35 static HRESULT (WINAPI *pSHGetThreadRef)(IUnknown**);
36 static HRESULT (WINAPI *pSHSetThreadRef)(IUnknown*);
38 static DWORD AddRef_called;
40 typedef struct
42 IUnknown IUnknown_iface;
43 LONG *ref;
44 } threadref;
46 static inline threadref *impl_from_IUnknown(IUnknown *iface)
48 return CONTAINING_RECORD(iface, threadref, IUnknown_iface);
51 static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
53 threadref * This = impl_from_IUnknown(iface);
55 trace("unexpected QueryInterface(%p, %s, %p) called\n", This, wine_dbgstr_guid(riid), ppvObj);
56 *ppvObj = NULL;
57 return E_NOINTERFACE;
60 static ULONG WINAPI threadref_AddRef(IUnknown *iface)
62 threadref * This = impl_from_IUnknown(iface);
64 AddRef_called++;
65 return InterlockedIncrement(This->ref);
68 static ULONG WINAPI threadref_Release(IUnknown *iface)
70 threadref * This = impl_from_IUnknown(iface);
72 trace("unexpected Release(%p) called\n", This);
73 return InterlockedDecrement(This->ref);
76 /* VTable */
77 static const IUnknownVtbl threadref_vt =
79 threadref_QueryInterface,
80 threadref_AddRef,
81 threadref_Release
84 static void init_threadref(threadref* iface, LONG *refcount)
86 iface->IUnknown_iface.lpVtbl = &threadref_vt;
87 iface->ref = refcount;
90 /* ##### */
92 static void test_SHCreateThreadRef(void)
94 IUnknown *pobj;
95 IUnknown *punk;
96 LONG refcount;
97 HRESULT hr;
99 /* Not present before IE 6_XP_sp2 */
100 if (!pSHCreateThreadRef) {
101 win_skip("SHCreateThreadRef not found\n");
102 return;
105 /* start with a clean state */
106 hr = pSHSetThreadRef(NULL);
107 ok(hr == S_OK, "got 0x%lx (expected S_OK)\n", hr);
109 pobj = NULL;
110 refcount = 0xdeadbeef;
111 hr = pSHCreateThreadRef(&refcount, &pobj);
112 ok((hr == S_OK) && pobj && (refcount == 1),
113 "got 0x%lx and %p with %ld (expected S_OK and '!= NULL' with 1)\n",
114 hr, pobj, refcount);
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%lx and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
122 /* set the object */
123 hr = pSHSetThreadRef(pobj);
124 ok(hr == S_OK, "got 0x%lx (expected S_OK)\n", hr);
126 /* read back */
127 punk = NULL;
128 hr = pSHGetThreadRef(&punk);
129 ok( (hr == S_OK) && (punk == pobj) && (refcount == 2),
130 "got 0x%lx and %p with %ld (expected S_OK and %p with 2)\n",
131 hr, punk, refcount, pobj);
133 /* free the ref from SHGetThreadRef */
134 if (SUCCEEDED(hr)) {
135 hr = IUnknown_Release(pobj);
136 ok((hr == 1) && (hr == refcount),
137 "got %ld with %ld (expected 1 with 1)\n", hr, refcount);
140 /* free the object */
141 if (pobj) {
142 hr = IUnknown_Release(pobj);
143 ok((hr == 0) && (hr == refcount),
144 "got %ld with %ld (expected 0 with 0)\n", hr, refcount);
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%lx and %p with %ld\n", hr, punk, refcount);
155 /* remove the dead object pointer */
156 hr = pSHSetThreadRef(NULL);
157 ok(hr == S_OK, "got 0x%lx (expected S_OK)\n", hr);
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%lx (expected E_INVALIDARG)\n", hr);
166 refcount = 0xdeadbeef;
167 /* vista: E_INVALIDARG, XP: crash */
168 hr = pSHCreateThreadRef(&refcount, NULL);
169 ok( (hr == E_INVALIDARG) && (refcount == 0xdeadbeef),
170 "got 0x%lx with 0x%lx (expected E_INVALIDARG and oxdeadbeef)\n",
171 hr, refcount);
176 static void test_SHGetThreadRef(void)
178 IUnknown *punk;
179 HRESULT hr;
181 /* Not present before IE 5 */
182 if (!pSHGetThreadRef) {
183 win_skip("SHGetThreadRef not found\n");
184 return;
187 punk = NULL;
188 hr = pSHGetThreadRef(&punk);
189 ok( (hr == E_NOINTERFACE) && (punk == NULL),
190 "got 0x%lx and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
192 if (0) {
193 /* this crash on Windows */
194 pSHGetThreadRef(NULL);
198 static void test_SHSetThreadRef(void)
200 threadref ref;
201 IUnknown *punk;
202 HRESULT hr;
203 LONG refcount;
205 /* Not present before IE 5 */
206 if (!pSHSetThreadRef) {
207 win_skip("SHSetThreadRef not found\n");
208 return;
211 /* start with a clean state */
212 hr = pSHSetThreadRef(NULL);
213 ok(hr == S_OK, "got 0x%lx (expected S_OK)\n", hr);
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%lx with %ld, %ld (expected S_OK with 1, 0)\n",
222 hr, refcount, AddRef_called);
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%lx and %p with %ld, %ld (expected S_OK and %p with 2, 1)\n",
231 hr, punk, refcount, AddRef_called, &ref);
233 /* clear the object pointer */
234 hr = pSHSetThreadRef(NULL);
235 ok(hr == S_OK, "got 0x%lx (expected S_OK)\n", hr);
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%lx and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
244 START_TEST(thread)
246 HMODULE hshlwapi = GetModuleHandleA("shlwapi.dll");
248 pSHCreateThreadRef = (void *) GetProcAddress(hshlwapi, "SHCreateThreadRef");
249 pSHGetThreadRef = (void *) GetProcAddress(hshlwapi, "SHGetThreadRef");
250 pSHSetThreadRef = (void *) GetProcAddress(hshlwapi, "SHSetThreadRef");
252 test_SHCreateThreadRef();
253 test_SHGetThreadRef();
254 test_SHSetThreadRef();