Use environment variables instead of config file entries to specify
path, profile, temp, windows and system directories.
Convert existing config file entries to registry values under
HKCU\Environment.

diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in
index 27d3842..843e51a 100644
--- a/dlls/kernel/Makefile.in
+++ b/dlls/kernel/Makefile.in
@@ -18,7 +18,6 @@
 	windebug.spec
 
 C_SRCS = \
-	$(TOPOBJDIR)/files/directory.c \
 	$(TOPOBJDIR)/files/smb.c \
 	$(TOPOBJDIR)/misc/registry.c \
 	actctx.c \
diff --git a/dlls/kernel/kernel_private.h b/dlls/kernel/kernel_private.h
index 0605200..b022f4b 100644
--- a/dlls/kernel/kernel_private.h
+++ b/dlls/kernel/kernel_private.h
@@ -50,8 +50,8 @@
 #define DOS_TABLE_SIZE 256
 extern HANDLE dos_handles[DOS_TABLE_SIZE];
 
-extern WCHAR *DIR_Windows;
-extern WCHAR *DIR_System;
+extern const WCHAR *DIR_Windows;
+extern const WCHAR *DIR_System;
 
 extern void PTHREAD_Init(void);
 extern BOOL WOWTHUNK_Init(void);
diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c
index f85f887..c09b655 100644
--- a/dlls/kernel/process.c
+++ b/dlls/kernel/process.c
@@ -45,6 +45,7 @@
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(process);
+WINE_DECLARE_DEBUG_CHANNEL(file);
 WINE_DECLARE_DEBUG_CHANNEL(server);
 WINE_DECLARE_DEBUG_CHANNEL(relay);
 
@@ -67,6 +68,9 @@
 int main_create_flags = 0;
 HMODULE kernel32_handle = 0;
 
+const WCHAR *DIR_Windows = NULL;
+const WCHAR *DIR_System = NULL;
+
 /* Process flags */
 #define PDB32_DEBUGGED      0x0001  /* Process is being debugged */
 #define PDB32_WIN16_PROC    0x0008  /* Win16 process */
@@ -79,7 +83,6 @@
 static const WCHAR batW[] = {'.','b','a','t',0};
 static const WCHAR winevdmW[] = {'w','i','n','e','v','d','m','.','e','x','e',0};
 
-extern int DIR_Init(void);
 extern void SHELL_LoadRegistry(void);
 extern void VOLUME_CreateDevices(void);
 extern void VERSION_Init( const WCHAR *appname );
@@ -780,6 +783,57 @@
 
 
 /***********************************************************************
+ *           init_windows_dirs
+ *
+ * Initialize the windows and system directories from the environment.
+ */
+static void init_windows_dirs(void)
+{
+    static const WCHAR windirW[] = {'w','i','n','d','i','r',0};
+    static const WCHAR winsysdirW[] = {'w','i','n','s','y','s','d','i','r',0};
+    static const WCHAR default_windirW[] = {'c',':','\\','w','i','n','d','o','w','s',0};
+    static const WCHAR default_sysdirW[] = {'c',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m',0};
+
+    DWORD len;
+    WCHAR *buffer;
+
+    if ((len = GetEnvironmentVariableW( windirW, NULL, 0 )))
+    {
+        buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+        GetEnvironmentVariableW( windirW, buffer, len );
+        DIR_Windows = buffer;
+    }
+    else
+    {
+        DIR_Windows = default_windirW;
+        SetEnvironmentVariableW( windirW, DIR_Windows );
+    }
+
+    if ((len = GetEnvironmentVariableW( winsysdirW, NULL, 0 )))
+    {
+        buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+        GetEnvironmentVariableW( winsysdirW, buffer, len );
+        DIR_System = buffer;
+    }
+    else
+    {
+        DIR_System = default_sysdirW;
+        SetEnvironmentVariableW( winsysdirW, DIR_System );
+    }
+
+    if (GetFileAttributesW( DIR_Windows ) == INVALID_FILE_ATTRIBUTES)
+        MESSAGE( "Warning: the specified Windows directory %s is not accessible.\n",
+                 debugstr_w(DIR_Windows) );
+    if (GetFileAttributesW( DIR_System ) == INVALID_FILE_ATTRIBUTES)
+        MESSAGE( "Warning: the specified System directory %s is not accessible.\n",
+                 debugstr_w(DIR_System) );
+
+    TRACE_(file)( "WindowsDir = %s\n", debugstr_w(DIR_Windows) );
+    TRACE_(file)( "SystemDir  = %s\n", debugstr_w(DIR_System) );
+}
+
+
+/***********************************************************************
  *           process_init
  *
  * Main process initialisation code
@@ -876,9 +930,6 @@
     /* Create device symlinks */
     VOLUME_CreateDevices();
 
-    /* initialise DOS directories */
-    if (!DIR_Init()) return FALSE;
-
     init_current_directory( &params->CurrentDirectory );
 
     /* registry initialisation */
@@ -894,6 +945,8 @@
 
     if (!info_size) set_registry_environment();
 
+    init_windows_dirs();
+
     return TRUE;
 }
 
diff --git a/files/directory.c b/files/directory.c
deleted file mode 100644
index fffb9e8..0000000
--- a/files/directory.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * DOS directories functions
- *
- * Copyright 1995 Alexandre Julliard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "config.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_SYS_ERRNO_H
-#include <sys/errno.h>
-#endif
-
-#include "ntstatus.h"
-#include "windef.h"
-#include "winbase.h"
-#include "wine/winbase16.h"
-#include "wingdi.h"
-#include "wine/winuser16.h"
-#include "winerror.h"
-#include "winreg.h"
-#include "winternl.h"
-#include "thread.h"
-#include "wine/unicode.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(dosfs);
-WINE_DECLARE_DEBUG_CHANNEL(file);
-
-#define MAX_PATHNAME_LEN   1024
-
-WCHAR *DIR_Windows = NULL;
-WCHAR *DIR_System = NULL;
-
-/***********************************************************************
- *           DIR_GetPath
- *
- * Get a path name from the wine.ini file and make sure it is valid.
- */
-static WCHAR *DIR_GetPath( HKEY hkey, LPCWSTR keyname, LPCWSTR defval, BOOL warn )
-{
-    UNICODE_STRING nameW;
-    DWORD dummy;
-    WCHAR tmp[MAX_PATHNAME_LEN];
-    const WCHAR *path;
-    const char *mess;
-    WCHAR *ret;
-    DWORD attr;
-
-    RtlInitUnicodeString( &nameW, keyname );
-    if (hkey && !NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
-        path = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
-    else
-        path = defval;
-
-    attr = GetFileAttributesW( path );
-    if (attr == INVALID_FILE_ATTRIBUTES) mess = "does not exist";
-    else if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) mess = "not a directory";
-    else
-    {
-        DWORD len = GetFullPathNameW( path, 0, NULL, NULL );
-        ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-        if (ret) GetFullPathNameW( path, len, ret, NULL );
-        return ret;
-    }
-
-    if (warn)
-    {
-        MESSAGE("Invalid path %s for %s directory: %s.\n",
-                debugstr_w(path), debugstr_w(keyname), mess);
-        MESSAGE("Perhaps you have not properly edited your Wine configuration file (%s/config)\n",
-                wine_get_config_dir());
-    }
-    return NULL;
-}
-
-
-/***********************************************************************
- *           DIR_Init
- */
-int DIR_Init(void)
-{
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING nameW;
-    HKEY hkey;
-    WCHAR longpath[MAX_PATHNAME_LEN];
-    WCHAR *tmp_dir, *profile_dir;
-    static const WCHAR wineW[] = {'M','a','c','h','i','n','e','\\',
-                                  'S','o','f','t','w','a','r','e','\\',
-                                  'W','i','n','e','\\','W','i','n','e','\\',
-                                  'C','o','n','f','i','g','\\','W','i','n','e',0};
-    static const WCHAR windowsW[] = {'w','i','n','d','o','w','s',0};
-    static const WCHAR systemW[] = {'s','y','s','t','e','m',0};
-    static const WCHAR tempW[] = {'t','e','m','p',0};
-    static const WCHAR profileW[] = {'p','r','o','f','i','l','e',0};
-    static const WCHAR windows_dirW[] = {'c',':','\\','w','i','n','d','o','w','s',0};
-    static const WCHAR system_dirW[] = {'c',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m',0};
-    static const WCHAR temp_dirW[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','m','p',0};
-    static const WCHAR pathW[] = {'p','a','t','h',0};
-    static const WCHAR path_dirW[] = {'c',':','\\','w','i','n','d','o','w','s',';',
-                                      'c',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m',0};
-    static const WCHAR path_capsW[] = {'P','A','T','H',0};
-    static const WCHAR temp_capsW[] = {'T','E','M','P',0};
-    static const WCHAR tmp_capsW[] = {'T','M','P',0};
-    static const WCHAR windirW[] = {'w','i','n','d','i','r',0};
-    static const WCHAR winsysdirW[] = {'w','i','n','s','y','s','d','i','r',0};
-    static const WCHAR userprofileW[] = {'U','S','E','R','P','R','O','F','I','L','E',0};
-    static const WCHAR systemrootW[] = {'S','Y','S','T','E','M','R','O','O','T',0};
-    static const WCHAR wcmdW[] = {'\\','w','c','m','d','.','e','x','e',0};
-    static const WCHAR comspecW[] = {'C','O','M','S','P','E','C',0};
-    static const WCHAR empty_strW[] = { 0 };
-
-    attr.Length = sizeof(attr);
-    attr.RootDirectory = 0;
-    attr.ObjectName = &nameW;
-    attr.Attributes = 0;
-    attr.SecurityDescriptor = NULL;
-    attr.SecurityQualityOfService = NULL;
-
-    RtlInitUnicodeString( &nameW, wineW );
-    if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) hkey = 0;
-
-    if (!(DIR_Windows = DIR_GetPath( hkey, windowsW, windows_dirW, TRUE )) ||
-        !(DIR_System = DIR_GetPath( hkey, systemW, system_dirW, TRUE )) ||
-        !(tmp_dir = DIR_GetPath( hkey, tempW, temp_dirW, TRUE )))
-    {
-        if (hkey) NtClose( hkey );
-        return 0;
-    }
-
-    /* Set the environment variables */
-
-    /* set COMSPEC only if it doesn't exist already */
-    if (!GetEnvironmentVariableW( comspecW, NULL, 0 ))
-    {
-        strcpyW( longpath, DIR_System );
-        strcatW( longpath, wcmdW );
-        SetEnvironmentVariableW( comspecW, longpath );
-    }
-
-    /* set PATH only if not set already */
-    if (!GetEnvironmentVariableW( path_capsW, NULL, 0 ))
-    {
-        WCHAR tmp[MAX_PATHNAME_LEN];
-        DWORD dummy;
-        const WCHAR *path = path_dirW;
-
-        RtlInitUnicodeString( &nameW, pathW );
-        if (hkey && !NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
-                                      tmp, sizeof(tmp), &dummy ))
-        {
-            path = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
-        }
-
-        if (strchrW(path, '/'))
-        {
-            MESSAGE("Fix your wine config (%s/config) to use DOS drive syntax in [wine] 'Path=' statement! (no '/' allowed)\n", wine_get_config_dir() );
-            ExitProcess(1);
-        }
-        SetEnvironmentVariableW( path_capsW, path );
-        TRACE("Path       = %s\n", debugstr_w(path) );
-    }
-
-    if (!GetEnvironmentVariableW( temp_capsW, NULL, 0 ))
-        SetEnvironmentVariableW( temp_capsW, tmp_dir );
-    if (!GetEnvironmentVariableW( tmp_capsW, NULL, 0 ))
-        SetEnvironmentVariableW( tmp_capsW, tmp_dir );
-
-    SetEnvironmentVariableW( windirW, DIR_Windows );
-    SetEnvironmentVariableW( systemrootW, DIR_Windows );
-    SetEnvironmentVariableW( winsysdirW, DIR_System );
-
-    TRACE("WindowsDir = %s\n", debugstr_w(DIR_Windows) );
-    TRACE("SystemDir  = %s\n", debugstr_w(DIR_System) );
-    TRACE("TempDir    = %s\n", debugstr_w(tmp_dir) );
-    TRACE("SYSTEMROOT = %s\n", debugstr_w(DIR_Windows) );
-
-    HeapFree( GetProcessHeap(), 0, tmp_dir );
-
-    if ((profile_dir = DIR_GetPath( hkey, profileW, empty_strW, FALSE )))
-    {
-        TRACE("USERPROFILE= %s\n", debugstr_w(profile_dir) );
-        SetEnvironmentVariableW( userprofileW, profile_dir );
-        HeapFree( GetProcessHeap(), 0, profile_dir );
-    }
-
-    if (hkey) NtClose( hkey );
-
-    return 1;
-}
diff --git a/misc/registry.c b/misc/registry.c
index d6528e1..f75f1f4 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -390,7 +390,7 @@
 /******************************************************************************
  * _w31_loadreg [Internal]
  */
-static void _w31_loadreg(void)
+static void _w31_loadreg( const WCHAR *path )
 {
     HANDLE                      hf;
     HKEY                        root;
@@ -400,7 +400,6 @@
     struct _w31_tabent*         tab = NULL;
     unsigned char*              txt = NULL;
     unsigned int		len;
-    OFSTRUCT		        ofs;
     ULONG			lastmodified;
     NTSTATUS                    status;
     IO_STATUS_BLOCK             iosb;
@@ -409,8 +408,8 @@
 
     TRACE("(void)\n");
 
-    hf = (HANDLE)OpenFile("reg.dat",&ofs,OF_READ);
-    if (hf==(HANDLE)HFILE_ERROR) return;
+    hf = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
+    if (hf==INVALID_HANDLE_VALUE) return;
 
     /* read & dump header */
     if (NtReadFile(hf, 0, NULL, NULL, &iosb, 
@@ -1598,9 +1597,14 @@
         }
 
         case REG_WIN31:
+        {
+            static const WCHAR reg_datW[] = {'\\','r','e','g','.','d','a','t',0};
             /* FIXME: here we should convert to *.reg file supported by server and call REQ_LOAD_REGISTRY, see REG_WIN95 case */
-            _w31_loadreg();
+            strcpyW(path, windir);
+            strcatW(path, reg_datW);
+            _w31_loadreg( path );
             break;
+        }
 
         case REG_DONTLOAD:
             TRACE("REG_DONTLOAD\n");
@@ -1803,7 +1807,11 @@
     RtlInitUnicodeString( &nameW, drive_types_keyW );
 
     if (NtCreateKey( &hkey_new, KEY_ALL_ACCESS, &attr, 0, NULL, 0, &disp )) return;
-    if (disp != REG_CREATED_NEW_KEY) return;
+    if (disp != REG_CREATED_NEW_KEY)
+    {
+        NtClose( hkey_new );
+        return;
+    }
 
     for (i = 0; i < 26; i++)
     {
@@ -1828,6 +1836,107 @@
 }
 
 
+/* convert the environment variable entries from the old format to the new one */
+static void convert_environment( HKEY hkey_current_user )
+{
+    static const WCHAR wineW[] = {'M','a','c','h','i','n','e','\\',
+                                  'S','o','f','t','w','a','r','e','\\',
+                                  'W','i','n','e','\\','W','i','n','e','\\',
+                                  'C','o','n','f','i','g','\\','W','i','n','e',0};
+    static const WCHAR windowsW[] = {'w','i','n','d','o','w','s',0};
+    static const WCHAR systemW[] = {'s','y','s','t','e','m',0};
+    static const WCHAR windirW[] = {'w','i','n','d','i','r',0};
+    static const WCHAR winsysdirW[] = {'w','i','n','s','y','s','d','i','r',0};
+    static const WCHAR envW[] = {'E','n','v','i','r','o','n','m','e','n','t',0};
+    static const WCHAR tempW[] = {'T','E','M','P',0};
+    static const WCHAR tmpW[] = {'T','M','P',0};
+    static const WCHAR pathW[] = {'P','A','T','H',0};
+    static const WCHAR profileW[] = {'p','r','o','f','i','l','e',0};
+    static const WCHAR userprofileW[] = {'U','S','E','R','P','R','O','F','I','L','E',0};
+
+    char buffer[1024*sizeof(WCHAR) + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
+    KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING nameW;
+    DWORD dummy;
+    ULONG disp;
+    HKEY hkey_old, hkey_env;
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+    RtlInitUnicodeString( &nameW, wineW );
+
+    if (NtOpenKey( &hkey_old, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) return;
+
+    attr.RootDirectory = hkey_current_user;
+    RtlInitUnicodeString( &nameW, envW );
+    if (NtCreateKey( &hkey_env, KEY_ALL_ACCESS, &attr, 0, NULL, 0, &disp ))
+    {
+        NtClose( hkey_old );
+        return;
+    }
+    if (disp != REG_CREATED_NEW_KEY) goto done;
+
+    /* convert TEMP */
+    RtlInitUnicodeString( &nameW, tempW );
+    if (!NtQueryValueKey( hkey_old, &nameW, KeyValuePartialInformation, buffer, sizeof(buffer), &dummy ))
+    {
+        NtSetValueKey( hkey_env, &nameW, 0, info->Type, info->Data, info->DataLength );
+        RtlInitUnicodeString( &nameW, tmpW );
+        NtSetValueKey( hkey_env, &nameW, 0, info->Type, info->Data, info->DataLength );
+        MESSAGE( "Converted temp dir to new entry HKCU\\Environment \"TEMP\" = %s\n",
+                 debugstr_w( (WCHAR*)info->Data ) );
+    }
+
+    /* convert PATH */
+    RtlInitUnicodeString( &nameW, pathW );
+    if (!NtQueryValueKey( hkey_old, &nameW, KeyValuePartialInformation, buffer, sizeof(buffer), &dummy ))
+    {
+        NtSetValueKey( hkey_env, &nameW, 0, info->Type, info->Data, info->DataLength );
+        MESSAGE( "Converted path dir to new entry HKCU\\Environment \"PATH\" = %s\n",
+                 debugstr_w( (WCHAR*)info->Data ) );
+    }
+
+    /* convert USERPROFILE */
+    RtlInitUnicodeString( &nameW, profileW );
+    if (!NtQueryValueKey( hkey_old, &nameW, KeyValuePartialInformation, buffer, sizeof(buffer), &dummy ))
+    {
+        RtlInitUnicodeString( &nameW, userprofileW );
+        NtSetValueKey( hkey_env, &nameW, 0, info->Type, info->Data, info->DataLength );
+        MESSAGE( "Converted profile dir to new entry HKCU\\Environment \"USERPROFILE\" = %s\n",
+                 debugstr_w( (WCHAR*)info->Data ) );
+    }
+
+    /* convert windir */
+    RtlInitUnicodeString( &nameW, windowsW );
+    if (!NtQueryValueKey( hkey_old, &nameW, KeyValuePartialInformation, buffer, sizeof(buffer), &dummy ))
+    {
+        RtlInitUnicodeString( &nameW, windirW );
+        NtSetValueKey( hkey_env, &nameW, 0, info->Type, info->Data, info->DataLength );
+        MESSAGE( "Converted windows dir to new entry HKCU\\Environment \"windir\" = %s\n",
+                 debugstr_w( (WCHAR*)info->Data ) );
+    }
+
+    /* convert winsysdir */
+    RtlInitUnicodeString( &nameW, systemW );
+    if (!NtQueryValueKey( hkey_old, &nameW, KeyValuePartialInformation, buffer, sizeof(buffer), &dummy ))
+    {
+        RtlInitUnicodeString( &nameW, winsysdirW );
+        NtSetValueKey( hkey_env, &nameW, 0, info->Type, info->Data, info->DataLength );
+        MESSAGE( "Converted system dir to new entry HKCU\\Environment \"winsysdir\" = %s\n",
+                 debugstr_w( (WCHAR*)info->Data ) );
+    }
+
+done:
+    NtClose( hkey_old );
+    NtClose( hkey_env );
+}
+
+
 /* load all registry (native and global and home) */
 void SHELL_LoadRegistry( void )
 {
@@ -1977,6 +2086,7 @@
     /* convert keys from config file to new registry format */
 
     convert_drive_types();
+    convert_environment( hkey_current_user );
 
     NtClose(hkey_users_default);
     NtClose(hkey_current_user);