oleaut32: Unmarshalled safearray is always unlocked.
[wine] / dlls / oleaut32 / tests / 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 <wine/test.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <oaidl.h>
25
26 static const WCHAR szSunshine[] = {'S','u','n','s','h','i','n','e',0};
27
28 /* Temporary storage for ok_bstr. */
29 static CHAR temp_str[MAX_PATH];
30
31 #define ok_bstr(bstr, expected, format) \
32     do { \
33     WideCharToMultiByte(CP_ACP, 0, bstr, -1, temp_str, MAX_PATH, NULL, NULL); \
34     if (lstrcmpA(temp_str, expected) != 0) \
35         ok(0, format, expected, temp_str); \
36     } while(0);
37
38 #define INIT_DISPPARAMS(dp, args, named_args, num_args, num_named_args) \
39   dp.rgvarg = args; \
40   dp.rgdispidNamedArgs = named_args; \
41   dp.cArgs = num_args; \
42   dp.cNamedArgs = num_named_args; \
43
44 /* Initializes vararg with three values:
45  *  VT_I2 - 42
46  *  VT_I4 - 1234567890
47  *  VT_BSTR - "Sunshine"
48  */
49 #define INIT_VARARG(vararg) \
50   VariantInit(&vararg[0]); \
51   V_VT(&vararg[0]) = VT_I2; \
52   V_I2(&vararg[0]) = 42; \
53   VariantInit(&vararg[1]); \
54   V_VT(&vararg[1]) = VT_I4; \
55   V_I4(&vararg[1]) = 1234567890; \
56   VariantInit(&vararg[2]); \
57   V_VT(&vararg[2]) = VT_BSTR; \
58   V_BSTR(&vararg[2]) = SysAllocString(szSunshine);
59
60 /* Clears the vararg. */
61 #define CLEAR_VARARG(vararg) \
62   VariantClear(&vararg[0]); \
63   VariantClear(&vararg[1]); \
64   VariantClear(&vararg[2]);
65
66 static void test_DispGetParam(void)
67 {
68     HRESULT hr;
69     DISPPARAMS dispparams;
70     VARIANTARG vararg[3];
71     VARIANT result;
72     unsigned int err_index;
73
74     VariantInit(&result);
75
76     /* DispGetParam crashes on Windows if pdispparams is NULL. */
77
78     /* pdispparams has zero parameters. */
79     INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
80     VariantInit(&result);
81     err_index = 0xdeadbeef;
82     hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index);
83     ok(hr == DISP_E_PARAMNOTFOUND,
84        "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
85     ok(V_VT(&result) == VT_EMPTY,
86        "Expected VT_EMPTY, got %08x\n", V_VT(&result));
87     ok(err_index == 0xdeadbeef,
88        "Expected err_index to be unchanged, got %d\n", err_index);
89
90     /* pdispparams has zero parameters, position is invalid. */
91     INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
92     VariantInit(&result);
93     err_index = 0xdeadbeef;
94     hr = DispGetParam(&dispparams, 1, VT_I2, &result, &err_index);
95     ok(hr == DISP_E_PARAMNOTFOUND,
96        "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
97     ok(V_VT(&result) == VT_EMPTY,
98        "Expected VT_EMPTY, got %08x\n", V_VT(&result));
99     ok(err_index == 0xdeadbeef,
100        "Expected err_index to be unchanged, got %d\n", err_index);
101
102     /* pdispparams has zero parameters, pvarResult is NULL. */
103     INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
104     err_index = 0xdeadbeef;
105     hr = DispGetParam(&dispparams, 0, VT_I2, NULL, &err_index);
106     ok(hr == DISP_E_PARAMNOTFOUND,
107        "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
108     ok(err_index == 0xdeadbeef,
109        "Expected err_index to be unchanged, got %d\n", err_index);
110
111     /* pdispparams has zero parameters, puArgErr is NULL. */
112     INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0);
113     VariantInit(&result);
114     hr = DispGetParam(&dispparams, 0, VT_I2, &result, NULL);
115     ok(hr == DISP_E_PARAMNOTFOUND,
116        "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
117     ok(V_VT(&result) == VT_EMPTY,
118        "Expected VT_EMPTY, got %08x\n", V_VT(&result));
119
120     /* pdispparams.cArgs is 1, yet pdispparams.rgvarg is NULL. */
121     INIT_DISPPARAMS(dispparams, NULL, NULL, 1, 0);
122     VariantInit(&result);
123     err_index = 0xdeadbeef;
124     hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index);
125     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
126     ok(V_VT(&result) == VT_EMPTY,
127        "Expected VT_EMPTY, got %08x\n", V_VT(&result));
128     ok(err_index == 0, "Expected 0, got %d\n", err_index);
129
130     /* pdispparams.cNamedArgs is 1, yet pdispparams.rgdispidNamedArgs is NULL.
131      *
132      * This crashes on Windows.
133      */
134
135     /* {42, 1234567890, "Sunshine"} */
136     INIT_VARARG(vararg);
137
138     /* Get the first param.  position is end-based, so 2 is the first parameter
139      * of 3 parameters.
140      */
141     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
142     VariantInit(&result);
143     err_index = 0xdeadbeef;
144     hr = DispGetParam(&dispparams, 2, VT_I2, &result, &err_index);
145     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
146     ok(V_VT(&result) == VT_I2, "Expected VT_I2, got %08x\n", V_VT(&result));
147     ok(V_I2(&result) == 42, "Expected 42, got %d\n", V_I2(&result));
148     ok(err_index == 0xdeadbeef,
149        "Expected err_index to be unchanged, got %d\n", err_index);
150
151     /* Get the second param. */
152     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
153     VariantInit(&result);
154     err_index = 0xdeadbeef;
155     hr = DispGetParam(&dispparams, 1, VT_I4, &result, &err_index);
156     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
157     ok(V_VT(&result) == VT_I4, "Expected VT_I4, got %08x\n", V_VT(&result));
158     ok(V_I4(&result) == 1234567890,
159        "Expected 1234567890, got %d\n", V_I4(&result));
160     ok(err_index == 0xdeadbeef,
161        "Expected err_index to be unchanged, got %d\n", err_index);
162
163     /* Get the third param. */
164     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
165     VariantInit(&result);
166     err_index = 0xdeadbeef;
167     hr = DispGetParam(&dispparams, 0, VT_BSTR, &result, &err_index);
168     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
169     ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
170     ok_bstr(V_BSTR(&result), "Sunshine", "Expected %s, got %s\n");
171     ok(err_index == 0xdeadbeef,
172        "Expected err_index to be unchanged, got %d\n", err_index);
173     VariantClear(&result);
174
175     /* position is out of range. */
176     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
177     VariantInit(&result);
178     err_index = 0xdeadbeef;
179     hr = DispGetParam(&dispparams, 3, VT_I2, &result, &err_index);
180     ok(hr == DISP_E_PARAMNOTFOUND,
181        "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr);
182     ok(V_VT(&result) == VT_EMPTY,
183        "Expected VT_EMPTY, got %08x\n", V_VT(&result));
184     ok(err_index == 0xdeadbeef,
185        "Expected err_index to be unchanged, got %d\n", err_index);
186
187     /* pvarResult is NULL. */
188     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
189     err_index = 0xdeadbeef;
190     hr = DispGetParam(&dispparams, 2, VT_I2, NULL, &err_index);
191     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
192     ok(err_index == 0, "Expected 0, got %d\n", err_index);
193
194     /* puArgErr is NULL. */
195     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
196     VariantInit(&result);
197     hr = DispGetParam(&dispparams, 2, VT_I2, &result, NULL);
198     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
199     ok(V_VT(&result) == VT_I2, "Expected VT_I2, got %08x\n", V_VT(&result));
200     ok(V_I2(&result) == 42, "Expected 42, got %d\n", V_I2(&result));
201
202     /* Coerce the first param to VT_I4. */
203     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
204     VariantInit(&result);
205     err_index = 0xdeadbeef;
206     hr = DispGetParam(&dispparams, 2, VT_I4, &result, &err_index);
207     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
208     ok(V_VT(&result) == VT_I4, "Expected VT_I4, got %08x\n", V_VT(&result));
209     ok(V_I4(&result) == 42, "Expected 42, got %d\n", V_I4(&result));
210     ok(err_index == 0xdeadbeef,
211        "Expected err_index to be unchanged, got %d\n", err_index);
212
213     /* Coerce the first param to VT_BSTR. */
214     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
215     VariantInit(&result);
216     err_index = 0xdeadbeef;
217     hr = DispGetParam(&dispparams, 2, VT_BSTR, &result, &err_index);
218     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
219     ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
220     ok_bstr(V_BSTR(&result), "42", "Expected %s, got %s\n");
221     ok(err_index == 0xdeadbeef,
222        "Expected err_index to be unchanged, got %d\n", err_index);
223     VariantClear(&result);
224
225     /* Coerce the second (VT_I4) param to VT_I2. */
226     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
227     VariantInit(&result);
228     err_index = 0xdeadbeef;
229     hr = DispGetParam(&dispparams, 1, VT_I2, &result, &err_index);
230     ok(hr == DISP_E_OVERFLOW, "Expected DISP_E_OVERFLOW, got %08x\n", hr);
231     ok(V_VT(&result) == VT_EMPTY,
232        "Expected VT_EMPTY, got %08x\n", V_VT(&result));
233     ok(err_index == 1, "Expected 1, got %d\n", err_index);
234
235     /* Coerce the third (VT_BSTR) param to VT_I2. */
236     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
237     VariantInit(&result);
238     err_index = 0xdeadbeef;
239     hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index);
240     ok(hr == DISP_E_TYPEMISMATCH,
241        "Expected DISP_E_TYPEMISMATCH, got %08x\n", hr);
242     ok(V_VT(&result) == VT_EMPTY,
243        "Expected VT_EMPTY, got %08x\n", V_VT(&result));
244     ok(err_index == 2, "Expected 2, got %d\n", err_index);
245
246     /* Coerce the first parameter to an invalid type. */
247     INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0);
248     VariantInit(&result);
249     err_index = 0xdeadbeef;
250     hr = DispGetParam(&dispparams, 2, VT_ILLEGAL, &result, &err_index);
251     ok(hr == DISP_E_BADVARTYPE, "Expected DISP_E_BADVARTYPE, got %08x\n", hr);
252     ok(V_VT(&result) == VT_EMPTY,
253        "Expected VT_EMPTY, got %08x\n", V_VT(&result));
254     ok(err_index == 0, "Expected 0, got %d\n", err_index);
255
256     CLEAR_VARARG(vararg);
257
258     /* Coerce the first parameter, which is of type VT_EMPTY, to VT_BSTR. */
259     VariantInit(&vararg[0]);
260     INIT_DISPPARAMS(dispparams, vararg, NULL, 1, 0);
261     VariantInit(&result);
262     err_index = 0xdeadbeef;
263     hr = DispGetParam(&dispparams, 0, VT_BSTR, &result, &err_index);
264     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
265     ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result));
266     ok(err_index == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", err_index);
267     VariantClear(&result);
268 }
269
270 START_TEST(dispatch)
271 {
272     test_DispGetParam();
273 }