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 } 338