widl: Use the output buffer functions to write typelibs.
[wine] / dlls / shlwapi / tests / thread.c
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 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "ole2.h"
28 #include "shlwapi.h"
29
30 #include "wine/test.h"
31
32 static HRESULT (WINAPI *pSHCreateThreadRef)(LONG*, IUnknown**);
33 static HRESULT (WINAPI *pSHGetThreadRef)(IUnknown**);
34 static HRESULT (WINAPI *pSHSetThreadRef)(IUnknown*);
35
36 static DWORD AddRef_called;
37
38 typedef struct
39 {
40   const IUnknownVtbl* lpVtbl;
41   LONG  *ref;
42 } threadref;
43
44 static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
45 {
46     threadref * This = (threadref *)iface;
47
48     trace("unexpected QueryInterface(%p, %p, %p) called\n", This, riid, ppvObj);
49     *ppvObj = NULL;
50     return E_NOINTERFACE;
51 }
52
53 static ULONG WINAPI threadref_AddRef(IUnknown *iface)
54 {
55     threadref * This = (threadref *)iface;
56
57     AddRef_called++;
58     return InterlockedIncrement(This->ref);
59 }
60
61 static ULONG WINAPI threadref_Release(IUnknown *iface)
62 {
63     threadref * This = (threadref *)iface;
64
65     trace("unexpected Release(%p) called\n", This);
66     return InterlockedDecrement(This->ref);
67 }
68
69 /* VTable */
70 static const IUnknownVtbl threadref_vt =
71 {
72   threadref_QueryInterface,
73   threadref_AddRef,
74   threadref_Release
75 };
76
77 static void init_threadref(threadref* iface, LONG *refcount)
78 {
79   iface->lpVtbl = &threadref_vt;
80   iface->ref = refcount;
81 }
82
83 /* ##### */
84
85 static void test_SHCreateThreadRef(void)
86 {
87     IUnknown *pobj;
88     IUnknown *punk;
89     LONG refcount;
90     HRESULT hr;
91
92     /* Not present before IE 6_XP_sp2 */
93     if (!pSHCreateThreadRef) {
94         win_skip("SHCreateThreadRef not found\n");
95         return;
96     }
97
98     /* start with a clean state */
99     hr = pSHSetThreadRef(NULL);
100     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
101
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);
108
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);
114
115     /* set the object */
116     hr = pSHSetThreadRef(pobj);
117     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
118
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);
125
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);
131     }
132
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);
138     }
139
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);
146     }
147
148     /* remove the dead object pointer */
149     hr = pSHSetThreadRef(NULL);
150     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
151
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);
158
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);
165     }
166 }
167
168
169 static void test_SHGetThreadRef(void)
170 {
171     IUnknown *punk;
172     HRESULT hr;
173
174     /* Not present before IE 5 */
175     if (!pSHGetThreadRef) {
176         win_skip("SHGetThreadRef not found\n");
177         return;
178     }
179
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);
184
185     if (0) {
186         /* this crash on Windows */
187         hr = pSHGetThreadRef(NULL);
188     }
189 }
190
191 static void test_SHSetThreadRef(void)
192 {
193     threadref ref;
194     IUnknown *punk;
195     HRESULT hr;
196     LONG refcount;
197
198     /* Not present before IE 5 */
199     if (!pSHSetThreadRef) {
200         win_skip("SHSetThreadRef not found\n");
201         return;
202     }
203
204     /* start with a clean state */
205     hr = pSHSetThreadRef(NULL);
206     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
207
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);
216
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);
225
226     /* clear the object pointer */
227     hr = pSHSetThreadRef(NULL);
228     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
229
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);
234
235 }
236
237 START_TEST(thread)
238 {
239     HMODULE hshlwapi = GetModuleHandleA("shlwapi.dll");
240
241     pSHCreateThreadRef = (void *) GetProcAddress(hshlwapi, "SHCreateThreadRef");
242     pSHGetThreadRef = (void *) GetProcAddress(hshlwapi, "SHGetThreadRef");
243     pSHSetThreadRef = (void *) GetProcAddress(hshlwapi, "SHSetThreadRef");
244
245     test_SHCreateThreadRef();
246     test_SHGetThreadRef();
247     test_SHSetThreadRef();
248
249 }