Index: rostests/apitests/shell32/ShellExecuteEx.cpp =================================================================== --- rostests/apitests/shell32/ShellExecuteEx.cpp (revision 74978) +++ rostests/apitests/shell32/ShellExecuteEx.cpp (working copy) @@ -2,16 +2,145 @@ * PROJECT: ReactOS api tests * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Testing ShellExecuteEx - * PROGRAMMER: Yaroslav Veremenko + * PROGRAMMERS: Yaroslav Veremenko + * Katayama Hirofumi MZ */ #include "shelltest.h" +#include +#define ok_ShellExecuteEx (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : TestShellExecuteEx +#define ok_ShellExecuteEx2 (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : TestShellExecuteEx2 +#define MAX_PROCESS 512 +typedef struct PROCESS_LIST +{ + INT ProcessCount; + DWORD ProcessIDs[MAX_PROCESS]; +} PROCESS_LIST; -#define ok_ShellExecuteEx (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : TestShellExecuteEx +#define MAX_WINDOWS 512 +typedef struct WINDOW_LIST +{ + INT WindowCount; + HWND Windows[MAX_WINDOWS]; +} WINDOW_LIST; +BOOL EnableProcessPriviledge(LPCTSTR pszSE_) +{ + BOOL f; + HANDLE hProcess; + HANDLE hToken; + LUID luid; + TOKEN_PRIVILEGES tp; + + f = FALSE; + hProcess = GetCurrentProcess(); + if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + if (LookupPrivilegeValue(NULL, pszSE_, &luid)) + { + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + tp.Privileges[0].Luid = luid; + f = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL); + } + CloseHandle(hToken); + } + return f; +} + +static BOOL ListProcess(PROCESS_LIST *pList) +{ + pList->ProcessCount = 0; + + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnap == INVALID_HANDLE_VALUE) + return FALSE; + + PROCESSENTRY32 pe; + pe.dwSize = sizeof(pe); + if (Process32First(hSnap, &pe)) + { + do + { + pList->ProcessIDs[pList->ProcessCount++] = pe.th32ProcessID; + } while (Process32Next(hSnap, &pe)); + } + + CloseHandle(hSnap); + + return TRUE; +} + +static BOOL ListWindows(WINDOW_LIST *pList) +{ + pList->WindowCount = 0; + + HWND hwnd = GetTopWindow(NULL); + while (hwnd) + { + pList->Windows[pList->WindowCount++] = hwnd; + hwnd = GetWindow(hwnd, GW_HWNDNEXT); + } + + return TRUE; +} + +static BOOL +CloseProcessID(DWORD ProcessID) +{ + BOOL Ret; + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID); + Ret = TerminateProcess(hProcess, -1); + CloseHandle(hProcess); + return Ret; +} + +static INT +CloseOpenedProcess(PROCESS_LIST *pListBefore, PROCESS_LIST *pListAfter) +{ + INT m, n, Count = 0; + for (n = 0; n < pListAfter->ProcessCount; ++n) + { + for (m = 0; m < pListBefore->ProcessCount; ++m) + { + if (pListBefore->ProcessIDs[m] == pListAfter->ProcessIDs[n]) + break; + } + if (m == pListBefore->ProcessCount) + { + Count += CloseProcessID(pListAfter->ProcessIDs[n]); + } + } + return Count; +} + +static INT +CloseOpenedWindows(WINDOW_LIST *pListBefore, WINDOW_LIST *pListAfter) +{ + INT m, n, Count = 0; + for (n = 0; n < pListAfter->WindowCount; ++n) + { + for (m = 0; m < pListBefore->WindowCount; ++m) + { + if (pListBefore->Windows[m] == pListAfter->Windows[n]) + break; + } + if (m == pListBefore->WindowCount) + { + DWORD pid; + DWORD tid = GetWindowThreadProcessId(pListAfter->Windows[n], &pid); + PostThreadMessage(tid, WM_CLOSE, 0, 0); + PostThreadMessage(tid, WM_SYSCOMMAND, SC_CLOSE, 0); + CloseProcessID(pid); + Count += !!IsWindow(pListAfter->Windows[n]); + } + } + return Count; +} + static BOOL CreateAppPathRegKey(const WCHAR* Name) @@ -84,7 +213,8 @@ } } -START_TEST(ShellExecuteEx) +static void +Test_ShellExecuteEx(void) { ok_ShellExecuteEx(L"iexplore", TRUE); ok_ShellExecuteEx(L"iexplore.exe", TRUE); @@ -103,3 +233,161 @@ DeleteAppPathRegKey(L"iexplore.bat.exe"); } } + +static void +TestShellExecuteEx2(const WCHAR* File, const WCHAR* Params, BOOL ExpectedResult) +{ + SHELLEXECUTEINFOW ShellExecInfo; + BOOL Result; + ZeroMemory(&ShellExecInfo, sizeof(ShellExecInfo)); + ShellExecInfo.cbSize = sizeof(ShellExecInfo); + ShellExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI | + SEE_MASK_WAITFORINPUTIDLE; + ShellExecInfo.hwnd = NULL; + ShellExecInfo.nShow = SW_SHOWNORMAL; + ShellExecInfo.lpFile = File; + ShellExecInfo.lpParameters = Params; + Result = ShellExecuteExW(&ShellExecInfo); + ok(Result == ExpectedResult, "ShellExecute (%s, %s) failed. Error: %lu\n", + wine_dbgstr_w(File), wine_dbgstr_w(Params), GetLastError()); + if (ShellExecInfo.hProcess) + { + Result = TerminateProcess(ShellExecInfo.hProcess, 0); + if (!Result) trace("Terminate process failed. Error: %lu\n", GetLastError()); + WaitForSingleObject(ShellExecInfo.hProcess, 1000); + CloseHandle(ShellExecInfo.hProcess); + } +} + +static void +Test_ShellExecuteEx2(void) +{ + WCHAR WinDir[MAX_PATH], SysDir[MAX_PATH], FontsDir[MAX_PATH]; + WCHAR *pch, ReadMePath[MAX_PATH], ModifiedPath[MAX_PATH]; + + GetWindowsDirectoryW(WinDir, _countof(WinDir)); + GetSystemDirectoryW(SysDir, _countof(SysDir)); + lstrcpyW(FontsDir, WinDir); + lstrcatW(FontsDir, L"\\Fonts"); + + ok_ShellExecuteEx2(WinDir, NULL, TRUE); + ok_ShellExecuteEx2(SysDir, NULL, TRUE); + ok_ShellExecuteEx2(FontsDir, NULL, TRUE); + ok_ShellExecuteEx2(L"fonts", NULL, TRUE); + + ok_ShellExecuteEx2(L"explorer", WinDir, TRUE); + ok_ShellExecuteEx2(L"explorer", SysDir, TRUE); + ok_ShellExecuteEx2(L"explorer", FontsDir, TRUE); + ok_ShellExecuteEx2(L"explorer", L"fonts", TRUE); + + ok_ShellExecuteEx2(L"EXPLORER", WinDir, TRUE); + ok_ShellExecuteEx2(L"EXPLORER", SysDir, TRUE); + ok_ShellExecuteEx2(L"EXPLORER", FontsDir, TRUE); + ok_ShellExecuteEx2(L"EXPLORER", L"fonts", TRUE); + + ok_ShellExecuteEx2(L"explorer.exe", WinDir, TRUE); + ok_ShellExecuteEx2(L"explorer.exe", SysDir, TRUE); + ok_ShellExecuteEx2(L"explorer.exe", FontsDir, TRUE); + ok_ShellExecuteEx2(L"explorer.exe", L"fonts", TRUE); + + ok_ShellExecuteEx2(L"EXPLORER.EXE", WinDir, TRUE); + ok_ShellExecuteEx2(L"EXPLORER.EXE", SysDir, TRUE); + ok_ShellExecuteEx2(L"EXPLORER.EXE", FontsDir, TRUE); + ok_ShellExecuteEx2(L"EXPLORER.EXE", L"fonts", TRUE); + + ok_ShellExecuteEx2(L"notepad", NULL, TRUE); + ok_ShellExecuteEx2(L"NOTEPAD", NULL, TRUE); + + ok_ShellExecuteEx2(L"notepad.exe", NULL, TRUE); + ok_ShellExecuteEx2(L"NOTEPAD.EXE", NULL, TRUE); + + ok_ShellExecuteEx2(L"notepad.exe ", NULL, TRUE); + ok_ShellExecuteEx2(L"notepad.exe\t", NULL, FALSE); + ok_ShellExecuteEx2(L"notepad.exe\n", NULL, FALSE); + + ok_ShellExecuteEx2(L" notepad.exe", NULL, FALSE); + ok_ShellExecuteEx2(L"\tnotepad.exe", NULL, FALSE); + ok_ShellExecuteEx2(L"\nnotepad.exe", NULL, FALSE); + + GetModuleFileNameW(NULL, ReadMePath, _countof(ReadMePath)); + pch = wcsrchr(ReadMePath, L'\\'); + lstrcpyW(pch, L"\\testdata\\README.txt"); + + if (GetFileAttributesW(ReadMePath) == INVALID_FILE_ATTRIBUTES) + { + skip("Not found: %s\n", wine_dbgstr_w(ReadMePath)); + } + else + { + ok_ShellExecuteEx2(ReadMePath, NULL, TRUE); + + ok_ShellExecuteEx2(L"notepad", ReadMePath, TRUE); + ok_ShellExecuteEx2(L"NOTEPAD", ReadMePath, TRUE); + ok_ShellExecuteEx2(L"notepad.exe", ReadMePath, TRUE); + ok_ShellExecuteEx2(L"NOTEPAD.EXE", ReadMePath, TRUE); + + ok_ShellExecuteEx2(L"notepad.exe ", ReadMePath, TRUE); + ok_ShellExecuteEx2(L"notepad.exe\t", ReadMePath, FALSE); + ok_ShellExecuteEx2(L"notepad.exe\n", ReadMePath, FALSE); + ok_ShellExecuteEx2(L" notepad.exe", ReadMePath, FALSE); + ok_ShellExecuteEx2(L"\tnotepad.exe", ReadMePath, FALSE); + ok_ShellExecuteEx2(L"\nnotepad.exe", ReadMePath, FALSE); + + lstrcpyW(ModifiedPath, ReadMePath); + lstrcatW(ModifiedPath, L" "); + ok_ShellExecuteEx2(ModifiedPath, NULL, TRUE); + + lstrcpyW(ModifiedPath, ReadMePath); + lstrcatW(ModifiedPath, L"\t"); + ok_ShellExecuteEx2(ModifiedPath, NULL, FALSE); + + lstrcpyW(ModifiedPath, ReadMePath); + lstrcatW(ModifiedPath, L"\n"); + ok_ShellExecuteEx2(ModifiedPath, NULL, FALSE); + + lstrcpyW(ModifiedPath, L" "); + lstrcatW(ModifiedPath, ReadMePath); + ok_ShellExecuteEx2(ModifiedPath, NULL, FALSE); + + lstrcpyW(ModifiedPath, L"\t"); + lstrcatW(ModifiedPath, ReadMePath); + ok_ShellExecuteEx2(ModifiedPath, NULL, FALSE); + + lstrcpyW(ModifiedPath, L"\n"); + lstrcatW(ModifiedPath, ReadMePath); + ok_ShellExecuteEx2(ModifiedPath, NULL, FALSE); + } +} + +START_TEST(ShellExecuteEx) +{ + PROCESS_LIST ProcessListBefore, ProcessListAfter; + WINDOW_LIST WindowListBefore, WindowListAfter; + + EnableProcessPriviledge(SE_DEBUG_NAME); + + if (!ListProcess(&ProcessListBefore)) + { + skip("ListProcess failed\n"); + } + + if (!ListWindows(&WindowListBefore)) + { + skip("ListWindows failed\n"); + } + + Test_ShellExecuteEx(); + Test_ShellExecuteEx2(); + + ok(ListProcess(&ProcessListAfter), "ListProcess failed\n"); + ok(ListWindows(&WindowListAfter), "ListWindows failed\n"); + + trace("ProcessListBefore.ProcessCount: %d\n", ProcessListBefore.ProcessCount); + trace("ProcessListAfter.ProcessCount: %d\n", ProcessListAfter.ProcessCount); + + trace("WindowListBefore.WindowCount: %d\n", WindowListBefore.WindowCount); + trace("WindowListAfter.WindowCount: %d\n", WindowListAfter.WindowCount); + + CloseOpenedProcess(&ProcessListBefore, &ProcessListAfter); + CloseOpenedWindows(&WindowListBefore, &WindowListAfter); +}