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.
This commit is contained in:
parent
8db4d73d89
commit
553a75e16e
|
@ -19,7 +19,6 @@ SPEC_SRCS16 = \
|
|||
|
||||
C_SRCS = \
|
||||
$(TOPOBJDIR)/files/directory.c \
|
||||
$(TOPOBJDIR)/files/drive.c \
|
||||
$(TOPOBJDIR)/files/file.c \
|
||||
$(TOPOBJDIR)/files/smb.c \
|
||||
$(TOPOBJDIR)/misc/options.c \
|
||||
|
|
|
@ -733,8 +733,8 @@ static BOOL process_init( char *argv[], char **environ )
|
|||
/* 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 @@ static BOOL process_init( char *argv[], char **environ )
|
|||
/* registry initialisation */
|
||||
SHELL_LoadRegistry();
|
||||
|
||||
/* Create device symlinks */
|
||||
VOLUME_CreateDevices();
|
||||
|
||||
/* global boot finished, the rest is process-local */
|
||||
SERVER_START_REQ( boot_done )
|
||||
{
|
||||
|
|
|
@ -167,35 +167,36 @@ static BOOL open_device_root( LPCWSTR root, HANDLE *handle )
|
|||
/* 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 @@ static UINT get_registry_drive_type( const WCHAR *root )
|
|||
|
||||
|
||||
/* 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 @@ void VOLUME_CreateDevices(void)
|
|||
}
|
||||
NtClose( hkey );
|
||||
}
|
||||
count += create_drives();
|
||||
count += create_drives( FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -351,13 +426,22 @@ void VOLUME_CreateDevices(void)
|
|||
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 );
|
||||
}
|
||||
|
|
|
@ -840,7 +840,7 @@ static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, ANSI_STRING *u
|
|||
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 @@ static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, ANSI_STRING *u
|
|||
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 (;;)
|
||||
{
|
||||
|
|
|
@ -4,35 +4,6 @@ WINE REGISTRY Version 2
|
|||
;; 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"
|
||||
|
|
|
@ -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 @@ consist of lines of the form
|
|||
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 @@ file, the registry files, and the DOS device mappings. The default is
|
|||
.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)
|
||||
|
|
|
@ -115,7 +115,8 @@ If set, the content of this variable is taken as the name of the directory where
|
|||
.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 @@ always as native.
|
|||
.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 @@ in the top-level directory of the source distribution.
|
|||
.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 @@ development, you might want to subscribe to the
|
|||
.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)
|
||||
|
|
|
@ -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 @@ int DIR_Init(void)
|
|||
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 @@ int DIR_Init(void)
|
|||
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 @@ int DIR_Init(void)
|
|||
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 */
|
||||
|
||||
|
|
397
files/drive.c
397
files/drive.c
|
@ -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;
|
||||
}
|
85
files/file.c
85
files/file.c
|
@ -174,78 +174,6 @@ void FILE_SetDosError(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* 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 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
|
|||
}
|
||||
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 )))
|
||||
{
|
||||
|
|
|
@ -33,13 +33,6 @@ extern void FILE_SetDosError(void);
|
|||
/* 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 );
|
||||
|
||||
|
|
|
@ -1833,6 +1833,59 @@ static void create_hardware_branch(void)
|
|||
}
|
||||
|
||||
|
||||
/* 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 @@ void SHELL_LoadRegistry( void )
|
|||
_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);
|
||||
|
|
Loading…
Reference in New Issue