The following series is the result of work from - Torge Matties, Jacek Caban and myself - and went through various convergence, merges, rewrite and improvements (especially patch #2 for various authors)
it provides: - support for CREATE_NO_WINDOW flag in CreateProcess - a solution for regression introduced in f034084d49b354811096524d472ae5172ac1cebf (when a Wine initial process isn't attached to a unix console, it can generates lots new console window creation, with unwanted side effects) - with the correspondings non regression tests
Signed-off-by: Eric Pouech eric.pouech@gmail.com ---
Eric Pouech (4): dlls/kernel32/tests: Add more CreateProcess console management tests. dlls/{ntdll, kernel*}: Add support for CREATE_NO_WINDOW flag in CreateProcess. dlls/{ntdll,kernel*}: provide a pseudo console environment for initial CUI processes not tied to an Unix tty dlls/kernel32/tests: added tests for CreateProcess on a shell_no_window console
dlls/kernel32/tests/console.c | 126 ++++++++++++++++++++++++++++++---- dlls/kernelbase/console.c | 44 +++++++++--- dlls/kernelbase/process.c | 11 +-- dlls/ntdll/unix/env.c | 2 + dlls/ntdll/unix/process.c | 2 + include/wine/condrv.h | 6 +- programs/conhost/conhost.c | 11 ++- programs/conhost/conhost.h | 1 + server/process.c | 4 +- 9 files changed, 172 insertions(+), 35 deletions(-)
- check for console bits after create process - add tests for CREATE_NO_WINDOW flag in CreateProcess
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/kernel32/tests/console.c | 91 +++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 14 deletions(-)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 98692760acf..91136683f73 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4689,7 +4689,7 @@ static void copy_change_subsystem(const char* in, const char* out, DWORD subsyst CloseHandle(hFile); }
-static BOOL check_whether_child_attached(const char* exec, DWORD flags) +static DWORD check_child_console_bits(const char* exec, DWORD flags) { STARTUPINFOA si = { sizeof(si) }; PROCESS_INFORMATION info; @@ -4705,12 +4705,18 @@ static BOOL check_whether_child_attached(const char* exec, DWORD flags) ret = WaitForSingleObject(info.hProcess, 30000); ok(ret == WAIT_OBJECT_0, "Could not wait for the child process: %ld le=%lu\n", ret, GetLastError()); - ret = GetExitCodeProcess(info.hProcess, &exit_code); - ok(ret && exit_code <= 255, "Couldn't get exit_code\n"); + res = GetExitCodeProcess(info.hProcess, &exit_code); + ok(res && exit_code <= 255, "Couldn't get exit_code\n"); CloseHandle(info.hProcess); - return exit_code != 0; + return exit_code; }
+#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 */ + static void test_CreateProcessCUI(void) { char guiexec[MAX_PATH]; @@ -4728,14 +4734,63 @@ static void test_CreateProcessCUI(void)
FreeConsole();
- res = check_whether_child_attached(guiexec, DETACHED_PROCESS); - ok(!res, "Don't expecting child to be attached to a console\n"); - res = check_whether_child_attached(guiexec, 0); - ok(!res, "Don't expecting child to be attached to a console\n"); - res = check_whether_child_attached(cuiexec, DETACHED_PROCESS); - ok(!res, "Don't expecting child to be attached to a console\n"); - res = check_whether_child_attached(cuiexec, 0); - ok(res, "Expecting child to be attached to a console\n"); + res = check_child_console_bits(guiexec, 0); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, DETACHED_PROCESS); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + + res = check_child_console_bits(cuiexec, 0); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, DETACHED_PROCESS); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NO_WINDOW); + todo_wine + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); + + AllocConsole(); + + res = check_child_console_bits(guiexec, 0); + todo_wine + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, DETACHED_PROCESS); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NO_WINDOW); + todo_wine + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + + res = check_child_console_bits(cuiexec, 0); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, DETACHED_PROCESS); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NO_WINDOW); + todo_wine + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res);
DeleteFileA(guiexec); DeleteFileA(cuiexec); @@ -4769,9 +4824,17 @@ START_TEST(console) return; }
- if (argc == 3 && !strcmp(argv[2], "check_console")) + if (argc >= 3 && !strcmp(argv[2], "check_console")) { - ExitProcess(GetConsoleCP() != 0); + 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; + if (pGetConsoleProcessList && GetConsoleProcessList(&pcslist, 1) == 1) + exit_code |= CP_ALONE; + if (RtlGetCurrentPeb()->ProcessParameters->ProcessGroupId == GetCurrentProcessId()) + exit_code |= CP_GROUP_LEADER; + ExitProcess(exit_code); }
test_current = argc >= 3 && !strcmp(argv[2], "--current");
Signed-off-by: Jacek Caban jacek@codeweavers.com
From Jacek Caban jacek@codeweavers.com
Based on patches by Eric Pouech and Torge Matthies.
v2: Added spawn_process part, spotted and implemented by Eric. v3: Added fork_and_exec, spotted and implemented by Eric.
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/kernel32/tests/console.c | 3 --- dlls/kernelbase/console.c | 21 +++++++++++++++------ dlls/kernelbase/process.c | 11 +++++++---- dlls/ntdll/unix/process.c | 2 ++ include/wine/condrv.h | 5 +++-- programs/conhost/conhost.c | 11 ++++++++--- programs/conhost/conhost.h | 1 + 7 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 91136683f73..72e4f123377 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4754,7 +4754,6 @@ static void test_CreateProcessCUI(void) res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE); ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); res = check_child_console_bits(cuiexec, CREATE_NO_WINDOW); - todo_wine ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE), "Unexpected result %x\n", res); res = check_child_console_bits(cuiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); ok(res == 0, "Unexpected result %x\n", res); @@ -4771,7 +4770,6 @@ static void test_CreateProcessCUI(void) res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE); ok(res == 0, "Unexpected result %x\n", res); res = check_child_console_bits(guiexec, CREATE_NO_WINDOW); - todo_wine ok(res == 0, "Unexpected result %x\n", res); res = check_child_console_bits(guiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); ok(res == 0, "Unexpected result %x\n", res); @@ -4785,7 +4783,6 @@ static void test_CreateProcessCUI(void) res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE); ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); res = check_child_console_bits(cuiexec, CREATE_NO_WINDOW); - todo_wine ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE), "Unexpected result %x\n", res); res = check_child_console_bits(cuiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); ok(res == 0, "Unexpected result %x\n", res); diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c index b2bb6c53fd9..046eee6147c 100644 --- a/dlls/kernelbase/console.c +++ b/dlls/kernelbase/console.c @@ -361,10 +361,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH AttachConsole( DWORD pid ) }
-/****************************************************************** - * AllocConsole (kernelbase.@) - */ -BOOL WINAPI AllocConsole(void) +static BOOL alloc_console( BOOL headless ) { SECURITY_ATTRIBUTES inheritable_attr = { sizeof(inheritable_attr), NULL, TRUE }; STARTUPINFOW app_si, console_si; @@ -419,6 +416,7 @@ BOOL WINAPI AllocConsole(void)
swprintf( conhost_path, ARRAY_SIZE(conhost_path), L"%s\conhost.exe", system_dir ); swprintf( cmd, ARRAY_SIZE(cmd), L""%s" --server 0x%x", conhost_path, condrv_handle( server )); + if (headless) wcscat( cmd, L" --headless" ); Wow64DisableWow64FsRedirection( &redir ); ret = CreateProcessW( conhost_path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &console_si, &pi ); Wow64RevertWow64FsRedirection( redir ); @@ -444,6 +442,15 @@ error: }
+/****************************************************************** + * AllocConsole (kernelbase.@) + */ +BOOL WINAPI AllocConsole(void) +{ + return alloc_console( FALSE ); +} + + /****************************************************************************** * CreateConsoleScreenBuffer (kernelbase.@) */ @@ -2287,12 +2294,14 @@ void init_console( void ) init_console_std_handles( FALSE ); } } - else if (params->ConsoleHandle == CONSOLE_HANDLE_ALLOC) + else if (params->ConsoleHandle == CONSOLE_HANDLE_ALLOC || + params->ConsoleHandle == CONSOLE_HANDLE_ALLOC_NO_WINDOW) { + BOOL no_window = params->ConsoleHandle == CONSOLE_HANDLE_ALLOC_NO_WINDOW; HMODULE mod = GetModuleHandleW( NULL ); params->ConsoleHandle = NULL; if (RtlImageNtHeader( mod )->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) - AllocConsole(); + alloc_console( no_window ); } else if (params->ConsoleHandle) create_console_connection( params->ConsoleHandle ); } diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 1cecbce9321..32f622bdf3e 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -193,8 +193,12 @@ static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC; else if (!(flags & DETACHED_PROCESS)) { - params->ConsoleHandle = NtCurrentTeb()->Peb->ProcessParameters->ConsoleHandle; - if (!params->ConsoleHandle) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC; + if (flags & CREATE_NO_WINDOW) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC_NO_WINDOW; + else + { + params->ConsoleHandle = NtCurrentTeb()->Peb->ProcessParameters->ConsoleHandle; + if (!params->ConsoleHandle) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC; + } }
if (startup->dwFlags & STARTF_USESTDHANDLES) @@ -532,8 +536,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR /* Warn if unsupported features are used */
if (flags & (IDLE_PRIORITY_CLASS | HIGH_PRIORITY_CLASS | REALTIME_PRIORITY_CLASS | - CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW | - PROFILE_USER | PROFILE_KERNEL | PROFILE_SERVER)) + CREATE_DEFAULT_ERROR_MODE | PROFILE_USER | PROFILE_KERNEL | PROFILE_SERVER)) WARN( "(%s,...): ignoring some flags in %lx\n", debugstr_w(app_name), flags );
if (cur_dir) diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 99c8e37053c..078ad75099d 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -445,6 +445,7 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so { if (params->ConsoleFlags || params->ConsoleHandle == CONSOLE_HANDLE_ALLOC || + params->ConsoleHandle == CONSOLE_HANDLE_ALLOC_NO_WINDOW || (params->hStdInput == INVALID_HANDLE_VALUE && params->hStdOutput == INVALID_HANDLE_VALUE)) { setsid(); @@ -585,6 +586,7 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
if (params->ConsoleFlags || params->ConsoleHandle == CONSOLE_HANDLE_ALLOC || + params->ConsoleHandle == CONSOLE_HANDLE_ALLOC_NO_WINDOW || (params->hStdInput == INVALID_HANDLE_VALUE && params->hStdOutput == INVALID_HANDLE_VALUE)) { setsid(); diff --git a/include/wine/condrv.h b/include/wine/condrv.h index 1000e62e765..452ce552da1 100644 --- a/include/wine/condrv.h +++ b/include/wine/condrv.h @@ -188,7 +188,8 @@ struct condrv_ctrl_event };
/* Wine specific values for console inheritance (params->ConsoleHandle) */ -#define CONSOLE_HANDLE_ALLOC ((HANDLE)1) -#define CONSOLE_HANDLE_SHELL ((HANDLE)2) +#define CONSOLE_HANDLE_ALLOC UlongToHandle(1) +#define CONSOLE_HANDLE_ALLOC_NO_WINDOW UlongToHandle(2) +#define CONSOLE_HANDLE_SHELL UlongToHandle(3)
#endif /* _INC_CONDRV */ diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index d494e3f53a5..6ea64395e1a 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -2650,7 +2650,7 @@ static NTSTATUS console_input_ioctl( struct console *console, unsigned int code, TRACE( "get window\n" ); if (in_size || *out_size != sizeof(*result)) return STATUS_INVALID_PARAMETER; if (!(result = alloc_ioctl_buffer( sizeof(*result )))) return STATUS_NO_MEMORY; - if (!console->win) init_message_window( console ); + if (!console->win && !console->no_window) init_message_window( console ); *result = condrv_handle( console->win ); return STATUS_SUCCESS; } @@ -2929,8 +2929,13 @@ int __cdecl wmain(int argc, WCHAR *argv[]) { console.tty_input = GetStdHandle( STD_INPUT_HANDLE ); console.tty_output = GetStdHandle( STD_OUTPUT_HANDLE ); - init_tty_output( &console ); - if (!console.is_unix && !ensure_tty_input_thread( &console )) return 1; + + if (console.tty_input || console.tty_output) + { + init_tty_output( &console ); + if (!console.is_unix && !ensure_tty_input_thread( &console )) return 1; + } + else console.no_window = TRUE; } else { diff --git a/programs/conhost/conhost.h b/programs/conhost/conhost.h index 8ca09bb80d0..65cf5d39ebd 100644 --- a/programs/conhost/conhost.h +++ b/programs/conhost/conhost.h @@ -79,6 +79,7 @@ struct console struct screen_buffer *active; /* active screen buffer */ int is_unix; /* UNIX terminal mode */ int use_relative_cursor; /* use relative cursor positionning */ + int no_window; /* don't create console window */ INPUT_RECORD *records; /* input records */ unsigned int record_count; /* number of input records */ unsigned int record_size; /* size of input records buffer */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=112090
Your paranoid android.
=== debian11 (32 bit Chinese:China report) ===
ntdll: pipe.c:1561: Test failed: pipe is not signaled
Signed-off-by: Jacek Caban jacek@codeweavers.com
should improve situation for various bug reports
https://bugs.winehq.org/show_bug.cgi?id=52771 https://bugs.winehq.org/show_bug.cgi?id=52761 https://bugs.winehq.org/show_bug.cgi?id=52743 Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/kernelbase/console.c | 23 +++++++++++++++++++---- dlls/ntdll/unix/env.c | 2 ++ include/wine/condrv.h | 1 + server/process.c | 4 ++-- 4 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c index 046eee6147c..eddfa5f271e 100644 --- a/dlls/kernelbase/console.c +++ b/dlls/kernelbase/console.c @@ -86,6 +86,17 @@ static BOOL console_ioctl( HANDLE handle, DWORD code, void *in_buff, DWORD in_co IO_STATUS_BLOCK io; NTSTATUS status;
+ if (handle == CONSOLE_HANDLE_SHELL_NO_WINDOW) + { + static unsigned once; + if (!once) + { + FIXME("Incorrect access to Shell-no-window console\n"); + once = TRUE; + } + SetLastError( ERROR_INVALID_ACCESS ); + return FALSE; + } status = NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io, code, in_buff, in_count, out_buff, out_count ); switch( status ) @@ -621,10 +632,13 @@ BOOL WINAPI DECLSPEC_HOTPATCH FreeConsole(void) { RtlEnterCriticalSection( &console_section );
- NtClose( console_connection ); - console_connection = NULL; + if (RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle != CONSOLE_HANDLE_SHELL_NO_WINDOW) + { + NtClose( console_connection ); + console_connection = NULL;
- NtClose( RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle ); + NtClose( RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle ); + } RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
if (console_flags & CONSOLE_INPUT_HANDLE) NtClose( GetStdHandle( STD_INPUT_HANDLE )); @@ -2303,5 +2317,6 @@ void init_console( void ) if (RtlImageNtHeader( mod )->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) alloc_console( no_window ); } - else if (params->ConsoleHandle) create_console_connection( params->ConsoleHandle ); + else if (params->ConsoleHandle && params->ConsoleHandle != CONSOLE_HANDLE_SHELL_NO_WINDOW) + create_console_connection( params->ConsoleHandle ); } diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c index 64117e70abe..2ead6c1fcc3 100644 --- a/dlls/ntdll/unix/env.c +++ b/dlls/ntdll/unix/env.c @@ -1684,6 +1684,8 @@ static void get_initial_console( RTL_USER_PROCESS_PARAMETERS *params ) params->hStdOutput = (HANDLE)((UINT_PTR)params->hStdOutput | 1); output_fd = 1; } + if (!params->ConsoleHandle && main_image_info.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_CUI) + params->ConsoleHandle = CONSOLE_HANDLE_SHELL_NO_WINDOW;
if (output_fd != -1) { diff --git a/include/wine/condrv.h b/include/wine/condrv.h index 452ce552da1..94afb1d49c4 100644 --- a/include/wine/condrv.h +++ b/include/wine/condrv.h @@ -191,5 +191,6 @@ struct condrv_ctrl_event #define CONSOLE_HANDLE_ALLOC UlongToHandle(1) #define CONSOLE_HANDLE_ALLOC_NO_WINDOW UlongToHandle(2) #define CONSOLE_HANDLE_SHELL UlongToHandle(3) +#define CONSOLE_HANDLE_SHELL_NO_WINDOW UlongToHandle(5)
#endif /* _INC_CONDRV */ diff --git a/server/process.c b/server/process.c index 65e2aa70de2..d36ef463d60 100644 --- a/server/process.c +++ b/server/process.c @@ -1333,8 +1333,8 @@ DECL_HANDLER(new_process) /* connect to the window station */ connect_process_winstation( process, parent_thread, parent );
- /* set the process console */ - if (info->data->console > 3) + /* set the process console (caring also for CONSOLE_HANDLE_* values) */ + if (info->data->console > 5 || info->data->console == 4) info->data->console = duplicate_handle( parent, info->data->console, process, 0, 0, DUPLICATE_SAME_ACCESS );
On 4/6/22 17:02, Eric Pouech wrote:
- /* set the process console */
- if (info->data->console > 3)
- /* set the process console (caring also for CONSOLE_HANDLE_* values) */
- if (info->data->console > 5 || info->data->console == 4)
This is not pretty, IMHO...
Thanks,
Jacek
On 4/7/22 19:39, Eric Pouech wrote:
What do you suggest then ? Include condrv.h and test each individual manifest constant ?
I still think that we could use negative values. Collision with other magic handles does not seem concerning to me, since those handles are limited CreateProcess() interface anyway. Another idea would be to use magic lower bits.
BTW, I'd also consider WARN() instead of once+FIXME() for console_ioctl().
Thanks,
Jacek
Le 11/04/2022 à 12:15, Jacek Caban a écrit :
On 4/7/22 19:39, Eric Pouech wrote:
What do you suggest then ? Include condrv.h and test each individual manifest constant ?
I still think that we could use negative values. Collision with other magic handles does not seem concerning to me, since those handles are limited CreateProcess() interface anyway. Another idea would be to use magic lower bits.
well, as tweaking with ConsoleHandle requires a couple of convolutions to get the PROCESS_PARAMS struct, let's assume no app will play with that <g>
I'll resend with negative values then
BTW, I'd also consider WARN() instead of once+FIXME() for console_ioctl().
the rationale behind this one was to be able to track when some program ends up using Console* interface while being attached to the shell_no_screen console type
this could be complicated to track or understand
(actually an ERR would be perhaps more suited than a FIXME)
A+
On 4/11/22 12:42, Eric Pouech wrote:
BTW, I'd also consider WARN() instead of once+FIXME() for console_ioctl().
the rationale behind this one was to be able to track when some program ends up using Console* interface while being attached to the shell_no_screen console type
this could be complicated to track or understand
(actually an ERR would be perhaps more suited than a FIXME)
ERR() is usually for cases that should not happen. Those ioctl()s may legitimately happen and in some cases they may even be desired bevavior, so I'm not sure that any debug channel that is turned on by default is appropriate. I'd hope that retval=0 from a console function call in relay logs will not be too hard to spot (and then +console could clarify that with a WARN()).
Thanks,
Jacek
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/kernel32/tests/console.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 72e4f123377..a74170a898c 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -27,6 +27,7 @@ #include <stdio.h>
#include "wine/test.h" +#include "wine/condrv.h"
static void (WINAPI *pClosePseudoConsole)(HPCON); static HRESULT (WINAPI *pCreatePseudoConsole)(COORD,HANDLE,HANDLE,DWORD,HPCON*); @@ -4716,6 +4717,7 @@ static DWORD check_child_console_bits(const char* exec, DWORD flags) #define CP_WITH_WINDOW 0x04 /* child has a console window */ #define CP_ALONE 0x08 /* whether child is the single process attached to console */ #define CP_GROUP_LEADER 0x10 /* whether the child is the process group leader */ +#define CP_PSEUDO_HANDLE 0x20 /* whether the ConsoleHandle is a pseudo handle */
static void test_CreateProcessCUI(void) { @@ -4760,6 +4762,41 @@ static void test_CreateProcessCUI(void) res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res);
+ /* testing also Wine's only shell_no_window pseudo console */ + if (!strcmp(winetest_platform, "wine")) + { + RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle = CONSOLE_HANDLE_SHELL_NO_WINDOW; + res = check_child_console_bits(guiexec, 0); + todo_wine + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, DETACHED_PROCESS); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(guiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + + res = check_child_console_bits(cuiexec, 0); + /* most of the *Console* calls should fail */ + ok(res == (CP_WITH_HANDLE | CP_PSEUDO_HANDLE), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, DETACHED_PROCESS); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NO_WINDOW); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_ALONE), "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, DETACHED_PROCESS | CREATE_NO_WINDOW); + ok(res == 0, "Unexpected result %x\n", res); + res = check_child_console_bits(cuiexec, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW); + ok(res == (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_WITH_WINDOW | CP_ALONE), "Unexpected result %x\n", res); + + FreeConsole(); + } + AllocConsole();
res = check_child_console_bits(guiexec, 0); @@ -4831,6 +4868,7 @@ START_TEST(console) exit_code |= CP_ALONE; if (RtlGetCurrentPeb()->ProcessParameters->ProcessGroupId == GetCurrentProcessId()) exit_code |= CP_GROUP_LEADER; + if (HandleToUlong(RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle) & 3) exit_code |= CP_PSEUDO_HANDLE; ExitProcess(exit_code); }
Hi Eric,
On 4/6/22 17:02, Eric Pouech wrote:
- /* testing also Wine's only shell_no_window pseudo console */
- if (!strcmp(winetest_platform, "wine"))
We usually don't do this kind of things. I would suggest just to skip this patch.
Thanks,
Jacek