mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 01:45:40 +00:00
[MOUNTMGR] Introduce MountMgrSendSyncDeviceIoCtl() to replace repeated code (#6960)
See https://www.osr.com/blog/2018/02/14/beware-iobuilddeviceiocontrolrequest/ for some details about IRQL requirements.
This commit is contained in:
parent
50271949e7
commit
ab0e04c81d
5 changed files with 234 additions and 448 deletions
|
@ -39,6 +39,90 @@ LONG Unloading;
|
|||
static const WCHAR Cunc[] = L"\\??\\C:";
|
||||
#define Cunc_LETTER_POSITION 4
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Sends a synchronous IOCTL to the specified device object.
|
||||
*
|
||||
* @param[in] IoControlCode
|
||||
* The IOCTL to send to the device.
|
||||
*
|
||||
* @param[in] DeviceObject
|
||||
* Pointer to the device object that will handle the IOCTL.
|
||||
*
|
||||
* @param[in] InputBuffer
|
||||
* Optional pointer to a buffer containing input data for the IOCTL.
|
||||
* When specified, the buffer should be at least of InputBufferLength size.
|
||||
*
|
||||
* @param[in] InputBufferLength
|
||||
* Size in bytes, of the buffer pointed by InputBuffer.
|
||||
*
|
||||
* @param[out] OutputBuffer
|
||||
* Optional pointer to a buffer that will receive output data from the IOCTL.
|
||||
* When specified, the buffer should be at least of OutputBufferLength size.
|
||||
*
|
||||
* @param[in] OutputBufferLength
|
||||
* Size in bytes, of the buffer pointed by OutputBuffer.
|
||||
*
|
||||
* @param[in] FileObject
|
||||
* Optional pointer to a file object that may be necessary for the IOCTL.
|
||||
*
|
||||
* @return
|
||||
* An NTSTATUS code indicating success or failure of this function.
|
||||
*
|
||||
* @note
|
||||
* Must be called at PASSIVE_LEVEL with all APCs enabled.
|
||||
**/
|
||||
_IRQL_requires_(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
MountMgrSendSyncDeviceIoCtl(
|
||||
_In_ ULONG IoControlCode,
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
|
||||
_In_ ULONG InputBufferLength,
|
||||
_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
|
||||
_In_ ULONG OutputBufferLength,
|
||||
_In_opt_ PFILE_OBJECT FileObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KEVENT Event;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIRP Irp;
|
||||
|
||||
/* We must be at passive level as we are using an on-stack event, and
|
||||
* APCs must be enabled for allowing the Special Kernel APC queued by
|
||||
* the IO Manager to run for completing the IRP */
|
||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
||||
ASSERT(!KeAreAllApcsDisabled());
|
||||
|
||||
/* Initialize the on-stack notification event and build the threaded IRP */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
|
||||
DeviceObject,
|
||||
InputBuffer,
|
||||
InputBufferLength,
|
||||
OutputBuffer,
|
||||
OutputBufferLength,
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Set up the FileObject for the IOCTL if required */
|
||||
if (FileObject)
|
||||
IoGetNextIrpStackLocation(Irp)->FileObject = FileObject;
|
||||
|
||||
/* Finally, call the driver and wait for IRP completion if necessary */
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -196,17 +280,13 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
IN OUT LPGUID StableGuid OPTIONAL,
|
||||
OUT PBOOLEAN Valid OPTIONAL)
|
||||
{
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
USHORT Size;
|
||||
KEVENT Event;
|
||||
BOOLEAN IsRemovable;
|
||||
PMOUNTDEV_NAME Name;
|
||||
PMOUNTDEV_UNIQUE_ID Id;
|
||||
PFILE_OBJECT FileObject;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
NTSTATUS Status, IntStatus;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PARTITION_INFORMATION_EX PartitionInfo;
|
||||
STORAGE_DEVICE_NUMBER StorageDeviceNumber;
|
||||
VOLUME_GET_GPT_ATTRIBUTES_INFORMATION GptAttributes;
|
||||
|
@ -247,30 +327,21 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
if (!IsRemovable)
|
||||
{
|
||||
/* Query the GPT attributes */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_VOLUME_GET_GPT_ATTRIBUTES,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
&GptAttributes,
|
||||
sizeof(GptAttributes),
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_VOLUME_GET_GPT_ATTRIBUTES,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
&GptAttributes,
|
||||
sizeof(GptAttributes),
|
||||
NULL);
|
||||
#if 0
|
||||
if (Status == STATUS_INSUFFICIENT_RESOURCES)
|
||||
{
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* In case of failure, don't fail, that's no vital */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -293,30 +364,21 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
if (!IsRemovable)
|
||||
{
|
||||
/* Query partitions information */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
&PartitionInfo,
|
||||
sizeof(PartitionInfo),
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
&PartitionInfo,
|
||||
sizeof(PartitionInfo),
|
||||
NULL);
|
||||
#if 0
|
||||
if (Status == STATUS_INSUFFICIENT_RESOURCES)
|
||||
{
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Once again here, failure isn't major */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -332,38 +394,25 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
/* It looks correct, ensure it is & query device number */
|
||||
if (*Valid)
|
||||
{
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
&StorageDeviceNumber,
|
||||
sizeof(StorageDeviceNumber),
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
&StorageDeviceNumber,
|
||||
sizeof(StorageDeviceNumber),
|
||||
NULL);
|
||||
#if 0
|
||||
if (Status == STATUS_INSUFFICIENT_RESOURCES)
|
||||
{
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
*Valid = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -381,35 +430,14 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
}
|
||||
|
||||
/* Query device name */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
Name,
|
||||
sizeof(MOUNTDEV_NAME),
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
{
|
||||
FreePool(Name);
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
Stack->FileObject = FileObject;
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
/* Now, we've got the correct length */
|
||||
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
Name,
|
||||
sizeof(MOUNTDEV_NAME),
|
||||
FileObject);
|
||||
/* Retry with appropriate length */
|
||||
if (Status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
Size = Name->NameLength + sizeof(MOUNTDEV_NAME);
|
||||
|
@ -426,33 +454,13 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
}
|
||||
|
||||
/* And query name (for real that time) */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
Name,
|
||||
Size,
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
{
|
||||
FreePool(Name);
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
Stack->FileObject = FileObject;
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
Name,
|
||||
Size,
|
||||
FileObject);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
|
@ -495,34 +503,13 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
}
|
||||
|
||||
/* Query unique ID length */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
Id,
|
||||
sizeof(MOUNTDEV_UNIQUE_ID),
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
{
|
||||
FreePool(Id);
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
Stack->FileObject = FileObject;
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
Id,
|
||||
sizeof(MOUNTDEV_UNIQUE_ID),
|
||||
FileObject);
|
||||
/* Retry with appropriate length */
|
||||
if (Status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
|
@ -540,33 +527,13 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
}
|
||||
|
||||
/* Query unique ID */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
Id,
|
||||
Size,
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
{
|
||||
FreePool(Id);
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
Stack->FileObject = FileObject;
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
Id,
|
||||
Size,
|
||||
FileObject);
|
||||
}
|
||||
|
||||
/* Hands back unique ID */
|
||||
|
@ -579,13 +546,10 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
/* In case of failure, also free the rest */
|
||||
FreePool(Id);
|
||||
if (DeviceName->Length)
|
||||
{
|
||||
FreePool(DeviceName->Buffer);
|
||||
}
|
||||
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
@ -594,33 +558,14 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
|
|||
if (HasGuid)
|
||||
{
|
||||
/* Query device stable GUID */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_STABLE_GUID,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
StableGuid,
|
||||
sizeof(GUID),
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
{
|
||||
ObDereferenceObject(DeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
Stack->FileObject = FileObject;
|
||||
|
||||
IntStatus = IoCallDriver(DeviceObject, Irp);
|
||||
if (IntStatus == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
IntStatus = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
NTSTATUS IntStatus;
|
||||
IntStatus = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_STABLE_GUID,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
StableGuid,
|
||||
sizeof(GUID),
|
||||
FileObject);
|
||||
*HasGuid = NT_SUCCESS(IntStatus);
|
||||
}
|
||||
|
||||
|
@ -791,7 +736,7 @@ MountMgrFreeSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation)
|
|||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
MountMgrUnload(IN struct _DRIVER_OBJECT *DriverObject)
|
||||
MountMgrUnload(IN PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PUNIQUE_ID_WORK_ITEM WorkItem;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue