mountmgr: Store mount points as a list instead of an array.

This commit is contained in:
Alexandre Julliard 2008-10-17 20:09:31 +02:00
parent a12789e97e
commit 1680ba67ef
1 changed files with 76 additions and 79 deletions

View File

@ -37,6 +37,7 @@
#include "ddk/mountmgr.h"
#include "wine/library.h"
#include "wine/unicode.h"
#include "wine/list.h"
#include "wine/debug.h"
#include "mountmgr.h"
@ -44,7 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
#define MIN_ID_LEN 4
#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
@ -55,13 +55,14 @@ struct disk_device_info
struct mount_point
{
DEVICE_OBJECT *device;
struct list entry; /* entry in mount points list */
DEVICE_OBJECT *device; /* disk 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 struct list mount_points_list = LIST_INIT(mount_points_list);
static HKEY mount_key;
static inline UNICODE_STRING *get_device_name( DEVICE_OBJECT *dev )
@ -180,68 +181,58 @@ static void set_mount_point_id( struct mount_point *mount, const void *id, unsig
else mount->id_len = 0;
}
static NTSTATUS add_mount_point( DRIVER_OBJECT *driver, DWORD type, int drive,
const void *id, unsigned int id_len )
static struct mount_point *add_mount_point( DEVICE_OBJECT *device, UNICODE_STRING *device_name,
const WCHAR *link, const void *id, unsigned int id_len )
{
struct mount_point *mount;
WCHAR *str;
UINT len = (strlenW(link) + 1) * sizeof(WCHAR);
if (!(mount = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mount) + len ))) return NULL;
str = (WCHAR *)(mount + 1);
strcpyW( str, link );
RtlInitUnicodeString( &mount->link, str );
mount->device = device;
mount->id = NULL;
list_add_tail( &mount_points_list, &mount->entry );
IoCreateSymbolicLink( &mount->link, device_name );
set_mount_point_id( mount, id, id_len );
TRACE( "created %s id %s for %s\n", debugstr_w(mount->link.Buffer),
debugstr_a(mount->id), debugstr_w(device_name->Buffer) );
return mount;
}
/* create the DosDevices mount point symlink for a new device */
static struct mount_point *add_dosdev_mount_point( DEVICE_OBJECT *device, UNICODE_STRING *device_name,
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};
WCHAR link[sizeof(driveW)];
sprintfW( link, driveW, 'A' + drive );
return add_mount_point( device, device_name, link, id, id_len );
}
/* create the Volume mount point symlink for a new device */
static struct mount_point *add_volume_mount_point( DEVICE_OBJECT *device, UNICODE_STRING *device_name,
int drive, const void *id, unsigned int id_len )
{
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;
WCHAR link[sizeof(volumeW)];
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,
sprintfW( 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 */
set_mount_point_id( mount_drive, id, id_len );
set_mount_point_id( mount_volume, 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;
return add_mount_point( device, device_name, link, id, id_len );
}
/* check if a given mount point matches the requested specs */
@ -275,10 +266,11 @@ static BOOL matching_mount_point( const struct mount_point *mount, const MOUNTMG
static NTSTATUS query_mount_points( const void *in_buff, SIZE_T insize,
void *out_buff, SIZE_T outsize, IO_STATUS_BLOCK *iosb )
{
UINT i, j, pos, size;
UINT count, pos, size;
const MOUNTMGR_MOUNT_POINT *input = in_buff;
MOUNTMGR_MOUNT_POINTS *info = out_buff;
UNICODE_STRING *dev_name;
struct mount_point *mount;
/* sanity checks */
if (input->SymbolicLinkNameOffset + input->SymbolicLinkNameLength > insize ||
@ -289,17 +281,17 @@ static NTSTATUS query_mount_points( const void *in_buff, SIZE_T insize,
input->DeviceNameOffset + input->DeviceNameLength < input->DeviceNameOffset)
return STATUS_INVALID_PARAMETER;
for (i = j = size = 0; i < MAX_MOUNT_POINTS; i++)
count = size = 0;
LIST_FOR_EACH_ENTRY( mount, &mount_points_list, struct mount_point, entry )
{
if (!mount_points[i].device) continue;
if (!matching_mount_point( &mount_points[i], input )) continue;
size += get_device_name(mount_points[i].device)->Length;
size += mount_points[i].link.Length;
size += mount_points[i].id_len;
if (!matching_mount_point( mount, input )) continue;
size += get_device_name(mount->device)->Length;
size += mount->link.Length;
size += mount->id_len;
size = (size + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
j++;
count++;
}
pos = FIELD_OFFSET( MOUNTMGR_MOUNT_POINTS, MountPoints[j] );
pos = FIELD_OFFSET( MOUNTMGR_MOUNT_POINTS, MountPoints[count] );
size += pos;
if (size > outsize)
@ -309,29 +301,29 @@ static NTSTATUS query_mount_points( const void *in_buff, SIZE_T insize,
return STATUS_MORE_ENTRIES;
}
info->NumberOfMountPoints = j;
for (i = j = 0; i < MAX_MOUNT_POINTS; i++)
info->NumberOfMountPoints = count;
count = 0;
LIST_FOR_EACH_ENTRY( mount, &mount_points_list, struct mount_point, entry )
{
if (!mount_points[i].device) continue;
if (!matching_mount_point( &mount_points[i], input )) continue;
if (!matching_mount_point( mount, input )) continue;
dev_name = get_device_name( mount_points[i].device );
info->MountPoints[j].DeviceNameOffset = pos;
info->MountPoints[j].DeviceNameLength = dev_name->Length;
dev_name = get_device_name( mount->device );
info->MountPoints[count].DeviceNameOffset = pos;
info->MountPoints[count].DeviceNameLength = dev_name->Length;
memcpy( (char *)out_buff + pos, dev_name->Buffer, dev_name->Length );
pos += dev_name->Length;
info->MountPoints[j].SymbolicLinkNameOffset = pos;
info->MountPoints[j].SymbolicLinkNameLength = mount_points[i].link.Length;
memcpy( (char *)out_buff + pos, mount_points[i].link.Buffer, mount_points[i].link.Length );
pos += mount_points[i].link.Length;
info->MountPoints[count].SymbolicLinkNameOffset = pos;
info->MountPoints[count].SymbolicLinkNameLength = mount->link.Length;
memcpy( (char *)out_buff + pos, mount->link.Buffer, mount->link.Length );
pos += mount->link.Length;
info->MountPoints[j].UniqueIdOffset = pos;
info->MountPoints[j].UniqueIdLength = mount_points[i].id_len;
memcpy( (char *)out_buff + pos, mount_points[i].id, strlen(mount_points[i].id) + 1 );
pos += mount_points[i].id_len;
info->MountPoints[count].UniqueIdOffset = pos;
info->MountPoints[count].UniqueIdLength = mount->id_len;
memcpy( (char *)out_buff + pos, mount->id, mount->id_len );
pos += mount->id_len;
pos = (pos + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
j++;
count++;
}
info->Size = pos;
iosb->Information = pos;
@ -421,6 +413,7 @@ static void create_drive_mount_points( DRIVER_OBJECT *driver )
const char *config_dir = wine_get_config_dir();
char *buffer, *p, *link;
unsigned int i;
DEVICE_OBJECT *device;
if ((buffer = RtlAllocateHeap( GetProcessHeap(), 0,
strlen(config_dir) + sizeof("/dosdevices/a:") )))
@ -433,7 +426,11 @@ static void create_drive_mount_points( DRIVER_OBJECT *driver )
{
*p = 'a' + i;
if (!(link = read_symlink( buffer ))) continue;
add_mount_point( driver, DRIVE_FIXED, i, link, strlen(link) + 1 );
if (!create_disk_device( driver, DRIVE_FIXED, &device ))
{
add_dosdev_mount_point( device, get_device_name(device), i, link, strlen(link) + 1 );
add_volume_mount_point( device, get_device_name(device), i, link, strlen(link) + 1 );
}
RtlFreeHeap( GetProcessHeap(), 0, link );
}
RtlFreeHeap( GetProcessHeap(), 0, buffer );