https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c35a84985abcc05b0b537…
commit c35a84985abcc05b0b5376bf97928bea3ea62bde
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Jun 8 08:07:37 2021 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Jun 8 08:07:37 2021 +0900
[SHELL32_APITEST] Strengthen ShellExecuteEx testcase (#3731)
Investigate shell32!ShellExecuteEx function more. CORE-17351, CORE-16898, CORE-17612
---
.../rostests/apitests/shell32/ShellExecuteEx.cpp | 271 ++++++++++++++++++++-
.../apitests/shell32/shell32_apitest_sub.cpp | 2 +-
2 files changed, 271 insertions(+), 2 deletions(-)
diff --git a/modules/rostests/apitests/shell32/ShellExecuteEx.cpp
b/modules/rostests/apitests/shell32/ShellExecuteEx.cpp
index 73afcd1e2e5..72661ab389f 100644
--- a/modules/rostests/apitests/shell32/ShellExecuteEx.cpp
+++ b/modules/rostests/apitests/shell32/ShellExecuteEx.cpp
@@ -3,9 +3,12 @@
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: Testing ShellExecuteEx
* PROGRAMMER: Yaroslav Veremenko <yaroslav(a)veremenko.info>
+ * Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
*/
#include "shelltest.h"
+#include <shlwapi.h>
+#include <stdio.h>
#define ok_ShellExecuteEx (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 :
TestShellExecuteEx
@@ -81,7 +84,7 @@ TestShellExecuteEx(const WCHAR* Name, BOOL ExpectedResult)
}
}
-START_TEST(ShellExecuteEx)
+static void DoAppPathTest(void)
{
ok_ShellExecuteEx(L"iexplore", TRUE);
ok_ShellExecuteEx(L"iexplore.exe", TRUE);
@@ -100,3 +103,269 @@ START_TEST(ShellExecuteEx)
DeleteAppPathRegKey(L"iexplore.bat.exe");
}
}
+
+typedef struct TEST_ENTRY
+{
+ INT lineno;
+ BOOL ret;
+ BOOL bProcessHandle;
+ LPCSTR file;
+ LPCSTR params;
+ LPCSTR curdir;
+} TEST_ENTRY;
+
+static char s_sub_program[MAX_PATH];
+static char s_win_test_exe[MAX_PATH];
+static char s_sys_test_exe[MAX_PATH];
+static char s_win_bat_file[MAX_PATH];
+static char s_sys_bat_file[MAX_PATH];
+static char s_win_txt_file[MAX_PATH];
+static char s_sys_txt_file[MAX_PATH];
+
+#define DONT_CARE 0x0BADF00D
+
+static const TEST_ENTRY s_entries_1[] =
+{
+ { __LINE__, TRUE, TRUE, "test program" },
+ { __LINE__, TRUE, TRUE, "test program.bat" },
+ { __LINE__, TRUE, TRUE, "test program.exe" },
+ { __LINE__, FALSE, FALSE, " test program" },
+ { __LINE__, FALSE, FALSE, " test program.bat" },
+ { __LINE__, FALSE, FALSE, " test program.exe" },
+ { __LINE__, FALSE, FALSE, "test program " },
+ { __LINE__, TRUE, TRUE, "test program.bat " },
+ { __LINE__, TRUE, TRUE, "test program.exe " },
+ { __LINE__, TRUE, TRUE, "test program", "TEST" },
+ { __LINE__, TRUE, TRUE, "test program.bat", "TEST" },
+ { __LINE__, TRUE, TRUE, "test program.exe", "TEST" },
+ { __LINE__, FALSE, FALSE, ".\\test program.bat" },
+ { __LINE__, FALSE, FALSE, ".\\test program.exe" },
+ { __LINE__, TRUE, TRUE, "\"test program\"" },
+ { __LINE__, TRUE, TRUE, "\"test program.bat\"" },
+ { __LINE__, TRUE, TRUE, "\"test program.exe\"" },
+ { __LINE__, FALSE, FALSE, "\"test program\" TEST" },
+ { __LINE__, FALSE, FALSE, "\"test program.bat\" TEST" },
+ { __LINE__, FALSE, FALSE, "\"test program.exe\" TEST" },
+ { __LINE__, FALSE, FALSE, " \"test program\"" },
+ { __LINE__, FALSE, FALSE, " \"test program.bat\"" },
+ { __LINE__, FALSE, FALSE, " \"test program.exe\"" },
+ { __LINE__, FALSE, FALSE, "\"test program\" " },
+ { __LINE__, FALSE, FALSE, "\"test program.bat\" " },
+ { __LINE__, FALSE, FALSE, "\"test program.exe\" " },
+ { __LINE__, FALSE, FALSE, "\".\\test program.bat\"" },
+ { __LINE__, FALSE, FALSE, "\".\\test program.exe\"" },
+ { __LINE__, TRUE, TRUE, s_win_test_exe },
+ { __LINE__, TRUE, TRUE, s_sys_test_exe },
+ { __LINE__, TRUE, TRUE, s_win_bat_file },
+ { __LINE__, TRUE, TRUE, s_sys_bat_file },
+ { __LINE__, TRUE, TRUE, s_win_bat_file, "TEST" },
+ { __LINE__, TRUE, TRUE, s_sys_bat_file, "TEST" },
+ { __LINE__, FALSE, FALSE, "invalid program" },
+ { __LINE__, FALSE, FALSE, "invalid program.bat" },
+ { __LINE__, FALSE, FALSE, "invalid program.exe" },
+ { __LINE__, TRUE, TRUE, "test_file.txt" },
+ { __LINE__, TRUE, TRUE, "test_file.txt", "parameters parameters"
},
+ { __LINE__, TRUE, TRUE, "test_file.txt", "parameters parameters",
"." },
+ { __LINE__, TRUE, TRUE, "shell32_apitest_sub.exe" },
+ { __LINE__, TRUE, TRUE, ".\\shell32_apitest_sub.exe" },
+ { __LINE__, TRUE, TRUE, "\"shell32_apitest_sub.exe\"" },
+ { __LINE__, TRUE, TRUE, "\".\\shell32_apitest_sub.exe\"" },
+ { __LINE__, TRUE, DONT_CARE, "https://google.com" },
+ { __LINE__, TRUE, FALSE, "::{450d8fba-ad25-11d0-98a8-0800361b1103}" },
+ { __LINE__, TRUE, FALSE, "shell:::{450d8fba-ad25-11d0-98a8-0800361b1103}"
},
+ { __LINE__, TRUE, FALSE, "shell:sendto" },
+};
+
+static const TEST_ENTRY s_entries_2[] =
+{
+ { __LINE__, TRUE, TRUE, "test program" },
+ { __LINE__, TRUE, TRUE, "test program", "TEST" },
+ { __LINE__, TRUE, TRUE, "\"test program\"" },
+ { __LINE__, TRUE, TRUE, s_win_test_exe },
+ { __LINE__, TRUE, TRUE, s_sys_test_exe },
+ { __LINE__, FALSE, FALSE, s_win_bat_file },
+ { __LINE__, FALSE, FALSE, s_sys_bat_file },
+ { __LINE__, FALSE, FALSE, s_win_bat_file, "TEST" },
+ { __LINE__, FALSE, FALSE, s_sys_bat_file, "TEST" },
+};
+
+typedef struct OPENWNDS
+{
+ UINT count;
+ HWND *phwnd;
+} OPENWNDS;
+
+static OPENWNDS s_wi0 = { 0 }, s_wi1 = { 0 };
+
+static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
+{
+ OPENWNDS *info = (OPENWNDS *)lParam;
+ info->phwnd = (HWND *)realloc(info->phwnd, (info->count + 1) *
sizeof(HWND));
+ if (!info->phwnd)
+ return FALSE;
+ info->phwnd[info->count] = hwnd;
+ ++(info->count);
+ return TRUE;
+}
+
+static VOID DoTestEntry(const TEST_ENTRY *pEntry)
+{
+ SHELLEXECUTEINFOA info = { sizeof(info) };
+ info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
+ info.nShow = SW_SHOWNORMAL;
+ info.lpFile = pEntry->file;
+ info.lpParameters = pEntry->params;
+ info.lpDirectory = pEntry->curdir;
+ BOOL ret = ShellExecuteExA(&info);
+ ok(ret == pEntry->ret, "Line %u: ret expected %d, got %d\n",
+ pEntry->lineno, pEntry->ret, ret);
+ if (!pEntry->ret)
+ return;
+
+ if ((UINT)pEntry->bProcessHandle != DONT_CARE)
+ {
+ if (pEntry->bProcessHandle)
+ {
+ ok(!!info.hProcess, "Line %u: hProcess expected non-NULL\n",
pEntry->lineno);
+ }
+ else
+ {
+ ok(!info.hProcess, "Line %u: hProcess expected NULL\n",
pEntry->lineno);
+ return;
+ }
+ }
+
+ WaitForInputIdle(info.hProcess, INFINITE);
+
+ // close newly opened windows
+ EnumWindows(EnumWindowsProc, (LPARAM)&s_wi1);
+ for (UINT i1 = 0; i1 < s_wi1.count; ++i1)
+ {
+ BOOL bFound = FALSE;
+ for (UINT i0 = 0; i0 < s_wi0.count; ++i0)
+ {
+ if (s_wi1.phwnd[i1] == s_wi0.phwnd[i0])
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+ if (!bFound)
+ PostMessageW(s_wi1.phwnd[i1], WM_CLOSE, 0, 0);
+ }
+ free(s_wi1.phwnd);
+ ZeroMemory(&s_wi1, sizeof(s_wi1));
+
+ WaitForSingleObject(info.hProcess, INFINITE);
+ CloseHandle(info.hProcess);
+}
+
+static BOOL
+GetSubProgramPath(void)
+{
+ GetModuleFileNameA(NULL, s_sub_program, _countof(s_sub_program));
+ PathRemoveFileSpecA(s_sub_program);
+ PathAppendA(s_sub_program, "shell32_apitest_sub.exe");
+
+ if (!PathFileExistsA(s_sub_program))
+ {
+ PathRemoveFileSpecA(s_sub_program);
+ PathAppendA(s_sub_program, "testdata\\shell32_apitest_sub.exe");
+
+ if (!PathFileExistsA(s_sub_program))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static void DoTestEntries(void)
+{
+ if (!GetSubProgramPath())
+ {
+ skip("shell32_apitest_sub.exe is not found\n");
+ return;
+ }
+
+ // s_win_test_exe
+ GetWindowsDirectoryA(s_win_test_exe, _countof(s_win_test_exe));
+ PathAppendA(s_win_test_exe, "test program.exe");
+ BOOL ret = CopyFileA(s_sub_program, s_win_test_exe, FALSE);
+ if (!ret)
+ {
+ skip("Please retry with admin rights\n");
+ return;
+ }
+
+ // record open windows
+ if (!EnumWindows(EnumWindowsProc, (LPARAM)&s_wi0))
+ {
+ skip("EnumWindows failed\n");
+ DeleteFileA(s_win_test_exe);
+ free(s_wi0.phwnd);
+ return;
+ }
+
+ // s_sys_test_exe
+ GetSystemDirectoryA(s_sys_test_exe, _countof(s_sys_test_exe));
+ PathAppendA(s_sys_test_exe, "test program.exe");
+ ok_int(CopyFileA(s_sub_program, s_sys_test_exe, FALSE), TRUE);
+
+ // s_win_bat_file
+ GetWindowsDirectoryA(s_win_bat_file, _countof(s_win_bat_file));
+ PathAppendA(s_win_bat_file, "test program.bat");
+ FILE *fp = fopen(s_win_bat_file, "wb");
+ fprintf(fp, "exit /b 3");
+ fclose(fp);
+ ok_int(PathFileExistsA(s_win_bat_file), TRUE);
+
+ // s_sys_bat_file
+ GetSystemDirectoryA(s_sys_bat_file, _countof(s_sys_bat_file));
+ PathAppendA(s_sys_bat_file, "test program.bat");
+ fp = fopen(s_sys_bat_file, "wb");
+ fprintf(fp, "exit /b 4");
+ fclose(fp);
+ ok_int(PathFileExistsA(s_sys_bat_file), TRUE);
+
+ // s_win_txt_file
+ GetWindowsDirectoryA(s_win_txt_file, _countof(s_win_txt_file));
+ PathAppendA(s_win_txt_file, "test_file.txt");
+ fp = fopen(s_win_txt_file, "wb");
+ fclose(fp);
+ ok_int(PathFileExistsA(s_win_txt_file), TRUE);
+
+ // s_sys_txt_file
+ GetSystemDirectoryA(s_sys_txt_file, _countof(s_sys_txt_file));
+ PathAppendA(s_sys_txt_file, "test_file.txt");
+ fp = fopen(s_sys_txt_file, "wb");
+ fclose(fp);
+ ok_int(PathFileExistsA(s_sys_txt_file), TRUE);
+
+ for (UINT iTest = 0; iTest < _countof(s_entries_1); ++iTest)
+ {
+ DoTestEntry(&s_entries_1[iTest]);
+ }
+
+ DeleteFileA(s_win_bat_file);
+ DeleteFileA(s_sys_bat_file);
+
+ for (UINT iTest = 0; iTest < _countof(s_entries_2); ++iTest)
+ {
+ DoTestEntry(&s_entries_2[iTest]);
+ }
+
+ DeleteFileA(s_win_test_exe);
+ DeleteFileA(s_sys_test_exe);
+ DeleteFileA(s_win_txt_file);
+ DeleteFileA(s_sys_txt_file);
+
+ free(s_wi0.phwnd);
+}
+
+START_TEST(ShellExecuteEx)
+{
+ DoAppPathTest();
+ DoTestEntries();
+}
diff --git a/modules/rostests/apitests/shell32/shell32_apitest_sub.cpp
b/modules/rostests/apitests/shell32/shell32_apitest_sub.cpp
index c0d3cc4d83e..127ecaf687f 100644
--- a/modules/rostests/apitests/shell32/shell32_apitest_sub.cpp
+++ b/modules/rostests/apitests/shell32/shell32_apitest_sub.cpp
@@ -262,7 +262,7 @@ wWinMain(HINSTANCE hInstance,
LPWSTR lpCmdLine,
INT nCmdShow)
{
- if (lstrcmpiW(lpCmdLine, L"") == 0)
+ if (lstrcmpiW(lpCmdLine, L"") == 0 || lstrcmpiW(lpCmdLine,
L"TEST") == 0)
return 0;
s_nMode = _wtoi(lpCmdLine);