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
@@ -575,6 +575,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)
  */
@@ -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
@@ -1192,6 +1192,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
  *
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
@@ -296,24 +296,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
  *
@@ -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 );