From a1377319bc6b4b7c7841c5410d252f48bba28c7e Mon Sep 17 00:00:00 2001 From: Bernhard Loos Date: Tue, 1 Nov 2011 13:03:12 +0100 Subject: [PATCH] mountmgr, ntoskrnl: METHOD_BUFFERED uses irp->AssociatedIrp.SystemBuffer for both input and output. --- dlls/mountmgr.sys/device.c | 8 +++---- dlls/mountmgr.sys/mountmgr.c | 41 ++++++++++++++++++++++-------------- dlls/ntoskrnl.exe/ntoskrnl.c | 14 +++++++++++- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c index a3aa81cd389..3f393e78b38 100644 --- a/dlls/mountmgr.sys/device.c +++ b/dlls/mountmgr.sys/device.c @@ -890,7 +890,7 @@ static NTSTATUS WINAPI harddisk_ioctl( DEVICE_OBJECT *device, IRP *irp ) info.TracksPerCylinder = 255; info.SectorsPerTrack = 63; info.BytesPerSector = 512; - memcpy( irp->MdlAddress->StartVa, &info, len ); + memcpy( irp->AssociatedIrp.SystemBuffer, &info, len ); irp->IoStatus.Information = len; irp->IoStatus.u.Status = STATUS_SUCCESS; break; @@ -910,7 +910,7 @@ static NTSTATUS WINAPI harddisk_ioctl( DEVICE_OBJECT *device, IRP *irp ) info.DiskSize.QuadPart = info.Geometry.Cylinders.QuadPart * info.Geometry.TracksPerCylinder * info.Geometry.SectorsPerTrack * info.Geometry.BytesPerSector; info.Data[0] = 0; - memcpy( irp->MdlAddress->StartVa, &info, len ); + memcpy( irp->AssociatedIrp.SystemBuffer, &info, len ); irp->IoStatus.Information = len; irp->IoStatus.u.Status = STATUS_SUCCESS; break; @@ -919,7 +919,7 @@ static NTSTATUS WINAPI harddisk_ioctl( DEVICE_OBJECT *device, IRP *irp ) { DWORD len = min( sizeof(dev->devnum), irpsp->Parameters.DeviceIoControl.OutputBufferLength ); - memcpy( irp->MdlAddress->StartVa, &dev->devnum, len ); + memcpy( irp->AssociatedIrp.SystemBuffer, &dev->devnum, len ); irp->IoStatus.Information = len; irp->IoStatus.u.Status = STATUS_SUCCESS; break; @@ -932,7 +932,7 @@ static NTSTATUS WINAPI harddisk_ioctl( DEVICE_OBJECT *device, IRP *irp ) DWORD len = min( 32, irpsp->Parameters.DeviceIoControl.OutputBufferLength ); FIXME( "returning zero-filled buffer for IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS\n" ); - memset( irp->MdlAddress->StartVa, 0, len ); + memset( irp->AssociatedIrp.SystemBuffer, 0, len ); irp->IoStatus.Information = len; irp->IoStatus.u.Status = STATUS_SUCCESS; break; diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c index 4e9900f9f00..afb9d927a94 100644 --- a/dlls/mountmgr.sys/mountmgr.c +++ b/dlls/mountmgr.sys/mountmgr.c @@ -153,12 +153,12 @@ static BOOL matching_mount_point( const struct mount_point *mount, const MOUNTMG } /* 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 ) +static NTSTATUS query_mount_points( void *buff, SIZE_T insize, + SIZE_T outsize, IO_STATUS_BLOCK *iosb ) { UINT count, pos, size; - const MOUNTMGR_MOUNT_POINT *input = in_buff; - MOUNTMGR_MOUNT_POINTS *info = out_buff; + MOUNTMGR_MOUNT_POINT *input = buff; + MOUNTMGR_MOUNT_POINTS *info; struct mount_point *mount; /* sanity checks */ @@ -185,11 +185,18 @@ static NTSTATUS query_mount_points( const void *in_buff, SIZE_T insize, if (size > outsize) { + info = buff; if (size >= sizeof(info->Size)) info->Size = size; iosb->Information = sizeof(info->Size); return STATUS_MORE_ENTRIES; } + input = HeapAlloc( GetProcessHeap(), 0, insize ); + if (!input) + return STATUS_NO_MEMORY; + memcpy( input, buff, insize ); + info = buff; + info->NumberOfMountPoints = count; count = 0; LIST_FOR_EACH_ENTRY( mount, &mount_points_list, struct mount_point, entry ) @@ -198,23 +205,24 @@ static NTSTATUS query_mount_points( const void *in_buff, SIZE_T insize, info->MountPoints[count].DeviceNameOffset = pos; info->MountPoints[count].DeviceNameLength = mount->name.Length; - memcpy( (char *)out_buff + pos, mount->name.Buffer, mount->name.Length ); + memcpy( (char *)buff + pos, mount->name.Buffer, mount->name.Length ); pos += mount->name.Length; info->MountPoints[count].SymbolicLinkNameOffset = pos; info->MountPoints[count].SymbolicLinkNameLength = mount->link.Length; - memcpy( (char *)out_buff + pos, mount->link.Buffer, mount->link.Length ); + memcpy( (char *)buff + pos, mount->link.Buffer, mount->link.Length ); pos += mount->link.Length; info->MountPoints[count].UniqueIdOffset = pos; info->MountPoints[count].UniqueIdLength = mount->id_len; - memcpy( (char *)out_buff + pos, mount->id, mount->id_len ); + memcpy( (char *)buff + pos, mount->id, mount->id_len ); pos += mount->id_len; pos = (pos + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1); count++; } info->Size = pos; iosb->Information = pos; + HeapFree( GetProcessHeap(), 0, input ); return STATUS_SUCCESS; } @@ -271,11 +279,11 @@ static NTSTATUS define_unix_drive( const void *in_buff, SIZE_T insize ) } /* implementation of IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE */ -static NTSTATUS query_unix_drive( const void *in_buff, SIZE_T insize, - void *out_buff, SIZE_T outsize, IO_STATUS_BLOCK *iosb ) +static NTSTATUS query_unix_drive( void *buff, SIZE_T insize, + SIZE_T outsize, IO_STATUS_BLOCK *iosb ) { - const struct mountmgr_unix_drive *input = in_buff; - struct mountmgr_unix_drive *output = out_buff; + const struct mountmgr_unix_drive *input = buff; + struct mountmgr_unix_drive *output = NULL; char *device, *mount_point; int letter = tolowerW( input->letter ); NTSTATUS status; @@ -302,6 +310,9 @@ static NTSTATUS query_unix_drive( const void *in_buff, SIZE_T insize, if (device) size += strlen(device) + 1; if (mount_point) size += strlen(mount_point) + 1; + input = NULL; + output = buff; + if (size > outsize) { iosb->Information = 0; @@ -364,9 +375,8 @@ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp ) 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, + irp->IoStatus.u.Status = query_mount_points( irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.DeviceIoControl.InputBufferLength, - irp->MdlAddress->StartVa, irpsp->Parameters.DeviceIoControl.OutputBufferLength, &irp->IoStatus ); break; @@ -374,15 +384,14 @@ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp ) if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct mountmgr_unix_drive)) return STATUS_INVALID_PARAMETER; irp->IoStatus.Information = 0; - irp->IoStatus.u.Status = define_unix_drive( irpsp->Parameters.DeviceIoControl.Type3InputBuffer, + irp->IoStatus.u.Status = define_unix_drive( irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.DeviceIoControl.InputBufferLength ); break; case IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE: if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct mountmgr_unix_drive)) return STATUS_INVALID_PARAMETER; - irp->IoStatus.u.Status = query_unix_drive( irpsp->Parameters.DeviceIoControl.Type3InputBuffer, + irp->IoStatus.u.Status = query_unix_drive( irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.DeviceIoControl.InputBufferLength, - irp->MdlAddress->StartVa, irpsp->Parameters.DeviceIoControl.OutputBufferLength, &irp->IoStatus ); break; diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 9c7916e63de..b00c070c66d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -32,6 +32,7 @@ #include "windef.h" #include "winternl.h" #include "excpt.h" +#include "winioctl.h" #include "ddk/ntddk.h" #include "wine/unicode.h" #include "wine/server.h" @@ -151,7 +152,13 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, memset( &mdl, 0x77, sizeof(mdl) ); irp.RequestorMode = UserMode; - irp.AssociatedIrp.SystemBuffer = in_buff; + if ((code & 3) == METHOD_BUFFERED) + { + irp.AssociatedIrp.SystemBuffer = HeapAlloc( GetProcessHeap(), 0, max( in_size, *out_size ) ); + if (!irp.AssociatedIrp.SystemBuffer) + return STATUS_NO_MEMORY; + memcpy( irp.AssociatedIrp.SystemBuffer, in_buff, in_size ); + } irp.UserBuffer = out_buff; irp.MdlAddress = &mdl; irp.Tail.Overlay.s.u2.CurrentStackLocation = &irpsp; @@ -186,6 +193,11 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, GetCurrentThreadId(), dispatch, device, &irp, status ); *out_size = (irp.IoStatus.u.Status >= 0) ? irp.IoStatus.Information : 0; + if ((code & 3) == METHOD_BUFFERED) + { + memcpy( out_buff, irp.AssociatedIrp.SystemBuffer, *out_size ); + HeapFree( GetProcessHeap(), 0, irp.AssociatedIrp.SystemBuffer ); + } return irp.IoStatus.u.Status; }