[MOUNTMGR]

Implement MountMgrQueryDosVolumePath

svn path=/trunk/; revision=61421
This commit is contained in:
Pierre Schweitzer 2013-12-25 22:47:30 +00:00
parent ad8fe5ab95
commit 3c03b26a4f
2 changed files with 220 additions and 4 deletions

View file

@ -27,6 +27,8 @@
#include "mntmgr.h"
#define MAX_DEVICES 0x3E8 /* Matches 1000 devices */
#define NDEBUG
#include <debug.h>
@ -833,9 +835,224 @@ NTSTATUS
MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension,
IN PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceExtension);
UNREFERENCED_PARAMETER(Irp);
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status;
ULONG DevicesFound;
PIO_STACK_LOCATION Stack;
PLIST_ENTRY SymlinksEntry;
UNICODE_STRING SymbolicName;
PMOUNTMGR_TARGET_NAME Target;
PWSTR DeviceString, OldBuffer;
USHORT DeviceLength, OldLength;
PDEVICE_INFORMATION DeviceInformation;
PSYMLINK_INFORMATION SymlinkInformation;
PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
Stack = IoGetNextIrpStackLocation(Irp);
/* Validate input size */
if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
{
return STATUS_INVALID_PARAMETER;
}
/* Ensure we have received UNICODE_STRING */
Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
if (Target->DeviceNameLength & 1)
{
return STATUS_INVALID_PARAMETER;
}
/* Validate the entry structure size */
if (Target->DeviceNameLength + sizeof(UNICODE_NULL) > Stack->Parameters.DeviceIoControl.InputBufferLength)
{
return STATUS_INVALID_PARAMETER;
}
/* Ensure we can at least return needed size */
if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
{
return STATUS_INVALID_PARAMETER;
}
/* Construct string for query */
SymbolicName.Length = Target->DeviceNameLength;
SymbolicName.MaximumLength = Target->DeviceNameLength + sizeof(UNICODE_NULL);
SymbolicName.Buffer = Target->DeviceName;
/* Find device with our info */
Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
if (!NT_SUCCESS(Status))
{
return Status;
}
DeviceLength = 0;
DeviceString = NULL;
DevicesFound = 0;
/* Try to find associated device info */
while (TRUE)
{
for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
SymlinksEntry = SymlinksEntry->Flink)
{
SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
/* Try to find with drive letter */
if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
{
break;
}
}
/* We didn't find, break */
if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
{
break;
}
/* It doesn't have associated device, go to fallback method */
if (IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
{
goto TryWithVolumeName;
}
/* Create a string with the information about the device */
AssociatedDevice = CONTAINING_RECORD(&(DeviceInformation->SymbolicLinksListHead), ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
OldLength = DeviceLength;
OldBuffer = DeviceString;
DeviceLength += AssociatedDevice->String.Length;
DeviceString = AllocatePool(DeviceLength);
if (!DeviceString)
{
if (OldBuffer)
{
FreePool(OldBuffer);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Store our info and previous if any */
RtlCopyMemory(DeviceString, AssociatedDevice->String.Buffer, AssociatedDevice->String.Length);
if (OldBuffer)
{
RtlCopyMemory(&DeviceString[AssociatedDevice->String.Length / sizeof(WCHAR)], OldBuffer, OldLength);
FreePool(OldBuffer);
}
/* Count and continue looking */
++DevicesFound;
DeviceInformation = AssociatedDevice->DeviceInformation;
/* If too many devices, try another way */
if (DevicesFound > MAX_DEVICES) /* 1000 */
{
goto TryWithVolumeName;
}
}
/* Reallocate our string, so that we can prepend disk letter */
OldBuffer = DeviceString;
OldLength = DeviceLength;
DeviceLength += 2 * sizeof(WCHAR);
DeviceString = AllocatePool(DeviceLength);
if (!DeviceString)
{
if (OldBuffer)
{
FreePool(OldBuffer);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Get the letter */
DeviceString[0] = SymlinkInformation->Name.Buffer[12];
DeviceString[1] = L':';
/* And copy the rest */
if (OldBuffer)
{
RtlCopyMemory(&DeviceString[2], OldBuffer, OldLength);
FreePool(OldBuffer);
}
TryWithVolumeName:
/* If we didn't find anything, try differently */
if (DeviceLength < 2 * sizeof(WCHAR) || DeviceString[2] != L':')
{
if (DeviceString)
{
FreePool(DeviceString);
DeviceLength = 0;
}
/* Try to find a volume name matching */
for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
SymlinksEntry = SymlinksEntry->Flink)
{
SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation->Name))
{
break;
}
}
/* If found copy */
if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
{
DeviceLength = SymlinkInformation->Name.Length;
DeviceString = AllocatePool(DeviceLength);
if (!DeviceString)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(DeviceString, SymlinkInformation->Name.Buffer, DeviceLength);
/* Ensure we are in the right namespace; [1] can be ? */
DeviceString[1] = L'\\';
}
}
/* If we found something */
if (DeviceString)
{
/* At least, we will return our length */
((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSzLength = DeviceLength;
/* MOUNTMGR_VOLUME_PATHS is a string + a ULONG */
Irp->IoStatus.Information = DeviceLength + sizeof(ULONG);
/* If we have enough room for copying the string */
if (sizeof(ULONG) + DeviceLength <= Stack->Parameters.DeviceIoControl.OutputBufferLength)
{
/* Copy it */
if (DeviceLength)
{
RtlCopyMemory(((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz, DeviceString, DeviceLength);
}
/* And double zero at its end - this is needed in case of multiple paths which are separated by a single 0 */
FreePool(DeviceString);
((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR)] = 0;
((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR) + 1] = 0;
return STATUS_SUCCESS;
}
else
{
/* Just return appropriate size and leave */
FreePool(DeviceString);
Irp->IoStatus.Information = sizeof(ULONG);
return STATUS_BUFFER_OVERFLOW;
}
}
/* Fail */
return STATUS_NOT_FOUND;
}
NTSTATUS

View file

@ -42,7 +42,6 @@ static const WCHAR Cunc[] = L"\\??\\C:";
/*
* TODO:
* - MountMgrQueryDosVolumePath
* - MountMgrQueryDosVolumePaths
* - MountMgrQueryVolumePaths
* - MountMgrValidateBackPointer