Use symlinks in dosdevices/ for the drive devices too.
Store drive types in the registry instead of in the config file.
Added some more code to convert existing config to the new scheme.
diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in
index 688c497..0f88667 100644
--- a/dlls/kernel/Makefile.in
+++ b/dlls/kernel/Makefile.in
@@ -19,7 +19,6 @@
C_SRCS = \
$(TOPOBJDIR)/files/directory.c \
- $(TOPOBJDIR)/files/drive.c \
$(TOPOBJDIR)/files/file.c \
$(TOPOBJDIR)/files/smb.c \
$(TOPOBJDIR)/misc/options.c \
diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c
index 8ca5d1a..e5e3bd2 100644
--- a/dlls/kernel/process.c
+++ b/dlls/kernel/process.c
@@ -733,8 +733,8 @@
/* Parse command line arguments */
if (!info_size) OPTIONS_ParseOptions( argv );
- /* initialise DOS drives */
- if (!DRIVE_Init()) return FALSE;
+ /* Create device symlinks */
+ VOLUME_CreateDevices();
/* initialise DOS directories */
if (!DIR_Init()) return FALSE;
@@ -742,9 +742,6 @@
/* registry initialisation */
SHELL_LoadRegistry();
- /* Create device symlinks */
- VOLUME_CreateDevices();
-
/* global boot finished, the rest is process-local */
SERVER_START_REQ( boot_done )
{
diff --git a/dlls/kernel/volume.c b/dlls/kernel/volume.c
index 421398c2..153ef17 100644
--- a/dlls/kernel/volume.c
+++ b/dlls/kernel/volume.c
@@ -167,35 +167,36 @@
/* fetch the type of a drive from the registry */
static UINT get_registry_drive_type( const WCHAR *root )
{
+ static const WCHAR drive_types_keyW[] = {'M','a','c','h','i','n','e','\\',
+ 'S','o','f','t','w','a','r','e','\\',
+ 'W','i','n','e','\\',
+ 'D','r','i','v','e','s',0 };
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
HKEY hkey;
DWORD dummy;
UINT ret = DRIVE_UNKNOWN;
char tmp[32 + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
- WCHAR path[MAX_PATH];
- 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};
- static const WCHAR TypeW[] = {'T','y','p','e',0};
+ WCHAR driveW[] = {'A',':',0};
-
- if (!root)
- {
- GetCurrentDirectoryW( MAX_PATH, path );
- root = path;
- }
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString( &nameW, driveW );
- nameW.Buffer[(nameW.Length / sizeof(WCHAR)) - 1] = root[0];
+ RtlInitUnicodeString( &nameW, drive_types_keyW );
if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) return DRIVE_UNKNOWN;
- RtlInitUnicodeString( &nameW, TypeW );
+ if (root) driveW[0] = root[0];
+ else
+ {
+ WCHAR path[MAX_PATH];
+ GetCurrentDirectoryW( MAX_PATH, path );
+ driveW[0] = path[0];
+ }
+
+ RtlInitUnicodeString( &nameW, driveW );
if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
{
int i;
@@ -216,25 +217,99 @@
/* create symlinks for the DOS drives; helper for VOLUME_CreateDevices */
-static int create_drives(void)
+static int create_drives( int devices_only )
{
- WCHAR name[3], rootW[MAX_PATHNAME_LEN];
+ static const WCHAR PathW[] = {'P','a','t','h',0};
+ static const WCHAR DeviceW[] = {'D','e','v','i','c','e',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};
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+ char tmp[1024*sizeof(WCHAR) + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
+ char dest[1024];
+ WCHAR *p, name[3];
+ HKEY hkey;
+ DWORD dummy;
int i, count = 0;
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ /* create symlinks for the drive roots */
+
+ if (!devices_only) for (i = 0; i < 26; i++)
+ {
+ RtlInitUnicodeString( &nameW, driveW );
+ nameW.Buffer[(nameW.Length / sizeof(WCHAR)) - 1] = 'A' + i;
+ if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) continue;
+
+ RtlInitUnicodeString( &nameW, PathW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR path[1024];
+ 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';
+
+ name[0] = 'a' + i;
+ name[1] = ':';
+ name[2] = 0;
+
+ if (path[0] != '/')
+ {
+ /* relative paths are relative to config dir */
+ memmove( path + 3, path, (strlenW(path) + 1) * sizeof(WCHAR) );
+ path[0] = '.';
+ path[1] = '.';
+ path[2] = '/';
+ }
+ if (DefineDosDeviceW( DDD_RAW_TARGET_PATH, name, path ))
+ {
+ WideCharToMultiByte(CP_UNIXCP, 0, path, -1, dest, sizeof(dest), NULL, NULL);
+ MESSAGE( "Created symlink %s/dosdevices/%c: -> %s\n",
+ wine_get_config_dir(), 'a' + i, dest );
+ count++;
+ }
+ }
+ NtClose( hkey );
+ }
+
+ /* create symlinks for the drive devices */
+
for (i = 0; i < 26; i++)
{
- const char *root = DRIVE_GetRoot( i );
- if (!root) continue;
- name[0] = 'a' + i;
- name[1] = ':';
- name[2] = 0;
- if (MultiByteToWideChar( CP_UNIXCP, 0, root, -1, rootW, MAX_PATHNAME_LEN ) &&
- DefineDosDeviceW( DDD_RAW_TARGET_PATH, name, rootW ))
+ RtlInitUnicodeString( &nameW, driveW );
+ nameW.Buffer[(nameW.Length / sizeof(WCHAR)) - 1] = 'A' + i;
+ if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) continue;
+
+ RtlInitUnicodeString( &nameW, DeviceW );
+ if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
{
- MESSAGE( "Created symlink %s/dosdevices/%c: -> %s\n", wine_get_config_dir(), 'a' + i, root );
- count++;
+ char *path, *p;
+ WCHAR devname[] = {'A',':',':',0 };
+ WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ WideCharToMultiByte(CP_UNIXCP, 0, data, -1, dest, sizeof(dest), NULL, NULL);
+ path = get_dos_device_path( devname );
+ p = path + strlen(path);
+ p[-3] = 'a' + i;
+ if (!symlink( dest, path ))
+ {
+ MESSAGE( "Created symlink %s/dosdevices/%c:: -> %s\n",
+ wine_get_config_dir(), 'a' + i, dest );
+ count++;
+ }
+ HeapFree( GetProcessHeap(), 0, path );
}
+ NtClose( hkey );
}
+
return count;
}
@@ -336,7 +411,7 @@
}
NtClose( hkey );
}
- count += create_drives();
+ count += create_drives( FALSE );
}
else
{
@@ -351,13 +426,22 @@
buffer[strlen(buffer)-2] = 'a' + i;
if (!lstat( buffer, &st )) break;
}
- if (i == 26) count += create_drives();
+ if (i == 26) count += create_drives( FALSE );
+ else
+ {
+ strcat( buffer, ":" );
+ for (i = 0; i < 26; i++)
+ {
+ buffer[strlen(buffer)-3] = 'a' + i;
+ if (!lstat( buffer, &st )) break;
+ }
+ if (i == 26) count += create_drives( TRUE );
+ }
}
if (count)
- MESSAGE( "\nYou can now remove the [SerialPorts] and [ParallelPorts] sections\n"
- "in your configuration file, as well as the \"Path=\" definitions in\n"
- "the drive sections, they are replaced by the above symlinks.\n\n" );
+ MESSAGE( "\nYou can now remove the [SerialPorts], [ParallelPorts], and [Drive] sections\n"
+ "in your configuration file, they are replaced by the above symlinks.\n\n" );
HeapFree( GetProcessHeap(), 0, buffer );
}
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index bf6ac26..3e35eac 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -840,7 +840,7 @@
for (i = 0; i < name_len; i++)
if (name[i] <= 32 || name[i] >= 127) return STATUS_OBJECT_NAME_NOT_FOUND;
- unix_len = strlen(config_dir) + sizeof("/dosdevices/") + name_len;
+ unix_len = strlen(config_dir) + sizeof("/dosdevices/") + name_len + 1;
if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len )))
return STATUS_NO_MEMORY;
@@ -853,7 +853,11 @@
dev[i] = 0;
/* special case for drive devices */
- if (name_len == 2 && dev[1] == ':') dev[1] = '|';
+ if (name_len == 2 && dev[1] == ':')
+ {
+ dev[i++] = ':';
+ dev[i] = 0;
+ }
for (;;)
{
diff --git a/documentation/samples/config b/documentation/samples/config
index a56b1a0..2ca0562 100644
--- a/documentation/samples/config
+++ b/documentation/samples/config
@@ -4,35 +4,6 @@
;; If you think it is necessary to show others your complete config for a
;; bug report, filter out empty lines and comments with
;; grep -v "^;" ~/.wine/config | grep '.'
-;;
-;; MS-DOS drives configuration
-;;
-;; Each section has the following format:
-;; [Drive X]
-;; "Path"="xxx" (Unix path for drive root)
-;; "Type"="xxx" (supported types are 'floppy', 'hd', 'cdrom' and 'network')
-;; "Device"="/dev/xx" (only if you want to allow raw device access)
-;;
-[Drive A]
-"Type" = "floppy"
-"Device" = "/dev/fd0"
-
-[Drive C]
-"Type" = "hd"
-
-[Drive D]
-"Type" = "cdrom"
-; make sure that device is correct and has proper permissions !
-"Device" = "/dev/cdrom"
-
-[Drive E]
-"Type" = "hd"
-
-[Drive F]
-"Type" = "network"
-
-[Drive Z]
-"Type" = "hd"
[wine]
"Windows" = "c:\\windows"
diff --git a/documentation/wine.conf.man b/documentation/wine.conf.man
index 58df5eb..3b8c180 100644
--- a/documentation/wine.conf.man
+++ b/documentation/wine.conf.man
@@ -1,5 +1,5 @@
.\" -*- nroff -*-
-.TH WINE.CONF 5 "September 2003" "Version 20030911" "Wine Configuration File"
+.TH WINE.CONF 5 "April 2004" "Version 20040408" "Wine Configuration File"
.SH NAME
wine.conf \- Wine configuration file
.SH DESCRIPTION
@@ -24,42 +24,12 @@
The entry and value can be any text strings, included in double
quotes; it can also contain references to environment variables
surrounded by
-.I ${}.
+.I %
+signs.
Inside the double quotes, special characters, backslashes and quotes
must be escaped with backslashes. Supported section names and entries
are listed below.
.PP
-.B [Drive X]
-.br
-This section is used to specify the root directory and type of each emulated
-.B DOS
-drive, since most Windows applications require a DOS/MS-Windows based
-disk drive & directory scheme, which is either provided by a real
-DOS partition mounted somewhere or by some carefully crafted directory layout
-on a Unix file system ("no-windows fake installation").
-There is one such section for every drive you want to configure.
-.PP
-.I format: """Path""=""<rootdirectory>"""
-.br
-default: none
-.br
-If you mounted your dos partition as
-.I /dos
-and installed Microsoft Windows in
-C:\\WINDOWS (thus it shows up as /dos/WINDOWS), then you should specify
-.I """Path""=""/dos"""
-in the
-.I [Drive C]
-section in order to configure /dos as the drive root of drive C:.
-.PP
-.I format: """Type""=""<type>"""
-.br
-default: "hd"
-.br
-Used to specify the drive type this drive appears as in Windows
-or DOS programs; supported types are "floppy", "hd", "cdrom"
-and "network".
-.PP
.B [wine]
.br
.I format: """windows""=""<directory>"""
@@ -331,11 +301,5 @@
.TP
.I $WINEPREFIX/config
User-specific configuration file
-.TP
-.I $WINEPREFIX/dosdevices
-Directory containing the DOS device mappings. Each file in that
-directory is a symlink to the Unix device file implementing a given
-device. For instance, if COM1 is mapped to /dev/ttyS0 you'd have a
-symlink of the form $WINEPREFIX/dosdevices/com1 -> /dev/ttyS0.
.SH "SEE ALSO"
.BR wine (1)
diff --git a/documentation/wine.man.in b/documentation/wine.man.in
index 8f28b8e..f19b298 100644
--- a/documentation/wine.man.in
+++ b/documentation/wine.man.in
@@ -115,7 +115,8 @@
.B wine
stores its data (the default is
.I $HOME/.wine
-). This directory contains also the socket, which is used to communicate with the
+). This directory is also used to identify the socket which is used to
+communicate with the
.I wineserver.
All
.B wine
@@ -254,18 +255,59 @@
.TP
.I DISPLAY
Specifies the X11 display to use.
-.SH CONFIGURATION FILE
-.B wine
-expects a configuration file (
+.SH FILES
+.TP
+.I @bindir@/wine
+The
+.B wine
+program loader.
+.TP
+.I @bindir@/wineconsole
+The
+.B wine
+program loader for CUI (console) applications.
+.TP
+.I @bindir@/wineserver
+The
+.B wine
+server
+.TP
+.I @bindir@/winedbg
+The
+.B wine
+debugger
+.TP
+.I @bindir@/wineclipsrv
+The
+.B wine
+clipboard server
+.TP
+.I @dlldir@
+Directory containing
+.B wine's
+shared libraries
+.TP
.I $WINEPREFIX/config
-or
-.I ~/.wine/config
-if WINEPREFIX is not set), which must conform to the format specified
+User-specific configuration file, which must conform to the format specified
in the
.BR wine.conf (5)
man page. A sample configuration file is documentation/samples/config in the
.B wine
source archive.
+.TP
+.I $WINEPREFIX/dosdevices
+Directory containing the DOS device mappings. Each file in that
+directory is a symlink to the Unix device file implementing a given
+device. For instance, if COM1 is mapped to /dev/ttyS0 you'd have a
+symlink of the form $WINEPREFIX/dosdevices/com1 -> /dev/ttyS0.
+.br
+DOS drives are also specified with symlinks; for instance if drive D:
+corresponds to the CDROM mounted at /mnt/cdrom, you'd have a symlink
+$WINEPREFIX/dosdevices/d: -> /mnt/cdrom. The Unix device corresponding
+to a DOS drive can be specified the same way, except with '::' instead
+of ':'. So for the previous example, if the CDROM device is mounted
+from /dev/hdc, the corresponding symlink would be
+$WINEPREFIX/dosdevices/d:: -> /dev/hdc.
.SH AUTHORS
.B wine
is available thanks to the work of many developers. For a listing
@@ -276,7 +318,7 @@
.B wine
can be distributed under the terms of the LGPL license. A copy of the
license is in the file
-.B LICENSE
+.B COPYING.LIB
in the top-level directory of the source distribution.
.SH BUGS
.PP
@@ -326,45 +368,6 @@
.B wine
mailing lists at
.I http://www.winehq.org/forums
-.SH FILES
-.PD 0
-.TP
-.I @bindir@/wine
-The
-.B wine
-program loader.
-.TP
-.I @bindir@/wineconsole
-The
-.B wine
-program loader for CUI (console) applications.
-.TP
-.I @bindir@/wineserver
-The
-.B wine
-server
-.TP
-.I @bindir@/winedbg
-The
-.B wine
-debugger
-.TP
-.I @bindir@/wineclipsrv
-The
-.B wine
-clipboard server
-.TP
-.I @dlldir@
-Directory containing
-.B wine's
-shared libraries
-.TP
-.I ~/.wine/config
-User-specific configuration file
-.TP
-.I ~/.wine
-Directory containing user specific data managed by
-.B wine.
.SH "SEE ALSO"
.BR wine.conf (5)
diff --git a/files/directory.c b/files/directory.c
index 92fe9f0..26b8776 100644
--- a/files/directory.c
+++ b/files/directory.c
@@ -44,6 +44,7 @@
#include "winerror.h"
#include "winreg.h"
#include "winternl.h"
+#include "thread.h"
#include "wine/unicode.h"
#include "file.h"
#include "wine/debug.h"
@@ -108,8 +109,6 @@
char path[MAX_PATHNAME_LEN];
WCHAR longpath[MAX_PATHNAME_LEN];
WCHAR *tmp_dir, *profile_dir;
- int drive;
- const char *cwd;
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','\\',
@@ -135,28 +134,6 @@
static const WCHAR comspecW[] = {'C','O','M','S','P','E','C',0};
static const WCHAR empty_strW[] = { 0 };
- if (!getcwd( path, MAX_PATHNAME_LEN ))
- {
- perror( "Could not get current directory" );
- return 0;
- }
- cwd = path;
- if ((drive = DRIVE_FindDriveRoot( &cwd )) == -1)
- {
- MESSAGE("Warning: could not find wine config [Drive x] entry "
- "for current working directory %s; "
- "starting in windows directory.\n", cwd );
- }
- else
- {
- longpath[0] = 'a' + drive;
- longpath[1] = ':';
- MultiByteToWideChar(CP_UNIXCP, 0, cwd, -1, longpath + 2, MAX_PATHNAME_LEN);
- SetCurrentDirectoryW( longpath );
- if(GetDriveTypeW(longpath)==DRIVE_CDROM)
- chdir("/"); /* change to root directory so as not to lock cdroms */
- }
-
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &nameW;
@@ -175,7 +152,25 @@
return 0;
}
- if (drive == -1) SetCurrentDirectoryW( DIR_Windows );
+ if (!getcwd( path, MAX_PATHNAME_LEN ))
+ {
+ MESSAGE("Warning: could not get current Unix working directory, "
+ "starting in the Windows directory.\n" );
+ SetCurrentDirectoryW( DIR_Windows );
+ }
+ else
+ {
+ MultiByteToWideChar( CP_UNIXCP, 0, path, -1, longpath, MAX_PATHNAME_LEN);
+ GetFullPathNameW( longpath, MAX_PATHNAME_LEN, longpath, NULL );
+ if (!SetCurrentDirectoryW( longpath ))
+ {
+ MESSAGE("Warning: could not find DOS drive for current working directory '%s', "
+ "starting in the Windows directory.\n", path );
+ SetCurrentDirectoryW( DIR_Windows );
+ }
+ else if (!NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle)
+ chdir("/"); /* change to root directory so as not to lock cdroms */
+ }
/* Set the environment variables */
diff --git a/files/drive.c b/files/drive.c
deleted file mode 100644
index 94a56cf..0000000
--- a/files/drive.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * DOS drives handling functions
- *
- * Copyright 1993 Erik Bos
- * Copyright 1996 Alexandre Julliard
- *
- * Label & serial number read support.
- * (c) 1999 Petr Tomasek <tomasek@etf.cuni.cz>
- * (c) 2000 Andreas Mohr (changes)
- *
- * 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 "wine/port.h"
-
-#include <assert.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-#include "ntstatus.h"
-#include "windef.h"
-#include "winbase.h"
-#include "winreg.h"
-#include "winternl.h"
-#include "wine/winbase16.h" /* for GetCurrentTask */
-#include "winerror.h"
-#include "winioctl.h"
-#include "ntddstor.h"
-#include "ntddcdrm.h"
-#include "file.h"
-#include "wine/unicode.h"
-#include "wine/library.h"
-#include "wine/server.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(dosfs);
-WINE_DECLARE_DEBUG_CHANNEL(file);
-
-typedef struct
-{
- char *root; /* root dir in Unix format without trailing / */
- char *device; /* raw device path */
- dev_t dev; /* unix device number */
- ino_t ino; /* unix inode number */
-} DOSDRIVE;
-
-
-#define MAX_DOS_DRIVES 26
-
-static DOSDRIVE DOSDrives[MAX_DOS_DRIVES];
-
-/* 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;
-}
-
-/***********************************************************************
- * DRIVE_Init
- */
-int DRIVE_Init(void)
-{
- int i, len, symlink_count = 0, 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 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;
- char *root;
- const char *config_dir = wine_get_config_dir();
-
- static const WCHAR PathW[] = {'P','a','t','h',0};
- static const WCHAR DeviceW[] = {'D','e','v','i','c','e',0};
-
- attr.Length = sizeof(attr);
- attr.RootDirectory = 0;
- attr.ObjectName = &nameW;
- attr.Attributes = 0;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
-
- /* get the root of the drives from symlinks */
-
- root = NULL;
- for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, drive++)
- {
- if (!root)
- {
- root = HeapAlloc( GetProcessHeap(), 0, strlen(config_dir) + sizeof("/dosdevices/a:") );
- strcpy( root, config_dir );
- strcat( root, "/dosdevices/a:" );
- }
- root[strlen(root)-2] = 'a' + i;
- if (stat( root, &drive_stat_buffer ))
- {
- if (!lstat( root, &drive_stat_buffer))
- MESSAGE("Could not stat %s (%s), ignoring drive %c:\n",
- root, strerror(errno), 'a' + i);
- continue;
- }
- if (!S_ISDIR(drive_stat_buffer.st_mode))
- {
- MESSAGE("%s is not a directory, ignoring drive %c:\n", root, 'a' + i );
- continue;
- }
- drive->root = root;
- drive->device = NULL;
- drive->dev = drive_stat_buffer.st_dev;
- drive->ino = drive_stat_buffer.st_ino;
- root = NULL;
- symlink_count++;
- }
- if (root) HeapFree( GetProcessHeap(), 0, root );
-
- /* now get the parameters from the config file */
-
- 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 */
- if (!symlink_count)
- {
- 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->device = NULL;
- drive->dev = drive_stat_buffer.st_dev;
- drive->ino = drive_stat_buffer.st_ino;
- }
- }
-
- if (drive->root)
- {
- /* Get the device */
- RtlInitUnicodeString( &nameW, DeviceW );
- if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
- {
- WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
- len = WideCharToMultiByte(CP_UNIXCP, 0, data, -1, NULL, 0, NULL, NULL);
- drive->device = HeapAlloc(GetProcessHeap(), 0, len);
- WideCharToMultiByte(CP_UNIXCP, 0, data, -1, drive->device, len, NULL, NULL);
- }
-
- count++;
- TRACE("Drive %c: path=%s dev=%x ino=%x\n",
- 'A' + i, drive->root, (int)drive->dev, (int)drive->ino );
- }
-
- next:
- NtClose( hkey );
- }
- return 1;
-}
-
-
-/***********************************************************************
- * DRIVE_IsValid
- */
-int DRIVE_IsValid( int drive )
-{
- if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0;
- return (DOSDrives[drive].root != NULL);
-}
-
-
-/***********************************************************************
- * 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) 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) 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_GetDevice
- */
-const char * DRIVE_GetDevice( int drive )
-{
- return (DRIVE_IsValid( drive )) ? DOSDrives[drive].device : NULL;
-}
diff --git a/files/file.c b/files/file.c
index 3752c59..138c503 100644
--- a/files/file.c
+++ b/files/file.c
@@ -174,78 +174,6 @@
}
-/***********************************************************************
- * FILE_CreateFile
- *
- * Implementation of CreateFile. Takes a Unix path name.
- * Returns 0 on failure.
- */
-HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
- LPSECURITY_ATTRIBUTES sa, DWORD creation,
- DWORD attributes, HANDLE template )
-{
- unsigned int err;
- UINT disp, options;
- HANDLE ret;
-
- switch (creation)
- {
- case CREATE_ALWAYS: disp = FILE_OVERWRITE_IF; break;
- case CREATE_NEW: disp = FILE_CREATE; break;
- case OPEN_ALWAYS: disp = FILE_OPEN_IF; break;
- case OPEN_EXISTING: disp = FILE_OPEN; break;
- case TRUNCATE_EXISTING: disp = FILE_OVERWRITE; break;
- default:
- SetLastError( ERROR_INVALID_PARAMETER );
- return 0;
- }
-
- options = 0;
- if (attributes & FILE_FLAG_BACKUP_SEMANTICS)
- options |= FILE_OPEN_FOR_BACKUP_INTENT;
- else
- options |= FILE_NON_DIRECTORY_FILE;
- if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
- options |= FILE_DELETE_ON_CLOSE;
- if (!(attributes & FILE_FLAG_OVERLAPPED))
- options |= FILE_SYNCHRONOUS_IO_ALERT;
- if (attributes & FILE_FLAG_RANDOM_ACCESS)
- options |= FILE_RANDOM_ACCESS;
- attributes &= FILE_ATTRIBUTE_VALID_FLAGS;
-
- SERVER_START_REQ( create_file )
- {
- req->access = access;
- req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
- req->sharing = sharing;
- req->create = disp;
- req->options = options;
- req->attrs = attributes;
- wine_server_add_data( req, filename, strlen(filename) );
- SetLastError(0);
- err = wine_server_call( req );
- ret = reply->handle;
- }
- SERVER_END_REQ;
-
- if (err)
- {
- /* In the case file creation was rejected due to CREATE_NEW flag
- * was specified and file with that name already exists, correct
- * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
- * Note: RtlNtStatusToDosError is not the subject to blame here.
- */
- if (err == STATUS_OBJECT_NAME_COLLISION)
- SetLastError( ERROR_FILE_EXISTS );
- else
- SetLastError( RtlNtStatusToDosError(err) );
- }
-
- if (!ret) WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
- return ret;
-}
-
-
static HANDLE FILE_OpenPipe(LPCWSTR name, DWORD access, LPSECURITY_ATTRIBUTES sa )
{
HANDLE ret;
@@ -368,18 +296,7 @@
}
else if (isalphaW(filename[4]) && filename[5] == ':' && filename[6] == '\0')
{
- const char *device = DRIVE_GetDevice( toupperW(filename[4]) - 'A' );
- if (device)
- {
- ret = FILE_CreateFile( device, access, sharing, sa, creation,
- attributes, template );
- }
- else
- {
- SetLastError( ERROR_ACCESS_DENIED );
- return INVALID_HANDLE_VALUE;
- }
- goto done;
+ dosdev = 0;
}
else if ((dosdev = RtlIsDosDeviceName_U( filename + 4 )))
{
diff --git a/include/file.h b/include/file.h
index 8c4a7b2..b234399 100644
--- a/include/file.h
+++ b/include/file.h
@@ -33,13 +33,6 @@
/* files/directory.c */
extern int DIR_Init(void);
-/* drive.c */
-extern int DRIVE_Init(void);
-extern int DRIVE_FindDriveRoot( const char **path );
-extern int DRIVE_FindDriveRootW( LPCWSTR *path );
-extern const char * DRIVE_GetRoot( int drive );
-extern const char * DRIVE_GetDevice( int drive );
-
/* vxd.c */
extern HANDLE VXD_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa );
diff --git a/misc/registry.c b/misc/registry.c
index 3835bf9..1c8d4e2 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -1833,6 +1833,59 @@
}
+/* convert the drive type entries from the old format to the new one */
+static void convert_drive_types(void)
+{
+ static const WCHAR TypeW[] = {'T','y','p','e',0};
+ static const WCHAR drive_types_keyW[] = {'M','a','c','h','i','n','e','\\',
+ 'S','o','f','t','w','a','r','e','\\',
+ 'W','i','n','e','\\',
+ 'D','r','i','v','e','s',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};
+ char tmp[32*sizeof(WCHAR) + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+ DWORD dummy;
+ ULONG disp;
+ HKEY hkey_old, hkey_new;
+ int i;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ 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;
+
+ for (i = 0; i < 26; i++)
+ {
+ RtlInitUnicodeString( &nameW, driveW );
+ nameW.Buffer[(nameW.Length / sizeof(WCHAR)) - 1] = 'A' + i;
+ if (NtOpenKey( &hkey_old, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) continue;
+ RtlInitUnicodeString( &nameW, TypeW );
+ if (!NtQueryValueKey( hkey_old, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
+ {
+ WCHAR valueW[] = {'A',':',0};
+ WCHAR *type = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+
+ valueW[0] = 'A' + i;
+ RtlInitUnicodeString( &nameW, valueW );
+ NtSetValueKey( hkey_new, &nameW, 0, REG_SZ, type, (strlenW(type) + 1) * sizeof(WCHAR) );
+ MESSAGE( "Converted drive type to new entry HKLM\\Software\\Wine\\Drives \"%c:\" = %s\n",
+ 'A' + i, debugstr_w(type) );
+ }
+ NtClose( hkey_old );
+ }
+ NtClose( hkey_new );
+}
+
+
/* load all registry (native and global and home) */
void SHELL_LoadRegistry( void )
{
@@ -2002,6 +2055,10 @@
_save_at_exit(hkey_users_default,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
}
+ /* convert keys from config file to new registry format */
+
+ convert_drive_types();
+
NtClose(hkey_users_default);
NtClose(hkey_current_user);
NtClose(hkey_users);