ntdll/kernel32: #25 (take 2)
Eric Pouech
pouech-eric at wanadoo.fr
Thu May 22 08:40:59 CDT 2003
this patch revisits the management of process parameters. it also
includes the latest fix to Alexandre's comments
mainly:
- it fixes a couple of bugs in ntdll environment functions (one in
trace, the other one in environment variable expansion)
- the process parameters, when passed thru wineserver, are now fully
handled in ntdll. they are stored in the RTL_USER_PROCESS_PARAMETERS
structure.
- later on in kernel32 loading sequence, those parameters are copied
into STARTUPINFO shadow structures
- later modification to those paramters are now reflected to the
RTL_USER_PROCESS_PARAMETERS structure (and STARTUPINFO is kept
untouched) (for example, StdHandle setting) (Win 2k behaves like this)
- ENVDB has been removed
- command line inheritance (from unix command line) is now purely in ntdll
- all kernel32 environment functions now rely on their ntdll counterparts
- goodies: input/output handle inheritance while asking for a detached
console is better handled; a few more kernel32 environment tests now
pass ; silenced a valgrind warning in process creation
bad side effects:
- we no longer can provide a decent access to 16 bit environment block:
mainly because the environment reference block is stored as unicode.
Current code recreates a new 16 bit environment each time the
environment is modified. However, this suffers from several issues: 1/
it's rather costly, 2/ it won't work when environment is modified thru
ntdll APIs 3/ it won't work if the app modifies its own 16 bit
environment. I still wonder if current code is sufficient or not.
A+
--
Eric Pouech
-------------- next part --------------
Index: dlls/kernel25/kernel_main.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/kernel/kernel_main.c,v
retrieving revision 1.43
diff -u -r1.43 kernel_main.c
--- dlls/kernel25/kernel_main.c 22 May 2003 03:41:27 -0000 1.43
+++ dlls/kernel25/kernel_main.c 22 May 2003 12:40:52 -0000
@@ -48,6 +48,8 @@
extern void COMPUTERNAME_Init(void);
extern int __wine_set_signal_handler(unsigned, int (*)(unsigned));
+/* memory/environ.c */
+extern void ENV_CopyStartupInformation(void);
extern int main_create_flags;
@@ -113,6 +115,9 @@
/* Setup computer name */
COMPUTERNAME_Init();
+
+ /* copy process information from ntdll */
+ ENV_CopyStartupInformation();
if ((hModule = LoadLibrary16( "krnl386.exe" )) >= 32)
{
@@ -168,6 +173,14 @@
if (RtlImageNtHeader(mod)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
AllocConsole();
}
+ else if (!(main_create_flags & DETACHED_PROCESS))
+ {
+ /* 1/ shall inherit console + handles
+ * 2/ shall create std handles, if handles are not inherited
+ * TBD when not using wineserver handles for console handles
+ */
+ }
+
if (main_create_flags & CREATE_NEW_PROCESS_GROUP)
SetConsoleCtrlHandler(NULL, TRUE);
Index: dlls/ntdll25/env.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/env.c,v
retrieving revision 1.2
diff -u -r1.2 env.c
--- dlls/ntdll25/env.c 13 May 2003 04:45:50 -0000 1.2
+++ dlls/ntdll25/env.c 22 May 2003 12:02:22 -0000
@@ -130,6 +130,7 @@
if (var != NULL)
{
value->Length = strlenW(var) * sizeof(WCHAR);
+
if (value->Length <= value->MaximumLength)
{
memmove(value->Buffer, var, min(value->Length + sizeof(WCHAR), value->MaximumLength));
@@ -171,7 +172,9 @@
NTSTATUS nts = STATUS_VARIABLE_NOT_FOUND;
MEMORY_BASIC_INFORMATION mbi;
- TRACE("(%p,%s,%s): stub!\n", penv, debugstr_w(name->Buffer), debugstr_w(value->Buffer));
+ TRACE("(%p,%s,%s)\n",
+ penv, debugstr_w(name->Buffer),
+ value ? debugstr_w(value->Buffer) : "--nil--");
if (!name || !name->Buffer || !name->Buffer[0])
return STATUS_INVALID_PARAMETER_1;
@@ -245,7 +248,6 @@
strcatW(p, equalW);
strcatW(p, value->Buffer);
}
-
done:
if (!penv) RtlReleasePebLock();
@@ -256,18 +258,23 @@
* RtlExpandEnvironmentStrings_U (NTDLL.@)
*
*/
-NTSTATUS WINAPI RtlExpandEnvironmentStrings_U(PWSTR env, const UNICODE_STRING* us_src,
+NTSTATUS WINAPI RtlExpandEnvironmentStrings_U(PWSTR renv, const UNICODE_STRING* us_src,
PUNICODE_STRING us_dst, PULONG plen)
{
DWORD len, count, total_size = 1; /* 1 for terminating '\0' */
- LPCWSTR src, p, var;
+ LPCWSTR env, src, p, var;
LPWSTR dst;
src = us_src->Buffer;
count = us_dst->MaximumLength / sizeof(WCHAR);
dst = count ? us_dst->Buffer : NULL;
- RtlAcquirePebLock();
+ if (!renv)
+ {
+ RtlAcquirePebLock();
+ env = ntdll_get_process_pmts()->Environment;
+ }
+ else env = renv;
while (*src)
{
@@ -312,12 +319,12 @@
}
}
- RtlReleasePebLock();
+ if (!renv) RtlReleasePebLock();
/* Null-terminate the string */
if (dst && count) *dst = '\0';
- us_dst->Length = (dst) ? (dst - us_dst->Buffer) * sizeof(WCHAR): 0;
+ us_dst->Length = (dst) ? (dst - us_dst->Buffer) * sizeof(WCHAR) : 0;
if (plen) *plen = total_size * sizeof(WCHAR);
return (count) ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL;
@@ -328,7 +335,7 @@
*
* Build the Win32 environment from the Unix environment
*/
-BOOL build_initial_environment(void)
+static NTSTATUS build_initial_environment(void)
{
extern char **environ;
LPSTR* e, te;
@@ -349,9 +356,10 @@
/* Now allocate the environment */
nts = NtAllocateVirtualMemory(NtCurrentProcess(), (void**)&p, 0, &size,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
- if (nts != STATUS_SUCCESS) return FALSE;
+ if (nts != STATUS_SUCCESS) return nts;
ntdll_get_process_pmts()->Environment = p;
+
/* And fill it with the Unix environment */
for (e = environ; *e; e++)
{
@@ -365,5 +373,260 @@
}
*p = 0;
+ return STATUS_SUCCESS;
+}
+
+static void init_unicode( UNICODE_STRING* us, const char** src, size_t len)
+{
+ if (len)
+ {
+ STRING ansi;
+ ansi.Buffer = (char*)*src;
+ ansi.Length = len;
+ ansi.MaximumLength = len;
+ /* FIXME: should check value returned */
+ RtlAnsiStringToUnicodeString( us, &ansi, TRUE );
+ *src += len;
+ }
+}
+
+/***********************************************************************
+ * init_user_process_pmts
+ *
+ * Fill the RTL_USER_PROCESS_ARAMETERS structure from the server.
+ */
+BOOL init_user_process_pmts( size_t info_size, char *main_exe_name, size_t main_exe_size )
+{
+ startup_info_t info;
+ void *data;
+ const char *src;
+ size_t len;
+ RTL_USER_PROCESS_PARAMETERS *rupp;
+
+ if (build_initial_environment() != STATUS_SUCCESS) return FALSE;
+ if (!info_size) return TRUE;
+ if (!(data = RtlAllocateHeap( ntdll_get_process_heap(), 0, info_size )))
+ return FALSE;
+
+ SERVER_START_REQ( get_startup_info )
+ {
+ wine_server_set_reply( req, data, info_size );
+ wine_server_call( req );
+ info_size = wine_server_reply_size( reply );
+ }
+ SERVER_END_REQ;
+
+ if (info_size < sizeof(info.size)) goto done;
+ len = min( info_size, ((startup_info_t *)data)->size );
+ memset( &info, 0, sizeof(info) );
+ memcpy( &info, data, len );
+ src = (char *)data + len;
+ info_size -= len;
+
+ /* fixup the lengths */
+ if (info.filename_len > info_size) info.filename_len = info_size;
+ info_size -= info.filename_len;
+ if (info.cmdline_len > info_size) info.cmdline_len = info_size;
+ info_size -= info.cmdline_len;
+ if (info.desktop_len > info_size) info.desktop_len = info_size;
+ info_size -= info.desktop_len;
+ if (info.title_len > info_size) info.title_len = info_size;
+
+ /* store the filename */
+ len = min( info.filename_len, main_exe_size-1 );
+ memcpy( main_exe_name, src, len );
+ main_exe_name[len] = 0;
+
+ rupp = NtCurrentTeb()->Peb->ProcessParameters;
+
+ init_unicode( &rupp->ImagePathName, &src, info.filename_len );
+ init_unicode( &rupp->CommandLine, &src, info.cmdline_len );
+ init_unicode( &rupp->Desktop, &src, info.desktop_len );
+ init_unicode( &rupp->WindowTitle, &src, info.title_len );
+
+ rupp->dwX = info.x;
+ rupp->dwY = info.y;
+ rupp->dwXSize = info.cx;
+ rupp->dwYSize = info.cy;
+ rupp->dwXCountChars = info.x_chars;
+ rupp->dwYCountChars = info.y_chars;
+ rupp->dwFillAttribute = info.attribute;
+ rupp->wShowWindow = info.cmd_show;
+ rupp->dwFlags = info.flags;
+
+ done:
+ RtlFreeHeap( ntdll_get_process_heap(), 0, data );
return TRUE;
}
+
+/***********************************************************************
+ * set_library_argv
+ *
+ * Set the Wine library argc/argv global variables.
+ */
+static void set_library_argv( char **argv )
+{
+ int argc;
+ WCHAR *p;
+ WCHAR **wargv;
+ DWORD total = 0, len, reslen;
+
+ for (argc = 0; argv[argc]; argc++)
+ {
+ len = strlen(argv[argc]) + 1;
+ RtlMultiByteToUnicodeN(NULL, 0, &reslen, argv[argc], len);
+ total += reslen;
+ }
+ wargv = RtlAllocateHeap( ntdll_get_process_heap(), 0,
+ total + (argc + 1) * sizeof(*wargv) );
+ p = (WCHAR *)(wargv + argc + 1);
+ for (argc = 0; argv[argc]; argc++)
+ {
+ len = strlen(argv[argc]) + 1;
+ RtlMultiByteToUnicodeN(p, total, &reslen, argv[argc], len);
+ wargv[argc] = p;
+ p += reslen / sizeof(WCHAR);
+ total -= reslen;
+ }
+ wargv[argc] = NULL;
+
+ __wine_main_argc = argc;
+ __wine_main_argv = argv;
+ __wine_main_wargv = wargv;
+}
+
+/***********************************************************************
+ * build_command_line
+ *
+ * Build the command line of a process from the argv array.
+ *
+ * Note that it does NOT necessarily include the file name.
+ * Sometimes we don't even have any command line options at all.
+ *
+ * We must quote and escape characters so that the argv array can be rebuilt
+ * from the command line:
+ * - spaces and tabs must be quoted
+ * 'a b' -> '"a b"'
+ * - quotes must be escaped
+ * '"' -> '\"'
+ * - if '\'s are followed by a '"', they must be doubled and followed by '\"',
+ * resulting in an odd number of '\' followed by a '"'
+ * '\"' -> '\\\"'
+ * '\\"' -> '\\\\\"'
+ * - '\'s that are not followed by a '"' can be left as is
+ * 'a\b' == 'a\b'
+ * 'a\\b' == 'a\\b'
+ */
+BOOL build_command_line( char **argv )
+{
+ int len;
+ char **arg;
+ LPWSTR p;
+ RTL_USER_PROCESS_PARAMETERS* rupp;
+
+ set_library_argv( argv );
+
+ rupp = ntdll_get_process_pmts();
+ if (rupp->CommandLine.Buffer) return TRUE; /* already got it from the server */
+
+ len = 0;
+ for (arg = argv; *arg; arg++)
+ {
+ int has_space,bcount;
+ char* a;
+
+ has_space=0;
+ bcount=0;
+ a=*arg;
+ while (*a!='\0') {
+ if (*a=='\\') {
+ bcount++;
+ } else {
+ if (*a==' ' || *a=='\t') {
+ has_space=1;
+ } else if (*a=='"') {
+ /* doubling of '\' preceeding a '"',
+ * plus escaping of said '"'
+ */
+ len+=2*bcount+1;
+ }
+ bcount=0;
+ }
+ a++;
+ }
+ len+=(a-*arg)+1 /* for the separating space */;
+ if (has_space)
+ len+=2; /* for the quotes */
+ }
+
+ if (!(rupp->CommandLine.Buffer = RtlAllocateHeap( ntdll_get_process_heap(), 0, len * sizeof(WCHAR))))
+ return FALSE;
+
+ p = rupp->CommandLine.Buffer;
+ rupp->CommandLine.Length = (len - 1) * sizeof(WCHAR);
+ rupp->CommandLine.MaximumLength = len * sizeof(WCHAR);
+ for (arg = argv; *arg; arg++)
+ {
+ int has_space,has_quote;
+ char* a;
+
+ /* Check for quotes and spaces in this argument */
+ has_space=has_quote=0;
+ a=*arg;
+ while (*a!='\0') {
+ if (*a==' ' || *a=='\t') {
+ has_space=1;
+ if (has_quote)
+ break;
+ } else if (*a=='"') {
+ has_quote=1;
+ if (has_space)
+ break;
+ }
+ a++;
+ }
+
+ /* Now transfer it to the command line */
+ if (has_space)
+ *p++='"';
+ if (has_quote) {
+ int bcount;
+ char* a;
+
+ bcount=0;
+ a=*arg;
+ while (*a!='\0') {
+ if (*a=='\\') {
+ *p++=*a;
+ bcount++;
+ } else {
+ if (*a=='"') {
+ int i;
+
+ /* Double all the '\\' preceeding this '"', plus one */
+ for (i=0;i<=bcount;i++)
+ *p++='\\';
+ *p++='"';
+ } else {
+ *p++=*a;
+ }
+ bcount=0;
+ }
+ a++;
+ }
+ } else {
+ char* x = *arg;
+ while ((*p=*x++)) p++;
+ }
+ if (has_space)
+ *p++='"';
+ *p++=' ';
+ }
+ if (p > rupp->CommandLine.Buffer)
+ p--; /* remove last space */
+ *p = '\0';
+
+ return TRUE;
+}
+
+
Index: dlls/ntdll25/ntdll_misc.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/ntdll_misc.h,v
retrieving revision 1.17
diff -u -r1.17 ntdll_misc.h
--- dlls/ntdll25/ntdll_misc.h 22 May 2003 03:44:02 -0000 1.17
+++ dlls/ntdll25/ntdll_misc.h 22 May 2003 11:31:31 -0000
@@ -45,12 +45,8 @@
return NtCurrentTeb()->Peb->ProcessHeap;
}
-/* FIXME: this should be part of PEB, once it's defined */
-extern RTL_USER_PROCESS_PARAMETERS process_pmts;
-BOOL build_initial_environment(void);
-
static inline RTL_USER_PROCESS_PARAMETERS* ntdll_get_process_pmts(void)
{
- return &process_pmts;
+ return NtCurrentTeb()->Peb->ProcessParameters;
}
#endif
Index: include25/winternl.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/include/winternl.h,v
retrieving revision 1.38
diff -u -r1.38 winternl.h
--- include25/winternl.h 22 May 2003 03:44:01 -0000 1.38
+++ include25/winternl.h 22 May 2003 11:31:16 -0000
@@ -126,7 +126,7 @@
ULONG dwFlags;
ULONG wShowWindow;
UNICODE_STRING WindowTitle;
- UNICODE_STRING DesktopInfo;
+ UNICODE_STRING Desktop;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeInfo;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
Index: memory25/environ.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/memory/environ.c,v
retrieving revision 1.39
diff -u -r1.39 environ.c
--- memory25/environ.c 23 Jan 2003 23:07:39 -0000 1.39
+++ memory25/environ.c 22 May 2003 12:41:29 -0000
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include "windef.h"
#include "winerror.h"
@@ -33,27 +34,13 @@
#include "heap.h"
#include "winternl.h"
#include "selectors.h"
+#include "wine/debug.h"
-/* Win32 process environment database */
-typedef struct _ENVDB
-{
- LPSTR env; /* 00 Process environment strings */
- DWORD unknown1; /* 04 Unknown */
- LPSTR cmd_line; /* 08 Command line */
- LPSTR cur_dir; /* 0c Current directory */
- STARTUPINFOA *startup_info; /* 10 Startup information */
- HANDLE hStdin; /* 14 Handle for standard input */
- HANDLE hStdout; /* 18 Handle for standard output */
- HANDLE hStderr; /* 1c Handle for standard error */
- DWORD unknown2; /* 20 Unknown */
- DWORD inherit_console; /* 24 Inherit console flag */
- DWORD break_type; /* 28 Console events flag */
- void *break_sem; /* 2c SetConsoleCtrlHandler semaphore */
- void *break_event; /* 30 SetConsoleCtrlHandler event */
- void *break_thread; /* 34 SetConsoleCtrlHandler thread */
- void *break_handlers; /* 38 List of console handlers */
-} ENVDB;
+WINE_DEFAULT_DEBUG_CHANNEL(environ);
+/* TODO:
+ * - 16 bit environment ??? (see generate_env_block16 for the details)
+ */
/* Format of an environment block:
* ASCIIZ string 1 (xx=yy format)
@@ -67,386 +54,61 @@
* - contrary to Microsoft docs, the environment strings do not appear
* to be sorted on Win95 (although they are on NT); so we don't bother
* to sort them either.
+ * - on Win2K (and likely most of NT versions) the last part (WORD 1 and
+ * program name no longer appear in the environment block (from the 32
+ * bit interface)
*/
static const char ENV_program_name[] = "C:\\WINDOWS\\SYSTEM\\KRNL386.EXE";
+static STARTUPINFOW startup_infoW;
+static STARTUPINFOA startup_infoA;
+
/* Maximum length of a Win16 environment string (including NULL) */
#define MAX_WIN16_LEN 128
-STARTUPINFOA current_startupinfo =
-{
- sizeof(STARTUPINFOA), /* cb */
- 0, /* lpReserved */
- 0, /* lpDesktop */
- 0, /* lpTitle */
- 0, /* dwX */
- 0, /* dwY */
- 0, /* dwXSize */
- 0, /* dwYSize */
- 0, /* dwXCountChars */
- 0, /* dwYCountChars */
- 0, /* dwFillAttribute */
- 0, /* dwFlags */
- 0, /* wShowWindow */
- 0, /* cbReserved2 */
- 0, /* lpReserved2 */
- 0, /* hStdInput */
- 0, /* hStdOutput */
- 0 /* hStdError */
-};
-
-ENVDB current_envdb =
-{
- 0, /* environ */
- 0, /* unknown1 */
- 0, /* cmd_line */
- 0, /* cur_dir */
- ¤t_startupinfo, /* startup_info */
- 0, /* hStdin */
- 0, /* hStdout */
- 0, /* hStderr */
- 0, /* unknown2 */
- 0, /* inherit_console */
- 0, /* break_type */
- 0, /* break_sem */
- 0, /* break_event */
- 0, /* break_thread */
- 0 /* break_handlers */
-};
-
-
-static WCHAR *cmdlineW; /* Unicode command line */
-static WORD env_sel; /* selector to the environment */
-
-/***********************************************************************
- * ENV_FindVariable
- *
- * Find a variable in the environment and return a pointer to the value.
- * Helper function for GetEnvironmentVariable and ExpandEnvironmentStrings.
- */
-static LPCSTR ENV_FindVariable( LPCSTR env, LPCSTR name, INT len )
-{
- while (*env)
- {
- if (!strncasecmp( name, env, len ) && (env[len] == '='))
- return env + len + 1;
- env += strlen(env) + 1;
- }
- return NULL;
-}
-
-
-/***********************************************************************
- * build_environment
- *
- * Build the environment for the initial process
- */
-static BOOL build_environment(void)
-{
- extern char **environ;
- static const WORD one = 1;
- LPSTR p, *e;
- int size;
-
- /* Compute the total size of the Unix environment */
-
- size = sizeof(BYTE) + sizeof(WORD) + sizeof(ENV_program_name);
- for (e = environ; *e; e++)
- {
- if (!memcmp( *e, "PATH=", 5 )) continue;
- size += strlen(*e) + 1;
- }
-
- /* Now allocate the environment */
-
- if (!(p = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
- current_envdb.env = p;
- env_sel = SELECTOR_AllocBlock( p, 0x10000, WINE_LDT_FLAGS_DATA );
-
- /* And fill it with the Unix environment */
-
- for (e = environ; *e; e++)
- {
- /* skip Unix PATH and store WINEPATH as PATH */
- if (!memcmp( *e, "PATH=", 5 )) continue;
- if (!memcmp( *e, "WINEPATH=", 9 )) strcpy( p, *e + 4 );
- else strcpy( p, *e );
- p += strlen(p) + 1;
- }
-
- /* Now add the program name */
-
- *p++ = 0;
- memcpy( p, &one, sizeof(WORD) );
- strcpy( p + sizeof(WORD), ENV_program_name );
- return TRUE;
-}
-
-
-/***********************************************************************
- * copy_str
- *
- * Small helper for ENV_InitStartupInfo.
- */
-inline static char *copy_str( char **dst, const char **src, size_t len )
-{
- char *ret;
-
- if (!len) return NULL;
- ret = *dst;
- memcpy( ret, *src, len );
- ret[len] = 0;
- *dst += len + 1;
- *src += len;
- return ret;
-}
-
-
-/***********************************************************************
- * ENV_InitStartupInfo
- *
- * Fill the startup info structure from the server.
- */
-ENVDB *ENV_InitStartupInfo( size_t info_size, char *main_exe_name, size_t main_exe_size )
-{
- startup_info_t info;
- void *data;
- char *dst;
- const char *src;
- size_t len;
-
- if (!build_environment()) return NULL;
- if (!info_size) return ¤t_envdb; /* nothing to retrieve */
+static WORD env_sel; /* selector to the 16 bit environment */
- if (!(data = HeapAlloc( GetProcessHeap(), 0, info_size ))) return NULL;
-
- SERVER_START_REQ( get_startup_info )
- {
- wine_server_set_reply( req, data, info_size );
- wine_server_call( req );
- info_size = wine_server_reply_size( reply );
- }
- SERVER_END_REQ;
- if (info_size < sizeof(info.size)) goto done;
- len = min( info_size, ((startup_info_t *)data)->size );
- memset( &info, 0, sizeof(info) );
- memcpy( &info, data, len );
- src = (char *)data + len;
- info_size -= len;
-
- /* fixup the lengths */
- if (info.filename_len > info_size) info.filename_len = info_size;
- info_size -= info.filename_len;
- if (info.cmdline_len > info_size) info.cmdline_len = info_size;
- info_size -= info.cmdline_len;
- if (info.desktop_len > info_size) info.desktop_len = info_size;
- info_size -= info.desktop_len;
- if (info.title_len > info_size) info.title_len = info_size;
-
- /* store the filename */
- if (info.filename_len)
- {
- len = min( info.filename_len, main_exe_size-1 );
- memcpy( main_exe_name, src, len );
- main_exe_name[len] = 0;
- src += info.filename_len;
- }
-
- /* copy the other strings */
- len = info.cmdline_len + info.desktop_len + info.title_len;
- if (len && (dst = HeapAlloc( GetProcessHeap(), 0, len + 3 )))
- {
- current_envdb.cmd_line = copy_str( &dst, &src, info.cmdline_len );
- current_startupinfo.lpDesktop = copy_str( &dst, &src, info.desktop_len );
- current_startupinfo.lpTitle = copy_str( &dst, &src, info.title_len );
- }
-
- current_startupinfo.dwX = info.x;
- current_startupinfo.dwY = info.y;
- current_startupinfo.dwXSize = info.cx;
- current_startupinfo.dwYSize = info.cy;
- current_startupinfo.dwXCountChars = info.x_chars;
- current_startupinfo.dwYCountChars = info.y_chars;
- current_startupinfo.dwFillAttribute = info.attribute;
- current_startupinfo.wShowWindow = info.cmd_show;
- current_startupinfo.dwFlags = info.flags;
- done:
- HeapFree( GetProcessHeap(), 0, data );
- return ¤t_envdb;
-}
-
-
-
-/***********************************************************************
- * set_library_argv
- *
- * Set the Wine library argc/argv global variables.
- */
-static void set_library_argv( char **argv )
-{
- int argc;
- WCHAR *p;
- WCHAR **wargv;
- DWORD total = 0;
-
- for (argc = 0; argv[argc]; argc++)
- total += MultiByteToWideChar( CP_ACP, 0, argv[argc], -1, NULL, 0 );
-
- wargv = HeapAlloc( GetProcessHeap(), 0,
- total * sizeof(WCHAR) + (argc + 1) * sizeof(*wargv) );
- p = (WCHAR *)(wargv + argc + 1);
- for (argc = 0; argv[argc]; argc++)
- {
- DWORD len = MultiByteToWideChar( CP_ACP, 0, argv[argc], -1, p, total );
- wargv[argc] = p;
- p += len;
- total -= len;
- }
- wargv[argc] = NULL;
-
- __wine_main_argc = argc;
- __wine_main_argv = argv;
- __wine_main_wargv = wargv;
-}
-
-
-/***********************************************************************
- * ENV_BuildCommandLine
- *
- * Build the command line of a process from the argv array.
+/******************************************************************
+ * generate_env_block16
*
- * Note that it does NOT necessarily include the file name.
- * Sometimes we don't even have any command line options at all.
+ * This internal function generates a suitable environment for the 16 bit
+ * subsystem and returns the value as a segmented pointer.
*
- * We must quote and escape characters so that the argv array can be rebuilt
- * from the command line:
- * - spaces and tabs must be quoted
- * 'a b' -> '"a b"'
- * - quotes must be escaped
- * '"' -> '\"'
- * - if '\'s are followed by a '"', they must be doubled and followed by '\"',
- * resulting in an odd number of '\' followed by a '"'
- * '\"' -> '\\\"'
- * '\\"' -> '\\\\\"'
- * - '\'s that are not followed by a '"' can be left as is
- * 'a\b' == 'a\b'
- * 'a\\b' == 'a\\b'
- */
-BOOL ENV_BuildCommandLine( char **argv )
-{
- int len;
- char *p, **arg;
-
- set_library_argv( argv );
-
- if (current_envdb.cmd_line) goto done; /* already got it from the server */
-
- len = 0;
- for (arg = argv; *arg; arg++)
- {
- int has_space,bcount;
- char* a;
-
- has_space=0;
- bcount=0;
- a=*arg;
- while (*a!='\0') {
- if (*a=='\\') {
- bcount++;
- } else {
- if (*a==' ' || *a=='\t') {
- has_space=1;
- } else if (*a=='"') {
- /* doubling of '\' preceeding a '"',
- * plus escaping of said '"'
- */
- len+=2*bcount+1;
- }
- bcount=0;
- }
- a++;
- }
- len+=(a-*arg)+1 /* for the separating space */;
- if (has_space)
- len+=2; /* for the quotes */
- }
+ * FIXME: current implementation will allocate a private copy of the
+ * environment strings, but will not follow the modifications (if any)
+ * from the unicode env block stored in the PEB
+ * => how should this be updated from the ntdll modifications ?
+ * should we use the peb->EnvironmentUpdateCount field to
+ * know when environment has changed ???
+ * we currently regenerate this block each time an environment
+ * variable is modified from a Win32 API call, but we'll miss all
+ * direct access to the NTDLL APIs
+ */
+static SEGPTR generate_env_block16(void)
+{
+ static LPSTR env16;
+
+ DWORD size, new_size;
+ WORD one = 1;
+
+ if (env16) FreeEnvironmentStringsA( env16 );
+
+ env16 = GetEnvironmentStringsA();
+ size = HeapSize(GetProcessHeap(), 0, env16);
+ new_size = size + sizeof(WORD) + sizeof(ENV_program_name);
+ if (!(env16 = HeapReAlloc( GetProcessHeap(), 0, env16, new_size ))) return 0;
+
+ memcpy(env16 + size, &one, sizeof(one));
+ memcpy(env16 + size + sizeof(WORD), ENV_program_name, sizeof(ENV_program_name));
+ if (env_sel)
+ env_sel = SELECTOR_ReallocBlock( env_sel, env16, new_size );
+ else
+ env_sel = SELECTOR_AllocBlock( env16, 0x10000, WINE_LDT_FLAGS_DATA );
- if (!(current_envdb.cmd_line = HeapAlloc( GetProcessHeap(), 0, len )))
- return FALSE;
-
- p = current_envdb.cmd_line;
- for (arg = argv; *arg; arg++)
- {
- int has_space,has_quote;
- char* a;
-
- /* Check for quotes and spaces in this argument */
- has_space=has_quote=0;
- a=*arg;
- while (*a!='\0') {
- if (*a==' ' || *a=='\t') {
- has_space=1;
- if (has_quote)
- break;
- } else if (*a=='"') {
- has_quote=1;
- if (has_space)
- break;
- }
- a++;
- }
-
- /* Now transfer it to the command line */
- if (has_space)
- *p++='"';
- if (has_quote) {
- int bcount;
- char* a;
-
- bcount=0;
- a=*arg;
- while (*a!='\0') {
- if (*a=='\\') {
- *p++=*a;
- bcount++;
- } else {
- if (*a=='"') {
- int i;
-
- /* Double all the '\\' preceeding this '"', plus one */
- for (i=0;i<=bcount;i++)
- *p++='\\';
- *p++='"';
- } else {
- *p++=*a;
- }
- bcount=0;
- }
- a++;
- }
- } else {
- strcpy(p,*arg);
- p+=strlen(*arg);
- }
- if (has_space)
- *p++='"';
- *p++=' ';
- }
- if (p > current_envdb.cmd_line)
- p--; /* remove last space */
- *p = '\0';
-
- /* now allocate the Unicode version */
- done:
- len = MultiByteToWideChar( CP_ACP, 0, current_envdb.cmd_line, -1, NULL, 0 );
- if (!(cmdlineW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
- return FALSE;
- MultiByteToWideChar( CP_ACP, 0, current_envdb.cmd_line, -1, cmdlineW, len );
- return TRUE;
+ return MAKESEGPTR( env_sel, 0 );
}
-
/***********************************************************************
* GetCommandLineA (KERNEL32.@)
*
@@ -467,7 +129,18 @@
*/
LPSTR WINAPI GetCommandLineA(void)
{
- return current_envdb.cmd_line;
+ static char *cmdlineA; /* ASCII command line */
+
+ if (!cmdlineA) /* make an ansi version if we don't have it */
+ {
+ ANSI_STRING ansi;
+ RtlAcquirePebLock();
+
+ cmdlineA = (RtlUnicodeStringToAnsiString( &ansi, &NtCurrentTeb()->Peb->ProcessParameters->CommandLine, TRUE) == STATUS_SUCCESS) ?
+ ansi.Buffer : NULL;
+ RtlReleasePebLock();
+ }
+ return cmdlineA;
}
/***********************************************************************
@@ -475,7 +148,7 @@
*/
LPWSTR WINAPI GetCommandLineW(void)
{
- return cmdlineW;
+ return NtCurrentTeb()->Peb->ProcessParameters->CommandLine.Buffer;
}
@@ -485,7 +158,38 @@
*/
LPSTR WINAPI GetEnvironmentStringsA(void)
{
- return current_envdb.env;
+ LPWSTR ptrW;
+ unsigned len, slen;
+ LPSTR ret, ptrA;
+
+ RtlAcquirePebLock();
+
+ len = 1;
+
+ ptrW = NtCurrentTeb()->Peb->ProcessParameters->Environment;
+ while (*ptrW)
+ {
+ slen = lstrlenW(ptrW) + 1;
+ len += WideCharToMultiByte( CP_ACP, 0, ptrW, slen, NULL, 0, NULL, NULL );
+ ptrW += slen;
+ }
+
+ if ((ret = HeapAlloc( GetProcessHeap(), 0, len )) != NULL)
+ {
+ ptrW = NtCurrentTeb()->Peb->ProcessParameters->Environment;
+ ptrA = ret;
+ while (*ptrW)
+ {
+ slen = lstrlenW(ptrW) + 1;
+ WideCharToMultiByte( CP_ACP, 0, ptrW, slen, ptrA, len, NULL, NULL );
+ ptrW += slen;
+ ptrA += strlen(ptrA) + 1;
+ }
+ *ptrA = 0;
+ }
+
+ RtlReleasePebLock();
+ return ret;
}
@@ -494,19 +198,7 @@
*/
LPWSTR WINAPI GetEnvironmentStringsW(void)
{
- INT size;
- LPWSTR ret;
-
- RtlAcquirePebLock();
- size = HeapSize( GetProcessHeap(), 0, current_envdb.env );
- if ((ret = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )) != NULL)
- {
- LPSTR pA = current_envdb.env;
- LPWSTR pW = ret;
- while (size--) *pW++ = (WCHAR)(BYTE)*pA++;
- }
- RtlReleasePebLock();
- return ret;
+ return NtCurrentTeb()->Peb->ProcessParameters->Environment;
}
@@ -515,12 +207,7 @@
*/
BOOL WINAPI FreeEnvironmentStringsA( LPSTR ptr )
{
- if (ptr != current_envdb.env)
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return FALSE;
- }
- return TRUE;
+ return HeapFree( GetProcessHeap(), 0, ptr );
}
@@ -529,7 +216,7 @@
*/
BOOL WINAPI FreeEnvironmentStringsW( LPWSTR ptr )
{
- return HeapFree( GetProcessHeap(), 0, ptr );
+ return TRUE;
}
@@ -538,30 +225,36 @@
*/
DWORD WINAPI GetEnvironmentVariableA( LPCSTR name, LPSTR value, DWORD size )
{
- LPCSTR p;
- INT ret = 0;
+ UNICODE_STRING us_name;
+ PWSTR valueW;
+ DWORD ret;
if (!name || !*name)
{
- SetLastError( ERROR_ENVVAR_NOT_FOUND );
+ SetLastError(ERROR_ENVVAR_NOT_FOUND);
return 0;
}
- RtlAcquirePebLock();
- if ((p = ENV_FindVariable( current_envdb.env, name, strlen(name) )))
- {
- ret = strlen(p);
- if (size <= ret)
- {
- /* If not enough room, include the terminating null
- * in the returned size */
- ret++;
- }
- else if (value) strcpy( value, p );
- }
- RtlReleasePebLock();
- if (!ret)
- SetLastError( ERROR_ENVVAR_NOT_FOUND );
+ if (!(valueW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR))))
+ return 0;
+
+ RtlCreateUnicodeStringFromAsciiz( &us_name, name );
+ SetLastError(0);
+ ret = GetEnvironmentVariableW( us_name.Buffer, valueW, size);
+ if (ret && ret < size)
+ {
+ WideCharToMultiByte( CP_ACP, 0, valueW, ret + 1, value, size, NULL, NULL );
+ }
+ /* this is needed to tell, with 0 as a return value, the difference between:
+ * - an error (GetLastError() != 0)
+ * - returning an empty string (in this case, we need to update the buffer)
+ */
+ if (ret == 0 && size && GetLastError() == 0)
+ value[0] = '\0';
+
+ RtlFreeUnicodeString( &us_name );
+ HeapFree(GetProcessHeap(), 0, valueW);
+
return ret;
}
@@ -569,28 +262,36 @@
/***********************************************************************
* GetEnvironmentVariableW (KERNEL32.@)
*/
-DWORD WINAPI GetEnvironmentVariableW( LPCWSTR nameW, LPWSTR valW, DWORD size)
+DWORD WINAPI GetEnvironmentVariableW( LPCWSTR name, LPWSTR val, DWORD size )
{
- LPSTR name, val;
- DWORD ret;
+ UNICODE_STRING us_name;
+ UNICODE_STRING us_value;
+ NTSTATUS status;
+ unsigned len;
+
+ TRACE("(%s %p %lu)\n", debugstr_w(name), val, size);
- if (!nameW || !*nameW)
+ if (!name || !*name)
{
- SetLastError( ERROR_ENVVAR_NOT_FOUND );
+ SetLastError(ERROR_ENVVAR_NOT_FOUND);
return 0;
}
- name = HEAP_strdupWtoA( GetProcessHeap(), 0, nameW );
- val = valW ? HeapAlloc( GetProcessHeap(), 0, size ) : NULL;
- ret = GetEnvironmentVariableA( name, val, size );
- if (ret && val)
+ RtlInitUnicodeString(&us_name, name);
+ us_value.Length = 0;
+ us_value.MaximumLength = (size ? size - 1 : 0) * sizeof(WCHAR);
+ us_value.Buffer = val;
+
+ status = RtlQueryEnvironmentVariable_U(NULL, &us_name, &us_value);
+ len = us_value.Length / sizeof(WCHAR);
+ if (status != STATUS_SUCCESS)
{
- if (size && !MultiByteToWideChar( CP_ACP, 0, val, -1, valW, size ))
- valW[size-1] = 0;
+ SetLastError( RtlNtStatusToDosError(status) );
+ return (status == STATUS_BUFFER_TOO_SMALL) ? len + 1 : 0;
}
- HeapFree( GetProcessHeap(), 0, name );
- if (val) HeapFree( GetProcessHeap(), 0, val );
- return ret;
+ if (size) val[len] = '\0';
+
+ return us_value.Length / sizeof(WCHAR);
}
@@ -599,59 +300,28 @@
*/
BOOL WINAPI SetEnvironmentVariableA( LPCSTR name, LPCSTR value )
{
- INT old_size, len, res;
- LPSTR p, env, new_env;
- BOOL ret = FALSE;
+ UNICODE_STRING us_name;
+ BOOL ret;
- if (!name || !*name)
+ if (!name)
{
- SetLastError( ERROR_INVALID_PARAMETER );
- return FALSE;
+ SetLastError(ERROR_ENVVAR_NOT_FOUND);
+ return 0;
}
- RtlAcquirePebLock();
- env = p = current_envdb.env;
-
- /* Find a place to insert the string */
-
- res = -1;
- len = strlen(name);
- while (*p)
+ RtlCreateUnicodeStringFromAsciiz( &us_name, name );
+ if (value)
{
- if (!strncasecmp( name, p, len ) && (p[len] == '=')) break;
- p += strlen(p) + 1;
- }
- if (!value && !*p) goto done; /* Value to remove doesn't exist */
-
- /* Realloc the buffer */
+ UNICODE_STRING us_value;
- len = value ? strlen(name) + strlen(value) + 2 : 0;
- if (*p) len -= strlen(p) + 1; /* The name already exists */
- old_size = HeapSize( GetProcessHeap(), 0, env );
- if (len < 0)
- {
- LPSTR next = p + strlen(p) + 1; /* We know there is a next one */
- memmove( next + len, next, old_size - (next - env) );
+ RtlCreateUnicodeStringFromAsciiz( &us_value, value );
+ ret = SetEnvironmentVariableW( us_name.Buffer, us_value.Buffer );
+ RtlFreeUnicodeString( &us_value );
}
- if (!(new_env = HeapReAlloc( GetProcessHeap(), 0, env, old_size + len )))
- goto done;
- if (env_sel) env_sel = SELECTOR_ReallocBlock( env_sel, new_env, old_size + len );
- p = new_env + (p - env);
- if (len > 0) memmove( p + len, p, old_size - (p - new_env) );
-
- /* Set the new string */
+ else ret = SetEnvironmentVariableW( us_name.Buffer, NULL );
- if (value)
- {
- strcpy( p, name );
- strcat( p, "=" );
- strcat( p, value );
- }
- current_envdb.env = new_env;
- ret = TRUE;
+ RtlFreeUnicodeString( &us_name );
-done:
- RtlReleasePebLock();
return ret;
}
@@ -661,12 +331,36 @@
*/
BOOL WINAPI SetEnvironmentVariableW( LPCWSTR name, LPCWSTR value )
{
- LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
- LPSTR valueA = HEAP_strdupWtoA( GetProcessHeap(), 0, value );
- BOOL ret = SetEnvironmentVariableA( nameA, valueA );
- HeapFree( GetProcessHeap(), 0, nameA );
- HeapFree( GetProcessHeap(), 0, valueA );
- return ret;
+ UNICODE_STRING us_name;
+ NTSTATUS status;
+
+ TRACE("(%s %s)\n", debugstr_w(name), debugstr_w(value));
+
+ if (!name)
+ {
+ SetLastError(ERROR_ENVVAR_NOT_FOUND);
+ return 0;
+ }
+
+ RtlInitUnicodeString(&us_name, name);
+ if (value)
+ {
+ UNICODE_STRING us_value;
+
+ RtlInitUnicodeString(&us_value, value);
+ status = RtlSetEnvironmentVariable(NULL, &us_name, &us_value);
+ }
+ else status = RtlSetEnvironmentVariable(NULL, &us_name, NULL);
+
+ if (status != STATUS_SUCCESS)
+ {
+ SetLastError( RtlNtStatusToDosError(status) );
+ return FALSE;
+ }
+
+ /* FIXME: see comments in generate_env_block16 */
+ if (env_sel) generate_env_block16();
+ return TRUE;
}
@@ -677,63 +371,25 @@
*/
DWORD WINAPI ExpandEnvironmentStringsA( LPCSTR src, LPSTR dst, DWORD count )
{
- DWORD len, total_size = 1; /* 1 for terminating '\0' */
- LPCSTR p, var;
-
- if (!count) dst = NULL;
- RtlAcquirePebLock();
+ UNICODE_STRING us_src;
+ PWSTR dstW = NULL;
+ DWORD ret;
+
+ RtlCreateUnicodeStringFromAsciiz( &us_src, src );
+ if (count)
+ {
+ if (!(dstW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
+ return 0;
+ ret = ExpandEnvironmentStringsW( us_src.Buffer, dstW, count);
+ if (ret)
+ WideCharToMultiByte( CP_ACP, 0, dstW, ret, dst, count, NULL, NULL );
+ }
+ else ret = ExpandEnvironmentStringsW( us_src.Buffer, NULL, 0);
+
+ RtlFreeUnicodeString( &us_src );
+ if (dstW) HeapFree(GetProcessHeap(), 0, dstW);
- while (*src)
- {
- if (*src != '%')
- {
- if ((p = strchr( src, '%' ))) len = p - src;
- else len = strlen(src);
- var = src;
- src += len;
- }
- else /* we are at the start of a variable */
- {
- if ((p = strchr( src + 1, '%' )))
- {
- len = p - src - 1; /* Length of the variable name */
- if ((var = ENV_FindVariable( current_envdb.env, src + 1, len )))
- {
- src += len + 2; /* Skip the variable name */
- len = strlen(var);
- }
- else
- {
- var = src; /* Copy original name instead */
- len += 2;
- src += len;
- }
- }
- else /* unfinished variable name, ignore it */
- {
- var = src;
- len = strlen(src); /* Copy whole string */
- src += len;
- }
- }
- total_size += len;
- if (dst)
- {
- if (count < len) len = count;
- memcpy( dst, var, len );
- dst += len;
- count -= len;
- }
- }
- RtlReleasePebLock();
-
- /* Null-terminate the string */
- if (dst)
- {
- if (!count) dst--;
- *dst = '\0';
- }
- return total_size;
+ return ret;
}
@@ -742,16 +398,29 @@
*/
DWORD WINAPI ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR dst, DWORD len )
{
- LPSTR srcA = HEAP_strdupWtoA( GetProcessHeap(), 0, src );
- LPSTR dstA = dst ? HeapAlloc( GetProcessHeap(), 0, len ) : NULL;
- DWORD ret = ExpandEnvironmentStringsA( srcA, dstA, len );
- if (dstA)
+ UNICODE_STRING us_src;
+ UNICODE_STRING us_dst;
+ NTSTATUS status;
+ DWORD res;
+
+ TRACE("(%s %p %lu)\n", debugstr_w(src), dst, len);
+
+ RtlInitUnicodeString(&us_src, src);
+ us_dst.Length = 0;
+ us_dst.MaximumLength = len * sizeof(WCHAR);
+ us_dst.Buffer = dst;
+
+ res = 0;
+ status = RtlExpandEnvironmentStrings_U(NULL, &us_src, &us_dst, &res);
+ res /= sizeof(WCHAR);
+ if (status != STATUS_SUCCESS)
{
- ret = MultiByteToWideChar( CP_ACP, 0, dstA, -1, dst, len );
- HeapFree( GetProcessHeap(), 0, dstA );
+ SetLastError( RtlNtStatusToDosError(status) );
+ if (status != STATUS_BUFFER_TOO_SMALL) return 0;
+ if (len && dst) dst[len - 1] = '\0';
}
- HeapFree( GetProcessHeap(), 0, srcA );
- return ret;
+
+ return res;
}
@@ -760,7 +429,7 @@
*/
SEGPTR WINAPI GetDOSEnvironment16(void)
{
- return MAKESEGPTR( env_sel, 0 );
+ return generate_env_block16();
}
@@ -769,11 +438,11 @@
*/
HANDLE WINAPI GetStdHandle( DWORD std_handle )
{
- switch(std_handle)
+ switch (std_handle)
{
- case STD_INPUT_HANDLE: return current_envdb.hStdin;
- case STD_OUTPUT_HANDLE: return current_envdb.hStdout;
- case STD_ERROR_HANDLE: return current_envdb.hStderr;
+ case STD_INPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdInput;
+ case STD_OUTPUT_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdOutput;
+ case STD_ERROR_HANDLE: return NtCurrentTeb()->Peb->ProcessParameters->hStdError;
}
SetLastError( ERROR_INVALID_PARAMETER );
return INVALID_HANDLE_VALUE;
@@ -785,23 +454,23 @@
*/
BOOL WINAPI SetStdHandle( DWORD std_handle, HANDLE handle )
{
- switch(std_handle)
+ switch (std_handle)
{
- case STD_INPUT_HANDLE: current_envdb.hStdin = handle; return TRUE;
- case STD_OUTPUT_HANDLE: current_envdb.hStdout = handle; return TRUE;
- case STD_ERROR_HANDLE: current_envdb.hStderr = handle; return TRUE;
+ case STD_INPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdInput = handle; return TRUE;
+ case STD_OUTPUT_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdOutput = handle; return TRUE;
+ case STD_ERROR_HANDLE: NtCurrentTeb()->Peb->ProcessParameters->hStdError = handle; return TRUE;
}
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
-
/***********************************************************************
* GetStartupInfoA (KERNEL32.@)
*/
VOID WINAPI GetStartupInfoA( LPSTARTUPINFOA info )
{
- *info = current_startupinfo;
+ assert(startup_infoA.cb);
+ memcpy(info, &startup_infoA, sizeof(startup_infoA));
}
@@ -810,25 +479,65 @@
*/
VOID WINAPI GetStartupInfoW( LPSTARTUPINFOW info )
{
- UNICODE_STRING usBuffer;
- info->cb = sizeof(STARTUPINFOW);
- info->dwX = current_startupinfo.dwX;
- info->dwY = current_startupinfo.dwY;
- info->dwXSize = current_startupinfo.dwXSize;
- info->dwXCountChars = current_startupinfo.dwXCountChars;
- info->dwYCountChars = current_startupinfo.dwYCountChars;
- info->dwFillAttribute = current_startupinfo.dwFillAttribute;
- info->dwFlags = current_startupinfo.dwFlags;
- info->wShowWindow = current_startupinfo.wShowWindow;
- info->cbReserved2 = current_startupinfo.cbReserved2;
- info->lpReserved2 = current_startupinfo.lpReserved2;
- info->hStdInput = current_startupinfo.hStdInput;
- info->hStdOutput = current_startupinfo.hStdOutput;
- info->hStdError = current_startupinfo.hStdError;
- RtlCreateUnicodeStringFromAsciiz (&usBuffer,current_startupinfo.lpReserved);
- info->lpReserved = usBuffer.Buffer;
- RtlCreateUnicodeStringFromAsciiz (&usBuffer,current_startupinfo.lpDesktop);
- info->lpDesktop = usBuffer.Buffer;
- RtlCreateUnicodeStringFromAsciiz (&usBuffer,current_startupinfo.lpTitle);
- info->lpTitle = usBuffer.Buffer;
+ assert(startup_infoW.cb);
+ memcpy(info, &startup_infoW, sizeof(startup_infoW));
+}
+
+/******************************************************************
+ * ENV_CopyStartupInformation (internal)
+ *
+ * Creates the STARTUPINFO information from the ntdll information
+ */
+void ENV_CopyStartupInformation(void)
+{
+ RTL_USER_PROCESS_PARAMETERS* rupp;
+ ANSI_STRING ansi;
+
+ RtlAcquirePebLock();
+
+ rupp = NtCurrentTeb()->Peb->ProcessParameters;
+
+ startup_infoW.cb = sizeof(startup_infoW);
+ startup_infoW.lpReserved = NULL;
+ startup_infoW.lpDesktop = rupp->Desktop.Buffer;
+ startup_infoW.lpTitle = rupp->WindowTitle.Buffer;
+ startup_infoW.dwX = rupp->dwX;
+ startup_infoW.dwY = rupp->dwY;
+ startup_infoW.dwXSize = rupp->dwXSize;
+ startup_infoW.dwYSize = rupp->dwYSize;
+ startup_infoW.dwXCountChars = rupp->dwXCountChars;
+ startup_infoW.dwYCountChars = rupp->dwYCountChars;
+ startup_infoW.dwFillAttribute = rupp->dwFillAttribute;
+ startup_infoW.dwFlags = rupp->dwFlags;
+ startup_infoW.wShowWindow = rupp->wShowWindow;
+ startup_infoW.cbReserved2 = 0;
+ startup_infoW.lpReserved2 = NULL;
+ startup_infoW.hStdInput = rupp->hStdInput;
+ startup_infoW.hStdOutput = rupp->hStdOutput;
+ startup_infoW.hStdError = rupp->hStdError;
+
+ startup_infoA.cb = sizeof(startup_infoW);
+ startup_infoA.lpReserved = NULL;
+ startup_infoA.lpDesktop = (rupp->Desktop.Length &&
+ RtlUnicodeStringToAnsiString( &ansi, &rupp->Desktop, TRUE) == STATUS_SUCCESS) ?
+ ansi.Buffer : NULL;
+ startup_infoA.lpTitle = (rupp->WindowTitle.Length &&
+ RtlUnicodeStringToAnsiString( &ansi, &rupp->WindowTitle, TRUE) == STATUS_SUCCESS) ?
+ ansi.Buffer : NULL;
+ startup_infoA.dwX = rupp->dwX;
+ startup_infoA.dwY = rupp->dwY;
+ startup_infoA.dwXSize = rupp->dwXSize;
+ startup_infoA.dwYSize = rupp->dwYSize;
+ startup_infoA.dwXCountChars = rupp->dwXCountChars;
+ startup_infoA.dwYCountChars = rupp->dwYCountChars;
+ startup_infoA.dwFillAttribute = rupp->dwFillAttribute;
+ startup_infoA.dwFlags = rupp->dwFlags;
+ startup_infoA.wShowWindow = rupp->wShowWindow;
+ startup_infoA.cbReserved2 = 0;
+ startup_infoA.lpReserved2 = NULL;
+ startup_infoA.hStdInput = rupp->hStdInput;
+ startup_infoA.hStdOutput = rupp->hStdOutput;
+ startup_infoA.hStdError = rupp->hStdError;
+
+ RtlReleasePebLock();
}
Index: scheduler25/process.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/scheduler/process.c,v
retrieving revision 1.219
diff -u -r1.219 process.c
--- scheduler25/process.c 20 May 2003 19:21:43 -0000 1.219
+++ scheduler25/process.c 22 May 2003 12:28:36 -0000
@@ -47,7 +47,6 @@
#include "wine/server.h"
#include "options.h"
#include "wine/debug.h"
-#include "ntdll_misc.h"
WINE_DEFAULT_DEBUG_CHANNEL(process);
WINE_DECLARE_DEBUG_CHANNEL(server);
@@ -55,8 +54,6 @@
WINE_DECLARE_DEBUG_CHANNEL(snoop);
WINE_DECLARE_DEBUG_CHANNEL(win32);
-struct _ENVDB;
-
/* Win32 process database */
typedef struct _PDB
{
@@ -109,7 +106,7 @@
PDB current_process;
-RTL_USER_PROCESS_PARAMETERS process_pmts;
+static RTL_USER_PROCESS_PARAMETERS process_pmts;
/* Process flags */
#define PDB32_DEBUGGED 0x0001 /* Process is being debugged */
@@ -126,15 +123,13 @@
int main_create_flags = 0;
-/* memory/environ.c */
-extern struct _ENVDB *ENV_InitStartupInfo( size_t info_size, char *main_exe_name,
- size_t main_exe_size );
-extern BOOL ENV_BuildCommandLine( char **argv );
-extern STARTUPINFOA current_startupinfo;
-
/* scheduler/pthread.c */
extern void PTHREAD_init_done(void);
+/* dlls/ntdll/env.c */
+extern BOOL init_user_process_pmts( size_t, char*, size_t );
+extern BOOL build_command_line( char **argv );
+
extern void RELAY_InitDebugLists(void);
extern void SHELL_LoadRegistry(void);
extern void VERSION_Init( const char *appname );
@@ -302,12 +297,12 @@
argv0 = argv[0];
/* Fill the initial process structure */
- current_process.exit_code = STILL_ACTIVE;
current_process.threads = 1;
current_process.running_threads = 1;
current_process.ring0_threads = 1;
current_process.group = ¤t_process;
current_process.priority = 8; /* Normal */
+ current_process.exit_code = (DWORD)&process_pmts; /* FIXME */
/* Setup the server connection */
CLIENT_InitServer();
@@ -322,9 +317,9 @@
main_create_flags = reply->create_flags;
info_size = reply->info_size;
server_startticks = reply->server_start;
- current_startupinfo.hStdInput = reply->hstdin;
- current_startupinfo.hStdOutput = reply->hstdout;
- current_startupinfo.hStdError = reply->hstderr;
+ process_pmts.hStdInput = reply->hstdin;
+ process_pmts.hStdOutput = reply->hstdout;
+ process_pmts.hStdError = reply->hstderr;
}
}
SERVER_END_REQ;
@@ -334,44 +329,33 @@
current_process.heap = HeapCreate( HEAP_GROWABLE, 0, 0 );
if (main_create_flags == 0 &&
- current_startupinfo.hStdInput == 0 &&
- current_startupinfo.hStdOutput == 0 &&
- current_startupinfo.hStdError == 0)
+ process_pmts.hStdInput == 0 &&
+ process_pmts.hStdOutput == 0 &&
+ process_pmts.hStdError == 0)
{
- /* no parent, and no new console requested, create a simple console with bare handles to
+ /* This is wine specific:
+ * no parent, and no new console requested, create a simple console with bare handles to
* unix stdio input & output streams (aka simple console)
- */
- HANDLE handle;
- wine_server_fd_to_handle( 0, GENERIC_READ|SYNCHRONIZE, TRUE, &handle );
- SetStdHandle( STD_INPUT_HANDLE, handle );
- wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, TRUE, &handle );
- SetStdHandle( STD_OUTPUT_HANDLE, handle );
- wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, TRUE, &handle );
- SetStdHandle( STD_ERROR_HANDLE, handle );
- }
- else if (!(main_create_flags & (DETACHED_PROCESS|CREATE_NEW_CONSOLE)))
- {
- SetStdHandle( STD_INPUT_HANDLE, current_startupinfo.hStdInput );
- SetStdHandle( STD_OUTPUT_HANDLE, current_startupinfo.hStdOutput );
- SetStdHandle( STD_ERROR_HANDLE, current_startupinfo.hStdError );
+ */
+ wine_server_fd_to_handle( 0, GENERIC_READ|SYNCHRONIZE, TRUE, &process_pmts.hStdInput );
+ wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, TRUE, &process_pmts.hStdOutput );
+ wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, TRUE, &process_pmts.hStdError );
}
/* Now we can use the pthreads routines */
PTHREAD_init_done();
/* Copy the parent environment */
- if (!(current_process.env_db = ENV_InitStartupInfo( info_size, main_exe_name,
- sizeof(main_exe_name) )))
+ if (!init_user_process_pmts( info_size, main_exe_name, sizeof(main_exe_name) ))
return FALSE;
/* Parse command line arguments */
OPTIONS_ParseOptions( !info_size ? argv : NULL );
/* <hack: to be changed later on> */
- build_initial_environment();
process_pmts.CurrentDirectoryName.Length = 3 * sizeof(WCHAR);
process_pmts.CurrentDirectoryName.MaximumLength = RtlGetLongestNtPathLength() * sizeof(WCHAR);
- process_pmts.CurrentDirectoryName.Buffer = RtlAllocateHeap( ntdll_get_process_heap(), 0, process_pmts.CurrentDirectoryName.MaximumLength);
+ process_pmts.CurrentDirectoryName.Buffer = RtlAllocateHeap( NtCurrentTeb()->Peb->ProcessHeap, 0, process_pmts.CurrentDirectoryName.MaximumLength);
process_pmts.CurrentDirectoryName.Buffer[0] = 'C';
process_pmts.CurrentDirectoryName.Buffer[1] = ':';
process_pmts.CurrentDirectoryName.Buffer[2] = '\\';
@@ -579,7 +563,7 @@
found:
/* build command line */
- if (!ENV_BuildCommandLine( argv )) goto error;
+ if (!build_command_line( argv )) goto error;
/* create 32-bit module for main exe */
if (!(current_process.module = BUILTIN32_LoadExeModule( current_process.module ))) goto error;
@@ -861,7 +845,7 @@
int execfd[2];
pid_t pid;
int err;
- char dummy;
+ char dummy = 0;
if (!env)
{
@@ -1404,7 +1388,8 @@
*/
DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
{
- DWORD x, y;
+ DWORD x, y;
+ STARTUPINFOW siw;
TRACE_(win32)("(%ld, %d)\n", dwProcessID, offset );
@@ -1435,30 +1420,36 @@
return (DWORD)¤t_process;
case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */
- return (DWORD)current_startupinfo.hStdOutput;
+ GetStartupInfoW(&siw);
+ return (DWORD)siw.hStdOutput;
case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */
- return (DWORD)current_startupinfo.hStdInput;
+ GetStartupInfoW(&siw);
+ return (DWORD)siw.hStdInput;
case GPD_STARTF_SHOWWINDOW:
- return current_startupinfo.wShowWindow;
+ GetStartupInfoW(&siw);
+ return siw.wShowWindow;
case GPD_STARTF_SIZE:
- x = current_startupinfo.dwXSize;
+ GetStartupInfoW(&siw);
+ x = siw.dwXSize;
if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
- y = current_startupinfo.dwYSize;
+ y = siw.dwYSize;
if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
return MAKELONG( x, y );
case GPD_STARTF_POSITION:
- x = current_startupinfo.dwX;
+ GetStartupInfoW(&siw);
+ x = siw.dwX;
if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
- y = current_startupinfo.dwY;
+ y = siw.dwY;
if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
return MAKELONG( x, y );
case GPD_STARTF_FLAGS:
- return current_startupinfo.dwFlags;
+ GetStartupInfoW(&siw);
+ return process_pmts.dwFlags;
case GPD_PARENT:
return 0;
More information about the wine-patches
mailing list