From aef9a36059790c5e7665e479680dbff310cab065 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 3 Oct 2000 04:19:16 +0000 Subject: [PATCH] Use special environment variables to transmit the cwd of the various drives to child processes (based on a patch by Andreas Mohr). --- files/drive.c | 38 ++++++++++++++++++++++++++++++++++++++ include/drive.h | 1 + scheduler/process.c | 27 ++++++++++++++++++++------- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/files/drive.c b/files/drive.c index 058c6ae8c16..f11f11923a9 100644 --- a/files/drive.c +++ b/files/drive.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -146,6 +147,7 @@ int DRIVE_Init(void) { int i, len, count = 0; char name[] = "Drive A"; + char drive_env[] = "=A:"; char path[MAX_PATHNAME_LEN]; char buffer[80]; struct stat drive_stat_buffer; @@ -257,6 +259,14 @@ int DRIVE_Init(void) } } + /* get current working directory info for all drives */ + for (i = 0; i < MAX_DOS_DRIVES; i++, drive_env[1]++) + { + if (!GetEnvironmentVariableA(drive_env, path, sizeof(path))) continue; + /* sanity check */ + if (toupper(path[0]) != drive_env[1] || path[1] != ':') continue; + DRIVE_Chdir( i, path + 2 ); + } return 1; } @@ -920,6 +930,34 @@ static UINT DRIVE_GetCurrentDirectory( UINT buflen, LPSTR buf ) return ret; } + +/*********************************************************************** + * DRIVE_BuildEnv + * + * Build the environment array containing the drives current directories. + * Resulting pointer must be freed with HeapFree. + */ +char *DRIVE_BuildEnv(void) +{ + int i, length = 0; + const char *cwd[MAX_DOS_DRIVES]; + char *env, *p; + + for (i = 0; i < MAX_DOS_DRIVES; i++) + { + if ((cwd[i] = DRIVE_GetDosCwd(i)) && cwd[i][0]) length += strlen(cwd[i]) + 8; + } + if (!(env = HeapAlloc( GetProcessHeap(), 0, length+1 ))) return NULL; + for (i = 0, p = env; i < MAX_DOS_DRIVES; i++) + { + if (cwd[i] && cwd[i][0]) + p += sprintf( p, "=%c:=%c:\\%s", 'A'+i, 'A'+i, cwd[i] ) + 1; + } + *p = 0; + return env; +} + + /*********************************************************************** * GetDiskFreeSpace16 (KERNEL.422) */ diff --git a/include/drive.h b/include/drive.h index 631fdd6474f..a26d63958f7 100644 --- a/include/drive.h +++ b/include/drive.h @@ -50,5 +50,6 @@ extern int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive ); extern int DRIVE_OpenDevice( int drive, int flags ); extern int DRIVE_RawRead(BYTE drive, DWORD begin, DWORD length, BYTE *dataptr, BOOL fake_success ); extern int DRIVE_RawWrite(BYTE drive, DWORD begin, DWORD length, BYTE *dataptr, BOOL fake_success ); +extern char *DRIVE_BuildEnv(void); #endif /* __WINE_DRIVE_H */ diff --git a/scheduler/process.c b/scheduler/process.c index 1ce4e7d4cca..a96a2a35bad 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -15,6 +15,7 @@ #include "wine/winbase16.h" #include "wine/exception.h" #include "process.h" +#include "drive.h" #include "main.h" #include "module.h" #include "neexe.h" @@ -577,20 +578,24 @@ static char **build_argv( char *cmdline, int reserved ) * * Build the environment of a new child process. */ -static char **build_envp( const char *env ) +static char **build_envp( const char *env, const char *extra_env ) { const char *p; char **envp; - int count; + int count = 0; - for (p = env, count = 0; *p; count++) p += strlen(p) + 1; + if (extra_env) for (p = extra_env; *p; count++) p += strlen(p) + 1; + for (p = env; *p; count++) p += strlen(p) + 1; count += 3; + if ((envp = malloc( count * sizeof(*envp) ))) { extern char **environ; char **envptr = envp; char **unixptr = environ; - /* first put PATH, HOME and WINEPREFIX from the unix env */ + /* first the extra strings */ + if (extra_env) for (p = extra_env; *p; p += strlen(p) + 1) *envptr++ = (char *)p; + /* then put PATH, HOME and WINEPREFIX from the unix env */ for (unixptr = environ; unixptr && *unixptr; unixptr++) if (!memcmp( *unixptr, "PATH=", 5 ) || !memcmp( *unixptr, "HOME=", 5 ) || @@ -665,6 +670,13 @@ static int fork_and_exec( const char *filename, char *cmdline, { int fd[2]; int pid, err; + char *extra_env = NULL; + + if (!env) + { + env = GetEnvironmentStringsA(); + extra_env = DRIVE_BuildEnv(); + } if (pipe(fd) == -1) { @@ -675,10 +687,10 @@ static int fork_and_exec( const char *filename, char *cmdline, if (!(pid = fork())) /* child */ { char **argv = build_argv( cmdline, filename ? 0 : 2 ); - char **envp = build_envp( env ); + char **envp = build_envp( env, extra_env ); close( fd[0] ); - if (newdir) chdir(newdir); + if (newdir) chdir(newdir); if (argv && envp) { @@ -701,6 +713,7 @@ static int fork_and_exec( const char *filename, char *cmdline, } if (pid == -1) FILE_SetDosError(); close( fd[0] ); + if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env ); return pid; } @@ -784,7 +797,7 @@ BOOL PROCESS_Create( HFILE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env, /* fork and execute */ - pid = fork_and_exec( unixfilename, cmd_line, env ? env : GetEnvironmentStringsA(), unixdir ); + pid = fork_and_exec( unixfilename, cmd_line, env, unixdir ); SERVER_START_REQ {