mirror of
https://github.com/reactos/reactos.git
synced 2025-05-06 10:28:45 +00:00
[MOUNTMGR]
Implement MountMgrQueryDosVolumePath svn path=/trunk/; revision=61421
This commit is contained in:
parent
ad8fe5ab95
commit
3c03b26a4f
2 changed files with 220 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -42,7 +42,6 @@ static const WCHAR Cunc[] = L"\\??\\C:";
|
|||
|
||||
/*
|
||||
* TODO:
|
||||
* - MountMgrQueryDosVolumePath
|
||||
* - MountMgrQueryDosVolumePaths
|
||||
* - MountMgrQueryVolumePaths
|
||||
* - MountMgrValidateBackPointer
|
||||
|
|
Loading…
Reference in a new issue