Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/process.c | 103 ++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 26 deletions(-)
diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 2b9b1c019ec..0081b6bf9c8 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -242,26 +242,89 @@ static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename return params; }
+struct proc_thread_attr +{ + DWORD_PTR attr; + SIZE_T size; + void *value; +}; + +struct _PROC_THREAD_ATTRIBUTE_LIST +{ + DWORD mask; /* bitmask of items in list */ + DWORD size; /* max number of items in list */ + DWORD count; /* number of items in list */ + DWORD pad; + DWORD_PTR unk; + struct proc_thread_attr attrs[1]; +};
/*********************************************************************** * create_nt_process */ static NTSTATUS create_nt_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES *tsa, BOOL inherit, DWORD flags, RTL_USER_PROCESS_PARAMETERS *params, - RTL_USER_PROCESS_INFORMATION *info, HANDLE parent ) + RTL_USER_PROCESS_INFORMATION *info, HANDLE parent, + const struct proc_thread_attr *handle_list ) { - NTSTATUS status; + OBJECT_ATTRIBUTES process_attr, thread_attr; + PS_CREATE_INFO create_info; + ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[5] ) / sizeof(ULONG_PTR)]; + PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer; UNICODE_STRING nameW; + NTSTATUS status; + UINT pos = 0;
if (!params->ImagePathName.Buffer[0]) return STATUS_OBJECT_PATH_NOT_FOUND; status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nameW, NULL, NULL ); if (!status) { params->DebugFlags = flags; /* hack, cf. RtlCreateUserProcess implementation */ - status = RtlCreateUserProcess( &nameW, OBJ_CASE_INSENSITIVE, params, - psa ? psa->lpSecurityDescriptor : NULL, - tsa ? tsa->lpSecurityDescriptor : NULL, - parent, inherit, 0, 0, info ); + + RtlNormalizeProcessParams( params ); + + attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_NAME; + attr->Attributes[pos].Size = nameW.Length; + attr->Attributes[pos].ValuePtr = nameW.Buffer; + attr->Attributes[pos].ReturnLength = NULL; + pos++; + attr->Attributes[pos].Attribute = PS_ATTRIBUTE_CLIENT_ID; + attr->Attributes[pos].Size = sizeof(info->ClientId); + attr->Attributes[pos].ValuePtr = &info->ClientId; + attr->Attributes[pos].ReturnLength = NULL; + pos++; + attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_INFO; + attr->Attributes[pos].Size = sizeof(info->ImageInformation); + attr->Attributes[pos].ValuePtr = &info->ImageInformation; + attr->Attributes[pos].ReturnLength = NULL; + pos++; + if (parent) + { + attr->Attributes[pos].Attribute = PS_ATTRIBUTE_PARENT_PROCESS; + attr->Attributes[pos].Size = sizeof(parent); + attr->Attributes[pos].ValuePtr = parent; + attr->Attributes[pos].ReturnLength = NULL; + pos++; + } + if (inherit && handle_list) + { + attr->Attributes[pos].Attribute = PS_ATTRIBUTE_HANDLE_LIST; + attr->Attributes[pos].Size = handle_list->size; + attr->Attributes[pos].ValuePtr = handle_list->value; + attr->Attributes[pos].ReturnLength = NULL; + pos++; + } + attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] ); + + InitializeObjectAttributes( &process_attr, NULL, 0, NULL, psa ? psa->lpSecurityDescriptor : NULL ); + InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, tsa ? tsa->lpSecurityDescriptor : NULL ); + + status = NtCreateUserProcess( &info->Process, &info->Thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, + &process_attr, &thread_attr, + inherit ? PROCESS_CREATE_FLAGS_INHERIT_HANDLES : 0, + THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params, + &create_info, attr ); + RtlFreeUnicodeString( &nameW ); } return status; @@ -292,7 +355,7 @@ static NTSTATUS create_vdm_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTE winevdm, params->ImagePathName.Buffer, params->CommandLine.Buffer ); RtlInitUnicodeString( ¶ms->ImagePathName, winevdm ); RtlInitUnicodeString( ¶ms->CommandLine, newcmdline ); - status = create_nt_process( psa, tsa, inherit, flags, params, info, NULL ); + status = create_nt_process( psa, tsa, inherit, flags, params, info, NULL, NULL ); HeapFree( GetProcessHeap(), 0, newcmdline ); return status; } @@ -320,7 +383,7 @@ static NTSTATUS create_cmd_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTE swprintf( newcmdline, len, L"%s /s/c "%s"", comspec, params->CommandLine.Buffer ); RtlInitUnicodeString( ¶ms->ImagePathName, comspec ); RtlInitUnicodeString( ¶ms->CommandLine, newcmdline ); - status = create_nt_process( psa, tsa, inherit, flags, params, info, NULL ); + status = create_nt_process( psa, tsa, inherit, flags, params, info, NULL, NULL ); RtlFreeHeap( GetProcessHeap(), 0, newcmdline ); return status; } @@ -414,23 +477,6 @@ done: return ret; }
-struct proc_thread_attr -{ - DWORD_PTR attr; - SIZE_T size; - void *value; -}; - -struct _PROC_THREAD_ATTRIBUTE_LIST -{ - DWORD mask; /* bitmask of items in list */ - DWORD size; /* max number of items in list */ - DWORD count; /* number of items in list */ - DWORD pad; - DWORD_PTR unk; - struct proc_thread_attr attrs[1]; -}; - /********************************************************************** * CreateProcessInternalW (kernelbase.@) */ @@ -441,6 +487,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR const WCHAR *cur_dir, STARTUPINFOW *startup_info, PROCESS_INFORMATION *info, HANDLE *new_token ) { + const struct proc_thread_attr *handle_list = NULL; WCHAR name[MAX_PATH]; WCHAR *p, *tidy_cmdline = cmd_line; RTL_USER_PROCESS_PARAMETERS *params = NULL; @@ -517,6 +564,10 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR goto done; } break; + case PROC_THREAD_ATTRIBUTE_HANDLE_LIST: + handle_list = &attrs->attrs[i]; + TRACE("PROC_THREAD_ATTRIBUTE_HANDLE_LIST handle count %Iu.\n", attrs->attrs[i].size / sizeof(HANDLE)); + break; default: FIXME("Unsupported attribute %#Ix.\n", attrs->attrs[i].attr); break; @@ -525,7 +576,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR } }
- status = create_nt_process( process_attr, thread_attr, inherit, flags, params, &rtl_info, parent ); + status = create_nt_process( process_attr, thread_attr, inherit, flags, params, &rtl_info, parent, handle_list ); switch (status) { case STATUS_SUCCESS:
On 8/19/20 15:55, Nikolay Sivov wrote:
if (inherit && handle_list)
{
attr->Attributes[pos].Attribute = PS_ATTRIBUTE_HANDLE_LIST;
attr->Attributes[pos].Size = handle_list->size;
attr->Attributes[pos].ValuePtr = handle_list->value;
attr->Attributes[pos].ReturnLength = NULL;
pos++;
}
Are you sure it should work this way? 'inherit' flag on process creation means that all handles are inherited. I was under impression that PS_ATTRIBUTE_HANDLE_LIST makes sense with inherit set to FALSE only. Can't recall if I ever tested that precisely though.
On 8/19/20 4:03 PM, Paul Gofman wrote:
On 8/19/20 15:55, Nikolay Sivov wrote:
+ if (inherit && handle_list) + { + attr->Attributes[pos].Attribute = PS_ATTRIBUTE_HANDLE_LIST; + attr->Attributes[pos].Size = handle_list->size; + attr->Attributes[pos].ValuePtr = handle_list->value; + attr->Attributes[pos].ReturnLength = NULL; + pos++; + }
Are you sure it should work this way? 'inherit' flag on process creation means that all handles are inherited. I was under impression that PS_ATTRIBUTE_HANDLE_LIST makes sense with inherit set to FALSE only. Can't recall if I ever tested that precisely though.
Yes, you need to set the flag in both cases.