d5ac4f0383e741ab26151b2c13c41593455cf448
[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 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27
28 #include <wine/test.h>
29 //#include <windef.h>
30 //#include <winbase.h>
31 #include <winnls.h>
32 #include <ole2.h>
33 //#include <oaidl.h>
34
35 static const WCHAR szSunshine[] = {'S','u','n','s','h','i','n','e',0};
36
37 /* Temporary storage for ok_bstr. */
38 static CHAR temp_str[MAX_PATH];
39
40 #define ok_bstr(bstr, expected, format) \
41 do { \
42 WideCharToMultiByte(CP_ACP, 0, bstr, -1, temp_str, MAX_PATH, NULL, NULL); \
43 if (lstrcmpA(temp_str, expected) != 0) \
44 ok(0, format, expected, temp_str); \
45 } while(0);
46
47 #define INIT_DISPPARAMS(dp, args, named_args, num_args, num_named_args) \
48 dp.rgvarg = args; \
49 dp.rgdispidNamedArgs = named_args; \
50 dp.cArgs = num_args; \
51 dp.cNamedArgs = num_named_args; \
52
53 /* Initializes vararg with three values:
54 * VT_I2 - 42
55 * VT_I4 - 1234567890
56 * VT_BSTR - "Sunshine"
57 */
58 #define INIT_VARARG(vararg) \
59 VariantInit(&vararg[0]); \
60 V_VT(&vararg[0]) = VT_I2; \
61 V_I2(&vararg[0]) = 42; \
62 VariantInit(&vararg[1]); \
63 V_VT(&vararg[1]) = VT_I4; \
64 V_I4(&vararg[1]) = 1234567890; \
65 VariantInit(&vararg[2]); \
66 V_VT(&vararg[2]) = VT_BSTR; \
67 V_BSTR(&vararg[2]) = SysAllocString(szSunshine);
68
69 /* Clears the vararg. */
70 #define CLEAR_VARARG(vararg) \
71 VariantClear(&vararg[0]); \
72 VariantClear(&vararg[1]); \
73 VariantClear(&vararg[2]);
74
75 static void test_DispGetParam(void)
76 {
77 HRESULT hr;
78 DISPPARAMS dispparams;
79 VARIANTARG vararg[3];
80 VARIANT result;
81 unsigned int err_index;
82
83 VariantInit(&result);
84
85 /* DispGetParam crashes on Windows if pdispparams is NULL. */
86
87 /* pdispparams has zero parameters. */
88 INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
89 VariantInit(&result);
90 err_index = 0xdeadbeef;
91 hr = DispGetParam(&dispparams, 0, 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, position is invalid. */
100 INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
101 VariantInit(&result);
102 err_index = 0xdeadbeef;
103 hr = DispGetParam(&dispparams, 1, VT_I2, &result, &err_index);
104 ok(hr == DISP_E_PARAMNOTFOUND,
105 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
106 ok(V_VT(&result) == VT_EMPTY,
107 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
108 ok(err_index == 0xdeadbeef,
109 "Expected err_index to be unchanged, got %d\n", err_index);
110
111 /* pdispparams has zero parameters, pvarResult is NULL. */
112 INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
113 err_index = 0xdeadbeef;
114 hr = DispGetParam(&dispparams, 0, VT_I2, NULL, &err_index);
115 ok(hr == DISP_E_PARAMNOTFOUND,
116 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
117 ok(err_index == 0xdeadbeef,
118 "Expected err_index to be unchanged, got %d\n", err_index);
119
120 /* pdispparams has zero parameters, puArgErr is NULL. */
121 INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
122 VariantInit(&result);
123 hr = DispGetParam(&dispparams, 0, VT_I2, &result, NULL);
124 ok(hr == DISP_E_PARAMNOTFOUND,
125 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
126 ok(V_VT(&result) == VT_EMPTY,
127 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
128
129 /* pdispparams.cArgs is 1, yet pdispparams.rgvarg is NULL. */
130 INIT_DISPPARAMS(dispparams, NULL, NULL, 1, 0);
131 VariantInit(&result);
132 err_index = 0xdeadbeef;
133 hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index);
134 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
135 ok(V_VT(&result) == VT_EMPTY,
136 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
137 ok(err_index == 0, "Expected 0, got %d\n", err_index);
138
139 /* pdispparams.cNamedArgs is 1, yet pdispparams.rgdispidNamedArgs is NULL.
140 *
141 * This crashes on Windows.
142 */
143
144 /* {42, 1234567890, "Sunshine"} */
145 INIT_VARARG(vararg);
146
147 /* Get the first param. position is end-based, so 2 is the first parameter
148 * of 3 parameters.
149 */
150 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
151 VariantInit(&result);
152 err_index = 0xdeadbeef;
153 hr = DispGetParam(&dispparams, 2, VT_I2, &result, &err_index);
154 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
155 ok(V_VT(&result) == VT_I2, "Expected VT_I2, got %08x\n", V_VT(&result));
156 ok(V_I2(&result) == 42, "Expected 42, got %d\n", V_I2(&result));
157 ok(err_index == 0xdeadbeef,
158 "Expected err_index to be unchanged, got %d\n", err_index);
159
160 /* Get the second param. */
161 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
162 VariantInit(&result);
163 err_index = 0xdeadbeef;
164 hr = DispGetParam(&dispparams, 1, VT_I4, &result, &err_index);
165 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
166 ok(V_VT(&result) == VT_I4, "Expected VT_I4, got %08x\n", V_VT(&result));
167 ok(V_I4(&result) == 1234567890,
168 "Expected 1234567890, got %d\n", V_I4(&result));
169 ok(err_index == 0xdeadbeef,
170 "Expected err_index to be unchanged, got %d\n", err_index);
171
172 /* Get the third param. */
173 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
174 VariantInit(&result);
175 err_index = 0xdeadbeef;
176 hr = DispGetParam(&dispparams, 0, VT_BSTR, &result, &err_index);
177 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
178 ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
179 ok_bstr(V_BSTR(&result), "Sunshine", "Expected %s, got %s\n");
180 ok(err_index == 0xdeadbeef,
181 "Expected err_index to be unchanged, got %d\n", err_index);
182 VariantClear(&result);
183
184 /* position is out of range. */
185 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
186 VariantInit(&result);
187 err_index = 0xdeadbeef;
188 hr = DispGetParam(&dispparams, 3, VT_I2, &result, &err_index);
189 ok(hr == DISP_E_PARAMNOTFOUND,
190 "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
191 ok(V_VT(&result) == VT_EMPTY,
192 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
193 ok(err_index == 0xdeadbeef,
194 "Expected err_index to be unchanged, got %d\n", err_index);
195
196 /* pvarResult is NULL. */
197 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
198 err_index = 0xdeadbeef;
199 hr = DispGetParam(&dispparams, 2, VT_I2, NULL, &err_index);
200 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
201 ok(err_index == 0, "Expected 0, got %d\n", err_index);
202
203 /* puArgErr is NULL. */
204 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
205 VariantInit(&result);
206 hr = DispGetParam(&dispparams, 2, VT_I2, &result, NULL);
207 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
208 ok(V_VT(&result) == VT_I2, "Expected VT_I2, got %08x\n", V_VT(&result));
209 ok(V_I2(&result) == 42, "Expected 42, got %d\n", V_I2(&result));
210
211 /* Coerce the first param to VT_I4. */
212 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
213 VariantInit(&result);
214 err_index = 0xdeadbeef;
215 hr = DispGetParam(&dispparams, 2, VT_I4, &result, &err_index);
216 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
217 ok(V_VT(&result) == VT_I4, "Expected VT_I4, got %08x\n", V_VT(&result));
218 ok(V_I4(&result) == 42, "Expected 42, got %d\n", V_I4(&result));
219 ok(err_index == 0xdeadbeef,
220 "Expected err_index to be unchanged, got %d\n", err_index);
221
222 /* Coerce the first param to VT_BSTR. */
223 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
224 VariantInit(&result);
225 err_index = 0xdeadbeef;
226 hr = DispGetParam(&dispparams, 2, VT_BSTR, &result, &err_index);
227 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
228 ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
229 ok_bstr(V_BSTR(&result), "42", "Expected %s, got %s\n");
230 ok(err_index == 0xdeadbeef,
231 "Expected err_index to be unchanged, got %d\n", err_index);
232 VariantClear(&result);
233
234 /* Coerce the second (VT_I4) param to VT_I2. */
235 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
236 VariantInit(&result);
237 err_index = 0xdeadbeef;
238 hr = DispGetParam(&dispparams, 1, VT_I2, &result, &err_index);
239 ok(hr == DISP_E_OVERFLOW, "Expected DISP_E_OVERFLOW, got %08x\n", hr);
240 ok(V_VT(&result) == VT_EMPTY,
241 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
242 ok(err_index == 1, "Expected 1, got %d\n", err_index);
243
244 /* Coerce the third (VT_BSTR) param to VT_I2. */
245 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
246 VariantInit(&result);
247 err_index = 0xdeadbeef;
248 hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index);
249 ok(hr == DISP_E_TYPEMISMATCH,
250 "Expected DISP_E_TYPEMISMATCH, got %08x\n", hr);
251 ok(V_VT(&result) == VT_EMPTY,
252 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
253 ok(err_index == 2, "Expected 2, got %d\n", err_index);
254
255 /* Coerce the first parameter to an invalid type. */
256 INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
257 VariantInit(&result);
258 err_index = 0xdeadbeef;
259 hr = DispGetParam(&dispparams, 2, VT_ILLEGAL, &result, &err_index);
260 ok(hr == DISP_E_BADVARTYPE, "Expected DISP_E_BADVARTYPE, got %08x\n", hr);
261 ok(V_VT(&result) == VT_EMPTY,
262 "Expected VT_EMPTY, got %08x\n", V_VT(&result));
263 ok(err_index == 0, "Expected 0, got %d\n", err_index);
264
265 CLEAR_VARARG(vararg);
266
267 /* Coerce the first parameter, which is of type VT_EMPTY, to VT_BSTR. */
268 VariantInit(&vararg[0]);
269 INIT_DISPPARAMS(dispparams, vararg, NULL, 1, 0);
270 VariantInit(&result);
271 err_index = 0xdeadbeef;
272 hr = DispGetParam(&dispparams, 0, VT_BSTR, &result, &err_index);
273 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
274 ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
275 ok(err_index == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", err_index);
276 VariantClear(&result);
277 }
278
279 static HRESULT WINAPI unk_QI(IUnknown *iface, REFIID riid, void **obj)
280 {
281 if (IsEqualIID(riid, &IID_IUnknown))
282 {
283 *obj = iface;
284 return S_OK;
285 }
286 else
287 {
288 *obj = NULL;
289 return E_NOINTERFACE;
290 }
291 }
292
293 static ULONG WINAPI unk_AddRef(IUnknown *iface)
294 {
295 return 2;
296 }
297
298 static ULONG WINAPI unk_Release(IUnknown *iface)
299 {
300 return 1;
301 }
302
303 static const IUnknownVtbl unkvtbl =
304 {
305 unk_QI,
306 unk_AddRef,
307 unk_Release
308 };
309
310 static IUnknown test_unk = { &unkvtbl };
311
312 static void test_CreateStdDispatch(void)
313 {
314 static const WCHAR stdole2W[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
315 ITypeLib *tl;
316 ITypeInfo *ti;
317 IUnknown *unk;
318 HRESULT hr;
319
320 hr = CreateStdDispatch(NULL, NULL, NULL, NULL);
321 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
322
323 hr = CreateStdDispatch(NULL, NULL, NULL, &unk);
324 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
325
326 hr = LoadTypeLib(stdole2W, &tl);
327 ok(hr == S_OK, "got %08x\n", hr);
328 hr = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IUnknown, &ti);
329 ok(hr == S_OK, "got %08x\n", hr);
330 ITypeLib_Release(tl);
331
332 hr = CreateStdDispatch(NULL, &test_unk, NULL, &unk);
333 ok(hr == E_INVALIDARG, "got %08x\n", hr);
334
335 hr = CreateStdDispatch(NULL, NULL, ti, &unk);
336 ok(hr == E_INVALIDARG, "got %08x\n", hr);
337
338 hr = CreateStdDispatch(NULL, &test_unk, ti, &unk);
339 ok(hr == S_OK, "got %08x\n", hr);
340 IUnknown_Release(unk);
341
342 ITypeInfo_Release(ti);
343 }
344
345 START_TEST(dispatch)
346 {
347 test_DispGetParam();
348 test_CreateStdDispatch();
349 }