Reimplemented Get/SetCurrentDirectoryW using the corresponding ntdll
functions.
diff --git a/dlls/kernel/file16.c b/dlls/kernel/file16.c
index d757e1f..9da4517 100644
--- a/dlls/kernel/file16.c
+++ b/dlls/kernel/file16.c
@@ -576,6 +576,15 @@
/***********************************************************************
+ * 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 @@
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 6d5a31d..c00d59a 100644
--- a/dlls/kernel/path.c
+++ b/dlls/kernel/path.c
@@ -1193,6 +1193,87 @@
/***********************************************************************
+ * 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 61bc0f1..8ca5d1a 100644
--- a/dlls/kernel/process.c
+++ b/dlls/kernel/process.c
@@ -1060,23 +1060,13 @@
*
* 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 @@
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 @@
/* 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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 dcfe97f..302111d 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -297,24 +297,6 @@
/***********************************************************************
- * 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 @@
}
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 b4be155..46e9712 100644
--- a/include/file.h
+++ b/include/file.h
@@ -59,7 +59,6 @@
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 );