Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/kernelbase/process.c | 85 ++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 29 deletions(-)
diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 90ea299416..ec034aa75d 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -244,7 +244,7 @@ static RTL_USER_PROCESS_PARAMETERS *create_process_params( const WCHAR *filename */ 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 ) + RTL_USER_PROCESS_INFORMATION *info, HANDLE parent ) { NTSTATUS status; UNICODE_STRING nameW; @@ -257,7 +257,7 @@ static NTSTATUS create_nt_process( SECURITY_ATTRIBUTES *psa, SECURITY_ATTRIBUTES status = RtlCreateUserProcess( &nameW, OBJ_CASE_INSENSITIVE, params, psa ? psa->lpSecurityDescriptor : NULL, tsa ? tsa->lpSecurityDescriptor : NULL, - 0, inherit, 0, 0, info ); + parent, inherit, 0, 0, info ); RtlFreeUnicodeString( &nameW ); } return status; @@ -288,7 +288,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 ); + status = create_nt_process( psa, tsa, inherit, flags, params, info, NULL ); HeapFree( GetProcessHeap(), 0, newcmdline ); return status; } @@ -316,7 +316,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 ); + status = create_nt_process( psa, tsa, inherit, flags, params, info, NULL ); RtlFreeHeap( GetProcessHeap(), 0, newcmdline ); return status; } @@ -368,7 +368,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW( HANDLE token, const WCHAR *a inherit, flags, env, cur_dir, startup_info, info, NULL ); }
- /********************************************************************** * CreateProcessInternalA (kernelbase.@) */ @@ -382,7 +381,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalA( HANDLE token, const char * BOOL ret = FALSE; WCHAR *app_nameW = NULL, *cmd_lineW = NULL, *cur_dirW = NULL; UNICODE_STRING desktopW, titleW; - STARTUPINFOW infoW; + STARTUPINFOEXW infoW;
desktopW.Buffer = NULL; titleW.Buffer = NULL; @@ -393,12 +392,15 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalA( HANDLE token, const char * if (startup_info->lpDesktop) RtlCreateUnicodeStringFromAsciiz( &desktopW, startup_info->lpDesktop ); if (startup_info->lpTitle) RtlCreateUnicodeStringFromAsciiz( &titleW, startup_info->lpTitle );
- memcpy( &infoW, startup_info, sizeof(infoW) ); - infoW.lpDesktop = desktopW.Buffer; - infoW.lpTitle = titleW.Buffer; + memcpy( &infoW.StartupInfo, startup_info, sizeof(infoW.StartupInfo) ); + infoW.StartupInfo.lpDesktop = desktopW.Buffer; + infoW.StartupInfo.lpTitle = titleW.Buffer; + + if (flags & EXTENDED_STARTUPINFO_PRESENT) + infoW.lpAttributeList = ((STARTUPINFOEXW *)startup_info)->lpAttributeList;
ret = CreateProcessInternalW( token, app_nameW, cmd_lineW, process_attr, thread_attr, - inherit, flags, env, cur_dirW, &infoW, info, new_token ); + inherit, flags, env, cur_dirW, (STARTUPINFOW *)&infoW, info, new_token ); done: RtlFreeHeap( GetProcessHeap(), 0, app_nameW ); RtlFreeHeap( GetProcessHeap(), 0, cmd_lineW ); @@ -408,6 +410,22 @@ 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.@) @@ -423,6 +441,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR WCHAR *p, *tidy_cmdline = cmd_line; RTL_USER_PROCESS_PARAMETERS *params = NULL; RTL_USER_PROCESS_INFORMATION rtl_info; + HANDLE parent = NULL; NTSTATUS status;
/* Process the AppName and/or CmdLine to get module name and path */ @@ -473,7 +492,33 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessInternalW( HANDLE token, const WCHAR goto done; }
- status = create_nt_process( process_attr, thread_attr, inherit, flags, params, &rtl_info ); + if (flags & EXTENDED_STARTUPINFO_PRESENT) + { + struct _PROC_THREAD_ATTRIBUTE_LIST *attrs = + (struct _PROC_THREAD_ATTRIBUTE_LIST *)((STARTUPINFOEXW *)startup_info)->lpAttributeList; + unsigned int i; + + if (attrs) + { + for (i = 0; i < attrs->count; ++i) + { + switch(attrs->attrs[i].attr) + { + case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: + parent = *(HANDLE *)attrs->attrs[i].value; + TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent); + if (!parent) + parent = INVALID_HANDLE_VALUE; + break; + default: + FIXME("Unsupported attribute %#lx.\n", attrs->attrs[i].attr); + break; + } + } + } + } + + status = create_nt_process( process_attr, thread_attr, inherit, flags, params, &rtl_info, parent ); switch (status) { case STATUS_SUCCESS: @@ -1301,24 +1346,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW( LPCWSTR name, LPCWSTR val * Process/thread attribute lists ***********************************************************************/
- -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]; -}; - /*********************************************************************** * InitializeProcThreadAttributeList (kernelbase.@) */
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47817 Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/kernel32/tests/process.c | 4 ++-- dlls/ntdll/process.c | 11 +++++++++-- include/wine/server_protocol.h | 4 +++- server/process.c | 30 ++++++++++++++++++++++++------ server/protocol.def | 1 + server/request.h | 17 +++++++++-------- server/trace.c | 3 ++- 7 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index 3efbfa2402..6d7a9a74c3 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -3874,14 +3874,14 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
memset(&parent_data, 0, sizeof(parent_data)); ret = ReadFile(read_pipe, &parent_data, sizeof(parent_data), &size, NULL); - todo_wine_if(level == 2) ok((level == 2 && ret) || (level == 1 && !ret && GetLastError() == ERROR_INVALID_HANDLE), + ok((level == 2 && ret) || (level == 1 && !ret && GetLastError() == ERROR_INVALID_HANDLE), "Got unexpected ret %#x, level %u, GetLastError() %u.\n", ret, level, GetLastError()); }
if (level == 2) { - todo_wine ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n", + ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n", parent_id, parent_data.parent_id); return; } diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index 52d7ea429e..5d75a27e97 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -1667,8 +1667,14 @@ NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
RtlNormalizeProcessParams( params );
- TRACE( "%s image %s cmdline %s\n", debugstr_us( path ), - debugstr_us( ¶ms->ImagePathName ), debugstr_us( ¶ms->CommandLine )); + TRACE( "%s image %s cmdline %s, parent %p.\n", debugstr_us( path ), + debugstr_us( ¶ms->ImagePathName ), debugstr_us( ¶ms->CommandLine ), parent); + + if (parent == INVALID_HANDLE_VALUE) + { + memset(info, 0, sizeof(*info)); + return STATUS_INVALID_HANDLE; + }
if ((status = get_pe_file_info( path, attributes, &file_handle, &pe_info ))) { @@ -1709,6 +1715,7 @@ NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
SERVER_START_REQ( new_process ) { + req->parent_process = wine_server_obj_handle(parent); req->inherit_all = inherit; req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */ req->socket_fd = socketfd[1]; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index aaa5fd2e33..98ecd98b08 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -769,6 +769,7 @@ struct rawinput_device struct new_process_request { struct request_header __header; + obj_handle_t parent_process; int inherit_all; unsigned int create_flags; int socket_fd; @@ -779,6 +780,7 @@ struct new_process_request /* VARARG(objattr,object_attributes); */ /* VARARG(info,startup_info,info_size); */ /* VARARG(env,unicode_str); */ + char __pad_44[4]; }; struct new_process_reply { @@ -6702,6 +6704,6 @@ union generic_reply struct resume_process_reply resume_process_reply; };
-#define SERVER_PROTOCOL_VERSION 593 +#define SERVER_PROTOCOL_VERSION 594
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/process.c b/server/process.c index 16bb5d57e7..195f54fa79 100644 --- a/server/process.c +++ b/server/process.c @@ -1117,6 +1117,7 @@ DECL_HANDLER(new_process) const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); struct process *process = NULL; struct process *parent = current->process; + struct thread *parent_thread = current; int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
if (socket_fd == -1) @@ -1148,11 +1149,26 @@ DECL_HANDLER(new_process) return; }
+ if (req->parent_process) + { + if (!(parent = get_process_from_handle( req->parent_process, PROCESS_CREATE_PROCESS))) + { + set_error(STATUS_INVALID_HANDLE); + close(socket_fd); + return; + } + parent_thread = get_process_first_thread(parent); + } + if (parent->job && (req->create_flags & CREATE_BREAKAWAY_FROM_JOB) && !(parent->job->limit_flags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK))) { set_error( STATUS_ACCESS_DENIED ); close( socket_fd ); + + if (req->parent_process) + release_object(parent); + return; }
@@ -1222,7 +1238,7 @@ DECL_HANDLER(new_process) }
/* connect to the window station */ - connect_process_winstation( process, current ); + connect_process_winstation( process, parent_thread );
/* set the process console */ if (!(req->create_flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE))) @@ -1231,7 +1247,7 @@ DECL_HANDLER(new_process) * like if hConOut and hConIn are console handles, then they should be on the same * physical console */ - inherit_console( current, process, req->inherit_all ? info->data->hstdin : 0 ); + inherit_console( parent_thread, process, req->inherit_all ? info->data->hstdin : 0 ); }
if (!req->inherit_all && !(req->create_flags & CREATE_NEW_CONSOLE)) @@ -1246,16 +1262,15 @@ DECL_HANDLER(new_process) if (get_error() == STATUS_INVALID_HANDLE || get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error(); } - /* attach to the debugger if requested */ if (req->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) { set_process_debugger( process, current ); process->debug_children = !(req->create_flags & DEBUG_ONLY_THIS_PROCESS); } - else if (parent->debugger && parent->debug_children) + else if (current->process->debugger && current->process->debug_children) { - set_process_debugger( process, parent->debugger ); + set_process_debugger( process, current->process->debugger ); /* debug_children is set to 1 by default */ }
@@ -1265,9 +1280,12 @@ DECL_HANDLER(new_process) info->process = (struct process *)grab_object( process ); reply->info = alloc_handle( current->process, info, SYNCHRONIZE, 0 ); reply->pid = get_process_id( process ); - reply->handle = alloc_handle_no_access_check( parent, process, req->access, objattr->attributes ); + reply->handle = alloc_handle_no_access_check( current->process, process, req->access, objattr->attributes );
done: + if (req->parent_process) + release_object(parent); + if (process) release_object( process ); release_object( info ); } diff --git a/server/protocol.def b/server/protocol.def index 1cb1fea602..7f9ec3a149 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -783,6 +783,7 @@ struct rawinput_device
/* Create a new process from the context of the parent */ @REQ(new_process) + obj_handle_t parent_process; /* parent process */ int inherit_all; /* inherit all handles from parent */ unsigned int create_flags; /* creation flags */ int socket_fd; /* file descriptor for process socket */ diff --git a/server/request.h b/server/request.h index 90a3180a6c..9f36bcb711 100644 --- a/server/request.h +++ b/server/request.h @@ -745,14 +745,15 @@ C_ASSERT( sizeof(unsigned char) == 1 ); C_ASSERT( sizeof(unsigned int) == 4 ); C_ASSERT( sizeof(unsigned short) == 2 ); C_ASSERT( sizeof(user_handle_t) == 4 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 12 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 16 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 20 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 24 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 28 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 32 ); -C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 36 ); -C_ASSERT( sizeof(struct new_process_request) == 40 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 12 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 16 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 20 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 24 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 28 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 32 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 36 ); +C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 40 ); +C_ASSERT( sizeof(struct new_process_request) == 48 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, info) == 8 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 ); C_ASSERT( FIELD_OFFSET(struct new_process_reply, handle) == 16 ); diff --git a/server/trace.c b/server/trace.c index 411369a4f6..026aba9c50 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1243,7 +1243,8 @@ typedef void (*dump_func)( const void *req );
static void dump_new_process_request( const struct new_process_request *req ) { - fprintf( stderr, " inherit_all=%d", req->inherit_all ); + fprintf( stderr, " parent_process=%04x", req->parent_process ); + fprintf( stderr, ", inherit_all=%d", req->inherit_all ); fprintf( stderr, ", create_flags=%08x", req->create_flags ); fprintf( stderr, ", socket_fd=%d", req->socket_fd ); fprintf( stderr, ", exe_file=%04x", req->exe_file );
Paul Gofman gofmanp@gmail.com writes:
@@ -1148,11 +1149,26 @@ DECL_HANDLER(new_process) return; }
- if (req->parent_process)
- {
if (!(parent = get_process_from_handle( req->parent_process, PROCESS_CREATE_PROCESS)))
{
set_error(STATUS_INVALID_HANDLE);
close(socket_fd);
return;
}
parent_thread = get_process_first_thread(parent);
Picking the first thread seems arbitrary. This probably needs some more restructuring.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/kernel32/tests/process.c | 87 ++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index 6d7a9a74c3..b8df8b8dce 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -3825,7 +3825,8 @@ static void test_ProcThreadAttributeList(void) /* level 0: Main test process * level 1: Process created by level 0 process without handle inheritance * level 2: Process created by level 1 process with handle inheritance and level 0 - * process parent substitute. */ + * process parent substitute. + * level 255: Process created by level 1 process during invalid parent handles testing. */ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe) { PROCESS_BASIC_INFORMATION pbi; @@ -3848,6 +3849,9 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe) } parent_data;
+ if (level == 255) + return; + if (!pInitializeProcThreadAttributeList) { win_skip("No support for ProcThreadAttributeList.\n"); @@ -3891,11 +3895,92 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
if (level) { + HANDLE handle; SIZE_T size;
ret = pInitializeProcThreadAttributeList(NULL, 1, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + + sprintf(buffer, ""%s" tests/process.c parent %u %p %p", selfname, 255, read_pipe, NULL); + +#if 0 + /* Crashes on some Windows installations, otherwise successfully creates process. */ + ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT, + NULL, NULL, (STARTUPINFOA *)&si, &info); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); + CloseHandle(info.hThread); + CloseHandle(info.hProcess); +#endif + si.lpAttributeList = heap_alloc(size); + ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + handle = INVALID_HANDLE_VALUE; + ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, + &handle, sizeof(handle), NULL, NULL); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, + NULL, NULL, (STARTUPINFOA *)&si, &info); + /* Broken on w7u/w8. */ + ok((!ret && GetLastError() == ERROR_INVALID_HANDLE) || broken(ret), + "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + if (ret) + { + ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); + CloseHandle(info.hThread); + CloseHandle(info.hProcess); + } + pDeleteProcThreadAttributeList(si.lpAttributeList); + heap_free(si.lpAttributeList); + + si.lpAttributeList = heap_alloc(size); + ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + handle = (HANDLE)0xdeadbeef; + ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, + &handle, sizeof(handle), NULL, NULL); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, + NULL, NULL, (STARTUPINFOA *)&si, &info); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + pDeleteProcThreadAttributeList(si.lpAttributeList); + heap_free(si.lpAttributeList); + + si.lpAttributeList = heap_alloc(size); + ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + handle = NULL; + ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, + &handle, sizeof(handle), NULL, NULL); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, + NULL, NULL, (STARTUPINFOA *)&si, &info); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + pDeleteProcThreadAttributeList(si.lpAttributeList); + heap_free(si.lpAttributeList); + + si.lpAttributeList = heap_alloc(size); + ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + handle = GetCurrentProcess(); + ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, + &handle, sizeof(handle), NULL, NULL); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, + NULL, NULL, (STARTUPINFOA *)&si, &info); + /* Broken on w7u/w8. */ + ok((!ret && GetLastError() == ERROR_INVALID_HANDLE) || broken(ret), + "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); + if (ret) + { + ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); + CloseHandle(info.hThread); + CloseHandle(info.hProcess); + } + pDeleteProcThreadAttributeList(si.lpAttributeList); + heap_free(si.lpAttributeList); + si.lpAttributeList = heap_alloc(size); ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
Paul Gofman gofmanp@gmail.com writes:
case PROC_THREAD_ATTRIBUTE_PARENT_PROCESS:
parent = *(HANDLE *)attrs->attrs[i].value;
TRACE("PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parent %p.\n", parent);
if (!parent)
parent = INVALID_HANDLE_VALUE;
Using INVALID_HANDLE_VALUE for a process handle is probably not a good idea, especially since that's the same as GetCurrentProcess().