kernel32: Remove superfluous heap reallocation calls in FormatMessageA/W.
[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 *pSHGetThreadRef)(IUnknown**);
33 static HRESULT (WINAPI *pSHSetThreadRef)(IUnknown*);
34
35 static DWORD AddRef_called;
36
37 typedef struct
38 {
39   void* lpVtbl;
40   LONG  *ref;
41 } threadref;
42
43 static HRESULT WINAPI threadref_QueryInterface(threadref *This, REFIID riid, LPVOID *ppvObj)
44 {
45     trace("unexpected QueryInterface(%p, %p, %p) called\n", This, riid, ppvObj);
46     *ppvObj = NULL;
47     return E_NOINTERFACE;
48 }
49
50 static ULONG WINAPI threadref_AddRef(threadref *This)
51 {
52     AddRef_called++;
53     return InterlockedIncrement(This->ref);
54 }
55
56 static ULONG WINAPI threadref_Release(threadref *This)
57 {
58     trace("unexpected Release(%p) called\n", This);
59     return InterlockedDecrement(This->ref);
60 }
61
62 /* VTable */
63 static void* threadref_vt[] =
64 {
65   threadref_QueryInterface,
66   threadref_AddRef,
67   threadref_Release
68 };
69
70 static void init_threadref(threadref* iface, LONG *refcount)
71 {
72   iface->lpVtbl = (void*)threadref_vt;
73   iface->ref = refcount;
74 }
75
76 /* ##### */
77
78 static void test_SHGetThreadRef(void)
79 {
80     IUnknown *punk;
81     HRESULT hr;
82
83     /* Not present before IE 5 */
84     if (!pSHGetThreadRef) {
85         win_skip("SHGetThreadRef not found\n");
86         return;
87     }
88
89     punk = NULL;
90     hr = pSHGetThreadRef(&punk);
91     ok( (hr == E_NOINTERFACE) && (punk == NULL),
92         "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
93
94     if (0) {
95         /* this crash on Windows */
96         hr = pSHGetThreadRef(NULL);
97     }
98 }
99
100 static void test_SHSetThreadRef(void)
101 {
102     threadref ref;
103     IUnknown *punk;
104     HRESULT hr;
105     LONG refcount;
106
107     /* Not present before IE 5 */
108     if (!pSHSetThreadRef) {
109         win_skip("SHSetThreadRef not found\n");
110         return;
111     }
112
113     /* start with a clean state */
114     hr = pSHSetThreadRef(NULL);
115     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
116
117     /* build and set out object */
118     init_threadref(&ref, &refcount);
119     AddRef_called = 0;
120     refcount = 1;
121     hr = pSHSetThreadRef( (IUnknown *)&ref);
122     ok( (hr == S_OK) && (refcount == 1) && (!AddRef_called),
123         "got 0x%x with %d, %d (expected S_OK with 1, 0)\n",
124         hr, refcount, AddRef_called);
125
126     /* read back our object */
127     AddRef_called = 0;
128     refcount = 1;
129     punk = NULL;
130     hr = pSHGetThreadRef(&punk);
131     ok( (hr == S_OK) && (punk == (IUnknown *)&ref) && (refcount == 2) && (AddRef_called == 1),
132         "got 0x%x and %p with %d, %d (expected S_OK and %p with 2, 1)\n",
133         hr, punk, refcount, AddRef_called, &ref);
134
135     /* clear the onject pointer */
136     hr = pSHSetThreadRef(NULL);
137     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
138
139     /* verify, that our object is no longer known as ThreadRef */
140     hr = pSHGetThreadRef(&punk);
141     ok( (hr == E_NOINTERFACE) && (punk == NULL),
142         "got 0x%x and %p (expected E_NOINTERFACE and NULL)\n", hr, punk);
143
144 }
145
146 START_TEST(thread)
147 {
148     HMODULE hshlwapi = GetModuleHandleA("shlwapi.dll");
149
150     pSHGetThreadRef = (void *) GetProcAddress(hshlwapi, "SHGetThreadRef");
151     pSHSetThreadRef = (void *) GetProcAddress(hshlwapi, "SHSetThreadRef");
152
153     test_SHGetThreadRef();
154     test_SHSetThreadRef();
155
156 }