From 06c46d9aab93b9510d22e6c4df995c68d8af0ca7 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 28 Apr 2004 01:04:24 +0000 Subject: [PATCH] Reimplemented Get/SetCurrentDirectoryW using the corresponding ntdll functions. --- dlls/kernel/file16.c | 22 +++++- dlls/kernel/path.c | 81 +++++++++++++++++++++ dlls/kernel/process.c | 35 ++------- files/drive.c | 196 -------------------------------------------------- include/file.h | 1 - 5 files changed, 107 insertions(+), 228 deletions(-) diff --git a/dlls/kernel/file16.c b/dlls/kernel/file16.c index d757e1f4615..9da451722e1 100644 --- a/dlls/kernel/file16.c +++ b/dlls/kernel/file16.c @@ -576,6 +576,15 @@ BOOL16 WINAPI GetPrivateProfileStruct16(LPCSTR section, LPCSTR key, /*********************************************************************** + * GetCurrentDirectory (KERNEL.411) + */ +UINT16 WINAPI GetCurrentDirectory16( UINT16 buflen, LPSTR buf ) +{ + return GetCurrentDirectoryA( buflen, buf ); +} + + +/*********************************************************************** * SetCurrentDirectory (KERNEL.412) */ BOOL16 WINAPI SetCurrentDirectory16( LPCSTR dir ) @@ -584,13 +593,24 @@ BOOL16 WINAPI SetCurrentDirectory16( LPCSTR dir ) if (!GetFullPathNameA( dir, MAX_PATH, fulldir, NULL )) return FALSE; + if (!SetCurrentDirectoryA( dir )) return FALSE; + if (fulldir[0] && fulldir[1] == ':') { + TDB *pTask = GlobalLock16( GetCurrentTask() ); char env_var[4] = "=A:"; + env_var[1] = fulldir[0]; SetEnvironmentVariableA( env_var, fulldir ); + + /* update the directory in the TDB */ + if (pTask) + { + pTask->curdrive = 0x80 | (fulldir[0] - 'A'); + GetShortPathNameA( fulldir + 2, pTask->curdir, sizeof(pTask->curdir) ); + } } - return SetCurrentDirectoryA( dir ); + return TRUE; } diff --git a/dlls/kernel/path.c b/dlls/kernel/path.c index 6d5a31d0a02..c00d59a1f88 100644 --- a/dlls/kernel/path.c +++ b/dlls/kernel/path.c @@ -1193,6 +1193,87 @@ BOOL WINAPI RemoveDirectoryA( LPCSTR path ) /*********************************************************************** + * GetCurrentDirectoryW (KERNEL32.@) + */ +UINT WINAPI GetCurrentDirectoryW( UINT buflen, LPWSTR buf ) +{ + return RtlGetCurrentDirectory_U( buflen * sizeof(WCHAR), buf ) / sizeof(WCHAR); +} + + +/*********************************************************************** + * GetCurrentDirectoryA (KERNEL32.@) + */ +UINT WINAPI GetCurrentDirectoryA( UINT buflen, LPSTR buf ) +{ + WCHAR bufferW[MAX_PATH]; + DWORD ret, retW; + + retW = GetCurrentDirectoryW(MAX_PATH, bufferW); + + if (!retW) + ret = 0; + else if (retW > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + ret = 0; + } + else + { + ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL); + if (buflen >= ret) + { + WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buf, buflen, NULL, NULL); + ret--; /* length without 0 */ + } + } + return ret; +} + + +/*********************************************************************** + * SetCurrentDirectoryW (KERNEL32.@) + */ +BOOL WINAPI SetCurrentDirectoryW( LPCWSTR dir ) +{ + UNICODE_STRING dirW; + NTSTATUS status; + + RtlInitUnicodeString( &dirW, dir ); + status = RtlSetCurrentDirectory_U( &dirW ); + if (status != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + return TRUE; +} + + +/*********************************************************************** + * SetCurrentDirectoryA (KERNEL32.@) + */ +BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir ) +{ + UNICODE_STRING dirW; + NTSTATUS status; + + if (!RtlCreateUnicodeStringFromAsciiz( &dirW, dir )) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + status = RtlSetCurrentDirectory_U( &dirW ); + if (status != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + return TRUE; +} + + +/*********************************************************************** * wine_get_unix_file_name (KERNEL32.@) Not a Windows API * * Return the full Unix file name for a given path. diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index 61bc0f1dda3..8ca5d1a3ac7 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -1060,23 +1060,13 @@ static char *alloc_env_string( const char *name, const char *value ) * * Build the environment of a new child process. */ -static char **build_envp( const WCHAR *envW, const WCHAR *extra_envW ) +static char **build_envp( const WCHAR *envW ) { const WCHAR *p; char **envp; - char *env, *extra_env = NULL; + char *env; int count = 0, length; - if (extra_envW) - { - for (p = extra_envW; *p; count++) p += strlenW(p) + 1; - p++; - length = WideCharToMultiByte( CP_UNIXCP, 0, extra_envW, p - extra_envW, - NULL, 0, NULL, NULL ); - if ((extra_env = malloc( length ))) - WideCharToMultiByte( CP_UNIXCP, 0, extra_envW, p - extra_envW, - extra_env, length, NULL, NULL ); - } for (p = envW; *p; count++) p += strlenW(p) + 1; p++; length = WideCharToMultiByte( CP_UNIXCP, 0, envW, p - envW, NULL, 0, NULL, NULL ); @@ -1090,8 +1080,6 @@ static char **build_envp( const WCHAR *envW, const WCHAR *extra_envW ) char **envptr = envp; char *p; - /* first the extra strings */ - if (extra_env) for (p = extra_env; *p; p += strlen(p) + 1) *envptr++ = p; /* then put PATH, TEMP, TMP, HOME and WINEPREFIX from the unix env */ if ((p = getenv("PATH"))) *envptr++ = alloc_env_string( "PATH=", p ); if ((p = getenv("TEMP"))) *envptr++ = alloc_env_string( "TEMP=", p ); @@ -1101,8 +1089,6 @@ static char **build_envp( const WCHAR *envW, const WCHAR *extra_envW ) /* now put the Windows environment strings */ for (p = env; *p; p += strlen(p) + 1) { - if (extra_env && p[0]=='=' && 'A'<=p[1] && p[1]<='Z' && p[2]==':' && p[3]=='=') - continue; /* skipped */ if (is_special_env_var( p )) /* prefix it with "WINE" */ *envptr++ = alloc_env_string( "WINE", p ); else if (strncmp( p, "HOME=", 5 ) && @@ -1136,7 +1122,7 @@ static int fork_and_exec( const char *filename, const WCHAR *cmdline, if (!(pid = fork())) /* child */ { char **argv = build_argv( cmdline, 0 ); - char **envp = build_envp( env, NULL ); + char **envp = build_envp( env ); close( fd[0] ); /* Reset signals that we previously set to SIG_IGN */ @@ -1224,24 +1210,16 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW BOOL ret, success = FALSE; HANDLE process_info; RTL_USER_PROCESS_PARAMETERS *params; - WCHAR *extra_env = NULL; int startfd[2]; int execfd[2]; pid_t pid; int err; char dummy = 0; - if (!env) - { - env = GetEnvironmentStringsW(); - extra_env = DRIVE_BuildEnv(); - } + if (!env) env = GetEnvironmentStringsW(); if (!(params = create_user_params( filename, cmd_line, startup ))) - { - if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env ); return FALSE; - } /* create the synchronization pipes */ @@ -1249,7 +1227,6 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW { SetLastError( ERROR_TOO_MANY_OPEN_FILES ); RtlDestroyProcessParameters( params ); - if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env ); return FALSE; } if (pipe( execfd ) == -1) @@ -1258,7 +1235,6 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW close( startfd[0] ); close( startfd[1] ); RtlDestroyProcessParameters( params ); - if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env ); return FALSE; } fcntl( execfd[1], F_SETFD, 1 ); /* set close on exec */ @@ -1268,7 +1244,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW if (!(pid = fork())) /* child */ { char **argv = build_argv( cmd_line, 1 ); - char **envp = build_envp( env, extra_env ); + char **envp = build_envp( env ); close( startfd[1] ); close( execfd[0] ); @@ -1300,7 +1276,6 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW close( startfd[0] ); close( execfd[1] ); - if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env ); if (pid == -1) { close( startfd[1] ); diff --git a/files/drive.c b/files/drive.c index dcfe97fbdef..302111d4d6e 100644 --- a/files/drive.c +++ b/files/drive.c @@ -297,24 +297,6 @@ int DRIVE_GetCurrentDrive(void) /*********************************************************************** - * DRIVE_SetCurrentDrive - */ -static int DRIVE_SetCurrentDrive( int drive ) -{ - TDB *pTask = GlobalLock16(GetCurrentTask()); - if (!DRIVE_IsValid( drive )) - { - SetLastError( ERROR_INVALID_DRIVE ); - return 0; - } - TRACE("%c:\n", 'A' + drive ); - DRIVE_CurDrive = drive; - if (pTask) pTask->curdrive = drive | 0x80; - return 1; -} - - -/*********************************************************************** * DRIVE_FindDriveRoot * * Find a drive for which the root matches the beginning of the given path. @@ -570,181 +552,3 @@ int DRIVE_Chdir( int drive, LPCWSTR path ) } return 1; } - - -/*********************************************************************** - * DRIVE_GetCurrentDirectory - * Returns "X:\\path\\etc\\". - * - * Despite the API description, return required length including the - * terminating null when buffer too small. This is the real behaviour. -*/ -static UINT DRIVE_GetCurrentDirectory( UINT buflen, LPWSTR buf ) -{ - UINT ret; - LPCWSTR dos_cwd = DRIVE_GetDosCwd( DRIVE_GetCurrentDrive() ); - static const WCHAR driveA_rootW[] = {'A',':','\\',0}; - - ret = strlenW(dos_cwd) + 3; /* length of WHOLE current directory */ - if (ret >= buflen) return ret + 1; - - strcpyW( buf, driveA_rootW ); - buf[0] += DRIVE_GetCurrentDrive(); - strcatW( buf, dos_cwd ); - return ret; -} - - -/*********************************************************************** - * DRIVE_BuildEnv - * - * Build the environment array containing the drives' current directories. - * Resulting pointer must be freed with HeapFree. - */ -WCHAR *DRIVE_BuildEnv(void) -{ - int i, length = 0; - LPCWSTR cwd[MAX_DOS_DRIVES]; - WCHAR *env, *p; - - for (i = 0; i < MAX_DOS_DRIVES; i++) - { - if ((cwd[i] = DRIVE_GetDosCwd(i)) && cwd[i][0]) - length += strlenW(cwd[i]) + 8; - } - if (!(env = HeapAlloc( GetProcessHeap(), 0, (length+1) * sizeof(WCHAR) ))) return NULL; - for (i = 0, p = env; i < MAX_DOS_DRIVES; i++) - { - if (cwd[i] && cwd[i][0]) - { - *p++ = '='; *p++ = 'A' + i; *p++ = ':'; - *p++ = '='; *p++ = 'A' + i; *p++ = ':'; *p++ = '\\'; - strcpyW( p, cwd[i] ); - p += strlenW(p) + 1; - } - } - *p = 0; - return env; -} - - -/*********************************************************************** - * GetCurrentDirectory (KERNEL.411) - */ -UINT16 WINAPI GetCurrentDirectory16( UINT16 buflen, LPSTR buf ) -{ - WCHAR cur_dirW[MAX_PATH]; - - DRIVE_GetCurrentDirectory(MAX_PATH, cur_dirW); - return (UINT16)WideCharToMultiByte(CP_ACP, 0, cur_dirW, -1, buf, buflen, NULL, NULL); -} - - -/*********************************************************************** - * GetCurrentDirectoryW (KERNEL32.@) - */ -UINT WINAPI GetCurrentDirectoryW( UINT buflen, LPWSTR buf ) -{ - UINT ret; - WCHAR longname[MAX_PATHNAME_LEN]; - WCHAR shortname[MAX_PATHNAME_LEN]; - - ret = DRIVE_GetCurrentDirectory(MAX_PATHNAME_LEN, shortname); - if ( ret > MAX_PATHNAME_LEN ) { - ERR_(file)("pathnamelength (%d) > MAX_PATHNAME_LEN!\n", ret ); - return ret; - } - GetLongPathNameW(shortname, longname, MAX_PATHNAME_LEN); - ret = strlenW( longname ) + 1; - if (ret > buflen) return ret; - strcpyW(buf, longname); - return ret - 1; -} - -/*********************************************************************** - * GetCurrentDirectoryA (KERNEL32.@) - */ -UINT WINAPI GetCurrentDirectoryA( UINT buflen, LPSTR buf ) -{ - WCHAR bufferW[MAX_PATH]; - DWORD ret, retW; - - retW = GetCurrentDirectoryW(MAX_PATH, bufferW); - - if (!retW) - ret = 0; - else if (retW > MAX_PATH) - { - SetLastError(ERROR_FILENAME_EXCED_RANGE); - ret = 0; - } - else - { - ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL); - if (buflen >= ret) - { - WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buf, buflen, NULL, NULL); - ret--; /* length without 0 */ - } - } - return ret; -} - - -/*********************************************************************** - * SetCurrentDirectoryW (KERNEL32.@) - */ -BOOL WINAPI SetCurrentDirectoryW( LPCWSTR dir ) -{ - int drive, olddrive = DRIVE_GetCurrentDrive(); - - if (!dir) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if (dir[0] && (dir[1]==':')) - { - drive = toupperW( *dir ) - 'A'; - dir += 2; - } - else - drive = olddrive; - - /* WARNING: we need to set the drive before the dir, as DRIVE_Chdir - sets pTask->curdir only if pTask->curdrive is drive */ - if (!(DRIVE_SetCurrentDrive( drive ))) - return FALSE; - - /* FIXME: what about empty strings? Add a \\ ? */ - if (!DRIVE_Chdir( drive, dir )) { - DRIVE_SetCurrentDrive(olddrive); - return FALSE; - } - return TRUE; -} - - -/*********************************************************************** - * SetCurrentDirectoryA (KERNEL32.@) - */ -BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir ) -{ - UNICODE_STRING dirW; - BOOL ret = FALSE; - - if (!dir) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (RtlCreateUnicodeStringFromAsciiz(&dirW, dir)) - { - ret = SetCurrentDirectoryW(dirW.Buffer); - RtlFreeUnicodeString(&dirW); - } - else - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return ret; -} diff --git a/include/file.h b/include/file.h index b4be15559b9..46e9712312e 100644 --- a/include/file.h +++ b/include/file.h @@ -59,7 +59,6 @@ extern LPCWSTR DRIVE_GetDosCwd( int drive ); extern const char * DRIVE_GetUnixCwd( int drive ); extern const char * DRIVE_GetDevice( int drive ); extern int DRIVE_Chdir( int drive, LPCWSTR path ); -extern WCHAR *DRIVE_BuildEnv(void); /* vxd.c */ extern HANDLE VXD_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa ); -- 2.11.4.GIT