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.
From: Eric Pouech epouech@codeweavers.com
We were limited by the 8 bits of the exit code. Enable at least 32.
Signed-off-by: Eric Pouech epouech@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"))
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@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); }
From: Eric Pouech epouech@codeweavers.com
This will give us more flexibility in following changes.
Signed-off-by: Eric Pouech epouech@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 ||
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@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);
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
This merge request was closed by eric pouech.