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);