Alexandre Julliard : mountmgr.sys: Implemented the IOCTL_MOUNTMGR_QUERY_POINTS request.
Alexandre Julliard
julliard at winehq.org
Mon Jan 7 08:38:57 CST 2008
Module: wine
Branch: master
Commit: 838f12539bf54370d0c344d8b6d880ac303ffb39
URL: http://source.winehq.org/git/wine.git/?a=commit;h=838f12539bf54370d0c344d8b6d880ac303ffb39
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Jan 4 14:28:47 2008 +0100
mountmgr.sys: Implemented the IOCTL_MOUNTMGR_QUERY_POINTS request.
---
dlls/mountmgr.sys/mountmgr.c | 97 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c
index 875bd79..1ea73e4 100644
--- a/dlls/mountmgr.sys/mountmgr.c
+++ b/dlls/mountmgr.sys/mountmgr.c
@@ -217,6 +217,94 @@ static NTSTATUS add_mount_point( DRIVER_OBJECT *driver, DWORD type, int drive,
return STATUS_SUCCESS;
}
+/* check if a given mount point matches the requested specs */
+static BOOL matching_mount_point( const struct mount_point *mount, const MOUNTMGR_MOUNT_POINT *spec )
+{
+ if (spec->SymbolicLinkNameOffset)
+ {
+ const WCHAR *name = (const WCHAR *)((const char *)spec + spec->SymbolicLinkNameOffset);
+ if (spec->SymbolicLinkNameLength != mount->link.Length) return FALSE;
+ if (memicmpW( name, mount->link.Buffer, mount->link.Length/sizeof(WCHAR)))
+ return FALSE;
+ }
+ if (spec->DeviceNameOffset)
+ {
+ const WCHAR *name = (const WCHAR *)((const char *)spec + spec->DeviceNameOffset);
+ const UNICODE_STRING *dev_name = get_device_name( mount->device );
+ if (spec->DeviceNameLength != dev_name->Length) return FALSE;
+ if (memicmpW( name, dev_name->Buffer, dev_name->Length/sizeof(WCHAR)))
+ return FALSE;
+ }
+ if (spec->UniqueIdOffset)
+ {
+ const void *id = ((const char *)spec + spec->UniqueIdOffset);
+ if (spec->UniqueIdLength != mount->id_len) return FALSE;
+ if (memcmp( id, mount->id, mount->id_len )) return FALSE;
+ }
+ return TRUE;
+}
+
+/* implementation of IOCTL_MOUNTMGR_QUERY_POINTS */
+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;
+ const MOUNTMGR_MOUNT_POINT *input = in_buff;
+ MOUNTMGR_MOUNT_POINTS *info = out_buff;
+ UNICODE_STRING *dev_name;
+
+ /* sanity checks */
+ if (input->SymbolicLinkNameOffset + input->SymbolicLinkNameLength > insize ||
+ input->UniqueIdOffset + input->UniqueIdLength > insize ||
+ input->DeviceNameOffset + input->DeviceNameLength > insize ||
+ input->SymbolicLinkNameOffset + input->SymbolicLinkNameLength < input->SymbolicLinkNameOffset ||
+ input->UniqueIdOffset + input->UniqueIdLength < input->UniqueIdOffset ||
+ input->DeviceNameOffset + input->DeviceNameLength < input->DeviceNameOffset)
+ return STATUS_INVALID_PARAMETER;
+
+ for (i = j = size = 0; i < MAX_MOUNT_POINTS; i++)
+ {
+ 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;
+ j++;
+ }
+ pos = FIELD_OFFSET( MOUNTMGR_MOUNT_POINTS, MountPoints[j] );
+ size += pos;
+
+ if (size > outsize)
+ {
+ if (size >= sizeof(info->Size)) info->Size = size;
+ iosb->Information = sizeof(info->Size);
+ return STATUS_MORE_ENTRIES;
+ }
+
+ info->NumberOfMountPoints = j;
+ for (i = j = 0; i < MAX_MOUNT_POINTS; i++)
+ {
+ if (!mount_points[i].device) continue;
+ if (!matching_mount_point( &mount_points[i], input )) continue;
+ info->MountPoints[j].UniqueIdOffset = 0; /* FIXME */
+ info->MountPoints[j].UniqueIdLength = 0;
+
+ dev_name = get_device_name( mount_points[i].device );
+ info->MountPoints[j].DeviceNameOffset = pos;
+ info->MountPoints[j].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;
+ j++;
+ }
+ info->Size = pos;
+ iosb->Information = pos;
+ return STATUS_SUCCESS;
+}
+
/* handler for ioctls on the mount manager device */
static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp )
{
@@ -229,6 +317,15 @@ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp )
switch(irpsp->Parameters.DeviceIoControl.IoControlCode)
{
+ case IOCTL_MOUNTMGR_QUERY_POINTS:
+ if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
+ return STATUS_INVALID_PARAMETER;
+ irp->IoStatus.u.Status = query_mount_points( irpsp->Parameters.DeviceIoControl.Type3InputBuffer,
+ irpsp->Parameters.DeviceIoControl.InputBufferLength,
+ irp->MdlAddress->StartVa,
+ irpsp->Parameters.DeviceIoControl.OutputBufferLength,
+ &irp->IoStatus );
+ break;
default:
FIXME( "ioctl %x not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode );
irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
More information about the wine-cvs
mailing list