[OLEAUT32_WINETEST] Add a PCH.
[reactos.git] / modules / rostests / winetests / oleaut32 / dispatch.c
1 /*
2 * Dispatch test
3 *
4 * Copyright 2009 James Hawkins
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "precomp.h"
22
23 static const WCHAR szSunshine[] = {'S','u','n','s','h','i','n','e',0};
24
25 /* Temporary storage for ok_bstr. */
26 static CHAR temp_str[MAX_PATH];
27
28 #define ok_bstr(bstr, expected, format) \
29 do { \
30 WideCharToMultiByte(CP_ACP, 0, bstr, -1, temp_str, MAX_PATH, NULL, NULL); \
31 if (lstrcmpA(temp_str, expected) != 0) \
32 ok(0, format, expected, temp_str); \
33 } while(0);
34
35 #define INIT_DISPPARAMS(dp, args, named_args, num_args, num_named_args) \
36 dp.rgvarg = args; \
37 dp.rgdispidNamedArgs = named_args; \
38 dp.cArgs = num_args; \
39 dp.cNamedArgs = num_named_args; \
40
41 /* Initializes vararg with three values:
42 * VT_I2 - 42
43 * VT_I4 - 1234567890
44 * VT_BSTR - "Sunshine"
45 */
46 #define INIT_VARARG(vararg) \
47 VariantInit(&vararg[0]); \
48 V_VT(&vararg[0]) = VT_I2; \
49 V_I2(&vararg[0]) = 42; \
50 VariantInit(&vararg[1]); \
51 V_VT(&vararg[1]) = VT_I4; \
52 V_I4(&vararg[1]) = 1234567890; \
53 VariantInit(&vararg[2]); \
54 V_VT(&vararg[2]) = VT_BSTR; \
55 V_BSTR(&vararg[2]) = SysAllocString(szSunshine);
56
57 /* Clears the vararg. */
58 #define CLEAR_VARARG(vararg) \
59 VariantClear(&vararg[0]); \
60 VariantClear(&vararg[1]); \
61 VariantClear(&vararg[2]);
62
63 static void test_DispGetParam(void)
64 {
65 HRESULT hr;
66 DISPPARAMS dispparams;
67 VARIANTARG vararg[3];
68 VARIANT result;
69 unsigned int err_index;
70
71 VariantInit(&result);
72
73 /* DispGetParam crashes on Windows if pdispparams is NULL. */
74
75 /* pdispparams has zero parameters. */
76 INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
77 VariantInit(&result);
78 err_index = 0xdeadbeef;
79 hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index);
80 ok(hr == DISP_E_PARAMNOTFOUND,
81 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
82 ok(V_VT(&result) == VT_EMPTY,
83 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
84 ok(err_index == 0xdeadbeef,
85 "Expected err_index to be unchanged, got %d\n", err_index);
86
87 /* pdispparams has zero parameters, position is invalid. */
88 INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
89 VariantInit(&result);
90 err_index = 0xdeadbeef;
91 hr = DispGetParam(&dispparams, 1, VT_I2, &result, &err_index);
92 ok(hr == DISP_E_PARAMNOTFOUND,
93 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
94 ok(V_VT(&result) == VT_EMPTY,
95 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
96 ok(err_index == 0xdeadbeef,
97 "Expected err_index to be unchanged, got %d\n", err_index);
98
99 /* pdispparams has zero parameters, pvarResult is NULL. */
100 INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
101 err_index = 0xdeadbeef;
102 hr = DispGetParam(&dispparams, 0, VT_I2, NULL, &err_index);
103 ok(hr == DISP_E_PARAMNOTFOUND,
104 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
105 ok(err_index == 0xdeadbeef,
106 "Expected err_index to be unchanged, got %d\n", err_index);
107
108 /* pdispparams has zero parameters, puArgErr is NULL. */
109 INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
110 VariantInit(&result);
111 hr = DispGetParam(&dispparams, 0, VT_I2, &result, NULL);
112 ok(hr == DISP_E_PARAMNOTFOUND,
113 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
114 ok(V_VT(&result) == VT_EMPTY,
115 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
116
117 /* pdispparams.cArgs is 1, yet pdispparams.rgvarg is NULL. */
118 INIT_DISPPARAMS(dispparams, NULL, NULL, 1, 0);
119 VariantInit(&result);
120 err_index = 0xdeadbeef;
121 hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index);
122 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
123 ok(V_VT(&result) == VT_EMPTY,
124 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
125 ok(err_index == 0, "Expected 0, got %d\n", err_index);
126
127 /* pdispparams.cNamedArgs is 1, yet pdispparams.rgdispidNamedArgs is NULL.
128 *
129 * This crashes on Windows.
130 */
131
132 /* {42, 1234567890, "Sunshine"} */
133 INIT_VARARG(vararg);
134
135 /* Get the first param. position is end-based, so 2 is the first parameter
136 * of 3 parameters.
137 */
138 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
139 VariantInit(&result);
140 err_index = 0xdeadbeef;
141 hr = DispGetParam(&dispparams, 2, VT_I2, &result, &err_index);
142 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
143 ok(V_VT(&result) == VT_I2, "Expected VT_I2, got %08x\n", V_VT(&result));
144 ok(V_I2(&result) == 42, "Expected 42, got %d\n", V_I2(&result));
145 ok(err_index == 0xdeadbeef,
146 "Expected err_index to be unchanged, got %d\n", err_index);
147
148 /* Get the second param. */
149 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
150 VariantInit(&result);
151 err_index = 0xdeadbeef;
152 hr = DispGetParam(&dispparams, 1, VT_I4, &result, &err_index);
153 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
154 ok(V_VT(&result) == VT_I4, "Expected VT_I4, got %08x\n", V_VT(&result));
155 ok(V_I4(&result) == 1234567890,
156 "Expected 1234567890, got %d\n", V_I4(&result));
157 ok(err_index == 0xdeadbeef,
158 "Expected err_index to be unchanged, got %d\n", err_index);
159
160 /* Get the third param. */
161 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
162 VariantInit(&result);
163 err_index = 0xdeadbeef;
164 hr = DispGetParam(&dispparams, 0, VT_BSTR, &result, &err_index);
165 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
166 ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
167 ok_bstr(V_BSTR(&result), "Sunshine", "Expected %s, got %s\n");
168 ok(err_index == 0xdeadbeef,
169 "Expected err_index to be unchanged, got %d\n", err_index);
170 VariantClear(&result);
171
172 /* position is out of range. */
173 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
174 VariantInit(&result);
175 err_index = 0xdeadbeef;
176 hr = DispGetParam(&dispparams, 3, VT_I2, &result, &err_index);
177 ok(hr == DISP_E_PARAMNOTFOUND,
178 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
179 ok(V_VT(&result) == VT_EMPTY,
180 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
181 ok(err_index == 0xdeadbeef,
182 "Expected err_index to be unchanged, got %d\n", err_index);
183
184 /* pvarResult is NULL. */
185 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
186 err_index = 0xdeadbeef;
187 hr = DispGetParam(&dispparams, 2, VT_I2, NULL, &err_index);
188 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
189 ok(err_index == 0, "Expected 0, got %d\n", err_index);
190
191 /* puArgErr is NULL. */
192 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
193 VariantInit(&result);
194 hr = DispGetParam(&dispparams, 2, VT_I2, &result, NULL);
195 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
196 ok(V_VT(&result) == VT_I2, "Expected VT_I2, got %08x\n", V_VT(&result));
197 ok(V_I2(&result) == 42, "Expected 42, got %d\n", V_I2(&result));
198
199 /* Coerce the first param to VT_I4. */
200 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
201 VariantInit(&result);
202 err_index = 0xdeadbeef;
203 hr = DispGetParam(&dispparams, 2, VT_I4, &result, &err_index);
204 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
205 ok(V_VT(&result) == VT_I4, "Expected VT_I4, got %08x\n", V_VT(&result));
206 ok(V_I4(&result) == 42, "Expected 42, got %d\n", V_I4(&result));
207 ok(err_index == 0xdeadbeef,
208 "Expected err_index to be unchanged, got %d\n", err_index);
209
210 /* Coerce the first param to VT_BSTR. */
211 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
212 VariantInit(&result);
213 err_index = 0xdeadbeef;
214 hr = DispGetParam(&dispparams, 2, VT_BSTR, &result, &err_index);
215 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
216 ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
217 ok_bstr(V_BSTR(&result), "42", "Expected %s, got %s\n");
218 ok(err_index == 0xdeadbeef,
219 "Expected err_index to be unchanged, got %d\n", err_index);
220 VariantClear(&result);
221
222 /* Coerce the second (VT_I4) param to VT_I2. */
223 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
224 VariantInit(&result);
225 err_index = 0xdeadbeef;
226 hr = DispGetParam(&dispparams, 1, VT_I2, &result, &err_index);
227 ok(hr == DISP_E_OVERFLOW, "Expected DISP_E_OVERFLOW, got %08x\n", hr);
228 ok(V_VT(&result) == VT_EMPTY,
229 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
230 ok(err_index == 1, "Expected 1, got %d\n", err_index);
231
232 /* Coerce the third (VT_BSTR) param to VT_I2. */
233 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
234 VariantInit(&result);
235 err_index = 0xdeadbeef;
236 hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index);
237 ok(hr == DISP_E_TYPEMISMATCH,
238 "Expected DISP_E_TYPEMISMATCH, got %08x\n", hr);
239 ok(V_VT(&result) == VT_EMPTY,
240 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
241 ok(err_index == 2, "Expected 2, got %d\n", err_index);
242
243 /* Coerce the first parameter to an invalid type. */
244 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
245 VariantInit(&result);
246 err_index = 0xdeadbeef;
247 hr = DispGetParam(&dispparams, 2, VT_ILLEGAL, &result, &err_index);
248 ok(hr == DISP_E_BADVARTYPE, "Expected DISP_E_BADVARTYPE, got %08x\n", hr);
249 ok(V_VT(&result) == VT_EMPTY,
250 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
251 ok(err_index == 0, "Expected 0, got %d\n", err_index);
252
253 CLEAR_VARARG(vararg);
254
255 /* Coerce the first parameter, which is of type VT_EMPTY, to VT_BSTR. */
256 VariantInit(&vararg[0]);
257 INIT_DISPPARAMS(dispparams, vararg, NULL, 1, 0);
258 VariantInit(&result);
259 err_index = 0xdeadbeef;
260 hr = DispGetParam(&dispparams, 0, VT_BSTR, &result, &err_index);
261 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
262 ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
263 ok(err_index == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", err_index);
264 VariantClear(&result);
265 }
266
267 static HRESULT WINAPI unk_QI(IUnknown *iface, REFIID riid, void **obj)
268 {
269 if (IsEqualIID(riid, &IID_IUnknown))
270 {
271 *obj = iface;
272 return S_OK;
273 }
274 else
275 {
276 *obj = NULL;
277 return E_NOINTERFACE;
278 }
279 }
280
281 static ULONG WINAPI unk_AddRef(IUnknown *iface)
282 {
283 return 2;
284 }
285
286 static ULONG WINAPI unk_Release(IUnknown *iface)
287 {
288 return 1;
289 }
290
291 static const IUnknownVtbl unkvtbl =
292 {
293 unk_QI,
294 unk_AddRef,
295 unk_Release
296 };
297
298 static IUnknown test_unk = { &unkvtbl };
299
300 static void test_CreateStdDispatch(void)
301 {
302 static const WCHAR stdole2W[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
303 ITypeLib *tl;
304 ITypeInfo *ti;
305 IUnknown *unk;
306 HRESULT hr;
307
308 hr = CreateStdDispatch(NULL, NULL, NULL, NULL);
309 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
310
311 hr = CreateStdDispatch(NULL, NULL, NULL, &unk);
312 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
313
314 hr = LoadTypeLib(stdole2W, &tl);
315 ok(hr == S_OK, "got %08x\n", hr);
316 hr = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IUnknown, &ti);
317 ok(hr == S_OK, "got %08x\n", hr);
318 ITypeLib_Release(tl);
319
320 hr = CreateStdDispatch(NULL, &test_unk, NULL, &unk);
321 ok(hr == E_INVALIDARG, "got %08x\n", hr);
322
323 hr = CreateStdDispatch(NULL, NULL, ti, &unk);
324 ok(hr == E_INVALIDARG, "got %08x\n", hr);
325
326 hr = CreateStdDispatch(NULL, &test_unk, ti, &unk);
327 ok(hr == S_OK, "got %08x\n", hr);
328 IUnknown_Release(unk);
329
330 ITypeInfo_Release(ti);
331 }
332
333 START_TEST(dispatch)
334 {
335 test_DispGetParam();
336 test_CreateStdDispatch();
337 }