1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Testing ShellExecuteEx 5 * PROGRAMMER: Yaroslav Veremenko <yaroslav@veremenko.info> 6 * Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 7 */ 8 9 #include "shelltest.h" 10 #include <pstypes.h> 11 #include <psfuncs.h> 12 #include <stdlib.h> 13 #include <stdio.h> 14 #include <strsafe.h> 15 #include <versionhelpers.h> 16 17 static WCHAR s_win_dir[MAX_PATH]; 18 static WCHAR s_sys_dir[MAX_PATH]; 19 static WCHAR s_win_notepad[MAX_PATH]; 20 static WCHAR s_sys_notepad[MAX_PATH]; 21 static WCHAR s_win_test_exe[MAX_PATH]; 22 static WCHAR s_sys_test_exe[MAX_PATH]; 23 static WCHAR s_win_bat_file[MAX_PATH]; 24 static WCHAR s_sys_bat_file[MAX_PATH]; 25 static WCHAR s_win_txt_file[MAX_PATH]; 26 static WCHAR s_sys_txt_file[MAX_PATH]; 27 static WCHAR s_win_notepad_cmdline[MAX_PATH]; 28 static WCHAR s_sys_notepad_cmdline[MAX_PATH]; 29 static WCHAR s_win_test_exe_cmdline[MAX_PATH]; 30 static WCHAR s_sys_test_exe_cmdline[MAX_PATH]; 31 static BOOL s_bWow64; 32 33 #define REG_APPPATHS L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" 34 35 typedef enum TEST_RESULT 36 { 37 TEST_FAILED, 38 TEST_SUCCESS_NO_PROCESS, 39 TEST_SUCCESS_WITH_PROCESS, 40 } TEST_RESULT; 41 42 typedef struct TEST_ENTRY 43 { 44 INT line; 45 TEST_RESULT result; 46 LPCWSTR lpFile; 47 LPCWSTR cmdline; 48 } TEST_ENTRY, *PTEST_ENTRY; 49 50 static void 51 TEST_DoTestEntry(INT line, TEST_RESULT result, LPCWSTR lpFile, LPCWSTR cmdline = NULL); 52 53 static void TEST_DoTestEntries(void) 54 { 55 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, NULL); 56 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L""); 57 TEST_DoTestEntry(__LINE__, TEST_FAILED, L"This is an invalid path."); 58 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, s_sys_bat_file, NULL); 59 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, s_sys_test_exe, s_sys_test_exe_cmdline); 60 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, s_sys_txt_file, NULL); 61 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, s_win_bat_file, NULL); 62 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, s_win_notepad, s_win_notepad_cmdline); 63 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, s_win_test_exe, s_win_test_exe_cmdline); 64 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, s_win_txt_file, NULL); 65 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, L"notepad", s_sys_notepad_cmdline); 66 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, L"notepad.exe", s_sys_notepad_cmdline); 67 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, L"\"notepad.exe\"", s_sys_notepad_cmdline); 68 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, L"\"notepad\"", s_sys_notepad_cmdline); 69 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, L"test program.exe", s_sys_test_exe_cmdline); 70 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, L"\"test program.exe\"", s_sys_test_exe_cmdline); 71 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, s_win_dir); 72 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, s_sys_dir); 73 TEST_DoTestEntry(__LINE__, TEST_FAILED, L"shell:ThisIsAnInvalidName"); 74 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"); // My Computer 75 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"); // My Computer (with shell:) 76 77 if (!IsWindowsVistaOrGreater()) 78 { 79 WCHAR szCurDir[MAX_PATH]; 80 GetCurrentDirectoryW(_countof(szCurDir), szCurDir); 81 SetCurrentDirectoryW(s_sys_dir); 82 TEST_DoTestEntry(__LINE__, TEST_FAILED, L"::{21EC2020-3AEA-1069-A2DD-08002B30309D}"); // Control Panel (without path) 83 SetCurrentDirectoryW(szCurDir); 84 } 85 86 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"); // Control Panel (with path) 87 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"); // Control Panel (with path and shell:) 88 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:AppData"); 89 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Common Desktop"); 90 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Common Programs"); 91 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Common Start Menu"); 92 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Common StartUp"); 93 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:ControlPanelFolder"); 94 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Desktop"); 95 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Favorites"); 96 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Fonts"); 97 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Local AppData"); 98 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:My Pictures"); 99 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Personal"); 100 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Programs"); 101 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Recent"); 102 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:RecycleBinFolder"); 103 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:SendTo"); 104 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:Start Menu"); 105 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_NO_PROCESS, L"shell:StartUp"); 106 } 107 108 static LPWSTR 109 getCommandLineFromProcess(HANDLE hProcess) 110 { 111 PEB peb; 112 PROCESS_BASIC_INFORMATION info; 113 RTL_USER_PROCESS_PARAMETERS Params; 114 NTSTATUS Status; 115 BOOL ret; 116 117 Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &info, sizeof(info), NULL); 118 ok_ntstatus(Status, STATUS_SUCCESS); 119 120 ret = ReadProcessMemory(hProcess, info.PebBaseAddress, &peb, sizeof(peb), NULL); 121 if (!ret) 122 trace("ReadProcessMemory failed (%ld)\n", GetLastError()); 123 124 ReadProcessMemory(hProcess, peb.ProcessParameters, &Params, sizeof(Params), NULL); 125 if (!ret) 126 trace("ReadProcessMemory failed (%ld)\n", GetLastError()); 127 128 LPWSTR cmdline = Params.CommandLine.Buffer; 129 if (!cmdline) 130 trace("!cmdline\n"); 131 132 SIZE_T cbCmdLine = Params.CommandLine.Length; 133 if (!cbCmdLine) 134 trace("!cbCmdLine\n"); 135 136 LPWSTR pszBuffer = (LPWSTR)calloc(cbCmdLine + sizeof(WCHAR), 1); 137 if (!pszBuffer) 138 trace("!pszBuffer\n"); 139 140 ret = ReadProcessMemory(hProcess, cmdline, pszBuffer, cbCmdLine, NULL); 141 if (!ret) 142 trace("ReadProcessMemory failed (%ld)\n", GetLastError()); 143 144 pszBuffer[cbCmdLine / sizeof(WCHAR)] = UNICODE_NULL; 145 146 return pszBuffer; // needs free() 147 } 148 149 static void TEST_DoTestEntryStruct(const TEST_ENTRY *pEntry) 150 { 151 SHELLEXECUTEINFOW info = { sizeof(info) }; 152 info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_WAITFORINPUTIDLE | SEE_MASK_FLAG_NO_UI; 153 info.hwnd = NULL; 154 info.lpVerb = NULL; 155 info.lpFile = pEntry->lpFile; 156 info.nShow = SW_SHOWNORMAL; 157 158 BOOL ret = ShellExecuteExW(&info); 159 160 TEST_RESULT result; 161 if (ret && info.hProcess) 162 result = TEST_SUCCESS_WITH_PROCESS; 163 else if (ret && !info.hProcess) 164 result = TEST_SUCCESS_NO_PROCESS; 165 else 166 result = TEST_FAILED; 167 168 ok(pEntry->result == result, 169 "Line %d: result: %d vs %d\n", pEntry->line, pEntry->result, result); 170 171 if (pEntry->result == TEST_SUCCESS_WITH_PROCESS && pEntry->cmdline && !s_bWow64) 172 { 173 LPWSTR cmdline = getCommandLineFromProcess(info.hProcess); 174 if (!cmdline) 175 { 176 skip("!cmdline\n"); 177 } 178 else 179 { 180 ok(lstrcmpiW(pEntry->cmdline, cmdline) == 0, 181 "Line %d: cmdline: '%ls' vs '%ls'\n", pEntry->line, 182 pEntry->cmdline, cmdline); 183 } 184 185 TerminateProcess(info.hProcess, 0xDEADFACE); 186 free(cmdline); 187 } 188 189 CloseHandle(info.hProcess); 190 } 191 192 static void 193 TEST_DoTestEntry(INT line, TEST_RESULT result, LPCWSTR lpFile, LPCWSTR cmdline) 194 { 195 TEST_ENTRY entry = { line, result, lpFile, cmdline }; 196 TEST_DoTestEntryStruct(&entry); 197 } 198 199 static BOOL 200 enableTokenPrivilege(LPCWSTR pszPrivilege) 201 { 202 HANDLE hToken; 203 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 204 return FALSE; 205 206 TOKEN_PRIVILEGES tkp = { 0 }; 207 if (!LookupPrivilegeValueW(NULL, pszPrivilege, &tkp.Privileges[0].Luid)) 208 return FALSE; 209 210 tkp.PrivilegeCount = 1; 211 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 212 return AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, NULL); 213 } 214 215 typedef struct WINDOW_LIST 216 { 217 SIZE_T m_chWnds; 218 HWND *m_phWnds; 219 } WINDOW_LIST, *PWINDOW_LIST; 220 221 static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) 222 { 223 if (!IsWindowVisible(hwnd)) 224 return TRUE; 225 226 PWINDOW_LIST pList = (PWINDOW_LIST)lParam; 227 SIZE_T cb = (pList->m_chWnds + 1) * sizeof(HWND); 228 HWND *phWnds = (HWND *)realloc(pList->m_phWnds, cb); 229 if (!phWnds) 230 return FALSE; 231 phWnds[pList->m_chWnds++] = hwnd; 232 pList->m_phWnds = phWnds; 233 return TRUE; 234 } 235 236 static inline void TEST_GetWindowList(PWINDOW_LIST pList) 237 { 238 EnumWindows(EnumWindowsProc, (LPARAM)pList); 239 } 240 241 static void TEST_CloseNewWindows(PWINDOW_LIST List1, PWINDOW_LIST List2) 242 { 243 for (SIZE_T i2 = 0; i2 < List2->m_chWnds; ++i2) 244 { 245 BOOL bFoundInList1 = FALSE; 246 HWND hWnd = List2->m_phWnds[i2]; 247 for (SIZE_T i1 = 0; i1 < List1->m_chWnds; ++i1) 248 { 249 if (hWnd == List1->m_phWnds[i1]) 250 { 251 bFoundInList1 = TRUE; 252 goto Escape; 253 } 254 } 255 Escape: 256 if (!bFoundInList1) 257 { 258 for (INT i = 0; i < 5; ++i) 259 { 260 if (!IsWindow(hWnd)) 261 break; 262 263 SwitchToThisWindow(hWnd, TRUE); 264 265 // Alt+F4 266 keybd_event(VK_MENU, 0x38, 0, 0); 267 keybd_event(VK_F4, 0x3E, 0, 0); 268 keybd_event(VK_F4, 0x3E, KEYEVENTF_KEYUP, 0); 269 keybd_event(VK_MENU, 0x38, KEYEVENTF_KEYUP, 0); 270 Sleep(100); 271 } 272 } 273 } 274 } 275 276 static WINDOW_LIST s_List1, s_List2; 277 278 static BOOL TEST_Start(void) 279 { 280 // Check Wow64 281 s_bWow64 = FALSE; 282 IsWow64Process(GetCurrentProcess(), &s_bWow64); 283 if (s_bWow64) 284 skip("Wow64: Command Line check is skipped\n"); 285 286 // getCommandLineFromProcess needs this 287 enableTokenPrivilege(SE_DEBUG_NAME); 288 289 // s_win_dir 290 GetWindowsDirectoryW(s_win_dir, _countof(s_win_dir)); 291 292 // s_sys_dir 293 GetSystemDirectoryW(s_sys_dir, _countof(s_sys_dir)); 294 295 // s_win_notepad 296 GetWindowsDirectoryW(s_win_notepad, _countof(s_win_notepad)); 297 PathAppendW(s_win_notepad, L"notepad.exe"); 298 299 // s_sys_notepad 300 GetSystemDirectoryW(s_sys_notepad, _countof(s_sys_notepad)); 301 PathAppendW(s_sys_notepad, L"notepad.exe"); 302 303 // s_win_test_exe 304 GetWindowsDirectoryW(s_win_test_exe, _countof(s_win_test_exe)); 305 PathAppendW(s_win_test_exe, L"test program.exe"); 306 BOOL ret = CopyFileW(s_win_notepad, s_win_test_exe, FALSE); 307 if (!ret) 308 { 309 skip("Please retry with admin rights\n"); 310 return FALSE; 311 } 312 313 // s_sys_test_exe 314 GetSystemDirectoryW(s_sys_test_exe, _countof(s_sys_test_exe)); 315 PathAppendW(s_sys_test_exe, L"test program.exe"); 316 ok_int(CopyFileW(s_win_notepad, s_sys_test_exe, FALSE), TRUE); 317 318 // s_win_bat_file 319 GetWindowsDirectoryW(s_win_bat_file, _countof(s_win_bat_file)); 320 PathAppendW(s_win_bat_file, L"test program.bat"); 321 FILE *fp = _wfopen(s_win_bat_file, L"wb"); 322 fprintf(fp, "exit /b 3"); 323 fclose(fp); 324 ok_int(PathFileExistsW(s_win_bat_file), TRUE); 325 326 // s_sys_bat_file 327 GetSystemDirectoryW(s_sys_bat_file, _countof(s_sys_bat_file)); 328 PathAppendW(s_sys_bat_file, L"test program.bat"); 329 fp = _wfopen(s_sys_bat_file, L"wb"); 330 fprintf(fp, "exit /b 4"); 331 fclose(fp); 332 ok_int(PathFileExistsW(s_sys_bat_file), TRUE); 333 334 // s_win_txt_file 335 GetWindowsDirectoryW(s_win_txt_file, _countof(s_win_txt_file)); 336 PathAppendW(s_win_txt_file, L"test_file.txt"); 337 fp = _wfopen(s_win_txt_file, L"wb"); 338 fclose(fp); 339 ok_int(PathFileExistsW(s_win_txt_file), TRUE); 340 341 // s_sys_txt_file 342 GetSystemDirectoryW(s_sys_txt_file, _countof(s_sys_txt_file)); 343 PathAppendW(s_sys_txt_file, L"test_file.txt"); 344 fp = _wfopen(s_sys_txt_file, L"wb"); 345 fclose(fp); 346 ok_int(PathFileExistsW(s_sys_txt_file), TRUE); 347 348 // Check .txt settings 349 WCHAR szPath[MAX_PATH]; 350 FindExecutableW(s_sys_txt_file, NULL, szPath); 351 if (lstrcmpiW(PathFindFileNameW(szPath), L"notepad.exe") != 0) 352 { 353 skip("Please associate .txt with notepad.exe before tests\n"); 354 return FALSE; 355 } 356 357 // command lines 358 StringCchPrintfW(s_win_notepad_cmdline, _countof(s_win_notepad_cmdline), 359 L"\"%s\" ", s_win_notepad); 360 StringCchPrintfW(s_sys_notepad_cmdline, _countof(s_sys_notepad_cmdline), 361 L"\"%s\" ", s_sys_notepad); 362 StringCchPrintfW(s_win_test_exe_cmdline, _countof(s_win_test_exe_cmdline), 363 L"\"%s\" ", s_win_test_exe); 364 StringCchPrintfW(s_sys_test_exe_cmdline, _countof(s_sys_test_exe_cmdline), 365 L"\"%s\" ", s_sys_test_exe); 366 367 TEST_GetWindowList(&s_List1); 368 369 return TRUE; 370 } 371 372 static void TEST_End(void) 373 { 374 Sleep(500); 375 TEST_GetWindowList(&s_List2); 376 TEST_CloseNewWindows(&s_List1, &s_List2); 377 free(s_List1.m_phWnds); 378 free(s_List2.m_phWnds); 379 380 DeleteFileW(s_win_test_exe); 381 DeleteFileW(s_sys_test_exe); 382 DeleteFileW(s_win_txt_file); 383 DeleteFileW(s_sys_txt_file); 384 DeleteFileW(s_win_bat_file); 385 DeleteFileW(s_sys_bat_file); 386 } 387 388 static void test_properties() 389 { 390 HRESULT hrCoInit = CoInitialize(NULL); 391 392 WCHAR Buffer[MAX_PATH * 4]; 393 GetModuleFileNameW(NULL, Buffer, _countof(Buffer)); 394 395 SHELLEXECUTEINFOW info = { sizeof(info) }; 396 info.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_NO_UI; 397 info.lpVerb = L"properties"; 398 info.lpFile = Buffer; 399 info.nShow = SW_SHOW; 400 401 BOOL bRet = ShellExecuteExW(&info); 402 ok(bRet, "Failed! (GetLastError(): %d)\n", (int)GetLastError()); 403 ok_ptr(info.hInstApp, (HINSTANCE)42); 404 405 WCHAR* Extension = PathFindExtensionW(Buffer); 406 if (Extension) 407 { 408 // The inclusion of this depends on the file display settings! 409 *Extension = UNICODE_NULL; 410 } 411 412 // Now retry it with the extension cut off 413 bRet = ShellExecuteExW(&info); 414 ok(bRet, "Failed! (GetLastError(): %d)\n", (int)GetLastError()); 415 ok_ptr(info.hInstApp, (HINSTANCE)42); 416 417 // Now retry it with complete garabage 418 info.lpFile = L"complete garbage, cannot run this!"; 419 bRet = ShellExecuteExW(&info); 420 ok_int(bRet, 0); 421 ok_ptr(info.hInstApp, (HINSTANCE)2); 422 423 if (SUCCEEDED(hrCoInit)) 424 CoUninitialize(); 425 } 426 427 static void test_sei_lpIDList() 428 { 429 if (IsWindowsVistaOrGreater()) 430 { 431 skip("Vista+\n"); 432 return; 433 } 434 435 /* This tests ShellExecuteEx with lpIDList for explorer C:\ */ 436 437 /* ITEMIDLIST for CLSID of 'My Computer' followed by PIDL for 'C:\' */ 438 BYTE lpitemidlist[30] = { 0x14, 0, 0x1f, 0, 0xe0, 0x4f, 0xd0, 0x20, 0xea, 439 0x3a, 0x69, 0x10, 0xa2, 0xd8, 0x08, 0, 0x2b, 0x30, 0x30, 0x9d, // My Computer 440 0x8, 0, 0x23, 0x43, 0x3a, 0x5c, 0x5c, 0, 0, 0,}; // C:\\ + NUL-NUL ending 441 442 SHELLEXECUTEINFOW ShellExecInfo = { sizeof(ShellExecInfo) }; 443 ShellExecInfo.fMask = SEE_MASK_IDLIST; 444 ShellExecInfo.hwnd = NULL; 445 ShellExecInfo.nShow = SW_SHOWNORMAL; 446 ShellExecInfo.lpIDList = lpitemidlist; 447 BOOL ret = ShellExecuteExW(&ShellExecInfo); 448 ok_int(ret, TRUE); 449 } 450 451 static BOOL 452 CreateAppPath(LPCWSTR pszName, LPCWSTR pszValue) 453 { 454 WCHAR szSubKey[MAX_PATH]; 455 StringCchPrintfW(szSubKey, _countof(szSubKey), L"%s\\%s", REG_APPPATHS, pszName); 456 457 LSTATUS error; 458 HKEY hKey; 459 error = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szSubKey, 0, NULL, 0, KEY_WRITE, NULL, 460 &hKey, NULL); 461 if (error != ERROR_SUCCESS) 462 trace("Could not create test key (%lu)\n", error); 463 464 DWORD cbValue = (lstrlenW(pszValue) + 1) * sizeof(WCHAR); 465 error = RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)pszValue, cbValue); 466 if (error != ERROR_SUCCESS) 467 trace("Could not set value of the test key (%lu)\n", error); 468 469 RegCloseKey(hKey); 470 471 return error == ERROR_SUCCESS; 472 } 473 474 static VOID 475 DeleteAppPath(LPCWSTR pszName) 476 { 477 WCHAR szSubKey[MAX_PATH]; 478 StringCchPrintfW(szSubKey, _countof(szSubKey), L"%s\\%s", REG_APPPATHS, pszName); 479 480 LSTATUS error = RegDeleteKeyW(HKEY_LOCAL_MACHINE, szSubKey); 481 if (error != ERROR_SUCCESS) 482 trace("Could not remove the test key (%lu)\n", error); 483 } 484 485 static void TEST_AppPath(void) 486 { 487 if (CreateAppPath(L"app_path_test.bat", s_win_test_exe)) 488 { 489 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, L"app_path_test.bat"); 490 TEST_DoTestEntry(__LINE__, TEST_FAILED, L"app_path_test.bat.exe"); 491 DeleteAppPath(L"app_path_test.bat"); 492 } 493 494 if (CreateAppPath(L"app_path_test.bat.exe", s_sys_test_exe)) 495 { 496 TEST_DoTestEntry(__LINE__, TEST_FAILED, L"app_path_test.bat"); 497 TEST_DoTestEntry(__LINE__, TEST_SUCCESS_WITH_PROCESS, L"app_path_test.bat.exe"); 498 DeleteAppPath(L"app_path_test.bat.exe"); 499 } 500 } 501 502 START_TEST(ShellExecuteEx) 503 { 504 #ifdef _WIN64 505 skip("Win64 is not supported yet\n"); 506 return; 507 #endif 508 509 if (!TEST_Start()) 510 return; 511 512 TEST_AppPath(); 513 TEST_DoTestEntries(); 514 test_properties(); 515 test_sei_lpIDList(); 516 517 TEST_End(); 518 } 519