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

View file

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

View file

@ -39,6 +39,90 @@ LONG Unloading;
static const WCHAR Cunc[] = L"\\??\\C:"; static const WCHAR Cunc[] = L"\\??\\C:";
#define Cunc_LETTER_POSITION 4 #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 * @implemented
*/ */
@ -196,17 +280,13 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
IN OUT LPGUID StableGuid OPTIONAL, IN OUT LPGUID StableGuid OPTIONAL,
OUT PBOOLEAN Valid OPTIONAL) OUT PBOOLEAN Valid OPTIONAL)
{ {
PIRP Irp; NTSTATUS Status;
USHORT Size; USHORT Size;
KEVENT Event;
BOOLEAN IsRemovable; BOOLEAN IsRemovable;
PMOUNTDEV_NAME Name; PMOUNTDEV_NAME Name;
PMOUNTDEV_UNIQUE_ID Id; PMOUNTDEV_UNIQUE_ID Id;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PIO_STACK_LOCATION Stack;
NTSTATUS Status, IntStatus;
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK IoStatusBlock;
PARTITION_INFORMATION_EX PartitionInfo; PARTITION_INFORMATION_EX PartitionInfo;
STORAGE_DEVICE_NUMBER StorageDeviceNumber; STORAGE_DEVICE_NUMBER StorageDeviceNumber;
VOLUME_GET_GPT_ATTRIBUTES_INFORMATION GptAttributes; VOLUME_GET_GPT_ATTRIBUTES_INFORMATION GptAttributes;
@ -247,30 +327,21 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
if (!IsRemovable) if (!IsRemovable)
{ {
/* Query the GPT attributes */ /* Query the GPT attributes */
KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = MountMgrSendSyncDeviceIoCtl(IOCTL_VOLUME_GET_GPT_ATTRIBUTES,
Irp = IoBuildDeviceIoControlRequest(IOCTL_VOLUME_GET_GPT_ATTRIBUTES, DeviceObject,
DeviceObject, NULL,
NULL, 0,
0, &GptAttributes,
&GptAttributes, sizeof(GptAttributes),
sizeof(GptAttributes), NULL);
FALSE, #if 0
&Event, if (Status == STATUS_INSUFFICIENT_RESOURCES)
&IoStatusBlock);
if (!Irp)
{ {
ObDereferenceObject(DeviceObject); ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES; return Status;
} }
#endif
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
/* In case of failure, don't fail, that's no vital */ /* In case of failure, don't fail, that's no vital */
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -293,30 +364,21 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
if (!IsRemovable) if (!IsRemovable)
{ {
/* Query partitions information */ /* Query partitions information */
KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX,
Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX, DeviceObject,
DeviceObject, NULL,
NULL, 0,
0, &PartitionInfo,
&PartitionInfo, sizeof(PartitionInfo),
sizeof(PartitionInfo), NULL);
FALSE, #if 0
&Event, if (Status == STATUS_INSUFFICIENT_RESOURCES)
&IoStatusBlock);
if (!Irp)
{ {
ObDereferenceObject(DeviceObject); ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES; return Status;
} }
#endif
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
/* Once again here, failure isn't major */ /* Once again here, failure isn't major */
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -332,38 +394,25 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
/* It looks correct, ensure it is & query device number */ /* It looks correct, ensure it is & query device number */
if (*Valid) if (*Valid)
{ {
KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = MountMgrSendSyncDeviceIoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER,
Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, DeviceObject,
DeviceObject, NULL,
NULL, 0,
0, &StorageDeviceNumber,
&StorageDeviceNumber, sizeof(StorageDeviceNumber),
sizeof(StorageDeviceNumber), NULL);
FALSE, #if 0
&Event, if (Status == STATUS_INSUFFICIENT_RESOURCES)
&IoStatusBlock);
if (!Irp)
{ {
ObDereferenceObject(DeviceObject); ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES; return Status;
} }
#endif
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
}
else else
{
*Valid = FALSE; *Valid = FALSE;
}
} }
} }
} }
@ -381,35 +430,14 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
} }
/* Query device name */ /* Query device name */
KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, DeviceObject,
DeviceObject, NULL,
NULL, 0,
0, Name,
Name, sizeof(MOUNTDEV_NAME),
sizeof(MOUNTDEV_NAME), FileObject);
FALSE, /* Retry with appropriate length */
&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 */
if (Status == STATUS_BUFFER_OVERFLOW) if (Status == STATUS_BUFFER_OVERFLOW)
{ {
Size = Name->NameLength + sizeof(MOUNTDEV_NAME); Size = Name->NameLength + sizeof(MOUNTDEV_NAME);
@ -426,33 +454,13 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
} }
/* And query name (for real that time) */ /* And query name (for real that time) */
KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, DeviceObject,
DeviceObject, NULL,
NULL, 0,
0, Name,
Name, Size,
Size, FileObject);
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;
}
} }
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
@ -495,34 +503,13 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
} }
/* Query unique ID length */ /* Query unique ID length */
KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, DeviceObject,
DeviceObject, NULL,
NULL, 0,
0, Id,
Id, sizeof(MOUNTDEV_UNIQUE_ID),
sizeof(MOUNTDEV_UNIQUE_ID), FileObject);
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;
}
/* Retry with appropriate length */ /* Retry with appropriate length */
if (Status == STATUS_BUFFER_OVERFLOW) if (Status == STATUS_BUFFER_OVERFLOW)
{ {
@ -540,33 +527,13 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
} }
/* Query unique ID */ /* Query unique ID */
KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, DeviceObject,
DeviceObject, NULL,
NULL, 0,
0, Id,
Id, Size,
Size, FileObject);
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;
}
} }
/* Hands back unique ID */ /* Hands back unique ID */
@ -579,13 +546,10 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
/* In case of failure, also free the rest */ /* In case of failure, also free the rest */
FreePool(Id); FreePool(Id);
if (DeviceName->Length) if (DeviceName->Length)
{
FreePool(DeviceName->Buffer); FreePool(DeviceName->Buffer);
}
ObDereferenceObject(DeviceObject); ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
return Status; return Status;
} }
} }
@ -594,33 +558,14 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
if (HasGuid) if (HasGuid)
{ {
/* Query device stable GUID */ /* Query device stable GUID */
KeInitializeEvent(&Event, NotificationEvent, FALSE); NTSTATUS IntStatus;
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_STABLE_GUID, IntStatus = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_STABLE_GUID,
DeviceObject, DeviceObject,
NULL, NULL,
0, 0,
StableGuid, StableGuid,
sizeof(GUID), sizeof(GUID),
FALSE, FileObject);
&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;
}
*HasGuid = NT_SUCCESS(IntStatus); *HasGuid = NT_SUCCESS(IntStatus);
} }
@ -791,7 +736,7 @@ MountMgrFreeSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation)
*/ */
VOID VOID
NTAPI NTAPI
MountMgrUnload(IN struct _DRIVER_OBJECT *DriverObject) MountMgrUnload(IN PDRIVER_OBJECT DriverObject)
{ {
PLIST_ENTRY NextEntry; PLIST_ENTRY NextEntry;
PUNIQUE_ID_WORK_ITEM WorkItem; PUNIQUE_ID_WORK_ITEM WorkItem;

View file

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

View file

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