ReactOS  0.4.14-dev-831-gef8c9239
ShellExecCmdLine.cpp
Go to the documentation of this file.
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 //#define ShellExecCmdLine ShellExecCmdLine
17 
18 #ifndef SECL_NO_UI
19  #define SECL_NO_UI 0x2
20  #define SECL_LOG_USAGE 0x8
21  #define SECL_USE_IDLIST 0x10
22  #define SECL_ALLOW_NONEXE 0x20
23  #define SECL_RUNAS 0x40
24 #endif
25 
26 #ifdef ShellExecCmdLine
27 
28 #define shell32_hInstance GetModuleHandle(NULL)
29 #define IDS_FILE_NOT_FOUND (-1)
30 
31 static const WCHAR wszOpen[] = L"open";
32 static const WCHAR wszExe[] = L".exe";
33 static const WCHAR wszCom[] = L".com";
34 
35 static __inline void __SHCloneStrW(WCHAR **target, const WCHAR *source)
36 {
37  *target = (WCHAR *)SHAlloc((lstrlenW(source) + 1) * sizeof(WCHAR) );
39 }
40 
41 static LPCWSTR
42 SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
43 {
44  LPCWSTR pch;
45  size_t ich = 0;
46  if (*psz == L'"')
47  {
48  // 1st argument is quoted. the string in quotes is quoted 1st argument.
49  // [pch] --> [pszArg0+ich]
50  for (pch = psz + 1; *pch && ich + 1 < cchArg0; ++ich, ++pch)
51  {
52  if (*pch == L'"' && pch[1] == L'"')
53  {
54  // doubled double quotations found!
55  pszArg0[ich] = L'"';
56  }
57  else if (*pch == L'"')
58  {
59  // single double quotation found!
60  ++pch;
61  break;
62  }
63  else
64  {
65  // otherwise
66  pszArg0[ich] = *pch;
67  }
68  }
69  }
70  else
71  {
72  // 1st argument is unquoted. non-space sequence is 1st argument.
73  // [pch] --> [pszArg0+ich]
74  for (pch = psz; *pch && !iswspace(*pch) && ich + 1 < cchArg0; ++ich, ++pch)
75  {
76  pszArg0[ich] = *pch;
77  }
78  }
79  pszArg0[ich] = 0;
80 
81  // skip space
82  while (iswspace(*pch))
83  ++pch;
84 
85  return pch;
86 }
87 
89  HWND hwnd,
90  LPCWSTR pwszCommand,
91  LPCWSTR pwszStartDir,
92  int nShow,
93  LPVOID pUnused,
94  DWORD dwSeclFlags)
95 {
98  LPCWSTR pszVerb = NULL;
99  WCHAR szFile[MAX_PATH], szFile2[MAX_PATH];
100  HRESULT hr;
101  LPCWSTR pchParams;
102  LPWSTR lpCommand = NULL;
103 
104  if (pwszCommand == NULL)
106  1, (ULONG_PTR*)pwszCommand);
107 
108  __SHCloneStrW(&lpCommand, pwszCommand);
109  StrTrimW(lpCommand, L" \t");
110 
111  if (dwSeclFlags & SECL_NO_UI)
113  if (dwSeclFlags & SECL_LOG_USAGE)
115  if (dwSeclFlags & SECL_USE_IDLIST)
117 
118  if (dwSeclFlags & SECL_RUNAS)
119  {
120  dwSize = 0;
121  hr = AssocQueryStringW(0, ASSOCSTR_COMMAND, lpCommand, L"RunAs", NULL, &dwSize);
122  if (SUCCEEDED(hr) && dwSize != 0)
123  {
124  pszVerb = L"runas";
125  }
126  }
127 
128  if (UrlIsFileUrlW(lpCommand))
129  {
130  StringCchCopyW(szFile, _countof(szFile), lpCommand);
131  pchParams = NULL;
132  }
133  else
134  {
135  pchParams = SplitParams(lpCommand, szFile, _countof(szFile));
136  if (SearchPathW(NULL, szFile, NULL, _countof(szFile2), szFile2, NULL) ||
137  SearchPathW(NULL, szFile, wszExe, _countof(szFile2), szFile2, NULL) ||
138  SearchPathW(NULL, szFile, wszCom, _countof(szFile2), szFile2, NULL) ||
139  SearchPathW(pwszStartDir, szFile, NULL, _countof(szFile2), szFile2, NULL) ||
140  SearchPathW(pwszStartDir, szFile, wszExe, _countof(szFile2), szFile2, NULL) ||
141  SearchPathW(pwszStartDir, szFile, wszCom, _countof(szFile2), szFile2, NULL))
142  {
143  StringCchCopyW(szFile, _countof(szFile), szFile2);
144  }
145  else if (SearchPathW(NULL, lpCommand, NULL, _countof(szFile2), szFile2, NULL) ||
146  SearchPathW(NULL, lpCommand, wszExe, _countof(szFile2), szFile2, NULL) ||
147  SearchPathW(NULL, lpCommand, wszCom, _countof(szFile2), szFile2, NULL) ||
148  SearchPathW(pwszStartDir, lpCommand, NULL, _countof(szFile2), szFile2, NULL) ||
149  SearchPathW(pwszStartDir, lpCommand, wszExe, _countof(szFile2), szFile2, NULL) ||
150  SearchPathW(pwszStartDir, lpCommand, wszCom, _countof(szFile2), szFile2, NULL))
151  {
152  StringCchCopyW(szFile, _countof(szFile), szFile2);
153  pchParams = NULL;
154  }
155 
156  if (!(dwSeclFlags & SECL_ALLOW_NONEXE))
157  {
158  if (!GetBinaryTypeW(szFile, &dwType))
159  {
160  SHFree(lpCommand);
161 
162  if (!(dwSeclFlags & SECL_NO_UI))
163  {
164  WCHAR szText[128 + MAX_PATH], szFormat[128];
166  StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
168  }
169  return CO_E_APPNOTFOUND;
170  }
171  }
172  else
173  {
175  {
176  SHFree(lpCommand);
177 
178  if (!(dwSeclFlags & SECL_NO_UI))
179  {
180  WCHAR szText[128 + MAX_PATH], szFormat[128];
182  StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
184  }
186  }
187  }
188  }
189 
190  ZeroMemory(&info, sizeof(info));
191  info.cbSize = sizeof(info);
192  info.fMask = dwFlags;
193  info.hwnd = hwnd;
194  info.lpVerb = pszVerb;
195  info.lpFile = szFile;
196  info.lpParameters = (pchParams && *pchParams) ? pchParams : NULL;
197  info.lpDirectory = pwszStartDir;
198  info.nShow = nShow;
199  if (ShellExecuteExW(&info))
200  {
201  if (info.lpIDList)
202  CoTaskMemFree(info.lpIDList);
203 
204  SHFree(lpCommand);
205 
206  return S_OK;
207  }
208 
209  dwError = GetLastError();
210 
211  SHFree(lpCommand);
212 
213  return HRESULT_FROM_WIN32(dwError);
214 }
215 #else
218 #endif
219 
220 typedef struct TEST_ENTRY
221 {
222  INT lineno;
228 } TEST_ENTRY;
229 
230 static const char s_testfile1[] = "Test File.txt";
231 static const char s_testfile2[] = "Test File.bat";
232 static char s_notepad[] = "notepad.exe";
233 
234 static const TEST_ENTRY s_entries[] =
235 {
236  // NULL
237  { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, NULL },
238  { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"." },
239  { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"system32" },
240  { __LINE__, (HRESULT)0xDEADFACE, FALSE, NULL, NULL, L"C:\\Program Files" },
241  { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, NULL },
242  { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"." },
243  { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"system32" },
244  { __LINE__, (HRESULT)0xDEADFACE, TRUE, NULL, NULL, L"C:\\Program Files" },
245  // notepad
246  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", NULL },
247  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"." },
248  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"system32" },
249  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad", L"C:\\Program Files" },
250  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad \"Test File.txt\"", NULL },
251  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad \"Test File.txt\"", L"." },
252  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", NULL },
253  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"." },
254  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"system32" },
255  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad", L"C:\\Program Files" },
256  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad \"Test File.txt\"", NULL },
257  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad \"Test File.txt\"", L"." },
258  // notepad.exe
259  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", NULL },
260  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"." },
261  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"system32" },
262  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe", L"C:\\Program Files" },
263  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe \"Test File.txt\"", NULL },
264  { __LINE__, S_OK, FALSE, L"Notepad", L"notepad.exe \"Test File.txt\"", L"." },
265  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", NULL },
266  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"." },
267  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"system32" },
268  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe", L"C:\\Program Files" },
269  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe \"Test File.txt\"", NULL },
270  { __LINE__, S_OK, TRUE, L"Notepad", L"notepad.exe \"Test File.txt\"", L"." },
271  // C:\notepad.exe
272  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe", NULL },
273  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe", L"." },
274  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe", L"system32" },
275  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe", L"C:\\Program Files" },
276  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe \"Test File.txt\"", NULL },
277  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"C:\\notepad.exe \"Test File.txt\"", L"." },
278  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe", NULL },
279  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe", L"." },
280  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe", L"system32" },
281  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe", L"C:\\Program Files" },
282  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe \"Test File.txt\"", NULL },
283  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"C:\\notepad.exe \"Test File.txt\"", L"." },
284  // "notepad"
285  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\"", NULL },
286  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\"", L"." },
287  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\"", L"system32" },
288  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\"", L"C:\\Program Files" },
289  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\" \"Test File.txt\"", NULL },
290  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad\" \"Test File.txt\"", L"." },
291  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\"", NULL },
292  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\"", L"." },
293  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\"", L"system32" },
294  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\"", L"C:\\Program Files" },
295  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\" \"Test File.txt\"", NULL },
296  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad\" \"Test File.txt\"", L"." },
297  // "notepad.exe"
298  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\"", NULL },
299  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\"", L"." },
300  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\"", L"system32" },
301  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\"", L"C:\\Program Files" },
302  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\" \"Test File.txt\"", NULL },
303  { __LINE__, S_OK, FALSE, L"Notepad", L"\"notepad.exe\" \"Test File.txt\"", L"." },
304  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\"", NULL },
305  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\"", L"." },
306  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\"", L"system32" },
307  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\"", L"C:\\Program Files" },
308  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\" \"Test File.txt\"", NULL },
309  { __LINE__, S_OK, TRUE, L"Notepad", L"\"notepad.exe\" \"Test File.txt\"", L"." },
310  // test program.exe
311  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", NULL },
312  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"." },
313  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"system32" },
314  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe", L"C:\\Program Files" },
315  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe \"Test File.txt\"", NULL },
316  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"test program.exe \"Test File.txt\"", L"." },
317  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", NULL },
318  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"." },
319  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"system32" },
320  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe", L"C:\\Program Files" },
321  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe \"Test File.txt\"", NULL },
322  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"test program.exe \"Test File.txt\"", L"." },
323  // "test program"
324  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\"", NULL },
325  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\"", L"." },
326  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\"", L"system32" },
327  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\"", L"C:\\Program Files" },
328  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\" \"Test File.txt\"", NULL },
329  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program\" \"Test File.txt\"", L"." },
330  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\"", NULL },
331  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\"", L"." },
332  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\"", L"system32" },
333  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\"", L"C:\\Program Files" },
334  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\" \"Test File.txt\"", NULL },
335  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program\" \"Test File.txt\"", L"." },
336  // "test program.exe"
337  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\"", NULL },
338  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\"", L"." },
339  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\"", L"system32" },
340  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\"", L"C:\\Program Files" },
341  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\" \"Test File.txt\"", NULL },
342  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"test program.exe\" \"Test File.txt\"", L"." },
343  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\"", NULL },
344  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\"", L"." },
345  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\"", L"system32" },
346  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\"", L"C:\\Program Files" },
347  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\" \"Test File.txt\"", NULL },
348  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"test program.exe\" \"Test File.txt\"", L"." },
349  // invalid program
350  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", NULL },
351  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"." },
352  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"system32" },
353  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program", L"C:\\Program Files" },
354  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program \"Test File.txt\"", NULL },
355  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"invalid program \"Test File.txt\"", L"." },
356  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", NULL },
357  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"." },
358  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"system32" },
359  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program", L"C:\\Program Files" },
360  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program \"Test File.txt\"", NULL },
361  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"invalid program \"Test File.txt\"", L"." },
362  // \"invalid program.exe\"
363  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\"", NULL },
364  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\"", L"." },
365  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\"", L"system32" },
366  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\"", L"C:\\Program Files" },
367  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\" \"Test File.txt\"", NULL },
368  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", L"\"invalid program.exe\" \"Test File.txt\"", L"." },
369  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\"", NULL },
370  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\"", L"." },
371  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\"", L"system32" },
372  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\"", L"C:\\Program Files" },
373  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\" \"Test File.txt\"", NULL },
374  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", L"\"invalid program.exe\" \"Test File.txt\"", L"." },
375 };
376 
377 static void DoEntry(const TEST_ENTRY *pEntry)
378 {
379  HRESULT hr;
380  DWORD dwSeclFlags;
381 
382  if (pEntry->bAllowNonExe)
383  dwSeclFlags = SECL_NO_UI | SECL_ALLOW_NONEXE;
384  else
385  dwSeclFlags = SECL_NO_UI;
386 
387  _SEH2_TRY
388  {
389 #ifdef ShellExecCmdLine
390  hr = ShellExecCmdLine(NULL, pEntry->pwszCommand, pEntry->pwszStartDir,
391  SW_SHOWNORMAL, NULL, dwSeclFlags);
392 #else
393  hr = (*g_pShellExecCmdLine)(NULL, pEntry->pwszCommand, pEntry->pwszStartDir,
394  SW_SHOWNORMAL, NULL, dwSeclFlags);
395 #endif
396  }
398  {
399  hr = 0xDEADFACE;
400  }
401  _SEH2_END;
402 
403  ok(hr == pEntry->hr, "Line %d: hr expected 0x%lX, was 0x%lX\n", pEntry->lineno, pEntry->hr, hr);
404 
405 #define RETRY_COUNT 5
406 #define RETRY_INTERVAL 250
407  if (SUCCEEDED(hr) && pEntry->pwszWindowClass)
408  {
409  BOOL bFound = FALSE;
410  Sleep(RETRY_INTERVAL / 2);
411  for (int i = 0; i < RETRY_COUNT; ++i)
412  {
414  if (hwnd)
415  {
416  bFound = TRUE;
417  SendMessage(hwnd, WM_CLOSE, 0, 0);
419  break;
420  }
422  }
423  ok(bFound, "Line %d: The window not found\n", pEntry->lineno);
424  }
425 #undef RETRY_COUNT
426 #undef RETRY_INTERVAL
427 }
428 
430 {
431  using namespace std;
432 
433 #ifndef ShellExecCmdLine
434  // CHECKME
436  {
437  skip("ShellExecCmdLine is not available on this platform\n");
438  return;
439  }
440 
441  HMODULE hShell32 = GetModuleHandleA("shell32");
443  if (!g_pShellExecCmdLine)
444  {
445  skip("ShellExecCmdLine is not found\n");
446  return;
447  }
448 #endif
449 
450  // s_testfile1
451  FILE *fp = fopen(s_testfile1, "wb");
452  ok(fp != NULL, "failed to create a test file\n");
453  fclose(fp);
454 
455  // s_testfile2
456  fp = fopen(s_testfile2, "wb");
457  ok(fp != NULL, "failed to create a test file\n");
458  if (fp)
459  {
460  fprintf(fp, "echo OK\n");
461  }
462  fclose(fp);
463 
464  for (size_t i = 0; i < _countof(s_entries); ++i)
465  {
466  DoEntry(&s_entries[i]);
467  }
468 
469  WCHAR buf0[MAX_PATH];
470  WCHAR buf1[MAX_PATH];
471  WCHAR buf2[MAX_PATH];
472  TEST_ENTRY additionals[] =
473  {
474  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, NULL },
475  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, L"." },
476  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf0, L"system32" },
477  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, NULL },
478  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, L"." },
479  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf1, L"system32" },
480  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, NULL },
481  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, L"." },
482  { __LINE__, CO_E_APPNOTFOUND, FALSE, L"Notepad", buf2, L"system32" },
483  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf0, NULL }, // FIXME
484  { __LINE__, S_OK, TRUE, L"Notepad", buf0, L"." },
485  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf0, L"system32" }, // FIXME
486  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf1, NULL }, // FIXME
487  { __LINE__, S_OK, TRUE, L"Notepad", buf1, L"." },
488  { __LINE__, S_OK, TRUE, L"Notepad", buf1, L"system32" },
489  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, L"Notepad", buf2, NULL }, // FIXME
490  { __LINE__, S_OK, TRUE, L"Notepad", buf2, L"." },
491  { __LINE__, S_OK, TRUE, L"Notepad", buf2, L"system32" },
492  };
493 
494  wsprintfW(buf0, L"%hs", s_testfile1);
495  wsprintfW(buf1, L"\"%hs\"", s_testfile1);
496  wsprintfW(buf2, L"\"%hs\" \"Test File.txt\"", s_testfile1);
497  for (size_t i = 0; i < _countof(additionals); ++i)
498  {
499  DoEntry(&additionals[i]);
500  }
501 
502  TEST_ENTRY additionals2[] =
503  {
504  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, NULL },
505  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, L"." },
506  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf0, L"system32" },
507  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, NULL },
508  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, L"." },
509  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf1, L"system32" },
510  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, NULL },
511  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, L"." },
512  { __LINE__, CO_E_APPNOTFOUND, FALSE, NULL, buf2, L"system32" },
513  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf0, NULL }, // FIXME
514  { __LINE__, S_OK, TRUE, NULL, buf0, L"." },
515  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf0, L"system32" }, // FIXME
516  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf1, NULL }, // FIXME
517  { __LINE__, S_OK, TRUE, NULL, buf1, L"." },
518  { __LINE__, S_OK, TRUE, NULL, buf1, L"system32" },
519  { __LINE__, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), TRUE, NULL, buf2, NULL }, // FIXME
520  { __LINE__, S_OK, TRUE, NULL, buf2, L"." },
521  { __LINE__, S_OK, TRUE, NULL, buf2, L"system32" },
522  };
523 
524  wsprintfW(buf0, L"%hs", s_testfile2);
525  wsprintfW(buf1, L"\"%hs\"", s_testfile2);
526  wsprintfW(buf2, L"\"%hs\" \"Test File.txt\"", s_testfile2);
527  for (size_t i = 0; i < _countof(additionals2); ++i)
528  {
529  DoEntry(&additionals2[i]);
530  }
531 
532  char path[MAX_PATH];
533  ok((INT_PTR)FindExecutableA("notepad.exe", NULL, s_notepad) >= 32, "FindExecutableA failed\n");
534  ok(GetModuleFileNameA(NULL, path, _countof(path)), "GetModuleFileNameA failed\n");
535  char *pch = strrchr(path, '\\');
536 
537  if (pch == NULL)
538  {
539  skip("pch == NULL\n");
540  }
541  else
542  {
543  // create "My Directory"
544  strcpy(pch, "\\My Directory");
546  ok(CreateDirectoryA(path, NULL), "CreateDirectoryA failed\n");
547 
548  // create "My Directory\\Notepad.exe" as clone of Notepad.exe
549  strcpy(pch, "\\My Directory\\Notepad.exe");
550  ok(CopyFileA(s_notepad, path, FALSE), "CopyFileA failed\n");
551 
552  wsprintfW(buf0, L"%hs", path);
553  wsprintfW(buf1, L"\"%hs\"", path);
554  wsprintfW(buf2, L"\"%hs\" \"Test File.txt\"", path);
555  TEST_ENTRY additionals3[] =
556  {
557  { __LINE__, S_OK, FALSE, NULL, buf0, NULL },
558  { __LINE__, S_OK, FALSE, NULL, buf0, L"." },
559  { __LINE__, S_OK, FALSE, NULL, buf0, L"system32" },
560  { __LINE__, S_OK, FALSE, NULL, buf1, NULL },
561  { __LINE__, S_OK, FALSE, NULL, buf1, L"." },
562  { __LINE__, S_OK, FALSE, NULL, buf1, L"system32" },
563  { __LINE__, S_OK, FALSE, NULL, buf2, NULL },
564  { __LINE__, S_OK, FALSE, NULL, buf2, L"." },
565  { __LINE__, S_OK, FALSE, NULL, buf2, L"system32" },
566  { __LINE__, S_OK, TRUE, NULL, buf0, NULL },
567  { __LINE__, S_OK, TRUE, NULL, buf0, L"." },
568  { __LINE__, S_OK, TRUE, NULL, buf0, L"system32" },
569  { __LINE__, S_OK, TRUE, NULL, buf1, NULL },
570  { __LINE__, S_OK, TRUE, NULL, buf1, L"." },
571  { __LINE__, S_OK, TRUE, NULL, buf1, L"system32" },
572  { __LINE__, S_OK, TRUE, NULL, buf2, NULL },
573  { __LINE__, S_OK, TRUE, NULL, buf2, L"." },
574  { __LINE__, S_OK, TRUE, NULL, buf2, L"system32" },
575  };
576  for (size_t i = 0; i < _countof(additionals3); ++i)
577  {
578  DoEntry(&additionals3[i]);
579  }
580 
581  DeleteFileA(path);
582 
583  strcpy(pch, "\\My Directory");
585  }
586 
587  // clean up
588  ok(DeleteFileA(s_testfile1), "failed to delete the test file\n");
589  ok(DeleteFileA(s_testfile2), "failed to delete the test file\n");
590 }
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
struct TEST_ENTRY TEST_ENTRY
#define HRESULT
Definition: msvc.h:7
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define TRUE
Definition: types.h:120
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
static const char s_testfile2[]
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:420
HRESULT hr
Definition: shlfolder.c:183
LPCWSTR pwszStartDir
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
LPCWSTR pwszCommand
#define SECL_USE_IDLIST
HRESULT(WINAPI * SHELLEXECCMDLINE)(HWND, LPCWSTR, LPCWSTR, INT, LPVOID, DWORD)
#define _countof(array)
Definition: fontsub.cpp:30
#define EXCEPTION_ACCESS_VIOLATION
Definition: winbase.h:308
#define SECL_NO_UI
#define RemoveDirectory
Definition: winbase.h:3729
#define INT
Definition: polytest.cpp:20
#define EXCEPTION_NONCONTINUABLE
Definition: rtltypes.h:150
HANDLE HWND
Definition: compat.h:13
#define SECL_RUNAS
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1642
static LPCWSTR SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
Definition: shlexec.cpp:2345
BOOL WINAPI CopyFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:404
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
int32_t INT_PTR
Definition: typedefs.h:62
Definition: features.h:417
#define lstrlenW
Definition: compat.h:415
BOOL WINAPI GetBinaryTypeW(LPCWSTR lpApplicationName, LPDWORD lpBinaryType)
Definition: vdm.c:1235
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:56
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:548
#define pch(ap)
Definition: match.c:418
_SEH2_TRY
Definition: create.c:4250
struct _test_info info[]
Definition: SetCursorPos.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:63
static __inline void __SHCloneStrW(WCHAR **target, const WCHAR *source)
Definition: shell32_main.h:154
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HINSTANCE shell32_hInstance
Definition: misc.cpp:82
static const WCHAR szText[]
Definition: dialog.c:139
#define RETRY_INTERVAL
START_TEST(ShellExecCmdLine)
unsigned int BOOL
Definition: ntddk_ex.h:94
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:802
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:786
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
smooth NULL
Definition: ftsmooth.c:416
#define SEE_MASK_NOASYNC
Definition: shellapi.h:33
#define SEE_MASK_FLAG_NO_UI
Definition: shellapi.h:36
#define SECL_LOG_USAGE
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
#define SECL_ALLOW_NONEXE
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2239
INT lineno
Definition: DPtoLP.c:34
VERSIONHELPERAPI IsWindowsVistaOrGreater()
const char * LPCSTR
Definition: xmlstorage.h:183
HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc, LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut)
Definition: assoc.c:427
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static const WCHAR wszCom[]
Definition: shlexec.cpp:30
static const char s_testfile1[]
SHELLEXECCMDLINE g_pShellExecCmdLine
int WINAPI MessageBoxW(_In_opt_ HWND, _In_opt_ LPCWSTR, _In_opt_ LPCWSTR, _In_ UINT)
__wchar_t WCHAR
Definition: xmlstorage.h:180
HWND WINAPI FindWindowW(_In_opt_ LPCWSTR, _In_opt_ LPCWSTR)
LONG HRESULT
Definition: typedefs.h:77
LPCWSTR pwszWindowClass
#define WM_CLOSE
Definition: winuser.h:1603
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:6
#define SEE_MASK_DOENVSUBST
Definition: shellapi.h:35
BOOL bAllowNonExe
static const WCHAR wszExe[]
Definition: shlexec.cpp:29
unsigned long DWORD
Definition: ntddk_ex.h:95
HRESULT WINAPI ShellExecCmdLine(HWND hwnd, LPCWSTR pwszCommand, LPCWSTR pwszStartDir, int nShow, LPVOID pUnused, DWORD dwSeclFlags)
Definition: shlexec.cpp:2391
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define LPVOID
Definition: nt_native.h:45
static const TEST_ENTRY s_entries[]
#define iswspace(_c)
Definition: ctype.h:669
HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
Definition: shlexec.cpp:1207
Definition: cmd.c:12
static const WCHAR L[]
Definition: oid.c:1250
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define MB_ICONERROR
Definition: winuser.h:781
#define IDS_FILE_NOT_FOUND
Definition: shresdef.h:299
HRESULT hr
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
#define UrlIsFileUrlW(x)
Definition: shlwapi.h:1377
DWORD WINAPI SearchPathW(IN LPCWSTR lpPath OPTIONAL, IN LPCWSTR lpFileName, IN LPCWSTR lpExtension OPTIONAL, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart OPTIONAL)
Definition: path.c:1297
static const WCHAR wszOpen[]
Definition: shlexec.cpp:28
#define S_OK
Definition: intsafe.h:59
#define SW_SHOWNORMAL
Definition: winuser.h:764
_SEH2_END
Definition: create.c:4424
VOID WINAPI RaiseException(IN DWORD dwExceptionCode, IN DWORD dwExceptionFlags, IN DWORD nNumberOfArguments, IN CONST ULONG_PTR *lpArguments OPTIONAL)
Definition: except.c:693
#define lstrcpyW
Definition: compat.h:414
#define SEE_MASK_FLAG_LOG_USAGE
Definition: shellapi.h:57
#define ok(value,...)
Definition: atltest.h:57
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
static void DoEntry(const TEST_ENTRY *pEntry)
BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim)
Definition: string.c:1869
#define skip(...)
Definition: atltest.h:64
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:331
static char s_notepad[]
#define SendMessage
Definition: winuser.h:5818
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
GLenum target
Definition: glext.h:7315
#define RETRY_COUNT
#define SEE_MASK_INVOKEIDLIST
Definition: shellapi.h:28
#define GetProcAddress(x, y)
Definition: compat.h:418
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define CO_E_APPNOTFOUND
Definition: winerror.h:2808
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static HMODULE hShell32
Definition: string.c:34
LPVOID WINAPI SHAlloc(SIZE_T len)
Definition: shellole.c:309
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
#define SUCCEEDED(hr)
Definition: intsafe.h:57