/* * Dispatch test * * Copyright 2009 James Hawkins * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define WIN32_NO_STATUS #define _INC_WINDOWS #define COM_NO_WINDOWS_H #include //#include //#include #include #include //#include static const WCHAR szSunshine[] = {'S','u','n','s','h','i','n','e',0}; /* Temporary storage for ok_bstr. */ static CHAR temp_str[MAX_PATH]; #define ok_bstr(bstr, expected, format) \ do { \ WideCharToMultiByte(CP_ACP, 0, bstr, -1, temp_str, MAX_PATH, NULL, NULL); \ if (lstrcmpA(temp_str, expected) != 0) \ ok(0, format, expected, temp_str); \ } while(0); #define INIT_DISPPARAMS(dp, args, named_args, num_args, num_named_args) \ dp.rgvarg = args; \ dp.rgdispidNamedArgs = named_args; \ dp.cArgs = num_args; \ dp.cNamedArgs = num_named_args; \ /* Initializes vararg with three values: * VT_I2 - 42 * VT_I4 - 1234567890 * VT_BSTR - "Sunshine" */ #define INIT_VARARG(vararg) \ VariantInit(&vararg[0]); \ V_VT(&vararg[0]) = VT_I2; \ V_I2(&vararg[0]) = 42; \ VariantInit(&vararg[1]); \ V_VT(&vararg[1]) = VT_I4; \ V_I4(&vararg[1]) = 1234567890; \ VariantInit(&vararg[2]); \ V_VT(&vararg[2]) = VT_BSTR; \ V_BSTR(&vararg[2]) = SysAllocString(szSunshine); /* Clears the vararg. */ #define CLEAR_VARARG(vararg) \ VariantClear(&vararg[0]); \ VariantClear(&vararg[1]); \ VariantClear(&vararg[2]); static void test_DispGetParam(void) { HRESULT hr; DISPPARAMS dispparams; VARIANTARG vararg[3]; VARIANT result; unsigned int err_index; VariantInit(&result); /* DispGetParam crashes on Windows if pdispparams is NULL. */ /* pdispparams has zero parameters. */ INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index); ok(hr == DISP_E_PARAMNOTFOUND, "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr); ok(V_VT(&result) == VT_EMPTY, "Expected VT_EMPTY, got %08x\n", V_VT(&result)); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); /* pdispparams has zero parameters, position is invalid. */ INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 1, VT_I2, &result, &err_index); ok(hr == DISP_E_PARAMNOTFOUND, "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr); ok(V_VT(&result) == VT_EMPTY, "Expected VT_EMPTY, got %08x\n", V_VT(&result)); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); /* pdispparams has zero parameters, pvarResult is NULL. */ INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 0, VT_I2, NULL, &err_index); ok(hr == DISP_E_PARAMNOTFOUND, "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); /* pdispparams has zero parameters, puArgErr is NULL. */ INIT_DISPPARAMS(dispparams, NULL, NULL, 0, 0); VariantInit(&result); hr = DispGetParam(&dispparams, 0, VT_I2, &result, NULL); ok(hr == DISP_E_PARAMNOTFOUND, "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr); ok(V_VT(&result) == VT_EMPTY, "Expected VT_EMPTY, got %08x\n", V_VT(&result)); /* pdispparams.cArgs is 1, yet pdispparams.rgvarg is NULL. */ INIT_DISPPARAMS(dispparams, NULL, NULL, 1, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index); ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); ok(V_VT(&result) == VT_EMPTY, "Expected VT_EMPTY, got %08x\n", V_VT(&result)); ok(err_index == 0, "Expected 0, got %d\n", err_index); /* pdispparams.cNamedArgs is 1, yet pdispparams.rgdispidNamedArgs is NULL. * * This crashes on Windows. */ /* {42, 1234567890, "Sunshine"} */ INIT_VARARG(vararg); /* Get the first param. position is end-based, so 2 is the first parameter * of 3 parameters. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 2, VT_I2, &result, &err_index); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(V_VT(&result) == VT_I2, "Expected VT_I2, got %08x\n", V_VT(&result)); ok(V_I2(&result) == 42, "Expected 42, got %d\n", V_I2(&result)); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); /* Get the second param. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 1, VT_I4, &result, &err_index); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(V_VT(&result) == VT_I4, "Expected VT_I4, got %08x\n", V_VT(&result)); ok(V_I4(&result) == 1234567890, "Expected 1234567890, got %d\n", V_I4(&result)); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); /* Get the third param. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 0, VT_BSTR, &result, &err_index); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result)); ok_bstr(V_BSTR(&result), "Sunshine", "Expected %s, got %s\n"); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); VariantClear(&result); /* position is out of range. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 3, VT_I2, &result, &err_index); ok(hr == DISP_E_PARAMNOTFOUND, "Expected DISP_E_PARAMNOTFOUND, got %08x\n", hr); ok(V_VT(&result) == VT_EMPTY, "Expected VT_EMPTY, got %08x\n", V_VT(&result)); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); /* pvarResult is NULL. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 2, VT_I2, NULL, &err_index); ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); ok(err_index == 0, "Expected 0, got %d\n", err_index); /* puArgErr is NULL. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); hr = DispGetParam(&dispparams, 2, VT_I2, &result, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(V_VT(&result) == VT_I2, "Expected VT_I2, got %08x\n", V_VT(&result)); ok(V_I2(&result) == 42, "Expected 42, got %d\n", V_I2(&result)); /* Coerce the first param to VT_I4. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 2, VT_I4, &result, &err_index); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(V_VT(&result) == VT_I4, "Expected VT_I4, got %08x\n", V_VT(&result)); ok(V_I4(&result) == 42, "Expected 42, got %d\n", V_I4(&result)); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); /* Coerce the first param to VT_BSTR. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 2, VT_BSTR, &result, &err_index); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result)); ok_bstr(V_BSTR(&result), "42", "Expected %s, got %s\n"); ok(err_index == 0xdeadbeef, "Expected err_index to be unchanged, got %d\n", err_index); VariantClear(&result); /* Coerce the second (VT_I4) param to VT_I2. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 1, VT_I2, &result, &err_index); ok(hr == DISP_E_OVERFLOW, "Expected DISP_E_OVERFLOW, got %08x\n", hr); ok(V_VT(&result) == VT_EMPTY, "Expected VT_EMPTY, got %08x\n", V_VT(&result)); ok(err_index == 1, "Expected 1, got %d\n", err_index); /* Coerce the third (VT_BSTR) param to VT_I2. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 0, VT_I2, &result, &err_index); ok(hr == DISP_E_TYPEMISMATCH, "Expected DISP_E_TYPEMISMATCH, got %08x\n", hr); ok(V_VT(&result) == VT_EMPTY, "Expected VT_EMPTY, got %08x\n", V_VT(&result)); ok(err_index == 2, "Expected 2, got %d\n", err_index); /* Coerce the first parameter to an invalid type. */ INIT_DISPPARAMS(dispparams, vararg, NULL, 3, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 2, VT_ILLEGAL, &result, &err_index); ok(hr == DISP_E_BADVARTYPE, "Expected DISP_E_BADVARTYPE, got %08x\n", hr); ok(V_VT(&result) == VT_EMPTY, "Expected VT_EMPTY, got %08x\n", V_VT(&result)); ok(err_index == 0, "Expected 0, got %d\n", err_index); CLEAR_VARARG(vararg); /* Coerce the first parameter, which is of type VT_EMPTY, to VT_BSTR. */ VariantInit(&vararg[0]); INIT_DISPPARAMS(dispparams, vararg, NULL, 1, 0); VariantInit(&result); err_index = 0xdeadbeef; hr = DispGetParam(&dispparams, 0, VT_BSTR, &result, &err_index); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(V_VT(&result) == VT_BSTR, "Expected VT_BSTR, got %08x\n", V_VT(&result)); ok(err_index == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", err_index); VariantClear(&result); } START_TEST(dispatch) { test_DispGetParam(); }