Alexandre Julliard : mountmgr.sys: Create disk devices for all configured drives.
Alexandre Julliard
julliard at winehq.org
Mon Jan 7 08:38:57 CST 2008
Module: wine
Branch: master
Commit: 2143dee78a0acf8be8c07062e84cc12ef18ef7cb
URL: http://source.winehq.org/git/wine.git/?a=commit;h=2143dee78a0acf8be8c07062e84cc12ef18ef7cb
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Jan 4 14:24:59 2008 +0100
mountmgr.sys: Create disk devices for all configured drives.
---
dlls/mountmgr.sys/mountmgr.c | 199 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 199 insertions(+), 0 deletions(-)
diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c
index f6c0f20..c24c78c 100644
--- a/dlls/mountmgr.sys/mountmgr.c
+++ b/dlls/mountmgr.sys/mountmgr.c
@@ -38,6 +38,178 @@
WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
+#define MAX_DOS_DRIVES 26
+#define MAX_MOUNT_POINTS (2 * MAX_DOS_DRIVES)
+
+/* extra info for disk devices, stored in DeviceExtension */
+struct disk_device_info
+{
+ UNICODE_STRING name; /* device name */
+};
+
+struct mount_point
+{
+ DEVICE_OBJECT *device;
+ UNICODE_STRING link; /* DOS device symlink */
+ void *id; /* device unique id */
+ unsigned int id_len;
+};
+
+static struct mount_point mount_points[MAX_MOUNT_POINTS];
+
+static inline UNICODE_STRING *get_device_name( DEVICE_OBJECT *dev )
+{
+ return &((struct disk_device_info *)dev->DeviceExtension)->name;
+}
+
+/* read a Unix symlink; returned buffer must be freed by caller */
+static char *read_symlink( const char *path )
+{
+ char *buffer;
+ int ret, size = 128;
+
+ for (;;)
+ {
+ if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, size )))
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ return 0;
+ }
+ ret = readlink( path, buffer, size );
+ if (ret == -1)
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, buffer );
+ return 0;
+ }
+ if (ret != size)
+ {
+ buffer[ret] = 0;
+ return buffer;
+ }
+ RtlFreeHeap( GetProcessHeap(), 0, buffer );
+ size *= 2;
+ }
+}
+
+static NTSTATUS create_disk_device( DRIVER_OBJECT *driver, DWORD type, DEVICE_OBJECT **dev_obj )
+{
+ static const WCHAR harddiskW[] = {'\\','D','e','v','i','c','e',
+ '\\','H','a','r','d','d','i','s','k','V','o','l','u','m','e','%','u',0};
+ static const WCHAR cdromW[] = {'\\','D','e','v','i','c','e','\\','C','d','R','o','m','%','u',0};
+ static const WCHAR floppyW[] = {'\\','D','e','v','i','c','e','\\','F','l','o','p','p','y','%','u',0};
+
+ UINT i, first = 0;
+ NTSTATUS status = 0;
+ const WCHAR *format;
+ UNICODE_STRING name;
+ struct disk_device_info *info;
+
+ switch(type)
+ {
+ case DRIVE_REMOVABLE:
+ format = floppyW;
+ break;
+ case DRIVE_CDROM:
+ format = cdromW;
+ break;
+ case DRIVE_FIXED:
+ default: /* FIXME */
+ format = harddiskW;
+ first = 1; /* harddisk volumes start counting from 1 */
+ break;
+ }
+
+ name.MaximumLength = (strlenW(format) + 10) * sizeof(WCHAR);
+ name.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, name.MaximumLength );
+ for (i = first; i < 32; i++)
+ {
+ sprintfW( name.Buffer, format, i );
+ name.Length = strlenW(name.Buffer) * sizeof(WCHAR);
+ status = IoCreateDevice( driver, sizeof(*info), &name, 0, 0, FALSE, dev_obj );
+ if (status != STATUS_OBJECT_NAME_COLLISION) break;
+ }
+ if (!status)
+ {
+ info = (*dev_obj)->DeviceExtension;
+ info->name = name;
+ }
+ else
+ {
+ FIXME( "IoCreateDevice %s got %x\n", debugstr_w(name.Buffer), status );
+ RtlFreeUnicodeString( &name );
+ }
+ return status;
+}
+
+
+static NTSTATUS add_mount_point( DRIVER_OBJECT *driver, DWORD type, int drive,
+ const void *id, unsigned int id_len )
+{
+ static const WCHAR driveW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','%','c',':',0};
+ static const WCHAR volumeW[] = {'\\','?','?','\\','V','o','l','u','m','e','{',
+ '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-',
+ '%','0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x',
+ '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0};
+ WCHAR *drive_link, *volume_link;
+ NTSTATUS status;
+ GUID guid;
+ UINT i;
+ struct mount_point *mount_drive = NULL, *mount_volume = NULL;
+
+ /* find two free mount points */
+
+ for (i = 0; i < MAX_MOUNT_POINTS; i++)
+ {
+ if (mount_points[i].device) continue;
+ if (!mount_drive)
+ {
+ mount_drive = &mount_points[i];
+ continue;
+ }
+ mount_volume = &mount_points[i];
+ break;
+ }
+ if (!mount_volume) return STATUS_NO_MEMORY;
+
+ /* create the volume */
+
+ memset( &guid, 0, sizeof(guid) ); /* FIXME */
+ guid.Data4[7] = 'A' + drive;
+
+ drive_link = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(driveW) );
+ volume_link = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(volumeW) );
+ sprintfW( drive_link, driveW, 'A' + drive );
+ sprintfW( volume_link, volumeW, guid.Data1, guid.Data2, guid.Data3,
+ guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
+ guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+
+ RtlInitUnicodeString( &mount_drive->link, drive_link );
+ RtlInitUnicodeString( &mount_volume->link, volume_link );
+ status = create_disk_device( driver, type, &mount_drive->device );
+ if (status)
+ {
+ RtlFreeUnicodeString( &mount_drive->link );
+ RtlFreeUnicodeString( &mount_volume->link );
+ return status;
+ }
+
+ mount_volume->device = mount_drive->device; /* FIXME: incr ref count */
+ mount_drive->id = RtlAllocateHeap( GetProcessHeap(), 0, id_len );
+ mount_drive->id_len = id_len;
+ memcpy( mount_drive->id, id, id_len );
+ mount_volume->id = RtlAllocateHeap( GetProcessHeap(), 0, id_len );
+ mount_volume->id_len = id_len;
+ memcpy( mount_volume->id, id, id_len );
+
+ IoCreateSymbolicLink( &mount_drive->link, get_device_name(mount_drive->device) );
+ IoCreateSymbolicLink( &mount_volume->link, get_device_name(mount_volume->device) );
+
+ TRACE( "created device %s symlinks %s %s\n", debugstr_w(get_device_name(mount_drive->device)->Buffer),
+ debugstr_w(mount_drive->link.Buffer), debugstr_w(mount_volume->link.Buffer) );
+
+ return STATUS_SUCCESS;
+}
+
/* handler for ioctls on the mount manager device */
static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp )
{
@@ -78,6 +250,31 @@ static NTSTATUS WINAPI harddisk_ioctl( DEVICE_OBJECT *device, IRP *irp )
return irp->IoStatus.u.Status;
}
+/* create mount points for mapped drives */
+static void create_drive_mount_points( DRIVER_OBJECT *driver )
+{
+ const char *config_dir = wine_get_config_dir();
+ char *buffer, *p, *link;
+ unsigned int i;
+
+ if ((buffer = RtlAllocateHeap( GetProcessHeap(), 0,
+ strlen(config_dir) + sizeof("/dosdevices/a:") )))
+ {
+ strcpy( buffer, config_dir );
+ strcat( buffer, "/dosdevices/a:" );
+ p = buffer + strlen(buffer) - 2;
+
+ for (i = 0; i < MAX_DOS_DRIVES; i++)
+ {
+ *p = 'a' + i;
+ if (!(link = read_symlink( buffer ))) continue;
+ add_mount_point( driver, DRIVE_FIXED, i, link, strlen(link) );
+ RtlFreeHeap( GetProcessHeap(), 0, link );
+ }
+ RtlFreeHeap( GetProcessHeap(), 0, buffer );
+ }
+}
+
/* driver entry point for the harddisk driver */
static NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
{
@@ -101,6 +298,8 @@ static NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STR
return status;
}
+ create_drive_mount_points( driver );
+
return status;
}
More information about the wine-cvs
mailing list