ChangeSet ID: 12187 CVSROOT: /opt/cvs-commit Module name: wine Changes by: julliard@wine.codeweavers.com 2004/04/28 19:27:57 Modified files: misc : registry.c include : file.h files : file.c directory.c documentation/samples: config documentation : wine.man.in wine.conf.man dlls/ntdll : directory.c dlls/kernel : volume.c process.c Makefile.in Removed files: files : drive.c Log message: 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. Patch: http://cvs.winehq.org/patch.py?id=12187 Old revision New revision Changes Path 1.139 1.140 +57 -0 wine/misc/registry.c 1.74 1.75 +0 -7 wine/include/file.h 1.228 1.229 +1 -84 wine/files/file.c 1.79 1.80 +20 -25 wine/files/directory.c 1.62 1.63 +0 -29 wine/documentation/samples/config 1.51 1.52 +50 -47 wine/documentation/wine.man.in 1.18 1.19 +3 -39 wine/documentation/wine.conf.man 1.11 1.12 +6 -2 wine/dlls/ntdll/directory.c 1.12 1.13 +114 -30 wine/dlls/kernel/volume.c 1.55 1.56 +2 -5 wine/dlls/kernel/process.c 1.108 1.109 +0 -1 wine/dlls/kernel/Makefile.in 1.119 Removed +0 -0 wine/files/drive.c Index: wine/misc/registry.c diff -u -p wine/misc/registry.c:1.139 wine/misc/registry.c:1.140 --- wine/misc/registry.c:1.139 Fri May 24 22:29:08 2013 +++ wine/misc/registry.c Fri May 24 22:29:08 2013 @@ -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); Index: wine/include/file.h diff -u -p wine/include/file.h:1.74 wine/include/file.h:1.75 --- wine/include/file.h:1.74 Fri May 24 22:29:08 2013 +++ wine/include/file.h Fri May 24 22:29:08 2013 @@ -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 ); Index: wine/files/file.c diff -u -p wine/files/file.c:1.228 wine/files/file.c:1.229 --- wine/files/file.c:1.228 Fri May 24 22:29:08 2013 +++ wine/files/file.c Fri May 24 22:29:08 2013 @@ -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 filen } 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 ))) { Index: wine/files/directory.c diff -u -p wine/files/directory.c:1.79 wine/files/directory.c:1.80 --- wine/files/directory.c:1.79 Fri May 24 22:29:08 2013 +++ wine/files/directory.c Fri May 24 22:29:08 2013 @@ -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 */ Index: wine/documentation/samples/config diff -u -p wine/documentation/samples/config:1.62 wine/documentation/samples/config:1.63 --- wine/documentation/samples/config:1.62 Fri May 24 22:29:08 2013 +++ wine/documentation/samples/config Fri May 24 22:29:08 2013 @@ -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" Index: wine/documentation/wine.man.in diff -u -p wine/documentation/wine.man.in:1.51 wine/documentation/wine.man.in:1.52 --- wine/documentation/wine.man.in:1.51 Fri May 24 22:29:08 2013 +++ wine/documentation/wine.man.in Fri May 24 22:29:08 2013 @@ -115,7 +115,8 @@ If set, the content of this variable is .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 .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 .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) Index: wine/documentation/wine.conf.man diff -u -p wine/documentation/wine.conf.man:1.18 wine/documentation/wine.conf.man:1.19 --- wine/documentation/wine.conf.man:1.18 Fri May 24 22:29:08 2013 +++ wine/documentation/wine.conf.man Fri May 24 22:29:08 2013 @@ -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""=""""" -.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""=""""" -.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""=""""" @@ -331,11 +301,5 @@ file, the registry files, and the DOS de .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) Index: wine/dlls/ntdll/directory.c diff -u -p wine/dlls/ntdll/directory.c:1.11 wine/dlls/ntdll/directory.c:1.12 --- wine/dlls/ntdll/directory.c:1.11 Fri May 24 22:29:08 2013 +++ wine/dlls/ntdll/directory.c Fri May 24 22:29:08 2013 @@ -840,7 +840,7 @@ static NTSTATUS get_dos_device( const WC 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 WC 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 (;;) { Index: wine/dlls/kernel/volume.c diff -u -p wine/dlls/kernel/volume.c:1.12 wine/dlls/kernel/volume.c:1.13 --- wine/dlls/kernel/volume.c:1.12 Fri May 24 22:29:08 2013 +++ wine/dlls/kernel/volume.c Fri May 24 22:29:08 2013 @@ -167,35 +167,36 @@ static BOOL open_device_root( LPCWSTR ro /* 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( con /* 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 ); } Index: wine/dlls/kernel/process.c diff -u -p wine/dlls/kernel/process.c:1.55 wine/dlls/kernel/process.c:1.56 --- wine/dlls/kernel/process.c:1.55 Fri May 24 22:29:08 2013 +++ wine/dlls/kernel/process.c Fri May 24 22:29:08 2013 @@ -733,8 +733,8 @@ static BOOL process_init( char *argv[], /* 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[], /* registry initialisation */ SHELL_LoadRegistry(); - /* Create device symlinks */ - VOLUME_CreateDevices(); - /* global boot finished, the rest is process-local */ SERVER_START_REQ( boot_done ) { Index: wine/dlls/kernel/Makefile.in diff -u -p wine/dlls/kernel/Makefile.in:1.108 wine/dlls/kernel/Makefile.in:1.109 --- wine/dlls/kernel/Makefile.in:1.108 Fri May 24 22:29:08 2013 +++ wine/dlls/kernel/Makefile.in Fri May 24 22:29:08 2013 @@ -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 \ Index: wine/files/drive.c diff -u -p wine/files/drive.c:1.119 /dev/null --- wine/files/drive.c Fri May 24 22:29:08 2013 +++ /dev/null Fri May 24 22:29:08 2013 @@ -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 - * (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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#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; -}