From: Eric Pouech epouech@codeweavers.com
We were using bit 1 of RTL_USER_PROCESS_PARAMETERS for two different cases: - rightfully, as a sign to block ctrl-c events from being processed by handlers (and by default, terminating the process) - But this was also used to request for the creation of a new process group.
This patch properly separates the two use cases, by using the ProcessGroupId field in RTL_USER_PROCESS_PARAMETERS (checked that Win10 behaves as this patch in RtlCreateUserProcess wrt. RTL_USER_PROCESS_PARAMETERS ProcessGroupId usage input/output).
Introduce process_group_id in startup_info_t and use it to pass it to server. ProcessGroupId field in RTL_USER_PROCESS_PARAMETERS is now properly set.
Note: this will change some external behavior. - before this patch, a child process created with Ctrl-C disabled (ConsoleFlags set), couldn't turn it on as the process was detached from unix console. - now, SIGINT handling is moved to kernelbase (and can be turned on/off at application will), - when creating a new windows group id, the child will be detached from unix console, so will no longer receives the SIGINT from ctrl-c in unix console (if parent was attached to this unix console).
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/console.c | 8 ++++---- dlls/kernelbase/process.c | 6 +++++- dlls/ntdll/env.c | 1 + dlls/ntdll/unix/env.c | 4 ++++ dlls/ntdll/unix/process.c | 4 ++-- include/wine/server_protocol.h | 3 ++- server/process.c | 5 ++++- server/protocol.def | 1 + server/request.h | 2 +- server/trace.c | 5 +++-- tools/make_requests | 2 +- 11 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index 56dc27f2a94..7f66d34dc4c 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -5015,13 +5015,13 @@ static void test_CreateProcessCUI(void) 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, .is_todo = TRUE}, + {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, .is_todo = TRUE}, + {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, .is_todo = TRUE}, +/* 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, .is_todo = TRUE}, + {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}, diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 744474710ad..b6775052699 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -187,7 +187,11 @@ static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename } RtlFreeUnicodeString( &newdirW );
- if (flags & CREATE_NEW_PROCESS_GROUP) params->ConsoleFlags = 1; + if (flags & CREATE_NEW_PROCESS_GROUP) + params->ConsoleFlags = 1; + else + params->ProcessGroupId = NtCurrentTeb()->Peb->ProcessParameters->ProcessGroupId; + if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = CONSOLE_HANDLE_ALLOC; else if (!(flags & DETACHED_PROCESS)) { diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c index ab54a9ec563..04e4ba94563 100644 --- a/dlls/ntdll/env.c +++ b/dlls/ntdll/env.c @@ -684,6 +684,7 @@ void init_user_process_params(void) new_params->dwFillAttribute = params->dwFillAttribute; new_params->dwFlags = params->dwFlags; new_params->wShowWindow = params->wShowWindow; + new_params->ProcessGroupId = params->ProcessGroupId;
NtCurrentTeb()->Peb->ProcessParameters = new_params; NtFreeVirtualMemory( GetCurrentProcess(), (void **)¶ms, &size, MEM_RELEASE ); diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c index 9cd71e4b020..3f00f6f68de 100644 --- a/dlls/ntdll/unix/env.c +++ b/dlls/ntdll/unix/env.c @@ -1823,6 +1823,7 @@ static void *build_wow64_parameters( const RTL_USER_PROCESS_PARAMETERS *params ) wow64_params->dwFillAttribute = params->dwFillAttribute; wow64_params->dwFlags = params->dwFlags; wow64_params->wShowWindow = params->wShowWindow; + wow64_params->ProcessGroupId = params->ProcessGroupId;
dst = (WCHAR *)(wow64_params + 1); dup_unicode_string( ¶ms->CurrentDirectory.DosPath, &dst, &wow64_params->CurrentDirectory.DosPath ); @@ -1981,6 +1982,7 @@ static RTL_USER_PROCESS_PARAMETERS *build_initial_params( void **module ) params->Size = size; params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED; params->wShowWindow = 1; /* SW_SHOWNORMAL */ + params->ProcessGroupId = GetCurrentProcessId();
params->CurrentDirectory.DosPath.Buffer = (WCHAR *)(params + 1); wcscpy( params->CurrentDirectory.DosPath.Buffer, get_dos_path( curdir )); @@ -2079,6 +2081,7 @@ void init_startup_info(void) params->dwFillAttribute = info->attribute; params->dwFlags = info->flags; params->wShowWindow = info->show; + params->ProcessGroupId = info->process_group_id;
src = (WCHAR *)(info + 1); dst = (WCHAR *)(params + 1); @@ -2169,6 +2172,7 @@ void *create_startup_info( const UNICODE_STRING *nt_image, const RTL_USER_PROCES info->attribute = params->dwFillAttribute; info->flags = params->dwFlags; info->show = params->wShowWindow; + info->process_group_id = params->ProcessGroupId;
ptr = info + 1; info->curdir_len = append_string( &ptr, params, ¶ms->CurrentDirectory.DosPath ); diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 30bd6f083bd..4c7e545695c 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -441,7 +441,7 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so { if (!(pid = fork())) /* grandchild */ { - if (params->ConsoleFlags || + if ((peb->ProcessParameters && params->ProcessGroupId != peb->ProcessParameters->ProcessGroupId) || params->ConsoleHandle == CONSOLE_HANDLE_ALLOC || params->ConsoleHandle == CONSOLE_HANDLE_ALLOC_NO_WINDOW || (params->hStdInput == INVALID_HANDLE_VALUE && params->hStdOutput == INVALID_HANDLE_VALUE)) @@ -620,7 +620,7 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir, { close( fd[0] );
- if (params->ConsoleFlags || + if ((peb->ProcessParameters && params->ProcessGroupId != peb->ProcessParameters->ProcessGroupId) || params->ConsoleHandle == CONSOLE_HANDLE_ALLOC || params->ConsoleHandle == CONSOLE_HANDLE_ALLOC_NO_WINDOW || (params->hStdInput == INVALID_HANDLE_VALUE && params->hStdOutput == INVALID_HANDLE_VALUE)) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index e610a8941d7..52228a33b00 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -208,6 +208,7 @@ typedef struct unsigned int attribute; unsigned int flags; unsigned int show; + process_id_t process_group_id; data_size_t curdir_len; data_size_t dllpath_len; data_size_t imagepath_len; @@ -6456,7 +6457,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 780 +#define SERVER_PROTOCOL_VERSION 781
/* ### protocol_version end ### */
diff --git a/server/process.c b/server/process.c index 20d7fa678d5..a0d5ea64d97 100644 --- a/server/process.c +++ b/server/process.c @@ -1358,7 +1358,10 @@ DECL_HANDLER(new_process) /* debug_children is set to 1 by default */ }
- if (!info->data->console_flags) process->group_id = parent->group_id; + if (info->data->process_group_id == parent->group_id) + process->group_id = parent->group_id; + else + info->data->process_group_id = process->group_id;
info->process = (struct process *)grab_object( process ); reply->info = alloc_handle( current->process, info, SYNCHRONIZE, 0 ); diff --git a/server/protocol.def b/server/protocol.def index 919297c818c..68008f8a02b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -224,6 +224,7 @@ typedef struct unsigned int attribute; unsigned int flags; unsigned int show; + process_id_t process_group_id; data_size_t curdir_len; data_size_t dllpath_len; data_size_t imagepath_len; diff --git a/server/request.h b/server/request.h index de0931ab763..b550fbd77fa 100644 --- a/server/request.h +++ b/server/request.h @@ -721,7 +721,7 @@ C_ASSERT( sizeof(property_data_t) == 16 ); C_ASSERT( sizeof(rectangle_t) == 16 ); C_ASSERT( sizeof(select_op_t) == 264 ); C_ASSERT( sizeof(short int) == 2 ); -C_ASSERT( sizeof(startup_info_t) == 92 ); +C_ASSERT( sizeof(startup_info_t) == 96 ); C_ASSERT( sizeof(struct filesystem_event) == 12 ); C_ASSERT( sizeof(struct handle_info) == 20 ); C_ASSERT( sizeof(struct luid) == 8 ); diff --git a/server/trace.c b/server/trace.c index 58a31670ea3..f99591c7b1f 100644 --- a/server/trace.c +++ b/server/trace.c @@ -960,10 +960,11 @@ static void dump_varargs_startup_info( const char *prefix, data_size_t size )
fprintf( stderr, "%s{debug_flags=%x,console_flags=%x,console=%04x,hstdin=%04x,hstdout=%04x,hstderr=%04x," - "x=%u,y=%u,xsize=%u,ysize=%u,xchars=%u,ychars=%u,attribute=%02x,flags=%x,show=%u", + "x=%u,y=%u,xsize=%u,ysize=%u,xchars=%u,ychars=%u,attribute=%02x,flags=%x,show=%u," + "process_group_id=%u", prefix, info.debug_flags, info.console_flags, info.console, info.hstdin, info.hstdout, info.hstderr, info.x, info.y, info.xsize, info.ysize, - info.xchars, info.ychars, info.attribute, info.flags, info.show ); + info.xchars, info.ychars, info.attribute, info.flags, info.show, info.process_group_id ); pos = dump_inline_unicode_string( ",curdir=L"", pos, info.curdir_len, size ); pos = dump_inline_unicode_string( "",dllpath=L"", pos, info.dllpath_len, size ); pos = dump_inline_unicode_string( "",imagepath=L"", pos, info.imagepath_len, size ); diff --git a/tools/make_requests b/tools/make_requests index ec690642dda..5303ff058df 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -61,7 +61,7 @@ my %formats = "pe_image_info_t" => [ 80, 8 ], "property_data_t" => [ 16, 8 ], "select_op_t" => [ 264, 8 ], - "startup_info_t" => [ 92, 4 ], + "startup_info_t" => [ 96, 4 ], "user_apc_t" => [ 40, 8 ], "struct filesystem_event" => [ 12, 4 ], "struct handle_info" => [ 20, 4 ],