1 /* 2 * Copyright 2011 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #define COBJMACROS 20 #define CONST_VTABLE 21 22 #include <initguid.h> 23 #include <ole2.h> 24 #include <dispex.h> 25 26 #include "wshom.h" 27 #include "wine/test.h" 28 29 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); 30 31 #define EXPECT_HR(hr,hr_exp) \ 32 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp) 33 34 #define test_provideclassinfo(a, b) _test_provideclassinfo((IDispatch*)a, b, __LINE__) 35 static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line) 36 { 37 IProvideClassInfo *classinfo; 38 TYPEATTR *attr; 39 ITypeInfo *ti; 40 HRESULT hr; 41 42 hr = IDispatch_QueryInterface(disp, &IID_IProvideClassInfo, (void **)&classinfo); 43 ok_(__FILE__,line) (hr == S_OK, "Failed to get IProvideClassInfo, %#x.\n", hr); 44 45 hr = IProvideClassInfo_GetClassInfo(classinfo, &ti); 46 ok_(__FILE__,line) (hr == S_OK, "GetClassInfo() failed, %#x.\n", hr); 47 48 hr = ITypeInfo_GetTypeAttr(ti, &attr); 49 ok_(__FILE__,line) (hr == S_OK, "GetTypeAttr() failed, %#x.\n", hr); 50 51 ok_(__FILE__,line) (IsEqualGUID(&attr->guid, guid), "Unexpected typeinfo %s, expected %s\n", wine_dbgstr_guid(&attr->guid), 52 wine_dbgstr_guid(guid)); 53 54 IProvideClassInfo_Release(classinfo); 55 ITypeInfo_ReleaseTypeAttr(ti, attr); 56 ITypeInfo_Release(ti); 57 } 58 59 #define CHECK_BSTR_LENGTH(str) check_bstr_length(str, __LINE__) 60 static void check_bstr_length(BSTR str, int line) 61 { 62 ok_(__FILE__, line)(SysStringLen(str) == lstrlenW(str), "Unexpected string length %u vs %u.\n", 63 SysStringLen(str), lstrlenW(str)); 64 } 65 66 static void test_wshshell(void) 67 { 68 static const WCHAR notepadW[] = {'n','o','t','e','p','a','d','.','e','x','e',0}; 69 static const WCHAR desktopW[] = {'D','e','s','k','t','o','p',0}; 70 static const WCHAR lnk1W[] = {'f','i','l','e','.','l','n','k',0}; 71 static const WCHAR pathW[] = {'%','P','A','T','H','%',0}; 72 static const WCHAR sysW[] = {'S','Y','S','T','E','M',0}; 73 static const WCHAR path2W[] = {'P','A','T','H',0}; 74 static const WCHAR dummydirW[] = {'d','e','a','d','p','a','r','r','o','t',0}; 75 static const WCHAR emptyW[] = {'e','m','p','t','y',0}; 76 static const WCHAR cmdexeW[] = {'\\','c','m','d','.','e','x','e',0}; 77 static const WCHAR testdirW[] = {'w','s','h','o','m',' ','t','e','s','t',' ','d','i','r',0}; 78 static const WCHAR paramsW[] = 79 {' ','/','c',' ','r','d',' ','/','s',' ','/','q',' ','c',':','\\','n','o','s','u','c','h','d','i','r',0}; 80 static const WCHAR cmdW[] = 81 {'c','m','d','.','e','x','e',' ','/','c',' ','r','d',' ','/','s',' ','/','q',' ','c',':','\\', 82 'n','o','s','u','c','h','d','i','r',0}; 83 static const WCHAR cmd2W[] = 84 {'"','c','m','d','.','e','x','e',' ','"',' ','/','c',' ','r','d',' ','/','s',' ','/','q',' ','c',':','\\', 85 'n','o','s','u','c','h','d','i','r',0}; 86 WCHAR path[MAX_PATH], path2[MAX_PATH], buf[MAX_PATH]; 87 IWshEnvironment *env; 88 IWshExec *shexec; 89 IWshShell3 *sh3; 90 IDispatchEx *dispex; 91 IWshCollection *coll; 92 IDispatch *disp, *shortcut; 93 IUnknown *shell, *unk; 94 IFolderCollection *folders; 95 IWshShortcut *shcut; 96 ITypeInfo *ti; 97 HRESULT hr; 98 TYPEATTR *tattr; 99 DISPPARAMS dp; 100 EXCEPINFO ei; 101 VARIANT arg, res, arg2; 102 BSTR str, ret; 103 DWORD retval, attrs; 104 UINT err; 105 106 hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, 107 &IID_IDispatch, (void**)&disp); 108 ok(hr == S_OK, "got 0x%08x\n", hr); 109 110 hr = IDispatch_QueryInterface(disp, &IID_IWshShell3, (void**)&shell); 111 EXPECT_HR(hr, S_OK); 112 test_provideclassinfo(disp, &IID_IWshShell3); 113 114 hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); 115 EXPECT_HR(hr, E_NOINTERFACE); 116 IDispatch_Release(disp); 117 118 hr = IUnknown_QueryInterface(shell, &IID_IWshShell3, (void**)&sh3); 119 EXPECT_HR(hr, S_OK); 120 121 hr = IWshShell3_QueryInterface(sh3, &IID_IObjectWithSite, (void**)&unk); 122 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); 123 124 hr = IWshShell3_QueryInterface(sh3, &IID_IWshShell, (void**)&unk); 125 ok(hr == S_OK, "got 0x%08x\n", hr); 126 IUnknown_Release(unk); 127 128 hr = IWshShell3_QueryInterface(sh3, &IID_IWshShell2, (void**)&unk); 129 ok(hr == S_OK, "got 0x%08x\n", hr); 130 IUnknown_Release(unk); 131 132 hr = IWshShell3_get_SpecialFolders(sh3, &coll); 133 EXPECT_HR(hr, S_OK); 134 test_provideclassinfo(coll, &IID_IWshCollection); 135 136 hr = IWshCollection_QueryInterface(coll, &IID_IFolderCollection, (void**)&folders); 137 EXPECT_HR(hr, E_NOINTERFACE); 138 139 hr = IWshCollection_QueryInterface(coll, &IID_IDispatch, (void**)&disp); 140 EXPECT_HR(hr, S_OK); 141 142 hr = IDispatch_GetTypeInfo(disp, 0, 0, &ti); 143 EXPECT_HR(hr, S_OK); 144 145 hr = ITypeInfo_GetTypeAttr(ti, &tattr); 146 EXPECT_HR(hr, S_OK); 147 ok(IsEqualIID(&tattr->guid, &IID_IWshCollection), "got wrong type guid\n"); 148 ITypeInfo_ReleaseTypeAttr(ti, tattr); 149 150 /* try to call Item() with normal IDispatch procedure */ 151 str = SysAllocString(desktopW); 152 V_VT(&arg) = VT_BSTR; 153 V_BSTR(&arg) = str; 154 dp.rgvarg = &arg; 155 dp.rgdispidNamedArgs = NULL; 156 dp.cArgs = 1; 157 dp.cNamedArgs = 0; 158 hr = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, 1033, DISPATCH_PROPERTYGET, &dp, &res, &ei, &err); 159 EXPECT_HR(hr, DISP_E_MEMBERNOTFOUND); 160 161 /* try Item() directly, it returns directory path apparently */ 162 V_VT(&res) = VT_EMPTY; 163 hr = IWshCollection_Item(coll, &arg, &res); 164 EXPECT_HR(hr, S_OK); 165 ok(V_VT(&res) == VT_BSTR, "got res type %d\n", V_VT(&res)); 166 CHECK_BSTR_LENGTH(V_BSTR(&res)); 167 SysFreeString(str); 168 VariantClear(&res); 169 170 /* CreateShortcut() */ 171 str = SysAllocString(lnk1W); 172 hr = IWshShell3_CreateShortcut(sh3, str, &shortcut); 173 EXPECT_HR(hr, S_OK); 174 SysFreeString(str); 175 hr = IDispatch_QueryInterface(shortcut, &IID_IWshShortcut, (void**)&shcut); 176 EXPECT_HR(hr, S_OK); 177 test_provideclassinfo(shortcut, &IID_IWshShortcut); 178 179 hr = IWshShortcut_get_Arguments(shcut, NULL); 180 ok(hr == E_POINTER, "got 0x%08x\n", hr); 181 182 hr = IWshShortcut_get_IconLocation(shcut, NULL); 183 ok(hr == E_POINTER, "got 0x%08x\n", hr); 184 185 IWshShortcut_Release(shcut); 186 IDispatch_Release(shortcut); 187 188 /* ExpandEnvironmentStrings */ 189 hr = IWshShell3_ExpandEnvironmentStrings(sh3, NULL, NULL); 190 ok(hr == E_POINTER, "got 0x%08x\n", hr); 191 192 str = SysAllocString(pathW); 193 hr = IWshShell3_ExpandEnvironmentStrings(sh3, str, NULL); 194 ok(hr == E_POINTER, "got 0x%08x\n", hr); 195 SysFreeString(str); 196 197 V_VT(&arg) = VT_BSTR; 198 V_BSTR(&arg) = SysAllocString(sysW); 199 hr = IWshShell3_get_Environment(sh3, &arg, &env); 200 ok(hr == S_OK, "got 0x%08x\n", hr); 201 VariantClear(&arg); 202 203 hr = IWshEnvironment_get_Item(env, NULL, NULL); 204 ok(hr == E_POINTER, "got 0x%08x\n", hr); 205 test_provideclassinfo(env, &IID_IWshEnvironment); 206 207 ret = (BSTR)0x1; 208 hr = IWshEnvironment_get_Item(env, NULL, &ret); 209 ok(hr == S_OK, "got 0x%08x\n", hr); 210 ok(ret && !*ret, "got %p\n", ret); 211 SysFreeString(ret); 212 213 /* invalid var name */ 214 str = SysAllocString(lnk1W); 215 hr = IWshEnvironment_get_Item(env, str, NULL); 216 ok(hr == E_POINTER, "got 0x%08x\n", hr); 217 218 ret = NULL; 219 hr = IWshEnvironment_get_Item(env, str, &ret); 220 ok(hr == S_OK, "got 0x%08x\n", hr); 221 ok(ret && *ret == 0, "got %s\n", wine_dbgstr_w(ret)); 222 CHECK_BSTR_LENGTH(ret); 223 SysFreeString(ret); 224 SysFreeString(str); 225 226 /* valid name */ 227 str = SysAllocString(path2W); 228 hr = IWshEnvironment_get_Item(env, str, &ret); 229 ok(hr == S_OK, "got 0x%08x\n", hr); 230 ok(ret && *ret != 0, "got %s\n", wine_dbgstr_w(ret)); 231 CHECK_BSTR_LENGTH(ret); 232 SysFreeString(ret); 233 SysFreeString(str); 234 235 IWshEnvironment_Release(env); 236 237 V_VT(&arg) = VT_I2; 238 V_I2(&arg) = 0; 239 V_VT(&arg2) = VT_ERROR; 240 V_ERROR(&arg2) = DISP_E_PARAMNOTFOUND; 241 242 str = SysAllocString(notepadW); 243 hr = IWshShell3_Run(sh3, str, &arg, &arg2, NULL); 244 ok(hr == E_POINTER, "got 0x%08x\n", hr); 245 246 retval = 10; 247 hr = IWshShell3_Run(sh3, str, NULL, &arg2, &retval); 248 ok(hr == E_POINTER, "got 0x%08x\n", hr); 249 ok(retval == 10, "got %u\n", retval); 250 251 retval = 10; 252 hr = IWshShell3_Run(sh3, str, &arg, NULL, &retval); 253 ok(hr == E_POINTER, "got 0x%08x\n", hr); 254 ok(retval == 10, "got %u\n", retval); 255 256 retval = 10; 257 V_VT(&arg2) = VT_ERROR; 258 V_ERROR(&arg2) = 0; 259 hr = IWshShell3_Run(sh3, str, &arg, &arg2, &retval); 260 ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr); 261 ok(retval == 10, "got %u\n", retval); 262 SysFreeString(str); 263 264 V_VT(&arg2) = VT_BOOL; 265 V_BOOL(&arg2) = VARIANT_TRUE; 266 267 retval = 0xdeadbeef; 268 str = SysAllocString(cmdW); 269 hr = IWshShell3_Run(sh3, str, &arg, &arg2, &retval); 270 ok(hr == S_OK, "got 0x%08x\n", hr); 271 todo_wine ok(retval == ERROR_FILE_NOT_FOUND, "got %u\n", retval); 272 SysFreeString(str); 273 274 retval = 0xdeadbeef; 275 str = SysAllocString(cmd2W); 276 hr = IWshShell3_Run(sh3, str, &arg, &arg2, &retval); 277 ok(hr == S_OK, "got 0x%08x\n", hr); 278 todo_wine ok(retval == ERROR_FILE_NOT_FOUND, "got %u\n", retval); 279 SysFreeString(str); 280 281 GetSystemDirectoryW(path, ARRAY_SIZE(path)); 282 lstrcatW(path, cmdexeW); 283 attrs = GetFileAttributesW(path); 284 ok(attrs != INVALID_FILE_ATTRIBUTES, "cmd.exe not found\n"); 285 286 /* copy cmd.exe to a path with spaces */ 287 GetTempPathW(ARRAY_SIZE(path2), path2); 288 lstrcatW(path2, testdirW); 289 CreateDirectoryW(path2, NULL); 290 lstrcatW(path2, cmdexeW); 291 CopyFileW(path, path2, FALSE); 292 293 buf[0] = '"'; 294 lstrcpyW(buf + 1, path2); 295 buf[lstrlenW(buf)] = '"'; 296 lstrcpyW(buf + lstrlenW(path2) + 2, paramsW); 297 298 retval = 0xdeadbeef; 299 str = SysAllocString(buf); 300 hr = IWshShell3_Run(sh3, str, &arg, &arg2, &retval); 301 ok(hr == S_OK, "got 0x%08x\n", hr); 302 todo_wine ok(retval == ERROR_FILE_NOT_FOUND, "got %u\n", retval); 303 SysFreeString(str); 304 305 DeleteFileW(path2); 306 path2[lstrlenW(path2) - lstrlenW(cmdexeW)] = 0; 307 RemoveDirectoryW(path2); 308 309 /* current directory */ 310 if (0) /* crashes on native */ 311 hr = IWshShell3_get_CurrentDirectory(sh3, NULL); 312 313 str = NULL; 314 hr = IWshShell3_get_CurrentDirectory(sh3, &str); 315 ok(hr == S_OK, "got 0x%08x\n", hr); 316 ok(str && str[0] != 0, "got empty string\n"); 317 CHECK_BSTR_LENGTH(str); 318 SysFreeString(str); 319 320 hr = IWshShell3_put_CurrentDirectory(sh3, NULL); 321 ok(hr == E_INVALIDARG || 322 broken(hr == HRESULT_FROM_WIN32(ERROR_NOACCESS)), "got 0x%08x\n", hr); 323 324 str = SysAllocString(emptyW); 325 hr = IWshShell3_put_CurrentDirectory(sh3, str); 326 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 327 SysFreeString(str); 328 329 str = SysAllocString(dummydirW); 330 hr = IWshShell3_put_CurrentDirectory(sh3, str); 331 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 332 SysFreeString(str); 333 334 /* Exec */ 335 hr = IWshShell3_Exec(sh3, NULL, NULL); 336 ok(hr == E_POINTER, "got 0x%08x\n", hr); 337 338 hr = IWshShell3_Exec(sh3, NULL, &shexec); 339 ok(hr == DISP_E_EXCEPTION, "got 0x%08x\n", hr); 340 341 str = SysAllocString(emptyW); 342 hr = IWshShell3_Exec(sh3, str, &shexec); 343 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 344 SysFreeString(str); 345 346 IWshCollection_Release(coll); 347 IDispatch_Release(disp); 348 IWshShell3_Release(sh3); 349 IUnknown_Release(shell); 350 } 351 352 /* delete key and all its subkeys */ 353 static DWORD delete_key(HKEY hkey) 354 { 355 char name[MAX_PATH]; 356 DWORD ret; 357 358 while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name)))) { 359 HKEY tmp; 360 if (!(ret = RegOpenKeyExA(hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp))) { 361 ret = delete_key(tmp); 362 RegCloseKey(tmp); 363 } 364 if (ret) break; 365 } 366 if (ret != ERROR_NO_MORE_ITEMS) return ret; 367 RegDeleteKeyA(hkey, ""); 368 return 0; 369 } 370 371 static void test_registry(void) 372 { 373 static const WCHAR keypathW[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\', 374 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t','\\',0}; 375 static const WCHAR regsz2W[] = {'r','e','g','s','z','2',0}; 376 static const WCHAR regszW[] = {'r','e','g','s','z',0}; 377 static const WCHAR regdwordW[] = {'r','e','g','d','w','o','r','d',0}; 378 static const WCHAR regbinaryW[] = {'r','e','g','b','i','n','a','r','y',0}; 379 static const WCHAR regmultiszW[] = {'r','e','g','m','u','l','t','i','s','z',0}; 380 381 static const WCHAR regsz1W[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\', 382 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t','\\','r','e','g','s','z','1',0}; 383 static const WCHAR foobarW[] = {'f','o','o','b','a','r',0}; 384 static const WCHAR fooW[] = {'f','o','o',0}; 385 static const WCHAR brokenW[] = {'H','K','E','Y','_','b','r','o','k','e','n','_','k','e','y',0}; 386 static const WCHAR broken2W[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','a',0}; 387 WCHAR pathW[MAX_PATH]; 388 DWORD dwvalue, type; 389 VARIANT value, v; 390 IWshShell3 *sh3; 391 VARTYPE vartype; 392 LONG bound; 393 HRESULT hr; 394 BSTR name; 395 HKEY root; 396 LONG ret; 397 UINT dim; 398 399 hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, 400 &IID_IWshShell3, (void**)&sh3); 401 ok(hr == S_OK, "got 0x%08x\n", hr); 402 403 /* RegRead() */ 404 V_VT(&value) = VT_I2; 405 hr = IWshShell3_RegRead(sh3, NULL, &value); 406 ok(hr == E_POINTER, "got 0x%08x\n", hr); 407 ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value)); 408 409 name = SysAllocString(brokenW); 410 hr = IWshShell3_RegRead(sh3, name, NULL); 411 ok(hr == E_POINTER, "got 0x%08x\n", hr); 412 V_VT(&value) = VT_I2; 413 hr = IWshShell3_RegRead(sh3, name, &value); 414 ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "got 0x%08x\n", hr); 415 ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value)); 416 SysFreeString(name); 417 418 name = SysAllocString(broken2W); 419 V_VT(&value) = VT_I2; 420 hr = IWshShell3_RegRead(sh3, name, &value); 421 ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "got 0x%08x\n", hr); 422 ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value)); 423 SysFreeString(name); 424 425 ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &root); 426 ok(ret == 0, "got %d\n", ret); 427 428 ret = RegSetValueExA(root, "regsz", 0, REG_SZ, (const BYTE*)"foobar", 7); 429 ok(ret == 0, "got %d\n", ret); 430 431 ret = RegSetValueExA(root, "regsz2", 0, REG_SZ, (const BYTE*)"foobar\0f", 9); 432 ok(ret == 0, "got %d\n", ret); 433 434 ret = RegSetValueExA(root, "regmultisz", 0, REG_MULTI_SZ, (const BYTE*)"foo\0bar\0", 9); 435 ok(ret == 0, "got %d\n", ret); 436 437 dwvalue = 10; 438 ret = RegSetValueExA(root, "regdword", 0, REG_DWORD, (const BYTE*)&dwvalue, sizeof(dwvalue)); 439 ok(ret == 0, "got %d\n", ret); 440 441 dwvalue = 11; 442 ret = RegSetValueExA(root, "regbinary", 0, REG_BINARY, (const BYTE*)&dwvalue, sizeof(dwvalue)); 443 ok(ret == 0, "got %d\n", ret); 444 445 /* REG_SZ */ 446 lstrcpyW(pathW, keypathW); 447 lstrcatW(pathW, regszW); 448 name = SysAllocString(pathW); 449 VariantInit(&value); 450 hr = IWshShell3_RegRead(sh3, name, &value); 451 ok(hr == S_OK, "got 0x%08x\n", hr); 452 ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value)); 453 ok(!lstrcmpW(V_BSTR(&value), foobarW), "got %s\n", wine_dbgstr_w(V_BSTR(&value))); 454 CHECK_BSTR_LENGTH(V_BSTR(&value)); 455 VariantClear(&value); 456 SysFreeString(name); 457 458 /* REG_SZ with embedded NULL */ 459 lstrcpyW(pathW, keypathW); 460 lstrcatW(pathW, regsz2W); 461 name = SysAllocString(pathW); 462 VariantInit(&value); 463 hr = IWshShell3_RegRead(sh3, name, &value); 464 ok(hr == S_OK, "got 0x%08x\n", hr); 465 ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value)); 466 ok(SysStringLen(V_BSTR(&value)) == 6, "len %d\n", SysStringLen(V_BSTR(&value))); 467 CHECK_BSTR_LENGTH(V_BSTR(&value)); 468 VariantClear(&value); 469 SysFreeString(name); 470 471 /* REG_DWORD */ 472 lstrcpyW(pathW, keypathW); 473 lstrcatW(pathW, regdwordW); 474 name = SysAllocString(pathW); 475 VariantInit(&value); 476 hr = IWshShell3_RegRead(sh3, name, &value); 477 ok(hr == S_OK, "got 0x%08x\n", hr); 478 ok(V_VT(&value) == VT_I4, "got %d\n", V_VT(&value)); 479 ok(V_I4(&value) == 10, "got %d\n", V_I4(&value)); 480 SysFreeString(name); 481 482 /* REG_BINARY */ 483 lstrcpyW(pathW, keypathW); 484 lstrcatW(pathW, regbinaryW); 485 name = SysAllocString(pathW); 486 VariantInit(&value); 487 hr = IWshShell3_RegRead(sh3, name, &value); 488 ok(hr == S_OK, "got 0x%08x\n", hr); 489 ok(V_VT(&value) == (VT_ARRAY|VT_VARIANT), "got 0x%x\n", V_VT(&value)); 490 dim = SafeArrayGetDim(V_ARRAY(&value)); 491 ok(dim == 1, "got %u\n", dim); 492 493 hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &bound); 494 ok(hr == S_OK, "got 0x%08x\n", hr); 495 ok(bound == 0, "got %u\n", bound); 496 497 hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &bound); 498 ok(hr == S_OK, "got 0x%08x\n", hr); 499 ok(bound == 3, "got %u\n", bound); 500 501 hr = SafeArrayGetVartype(V_ARRAY(&value), &vartype); 502 ok(hr == S_OK, "got 0x%08x\n", hr); 503 ok(vartype == VT_VARIANT, "got %d\n", vartype); 504 505 bound = 0; 506 hr = SafeArrayGetElement(V_ARRAY(&value), &bound, &v); 507 ok(hr == S_OK, "got 0x%08x\n", hr); 508 ok(V_VT(&v) == VT_UI1, "got %d\n", V_VT(&v)); 509 ok(V_UI1(&v) == 11, "got %u\n", V_UI1(&v)); 510 VariantClear(&v); 511 VariantClear(&value); 512 SysFreeString(name); 513 514 /* REG_MULTI_SZ */ 515 lstrcpyW(pathW, keypathW); 516 lstrcatW(pathW, regmultiszW); 517 name = SysAllocString(pathW); 518 VariantInit(&value); 519 hr = IWshShell3_RegRead(sh3, name, &value); 520 ok(hr == S_OK, "got 0x%08x\n", hr); 521 ok(V_VT(&value) == (VT_ARRAY|VT_VARIANT), "got 0x%x\n", V_VT(&value)); 522 SysFreeString(name); 523 524 dim = SafeArrayGetDim(V_ARRAY(&value)); 525 ok(dim == 1, "got %u\n", dim); 526 527 hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &bound); 528 ok(hr == S_OK, "got 0x%08x\n", hr); 529 ok(bound == 0, "got %u\n", bound); 530 531 hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &bound); 532 ok(hr == S_OK, "got 0x%08x\n", hr); 533 ok(bound == 1, "got %u\n", bound); 534 535 hr = SafeArrayGetVartype(V_ARRAY(&value), &vartype); 536 ok(hr == S_OK, "got 0x%08x\n", hr); 537 ok(vartype == VT_VARIANT, "got %d\n", vartype); 538 539 bound = 0; 540 hr = SafeArrayGetElement(V_ARRAY(&value), &bound, &v); 541 ok(hr == S_OK, "got 0x%08x\n", hr); 542 ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v)); 543 ok(!lstrcmpW(V_BSTR(&v), fooW), "got %s\n", wine_dbgstr_w(V_BSTR(&v))); 544 CHECK_BSTR_LENGTH(V_BSTR(&v)); 545 VariantClear(&v); 546 VariantClear(&value); 547 548 name = SysAllocString(regsz1W); 549 V_VT(&value) = VT_I2; 550 hr = IWshShell3_RegRead(sh3, name, &value); 551 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 552 ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value)); 553 VariantClear(&value); 554 SysFreeString(name); 555 556 delete_key(root); 557 558 /* RegWrite() */ 559 ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &root); 560 ok(ret == 0, "got %d\n", ret); 561 562 hr = IWshShell3_RegWrite(sh3, NULL, NULL, NULL); 563 ok(hr == E_POINTER, "got 0x%08x\n", hr); 564 565 lstrcpyW(pathW, keypathW); 566 lstrcatW(pathW, regszW); 567 name = SysAllocString(pathW); 568 569 hr = IWshShell3_RegWrite(sh3, name, NULL, NULL); 570 ok(hr == E_POINTER, "got 0x%08x\n", hr); 571 572 VariantInit(&value); 573 hr = IWshShell3_RegWrite(sh3, name, &value, NULL); 574 ok(hr == E_POINTER, "got 0x%08x\n", hr); 575 576 hr = IWshShell3_RegWrite(sh3, name, &value, &value); 577 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 578 579 /* type is optional */ 580 V_VT(&v) = VT_ERROR; 581 V_ERROR(&v) = DISP_E_PARAMNOTFOUND; 582 hr = IWshShell3_RegWrite(sh3, name, &value, &v); 583 ok(hr == S_OK, "got 0x%08x\n", hr); 584 585 /* default type is REG_SZ */ 586 V_VT(&value) = VT_I4; 587 V_I4(&value) = 12; 588 hr = IWshShell3_RegWrite(sh3, name, &value, &v); 589 ok(hr == S_OK, "got 0x%08x\n", hr); 590 591 type = REG_NONE; 592 ret = RegQueryValueExA(root, "regsz", 0, &type, NULL, NULL); 593 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 594 ok(type == REG_SZ, "got %d\n", type); 595 596 ret = RegDeleteValueA(root, "regsz"); 597 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 598 V_VT(&value) = VT_BSTR; 599 V_BSTR(&value) = SysAllocString(regszW); 600 hr = IWshShell3_RegWrite(sh3, name, &value, &v); 601 ok(hr == S_OK, "got 0x%08x\n", hr); 602 VariantClear(&value); 603 604 type = REG_NONE; 605 ret = RegQueryValueExA(root, "regsz", 0, &type, NULL, NULL); 606 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 607 ok(type == REG_SZ, "got %d\n", type); 608 609 ret = RegDeleteValueA(root, "regsz"); 610 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 611 V_VT(&value) = VT_R4; 612 V_R4(&value) = 1.2; 613 hr = IWshShell3_RegWrite(sh3, name, &value, &v); 614 ok(hr == S_OK, "got 0x%08x\n", hr); 615 VariantClear(&value); 616 617 type = REG_NONE; 618 ret = RegQueryValueExA(root, "regsz", 0, &type, NULL, NULL); 619 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 620 ok(type == REG_SZ, "got %d\n", type); 621 622 ret = RegDeleteValueA(root, "regsz"); 623 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 624 V_VT(&value) = VT_R4; 625 V_R4(&value) = 1.2; 626 V_VT(&v) = VT_I2; 627 V_I2(&v) = 1; 628 hr = IWshShell3_RegWrite(sh3, name, &value, &v); 629 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 630 VariantClear(&value); 631 632 SysFreeString(name); 633 634 delete_key(root); 635 IWshShell3_Release(sh3); 636 } 637 638 static void test_popup(void) 639 { 640 static const WCHAR textW[] = {'T','e','x','t',0}; 641 VARIANT timeout, type, title, optional; 642 IWshShell *sh; 643 int button; 644 HRESULT hr; 645 BSTR text; 646 647 hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, 648 &IID_IWshShell, (void **)&sh); 649 ok(hr == S_OK, "Failed to create WshShell object, hr %#x.\n", hr); 650 651 button = 123; 652 text = SysAllocString(textW); 653 654 hr = IWshShell_Popup(sh, NULL, NULL, NULL, NULL, &button); 655 ok(hr == E_POINTER, "Unexpected retval %#x.\n", hr); 656 ok(button == 123, "Unexpected button id %d.\n", button); 657 658 hr = IWshShell_Popup(sh, text, NULL, NULL, NULL, &button); 659 ok(hr == E_POINTER, "Unexpected retval %#x.\n", hr); 660 ok(button == 123, "Unexpected button id %d.\n", button); 661 662 V_VT(&optional) = VT_ERROR; 663 V_ERROR(&optional) = DISP_E_PARAMNOTFOUND; 664 665 V_VT(&timeout) = VT_I2; 666 V_I2(&timeout) = 1; 667 668 V_VT(&type) = VT_I2; 669 V_I2(&type) = 1; 670 671 V_VT(&title) = VT_BSTR; 672 V_BSTR(&title) = NULL; 673 674 hr = IWshShell_Popup(sh, text, &timeout, &optional, &type, &button); 675 ok(hr == S_OK, "Unexpected retval %#x.\n", hr); 676 ok(button == -1, "Unexpected button id %d.\n", button); 677 678 hr = IWshShell_Popup(sh, text, &timeout, &title, &optional, &button); 679 ok(hr == S_OK, "Unexpected retval %#x.\n", hr); 680 ok(button == -1, "Unexpected button id %d.\n", button); 681 682 SysFreeString(text); 683 IWshShell_Release(sh); 684 } 685 686 START_TEST(wshom) 687 { 688 IUnknown *unk; 689 HRESULT hr; 690 691 CoInitialize(NULL); 692 693 hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, 694 &IID_IUnknown, (void**)&unk); 695 if (FAILED(hr)) { 696 win_skip("Could not create WshShell object: %08x\n", hr); 697 return; 698 } 699 IUnknown_Release(unk); 700 701 test_wshshell(); 702 test_registry(); 703 test_popup(); 704 705 CoUninitialize(); 706 } 707