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