mirror of
https://github.com/reactos/reactos.git
synced 2025-05-06 18:31:26 +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"
|
#include "mntmgr.h"
|
||||||
|
|
||||||
|
#define MAX_DEVICES 0x3E8 /* Matches 1000 devices */
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
@ -833,9 +835,224 @@ NTSTATUS
|
||||||
MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension,
|
MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(DeviceExtension);
|
NTSTATUS Status;
|
||||||
UNREFERENCED_PARAMETER(Irp);
|
ULONG DevicesFound;
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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
|
NTSTATUS
|
||||||
|
|
|
@ -42,7 +42,6 @@ static const WCHAR Cunc[] = L"\\??\\C:";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
* - MountMgrQueryDosVolumePath
|
|
||||||
* - MountMgrQueryDosVolumePaths
|
* - MountMgrQueryDosVolumePaths
|
||||||
* - MountMgrQueryVolumePaths
|
* - MountMgrQueryVolumePaths
|
||||||
* - MountMgrValidateBackPointer
|
* - MountMgrValidateBackPointer
|
||||||
|
|
Loading…
Reference in a new issue