From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/console.c | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 398b818776a..744482e40c1 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -5616,6 +5616,117 @@ static void test_CtrlHandlerSubsystem(void) DeleteFileA(cuiexec); }
+#define CFC_VALID_STD_HANDLE 0x01 +#define CFC_CLOSED_BY_FREECONSOLE 0x02 +#define CFC_SAME_OBJECTS 0x04 + +static void test_child_free_console(void) +{ + HANDLE std, std_clone = NULL; + unsigned exit_code = 0; + DWORD dw; + + std = GetStdHandle(STD_ERROR_HANDLE); + if (GetHandleInformation(std, &dw)) + exit_code |= CFC_VALID_STD_HANDLE; + if (std && std != INVALID_HANDLE_VALUE && + !DuplicateHandle(GetCurrentProcess(), std, GetCurrentProcess(), &std_clone, 0, FALSE, DUPLICATE_SAME_ACCESS)) + exit_code |= 0xff; + FreeConsole(); + if ((exit_code & CFC_VALID_STD_HANDLE) && !GetHandleInformation(std, &dw)) + { + exit_code |= CFC_CLOSED_BY_FREECONSOLE; + SetStdHandle(STD_ERROR_HANDLE, NULL); /* so that we can grab the new std handle set by AllocConsole() */ + } + AllocConsole(); /* need a new console so that the unbound handles point to something */ + + if (std && std != INVALID_HANDLE_VALUE && !NtCompareObjects(std_clone, GetStdHandle(STD_ERROR_HANDLE))) + exit_code |= CFC_SAME_OBJECTS; + + CloseHandle(std_clone); + ExitProcess(exit_code); +} + +static void test_FreeConsoleStd(void) +{ + char buf[MAX_PATH], **argv; + HANDLE saved_std; + unsigned i; + BOOL ret; + STARTUPINFOA si = {sizeof(si)}; + PROCESS_INFORMATION info; + DWORD status; + + static const struct + { + DWORD cp_flags; + enum {with_global, with_startupinfo, with_none} with; + unsigned expected_bits; + } + tests[] = + { + {0, with_global, CFC_VALID_STD_HANDLE}, + {0, with_startupinfo, CFC_VALID_STD_HANDLE | CFC_SAME_OBJECTS}, + {CREATE_NEW_CONSOLE, with_global, CFC_VALID_STD_HANDLE | CFC_CLOSED_BY_FREECONSOLE}, + {CREATE_NEW_CONSOLE, with_startupinfo, CFC_VALID_STD_HANDLE | CFC_SAME_OBJECTS}, + {CREATE_NEW_CONSOLE, with_none, CFC_VALID_STD_HANDLE | CFC_CLOSED_BY_FREECONSOLE}, + {DETACHED_PROCESS, with_global, 0}, + {DETACHED_PROCESS, with_startupinfo, CFC_VALID_STD_HANDLE | CFC_SAME_OBJECTS}, + {DETACHED_PROCESS, with_none, 0}, + }; + + if (!pVerifyConsoleIoHandle) + { + win_skip("Can't run test\n"); + return; + } + si.hStdInput = si.hStdOutput = INVALID_HANDLE_VALUE; + winetest_get_mainargs(&argv); + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + winetest_push_context("test[%u]", i); + sprintf(buf, ""%s" console free_console", argv[0]); + switch (tests[i].with) + { + case with_global: + si.dwFlags &= ~STARTF_USESTDHANDLES; + saved_std = GetStdHandle(STD_ERROR_HANDLE); + SetStdHandle(STD_ERROR_HANDLE, create_unbound_handle(TRUE, TRUE)); + break; + case with_startupinfo: + si.dwFlags |= STARTF_USESTDHANDLES; + si.hStdError = create_unbound_handle(TRUE, TRUE); + break; + case with_none: + si.dwFlags &= ~STARTF_USESTDHANDLES; + break; + } + + ret = CreateProcessA(NULL, buf, NULL, NULL, TRUE, tests[i].cp_flags, NULL, NULL, &si, &info); + ok(ret, "got error %lu\n", GetLastError()); + status = WaitForSingleObject(info.hProcess, INFINITE); + ok(status == WAIT_OBJECT_0, "Unexpected wait status\n"); + ret = GetExitCodeProcess(info.hProcess, &status); + ok(status == tests[i].expected_bits, "Expected %x but got %lx\n", tests[i].expected_bits, status); + switch (tests[i].with) + { + case with_global: + CloseHandle(GetStdHandle(STD_ERROR_HANDLE)); + SetStdHandle(STD_ERROR_HANDLE, saved_std); + break; + case with_startupinfo: + CloseHandle(si.hStdError); + break; + case with_none: + break; + } + + CloseHandle(info.hProcess); + CloseHandle(info.hThread); + winetest_pop_context(); + } +} + START_TEST(console) { HANDLE hConIn, hConOut, revert_output = NULL, unbound_output; @@ -5717,6 +5828,12 @@ START_TEST(console) return; }
+ if (argc >= 3 && !strcmp(argv[2], "free_console")) + { + test_child_free_console(); + return; + } + test_current = argc >= 3 && !strcmp(argv[2], "--current"); using_pseudo_console = argc >= 3 && !strcmp(argv[2], "--pseudo-console");
@@ -5906,6 +6023,7 @@ START_TEST(console) test_console_as_root_directory(); if (!test_current) { + test_FreeConsoleStd(); test_pseudo_console(); test_AttachConsole(hConOut); test_AllocConsole();