Commit 0701b074 authored by Alexandre Julliard's avatar Alexandre Julliard

Get the drive root directories from the symlinks in dosdevices/ if

they exist. Added creation of drive symlinks in the device transition code.
parent 21e5909a
...@@ -148,6 +148,30 @@ static char *get_dos_device_path( LPCWSTR name ) ...@@ -148,6 +148,30 @@ static char *get_dos_device_path( LPCWSTR name )
} }
/* create symlinks for the DOS drives; helper for VOLUME_CreateDevices */
static int create_drives(void)
{
WCHAR name[3], rootW[MAX_PATHNAME_LEN];
int i, count = 0;
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 ))
{
MESSAGE( "Created symlink %s/dosdevices/%c: -> %s\n", wine_get_config_dir(), 'a' + i, root );
count++;
}
}
return count;
}
/*********************************************************************** /***********************************************************************
* VOLUME_CreateDevices * VOLUME_CreateDevices
* *
...@@ -161,7 +185,7 @@ void VOLUME_CreateDevices(void) ...@@ -161,7 +185,7 @@ void VOLUME_CreateDevices(void)
int i, count = 0; int i, count = 0;
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, if (!(buffer = HeapAlloc( GetProcessHeap(), 0,
strlen(config_dir) + sizeof("/dosdevices") ))) strlen(config_dir) + sizeof("/dosdevices") + 3 )))
return; return;
strcpy( buffer, config_dir ); strcpy( buffer, config_dir );
...@@ -245,10 +269,29 @@ void VOLUME_CreateDevices(void) ...@@ -245,10 +269,29 @@ void VOLUME_CreateDevices(void)
} }
NtClose( hkey ); NtClose( hkey );
} }
if (count) count += create_drives();
MESSAGE( "\nYou can now remove the [SerialPorts] and [ParallelPorts] sections\n"
"in your configuration file, they are replaced by the above symlinks.\n\n" );
} }
else
{
struct stat st;
int i;
/* it is possible that the serial/parallel devices have been created but */
/* not the drives; check for at least one drive symlink to catch that case */
strcat( buffer, "/a:" );
for (i = 0; i < 26; i++)
{
buffer[strlen(buffer)-2] = 'a' + i;
if (!lstat( buffer, &st )) break;
}
if (i == 26) count += create_drives();
}
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" );
HeapFree( GetProcessHeap(), 0, buffer ); HeapFree( GetProcessHeap(), 0, buffer );
} }
......
...@@ -130,7 +130,7 @@ static inline UINT DRIVE_GetDriveType( INT drive, LPCWSTR value ) ...@@ -130,7 +130,7 @@ static inline UINT DRIVE_GetDriveType( INT drive, LPCWSTR value )
*/ */
int DRIVE_Init(void) int DRIVE_Init(void)
{ {
int i, len, count = 0; 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','\\', 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','\\', 'W','i','n','e','\\','W','i','n','e','\\',
'C','o','n','f','i','g','\\','D','r','i','v','e',' ','A',0}; 'C','o','n','f','i','g','\\','D','r','i','v','e',' ','A',0};
...@@ -144,6 +144,8 @@ int DRIVE_Init(void) ...@@ -144,6 +144,8 @@ int DRIVE_Init(void)
DWORD dummy; DWORD dummy;
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW; 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 PathW[] = {'P','a','t','h',0};
static const WCHAR TypeW[] = {'T','y','p','e',0}; static const WCHAR TypeW[] = {'T','y','p','e',0};
...@@ -157,6 +159,45 @@ int DRIVE_Init(void) ...@@ -157,6 +159,45 @@ int DRIVE_Init(void)
attr.SecurityDescriptor = NULL; attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = 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->dos_cwd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(drive->dos_cwd[0]));
drive->unix_cwd = heap_strdup( "" );
drive->device = NULL;
drive->flags = 0;
drive->dev = drive_stat_buffer.st_dev;
drive->ino = drive_stat_buffer.st_ino;
drive->type = DRIVE_FIXED;
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++) for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, drive++)
{ {
RtlInitUnicodeString( &nameW, driveW ); RtlInitUnicodeString( &nameW, driveW );
...@@ -164,57 +205,64 @@ int DRIVE_Init(void) ...@@ -164,57 +205,64 @@ int DRIVE_Init(void)
if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) continue; if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) continue;
/* Get the root path */ /* Get the root path */
RtlInitUnicodeString( &nameW, PathW ); if (!symlink_count)
if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
{ {
WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data; RtlInitUnicodeString( &nameW, PathW );
ExpandEnvironmentStringsW( data, path, sizeof(path)/sizeof(WCHAR) ); 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; p = path + strlenW(path) - 1;
while ((p > path) && (*p == '/')) *p-- = '\0'; while ((p > path) && (*p == '/')) *p-- = '\0';
if (path[0] == '/') if (path[0] == '/')
{ {
len = WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL); len = WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL);
drive->root = HeapAlloc(GetProcessHeap(), 0, len); drive->root = HeapAlloc(GetProcessHeap(), 0, len);
WideCharToMultiByte(CP_UNIXCP, 0, path, -1, drive->root, len, NULL, NULL); WideCharToMultiByte(CP_UNIXCP, 0, path, -1, drive->root, len, NULL, NULL);
} }
else else
{ {
/* relative paths are relative to config dir */ /* relative paths are relative to config dir */
const char *config = wine_get_config_dir(); const char *config = wine_get_config_dir();
len = strlen(config); len = strlen(config);
len += WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL) + 2; len += WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL) + 2;
drive->root = HeapAlloc( GetProcessHeap(), 0, len ); drive->root = HeapAlloc( GetProcessHeap(), 0, len );
len -= sprintf( drive->root, "%s/", config ); len -= sprintf( drive->root, "%s/", config );
WideCharToMultiByte(CP_UNIXCP, 0, path, -1, WideCharToMultiByte(CP_UNIXCP, 0, path, -1,
drive->root + strlen(drive->root), len, NULL, NULL); drive->root + strlen(drive->root), len, NULL, NULL);
} }
if (stat( drive->root, &drive_stat_buffer )) if (stat( drive->root, &drive_stat_buffer ))
{ {
MESSAGE("Could not stat %s (%s), ignoring drive %c:\n", MESSAGE("Could not stat %s (%s), ignoring drive %c:\n",
drive->root, strerror(errno), 'A' + i); drive->root, strerror(errno), 'A' + i);
HeapFree( GetProcessHeap(), 0, drive->root ); HeapFree( GetProcessHeap(), 0, drive->root );
drive->root = NULL; drive->root = NULL;
goto next; goto next;
} }
if (!S_ISDIR(drive_stat_buffer.st_mode)) if (!S_ISDIR(drive_stat_buffer.st_mode))
{ {
MESSAGE("%s is not a directory, ignoring drive %c:\n", MESSAGE("%s is not a directory, ignoring drive %c:\n",
drive->root, 'A' + i ); drive->root, 'A' + i );
HeapFree( GetProcessHeap(), 0, drive->root ); HeapFree( GetProcessHeap(), 0, drive->root );
drive->root = NULL; drive->root = NULL;
goto next; goto next;
} }
drive->dos_cwd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(drive->dos_cwd[0])); drive->dos_cwd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(drive->dos_cwd[0]));
drive->unix_cwd = heap_strdup( "" ); drive->unix_cwd = heap_strdup( "" );
drive->device = NULL; drive->device = NULL;
drive->flags = 0; drive->flags = 0;
drive->dev = drive_stat_buffer.st_dev; drive->dev = drive_stat_buffer.st_dev;
drive->ino = drive_stat_buffer.st_ino; drive->ino = drive_stat_buffer.st_ino;
drive->type = DRIVE_FIXED;
}
}
if (drive->root)
{
/* Get the drive type */ /* Get the drive type */
RtlInitUnicodeString( &nameW, TypeW ); RtlInitUnicodeString( &nameW, TypeW );
if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy )) if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
...@@ -222,7 +270,6 @@ int DRIVE_Init(void) ...@@ -222,7 +270,6 @@ int DRIVE_Init(void)
WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data; WCHAR *data = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
drive->type = DRIVE_GetDriveType( i, data ); drive->type = DRIVE_GetDriveType( i, data );
} }
else drive->type = DRIVE_FIXED;
/* Get the device */ /* Get the device */
RtlInitUnicodeString( &nameW, DeviceW ); RtlInitUnicodeString( &nameW, DeviceW );
...@@ -266,7 +313,7 @@ int DRIVE_Init(void) ...@@ -266,7 +313,7 @@ int DRIVE_Init(void)
NtClose( hkey ); NtClose( hkey );
} }
if (!count) if (!count && !symlink_count)
{ {
MESSAGE("Warning: no valid DOS drive found, check your configuration file.\n" ); MESSAGE("Warning: no valid DOS drive found, check your configuration file.\n" );
/* Create a C drive pointing to Unix root dir */ /* Create a C drive pointing to Unix root dir */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment