server: Define an architecture-independent structure for process startup info.

This commit is contained in:
Alexandre Julliard 2009-08-20 20:05:21 +02:00
parent f6f458a1eb
commit da8acbc47d
7 changed files with 371 additions and 257 deletions

View File

@ -1430,85 +1430,127 @@ static int fork_and_exec( const char *filename, const WCHAR *cmdline, const WCHA
}
/***********************************************************************
* create_user_params
*/
static RTL_USER_PROCESS_PARAMETERS *create_user_params( LPCWSTR filename, LPCWSTR cmdline,
LPCWSTR cur_dir, LPWSTR env, DWORD flags,
const STARTUPINFOW *startup )
static inline DWORD append_string( void **ptr, const WCHAR *str )
{
RTL_USER_PROCESS_PARAMETERS *params;
UNICODE_STRING image_str, cmdline_str, curdir_str, desktop, title, runtime, newdir;
NTSTATUS status;
WCHAR buffer[MAX_PATH];
DWORD len = strlenW( str );
memcpy( *ptr, str, len * sizeof(WCHAR) );
*ptr = (WCHAR *)*ptr + len;
return len * sizeof(WCHAR);
}
if(!GetLongPathNameW( filename, buffer, MAX_PATH ))
lstrcpynW( buffer, filename, MAX_PATH );
if(!GetFullPathNameW( buffer, MAX_PATH, buffer, NULL ))
lstrcpynW( buffer, filename, MAX_PATH );
RtlInitUnicodeString( &image_str, buffer );
/***********************************************************************
* create_startup_info
*/
static startup_info_t *create_startup_info( LPCWSTR filename, LPCWSTR cmdline,
LPCWSTR cur_dir, LPWSTR env, DWORD flags,
const STARTUPINFOW *startup, DWORD *info_size )
{
const RTL_USER_PROCESS_PARAMETERS *cur_params;
startup_info_t *info;
DWORD size;
void *ptr;
UNICODE_STRING newdir;
WCHAR imagepath[MAX_PATH];
HANDLE hstdin, hstdout, hstderr;
if(!GetLongPathNameW( filename, imagepath, MAX_PATH ))
lstrcpynW( imagepath, filename, MAX_PATH );
if(!GetFullPathNameW( imagepath, MAX_PATH, imagepath, NULL ))
lstrcpynW( imagepath, filename, MAX_PATH );
cur_params = NtCurrentTeb()->Peb->ProcessParameters;
RtlInitUnicodeString( &cmdline_str, cmdline );
newdir.Buffer = NULL;
if (cur_dir)
{
if (RtlDosPathNameToNtPathName_U( cur_dir, &newdir, NULL, NULL ))
{
/* skip \??\ prefix */
curdir_str.Buffer = newdir.Buffer + 4;
curdir_str.Length = newdir.Length - 4 * sizeof(WCHAR);
curdir_str.MaximumLength = newdir.MaximumLength - 4 * sizeof(WCHAR);
}
else cur_dir = NULL;
cur_dir = newdir.Buffer + 4; /* skip \??\ prefix */
else
cur_dir = NULL;
}
if (startup->lpDesktop) RtlInitUnicodeString( &desktop, startup->lpDesktop );
if (startup->lpTitle) RtlInitUnicodeString( &title, startup->lpTitle );
if (startup->lpReserved2 && startup->cbReserved2)
if (!cur_dir)
{
runtime.Length = 0;
runtime.MaximumLength = startup->cbReserved2;
runtime.Buffer = (WCHAR*)startup->lpReserved2;
if (NtCurrentTeb()->Tib.SubSystemTib) /* FIXME: hack */
cur_dir = ((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir.DosPath.Buffer;
else
cur_dir = cur_params->CurrentDirectory.DosPath.Buffer;
}
status = RtlCreateProcessParameters( &params, &image_str, NULL,
cur_dir ? &curdir_str : NULL,
&cmdline_str, env,
startup->lpTitle ? &title : NULL,
startup->lpDesktop ? &desktop : NULL,
NULL,
(startup->lpReserved2 && startup->cbReserved2) ? &runtime : NULL );
RtlFreeUnicodeString( &newdir );
if (status != STATUS_SUCCESS)
{
SetLastError( RtlNtStatusToDosError(status) );
return NULL;
}
size = sizeof(*info);
size += strlenW( cur_dir ) * sizeof(WCHAR);
size += cur_params->DllPath.Length;
size += strlenW( imagepath ) * sizeof(WCHAR);
size += strlenW( cmdline ) * sizeof(WCHAR);
if (startup->lpTitle) size += strlenW( startup->lpTitle ) * sizeof(WCHAR);
if (startup->lpDesktop) size += strlenW( startup->lpDesktop ) * sizeof(WCHAR);
/* FIXME: shellinfo */
if (startup->lpReserved2 && startup->cbReserved2) size += startup->cbReserved2;
size = (size + 1) & ~1;
*info_size = size;
if (flags & CREATE_NEW_PROCESS_GROUP) params->ConsoleFlags = 1;
if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = (HANDLE)1; /* FIXME: cf. kernel_main.c */
if (!(info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ))) goto done;
info->console_flags = cur_params->ConsoleFlags;
if (flags & CREATE_NEW_PROCESS_GROUP) info->console_flags = 1;
if (flags & CREATE_NEW_CONSOLE) info->console = (obj_handle_t)1; /* FIXME: cf. kernel_main.c */
if (startup->dwFlags & STARTF_USESTDHANDLES)
{
params->hStdInput = startup->hStdInput;
params->hStdOutput = startup->hStdOutput;
params->hStdError = startup->hStdError;
hstdin = startup->hStdInput;
hstdout = startup->hStdOutput;
hstderr = startup->hStdError;
}
else
{
params->hStdInput = GetStdHandle( STD_INPUT_HANDLE );
params->hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE );
params->hStdError = GetStdHandle( STD_ERROR_HANDLE );
hstdin = GetStdHandle( STD_INPUT_HANDLE );
hstdout = GetStdHandle( STD_OUTPUT_HANDLE );
hstderr = GetStdHandle( STD_ERROR_HANDLE );
}
params->dwX = startup->dwX;
params->dwY = startup->dwY;
params->dwXSize = startup->dwXSize;
params->dwYSize = startup->dwYSize;
params->dwXCountChars = startup->dwXCountChars;
params->dwYCountChars = startup->dwYCountChars;
params->dwFillAttribute = startup->dwFillAttribute;
params->dwFlags = startup->dwFlags;
params->wShowWindow = startup->wShowWindow;
return params;
info->hstdin = wine_server_obj_handle( hstdin );
info->hstdout = wine_server_obj_handle( hstdout );
info->hstderr = wine_server_obj_handle( hstderr );
if ((flags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)) != 0)
{
/* this is temporary (for console handles). We have no way to control that the handle is invalid in child process otherwise */
if (is_console_handle(hstdin)) info->hstdin = wine_server_obj_handle( INVALID_HANDLE_VALUE );
if (is_console_handle(hstdout)) info->hstdout = wine_server_obj_handle( INVALID_HANDLE_VALUE );
if (is_console_handle(hstderr)) info->hstderr = wine_server_obj_handle( INVALID_HANDLE_VALUE );
}
else
{
if (is_console_handle(hstdin)) info->hstdin = console_handle_unmap(hstdin);
if (is_console_handle(hstdout)) info->hstdout = console_handle_unmap(hstdout);
if (is_console_handle(hstderr)) info->hstderr = console_handle_unmap(hstderr);
}
info->x = startup->dwX;
info->y = startup->dwY;
info->xsize = startup->dwXSize;
info->ysize = startup->dwYSize;
info->xchars = startup->dwXCountChars;
info->ychars = startup->dwYCountChars;
info->attribute = startup->dwFillAttribute;
info->flags = startup->dwFlags;
info->show = startup->wShowWindow;
ptr = info + 1;
info->curdir_len = append_string( &ptr, cur_dir );
info->dllpath_len = cur_params->DllPath.Length;
memcpy( ptr, cur_params->DllPath.Buffer, cur_params->DllPath.Length );
ptr = (char *)ptr + cur_params->DllPath.Length;
info->imagepath_len = append_string( &ptr, imagepath );
info->cmdline_len = append_string( &ptr, cmdline );
if (startup->lpTitle) info->title_len = append_string( &ptr, startup->lpTitle );
if (startup->lpDesktop) info->desktop_len = append_string( &ptr, startup->lpDesktop );
if (startup->lpReserved2 && startup->cbReserved2)
{
info->runtime_len = startup->cbReserved2;
memcpy( ptr, startup->lpReserved2, startup->cbReserved2 );
}
done:
RtlFreeUnicodeString( &newdir );
return info;
}
@ -1525,11 +1567,12 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
void *res_start, void *res_end, DWORD binary_type, int exec_only )
{
BOOL ret, success = FALSE;
HANDLE process_info, hstdin, hstdout;
HANDLE process_info;
WCHAR *env_end;
char *winedebug = NULL;
char **argv;
RTL_USER_PROCESS_PARAMETERS *params;
startup_info_t *startup_info;
DWORD startup_info_size;
int socketfd[2], stdin_fd = -1, stdout_fd = -1;
pid_t pid;
int err;
@ -1541,14 +1584,16 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
return FALSE;
}
if (!env) RtlAcquirePebLock();
RtlAcquirePebLock();
if (!(params = create_user_params( filename, cmd_line, cur_dir, env, flags, startup )))
if (!(startup_info = create_startup_info( filename, cmd_line, cur_dir, env, flags, startup,
&startup_info_size )))
{
if (!env) RtlReleasePebLock();
RtlReleasePebLock();
return FALSE;
}
env_end = params->Environment;
if (!env) env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
env_end = env;
while (*env_end)
{
static const WCHAR WINEDEBUG[] = {'W','I','N','E','D','E','B','U','G','=',0};
@ -1566,9 +1611,9 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
if (socketpair( PF_UNIX, SOCK_STREAM, 0, socketfd ) == -1)
{
if (!env) RtlReleasePebLock();
RtlReleasePebLock();
HeapFree( GetProcessHeap(), 0, winedebug );
RtlDestroyProcessParameters( params );
HeapFree( GetProcessHeap(), 0, startup_info );
SetLastError( ERROR_TOO_MANY_OPEN_FILES );
return FALSE;
}
@ -1587,29 +1632,10 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
req->process_attr = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle) ? OBJ_INHERIT : 0;
req->thread_access = THREAD_ALL_ACCESS;
req->thread_attr = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0;
req->hstdin = wine_server_obj_handle( params->hStdInput );
req->hstdout = wine_server_obj_handle( params->hStdOutput );
req->hstderr = wine_server_obj_handle( params->hStdError );
req->info_size = startup_info_size;
if ((flags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)) != 0)
{
/* this is temporary (for console handles). We have no way to control that the handle is invalid in child process otherwise */
if (is_console_handle(params->hStdInput)) req->hstdin = wine_server_obj_handle( INVALID_HANDLE_VALUE );
if (is_console_handle(params->hStdOutput)) req->hstdout = wine_server_obj_handle( INVALID_HANDLE_VALUE );
if (is_console_handle(params->hStdError)) req->hstderr = wine_server_obj_handle( INVALID_HANDLE_VALUE );
hstdin = hstdout = 0;
}
else
{
if (is_console_handle(params->hStdInput)) req->hstdin = console_handle_unmap(params->hStdInput);
if (is_console_handle(params->hStdOutput)) req->hstdout = console_handle_unmap(params->hStdOutput);
if (is_console_handle(params->hStdError)) req->hstderr = console_handle_unmap(params->hStdError);
hstdin = wine_server_ptr_handle( req->hstdin );
hstdout = wine_server_ptr_handle( req->hstdout );
}
wine_server_add_data( req, params, params->Size );
wine_server_add_data( req, params->Environment, (env_end-params->Environment)*sizeof(WCHAR) );
wine_server_add_data( req, startup_info, startup_info_size );
wine_server_add_data( req, env, (env_end - env) * sizeof(WCHAR) );
if ((ret = !wine_server_call_err( req )))
{
info->dwProcessId = (DWORD)reply->pid;
@ -1621,17 +1647,25 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
}
SERVER_END_REQ;
if (!env) RtlReleasePebLock();
RtlDestroyProcessParameters( params );
RtlReleasePebLock();
if (!ret)
{
close( socketfd[0] );
HeapFree( GetProcessHeap(), 0, startup_info );
HeapFree( GetProcessHeap(), 0, winedebug );
return FALSE;
}
if (hstdin) wine_server_handle_to_fd( hstdin, FILE_READ_DATA, &stdin_fd, NULL );
if (hstdout) wine_server_handle_to_fd( hstdout, FILE_WRITE_DATA, &stdout_fd, NULL );
if (!(flags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)))
{
if (startup_info->hstdin)
wine_server_handle_to_fd( wine_server_ptr_handle(startup_info->hstdin),
FILE_READ_DATA, &stdin_fd, NULL );
if (startup_info->hstdout)
wine_server_handle_to_fd( wine_server_ptr_handle(startup_info->hstdout),
FILE_WRITE_DATA, &stdout_fd, NULL );
}
HeapFree( GetProcessHeap(), 0, startup_info );
/* create the child process */
argv = build_argv( cmd_line, 1 );

View File

@ -126,89 +126,118 @@ static inline NTSTATUS init_teb( TEB *teb )
/***********************************************************************
* fix_unicode_string
* get_unicode_string
*
* Make sure the unicode string doesn't point beyond the end pointer
* Copy a unicode string from the startup info.
*/
static inline void fix_unicode_string( UNICODE_STRING *str, const char *end_ptr )
static inline void get_unicode_string( UNICODE_STRING *str, WCHAR **src, WCHAR **dst, UINT len )
{
if ((char *)str->Buffer >= end_ptr)
{
str->Length = str->MaximumLength = 0;
str->Buffer = NULL;
return;
}
if ((char *)str->Buffer + str->MaximumLength > end_ptr)
{
str->MaximumLength = (end_ptr - (char *)str->Buffer) & ~(sizeof(WCHAR) - 1);
}
if (str->Length >= str->MaximumLength)
{
if (str->MaximumLength >= sizeof(WCHAR))
str->Length = str->MaximumLength - sizeof(WCHAR);
else
str->Length = str->MaximumLength = 0;
}
str->Buffer = *dst;
str->Length = len;
str->MaximumLength = len + sizeof(WCHAR);
memcpy( str->Buffer, *src, len );
str->Buffer[len / sizeof(WCHAR)] = 0;
*src += len / sizeof(WCHAR);
*dst += len / sizeof(WCHAR) + 1;
}
/***********************************************************************
* init_user_process_params
*
* Fill the RTL_USER_PROCESS_PARAMETERS structure from the server.
*/
static NTSTATUS init_user_process_params( SIZE_T info_size, HANDLE *exe_file )
static NTSTATUS init_user_process_params( SIZE_T data_size, HANDLE *exe_file )
{
void *ptr;
SIZE_T env_size;
WCHAR *src, *dst;
SIZE_T info_size, env_size, size, alloc_size;
NTSTATUS status;
startup_info_t *info;
RTL_USER_PROCESS_PARAMETERS *params = NULL;
status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&params, 0, &info_size,
MEM_COMMIT, PAGE_READWRITE );
if (status != STATUS_SUCCESS) return status;
params->AllocationSize = info_size;
NtCurrentTeb()->Peb->ProcessParameters = params;
if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, data_size )))
return STATUS_NO_MEMORY;
SERVER_START_REQ( get_startup_info )
{
wine_server_set_reply( req, params, info_size );
wine_server_set_reply( req, info, data_size );
if (!(status = wine_server_call( req )))
{
info_size = wine_server_reply_size( reply );
data_size = wine_server_reply_size( reply );
info_size = reply->info_size;
env_size = data_size - info_size;
*exe_file = wine_server_ptr_handle( reply->exe_file );
params->hStdInput = wine_server_ptr_handle( reply->hstdin );
params->hStdOutput = wine_server_ptr_handle( reply->hstdout );
params->hStdError = wine_server_ptr_handle( reply->hstderr );
}
}
SERVER_END_REQ;
if (status != STATUS_SUCCESS) return status;
if (params->Size > info_size) params->Size = info_size;
size = sizeof(*params);
size += MAX_NT_PATH_LENGTH * sizeof(WCHAR);
size += info->dllpath_len + sizeof(WCHAR);
size += info->imagepath_len + sizeof(WCHAR);
size += info->cmdline_len + sizeof(WCHAR);
size += info->title_len + sizeof(WCHAR);
size += info->desktop_len + sizeof(WCHAR);
size += info->shellinfo_len + sizeof(WCHAR);
size += info->runtime_len + sizeof(WCHAR);
/* make sure the strings are valid */
fix_unicode_string( &params->CurrentDirectory.DosPath, (char *)info_size );
fix_unicode_string( &params->DllPath, (char *)info_size );
fix_unicode_string( &params->ImagePathName, (char *)info_size );
fix_unicode_string( &params->CommandLine, (char *)info_size );
fix_unicode_string( &params->WindowTitle, (char *)info_size );
fix_unicode_string( &params->Desktop, (char *)info_size );
fix_unicode_string( &params->ShellInfo, (char *)info_size );
fix_unicode_string( &params->RuntimeInfo, (char *)info_size );
alloc_size = size;
status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&params, 0, &alloc_size,
MEM_COMMIT, PAGE_READWRITE );
if (status != STATUS_SUCCESS) goto done;
NtCurrentTeb()->Peb->ProcessParameters = params;
params->AllocationSize = alloc_size;
params->Size = size;
params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED;
params->DebugFlags = info->debug_flags;
params->ConsoleHandle = wine_server_ptr_handle( info->console );
params->ConsoleFlags = info->console_flags;
params->hStdInput = wine_server_ptr_handle( info->hstdin );
params->hStdOutput = wine_server_ptr_handle( info->hstdout );
params->hStdError = wine_server_ptr_handle( info->hstderr );
params->dwX = info->x;
params->dwY = info->y;
params->dwXSize = info->xsize;
params->dwYSize = info->ysize;
params->dwXCountChars = info->xchars;
params->dwYCountChars = info->ychars;
params->dwFillAttribute = info->attribute;
params->dwFlags = info->flags;
params->wShowWindow = info->show;
src = (WCHAR *)(info + 1);
dst = (WCHAR *)(params + 1);
/* current directory needs more space */
get_unicode_string( &params->CurrentDirectory.DosPath, &src, &dst, info->curdir_len );
params->CurrentDirectory.DosPath.MaximumLength = MAX_NT_PATH_LENGTH * sizeof(WCHAR);
dst = (WCHAR *)(params + 1) + MAX_NT_PATH_LENGTH;
get_unicode_string( &params->DllPath, &src, &dst, info->dllpath_len );
get_unicode_string( &params->ImagePathName, &src, &dst, info->imagepath_len );
get_unicode_string( &params->CommandLine, &src, &dst, info->cmdline_len );
get_unicode_string( &params->WindowTitle, &src, &dst, info->title_len );
get_unicode_string( &params->Desktop, &src, &dst, info->desktop_len );
get_unicode_string( &params->ShellInfo, &src, &dst, info->shellinfo_len );
/* runtime info isn't a real string */
params->RuntimeInfo.Buffer = dst;
params->RuntimeInfo.Length = params->RuntimeInfo.MaximumLength = info->runtime_len;
memcpy( dst, src, info->runtime_len );
/* environment needs to be a separate memory block */
env_size = info_size - params->Size;
if (!env_size) env_size = 1;
ptr = NULL;
status = NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, 0, &env_size,
alloc_size = max( 1, env_size );
status = NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, 0, &alloc_size,
MEM_COMMIT, PAGE_READWRITE );
if (status != STATUS_SUCCESS) return status;
memcpy( ptr, (char *)params + params->Size, info_size - params->Size );
if (status != STATUS_SUCCESS) goto done;
memcpy( ptr, (char *)info + info_size, env_size );
params->Environment = ptr;
RtlNormalizeProcessParams( params );
done:
RtlFreeHeap( GetProcessHeap(), 0, info );
return status;
}

View File

@ -211,6 +211,42 @@ typedef __int64 timeout_t;
#define TIMEOUT_INFINITE (((timeout_t)0x7fffffff) << 32 | 0xffffffff)
typedef struct
{
unsigned int debug_flags;
unsigned int console_flags;
obj_handle_t console;
obj_handle_t hstdin;
obj_handle_t hstdout;
obj_handle_t hstderr;
unsigned int x;
unsigned int y;
unsigned int xsize;
unsigned int ysize;
unsigned int xchars;
unsigned int ychars;
unsigned int attribute;
unsigned int flags;
unsigned int show;
data_size_t curdir_len;
data_size_t dllpath_len;
data_size_t imagepath_len;
data_size_t cmdline_len;
data_size_t title_len;
data_size_t desktop_len;
data_size_t shellinfo_len;
data_size_t runtime_len;
} startup_info_t;
typedef struct
{
atom_t atom;
@ -535,14 +571,12 @@ struct new_process_request
unsigned int create_flags;
int socket_fd;
obj_handle_t exe_file;
obj_handle_t hstdin;
obj_handle_t hstdout;
obj_handle_t hstderr;
unsigned int process_access;
unsigned int process_attr;
unsigned int thread_access;
unsigned int thread_attr;
/* VARARG(info,startup_info); */
data_size_t info_size;
/* VARARG(info,startup_info,info_size); */
/* VARARG(env,unicode_str); */
};
struct new_process_reply
@ -597,10 +631,8 @@ struct get_startup_info_reply
{
struct reply_header __header;
obj_handle_t exe_file;
obj_handle_t hstdin;
obj_handle_t hstdout;
obj_handle_t hstderr;
/* VARARG(info,startup_info); */
data_size_t info_size;
/* VARARG(info,startup_info,info_size); */
/* VARARG(env,unicode_str); */
};
@ -5315,6 +5347,6 @@ union generic_reply
struct set_window_layered_info_reply set_window_layered_info_reply;
};
#define SERVER_PROTOCOL_VERSION 388
#define SERVER_PROTOCOL_VERSION 389
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -102,13 +102,11 @@ static const struct fd_ops process_fd_ops =
struct startup_info
{
struct object obj; /* object header */
obj_handle_t hstdin; /* handle for stdin */
obj_handle_t hstdout; /* handle for stdout */
obj_handle_t hstderr; /* handle for stderr */
struct file *exe_file; /* file handle for main exe */
struct process *process; /* created process */
data_size_t data_size; /* size of startup data */
void *data; /* data for startup info */
data_size_t info_size; /* size of startup info */
data_size_t data_size; /* size of whole startup data */
startup_info_t *data; /* data for startup info */
};
static void startup_info_dump( struct object *obj, int verbose );
@ -478,7 +476,7 @@ static void startup_info_dump( struct object *obj, int verbose )
assert( obj->ops == &startup_info_ops );
fprintf( stderr, "Startup info in=%04x out=%04x err=%04x\n",
info->hstdin, info->hstdout, info->hstderr );
info->data->hstdin, info->data->hstdout, info->data->hstderr );
}
static int startup_info_signaled( struct object *obj, struct thread *thread )
@ -891,19 +889,46 @@ DECL_HANDLER(new_process)
/* build the startup info for a new process */
if (!(info = alloc_object( &startup_info_ops ))) return;
info->hstdin = req->hstdin;
info->hstdout = req->hstdout;
info->hstderr = req->hstderr;
info->exe_file = NULL;
info->process = NULL;
info->data_size = get_req_data_size();
info->data = NULL;
info->exe_file = NULL;
info->process = NULL;
info->data = NULL;
if (req->exe_file &&
!(info->exe_file = get_file_obj( current->process, req->exe_file, FILE_READ_DATA )))
goto done;
if (!(info->data = memdup( get_req_data(), info->data_size ))) goto done;
info->data_size = get_req_data_size();
info->info_size = min( req->info_size, info->data_size );
if (req->info_size < sizeof(*info->data))
{
/* make sure we have a full startup_info_t structure */
data_size_t env_size = info->data_size - info->info_size;
data_size_t info_size = min( req->info_size, FIELD_OFFSET( startup_info_t, curdir_len ));
if (!(info->data = mem_alloc( sizeof(*info->data) + env_size ))) goto done;
memcpy( info->data, get_req_data(), info_size );
memset( (char *)info->data + info_size, 0, sizeof(*info->data) - info_size );
memcpy( info->data + 1, (const char *)get_req_data() + req->info_size, env_size );
info->info_size = sizeof(startup_info_t);
info->data_size = info->info_size + env_size;
}
else
{
data_size_t pos = sizeof(*info->data);
if (!(info->data = memdup( get_req_data(), info->data_size ))) goto done;
#define FIXUP_LEN(len) do { (len) = min( (len), info->info_size - pos ); pos += (len); } while(0)
FIXUP_LEN( info->data->curdir_len );
FIXUP_LEN( info->data->dllpath_len );
FIXUP_LEN( info->data->imagepath_len );
FIXUP_LEN( info->data->cmdline_len );
FIXUP_LEN( info->data->title_len );
FIXUP_LEN( info->data->desktop_len );
FIXUP_LEN( info->data->shellinfo_len );
FIXUP_LEN( info->data->runtime_len );
#undef FIXUP_LEN
}
if (!(thread = create_process( socket_fd, current, req->inherit_all ))) goto done;
process = thread->process;
@ -923,17 +948,17 @@ 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 ? req->hstdin : 0 );
inherit_console( current, process, req->inherit_all ? info->data->hstdin : 0 );
}
if (!req->inherit_all && !(req->create_flags & CREATE_NEW_CONSOLE))
{
info->hstdin = duplicate_handle( parent, req->hstdin, process,
0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
info->hstdout = duplicate_handle( parent, req->hstdout, process,
0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
info->hstderr = duplicate_handle( parent, req->hstderr, process,
0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
info->data->hstdin = duplicate_handle( parent, info->data->hstdin, process,
0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
info->data->hstdout = duplicate_handle( parent, info->data->hstdout, process,
0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
info->data->hstderr = duplicate_handle( parent, info->data->hstderr, process,
0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
/* some handles above may have been invalid; this is not an error */
if (get_error() == STATUS_INVALID_HANDLE ||
get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error();
@ -985,11 +1010,8 @@ DECL_HANDLER(get_startup_info)
if (info->exe_file &&
!(reply->exe_file = alloc_handle( process, info->exe_file, GENERIC_READ, 0 ))) return;
reply->hstdin = info->hstdin;
reply->hstdout = info->hstdout;
reply->hstderr = info->hstderr;
/* we return the data directly without making a copy so this can only be called once */
reply->info_size = info->info_size;
size = info->data_size;
if (size > get_reply_max_size()) size = get_reply_max_size();
set_reply_data_ptr( info->data, size );

View File

@ -226,6 +226,42 @@ struct wake_up_reply
typedef __int64 timeout_t;
#define TIMEOUT_INFINITE (((timeout_t)0x7fffffff) << 32 | 0xffffffff)
/* structure for process startup info */
typedef struct
{
unsigned int debug_flags;
unsigned int console_flags;
obj_handle_t console;
obj_handle_t hstdin;
obj_handle_t hstdout;
obj_handle_t hstderr;
unsigned int x;
unsigned int y;
unsigned int xsize;
unsigned int ysize;
unsigned int xchars;
unsigned int ychars;
unsigned int attribute;
unsigned int flags;
unsigned int show;
data_size_t curdir_len;
data_size_t dllpath_len;
data_size_t imagepath_len;
data_size_t cmdline_len;
data_size_t title_len;
data_size_t desktop_len;
data_size_t shellinfo_len;
data_size_t runtime_len;
/* VARARG(curdir,unicode_str,curdir_len); */
/* VARARG(dllpath,unicode_str,dllpath_len); */
/* VARARG(imagepath,unicode_str,imagepath_len); */
/* VARARG(cmdline,unicode_str,cmdline_len); */
/* VARARG(title,unicode_str,title_len); */
/* VARARG(desktop,unicode_str,desktop_len); */
/* VARARG(shellinfo,unicode_str,shellinfo_len); */
/* VARARG(runtime,unicode_str,runtime_len); */
} startup_info_t;
/* structure returned in the list of window properties */
typedef struct
{
@ -549,14 +585,12 @@ typedef union
unsigned int create_flags; /* creation flags */
int socket_fd; /* file descriptor for process socket */
obj_handle_t exe_file; /* file handle for main exe */
obj_handle_t hstdin; /* handle for stdin */
obj_handle_t hstdout; /* handle for stdout */
obj_handle_t hstderr; /* handle for stderr */
unsigned int process_access; /* access rights for process object */
unsigned int process_attr; /* attributes for process object */
unsigned int thread_access; /* access rights for thread object */
unsigned int thread_attr; /* attributes for thread object */
VARARG(info,startup_info); /* startup information */
data_size_t info_size; /* size of startup info */
VARARG(info,startup_info,info_size); /* startup information */
VARARG(env,unicode_str); /* environment for new process */
@REPLY
obj_handle_t info; /* new process info handle */
@ -592,10 +626,8 @@ typedef union
@REQ(get_startup_info)
@REPLY
obj_handle_t exe_file; /* file handle for main exe */
obj_handle_t hstdin; /* handle for stdin */
obj_handle_t hstdout; /* handle for stdout */
obj_handle_t hstderr; /* handle for stderr */
VARARG(info,startup_info); /* startup information */
data_size_t info_size; /* size of startup info */
VARARG(info,startup_info,info_size); /* startup information */
VARARG(env,unicode_str); /* environment */
@END

View File

@ -627,13 +627,11 @@ 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, hstdin) == 28 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, hstdout) == 32 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, hstderr) == 36 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, process_access) == 40 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, process_attr) == 44 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, thread_access) == 48 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, thread_attr) == 52 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, process_access) == 28 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, process_attr) == 32 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, thread_access) == 36 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, thread_attr) == 40 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 44 );
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, phandle) == 16 );
@ -652,10 +650,8 @@ C_ASSERT( FIELD_OFFSET(struct new_thread_reply, tid) == 8 );
C_ASSERT( FIELD_OFFSET(struct new_thread_reply, handle) == 12 );
C_ASSERT( sizeof(struct new_thread_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_startup_info_reply, exe_file) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_startup_info_reply, hstdin) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_startup_info_reply, hstdout) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_startup_info_reply, hstderr) == 20 );
C_ASSERT( sizeof(struct get_startup_info_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_startup_info_reply, info_size) == 12 );
C_ASSERT( sizeof(struct get_startup_info_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_request, gui) == 12 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_request, module) == 16 );
C_ASSERT( FIELD_OFFSET(struct init_process_done_request, ldt_copy) == 24 );

View File

@ -675,65 +675,38 @@ static void dump_varargs_debug_event( const char *prefix, data_size_t size )
}
/* dump a unicode string contained in a buffer; helper for dump_varargs_startup_info */
static void dump_inline_unicode_string( const UNICODE_STRING *str, const void *data, data_size_t size )
static data_size_t dump_inline_unicode_string( const char *prefix, data_size_t pos, data_size_t len, data_size_t total_size )
{
size_t length = str->Length;
size_t offset = (size_t)str->Buffer;
if (offset >= size) return;
if (offset + length > size) length = size - offset;
dump_strW( (const WCHAR *)data + offset/sizeof(WCHAR), length/sizeof(WCHAR), stderr, "\"\"" );
fputs( prefix, stderr );
if (pos >= total_size) return pos;
if (len > total_size - pos) len = total_size - pos;
len /= sizeof(WCHAR);
dump_strW( (const WCHAR *)cur_data + pos/sizeof(WCHAR), len, stderr, "\"\"" );
return pos + len * sizeof(WCHAR);
}
static void dump_varargs_startup_info( const char *prefix, data_size_t size )
{
const RTL_USER_PROCESS_PARAMETERS *ptr = cur_data;
RTL_USER_PROCESS_PARAMETERS params;
startup_info_t info;
data_size_t pos = sizeof(info);
if (size < sizeof(params.Size))
{
fprintf( stderr, "%s{}", prefix );
return;
}
if (size > ptr->Size) size = ptr->Size;
memset( &params, 0, sizeof(params) );
memcpy( &params, ptr, min( size, sizeof(params) ));
memset( &info, 0, sizeof(info) );
memcpy( &info, cur_data, min( size, sizeof(info) ));
fprintf( stderr, "%s{AllocationSize=%x,", prefix, params.AllocationSize );
fprintf( stderr, "Size=%x,", params.Size );
fprintf( stderr, "Flags=%x,", params.Flags );
fprintf( stderr, "DebugFlags=%x,", params.DebugFlags );
fprintf( stderr, "ConsoleHandle=%p,", params.ConsoleHandle );
fprintf( stderr, "ConsoleFlags=%x,", params.ConsoleFlags );
fprintf( stderr, "hStdInput=%p,", params.hStdInput );
fprintf( stderr, "hStdOutput=%p,", params.hStdOutput );
fprintf( stderr, "hStdError=%p,", params.hStdError );
fprintf( stderr, "CurrentDirectory.Handle=%p,", params.CurrentDirectory.Handle );
fprintf( stderr, "dwX=%d,", params.dwX );
fprintf( stderr, "dwY=%d,", params.dwY );
fprintf( stderr, "dwXSize=%d,", params.dwXSize );
fprintf( stderr, "dwYSize=%d,", params.dwYSize );
fprintf( stderr, "dwXCountChars=%d,", params.dwXCountChars );
fprintf( stderr, "dwYCountChars=%d,", params.dwYCountChars );
fprintf( stderr, "dwFillAttribute=%x,", params.dwFillAttribute );
fprintf( stderr, "dwFlags=%x,", params.dwFlags );
fprintf( stderr, "wShowWindow=%x,", params.wShowWindow );
fprintf( stderr, "CurrentDirectory.DosPath=L\"" );
dump_inline_unicode_string( &params.CurrentDirectory.DosPath, cur_data, size );
fprintf( stderr, "\",DllPath=L\"" );
dump_inline_unicode_string( &params.DllPath, cur_data, size );
fprintf( stderr, "\",ImagePathName=L\"" );
dump_inline_unicode_string( &params.ImagePathName, cur_data, size );
fprintf( stderr, "\",CommandLine=L\"" );
dump_inline_unicode_string( &params.CommandLine, cur_data, size );
fprintf( stderr, "\",WindowTitle=L\"" );
dump_inline_unicode_string( &params.WindowTitle, cur_data, size );
fprintf( stderr, "\",Desktop=L\"" );
dump_inline_unicode_string( &params.Desktop, cur_data, size );
fprintf( stderr, "\",ShellInfo=L\"" );
dump_inline_unicode_string( &params.ShellInfo, cur_data, size );
fprintf( stderr, "\",RuntimeInfo=L\"" );
dump_inline_unicode_string( &params.RuntimeInfo, cur_data, 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",
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 );
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 );
pos = dump_inline_unicode_string( "\",cmdline=L\"", pos, info.cmdline_len, size );
pos = dump_inline_unicode_string( "\",title=L\"", pos, info.title_len, size );
pos = dump_inline_unicode_string( "\",desktop=L\"", pos, info.desktop_len, size );
pos = dump_inline_unicode_string( "\",shellinfo=L\"", pos, info.shellinfo_len, size );
pos = dump_inline_unicode_string( "\",runtime=L\"", pos, info.runtime_len, size );
fprintf( stderr, "\"}" );
remove_data( size );
}
@ -1025,14 +998,12 @@ static void dump_new_process_request( const struct new_process_request *req )
fprintf( stderr, ", create_flags=%08x", req->create_flags );
fprintf( stderr, ", socket_fd=%d", req->socket_fd );
fprintf( stderr, ", exe_file=%04x", req->exe_file );
fprintf( stderr, ", hstdin=%04x", req->hstdin );
fprintf( stderr, ", hstdout=%04x", req->hstdout );
fprintf( stderr, ", hstderr=%04x", req->hstderr );
fprintf( stderr, ", process_access=%08x", req->process_access );
fprintf( stderr, ", process_attr=%08x", req->process_attr );
fprintf( stderr, ", thread_access=%08x", req->thread_access );
fprintf( stderr, ", thread_attr=%08x", req->thread_attr );
dump_varargs_startup_info( ", info=", cur_size );
fprintf( stderr, ", info_size=%u", req->info_size );
dump_varargs_startup_info( ", info=", min(cur_size,req->info_size) );
dump_varargs_unicode_str( ", env=", cur_size );
}
@ -1077,10 +1048,8 @@ static void dump_get_startup_info_request( const struct get_startup_info_request
static void dump_get_startup_info_reply( const struct get_startup_info_reply *req )
{
fprintf( stderr, " exe_file=%04x", req->exe_file );
fprintf( stderr, ", hstdin=%04x", req->hstdin );
fprintf( stderr, ", hstdout=%04x", req->hstdout );
fprintf( stderr, ", hstderr=%04x", req->hstderr );
dump_varargs_startup_info( ", info=", cur_size );
fprintf( stderr, ", info_size=%u", req->info_size );
dump_varargs_startup_info( ", info=", min(cur_size,req->info_size) );
dump_varargs_unicode_str( ", env=", cur_size );
}