ntdll / kernel32: #49

Eric Pouech pouech-eric at wanadoo.fr
Wed Feb 4 14:55:51 CST 2004


Various clean-ups
- got rid of include/drive.h and include/file.h
- move remaining functions of files/dos_fs.c to dlls/kernel

Note: files/dos_fs.c shall be removed

that's all for now
A+
-------------- next part --------------
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/kernel_main.c dlls/kernel/kernel_main.c
--- dlls/kernel48/kernel_main.c	2004-01-01 09:53:31.000000000 +0100
+++ dlls/kernel/kernel_main.c	2004-02-01 21:56:58.000000000 +0100
@@ -36,7 +36,6 @@
 
 #include "wine/winbase16.h"
 #include "wine/library.h"
-#include "file.h"
 #include "miscemu.h"
 #include "module.h"
 #include "thread.h"
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/kernel_private.h dlls/kernel/kernel_private.h
--- dlls/kernel48/kernel_private.h	2004-01-20 21:48:28.000000000 +0100
+++ dlls/kernel/kernel_private.h	2004-02-01 22:01:33.000000000 +0100
@@ -47,12 +47,16 @@
 /* Size of per-process table of DOS handles */
 #define DOS_TABLE_SIZE 256
 extern HANDLE dos_handles[DOS_TABLE_SIZE];
+extern mode_t FILE_umask;
 #define MAX_PATHNAME_LEN   1024
-void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing );
-void FILE_SetDosError(void);
+extern void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing );
+extern void FILE_SetDosError(void);
 extern DWORD    DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
                                 LPWSTR full_name, unsigned fnlen, LPWSTR* last, BOOL win32 );
-int  DRIVE_GetCurrentDrive(void);
+extern int  DRIVE_GetCurrentDrive(void);
+extern int  DRIVE_Chdir( int drive, LPCWSTR path );
+extern int  DRIVE_Init(void);
+extern int  DIR_Init(void);
 
 extern void PTHREAD_Init(void);
 extern BOOL WOWTHUNK_Init(void);
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/Makefile.in dlls/kernel/Makefile.in
--- dlls/kernel48/Makefile.in	2004-02-01 16:03:11.000000000 +0100
+++ dlls/kernel/Makefile.in	2004-02-01 22:07:49.000000000 +0100
@@ -19,7 +19,6 @@
 
 C_SRCS = \
 	$(TOPOBJDIR)/files/directory.c \
-	$(TOPOBJDIR)/files/dos_fs.c \
 	$(TOPOBJDIR)/files/drive.c \
 	$(TOPOBJDIR)/files/file.c \
 	$(TOPOBJDIR)/files/smb.c \
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/ne_module.c dlls/kernel/ne_module.c
--- dlls/kernel48/ne_module.c	2004-01-14 22:29:57.000000000 +0100
+++ dlls/kernel/ne_module.c	2004-02-01 21:59:57.000000000 +0100
@@ -40,7 +40,6 @@
 #include "wownt32.h"
 #include "module.h"
 #include "toolhelp.h"
-#include "file.h"
 #include "builtin16.h"
 #include "stackframe.h"
 #include "excpt.h"
@@ -126,6 +125,46 @@
 }
 
 
+/* locale-independent case conversion */
+inline static char FILE_tolower( char c )
+{
+    if (c >= 'A' && c <= 'Z') c += 32;
+    return c;
+}
+inline static char FILE_toupper( char c )
+{
+    if (c >= 'a' && c <= 'z') c -= 32;
+    return c;
+}
+
+/***********************************************************************
+ *              FILE_strcasecmp
+ *
+ * locale-independent case conversion for file I/O
+ */
+int FILE_strcasecmp( const char *str1, const char *str2 )
+{
+    int ret = 0;
+    for ( ; ; str1++, str2++)
+        if ((ret = FILE_toupper(*str1) - FILE_toupper(*str2)) || !*str1) break;
+    return ret;
+}
+
+
+/***********************************************************************
+ *              FILE_strncasecmp
+ *
+ * locale-independent case conversion for file I/O
+ */
+int FILE_strncasecmp( const char *str1, const char *str2, int len )
+{
+    int ret = 0;
+    for ( ; len > 0; len--, str1++, str2++)
+        if ((ret = FILE_toupper(*str1) - FILE_toupper(*str2)) || !*str1) break;
+    return ret;
+}
+
+
 /***********************************************************************
  *           find_dll_descr
  *
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/ne_segment.c dlls/kernel/ne_segment.c
--- dlls/kernel48/ne_segment.c	2004-02-01 16:03:11.000000000 +0100
+++ dlls/kernel/ne_segment.c	2004-02-01 21:57:12.000000000 +0100
@@ -37,7 +37,6 @@
 #include "wownt32.h"
 #include "wine/library.h"
 #include "kernel_private.h"
-#include "file.h"
 #include "module.h"
 #include "stackframe.h"
 #include "builtin16.h"
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/process.c dlls/kernel/process.c
--- dlls/kernel48/process.c	2004-01-23 22:40:02.000000000 +0100
+++ dlls/kernel/process.c	2004-02-02 22:08:23.000000000 +0100
@@ -27,13 +27,15 @@
 #include <locale.h>
 #include <signal.h>
 #include <stdio.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
 
 #include "wine/winbase16.h"
 #include "wine/winuser16.h"
 #include "ntstatus.h"
 #include "thread.h"
-#include "drive.h"
-#include "file.h"
 #include "module.h"
 #include "options.h"
 #include "kernel_private.h"
@@ -334,49 +336,6 @@
 }
 
 /***********************************************************************
- *           build_initial_environment
- *
- * Build the Win32 environment from the Unix environment
- */
-static BOOL build_initial_environment( char **environ )
-{
-    ULONG size = 1;
-    char **e;
-    WCHAR *p, *endptr;
-    void *ptr;
-
-    /* Compute the total size of the Unix environment */
-    for (e = environ; *e; e++)
-    {
-        if (!memcmp(*e, "PATH=", 5)) continue;
-        size += MultiByteToWideChar( CP_UNIXCP, 0, *e, -1, NULL, 0 );
-    }
-    size *= sizeof(WCHAR);
-
-    /* Now allocate the environment */
-    if (NtAllocateVirtualMemory(NtCurrentProcess(), &ptr, 0, &size,
-                                MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) != STATUS_SUCCESS)
-        return FALSE;
-
-    NtCurrentTeb()->Peb->ProcessParameters->Environment = p = ptr;
-    endptr = p + size / sizeof(WCHAR);
-
-    /* And fill it with the Unix environment */
-    for (e = environ; *e; e++)
-    {
-        char *str = *e;
-        /* skip Unix PATH and store WINEPATH as PATH */
-        if (!memcmp(str, "PATH=", 5)) continue;
-        if (!memcmp(str, "WINEPATH=", 9 )) str += 4;
-        MultiByteToWideChar( CP_UNIXCP, 0, str, -1, p, endptr - p );
-        p += strlenW(p) + 1;
-    }
-    *p = 0;
-    return TRUE;
-}
-
-
-/***********************************************************************
  *              set_library_wargv
  *
  * Set the Wine library Unicode argv global variables.
@@ -611,7 +570,7 @@
  *
  * Main process initialisation code
  */
-static BOOL process_init( char *argv[], char **environ )
+static BOOL process_init( char *argv[] )
 {
     BOOL ret;
     size_t info_size = 0;
@@ -700,16 +659,10 @@
 
     LOCALE_Init();
 
-    /* Copy the parent environment */
-    if (!build_initial_environment( environ )) return FALSE;
-
     /* Parse command line arguments */
     OPTIONS_ParseOptions( !info_size ? argv : NULL );
 
-    /* initialise DOS drives */
-    if (!DRIVE_Init()) return FALSE;
-
-    /* initialise DOS directories */
+    /* initialise system directories */
     if (!DIR_Init()) return FALSE;
 
     /* registry initialisation */
@@ -776,7 +729,7 @@
     PEB *peb = NtCurrentTeb()->Peb;
 
     /* Initialize everything */
-    if (!process_init( __wine_main_argv, __wine_main_environ )) exit(1);
+    if (!process_init( __wine_main_argv )) exit(1);
     /* update argc in case options have been removed */
     for (__wine_main_argc = 0; __wine_main_argv[__wine_main_argc]; __wine_main_argc++) /*nothing*/;
 
@@ -810,6 +763,7 @@
 
     MODULE_InitLoadPath();
     VERSION_Init( main_exe_name );
+    DRIVE_Init();
 
     if (!main_exe_file)  /* no file handle -> Winelib app */
     {
@@ -1028,23 +982,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 );
@@ -1058,8 +1002,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, HOME and WINEPREFIX from the unix env */
         if ((p = getenv("PATH"))) *envptr++ = alloc_env_string( "PATH=", p );
         if ((p = getenv("HOME"))) *envptr++ = alloc_env_string( "HOME=", p );
@@ -1067,8 +1009,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 (!memcmp( p, "PATH=", 5 ))  /* store PATH as WINEPATH */
                 *envptr++ = alloc_env_string( "WINEPATH=", p + 5 );
             else if (memcmp( p, "HOME=", 5 ) &&
@@ -1103,7 +1043,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 */
@@ -1159,7 +1099,6 @@
         return NULL;
     }
 
-    params->Environment     = NULL;  /* we pass it through the Unix environment */
     params->hStdInput       = startup->hStdInput;
     params->hStdOutput      = startup->hStdOutput;
     params->hStdError       = startup->hStdError;
@@ -1190,24 +1129,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 */
 
@@ -1215,7 +1146,6 @@
     {
         FILE_SetDosError();
         RtlDestroyProcessParameters( params );
-        if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env );
         return FALSE;
     }
     if (pipe( execfd ) == -1)
@@ -1224,7 +1154,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 */
@@ -1234,7 +1163,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] );
@@ -1266,7 +1195,6 @@
 
     close( startfd[0] );
     close( execfd[1] );
-    if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env );
     if (pid == -1)
     {
         close( startfd[1] );
@@ -1688,7 +1616,7 @@
 
             if (wine_get_unix_file_name( name, uname, sizeof(uname) ))
                 retv = (fork_and_exec( uname, tidy_cmdline, envW, unixdir ) != -1);
-         }
+        }
         break;
     }
     CloseHandle( hFile );
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/profile.c dlls/kernel/profile.c
--- dlls/kernel48/profile.c	2004-01-20 22:30:04.000000000 +0100
+++ dlls/kernel/profile.c	2004-02-01 22:00:49.000000000 +0100
@@ -41,10 +41,10 @@
 #include "winreg.h"
 #include "winternl.h"
 #include "wine/winbase16.h"
-#include "file.h"
 #include "wine/unicode.h"
 #include "wine/server.h"
 #include "wine/library.h"
+#include "kernel_private.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(profile);
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/system.c dlls/kernel/system.c
--- dlls/kernel48/system.c	2004-01-23 22:40:03.000000000 +0100
+++ dlls/kernel/system.c	2004-02-01 22:06:54.000000000 +0100
@@ -254,3 +254,54 @@
     __asm__(".byte 0x66; frstor %0" : : "m" (ptr) );
 #endif
 }
+
+/***********************************************************************
+ *           MulDiv   (KERNEL32.@)
+ * RETURNS
+ *	Result of multiplication and division
+ *	-1: Overflow occurred or Divisor was 0
+ */
+INT WINAPI MulDiv(
+	     INT nMultiplicand,
+	     INT nMultiplier,
+	     INT nDivisor)
+{
+#if SIZEOF_LONG_LONG >= 8
+    long long ret;
+
+    if (!nDivisor) return -1;
+
+    /* We want to deal with a positive divisor to simplify the logic. */
+    if (nDivisor < 0)
+    {
+        nMultiplicand = - nMultiplicand;
+        nDivisor = -nDivisor;
+    }
+
+    /* If the result is positive, we "add" to round. else, we subtract to round. */
+    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
+	 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
+        ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
+    else
+        ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
+
+    if ((ret > 2147483647) || (ret < -2147483647)) return -1;
+    return ret;
+#else
+    if (!nDivisor) return -1;
+
+    /* We want to deal with a positive divisor to simplify the logic. */
+    if (nDivisor < 0)
+    {
+        nMultiplicand = - nMultiplicand;
+        nDivisor = -nDivisor;
+    }
+
+    /* If the result is positive, we "add" to round. else, we subtract to round. */
+    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
+	 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
+        return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
+
+    return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
+#endif
+}
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel48/time.c dlls/kernel/time.c
--- dlls/kernel48/time.c	2004-01-23 22:40:03.000000000 +0100
+++ dlls/kernel/time.c	2004-02-01 22:07:39.000000000 +0100
@@ -21,10 +21,12 @@
 #include "config.h"
 
 #include <string.h>
+#include <stdarg.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
 #include <stdlib.h>
+#include <time.h>
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 #endif
@@ -35,10 +37,13 @@
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
 #include "ntstatus.h"
-#include "file.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
 #include "winternl.h"
 #include "winerror.h"
 #include "winnls.h"
+#include "wine/winbase16.h"
 #include "kernel_private.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
@@ -805,6 +810,60 @@
     return TRUE;
 }
 
+/***********************************************************************
+ *           DosDateTimeToFileTime   (KERNEL32.@)
+ */
+BOOL WINAPI DosDateTimeToFileTime( WORD fatdate, WORD fattime, LPFILETIME ft)
+{
+    struct tm newtm;
+#ifndef HAVE_TIMEGM
+    struct tm *gtm;
+    time_t time1, time2;
+#endif
+
+    newtm.tm_sec  = (fattime & 0x1f) * 2;
+    newtm.tm_min  = (fattime >> 5) & 0x3f;
+    newtm.tm_hour = (fattime >> 11);
+    newtm.tm_mday = (fatdate & 0x1f);
+    newtm.tm_mon  = ((fatdate >> 5) & 0x0f) - 1;
+    newtm.tm_year = (fatdate >> 9) + 80;
+#ifdef HAVE_TIMEGM
+    RtlSecondsSince1970ToTime( timegm(&newtm), (LARGE_INTEGER *)ft );
+#else
+    time1 = mktime(&newtm);
+    gtm = gmtime(&time1);
+    time2 = mktime(gtm);
+    RtlSecondsSince1970ToTime( 2*time1-time2, (LARGE_INTEGER *)ft );
+#endif
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           FileTimeToDosDateTime   (KERNEL32.@)
+ */
+BOOL WINAPI FileTimeToDosDateTime( const FILETIME *ft, LPWORD fatdate,
+                                     LPWORD fattime )
+{
+    LARGE_INTEGER       li;
+    ULONG               t;
+    time_t              unixtime;
+    struct tm*          tm;
+
+    li.u.LowPart = ft->dwLowDateTime;
+    li.u.HighPart = ft->dwHighDateTime;
+    RtlTimeToSecondsSince1970( &li, &t );
+    unixtime = t;
+    tm = gmtime( &unixtime );
+    if (fattime)
+        *fattime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
+    if (fatdate)
+        *fatdate = ((tm->tm_year - 80) << 9) + ((tm->tm_mon + 1) << 5)
+                   + tm->tm_mday;
+    return TRUE;
+}
+
+
 /*********************************************************************
  *      CompareFileTime                                 (KERNEL32.@)
  *
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll48/cdrom.c dlls/ntdll/cdrom.c
--- dlls/ntdll48/cdrom.c	2004-02-02 22:02:01.000000000 +0100
+++ dlls/ntdll/cdrom.c	2004-02-02 22:00:25.000000000 +0100
@@ -385,7 +385,8 @@
     *iface = 0;
     *device = 0;
     *lun = 0;
-    switch (major(st.st_rdev)) {
+    switch (major(st.st_rdev))
+    {
     case IDE0_MAJOR: *iface = 0; break;
     case IDE1_MAJOR: *iface = 1; break;
     case IDE2_MAJOR: *iface = 2; break;
@@ -425,12 +426,14 @@
     {
         switch (addr.type) 
         {
-        case TYPE_SCSI:  *port = 1;
+        case TYPE_SCSI:
+            *port = 1;
             *iface = addr.addr.scsi.scbus;
             *device = addr.addr.scsi.target;
             *lun = addr.addr.scsi.lun;
             break;
-        case TYPE_ATAPI: *port = 0;
+        case TYPE_ATAPI:
+            *port = 0;
             *iface = addr.addr.atapi.atbus;
             *device = addr.addr.atapi.drive;
             *lun = 0;
@@ -449,16 +452,7 @@
 }
 
 
-/******************************************************************
- *		CDROM_InitRegistry
- *
- * Initializes registry to contain scsi info about the cdrom in NT.
- * All devices (even not real scsi ones) have this info in NT.
- * TODO: for now it only works for non scsi devices
- * NOTE: programs usually read these registry entries after sending the
- *       IOCTL_SCSI_GET_ADDRESS ioctl to the cdrom
- */
-void CDROM_InitRegistry(int fd)
+void CDROM_InitCdInstance(int fd)
 {
     int portnum, busid, targetid, lun;
     OBJECT_ATTRIBUTES attr;
@@ -585,6 +579,43 @@
     NtClose( scsiKey );
 }
 
+/******************************************************************
+ *		CDROM_InitRegistry
+ *
+ * Initializes registry to contain scsi info about the cdrom in NT.
+ * All devices (even not real scsi ones) have this info in NT.
+ * TODO: for now it only works for non scsi devices
+ * NOTE: programs usually read these registry entries after sending the
+ *       IOCTL_SCSI_GET_ADDRESS ioctl to the cdrom
+ */
+void CDROM_InitRegistry(void)
+{
+    char        tmp[1024];
+    int         drv, fd, cd_fd;
+    unsigned    len;
+
+    for (drv = 'a'; drv <= 'z'; drv++)
+    {
+        sprintf(tmp, "%s/device/%c:/type", wine_get_config_dir(), drv);
+        fd = open(tmp, O_RDONLY);
+        if (fd == -1) continue;
+        if ((len = read(fd, tmp, sizeof(tmp))) != -1)
+        {
+            tmp[len] = '\0';
+            if (!strcmp(tmp, "cdrom"));
+            {
+                sprintf(tmp, "%s/device/%c:/device", wine_get_config_dir(), drv);
+                /* should check that flags is cdrom */
+                if ((cd_fd = open(tmp, O_RDONLY|O_NONBLOCK)) != -1)
+                {
+                    CDROM_InitCdInstance(cd_fd);
+                    close(cd_fd);
+                }
+            }
+        }
+        close(fd);
+    }
+}
 
 /******************************************************************
  *		CDROM_Open
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll48/env.c dlls/ntdll/env.c
--- dlls/ntdll48/env.c	2004-01-01 09:53:16.000000000 +0100
+++ dlls/ntdll/env.c	2004-02-02 21:50:46.000000000 +0100
@@ -29,10 +29,54 @@
 #include "winternl.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
+#include "wine/library.h"
 #include "ntdll_misc.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(environ);
 
+/***********************************************************************
+ *           build_initial_environment
+ *
+ * Build the Win32 environment from the Unix environment
+ */
+BOOL build_initial_environment( void )
+{
+    ULONG size = 1;
+    char **e;
+    WCHAR *p, *endptr;
+    void *ptr;
+
+    /* Compute the total size of the Unix environment */
+    for (e = __wine_main_environ; *e; e++)
+    {
+        if (!memcmp(*e, "PATH=", 5)) continue;
+        size += ntdll_umbstowcs( 0, *e, strlen(*e) + 1, NULL, 0 );
+    }
+    size *= sizeof(WCHAR);
+
+    /* Now allocate the environment */
+    if (NtAllocateVirtualMemory(NtCurrentProcess(), &ptr, 0, &size,
+                                MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) != STATUS_SUCCESS)
+        return FALSE;
+
+    NtCurrentTeb()->Peb->ProcessParameters->Environment = p = ptr;
+    endptr = p + size / sizeof(WCHAR);
+
+    /* And fill it with the Unix environment */
+    for (e = __wine_main_environ; *e; e++)
+    {
+        char *str = *e;
+        /* skip Unix PATH and store WINEPATH as PATH */
+        if (!memcmp(str, "PATH=", 5)) continue;
+        if (!memcmp(str, "WINEPATH=", 9 )) str += 4;
+        ntdll_umbstowcs( 0, str, strlen(str) + 1, p, endptr - p );
+        p += strlenW(p) + 1;
+    }
+    *p = 0;
+    return TRUE;
+}
+
+
 /******************************************************************************
  *  RtlCreateEnvironment		[NTDLL.@]
  */
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll48/ntdll_misc.h dlls/ntdll/ntdll_misc.h
--- dlls/ntdll48/ntdll_misc.h	2004-02-01 21:18:58.000000000 +0100
+++ dlls/ntdll/ntdll_misc.h	2004-02-02 21:52:16.000000000 +0100
@@ -50,6 +50,8 @@
 extern void debug_init(void);
 extern void thread_init(void);
 extern void virtual_init(void);
+extern BOOL build_initial_environment(void);
+extern void CDROM_InitRegistry(void);
 
 /* server support */
 extern void server_init_process(void);
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll48/rtlstr.c dlls/ntdll/rtlstr.c
--- dlls/ntdll48/rtlstr.c	2004-01-23 22:40:03.000000000 +0100
+++ dlls/ntdll/rtlstr.c	2004-02-02 21:52:01.000000000 +0100
@@ -59,6 +59,8 @@
     oem_table = oem;
     unix_table = ucp;
     NlsAnsiCodePage = ansi->info.codepage;
+    build_initial_environment();
+    CDROM_InitRegistry();
 }
 
 int ntdll_umbstowcs(DWORD flags, const char* src, int srclen, WCHAR* dst, int dstlen)
diff -u -N -r -x '*~' -x '.#*' -x CVS files48/dos_fs.c files/dos_fs.c
--- files48/dos_fs.c	2004-01-23 22:42:48.000000000 +0100
+++ files/dos_fs.c	2004-02-01 22:07:08.000000000 +0100
@@ -52,8 +52,7 @@
 
 #include "wine/unicode.h"
 #include "wine/winbase16.h"
-#include "drive.h"
-#include "file.h"
+#include "winreg.h"
 #include "winternl.h"
 #include "wine/server.h"
 #include "wine/exception.h"
@@ -94,6 +93,8 @@
 /* Chars we don't want to see in DOS file names */
 #define INVALID_DOS_CHARS  "*?<>|\"+=,;[] \345"
 
+#define IS_END_OF_NAME(ch)  (!(ch) || ((ch) == '/') || ((ch) == '\\'))
+
 /*
  * Directory info for DOSFS_ReadDir
  * contains the names of *all* the files in the directory
@@ -105,210 +106,3 @@
     WCHAR names[1];
 } DOS_DIR;
 
-/***********************************************************************
- *           DOSFS_ToDosFCBFormat
- *
- * Convert a file name to DOS FCB format (8+3 chars, padded with blanks),
- * expanding wild cards and converting to upper-case in the process.
- * File name can be terminated by '\0', '\\' or '/'.
- * Return FALSE if the name is not a valid DOS name.
- * 'buffer' must be at least 12 characters long.
- */
-BOOL DOSFS_ToDosFCBFormat( LPCWSTR name, LPWSTR buffer )
-{
-    static const char invalid_chars[] = INVALID_DOS_CHARS;
-    LPCWSTR p = name;
-    int i;
-
-    /* Check for "." and ".." */
-    if (*p == '.')
-    {
-        p++;
-        buffer[0] = '.';
-        for(i = 1; i < 11; i++) buffer[i] = ' ';
-        buffer[11] = 0;
-        if (*p == '.')
-        {
-            buffer[1] = '.';
-            p++;
-        }
-        return (!*p || (*p == '/') || (*p == '\\'));
-    }
-
-    for (i = 0; i < 8; i++)
-    {
-        switch(*p)
-        {
-        case '\0':
-        case '\\':
-        case '/':
-        case '.':
-            buffer[i] = ' ';
-            break;
-        case '?':
-            p++;
-            /* fall through */
-        case '*':
-            buffer[i] = '?';
-            break;
-        default:
-            if (*p < 256 && strchr( invalid_chars, (char)*p )) return FALSE;
-            buffer[i] = toupperW(*p);
-            p++;
-            break;
-        }
-    }
-
-    if (*p == '*')
-    {
-        /* Skip all chars after wildcard up to first dot */
-        while (*p && (*p != '/') && (*p != '\\') && (*p != '.')) p++;
-    }
-    else
-    {
-        /* Check if name too long */
-        if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return FALSE;
-    }
-    if (*p == '.') p++;  /* Skip dot */
-
-    for (i = 8; i < 11; i++)
-    {
-        switch(*p)
-        {
-        case '\0':
-        case '\\':
-        case '/':
-            buffer[i] = ' ';
-            break;
-        case '.':
-            return FALSE;  /* Second extension not allowed */
-        case '?':
-            p++;
-            /* fall through */
-        case '*':
-            buffer[i] = '?';
-            break;
-        default:
-            if (*p < 256 && strchr( invalid_chars, (char)*p )) return FALSE;
-            buffer[i] = toupperW(*p);
-            p++;
-            break;
-        }
-    }
-    buffer[11] = '\0';
-
-    /* at most 3 character of the extension are processed
-     * is something behind this ?
-     */
-    while (*p == '*' || *p == ' ') p++; /* skip wildcards and spaces */
-    return IS_END_OF_NAME(*p);
-}
-
-
-/***********************************************************************
- *           MulDiv   (KERNEL32.@)
- * RETURNS
- *	Result of multiplication and division
- *	-1: Overflow occurred or Divisor was 0
- */
-INT WINAPI MulDiv(
-	     INT nMultiplicand,
-	     INT nMultiplier,
-	     INT nDivisor)
-{
-#if SIZEOF_LONG_LONG >= 8
-    long long ret;
-
-    if (!nDivisor) return -1;
-
-    /* We want to deal with a positive divisor to simplify the logic. */
-    if (nDivisor < 0)
-    {
-      nMultiplicand = - nMultiplicand;
-      nDivisor = -nDivisor;
-    }
-
-    /* If the result is positive, we "add" to round. else, we subtract to round. */
-    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
-	 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
-      ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
-    else
-      ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
-
-    if ((ret > 2147483647) || (ret < -2147483647)) return -1;
-    return ret;
-#else
-    if (!nDivisor) return -1;
-
-    /* We want to deal with a positive divisor to simplify the logic. */
-    if (nDivisor < 0)
-    {
-      nMultiplicand = - nMultiplicand;
-      nDivisor = -nDivisor;
-    }
-
-    /* If the result is positive, we "add" to round. else, we subtract to round. */
-    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
-	 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
-      return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
-
-    return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
-
-#endif
-}
-
-
-/***********************************************************************
- *           DosDateTimeToFileTime   (KERNEL32.@)
- */
-BOOL WINAPI DosDateTimeToFileTime( WORD fatdate, WORD fattime, LPFILETIME ft)
-{
-    struct tm newtm;
-#ifndef HAVE_TIMEGM
-    struct tm *gtm;
-    time_t time1, time2;
-#endif
-
-    newtm.tm_sec  = (fattime & 0x1f) * 2;
-    newtm.tm_min  = (fattime >> 5) & 0x3f;
-    newtm.tm_hour = (fattime >> 11);
-    newtm.tm_mday = (fatdate & 0x1f);
-    newtm.tm_mon  = ((fatdate >> 5) & 0x0f) - 1;
-    newtm.tm_year = (fatdate >> 9) + 80;
-#ifdef HAVE_TIMEGM
-    RtlSecondsSince1970ToTime( timegm(&newtm), (LARGE_INTEGER *)ft );
-#else
-    time1 = mktime(&newtm);
-    gtm = gmtime(&time1);
-    time2 = mktime(gtm);
-    RtlSecondsSince1970ToTime( 2*time1-time2, (LARGE_INTEGER *)ft );
-#endif
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           FileTimeToDosDateTime   (KERNEL32.@)
- */
-BOOL WINAPI FileTimeToDosDateTime( const FILETIME *ft, LPWORD fatdate,
-                                     LPWORD fattime )
-{
-    LARGE_INTEGER       li;
-    ULONG               t;
-    time_t              unixtime;
-    struct tm*          tm;
-
-    li.u.LowPart = ft->dwLowDateTime;
-    li.u.HighPart = ft->dwHighDateTime;
-    RtlTimeToSecondsSince1970( &li, &t );
-    unixtime = t;
-    tm = gmtime( &unixtime );
-    if (fattime)
-        *fattime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
-    if (fatdate)
-        *fatdate = ((tm->tm_year - 80) << 9) + ((tm->tm_mon + 1) << 5)
-                   + tm->tm_mday;
-    return TRUE;
-}
-
-
diff -u -N -r -x '*~' -x '.#*' -x CVS files48/drive.c files/drive.c
--- files48/drive.c	2004-01-23 22:43:07.000000000 +0100
+++ files/drive.c	2004-02-04 21:22:59.000000000 +0100
@@ -67,8 +67,7 @@
 #include "winioctl.h"
 #include "ntddstor.h"
 #include "ntddcdrm.h"
-#include "drive.h"
-#include "file.h"
+#include "kernel_private.h"
 #include "wine/unicode.h"
 #include "wine/library.h"
 #include "wine/server.h"
@@ -77,100 +76,8 @@
 WINE_DEFAULT_DEBUG_CHANNEL(dosfs);
 WINE_DECLARE_DEBUG_CHANNEL(file);
 
-typedef struct
-{
-    char     *root;      /* root dir in Unix format without trailing / */
-    LPWSTR    dos_cwd;   /* cwd in DOS format without leading or trailing \ */
-    char     *unix_cwd;  /* cwd in Unix format without leading or trailing / */
-    UINT      type;      /* drive type */
-    UINT      flags;     /* drive flags */
-    dev_t     dev;       /* unix device number */
-    ino_t     ino;       /* unix inode number */
-} DOSDRIVE;
-
-
-static const WCHAR DRIVE_Types[][8] =
-{
-    { 0 }, /* DRIVE_UNKNOWN */
-    { 0 }, /* DRIVE_NO_ROOT_DIR */
-    {'f','l','o','p','p','y',0}, /* DRIVE_REMOVABLE */
-    {'h','d',0}, /* DRIVE_FIXED */
-    {'n','e','t','w','o','r','k',0}, /* DRIVE_REMOTE */
-    {'c','d','r','o','m',0}, /* DRIVE_CDROM */
-    {'r','a','m','d','i','s','k',0} /* DRIVE_RAMDISK */
-};
-
-
-/* Known filesystem types */
-
-typedef struct
-{
-    const WCHAR name[6];
-    UINT      flags;
-} FS_DESCR;
-
-static const FS_DESCR DRIVE_Filesystems[] =
-{
-    { {'u','n','i','x',0}, DRIVE_CASE_SENSITIVE | DRIVE_CASE_PRESERVING },
-    { {'m','s','d','o','s',0}, DRIVE_SHORT_NAMES },
-    { {'d','o','s',0}, DRIVE_SHORT_NAMES },
-    { {'f','a','t',0}, DRIVE_SHORT_NAMES },
-    { {'v','f','a','t',0}, DRIVE_CASE_PRESERVING },
-    { {'w','i','n','9','5',0}, DRIVE_CASE_PRESERVING },
-    { { 0 }, 0 }
-};
-
-
-static DOSDRIVE DOSDrives[MAX_DOS_DRIVES];
 static int DRIVE_CurDrive = -1;
-
 static HTASK16 DRIVE_LastTask = 0;
-
-/* strdup on the process heap */
-inline static char *heap_strdup( const char *str )
-{
-    INT len = strlen(str) + 1;
-    LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
-    if (p) memcpy( p, str, len );
-    return p;
-}
-
-#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
-
-extern void CDROM_InitRegistry(int dev);
-
-/***********************************************************************
- *           DRIVE_GetDriveType
- */
-static inline UINT DRIVE_GetDriveType( INT drive, LPCWSTR value )
-{
-    int i;
-
-    for (i = 0; i < sizeof(DRIVE_Types)/sizeof(DRIVE_Types[0]); i++)
-    {
-        if (!strcmpiW( value, DRIVE_Types[i] )) return i;
-    }
-    MESSAGE("Drive %c: unknown drive type %s, defaulting to 'hd'.\n",
-            'A' + drive, debugstr_w(value) );
-    return DRIVE_FIXED;
-}
-
-
-/***********************************************************************
- *           DRIVE_GetFSFlags
- */
-static UINT DRIVE_GetFSFlags( INT drive, LPCWSTR value )
-{
-    const FS_DESCR *descr;
-
-    for (descr = DRIVE_Filesystems; *descr->name; descr++)
-        if (!strcmpiW( value, descr->name )) return descr->flags;
-    MESSAGE("Drive %c: unknown filesystem type %s, defaulting to 'win95'.\n",
-            'A' + drive, debugstr_w(value) );
-    return DRIVE_CASE_PRESERVING;
-}
-
-
 /* whether we set the =[A-Z]: environment variables when changing directories */
 static BOOL DRIVE_SetPerDriveEnv;
 
@@ -179,188 +86,8 @@
  */
 int DRIVE_Init(void)
 {
-    int i, len, count = 0;
-    WCHAR driveW[] = {'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','\\','D','r','i','v','e',' ','A',0};
-    WCHAR drive_env[] = {'=','A',':',0};
-    WCHAR path[MAX_PATHNAME_LEN];
-    char tmp[MAX_PATHNAME_LEN*sizeof(WCHAR) + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
-    struct stat drive_stat_buffer;
-    WCHAR *p;
-    DOSDRIVE *drive;
-    HKEY hkey;
-    DWORD dummy;
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING nameW;
-
-    static const WCHAR PathW[] = {'P','a','t','h',0};
-    static const WCHAR TypeW[] = {'T','y','p','e',0};
-    static const WCHAR FilesystemW[] = {'F','i','l','e','s','y','s','t','e','m',0};
-    static const WCHAR DeviceW[] = {'D','e','v','i','c','e',0};
-    static const WCHAR FailReadOnlyW[] = {'F','a','i','l','R','e','a','d','O','n','l','y',0};
-
-
-    attr.Length = sizeof(attr);
-    attr.RootDirectory = 0;
-    attr.ObjectName = &nameW;
-    attr.Attributes = 0;
-    attr.SecurityDescriptor = NULL;
-    attr.SecurityQualityOfService = NULL;
-
-    for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, drive++)
-    {
-        RtlInitUnicodeString( &nameW, driveW );
-        nameW.Buffer[(nameW.Length / sizeof(WCHAR)) - 1] = 'A' + i;
-        if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) continue;
-
-        /* Get the root path */
-        RtlInitUnicodeString( &nameW, PathW );
-        if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
-        {
-            WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
-            ExpandEnvironmentStringsW( data, path, sizeof(path)/sizeof(WCHAR) );
-
-            p = path + strlenW(path) - 1;
-            while ((p > path) && (*p == '/')) *p-- = '\0';
-
-            if (path[0] == '/')
-            {
-                len = WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL);
-                drive->root = HeapAlloc(GetProcessHeap(), 0, len);
-                WideCharToMultiByte(CP_UNIXCP, 0, path, -1, drive->root, len, NULL, NULL);
-            }
-            else
-            {
-                /* relative paths are relative to config dir */
-                const char *config = wine_get_config_dir();
-                len = strlen(config);
-                len += WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL) + 2;
-                drive->root = HeapAlloc( GetProcessHeap(), 0, len );
-                len -= sprintf( drive->root, "%s/", config );
-                WideCharToMultiByte(CP_UNIXCP, 0, path, -1,
-                                    drive->root + strlen(drive->root), len, NULL, NULL);
-            }
-
-            if (stat( drive->root, &drive_stat_buffer ))
-            {
-                MESSAGE("Could not stat %s (%s), ignoring drive %c:\n",
-                        drive->root, strerror(errno), 'A' + i);
-                HeapFree( GetProcessHeap(), 0, drive->root );
-                drive->root = NULL;
-                goto next;
-            }
-            if (!S_ISDIR(drive_stat_buffer.st_mode))
-            {
-                MESSAGE("%s is not a directory, ignoring drive %c:\n",
-                        drive->root, 'A' + i );
-                HeapFree( GetProcessHeap(), 0, drive->root );
-                drive->root = NULL;
-                goto next;
-            }
-
-            drive->dos_cwd  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(drive->dos_cwd[0]));
-            drive->unix_cwd = heap_strdup( "" );
-            drive->flags    = 0;
-            drive->dev      = drive_stat_buffer.st_dev;
-            drive->ino      = drive_stat_buffer.st_ino;
-
-            /* Get the drive type */
-            RtlInitUnicodeString( &nameW, TypeW );
-            if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
-            {
-                WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
-                drive->type = DRIVE_GetDriveType( i, data );
-            }
-            else drive->type = DRIVE_FIXED;
-
-            /* Get the filesystem type */
-            RtlInitUnicodeString( &nameW, FilesystemW );
-            if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
-            {
-                WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
-                drive->flags = DRIVE_GetFSFlags( i, data );
-            }
-            else drive->flags = DRIVE_CASE_PRESERVING;
-
-            /* Get the device */
-            RtlInitUnicodeString( &nameW, DeviceW );
-            if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
-            {
-                WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
-                char *device;
-
-                len = WideCharToMultiByte(CP_UNIXCP, 0, data, -1, NULL, 0, NULL, NULL);
-                device = HeapAlloc(GetProcessHeap(), 0, len);
-                WideCharToMultiByte(CP_UNIXCP, 0, data, -1, device, len, NULL, NULL);
-
-                if (drive->type == DRIVE_CDROM)
-                {
-                    int cd_fd;
-                    if ((cd_fd = open(device, O_RDONLY|O_NONBLOCK)) != -1)
-                    {
-                        CDROM_InitRegistry(cd_fd);
-                        close(cd_fd);
-                    }
-                }
-                HeapFree(GetProcessHeap(), 0, device);
-            }
-
-            /* Get the FailReadOnly flag */
-            RtlInitUnicodeString( &nameW, FailReadOnlyW );
-            if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
-            {
-                WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
-                if (IS_OPTION_TRUE(data[0])) drive->flags |= DRIVE_FAIL_READ_ONLY;
-            }
-
-            /* Make the first hard disk the current drive */
-            if ((DRIVE_CurDrive == -1) && (drive->type == DRIVE_FIXED))
-                DRIVE_CurDrive = i;
-
-            count++;
-            TRACE("Drive %c: path=%s type=%s flags=%08x dev=%x ino=%x\n",
-                  'A' + i, drive->root, debugstr_w(DRIVE_Types[drive->type]),
-                  drive->flags, (int)drive->dev, (int)drive->ino );
-        }
-
-    next:
-        NtClose( hkey );
-    }
-
-    if (!count)
-    {
-        MESSAGE("Warning: no valid DOS drive found, check your configuration file.\n" );
-        /* Create a C drive pointing to Unix root dir */
-        DOSDrives[2].root     = heap_strdup( "/" );
-        DOSDrives[2].dos_cwd  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSDrives[2].dos_cwd[0]));
-        DOSDrives[2].unix_cwd = heap_strdup( "" );
-        DOSDrives[2].type     = DRIVE_FIXED;
-        DOSDrives[2].flags    = 0;
-        DRIVE_CurDrive = 2;
-    }
-
-    /* Make sure the current drive is valid */
-    if (DRIVE_CurDrive == -1)
-    {
-        for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, drive++)
-        {
-            if (drive->root && !(drive->flags & DRIVE_DISABLED))
-            {
-                DRIVE_CurDrive = i;
-                break;
-            }
-        }
-    }
-
-    /* get current working directory info for all drives */
-    for (i = 0; i < MAX_DOS_DRIVES; i++, drive_env[1]++)
-    {
-        if (!GetEnvironmentVariableW(drive_env, path, MAX_PATHNAME_LEN)) continue;
-        /* sanity check */
-        if (toupperW(path[0]) != drive_env[1] || path[1] != ':') continue;
-        DRIVE_Chdir( i, path + 2 );
-    }
+    /* to TRUE when not emulating NT */
+    DRIVE_SetPerDriveEnv = (GetVersion() >= 0x80000000);
 
     /* temporary check to warn about
      * 1/ absence of device/drive directories
@@ -384,15 +111,15 @@
             {
                 MESSAGE("Your configuration file (%s/config) seems newer than\n"
                         "the device/drive directories (%s/device and %s/dosdevices).\n"
-                        "You should perhaps run tools/winefs in order to update the later.\n",
-                        pfx, pfx, pfx);
+                        "You should perhaps run 'tools/winefs --config-assign %s' in order to update the later.\n",
+                        pfx, pfx, pfx, pfx);
             }
         }
         else
         {
             MESSAGE("No device/drive directories files (%s/device and %s/dosdevices) found.\n"
-                    "You should run tools/winefs in order to create them\n",
-                    pfx, pfx);
+                    "You should run 'tools/winefs  --config-assign %s' in order to create them\n",
+                    pfx, pfx, pfx);
             exit(0);
         }
     } while (0);
@@ -404,11 +131,15 @@
 /***********************************************************************
  *           DRIVE_IsValid
  */
-int DRIVE_IsValid( int drive )
+static int DRIVE_IsValid( int drive )
 {
-    if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0;
-    return (DOSDrives[drive].root &&
-            !(DOSDrives[drive].flags & DRIVE_DISABLED));
+    struct stat st;
+    char tmp[MAX_PATH];
+
+    drive += 'a';
+    if ((drive < 'a') || (drive > 'z')) return 0;
+    sprintf(tmp, "%s/dosdevices/%c:", wine_get_config_dir(), drive);
+    return stat(tmp, &st) != -1 && S_ISDIR(st.st_mode);
 }
 
 
@@ -442,213 +173,6 @@
 
 
 /***********************************************************************
- *           DRIVE_FindDriveRoot
- *
- * Find a drive for which the root matches the beginning of the given path.
- * This can be used to translate a Unix path into a drive + DOS path.
- * Return value is the drive, or -1 on error. On success, path is modified
- * to point to the beginning of the DOS path.
- *
- * Note: path must be in the encoding of the underlying Unix file system.
- */
-int DRIVE_FindDriveRoot( const char **path )
-{
-    /* Starting with the full path, check if the device and inode match any of
-     * the wine 'drives'. If not then remove the last path component and try
-     * again. If the last component was a '..' then skip a normal component
-     * since it's a directory that's ascended back out of.
-     */
-    int drive, level, len;
-    char buffer[MAX_PATHNAME_LEN];
-    char *p;
-    struct stat st;
-
-    strcpy( buffer, *path );
-    for (p = buffer; *p; p++) if (*p == '\\') *p = '/';
-    len = p - buffer;
-
-    /* strip off trailing slashes */
-    while (len > 1 && buffer[len - 1] == '/') buffer[--len] = 0;
-
-    for (;;)
-    {
-        /* Find the drive */
-        if (stat( buffer, &st ) == 0 && S_ISDIR( st.st_mode ))
-        {
-            for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
-            {
-               if (!DOSDrives[drive].root ||
-                   (DOSDrives[drive].flags & DRIVE_DISABLED))
-                   continue;
-
-               if ((DOSDrives[drive].dev == st.st_dev) &&
-                   (DOSDrives[drive].ino == st.st_ino))
-               {
-                   if (len == 1) len = 0;  /* preserve root slash in returned path */
-                   TRACE( "%s -> drive %c:, root='%s', name='%s'\n",
-                       *path, 'A' + drive, buffer, *path + len);
-                   *path += len;
-                   if (!**path) *path = "\\";
-                   return drive;
-               }
-            }
-        }
-        if (len <= 1) return -1;  /* reached root */
-
-        level = 0;
-        while (level < 1)
-        {
-            /* find start of the last path component */
-            while (len > 1 && buffer[len - 1] != '/') len--;
-            if (!buffer[len]) break;  /* empty component -> reached root */
-            /* does removing it take us up a level? */
-            if (strcmp( buffer + len, "." ) != 0)
-                level += strcmp( buffer + len, ".." ) ? 1 : -1;
-            buffer[len] = 0;
-            /* strip off trailing slashes */
-            while (len > 1 && buffer[len - 1] == '/') buffer[--len] = 0;
-        }
-    }
-}
-
-
-/***********************************************************************
- *           DRIVE_FindDriveRootW
- *
- * Unicode version of DRIVE_FindDriveRoot.
- */
-int DRIVE_FindDriveRootW( LPCWSTR *path )
-{
-    int drive, level, len;
-    WCHAR buffer[MAX_PATHNAME_LEN];
-    WCHAR *p;
-    struct stat st;
-
-    strcpyW( buffer, *path );
-    for (p = buffer; *p; p++) if (*p == '\\') *p = '/';
-    len = p - buffer;
-
-    /* strip off trailing slashes */
-    while (len > 1 && buffer[len - 1] == '/') buffer[--len] = 0;
-
-    for (;;)
-    {
-        char buffA[MAX_PATHNAME_LEN];
-
-        WideCharToMultiByte( CP_UNIXCP, 0, buffer, -1, buffA, sizeof(buffA), NULL, NULL );
-        if (stat( buffA, &st ) == 0 && S_ISDIR( st.st_mode ))
-        {
-            /* Find the drive */
-            for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
-            {
-                if (!DOSDrives[drive].root ||
-                    (DOSDrives[drive].flags & DRIVE_DISABLED))
-                    continue;
-
-                if ((DOSDrives[drive].dev == st.st_dev) &&
-                    (DOSDrives[drive].ino == st.st_ino))
-                {
-                    static const WCHAR rootW[] = {'\\',0};
-
-                    if (len == 1) len = 0;  /* preserve root slash in returned path */
-                    TRACE( "%s -> drive %c:, root=%s, name=%s\n",
-                           debugstr_w(*path), 'A' + drive, debugstr_w(buffer), debugstr_w(*path + len));
-                    *path += len;
-                    if (!**path) *path = rootW;
-                    return drive;
-                }
-            }
-        }
-        if (len <= 1) return -1;  /* reached root */
-
-        level = 0;
-        while (level < 1)
-        {
-            static const WCHAR dotW[] = {'.',0};
-            static const WCHAR dotdotW[] = {'.','.',0};
-
-            /* find start of the last path component */
-            while (len > 1 && buffer[len - 1] != '/') len--;
-            if (!buffer[len]) break;  /* empty component -> reached root */
-            /* does removing it take us up a level? */
-            if (strcmpW( buffer + len, dotW ) != 0)
-                level += strcmpW( buffer + len, dotdotW ) ? 1 : -1;
-            buffer[len] = 0;
-            /* strip off trailing slashes */
-            while (len > 1 && buffer[len - 1] == '/') buffer[--len] = 0;
-        }
-    }
-}
-
-
-/***********************************************************************
- *           DRIVE_GetRoot
- */
-const char * DRIVE_GetRoot( int drive )
-{
-    if (!DRIVE_IsValid( drive )) return NULL;
-    return DOSDrives[drive].root;
-}
-
-
-/***********************************************************************
- *           DRIVE_GetDosCwd
- */
-LPCWSTR DRIVE_GetDosCwd( int drive )
-{
-    TDB *pTask = GlobalLock16(GetCurrentTask());
-    if (!DRIVE_IsValid( drive )) return NULL;
-
-    /* Check if we need to change the directory to the new task. */
-    if (pTask && (pTask->curdrive & 0x80) &&    /* The task drive is valid */
-        ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */
-        (DRIVE_LastTask != GetCurrentTask()))   /* and the task changed */
-    {
-        static const WCHAR rootW[] = {'\\',0};
-        WCHAR curdirW[MAX_PATH];
-        MultiByteToWideChar(CP_ACP, 0, pTask->curdir, -1, curdirW, MAX_PATH);
-        /* Perform the task-switch */
-        if (!DRIVE_Chdir( drive, curdirW )) DRIVE_Chdir( drive, rootW );
-        DRIVE_LastTask = GetCurrentTask();
-    }
-    return DOSDrives[drive].dos_cwd;
-}
-
-
-/***********************************************************************
- *           DRIVE_GetUnixCwd
- */
-const char * DRIVE_GetUnixCwd( int drive )
-{
-    TDB *pTask = GlobalLock16(GetCurrentTask());
-    if (!DRIVE_IsValid( drive )) return NULL;
-
-    /* Check if we need to change the directory to the new task. */
-    if (pTask && (pTask->curdrive & 0x80) &&    /* The task drive is valid */
-        ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */
-        (DRIVE_LastTask != GetCurrentTask()))   /* and the task changed */
-    {
-        static const WCHAR rootW[] = {'\\',0};
-        WCHAR curdirW[MAX_PATH];
-        MultiByteToWideChar(CP_ACP, 0, pTask->curdir, -1, curdirW, MAX_PATH);
-        /* Perform the task-switch */
-        if (!DRIVE_Chdir( drive, curdirW )) DRIVE_Chdir( drive, rootW );
-        DRIVE_LastTask = GetCurrentTask();
-    }
-    return DOSDrives[drive].unix_cwd;
-}
-
-
-/***********************************************************************
- *           DRIVE_GetFlags
- */
-UINT DRIVE_GetFlags( int drive )
-{
-    if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0;
-    return DOSDrives[drive].flags;
-}
-
-/***********************************************************************
  *           DRIVE_CheckDosCwd
  */
 void DRIVE_CheckDosCwd(void)
@@ -656,7 +180,7 @@
     TDB *pTask = GlobalLock16(GetCurrentTask());
     int drive = DRIVE_CurDrive;
 
-    if (!DRIVE_IsValid( 'A' + drive )) return;
+    if (!DRIVE_IsValid( drive )) return;
 
     /* Check if we need to change the directory to the new task. */
     if (pTask && (pTask->curdrive & 0x80) &&    /* The task drive is valid */
@@ -734,36 +258,6 @@
 
 
 /***********************************************************************
- *           DRIVE_Disable
- */
-int DRIVE_Disable( int drive  )
-{
-    if ((drive < 0) || (drive >= MAX_DOS_DRIVES) || !DOSDrives[drive].root)
-    {
-        SetLastError( ERROR_INVALID_DRIVE );
-        return 0;
-    }
-    DOSDrives[drive].flags |= DRIVE_DISABLED;
-    return 1;
-}
-
-
-/***********************************************************************
- *           DRIVE_Enable
- */
-int DRIVE_Enable( int drive  )
-{
-    if ((drive < 0) || (drive >= MAX_DOS_DRIVES) || !DOSDrives[drive].root)
-    {
-        SetLastError( ERROR_INVALID_DRIVE );
-        return 0;
-    }
-    DOSDrives[drive].flags &= ~DRIVE_DISABLED;
-    return 1;
-}
-
-
-/***********************************************************************
  *       DRIVE_GetCurrentDirectory
  * Returns "X:\\path\\etc\\".
  *
@@ -778,39 +272,6 @@
 
 
 /***********************************************************************
- *           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 )
@@ -908,7 +369,8 @@
 	return FALSE;
 
     /* FIXME: what about empty strings? Add a \\ ? */
-    if (!DRIVE_Chdir( drive, dir )) {
+    if (!DRIVE_Chdir( drive, dir ))
+    {
 	DRIVE_SetCurrentDrive(olddrive);
 	return FALSE;
     }
diff -u -N -r -x '*~' -x '.#*' -x CVS files48/file.c files/file.c
--- files48/file.c	2004-01-23 22:40:04.000000000 +0100
+++ files/file.c	2004-02-01 21:59:15.000000000 +0100
@@ -67,8 +67,6 @@
 #include "wine/winbase16.h"
 #include "wine/server.h"
 
-#include "drive.h"
-#include "file.h"
 #include "wincon.h"
 #include "kernel_private.h"
 
@@ -113,34 +111,6 @@
 
 
 /***********************************************************************
- *              FILE_strcasecmp
- *
- * locale-independent case conversion for file I/O
- */
-int FILE_strcasecmp( const char *str1, const char *str2 )
-{
-    int ret = 0;
-    for ( ; ; str1++, str2++)
-        if ((ret = FILE_toupper(*str1) - FILE_toupper(*str2)) || !*str1) break;
-    return ret;
-}
-
-
-/***********************************************************************
- *              FILE_strncasecmp
- *
- * locale-independent case conversion for file I/O
- */
-int FILE_strncasecmp( const char *str1, const char *str2, int len )
-{
-    int ret = 0;
-    for ( ; len > 0; len--, str1++, str2++)
-        if ((ret = FILE_toupper(*str1) - FILE_toupper(*str2)) || !*str1) break;
-    return ret;
-}
-
-
-/***********************************************************************
  *           FILE_SetDosError
  *
  * Set the DOS error code from errno.
diff -u -N -r -x '*~' -x '.#*' -x CVS files48/smb.c files/smb.c
--- files48/smb.c	2004-01-01 09:53:52.000000000 +0100
+++ files/smb.c	2004-02-01 22:01:09.000000000 +0100
@@ -108,10 +108,9 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winnls.h"
-#include "file.h"
-
-#include "smb.h"
+#include "winreg.h"
 #include "winternl.h"
+#include "smb.h"
 
 #include "wine/server.h"
 #include "wine/debug.h"


More information about the wine-patches mailing list