[PATCH v2 0/4] MR4378: Extend CreateProcess tests for handle inheritance.
This serie adds a couple of test for CreateProcess around std handles inheritance, depending on several options (cui/gui, use (or no use) of STARTF_USESTDHANDLES, type of handles...). This requires revisiting the existing tests to allow for more flexibility in implementing the new tests (and potentially others if needed). -- v2: kernel32/tests: Add tests for std handles inheritance in CreateProcess. kernel32/tests: Revisit argument generation in CreateProcess tests. kernel32/tests: Detect null/invalid handles, return file type as well. kernel32/tests: Extend returned values for cui/gui tests. https://gitlab.winehq.org/wine/wine/-/merge_requests/4378
From: Eric Pouech <epouech(a)codeweavers.com> We were limited by the 8 bits of the exit code. Enable at least 32. Signed-off-by: Eric Pouech <epouech(a)codeweavers.com> --- dlls/kernel32/tests/console.c | 118 ++++++++++++++++++++++++++-------- 1 file changed, 92 insertions(+), 26 deletions(-) diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 54d1a80709b..49d7d56eb68 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4892,9 +4892,61 @@ static void copy_change_subsystem(const char* in, const char* out, DWORD subsyst CloseHandle(hFile); } +static void get_temp_file_name(char* buf) +{ + char path[MAX_PATH]; + + buf[0] = '\0'; + GetTempPathA(sizeof(path), path); + GetTempFileNameA(path, "wt", 0, buf); +} + +#define load_blackbox(a, b, c) _load_blackbox(__LINE__, (a), (b), (c)) +static BOOL _load_blackbox(unsigned int line, const char* file, void* blackbox, int size) +{ + HANDLE hFile; + DWORD read; + BOOL ret; + + hFile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + if (hFile == INVALID_HANDLE_VALUE) + { + ok_(__FILE__, line)(0, "unable to open '%s': %#lx\n", file, GetLastError()); + return FALSE; + } + SetLastError(0xdeadbeef); + ret = ReadFile(hFile, blackbox, size, &read, NULL); + ok(ret, "ReadFile failed: %ld\n", GetLastError()); + ok(read == size, "wrong size for '%s': read=%ld\n", file, read); + CloseHandle(hFile); + return TRUE; +} + +static BOOL save_blackbox(const char* file, void* blackbox, int size) +{ + HANDLE hFile; + DWORD written; + BOOL ret; + + hFile = CreateFileA(file, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0); + ok(hFile != INVALID_HANDLE_VALUE, "Couldn't create %s: %lu\n", file, GetLastError()); + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + ret = WriteFile(hFile, blackbox, size, &written, NULL); + ok(ret && written == size, "Error writing\n"); + CloseHandle(hFile); + return TRUE; +} + enum inheritance_model {NULL_STD, CONSOLE_STD, STARTUPINFO_STD}; -static DWORD check_child_console_bits(const char* exec, DWORD flags, enum inheritance_model inherit) +struct black_box +{ + unsigned bitmask; +}; + +static BOOL check_child_console_bits(const char* exec, DWORD flags, enum inheritance_model inherit, + struct black_box* result) { SECURITY_ATTRIBUTES sa = {0, NULL, TRUE}; STARTUPINFOA si = { sizeof(si) }; @@ -4905,8 +4957,11 @@ static DWORD check_child_console_bits(const char* exec, DWORD flags, enum inheri BOOL res; DWORD ret; BOOL inherit_handles = FALSE; + char blackbox_file[MAX_PATH]; + + get_temp_file_name(blackbox_file); - sprintf(buf, "\"%s\" console check_console", exec); + sprintf(buf, "\"%s\" console check_console %s", exec, blackbox_file); switch (inherit) { case NULL_STD: @@ -4940,7 +4995,7 @@ static DWORD check_child_console_bits(const char* exec, DWORD flags, enum inheri ok(ret == WAIT_OBJECT_0, "Could not wait for the child process: %ld le=%lu\n", ret, GetLastError()); res = GetExitCodeProcess(info.hProcess, &exit_code); - ok(res && exit_code <= 255, "Couldn't get exit_code\n"); + ok(res && exit_code == 0, "Couldn't get exit_code\n"); CloseHandle(info.hProcess); switch (inherit) { @@ -4955,7 +5010,10 @@ static DWORD check_child_console_bits(const char* exec, DWORD flags, enum inheri CloseHandle(si.hStdOutput); break; } - return exit_code; + if (res) + res = load_blackbox(blackbox_file, result, sizeof(*result)); + DeleteFileA(blackbox_file); + return res; } #define CP_WITH_CONSOLE 0x01 /* attached to a console */ @@ -4979,6 +5037,7 @@ static void test_CreateProcessCUI(void) BOOL res; int i; BOOL saved_console_flags; + struct black_box result; static struct { @@ -5106,10 +5165,12 @@ static void test_CreateProcessCUI(void) { res = check_child_console_bits(no_console_tests[i].use_cui ? cuiexec : guiexec, no_console_tests[i].cp_flags, - no_console_tests[i].inherit); + no_console_tests[i].inherit, + &result); + ok(res, "Couldn't run child\n"); 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); + ok(result.bitmask == no_console_tests[i].expected, "[%d] Unexpected result %x (%lx)\n", + i, result.bitmask, no_console_tests[i].expected); } AllocConsole(); @@ -5118,12 +5179,14 @@ static void test_CreateProcessCUI(void) { res = check_child_console_bits(with_console_tests[i].use_cui ? cuiexec : guiexec, with_console_tests[i].cp_flags, - with_console_tests[i].inherit); + with_console_tests[i].inherit, + &result); + ok(res, "Couldn't run child\n"); 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)), + ok(result.bitmask == with_console_tests[i].expected || + broken(with_console_tests[i].is_broken && result.bitmask == (with_console_tests[i].is_broken & 0xff)), "[%d] Unexpected result %x (%lx)\n", - i, res, with_console_tests[i].expected); + i, result.bitmask, with_console_tests[i].expected); } saved_console_flags = RtlGetCurrentPeb()->ProcessParameters->ConsoleFlags; @@ -5134,13 +5197,14 @@ static void test_CreateProcessCUI(void) ok(res, "Couldn't set ctrl handler\n"); res = check_child_console_bits(group_flags_tests[i].use_cui ? cuiexec : guiexec, group_flags_tests[i].cp_flags, - group_flags_tests[i].inherit); + group_flags_tests[i].inherit, + &result); todo_wine_if(group_flags_tests[i].is_todo) - ok(res == group_flags_tests[i].expected || + ok(result.bitmask == group_flags_tests[i].expected || /* Win7 doesn't report group id */ - broken(res == (group_flags_tests[i].expected & ~CP_GROUP_LEADER)), + broken(result.bitmask == (group_flags_tests[i].expected & ~CP_GROUP_LEADER)), "[%d] Unexpected result %x (%lx)\n", - i, res, group_flags_tests[i].expected); + i, result.bitmask, group_flags_tests[i].expected); } RtlGetCurrentPeb()->ProcessParameters->ConsoleFlags = saved_console_flags; @@ -5332,26 +5396,28 @@ START_TEST(console) ExitProcess(mch_child_event); } - if (argc == 3 && !strcmp(argv[2], "check_console")) + if (argc == 4 && !strcmp(argv[2], "check_console")) { - DWORD exit_code = 0, pcslist; - if (GetConsoleCP() != 0) exit_code |= CP_WITH_CONSOLE; - if (RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle) exit_code |= CP_WITH_HANDLE; - if (IsWindow(GetConsoleWindow())) exit_code |= CP_WITH_WINDOW; + DWORD pcslist; + struct black_box result = {.bitmask = 0}; + + if (GetConsoleCP() != 0) result.bitmask |= CP_WITH_CONSOLE; + if (RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle) result.bitmask |= CP_WITH_HANDLE; + if (IsWindow(GetConsoleWindow())) result.bitmask |= CP_WITH_WINDOW; if (pGetConsoleProcessList && GetConsoleProcessList(&pcslist, 1) == 1) - exit_code |= CP_ALONE; + result.bitmask |= CP_ALONE; if (RtlGetCurrentPeb()->ProcessParameters->Size >= offsetof(RTL_USER_PROCESS_PARAMETERS, ProcessGroupId) + sizeof(RtlGetCurrentPeb()->ProcessParameters->ProcessGroupId) && RtlGetCurrentPeb()->ProcessParameters->ProcessGroupId == GetCurrentProcessId()) - exit_code |= CP_GROUP_LEADER; + result.bitmask |= CP_GROUP_LEADER; if (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR) - exit_code |= CP_INPUT_VALID; + result.bitmask |= CP_INPUT_VALID; if (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR) - exit_code |= CP_OUTPUT_VALID; + result.bitmask |= CP_OUTPUT_VALID; if (!(RtlGetCurrentPeb()->ProcessParameters->ConsoleFlags & 1)) - exit_code |= CP_ENABLED_CTRLC; - ExitProcess(exit_code); + result.bitmask |= CP_ENABLED_CTRLC; + ExitProcess(save_blackbox(argv[3], &result, sizeof(result)) ? 0 : 1); } if (argc >= 3 && !strcmp(argv[2], "title_test")) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4378
From: Eric Pouech <epouech(a)codeweavers.com> Signed-off-by: Eric Pouech <epouech(a)codeweavers.com> --- dlls/kernel32/tests/console.c | 201 +++++++++++++++++++++------------- 1 file changed, 124 insertions(+), 77 deletions(-) diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 49d7d56eb68..3b607db917c 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -5016,17 +5016,39 @@ static BOOL check_child_console_bits(const char* exec, DWORD flags, enum inherit return res; } -#define CP_WITH_CONSOLE 0x01 /* attached to a console */ -#define CP_WITH_HANDLE 0x02 /* child has a console handle */ -#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_ENABLED_CTRLC 0x80 /* whether the ctrl-c handling isn't blocked */ - -#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) +/* generic byte mapping: gg__ooii: + * g=global bits, __ unused, oo output stream, ii input stream + * per stream: at + * b=attr bits, t=FILE_TYPE_{UNKNOWN, CHAR, PIPE, FILE} + */ + +#define CP_WITH_CONSOLE 0x80000000 /* attached to a console */ +#define CP_WITH_HANDLE 0x40000000 /* child has a console handle */ +#define CP_WITH_WINDOW 0x20000000 /* child has a console window */ +#define CP_ALONE 0x10000000 /* whether child is the single process attached to console */ +#define CP_GROUP_LEADER 0x08000000 /* whether the child is the process group leader */ +#define CP_ENABLED_CTRLC 0x04000000 /* whether the ctrl-c handling isn't blocked */ +#define CP_BROKEN 0x02000000 /* pseudo flag to pass 0 broken values in test results */ + +#define CP_STREAM_WIDTH 8 +#define CP_STREAM_MASK ((1 << (2 * CP_STREAM_WIDTH)) - 1) +#define CP_STREAM_ATTR(x) (((a) >> 2) & 3) +#define CP_STREAM_ATTR_NULL 0x08 /* NULL handle value */ +#define CP_STREAM_ATTR_INVALID 0x04 /* INVALID_HANDLE_VALUE */ +#define CP_STREAM_ATTR_GARBAGE 0x00 /* value different from 2 above, but not a valid handle */ +#define CP_STREAM_ATTR_TYPE 0x0c /* valid handle, with type set */ +#define CP_STREAM_INHERIT 0x10 /* inheritance flag set */ +#define CP_STREAM_(v, s) ((v) << ((s) * CP_STREAM_WIDTH)) +#define CP_INPUT_STREAM 0 +#define CP_OUTPUT_STREAM 1 + +#define CP_STRMIO_NONE (CP_STREAM_(CP_STREAM_ATTR_NULL, CP_INPUT_STREAM) | CP_STREAM_(CP_STREAM_ATTR_NULL, CP_OUTPUT_STREAM)) +#define CP_STRMIO_CHAR (CP_STREAM_(CP_STREAM_INHERIT | CP_STREAM_ATTR_TYPE | FILE_TYPE_CHAR, CP_INPUT_STREAM) | \ + CP_STREAM_(CP_STREAM_INHERIT | CP_STREAM_ATTR_TYPE | FILE_TYPE_CHAR, CP_OUTPUT_STREAM)) + +#define CP_HAS_CONSOLE_WIN (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW) +#define CP_OWN_CONSOLE (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_STRMIO_CHAR | CP_ALONE) +#define CP_INH_CONSOLE (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_STRMIO_CHAR) static void test_CreateProcessCUI(void) { @@ -5050,62 +5072,62 @@ static void test_CreateProcessCUI(void) } 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}, +/* 0*/ {FALSE, 0, NULL_STD, CP_STRMIO_NONE}, + {FALSE, DETACHED_PROCESS, NULL_STD, CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_CONSOLE, NULL_STD, CP_STRMIO_NONE}, + {FALSE, CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, +/* 5*/ {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, {TRUE, 0, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, - {TRUE, DETACHED_PROCESS, NULL_STD, 0}, + {TRUE, DETACHED_PROCESS, NULL_STD, CP_STRMIO_NONE}, {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}, +/*10*/ {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, }, with_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}, - - {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}, +/* 0*/ {FALSE, 0, NULL_STD, CP_STRMIO_NONE}, + {FALSE, DETACHED_PROCESS, NULL_STD, CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_CONSOLE, NULL_STD, CP_STRMIO_NONE}, + {FALSE, CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, +/* 5*/ {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, + + {FALSE, 0, CONSOLE_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, DETACHED_PROCESS, CONSOLE_STD, CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_CONSOLE, CONSOLE_STD, CP_STRMIO_NONE}, + {FALSE, CREATE_NO_WINDOW, CONSOLE_STD, CP_STRMIO_NONE, TRUE}, +/*10*/ {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, CONSOLE_STD, CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, CONSOLE_STD, CP_STRMIO_NONE}, + + {FALSE, 0, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, DETACHED_PROCESS, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, CREATE_NEW_CONSOLE, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, +/*15*/ {FALSE, CREATE_NO_WINDOW, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + + {TRUE, 0, NULL_STD, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE}, + {TRUE, DETACHED_PROCESS, NULL_STD, CP_STRMIO_NONE}, /*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, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, {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}, +/*25*/ {TRUE, DETACHED_PROCESS, CONSOLE_STD, CP_STRMIO_NONE}, {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, DETACHED_PROCESS | CREATE_NO_WINDOW, CONSOLE_STD, CP_STRMIO_NONE}, {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, DETACHED_PROCESS, STARTUPINFO_STD, CP_STRMIO_CHAR, .is_broken = CP_BROKEN}, {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}, + {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, STARTUPINFO_STD, CP_STRMIO_CHAR, .is_broken = CP_BROKEN}, /*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}, }; static struct group_flags_tests @@ -5118,33 +5140,34 @@ static void test_CreateProcessCUI(void) /* output */ DWORD expected; BOOL is_todo; + DWORD is_broken; } group_flags_tests[] = { -/* 0 */ {TRUE, 0, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW}, - {TRUE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, - {TRUE, 0, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_ENABLED_CTRLC}, - {TRUE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, - {TRUE, 0, STARTUPINFO_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW}, -/* 5 */ {TRUE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, - {TRUE, 0, STARTUPINFO_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_ENABLED_CTRLC}, - {TRUE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, - {FALSE, 0, CONSOLE_STD, TRUE, 0, .is_todo = TRUE}, - {FALSE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, TRUE, CP_GROUP_LEADER, .is_todo = TRUE}, -/* 10 */ {FALSE, 0, CONSOLE_STD, FALSE, CP_ENABLED_CTRLC, .is_todo = TRUE}, - {FALSE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, FALSE, CP_GROUP_LEADER, .is_todo = TRUE}, - {FALSE, 0, STARTUPINFO_STD, TRUE, 0, .is_todo = TRUE}, - {FALSE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, TRUE, CP_GROUP_LEADER, .is_todo = TRUE}, - {FALSE, 0, STARTUPINFO_STD, FALSE, CP_ENABLED_CTRLC, .is_todo = TRUE}, -/* 15 */ {FALSE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, FALSE, CP_GROUP_LEADER, .is_todo = TRUE}, - {TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER | CP_ALONE}, - {FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, TRUE, CP_GROUP_LEADER}, - {TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER | CP_ALONE | CP_ENABLED_CTRLC}, - {FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_ENABLED_CTRLC}, -/* 20 */ {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, TRUE, CP_GROUP_LEADER}, - {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, TRUE, CP_GROUP_LEADER}, - {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, FALSE, CP_GROUP_LEADER}, - {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, FALSE, CP_GROUP_LEADER}, +/* 0 */ {TRUE, 0, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW}, + {TRUE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, + {TRUE, 0, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_ENABLED_CTRLC}, + {TRUE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, + {TRUE, 0, STARTUPINFO_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW}, +/* 5 */ {TRUE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, + {TRUE, 0, STARTUPINFO_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_ENABLED_CTRLC}, + {TRUE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, + {FALSE, 0, CONSOLE_STD, TRUE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, +/* 10 */ {FALSE, 0, CONSOLE_STD, FALSE, CP_ENABLED_CTRLC | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_ENABLED_CTRLC}, + {FALSE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, 0, STARTUPINFO_STD, TRUE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, 0, STARTUPINFO_STD, FALSE, CP_ENABLED_CTRLC | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_ENABLED_CTRLC}, +/* 15 */ {FALSE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER | CP_ALONE}, + {FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER | CP_ALONE | CP_ENABLED_CTRLC}, + {FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_ENABLED_CTRLC | CP_STRMIO_NONE}, +/* 20 */ {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE}, }; hstd[0] = GetStdHandle(STD_INPUT_HANDLE); @@ -5184,7 +5207,7 @@ static void test_CreateProcessCUI(void) ok(res, "Couldn't run child\n"); todo_wine_if(with_console_tests[i].is_todo) ok(result.bitmask == with_console_tests[i].expected || - broken(with_console_tests[i].is_broken && result.bitmask == (with_console_tests[i].is_broken & 0xff)), + broken(with_console_tests[i].is_broken && result.bitmask == (with_console_tests[i].is_broken & ~CP_BROKEN)), "[%d] Unexpected result %x (%lx)\n", i, result.bitmask, with_console_tests[i].expected); } @@ -5202,7 +5225,8 @@ static void test_CreateProcessCUI(void) todo_wine_if(group_flags_tests[i].is_todo) ok(result.bitmask == group_flags_tests[i].expected || /* Win7 doesn't report group id */ - broken(result.bitmask == (group_flags_tests[i].expected & ~CP_GROUP_LEADER)), + broken(result.bitmask == (group_flags_tests[i].expected & ~CP_GROUP_LEADER)) || + broken(group_flags_tests[i].is_broken && result.bitmask == (group_flags_tests[i].is_broken & ~CP_BROKEN)), "[%d] Unexpected result %x (%lx)\n", i, result.bitmask, group_flags_tests[i].expected); } @@ -5353,6 +5377,31 @@ static void test_CtrlHandlerSubsystem(void) DeleteFileA(cuiexec); } +static unsigned encode_handle(DWORD std) +{ + HANDLE h = GetStdHandle(std); + DWORD dw; + unsigned result; + + if (h == NULL) + result = CP_STREAM_ATTR_NULL; + else if (h == INVALID_HANDLE_VALUE) + result = CP_STREAM_ATTR_INVALID; + else if (!GetHandleInformation(h, &dw)) + result = CP_STREAM_ATTR_GARBAGE; + else + { + result = CP_STREAM_ATTR_TYPE; + if (dw & HANDLE_FLAG_INHERIT) + result |= CP_STREAM_INHERIT; + dw = GetFileType(h); + /* only report DISK, PIPE and CHAR */ + if (dw > 3) dw = FILE_TYPE_UNKNOWN; + result |= dw; + } + return result; +} + START_TEST(console) { HANDLE hConIn, hConOut, revert_output = NULL, unbound_output; @@ -5411,12 +5460,10 @@ START_TEST(console) sizeof(RtlGetCurrentPeb()->ProcessParameters->ProcessGroupId) && RtlGetCurrentPeb()->ProcessParameters->ProcessGroupId == GetCurrentProcessId()) result.bitmask |= CP_GROUP_LEADER; - if (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR) - result.bitmask |= CP_INPUT_VALID; - if (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR) - result.bitmask |= CP_OUTPUT_VALID; if (!(RtlGetCurrentPeb()->ProcessParameters->ConsoleFlags & 1)) result.bitmask |= CP_ENABLED_CTRLC; + result.bitmask |= CP_STREAM_(encode_handle(STD_INPUT_HANDLE), CP_INPUT_STREAM); + result.bitmask |= CP_STREAM_(encode_handle(STD_OUTPUT_HANDLE), CP_OUTPUT_STREAM); ExitProcess(save_blackbox(argv[3], &result, sizeof(result)) ? 0 : 1); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4378
From: Eric Pouech <epouech(a)codeweavers.com> This will give us more flexibility in following changes. Signed-off-by: Eric Pouech <epouech(a)codeweavers.com> --- dlls/kernel32/tests/console.c | 267 +++++++++++++++++++--------------- 1 file changed, 146 insertions(+), 121 deletions(-) diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 3b607db917c..5ae1bdc4c62 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4938,57 +4938,89 @@ static BOOL save_blackbox(const char* file, void* blackbox, int size) return TRUE; } -enum inheritance_model {NULL_STD, CONSOLE_STD, STARTUPINFO_STD}; +enum inheritance_model {H_NULL, H_CONSOLE, H_FILE}; + +#define ARG_STD 0x80000000 +#define ARG_STARTUPINFO 0x00000000 +#define ARG_CP_INHERIT 0x40000000 +#define ARG_HANDLE_INHERIT 0x20000000 +#define ARG_MODEL_MASK (~0xff000000) + +#define STD_NULL (ARG_STD | H_NULL) +#define STD_CONSOLE (ARG_STD | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_CONSOLE) +#define STD_FILE (ARG_STD | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_FILE) +#define STINFO_NULL (ARG_STARTUPINFO | H_NULL) +#define STINFO_CONSOLE (ARG_STARTUPINFO | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_CONSOLE) +#define STINFO_FILE (ARG_STARTUPINFO | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_FILE) struct black_box { unsigned bitmask; }; -static BOOL check_child_console_bits(const char* exec, DWORD flags, enum inheritance_model inherit, +static BOOL check_child_console_bits(const char* exec, DWORD flags, unsigned args, struct black_box* result) { SECURITY_ATTRIBUTES sa = {0, NULL, TRUE}; + SECURITY_ATTRIBUTES* psa; STARTUPINFOA si = { sizeof(si) }; PROCESS_INFORMATION info; char buf[MAX_PATH]; - HANDLE handle; DWORD exit_code; BOOL res; DWORD ret; - BOOL inherit_handles = FALSE; + BOOL needs_close = FALSE; char blackbox_file[MAX_PATH]; + HANDLE hin, hout, herr; get_temp_file_name(blackbox_file); sprintf(buf, "\"%s\" console check_console %s", exec, blackbox_file); - switch (inherit) + SetStdHandle(STD_INPUT_HANDLE, NULL); + SetStdHandle(STD_OUTPUT_HANDLE, NULL); + SetStdHandle(STD_ERROR_HANDLE, NULL); + + psa = (args & ARG_HANDLE_INHERIT) ? &sa : NULL; + + switch (args & ARG_MODEL_MASK) { - case NULL_STD: - SetStdHandle(STD_INPUT_HANDLE, NULL); - SetStdHandle(STD_OUTPUT_HANDLE, NULL); - SetStdHandle(STD_ERROR_HANDLE, NULL); + case H_NULL: + hin = hout = herr = 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); + case H_CONSOLE: + hin = CreateFileA("CONIN$", GENERIC_READ, 0, psa, OPEN_EXISTING, 0, 0); + ok(hin != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + hout = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, psa, OPEN_EXISTING, 0, 0); + ok(hout != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + herr = hout; + needs_close = TRUE; 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; + case H_FILE: + hin = CreateFileA("NUL", GENERIC_READ, 0, psa, OPEN_EXISTING, 0, 0); + ok(hin != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + hout = CreateFileA("NUL", GENERIC_READ|GENERIC_WRITE, 0, psa, OPEN_EXISTING, 0, 0); + ok(hout != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + herr = hout; + needs_close = TRUE; break; + default: + ok(0, "Unsupported handle type %x\n", args & ARG_MODEL_MASK); + return FALSE; } - res = CreateProcessA(NULL, buf, NULL, NULL, inherit_handles, flags, NULL, NULL, &si, &info); + if (args & ARG_STD) + { + SetStdHandle(STD_INPUT_HANDLE, hin); + SetStdHandle(STD_OUTPUT_HANDLE, hout); + SetStdHandle(STD_ERROR_HANDLE, herr); + } + else /* through startup info */ + { + si.dwFlags |= STARTF_USESTDHANDLES; + si.hStdInput = hin; + si.hStdOutput = hout; + si.hStdError = herr; + } + res = CreateProcessA(NULL, buf, NULL, NULL, !!(args & ARG_CP_INHERIT), flags, NULL, NULL, &si, &info); ok(res, "CreateProcess failed: %lu %s\n", GetLastError(), buf); CloseHandle(info.hThread); ret = WaitForSingleObject(info.hProcess, 30000); @@ -4997,18 +5029,11 @@ static BOOL check_child_console_bits(const char* exec, DWORD flags, enum inherit res = GetExitCodeProcess(info.hProcess, &exit_code); ok(res && exit_code == 0, "Couldn't get exit_code\n"); CloseHandle(info.hProcess); - switch (inherit) + if (needs_close) { - 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; + CloseHandle(hin); + CloseHandle(hout); + if (hout != herr) CloseHandle(herr); } if (res) res = load_blackbox(blackbox_file, result, sizeof(*result)); @@ -5065,109 +5090,109 @@ static void test_CreateProcessCUI(void) { BOOL use_cui; DWORD cp_flags; - enum inheritance_model inherit; + unsigned args; DWORD expected; BOOL is_todo; DWORD is_broken; } no_console_tests[] = { -/* 0*/ {FALSE, 0, NULL_STD, CP_STRMIO_NONE}, - {FALSE, DETACHED_PROCESS, NULL_STD, CP_STRMIO_NONE}, - {FALSE, CREATE_NEW_CONSOLE, NULL_STD, CP_STRMIO_NONE}, - {FALSE, CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, - {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, -/* 5*/ {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, - - {TRUE, 0, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, - {TRUE, DETACHED_PROCESS, NULL_STD, CP_STRMIO_NONE}, - {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, CP_STRMIO_NONE}, - {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, CP_OWN_CONSOLE | CP_WITH_WINDOW}, +/* 0*/ {FALSE, 0, STD_NULL, CP_STRMIO_NONE}, + {FALSE, DETACHED_PROCESS, STD_NULL, CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_CONSOLE, STD_NULL, CP_STRMIO_NONE}, + {FALSE, CREATE_NO_WINDOW, STD_NULL, CP_STRMIO_NONE}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, STD_NULL, CP_STRMIO_NONE}, +/* 5*/ {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STD_NULL, CP_STRMIO_NONE}, + + {TRUE, 0, STD_NULL, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + {TRUE, DETACHED_PROCESS, STD_NULL, CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_CONSOLE, STD_NULL, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + {TRUE, CREATE_NO_WINDOW, STD_NULL, CP_OWN_CONSOLE}, +/*10*/ {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, STD_NULL, CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STD_NULL, CP_OWN_CONSOLE | CP_WITH_WINDOW}, }, with_console_tests[] = { -/* 0*/ {FALSE, 0, NULL_STD, CP_STRMIO_NONE}, - {FALSE, DETACHED_PROCESS, NULL_STD, CP_STRMIO_NONE}, - {FALSE, CREATE_NEW_CONSOLE, NULL_STD, CP_STRMIO_NONE}, - {FALSE, CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, - {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, -/* 5*/ {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, NULL_STD, CP_STRMIO_NONE}, - - {FALSE, 0, CONSOLE_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, - {FALSE, DETACHED_PROCESS, CONSOLE_STD, CP_STRMIO_NONE}, - {FALSE, CREATE_NEW_CONSOLE, CONSOLE_STD, CP_STRMIO_NONE}, - {FALSE, CREATE_NO_WINDOW, CONSOLE_STD, CP_STRMIO_NONE, TRUE}, -/*10*/ {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, CONSOLE_STD, CP_STRMIO_NONE}, - {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, CONSOLE_STD, CP_STRMIO_NONE}, - - {FALSE, 0, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, - {FALSE, DETACHED_PROCESS, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, - {FALSE, CREATE_NEW_CONSOLE, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, -/*15*/ {FALSE, CREATE_NO_WINDOW, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, - {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, - {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STARTUPINFO_STD, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, - - {TRUE, 0, NULL_STD, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE}, - {TRUE, DETACHED_PROCESS, NULL_STD, CP_STRMIO_NONE}, -/*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, CP_STRMIO_NONE}, - {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, CP_STRMIO_NONE}, - {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, CP_STRMIO_NONE}, - {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_STRMIO_CHAR, .is_broken = CP_BROKEN}, - {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_STRMIO_CHAR, .is_broken = CP_BROKEN}, -/*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}, +/* 0*/ {FALSE, 0, STD_NULL, CP_STRMIO_NONE}, + {FALSE, DETACHED_PROCESS, STD_NULL, CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_CONSOLE, STD_NULL, CP_STRMIO_NONE}, + {FALSE, CREATE_NO_WINDOW, STD_NULL, CP_STRMIO_NONE}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, STD_NULL, CP_STRMIO_NONE}, +/* 5*/ {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STD_NULL, CP_STRMIO_NONE}, + + {FALSE, 0, STD_CONSOLE, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, DETACHED_PROCESS, STD_CONSOLE, CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_CONSOLE, STD_CONSOLE, CP_STRMIO_NONE}, + {FALSE, CREATE_NO_WINDOW, STD_CONSOLE, CP_STRMIO_NONE, TRUE}, +/*10*/ {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, STD_CONSOLE, CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STD_CONSOLE, CP_STRMIO_NONE}, + + {FALSE, 0, STINFO_CONSOLE, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, DETACHED_PROCESS, STINFO_CONSOLE, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, CREATE_NEW_CONSOLE, STINFO_CONSOLE, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, +/*15*/ {FALSE, CREATE_NO_WINDOW, STINFO_CONSOLE, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, DETACHED_PROCESS | CREATE_NO_WINDOW, STINFO_CONSOLE, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + {FALSE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STINFO_CONSOLE, CP_STRMIO_NONE, TRUE, .is_broken = CP_BROKEN}, + + {TRUE, 0, STD_NULL, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE}, + {TRUE, DETACHED_PROCESS, STD_NULL, CP_STRMIO_NONE}, +/*20*/ {TRUE, CREATE_NEW_CONSOLE, STD_NULL, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + {TRUE, CREATE_NO_WINDOW, STD_NULL, CP_OWN_CONSOLE}, + {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, STD_NULL, CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STD_NULL, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + + {TRUE, 0, STD_CONSOLE, CP_INH_CONSOLE | CP_WITH_WINDOW}, +/*25*/ {TRUE, DETACHED_PROCESS, STD_CONSOLE, CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_CONSOLE, STD_CONSOLE, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + {TRUE, CREATE_NO_WINDOW, STD_CONSOLE, CP_OWN_CONSOLE}, + {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, STD_CONSOLE, CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STD_CONSOLE, CP_OWN_CONSOLE | CP_WITH_WINDOW}, + +/*30*/ {TRUE, 0, STINFO_CONSOLE, CP_INH_CONSOLE | CP_WITH_WINDOW}, + {TRUE, DETACHED_PROCESS, STINFO_CONSOLE, CP_STRMIO_CHAR, .is_broken = CP_BROKEN}, + {TRUE, CREATE_NEW_CONSOLE, STINFO_CONSOLE, CP_OWN_CONSOLE | CP_WITH_WINDOW, .is_broken = CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE}, + {TRUE, CREATE_NO_WINDOW, STINFO_CONSOLE, CP_OWN_CONSOLE, .is_broken = CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE}, + {TRUE, DETACHED_PROCESS | CREATE_NO_WINDOW, STINFO_CONSOLE, CP_STRMIO_CHAR, .is_broken = CP_BROKEN}, +/*35*/ {TRUE, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW, STINFO_CONSOLE, CP_OWN_CONSOLE | CP_WITH_WINDOW, .is_broken = CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE}, }; static struct group_flags_tests { /* input */ BOOL use_cui; DWORD cp_flags; - enum inheritance_model inherit; + unsigned args; BOOL noctrl_flag; /* output */ DWORD expected; BOOL is_todo; - DWORD is_broken; + BOOL is_broken; /* Win7: console are of UNKNOWN file type */ } group_flags_tests[] = { -/* 0 */ {TRUE, 0, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW}, - {TRUE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, - {TRUE, 0, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_ENABLED_CTRLC}, - {TRUE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, - {TRUE, 0, STARTUPINFO_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW}, -/* 5 */ {TRUE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, - {TRUE, 0, STARTUPINFO_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_ENABLED_CTRLC}, - {TRUE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, - {FALSE, 0, CONSOLE_STD, TRUE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, - {FALSE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, -/* 10 */ {FALSE, 0, CONSOLE_STD, FALSE, CP_ENABLED_CTRLC | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_ENABLED_CTRLC}, - {FALSE, CREATE_NEW_PROCESS_GROUP, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, - {FALSE, 0, STARTUPINFO_STD, TRUE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, - {FALSE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, - {FALSE, 0, STARTUPINFO_STD, FALSE, CP_ENABLED_CTRLC | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_ENABLED_CTRLC}, -/* 15 */ {FALSE, CREATE_NEW_PROCESS_GROUP, STARTUPINFO_STD, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, - {TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER | CP_ALONE}, - {FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, - {TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER | CP_ALONE | CP_ENABLED_CTRLC}, - {FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_ENABLED_CTRLC | CP_STRMIO_NONE}, -/* 20 */ {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, - {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, - {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE}, - {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, CONSOLE_STD, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE}, +/* 0 */ {TRUE, 0, STD_CONSOLE, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW}, + {TRUE, CREATE_NEW_PROCESS_GROUP, STD_CONSOLE, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, + {TRUE, 0, STD_CONSOLE, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_ENABLED_CTRLC}, + {TRUE, CREATE_NEW_PROCESS_GROUP, STD_CONSOLE, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, + {TRUE, 0, STINFO_CONSOLE, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW}, +/* 5 */ {TRUE, CREATE_NEW_PROCESS_GROUP, STINFO_CONSOLE, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, + {TRUE, 0, STINFO_CONSOLE, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_ENABLED_CTRLC}, + {TRUE, CREATE_NEW_PROCESS_GROUP, STINFO_CONSOLE, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER}, + {FALSE, 0, STD_CONSOLE, TRUE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, CREATE_NEW_PROCESS_GROUP, STD_CONSOLE, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, +/* 10 */ {FALSE, 0, STD_CONSOLE, FALSE, CP_ENABLED_CTRLC | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_ENABLED_CTRLC}, + {FALSE, CREATE_NEW_PROCESS_GROUP, STD_CONSOLE, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, 0, STINFO_CONSOLE, TRUE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, CREATE_NEW_PROCESS_GROUP, STINFO_CONSOLE, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, 0, STINFO_CONSOLE, FALSE, CP_ENABLED_CTRLC | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_ENABLED_CTRLC}, +/* 15 */ {FALSE, CREATE_NEW_PROCESS_GROUP, STINFO_CONSOLE, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, STD_CONSOLE, TRUE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER | CP_ALONE}, + {FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, STD_CONSOLE, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, STD_CONSOLE, FALSE, CP_INH_CONSOLE | CP_WITH_WINDOW | CP_GROUP_LEADER | CP_ALONE | CP_ENABLED_CTRLC}, + {FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, STD_CONSOLE, FALSE, CP_GROUP_LEADER | CP_ENABLED_CTRLC | CP_STRMIO_NONE}, +/* 20 */ {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, STD_CONSOLE, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, STD_CONSOLE, TRUE, CP_GROUP_LEADER | CP_STRMIO_NONE}, + {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, STD_CONSOLE, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE}, + {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, STD_CONSOLE, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE}, }; hstd[0] = GetStdHandle(STD_INPUT_HANDLE); @@ -5188,7 +5213,7 @@ static void test_CreateProcessCUI(void) { res = check_child_console_bits(no_console_tests[i].use_cui ? cuiexec : guiexec, no_console_tests[i].cp_flags, - no_console_tests[i].inherit, + no_console_tests[i].args, &result); ok(res, "Couldn't run child\n"); todo_wine_if(no_console_tests[i].is_todo) @@ -5202,7 +5227,7 @@ static void test_CreateProcessCUI(void) { res = check_child_console_bits(with_console_tests[i].use_cui ? cuiexec : guiexec, with_console_tests[i].cp_flags, - with_console_tests[i].inherit, + with_console_tests[i].args, &result); ok(res, "Couldn't run child\n"); todo_wine_if(with_console_tests[i].is_todo) @@ -5220,7 +5245,7 @@ static void test_CreateProcessCUI(void) ok(res, "Couldn't set ctrl handler\n"); res = check_child_console_bits(group_flags_tests[i].use_cui ? cuiexec : guiexec, group_flags_tests[i].cp_flags, - group_flags_tests[i].inherit, + group_flags_tests[i].args, &result); todo_wine_if(group_flags_tests[i].is_todo) ok(result.bitmask == group_flags_tests[i].expected || -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4378
From: Eric Pouech <epouech(a)codeweavers.com> Signed-off-by: Eric Pouech <epouech(a)codeweavers.com> --- dlls/kernel32/tests/console.c | 157 +++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 4 deletions(-) diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 5ae1bdc4c62..c0c520b71fe 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4938,7 +4938,7 @@ static BOOL save_blackbox(const char* file, void* blackbox, int size) return TRUE; } -enum inheritance_model {H_NULL, H_CONSOLE, H_FILE}; +enum inheritance_model {H_NULL, H_INVALID, H_DEVIL, H_CONSOLE, H_DISK, H_CHAR, H_PIPE}; #define ARG_STD 0x80000000 #define ARG_STARTUPINFO 0x00000000 @@ -4947,11 +4947,19 @@ enum inheritance_model {H_NULL, H_CONSOLE, H_FILE}; #define ARG_MODEL_MASK (~0xff000000) #define STD_NULL (ARG_STD | H_NULL) +#define STD_INVALID (ARG_STD | H_INVALID) +#define STD_DEVIL (ARG_STD | H_DEVIL) #define STD_CONSOLE (ARG_STD | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_CONSOLE) -#define STD_FILE (ARG_STD | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_FILE) +#define STD_CHAR (ARG_STD | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_CHAR) +#define STD_DISK (ARG_STD | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_DISK) +#define STD_PIPE (ARG_STD | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_PIPE) #define STINFO_NULL (ARG_STARTUPINFO | H_NULL) +#define STINFO_INVALID (ARG_STARTUPINFO | H_INVALID) +#define STINFO_DEVIL (ARG_STARTUPINFO | H_DEVIL) #define STINFO_CONSOLE (ARG_STARTUPINFO | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_CONSOLE) -#define STINFO_FILE (ARG_STARTUPINFO | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_FILE) +#define STINFO_CHAR (ARG_STARTUPINFO | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_CHAR) +#define STINFO_DISK (ARG_STARTUPINFO | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_DISK) +#define STINFO_PIPE (ARG_STARTUPINFO | ARG_CP_INHERIT | ARG_HANDLE_INHERIT | H_PIPE) struct black_box { @@ -4971,6 +4979,7 @@ static BOOL check_child_console_bits(const char* exec, DWORD flags, unsigned arg DWORD ret; BOOL needs_close = FALSE; char blackbox_file[MAX_PATH]; + char file[MAX_PATH] = {'\0'}; HANDLE hin, hout, herr; get_temp_file_name(blackbox_file); @@ -4987,6 +4996,14 @@ static BOOL check_child_console_bits(const char* exec, DWORD flags, unsigned arg case H_NULL: hin = hout = herr = NULL; break; + case H_INVALID: + hin = hout = herr = INVALID_HANDLE_VALUE; + break; + case H_DEVIL: + hin = (HANDLE)(ULONG_PTR)0x666000; + hout = (HANDLE)(ULONG_PTR)0x666100; + herr = (HANDLE)(ULONG_PTR)0x666200; + break; case H_CONSOLE: hin = CreateFileA("CONIN$", GENERIC_READ, 0, psa, OPEN_EXISTING, 0, 0); ok(hin != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); @@ -4995,7 +5012,7 @@ static BOOL check_child_console_bits(const char* exec, DWORD flags, unsigned arg herr = hout; needs_close = TRUE; break; - case H_FILE: + case H_CHAR: hin = CreateFileA("NUL", GENERIC_READ, 0, psa, OPEN_EXISTING, 0, 0); ok(hin != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); hout = CreateFileA("NUL", GENERIC_READ|GENERIC_WRITE, 0, psa, OPEN_EXISTING, 0, 0); @@ -5003,6 +5020,21 @@ static BOOL check_child_console_bits(const char* exec, DWORD flags, unsigned arg herr = hout; needs_close = TRUE; break; + case H_DISK: + get_temp_file_name(file); + hin = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, psa, OPEN_EXISTING, 0, 0); + ok(hin != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + hout = CreateFileA(file, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, psa, OPEN_EXISTING, 0, 0); + ok(hout != INVALID_HANDLE_VALUE, "Couldn't create input to console\n"); + herr = hout; + needs_close = TRUE; + break; + case H_PIPE: + res = CreatePipe(&hin, &hout, psa, 0); + ok(res, "Couldn't create anon pipe\n"); + needs_close = TRUE; + herr = hout; + break; default: ok(0, "Unsupported handle type %x\n", args & ARG_MODEL_MASK); return FALSE; @@ -5037,6 +5069,7 @@ static BOOL check_child_console_bits(const char* exec, DWORD flags, unsigned arg } if (res) res = load_blackbox(blackbox_file, result, sizeof(*result)); + if (file[0]) DeleteFileA(file); DeleteFileA(blackbox_file); return res; } @@ -5068,8 +5101,15 @@ static BOOL check_child_console_bits(const char* exec, DWORD flags, unsigned arg #define CP_OUTPUT_STREAM 1 #define CP_STRMIO_NONE (CP_STREAM_(CP_STREAM_ATTR_NULL, CP_INPUT_STREAM) | CP_STREAM_(CP_STREAM_ATTR_NULL, CP_OUTPUT_STREAM)) +#define CP_STRMIO_INVALID (CP_STREAM_(CP_STREAM_ATTR_INVALID, CP_INPUT_STREAM) | CP_STREAM_(CP_STREAM_ATTR_INVALID, CP_OUTPUT_STREAM)) +#define CP_STRMIO_GARBAGE (CP_STREAM_(CP_STREAM_ATTR_GARBAGE, CP_INPUT_STREAM) | CP_STREAM_(CP_STREAM_ATTR_GARBAGE, CP_OUTPUT_STREAM)) +#define CP_INHERIT (CP_STREAM_(CP_STREAM_INHERIT, CP_INPUT_STREAM) | CP_STREAM_(CP_STREAM_INHERIT, CP_OUTPUT_STREAM)) #define CP_STRMIO_CHAR (CP_STREAM_(CP_STREAM_INHERIT | CP_STREAM_ATTR_TYPE | FILE_TYPE_CHAR, CP_INPUT_STREAM) | \ CP_STREAM_(CP_STREAM_INHERIT | CP_STREAM_ATTR_TYPE | FILE_TYPE_CHAR, CP_OUTPUT_STREAM)) +#define CP_STRMIO_DISK (CP_STREAM_(CP_STREAM_INHERIT | CP_STREAM_ATTR_TYPE | FILE_TYPE_DISK, CP_INPUT_STREAM) | \ + CP_STREAM_(CP_STREAM_INHERIT | CP_STREAM_ATTR_TYPE | FILE_TYPE_DISK, CP_OUTPUT_STREAM)) +#define CP_STRMIO_PIPE (CP_STREAM_(CP_STREAM_INHERIT | CP_STREAM_ATTR_TYPE | FILE_TYPE_PIPE, CP_INPUT_STREAM) | \ + CP_STREAM_(CP_STREAM_INHERIT | CP_STREAM_ATTR_TYPE | FILE_TYPE_PIPE, CP_OUTPUT_STREAM)) #define CP_HAS_CONSOLE_WIN (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW) #define CP_OWN_CONSOLE (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_STRMIO_CHAR | CP_ALONE) @@ -5194,6 +5234,102 @@ static void test_CreateProcessCUI(void) {TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, STD_CONSOLE, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE}, {FALSE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, STD_CONSOLE, FALSE, CP_GROUP_LEADER | CP_STRMIO_NONE}, }; + static struct std_handles_inh_tests + { + /* input */ + BOOL use_cui; + unsigned args; + /* output */ + DWORD expected; + BOOL is_todo; + DWORD is_broken; /* Win7 broken file type */ + } + std_handles_inh_tests[] = + { +/* 0*/ {FALSE, STINFO_DISK, CP_STRMIO_DISK}, + {FALSE, STD_DISK, CP_STRMIO_DISK}, + {FALSE, STINFO_PIPE, CP_STRMIO_PIPE}, + {FALSE, STD_PIPE, CP_STRMIO_PIPE}, + {FALSE, STINFO_CHAR, CP_STRMIO_CHAR}, +/* 5*/ {FALSE, STD_CHAR, CP_STRMIO_CHAR}, + + /* no handle inheritance flags in CreateProcess */ + {FALSE, ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_DISK, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | ARG_HANDLE_INHERIT | H_DISK, CP_STRMIO_NONE, .is_todo = TRUE}, + {FALSE, ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_CHAR, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | ARG_HANDLE_INHERIT | H_CHAR, CP_STRMIO_NONE, .is_todo = TRUE}, +/*10*/ {FALSE, ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_PIPE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | ARG_HANDLE_INHERIT | H_PIPE, CP_STRMIO_NONE, .is_todo = TRUE}, + {FALSE, ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_CONSOLE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | ARG_HANDLE_INHERIT | H_CONSOLE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + + /* passed handles are not inheritable */ + {FALSE, ARG_STARTUPINFO | ARG_CP_INHERIT | H_DISK, CP_STRMIO_GARBAGE, .is_todo = TRUE, .is_broken = CP_BROKEN}, +/*15*/ {FALSE, ARG_STD | ARG_CP_INHERIT | H_DISK, CP_STRMIO_GARBAGE, .is_todo = TRUE}, + {FALSE, ARG_STARTUPINFO | ARG_CP_INHERIT | H_CHAR, CP_STRMIO_GARBAGE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | ARG_CP_INHERIT | H_CHAR, CP_STRMIO_GARBAGE, .is_todo = TRUE}, + {FALSE, ARG_STARTUPINFO | ARG_CP_INHERIT | H_PIPE, CP_STRMIO_GARBAGE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | ARG_CP_INHERIT | H_PIPE, CP_STRMIO_GARBAGE, .is_todo = TRUE}, +/*20*/ {FALSE, ARG_STARTUPINFO | ARG_CP_INHERIT | H_CONSOLE, CP_STRMIO_GARBAGE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | ARG_CP_INHERIT | H_CONSOLE, CP_STRMIO_GARBAGE, .is_todo = TRUE}, + + /* no inheritance (CreateProcess and handle) */ + {FALSE, ARG_STARTUPINFO | H_DISK, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | H_DISK, CP_STRMIO_NONE, .is_todo = TRUE}, + {FALSE, ARG_STARTUPINFO | H_CHAR, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, +/*25*/ {FALSE, ARG_STD | H_CHAR, CP_STRMIO_NONE, .is_todo = TRUE}, + {FALSE, ARG_STARTUPINFO | H_PIPE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | H_PIPE, CP_STRMIO_NONE, .is_todo = TRUE}, + {FALSE, ARG_STARTUPINFO | H_CONSOLE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {FALSE, ARG_STD | H_CONSOLE, CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + +/*30*/ {FALSE, STINFO_DEVIL, CP_STRMIO_NONE, .is_broken = CP_BROKEN}, + {FALSE, STD_DEVIL, CP_STRMIO_NONE, .is_broken = CP_STRMIO_INVALID}, + {FALSE, STINFO_INVALID, CP_STRMIO_NONE, .is_broken = CP_STRMIO_INVALID}, + {FALSE, STD_INVALID, CP_STRMIO_NONE}, + + {TRUE, STINFO_DISK, CP_HAS_CONSOLE_WIN | CP_STRMIO_DISK}, +/*35*/ {TRUE, STD_DISK, CP_HAS_CONSOLE_WIN | CP_STRMIO_DISK}, + {TRUE, STINFO_PIPE, CP_HAS_CONSOLE_WIN | CP_STRMIO_PIPE}, + {TRUE, STD_PIPE, CP_HAS_CONSOLE_WIN | CP_STRMIO_PIPE}, + {TRUE, STINFO_CHAR, CP_HAS_CONSOLE_WIN | CP_STRMIO_CHAR}, + {TRUE, STD_CHAR, CP_HAS_CONSOLE_WIN | CP_STRMIO_CHAR}, + + /* no handle inheritance flags in CreateProcess */ +/*40*/ {TRUE, ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_DISK, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | ARG_HANDLE_INHERIT | H_DISK, CP_HAS_CONSOLE_WIN | CP_STRMIO_DISK}, + {TRUE, ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_CHAR, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | ARG_HANDLE_INHERIT | H_CHAR, CP_HAS_CONSOLE_WIN | CP_STRMIO_CHAR}, + {TRUE, ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_PIPE, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, +/*45*/ {TRUE, ARG_STD | ARG_HANDLE_INHERIT | H_PIPE, CP_HAS_CONSOLE_WIN | CP_STRMIO_PIPE}, + {TRUE, ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_CONSOLE, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_STRMIO_CHAR}, + {TRUE, ARG_STD | ARG_HANDLE_INHERIT | H_CONSOLE, CP_HAS_CONSOLE_WIN | CP_STRMIO_CHAR}, + + /* passed handles are not inheritable */ + {TRUE, ARG_STARTUPINFO | ARG_CP_INHERIT | H_DISK, CP_HAS_CONSOLE_WIN | CP_STRMIO_GARBAGE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | ARG_CP_INHERIT | H_DISK, CP_HAS_CONSOLE_WIN | CP_STRMIO_GARBAGE, .is_todo = TRUE}, +/*50*/ {TRUE, ARG_STARTUPINFO | ARG_CP_INHERIT | H_CHAR, CP_HAS_CONSOLE_WIN | CP_STRMIO_GARBAGE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | ARG_CP_INHERIT | H_CHAR, CP_HAS_CONSOLE_WIN | CP_STRMIO_GARBAGE, .is_todo = TRUE}, + {TRUE, ARG_STARTUPINFO | ARG_CP_INHERIT | H_PIPE, CP_HAS_CONSOLE_WIN | CP_STRMIO_GARBAGE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | ARG_CP_INHERIT | H_PIPE, CP_HAS_CONSOLE_WIN | CP_STRMIO_GARBAGE, .is_todo = TRUE}, + {TRUE, ARG_STARTUPINFO | ARG_CP_INHERIT | H_CONSOLE, CP_HAS_CONSOLE_WIN | CP_STRMIO_GARBAGE, .is_todo = TRUE, .is_broken = CP_BROKEN}, +/*55*/ {TRUE, ARG_STD | ARG_CP_INHERIT | H_CONSOLE, CP_HAS_CONSOLE_WIN | CP_STRMIO_GARBAGE, .is_todo = TRUE}, + + /* no inheritance (CreateProcess and handle) */ + {TRUE, ARG_STARTUPINFO | H_DISK, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | H_DISK, CP_HAS_CONSOLE_WIN | (CP_STRMIO_DISK & ~CP_INHERIT), .is_todo = TRUE}, + {TRUE, ARG_STARTUPINFO | H_CHAR, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | H_CHAR, CP_HAS_CONSOLE_WIN | (CP_STRMIO_CHAR & ~CP_INHERIT), .is_todo = TRUE}, +/*60*/ {TRUE, ARG_STARTUPINFO | H_PIPE, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | H_PIPE, CP_HAS_CONSOLE_WIN | (CP_STRMIO_PIPE & ~CP_INHERIT), .is_todo = TRUE}, + {TRUE, ARG_STARTUPINFO | H_CONSOLE, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_todo = TRUE, .is_broken = CP_BROKEN}, + {TRUE, ARG_STD | H_CONSOLE, CP_HAS_CONSOLE_WIN | (CP_STRMIO_CHAR & ~CP_INHERIT), .is_todo = TRUE, .is_broken = CP_BROKEN}, + + {TRUE, STINFO_DEVIL, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_broken = CP_BROKEN}, +/*xx*/ {TRUE, STD_DEVIL, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE}, + {TRUE, STINFO_INVALID, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_broken = CP_STRMIO_INVALID}, + {TRUE, STD_INVALID, CP_HAS_CONSOLE_WIN | CP_STRMIO_NONE, .is_broken = CP_STREAM_(CP_STREAM_ATTR_TYPE, CP_INPUT_STREAM) | CP_STREAM_(CP_STREAM_ATTR_TYPE, CP_OUTPUT_STREAM)}, + }; hstd[0] = GetStdHandle(STD_INPUT_HANDLE); hstd[1] = GetStdHandle(STD_OUTPUT_HANDLE); @@ -5258,6 +5394,19 @@ static void test_CreateProcessCUI(void) RtlGetCurrentPeb()->ProcessParameters->ConsoleFlags = saved_console_flags; + for (i = 0; i < ARRAY_SIZE(std_handles_inh_tests); i++) + { + res = check_child_console_bits(std_handles_inh_tests[i].use_cui ? cuiexec : guiexec, + 0, std_handles_inh_tests[i].args, + &result); + todo_wine_if(std_handles_inh_tests[i].is_todo) + ok(result.bitmask == std_handles_inh_tests[i].expected || + broken(std_handles_inh_tests[i].is_broken && + result.bitmask == ((std_handles_inh_tests[i].expected & ~CP_STREAM_MASK) | (std_handles_inh_tests[i].is_broken & ~CP_BROKEN))), + "[%d] Unexpected result %x (%lx)\n", + i, result.bitmask, std_handles_inh_tests[i].expected); + } + DeleteFileA(guiexec); DeleteFileA(cuiexec); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4378
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=139846 Your paranoid android. === w10pro64_ja (64 bit report) === kernel32: console.c:5403: Test failed: [14] Unexpected result c00 (0) console.c:5403: Test failed: [15] Unexpected result c (0) console.c:5403: Test failed: [16] Unexpected result c00 (0) console.c:5403: Test failed: [17] Unexpected result c (0) console.c:5403: Test failed: [18] Unexpected result c00 (0) console.c:5403: Test failed: [19] Unexpected result c (0)
@julliard putting on hold for now (hence the draft status) this MR still needs improvement (it relies on Windows behavior to detect invalid handles which needs rework ; it depends on the other change of msvcrt for initial handles which shows issues in CreateProcess =\> so need to break the vicious circle somehow) and likely, shall integrate the tests into tests/process.c (there's likely quite some overlap) and reduce the number of tests -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4378#note_52377
This merge request was closed by eric pouech. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4378
participants (3)
-
Eric Pouech -
eric pouech (@epo) -
Marvin