[PATCH v2 0/1] MR3057: kernel32/tests: Extend console inheritance tests.
- defining what the std handles are before inheriting them - checking access to parent console from child through std handles Signed-off-by: Eric Pouech <epouech(a)codeweavers.com> -- v2: kernel32/tests: Extend console inheritance tests. https://gitlab.winehq.org/wine/wine/-/merge_requests/3057
From: Eric Pouech <epouech(a)codeweavers.com> - defining what the std handles are before inheriting them - checking access to parent console from child through std handles Signed-off-by: Eric Pouech <epouech(a)codeweavers.com> --- dlls/kernel32/tests/console.c | 212 +++++++++++++++++++++++++--------- 1 file changed, 157 insertions(+), 55 deletions(-) diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 4aa293df4b8..24c1e5c69fd 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4838,17 +4838,48 @@ static void copy_change_subsystem(const char* in, const char* out, DWORD subsyst CloseHandle(hFile); } -static DWORD check_child_console_bits(const char* exec, DWORD flags) +enum inheritance_model {NULL_STD, CONSOLE_STD, STARTUPINFO_STD}; + +static DWORD check_child_console_bits(const char* exec, DWORD flags, enum inheritance_model inherit) { + SECURITY_ATTRIBUTES sa = {0, NULL, TRUE}; STARTUPINFOA si = { sizeof(si) }; PROCESS_INFORMATION info; char buf[MAX_PATH]; + HANDLE handle; DWORD exit_code; BOOL res; DWORD ret; + BOOL inherit_handles = FALSE; sprintf(buf, "\"%s\" console check_console", exec); - res = CreateProcessA(NULL, buf, NULL, NULL, FALSE, flags, NULL, NULL, &si, &info); + switch (inherit) + { + case NULL_STD: + SetStdHandle(STD_INPUT_HANDLE, NULL); + SetStdHandle(STD_OUTPUT_HANDLE, NULL); + SetStdHandle(STD_ERROR_HANDLE, NULL); + break; + case CONSOLE_STD: + handle = CreateFileA("CONIN$", GENERIC_READ, 0, &sa, OPEN_EXISTING, 0, 0); + ok(handle != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + SetStdHandle(STD_INPUT_HANDLE, handle); + handle = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0); + ok(handle != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + SetStdHandle(STD_OUTPUT_HANDLE, handle); + SetStdHandle(STD_ERROR_HANDLE, handle); + break; + case STARTUPINFO_STD: + si.dwFlags |= STARTF_USESTDHANDLES; + si.hStdInput = CreateFileA("CONIN$", GENERIC_READ, 0, &sa, OPEN_EXISTING, 0, 0); + ok(si.hStdInput != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + si.hStdOutput = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0); + ok(si.hStdInput != INVALID_HANDLE_VALUE, "Couldn't create output to console\n"); + si.hStdError = INVALID_HANDLE_VALUE; + inherit_handles = TRUE; + break; + } + res = CreateProcessA(NULL, buf, NULL, NULL, inherit_handles, flags, NULL, NULL, &si, &info); ok(res, "CreateProcess failed: %lu %s\n", GetLastError(), buf); CloseHandle(info.hThread); ret = WaitForSingleObject(info.hProcess, 30000); @@ -4857,6 +4888,19 @@ static DWORD check_child_console_bits(const char* exec, DWORD flags) res = GetExitCodeProcess(info.hProcess, &exit_code); ok(res && exit_code <= 255, "Couldn't get exit_code\n"); CloseHandle(info.hProcess); + switch (inherit) + { + case NULL_STD: + break; + case CONSOLE_STD: + CloseHandle(GetStdHandle(STD_INPUT_HANDLE)); + CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE)); + break; + case STARTUPINFO_STD: + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + break; + } return exit_code; } @@ -4865,13 +4909,94 @@ static DWORD check_child_console_bits(const char* exec, DWORD flags) #define CP_WITH_WINDOW 0x04 /* child has a console window */ #define CP_ALONE 0x08 /* whether child is the single process attached to console */ #define CP_GROUP_LEADER 0x10 /* whether the child is the process group leader */ +#define CP_INPUT_VALID 0x20 /* whether StdHandle(INPUT) is a valid console handle */ +#define CP_OUTPUT_VALID 0x40 /* whether StdHandle(OUTPUT) is a valid console handle */ + +#define CP_OWN_CONSOLE (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_INPUT_VALID | CP_OUTPUT_VALID | CP_ALONE) +#define CP_INH_CONSOLE (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_INPUT_VALID | CP_OUTPUT_VALID) static void test_CreateProcessCUI(void) { - char guiexec[MAX_PATH]; - char cuiexec[MAX_PATH]; + HANDLE hstd[3]; + static char guiexec[MAX_PATH]; + static char cuiexec[MAX_PATH]; char **argv; BOOL res; + int i; + + static struct + { + BOOL use_cui; + DWORD cp_flags; + enum inheritance_model inherit; + DWORD expected; + BOOL is_todo; + DWORD is_broken; + } + no_console_tests[] = + { +/* 0*/ {FALSE, 0, NULL_STD, 0}, + {FALSE, DETACHED_PROCESS, NULL_STD, 0}, + {FALSE, CREATE_NEW_CONSOLE, NULL_STD, 0}, + {FALSE, CREATE_NO_WINDOW, NULL_STD, 0}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, 0}, +/* 5*/ {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, 0}, + + {TRUE, 0, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + {TRUE, DETACHED_PROCESS, NULL_STD, 0}, + {TRUE, CREATE_NEW_CONSOLE, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + {TRUE, CREATE_NO_WINDOW, NULL_STD, CP_OWN_CONSOLE}, +/*10*/ {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, 0}, + {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + }, + with_console_tests[] = + { +/* 0*/ {FALSE, 0, NULL_STD, 0, TRUE}, + {FALSE, DETACHED_PROCESS, NULL_STD, 0}, + {FALSE, CREATE_NEW_CONSOLE, NULL_STD, 0}, + {FALSE, CREATE_NO_WINDOW, NULL_STD, 0}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, 0}, +/* 5*/ {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, 0}, + + {FALSE, 0, CONSOLE_STD, 0, TRUE}, + {FALSE, DETACHED_PROCESS, CONSOLE_STD, 0}, + {FALSE, CREATE_NEW_CONSOLE, CONSOLE_STD, 0}, + {FALSE, CREATE_NO_WINDOW, CONSOLE_STD, 0, TRUE}, +/*10*/ {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, CONSOLE_STD, 0}, + {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, CONSOLE_STD, 0}, + + {FALSE, 0, STARTUPINFO_STD, 0, TRUE}, + {FALSE, DETACHED_PROCESS, STARTUPINFO_STD, 0, TRUE}, + {FALSE, CREATE_NEW_CONSOLE, STARTUPINFO_STD, 0, TRUE}, +/*15*/ {FALSE, CREATE_NO_WINDOW, STARTUPINFO_STD, 0, TRUE}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, STARTUPINFO_STD, 0, TRUE}, + {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STARTUPINFO_STD, 0, TRUE}, + + {TRUE, 0, NULL_STD, CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW}, + {TRUE, DETACHED_PROCESS, NULL_STD, 0}, +/*20*/ {TRUE, CREATE_NEW_CONSOLE, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + {TRUE, CREATE_NO_WINDOW, NULL_STD, CP_OWN_CONSOLE}, + {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, 0}, + {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + + {TRUE, 0, CONSOLE_STD, CP_INH_CONSOLE | CP_WITH_WINDOW}, +/*25*/ {TRUE, DETACHED_PROCESS, CONSOLE_STD, 0}, + {TRUE, CREATE_NEW_CONSOLE, CONSOLE_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + {TRUE, CREATE_NO_WINDOW, CONSOLE_STD, CP_OWN_CONSOLE}, + {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, CONSOLE_STD, 0}, + {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, CONSOLE_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + +/*30*/ {TRUE, 0, STARTUPINFO_STD, CP_INH_CONSOLE | CP_WITH_WINDOW}, + {TRUE, DETACHED_PROCESS, STARTUPINFO_STD, CP_INPUT_VALID | CP_OUTPUT_VALID, .is_broken = 0x100}, + {TRUE, CREATE_NEW_CONSOLE, STARTUPINFO_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW, .is_broken = CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE}, + {TRUE, CREATE_NO_WINDOW, STARTUPINFO_STD, CP_OWN_CONSOLE, .is_broken = CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE}, + {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, STARTUPINFO_STD, CP_INPUT_VALID | CP_OUTPUT_VALID, .is_broken = 0x100}, +/*35*/ {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STARTUPINFO_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW, .is_broken = CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE}, + }; + + hstd[0] = GetStdHandle(STD_INPUT_HANDLE); + hstd[1] = GetStdHandle(STD_OUTPUT_HANDLE); + hstd[2] = GetStdHandle(STD_ERROR_HANDLE); winetest_get_mainargs(&argv); GetTempPathA(ARRAY_SIZE(guiexec), guiexec); @@ -4883,63 +5008,36 @@ static void test_CreateProcessCUI(void) FreeConsole(); - res = check_child_console_bits(guiexec, 0); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, DETACHED_PROCESS); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, CREATE_NO_WINDOW); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); - ok(res == 0, "Unexpected result %x\n", res); - - res = check_child_console_bits(cuiexec, 0); - ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, DETACHED_PROCESS); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE); - ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, CREATE_NO_WINDOW); - ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE), "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); - ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); + for (i = 0; i < ARRAY_SIZE(no_console_tests); i++) + { + res = check_child_console_bits(no_console_tests[i].use_cui ? cuiexec : guiexec, + no_console_tests[i].cp_flags, + no_console_tests[i].inherit); + todo_wine_if(no_console_tests[i].is_todo) + ok(res == no_console_tests[i].expected, "[%d] Unexpected result %x (%lx)\n", + i, res, no_console_tests[i].expected); + } AllocConsole(); - res = check_child_console_bits(guiexec, 0); - todo_wine - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, DETACHED_PROCESS); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, CREATE_NO_WINDOW); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); - ok(res == 0, "Unexpected result %x\n", res); - - res = check_child_console_bits(cuiexec, 0); - ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW), "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, DETACHED_PROCESS); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE); - ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, CREATE_NO_WINDOW); - ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE), "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); - ok(res == 0, "Unexpected result %x\n", res); - res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); - ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); + for (i = 0; i < ARRAY_SIZE(with_console_tests); i++) + { + res = check_child_console_bits(with_console_tests[i].use_cui ? cuiexec : guiexec, + with_console_tests[i].cp_flags, + with_console_tests[i].inherit); + todo_wine_if(with_console_tests[i].is_todo) + ok(res == with_console_tests[i].expected || + broken(with_console_tests[i].is_broken && res == (with_console_tests[i].is_broken & 0xff)), + "[%d] Unexpected result %x (%lx)\n", + i, res, with_console_tests[i].expected); + } DeleteFileA(guiexec); DeleteFileA(cuiexec); + + SetStdHandle(STD_INPUT_HANDLE, hstd[0]); + SetStdHandle(STD_OUTPUT_HANDLE, hstd[1]); + SetStdHandle(STD_ERROR_HANDLE, hstd[2]); } START_TEST(console) @@ -4980,6 +5078,10 @@ START_TEST(console) exit_code |= CP_ALONE; if (RtlGetCurrentPeb()->ProcessParameters->ProcessGroupId == GetCurrentProcessId()) exit_code |= CP_GROUP_LEADER; + if (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR) + exit_code |= CP_INPUT_VALID; + if (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR) + exit_code |= CP_OUTPUT_VALID; ExitProcess(exit_code); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/3057
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=133737 Your paranoid android. === w864 (32 bit report) === kernel32: console.c:1230: Test failed: WaitForSingleObject returned 0 console.c:1232: Test failed: WaitForSingleObject returned 0 console.c:1234: Test failed: WaitForSingleObject returned 0 console.c:1236: Test failed: WaitForSingleObject returned 0 console.c:1238: Test failed: WaitForSingleObject returned 0 console.c:1240: Test failed: NtWaitForSingleObject returned 0 console.c:1243: Test failed: NtWaitForSingleObject returned 0
On Tue Jun 13 12:06:39 2023 +0000, **** wrote:
Marvin replied on the mailing list: ``` Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=133734 Your paranoid android. === w7u_2qxl (32 bit report) === kernel32: console.c:5028: Test failed: [31] Unexpected result 0 (60) console.c:5028: Test failed: [32] Unexpected result f (6f) console.c:5028: Test failed: [33] Unexpected result b (6b) console.c:5028: Test failed: [34] Unexpected result 0 (60) console.c:5028: Test failed: [35] Unexpected result f (6f) === w7u_adm (32 bit report) === kernel32: console.c:5028: Test failed: [31] Unexpected result 0 (60) console.c:5028: Test failed: [32] Unexpected result f (6f) console.c:5028: Test failed: [33] Unexpected result b (6b) console.c:5028: Test failed: [34] Unexpected result 0 (60) console.c:5028: Test failed: [35] Unexpected result f (6f) === w7u_el (32 bit report) === kernel32: console.c:5028: Test failed: [31] Unexpected result 0 (60) console.c:5028: Test failed: [32] Unexpected result f (6f) console.c:5028: Test failed: [33] Unexpected result b (6b) console.c:5028: Test failed: [34] Unexpected result 0 (60) console.c:5028: Test failed: [35] Unexpected result f (6f) === w7pro64 (64 bit report) === kernel32: console.c:5028: Test failed: [31] Unexpected result 0 (60) console.c:5028: Test failed: [32] Unexpected result f (6f) console.c:5028: Test failed: [33] Unexpected result b (6b) console.c:5028: Test failed: [34] Unexpected result 0 (60) console.c:5028: Test failed: [35] Unexpected result f (6f) ``` pushed V2 to support broken Win7 results
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/3057#note_35622
On Tue Jun 13 12:56:39 2023 +0000, **** wrote:
Marvin replied on the mailing list: ``` Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=133737 Your paranoid android. === w864 (32 bit report) === kernel32: console.c:1230: Test failed: WaitForSingleObject returned 0 console.c:1232: Test failed: WaitForSingleObject returned 0 console.c:1234: Test failed: WaitForSingleObject returned 0 console.c:1236: Test failed: WaitForSingleObject returned 0 console.c:1238: Test failed: WaitForSingleObject returned 0 console.c:1240: Test failed: NtWaitForSingleObject returned 0 console.c:1243: Test failed: NtWaitForSingleObject returned 0 ``` not related to the patch this is sometimes returned by console tests (see eg. https://test.winehq.org/data/6b0836e3f157318b00effc1de563da4d4b0d16b8/win22H...)
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/3057#note_35625
participants (3)
-
Eric Pouech -
eric pouech (@epo) -
Marvin