[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:
Hermès Bélusca-Maïto 2024-05-26 22:18:46 +02:00
parent 50271949e7
commit ab0e04c81d
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
5 changed files with 234 additions and 448 deletions

View file

@ -330,11 +330,8 @@ MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension,
BOOLEAN
IsFtVolume(IN PUNICODE_STRING SymbolicName)
{
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
PFILE_OBJECT FileObject;
IO_STATUS_BLOCK IoStatusBlock;
PARTITION_INFORMATION PartitionInfo;
PDEVICE_OBJECT DeviceObject, FileDeviceObject;
@ -344,9 +341,7 @@ IsFtVolume(IN PUNICODE_STRING SymbolicName)
&FileObject,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
/* Get attached device */
FileDeviceObject = FileObject->DeviceObject;
@ -363,34 +358,17 @@ IsFtVolume(IN PUNICODE_STRING SymbolicName)
ObDereferenceObject(FileObject);
/* Get partition information */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO,
DeviceObject,
NULL,
0,
&PartitionInfo,
sizeof(PartitionInfo),
FALSE,
&Event,
&IoStatusBlock);
if (!Irp)
{
ObDereferenceObject(DeviceObject);
return FALSE;
}
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO,
DeviceObject,
NULL,
0,
&PartitionInfo,
sizeof(PartitionInfo),
NULL);
ObDereferenceObject(DeviceObject);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
/* Check if this is a FT volume */
return IsFTPartition(PartitionInfo.PartitionType);

View file

@ -179,6 +179,17 @@ extern LONG Unloading;
CODE_SEG("INIT")
DRIVER_INITIALIZE DriverEntry;
_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);
VOID
NTAPI
MountMgrCancel(

View file

@ -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;

View file

@ -37,13 +37,9 @@
VOID
SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
{
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION Stack;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK IoStatusBlock;
/* Get device object */
Status = IoGetDeviceObjectPointer(SymbolicName,
@ -51,40 +47,21 @@ SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
&FileObject,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
return;
}
/* And attached device object */
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
/* And send VOLUME_ONLINE */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_VOLUME_ONLINE,
DeviceObject,
NULL, 0,
NULL, 0,
FALSE,
&Event,
&IoStatusBlock);
if (!Irp)
{
goto Cleanup;
}
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_VOLUME_ONLINE,
DeviceObject,
NULL, 0,
NULL, 0,
FileObject);
UNREFERENCED_PARAMETER(Status);
Stack = IoGetNextIrpStackLocation(Irp);
Stack->FileObject = FileObject;
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
}
Cleanup:
ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject);
return;
}

View file

@ -168,15 +168,11 @@ GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
VOID
SendLinkCreated(IN PUNICODE_STRING SymbolicName)
{
PIRP Irp;
KEVENT Event;
ULONG NameSize;
NTSTATUS Status;
ULONG NameSize;
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION Stack;
PMOUNTDEV_NAME Name = NULL;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK IoStatusBlock;
/* Get the device associated with the name */
Status = IoGetDeviceObjectPointer(SymbolicName,
@ -184,22 +180,18 @@ SendLinkCreated(IN PUNICODE_STRING SymbolicName)
&FileObject,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
return;
}
/* Get attached device (will notify it) */
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
/* NameSize is the size of the whole MOUNTDEV_NAME struct */
/* NameSize is the size of the whole MOUNTDEV_NAME structure */
NameSize = sizeof(USHORT) + SymbolicName->Length;
Name = AllocatePool(NameSize);
if (!Name)
{
goto Cleanup;
}
/* Initialize struct */
/* Initialize structure */
Name->NameLength = SymbolicName->Length;
RtlCopyMemory(Name->Name, SymbolicName->Buffer, SymbolicName->Length);
@ -207,61 +199,30 @@ SendLinkCreated(IN PUNICODE_STRING SymbolicName)
* (with limited access) first. If this fails, the called driver may be
* for an older NT version, and so, we send again the notification using
* the old (Windows 2000) IOCTL definition (with any access). */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_CREATED,
DeviceObject,
Name,
NameSize,
NULL,
0,
FALSE,
&Event,
&IoStatusBlock);
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_CREATED,
DeviceObject,
Name,
NameSize,
NULL,
0,
FileObject);
/* This one can fail, no one matters */
if (Irp)
{
Stack = IoGetNextIrpStackLocation(Irp);
Stack->FileObject = FileObject;
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
}
}
UNREFERENCED_PARAMETER(Status);
#if (NTDDI_VERSION >= NTDDI_WS03)
/* Then, second one */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED,
DeviceObject,
Name,
NameSize,
NULL,
0,
FALSE,
&Event,
&IoStatusBlock);
if (!Irp)
{
goto Cleanup;
}
Stack = IoGetNextIrpStackLocation(Irp);
Stack->FileObject = FileObject;
/* Really notify */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
}
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED,
DeviceObject,
Name,
NameSize,
NULL,
0,
FileObject);
UNREFERENCED_PARAMETER(Status);
#endif // (NTDDI_VERSION >= NTDDI_WS03)
Cleanup:
if (Name)
{
FreePool(Name);
}
ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject);
@ -276,15 +237,11 @@ VOID
SendLinkDeleted(IN PUNICODE_STRING DeviceName,
IN PUNICODE_STRING SymbolicName)
{
PIRP Irp;
KEVENT Event;
ULONG NameSize;
NTSTATUS Status;
ULONG NameSize;
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION Stack;
PMOUNTDEV_NAME Name = NULL;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK IoStatusBlock;
/* Get the device associated with the name */
Status = IoGetDeviceObjectPointer(DeviceName,
@ -292,22 +249,18 @@ SendLinkDeleted(IN PUNICODE_STRING DeviceName,
&FileObject,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
return;
}
/* Get attached device (will notify it) */
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
/* NameSize is the size of the whole MOUNTDEV_NAME struct */
/* NameSize is the size of the whole MOUNTDEV_NAME structure */
NameSize = sizeof(USHORT) + SymbolicName->Length;
Name = AllocatePool(NameSize);
if (!Name)
{
goto Cleanup;
}
/* Initialize struct */
/* Initialize structure */
Name->NameLength = SymbolicName->Length;
RtlCopyMemory(Name->Name, SymbolicName->Buffer, SymbolicName->Length);
@ -315,61 +268,30 @@ SendLinkDeleted(IN PUNICODE_STRING DeviceName,
* (with limited access) first. If this fails, the called driver may be
* for an older NT version, and so, we send again the notification using
* the old (Windows 2000) IOCTL definition (with any access). */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_DELETED,
DeviceObject,
Name,
NameSize,
NULL,
0,
FALSE,
&Event,
&IoStatusBlock);
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_DELETED,
DeviceObject,
Name,
NameSize,
NULL,
0,
FileObject);
/* This one can fail, no one matters */
if (Irp)
{
Stack = IoGetNextIrpStackLocation(Irp);
Stack->FileObject = FileObject;
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
}
}
UNREFERENCED_PARAMETER(Status);
#if (NTDDI_VERSION >= NTDDI_WS03)
/* Then, second one */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED,
DeviceObject,
Name,
NameSize,
NULL,
0,
FALSE,
&Event,
&IoStatusBlock);
if (!Irp)
{
goto Cleanup;
}
Stack = IoGetNextIrpStackLocation(Irp);
Stack->FileObject = FileObject;
/* Really notify */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
}
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED,
DeviceObject,
Name,
NameSize,
NULL,
0,
FileObject);
UNREFERENCED_PARAMETER(Status);
#endif // (NTDDI_VERSION >= NTDDI_WS03)
Cleanup:
if (Name)
{
FreePool(Name);
}
ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject);
@ -700,14 +622,10 @@ QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName,
OUT PUNICODE_STRING SuggestedLinkName,
OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
{
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
USHORT NameLength;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK IoStatusBlock;
PIO_STACK_LOCATION IoStackLocation;
PMOUNTDEV_SUGGESTED_LINK_NAME IoCtlSuggested;
/* First, get device */
@ -732,35 +650,14 @@ QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName,
}
/* Prepare request */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME,
DeviceObject,
NULL,
0,
IoCtlSuggested,
sizeof(MOUNTDEV_SUGGESTED_LINK_NAME),
FALSE,
&Event,
&IoStatusBlock);
if (!Irp)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Release;
}
IoStackLocation = IoGetNextIrpStackLocation(Irp);
IoStackLocation->FileObject = FileObject;
/* And ask */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode,
FALSE, NULL);
Status = IoStatusBlock.Status;
}
/* Overflow? Normal */
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME,
DeviceObject,
NULL,
0,
IoCtlSuggested,
sizeof(MOUNTDEV_SUGGESTED_LINK_NAME),
FileObject);
/* Retry with appropriate length */
if (Status == STATUS_BUFFER_OVERFLOW)
{
/* Reallocate big enough buffer */
@ -774,39 +671,17 @@ QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName,
goto Dereference;
}
/* And reask */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME,
DeviceObject,
NULL,
0,
IoCtlSuggested,
NameLength,
FALSE,
&Event,
&IoStatusBlock);
if (!Irp)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Release;
}
IoStackLocation = IoGetNextIrpStackLocation(Irp);
IoStackLocation->FileObject = FileObject;
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode,
FALSE, NULL);
Status = IoStatusBlock.Status;
}
/* And re-ask */
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME,
DeviceObject,
NULL,
0,
IoCtlSuggested,
NameLength,
FileObject);
}
if (!NT_SUCCESS(Status))
{
goto Release;
}
/* Now we have suggested name, copy it */
SuggestedLinkName->Length = IoCtlSuggested->NameLength;