1 /* 2 * PROJECT: ReactOS API tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Test for ShellExecCmdLine 5 * PROGRAMMERS: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 #include "shelltest.h" 8 #include <shlwapi.h> 9 #include <strsafe.h> 10 #include <versionhelpers.h> 11 12 #define NDEBUG 13 #include <debug.h> 14 #include <stdio.h> 15 16 #ifndef SECL_NO_UI 17 #define SECL_NO_UI 0x2 18 #define SECL_LOG_USAGE 0x8 19 #define SECL_USE_IDLIST 0x10 20 #define SECL_ALLOW_NONEXE 0x20 21 #define SECL_RUNAS 0x40 22 #endif 23 24 #define ShellExecCmdLine proxy_ShellExecCmdLine 25 26 #define shell32_hInstance GetModuleHandle(NULL) 27 #define IDS_FILE_NOT_FOUND (-1) 28 29 static const WCHAR wszOpen[] = L"open"; 30 static const WCHAR wszExe[] = L".exe"; 31 static const WCHAR wszCom[] = L".com"; 32 33 static __inline void __SHCloneStrW(WCHAR **target, const WCHAR *source) 34 { 35 *target = (WCHAR *)SHAlloc((lstrlenW(source) + 1) * sizeof(WCHAR) ); 36 lstrcpyW(*target, source); 37 } 38 39 // NOTE: You have to sync the following code to dll/win32/shell32/shlexec.cpp. 40 static LPCWSTR 41 SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0) 42 { 43 LPCWSTR pch; 44 size_t ich = 0; 45 if (*psz == L'"') 46 { 47 // 1st argument is quoted. the string in quotes is quoted 1st argument. 48 // [pch] --> [pszArg0+ich] 49 for (pch = psz + 1; *pch && ich + 1 < cchArg0; ++ich, ++pch) 50 { 51 if (*pch == L'"' && pch[1] == L'"') 52 { 53 // doubled double quotations found! 54 pszArg0[ich] = L'"'; 55 } 56 else if (*pch == L'"') 57 { 58 // single double quotation found! 59 ++pch; 60 break; 61 } 62 else 63 { 64 // otherwise 65 pszArg0[ich] = *pch; 66 } 67 } 68 } 69 else 70 { 71 // 1st argument is unquoted. non-space sequence is 1st argument. 72 // [pch] --> [pszArg0+ich] 73 for (pch = psz; *pch && !iswspace(*pch) && ich + 1 < cchArg0; ++ich, ++pch) 74 { 75 pszArg0[ich] = *pch; 76 } 77 } 78 pszArg0[ich] = 0; 79 80 // skip space 81 while (iswspace(*pch)) 82 ++pch; 83 84 return pch; 85 } 86 87 HRESULT WINAPI ShellExecCmdLine( 88 HWND hwnd, 89 LPCWSTR pwszCommand, 90 LPCWSTR pwszStartDir, 91 int nShow, 92 LPVOID pUnused, 93 DWORD dwSeclFlags) 94 { 95 SHELLEXECUTEINFOW info; 96 DWORD dwSize, dwError, dwType, dwFlags = SEE_MASK_DOENVSUBST | SEE_MASK_NOASYNC; 97 LPCWSTR pszVerb = NULL; 98 WCHAR szFile[MAX_PATH], szFile2[MAX_PATH]; 99 HRESULT hr; 100 LPCWSTR pchParams; 101 LPWSTR lpCommand = NULL; 102 103 if (pwszCommand == NULL) 104 RaiseException(EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 105 1, (ULONG_PTR*)pwszCommand); 106 107 __SHCloneStrW(&lpCommand, pwszCommand); 108 StrTrimW(lpCommand, L" \t"); 109 110 if (dwSeclFlags & SECL_NO_UI) 111 dwFlags |= SEE_MASK_FLAG_NO_UI; 112 if (dwSeclFlags & SECL_LOG_USAGE) 113 dwFlags |= SEE_MASK_FLAG_LOG_USAGE; 114 if (dwSeclFlags & SECL_USE_IDLIST) 115 dwFlags |= SEE_MASK_INVOKEIDLIST; 116 117 if (dwSeclFlags & SECL_RUNAS) 118 { 119 dwSize = 0; 120 hr = AssocQueryStringW(0, ASSOCSTR_COMMAND, lpCommand, L"RunAs", NULL, &dwSize); 121 if (SUCCEEDED(hr) && dwSize != 0) 122 { 123 pszVerb = L"runas"; 124 } 125 } 126 127 if (UrlIsFileUrlW(lpCommand)) 128 { 129 StringCchCopyW(szFile, _countof(szFile), lpCommand); 130 pchParams = NULL; 131 } 132 else 133 { 134 pchParams = SplitParams(lpCommand, szFile, _countof(szFile)); 135 if (szFile[0] != UNICODE_NULL && szFile[1] == L':' && 136 szFile[2] == UNICODE_NULL) 137 { 138 PathAddBackslashW(szFile); 139 } 140 141 WCHAR szCurDir[MAX_PATH]; 142 GetCurrentDirectoryW(_countof(szCurDir), szCurDir); 143 if (pwszStartDir) 144 { 145 SetCurrentDirectoryW(pwszStartDir); 146 } 147 148 if (PathIsRelativeW(szFile) && 149 GetFullPathNameW(szFile, _countof(szFile2), szFile2, NULL) && 150 PathFileExistsW(szFile2)) 151 { 152 StringCchCopyW(szFile, _countof(szFile), szFile2); 153 } 154 else if (SearchPathW(NULL, szFile, NULL, _countof(szFile2), szFile2, NULL) || 155 SearchPathW(NULL, szFile, wszExe, _countof(szFile2), szFile2, NULL) || 156 SearchPathW(NULL, szFile, wszCom, _countof(szFile2), szFile2, NULL) || 157 SearchPathW(pwszStartDir, szFile, NULL, _countof(szFile2), szFile2, NULL) || 158 SearchPathW(pwszStartDir, szFile, wszExe, _countof(szFile2), szFile2, NULL) || 159 SearchPathW(pwszStartDir, szFile, wszCom, _countof(szFile2), szFile2, NULL)) 160 { 161 StringCchCopyW(szFile, _countof(szFile), szFile2); 162 } 163 else if (SearchPathW(NULL, lpCommand, NULL, _countof(szFile2), szFile2, NULL) || 164 SearchPathW(NULL, lpCommand, wszExe, _countof(szFile2), szFile2, NULL) || 165 SearchPathW(NULL, lpCommand, wszCom, _countof(szFile2), szFile2, NULL) || 166 SearchPathW(pwszStartDir, lpCommand, NULL, _countof(szFile2), szFile2, NULL) || 167 SearchPathW(pwszStartDir, lpCommand, wszExe, _countof(szFile2), szFile2, NULL) || 168 SearchPathW(pwszStartDir, lpCommand, wszCom, _countof(szFile2), szFile2, NULL)) 169 { 170 StringCchCopyW(szFile, _countof(szFile), szFile2); 171 pchParams = NULL; 172 } 173 174 if (pwszStartDir) 175 { 176 SetCurrentDirectoryW(szCurDir); 177 } 178 179 if (!(dwSeclFlags & SECL_ALLOW_NONEXE)) 180 { 181 if (!GetBinaryTypeW(szFile, &dwType)) 182 { 183 SHFree(lpCommand); 184 185 if (!(dwSeclFlags & SECL_NO_UI)) 186 { 187 WCHAR szText[128 + MAX_PATH], szFormat[128]; 188 LoadStringW(shell32_hInstance, IDS_FILE_NOT_FOUND, szFormat, _countof(szFormat)); 189 StringCchPrintfW(szText, _countof(szText), szFormat, szFile); 190 MessageBoxW(hwnd, szText, NULL, MB_ICONERROR); 191 } 192 return CO_E_APPNOTFOUND; 193 } 194 } 195 else 196 { 197 if (GetFileAttributesW(szFile) == INVALID_FILE_ATTRIBUTES) 198 { 199 SHFree(lpCommand); 200 201 if (!(dwSeclFlags & SECL_NO_UI)) 202 { 203 WCHAR szText[128 + MAX_PATH], szFormat[128]; 204 LoadStringW(shell32_hInstance, IDS_FILE_NOT_FOUND, szFormat, _countof(szFormat)); 205 StringCchPrintfW(szText, _countof(szText), szFormat, szFile); 206 MessageBoxW(hwnd, szText, NULL, MB_ICONERROR); 207 } 208 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 209 } 210 } 211 } 212 213 ZeroMemory(&info, sizeof(info)); 214 info.cbSize = sizeof(info); 215 info.fMask = dwFlags; 216 info.hwnd = hwnd; 217 info.lpVerb = pszVerb; 218 info.lpFile = szFile; 219 info.lpParameters = (pchParams && *pchParams) ? pchParams : NULL; 220 info.lpDirectory = pwszStartDir; 221 info.nShow = nShow; 222 if (ShellExecuteExW(&info)) 223 { 224 if (info.lpIDList) 225 CoTaskMemFree(info.lpIDList); 226 227 SHFree(lpCommand); 228 229 return S_OK; 230 } 231 232 dwError = GetLastError(); 233 234 SHFree(lpCommand); 235 236 return HRESULT_FROM_WIN32(dwError); 237 } 238 239 #undef ShellExecCmdLine 240 241 typedef HRESULT (WINAPI *SHELLEXECCMDLINE)(HWND, LPCWSTR, LPCWSTR, INT, LPVOID, DWORD); 242 SHELLEXECCMDLINE g_pShellExecCmdLine = NULL; 243 244 typedef struct TEST_ENTRY 245 { 246 INT lineno; 247 HRESULT hr; 248 BOOL bAllowNonExe; 249 LPCWSTR pwszWindowClass; 250 LPCWSTR pwszCommand; 251 LPCWSTR pwszStartDir; 252 } TEST_ENTRY; 253 254 static const char s_testfile1[] = "Test File.txt"; 255 static const char s_testfile2[] = "Test File.bat"; 256 static char s_notepad[] = "notepad.exe"; 257 258 static const TEST_ENTRY s_entries[] = 259 { 260 // NULL 261 { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, NULL }, 262 { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"." }, 263 { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"system32" }, 264 { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"C:\\Program Files" }, 265 { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, NULL }, 266 { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"." }, 267 { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"system32" }, 268 { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"C:\\Program Files" }, 269 // notepad 270 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", NULL }, 271 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"." }, 272 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"system32" }, 273 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"C:\\Program Files" }, 274 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad \"Test File.txt\"", NULL }, 275 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad \"Test File.txt\"", L"." }, 276 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", NULL }, 277 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"." }, 278 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"system32" }, 279 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"C:\\Program Files" }, 280 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad \"Test File.txt\"", NULL }, 281 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad \"Test File.txt\"", L"." }, 282 // notepad.exe 283 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", NULL }, 284 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"." }, 285 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"system32" }, 286 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"C:\\Program Files" }, 287 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe \"Test File.txt\"", NULL }, 288 { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe \"Test File.txt\"", L"." }, 289 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", NULL }, 290 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"." }, 291 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"system32" }, 292 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"C:\\Program Files" }, 293 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe \"Test File.txt\"", NULL }, 294 { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe \"Test File.txt\"", L"." }, 295 // C:\notepad.exe 296 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe", NULL }, 297 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe", L"." }, 298 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe", L"system32" }, 299 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe", L"C:\\Program Files" }, 300 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe \"Test File.txt\"", NULL }, 301 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe \"Test File.txt\"", L"." }, 302 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe", NULL }, 303 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe", L"." }, 304 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe", L"system32" }, 305 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe", L"C:\\Program Files" }, 306 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe \"Test File.txt\"", NULL }, 307 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe \"Test File.txt\"", L"." }, 308 // "notepad" 309 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\"", NULL }, 310 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\"", L"." }, 311 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\"", L"system32" }, 312 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\"", L"C:\\Program Files" }, 313 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\" \"Test File.txt\"", NULL }, 314 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\" \"Test File.txt\"", L"." }, 315 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\"", NULL }, 316 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\"", L"." }, 317 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\"", L"system32" }, 318 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\"", L"C:\\Program Files" }, 319 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\" \"Test File.txt\"", NULL }, 320 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\" \"Test File.txt\"", L"." }, 321 // "notepad.exe" 322 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\"", NULL }, 323 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\"", L"." }, 324 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\"", L"system32" }, 325 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\"", L"C:\\Program Files" }, 326 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\" \"Test File.txt\"", NULL }, 327 { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\" \"Test File.txt\"", L"." }, 328 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\"", NULL }, 329 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\"", L"." }, 330 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\"", L"system32" }, 331 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\"", L"C:\\Program Files" }, 332 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\" \"Test File.txt\"", NULL }, 333 { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\" \"Test File.txt\"", L"." }, 334 // test program.exe 335 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", NULL }, 336 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"." }, 337 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"system32" }, 338 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"C:\\Program Files" }, 339 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe \"Test File.txt\"", NULL }, 340 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe \"Test File.txt\"", L"." }, 341 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", NULL }, 342 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"." }, 343 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"system32" }, 344 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"C:\\Program Files" }, 345 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe \"Test File.txt\"", NULL }, 346 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe \"Test File.txt\"", L"." }, 347 // "test program" 348 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\"", NULL }, 349 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\"", L"." }, 350 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\"", L"system32" }, 351 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\"", L"C:\\Program Files" }, 352 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\" \"Test File.txt\"", NULL }, 353 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\" \"Test File.txt\"", L"." }, 354 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\"", NULL }, 355 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\"", L"." }, 356 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\"", L"system32" }, 357 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\"", L"C:\\Program Files" }, 358 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\" \"Test File.txt\"", NULL }, 359 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\" \"Test File.txt\"", L"." }, 360 // "test program.exe" 361 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\"", NULL }, 362 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\"", L"." }, 363 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\"", L"system32" }, 364 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\"", L"C:\\Program Files" }, 365 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\" \"Test File.txt\"", NULL }, 366 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\" \"Test File.txt\"", L"." }, 367 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\"", NULL }, 368 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\"", L"." }, 369 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\"", L"system32" }, 370 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\"", L"C:\\Program Files" }, 371 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\" \"Test File.txt\"", NULL }, 372 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\" \"Test File.txt\"", L"." }, 373 // invalid program 374 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", NULL }, 375 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"." }, 376 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"system32" }, 377 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"C:\\Program Files" }, 378 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program \"Test File.txt\"", NULL }, 379 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program \"Test File.txt\"", L"." }, 380 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", NULL }, 381 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"." }, 382 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"system32" }, 383 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"C:\\Program Files" }, 384 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program \"Test File.txt\"", NULL }, 385 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program \"Test File.txt\"", L"." }, 386 // \"invalid program.exe\" 387 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\"", NULL }, 388 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\"", L"." }, 389 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\"", L"system32" }, 390 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\"", L"C:\\Program Files" }, 391 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\" \"Test File.txt\"", NULL }, 392 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\" \"Test File.txt\"", L"." }, 393 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\"", NULL }, 394 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\"", L"." }, 395 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\"", L"system32" }, 396 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\"", L"C:\\Program Files" }, 397 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\" \"Test File.txt\"", NULL }, 398 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\" \"Test File.txt\"", L"." }, 399 // My Documents 400 { __LINE__, S_OK, TRUE, NULL, L"::{450d8fba-ad25-11d0-98a8-0800361b1103}", NULL }, 401 { __LINE__, S_OK, TRUE, NULL, L"shell:::{450d8fba-ad25-11d0-98a8-0800361b1103}", NULL }, 402 // Control Panel 403 { __LINE__, S_OK, TRUE, NULL, L"::{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}", NULL }, 404 { __LINE__, S_OK, TRUE, NULL, L"shell:::{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}", NULL }, 405 }; 406 407 static void DoEntry(const TEST_ENTRY *pEntry) 408 { 409 HRESULT hr; 410 DWORD dwSeclFlags; 411 412 if (pEntry->bAllowNonExe) 413 dwSeclFlags = SECL_NO_UI | SECL_ALLOW_NONEXE; 414 else 415 dwSeclFlags = SECL_NO_UI; 416 417 _SEH2_TRY 418 { 419 if (IsReactOS()) 420 { 421 hr = proxy_ShellExecCmdLine(NULL, pEntry->pwszCommand, pEntry->pwszStartDir, 422 SW_SHOWNORMAL, NULL, dwSeclFlags); 423 } 424 else 425 { 426 hr = (*g_pShellExecCmdLine)(NULL, pEntry->pwszCommand, pEntry->pwszStartDir, 427 SW_SHOWNORMAL, NULL, dwSeclFlags); 428 } 429 } 430 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 431 { 432 hr = 0xDEADFACE; 433 } 434 _SEH2_END; 435 436 ok(hr == pEntry->hr, "Line %d: hr expected 0x%lX, was 0x%lX\n", pEntry->lineno, pEntry->hr, hr); 437 438 #define RETRY_COUNT 5 439 #define RETRY_INTERVAL 250 440 if (SUCCEEDED(hr) && pEntry->pwszWindowClass) 441 { 442 BOOL bFound = FALSE; 443 Sleep(RETRY_INTERVAL / 2); 444 for (int i = 0; i < RETRY_COUNT; ++i) 445 { 446 HWND hwnd = FindWindowW(pEntry->pwszWindowClass, NULL); 447 if (hwnd) 448 { 449 bFound = TRUE; 450 SendMessage(hwnd, WM_CLOSE, 0, 0); 451 Sleep(RETRY_INTERVAL); 452 break; 453 } 454 Sleep(RETRY_INTERVAL); 455 } 456 ok(bFound, "Line %d: The window not found\n", pEntry->lineno); 457 } 458 #undef RETRY_COUNT 459 #undef RETRY_INTERVAL 460 } 461 462 START_TEST(ShellExecCmdLine) 463 { 464 using namespace std; 465 466 if (!IsReactOS()) 467 { 468 if (!IsWindowsVistaOrGreater()) 469 { 470 skip("ShellExecCmdLine is not available on this platform\n"); 471 return; 472 } 473 474 HMODULE hShell32 = GetModuleHandleA("shell32"); 475 g_pShellExecCmdLine = (SHELLEXECCMDLINE)GetProcAddress(hShell32, (LPCSTR)(INT_PTR)265); 476 if (!g_pShellExecCmdLine) 477 { 478 skip("ShellExecCmdLine is not found\n"); 479 return; 480 } 481 } 482 483 // s_testfile1 484 FILE *fp = fopen(s_testfile1, "wb"); 485 ok(fp != NULL, "failed to create a test file\n"); 486 fclose(fp); 487 488 // s_testfile2 489 fp = fopen(s_testfile2, "wb"); 490 ok(fp != NULL, "failed to create a test file\n"); 491 if (fp) 492 { 493 fprintf(fp, "echo OK\n"); 494 } 495 fclose(fp); 496 497 for (size_t i = 0; i < _countof(s_entries); ++i) 498 { 499 DoEntry(&s_entries[i]); 500 } 501 502 WCHAR buf0[MAX_PATH]; 503 WCHAR buf1[MAX_PATH]; 504 WCHAR buf2[MAX_PATH]; 505 TEST_ENTRY additionals[] = 506 { 507 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, NULL }, 508 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, L"." }, 509 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, L"system32" }, 510 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, NULL }, 511 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, L"." }, 512 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, L"system32" }, 513 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, NULL }, 514 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, L"." }, 515 { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, L"system32" }, 516 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf0, NULL }, // FIXME 517 { __LINE__, S_OK, TRUE, L"Notepad", buf0, L"." }, 518 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf0, L"system32" }, // FIXME 519 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf1, NULL }, // FIXME 520 { __LINE__, S_OK, TRUE, L"Notepad", buf1, L"." }, 521 { __LINE__, S_OK, TRUE, L"Notepad", buf1, L"system32" }, 522 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf2, NULL }, // FIXME 523 { __LINE__, S_OK, TRUE, L"Notepad", buf2, L"." }, 524 { __LINE__, S_OK, TRUE, L"Notepad", buf2, L"system32" }, 525 }; 526 527 wsprintfW(buf0, L"%hs", s_testfile1); 528 wsprintfW(buf1, L"\"%hs\"", s_testfile1); 529 wsprintfW(buf2, L"\"%hs\" \"Test File.txt\"", s_testfile1); 530 for (size_t i = 0; i < _countof(additionals); ++i) 531 { 532 DoEntry(&additionals[i]); 533 } 534 535 TEST_ENTRY additionals2[] = 536 { 537 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, NULL }, 538 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, L"." }, 539 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, L"system32" }, 540 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, NULL }, 541 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, L"." }, 542 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, L"system32" }, 543 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, NULL }, 544 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, L"." }, 545 { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, L"system32" }, 546 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf0, NULL }, // FIXME 547 { __LINE__, S_OK, TRUE, NULL, buf0, L"." }, 548 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf0, L"system32" }, // FIXME 549 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf1, NULL }, // FIXME 550 { __LINE__, S_OK, TRUE, NULL, buf1, L"." }, 551 { __LINE__, S_OK, TRUE, NULL, buf1, L"system32" }, 552 { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf2, NULL }, // FIXME 553 { __LINE__, S_OK, TRUE, NULL, buf2, L"." }, 554 { __LINE__, S_OK, TRUE, NULL, buf2, L"system32" }, 555 }; 556 557 wsprintfW(buf0, L"%hs", s_testfile2); 558 wsprintfW(buf1, L"\"%hs\"", s_testfile2); 559 wsprintfW(buf2, L"\"%hs\" \"Test File.txt\"", s_testfile2); 560 for (size_t i = 0; i < _countof(additionals2); ++i) 561 { 562 DoEntry(&additionals2[i]); 563 } 564 565 char path[MAX_PATH]; 566 ok((INT_PTR)FindExecutableA("notepad.exe", NULL, s_notepad) >= 32, "FindExecutableA failed\n"); 567 ok(GetModuleFileNameA(NULL, path, _countof(path)), "GetModuleFileNameA failed\n"); 568 char *pch = strrchr(path, '\\'); 569 570 if (pch == NULL) 571 { 572 skip("pch == NULL\n"); 573 } 574 else 575 { 576 // create "My Directory" 577 strcpy(pch, "\\My Directory"); 578 if (GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) 579 ok(CreateDirectoryA(path, NULL), "CreateDirectoryA failed\n"); 580 581 // create "My Directory\\Notepad.exe" as clone of Notepad.exe 582 strcpy(pch, "\\My Directory\\Notepad.exe"); 583 ok(CopyFileA(s_notepad, path, FALSE), "CopyFileA failed\n"); 584 585 wsprintfW(buf0, L"%hs", path); 586 wsprintfW(buf1, L"\"%hs\"", path); 587 wsprintfW(buf2, L"\"%hs\" \"Test File.txt\"", path); 588 TEST_ENTRY additionals3[] = 589 { 590 { __LINE__, S_OK, FALSE, NULL, buf0, NULL }, 591 { __LINE__, S_OK, FALSE, NULL, buf0, L"." }, 592 { __LINE__, S_OK, FALSE, NULL, buf0, L"system32" }, 593 { __LINE__, S_OK, FALSE, NULL, buf1, NULL }, 594 { __LINE__, S_OK, FALSE, NULL, buf1, L"." }, 595 { __LINE__, S_OK, FALSE, NULL, buf1, L"system32" }, 596 { __LINE__, S_OK, FALSE, NULL, buf2, NULL }, 597 { __LINE__, S_OK, FALSE, NULL, buf2, L"." }, 598 { __LINE__, S_OK, FALSE, NULL, buf2, L"system32" }, 599 { __LINE__, S_OK, TRUE, NULL, buf0, NULL }, 600 { __LINE__, S_OK, TRUE, NULL, buf0, L"." }, 601 { __LINE__, S_OK, TRUE, NULL, buf0, L"system32" }, 602 { __LINE__, S_OK, TRUE, NULL, buf1, NULL }, 603 { __LINE__, S_OK, TRUE, NULL, buf1, L"." }, 604 { __LINE__, S_OK, TRUE, NULL, buf1, L"system32" }, 605 { __LINE__, S_OK, TRUE, NULL, buf2, NULL }, 606 { __LINE__, S_OK, TRUE, NULL, buf2, L"." }, 607 { __LINE__, S_OK, TRUE, NULL, buf2, L"system32" }, 608 }; 609 for (size_t i = 0; i < _countof(additionals3); ++i) 610 { 611 DoEntry(&additionals3[i]); 612 } 613 614 DeleteFileA(path); 615 616 strcpy(pch, "\\My Directory"); 617 RemoveDirectory(path); 618 } 619 620 // clean up 621 ok(DeleteFileA(s_testfile1), "failed to delete the test file\n"); 622 ok(DeleteFileA(s_testfile2), "failed to delete the test file\n"); 623 } 624