From: Pierre Schweitzer Date: Wed, 25 Dec 2013 22:47:30 +0000 (+0000) Subject: [MOUNTMGR] X-Git-Tag: ReactOS-0.3.16~432 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=3c03b26a4fba3abef944193bd8a28d2e58f31661;hp=ad8fe5ab9516c561f04cfee8ba667a0cbc943081 [MOUNTMGR] Implement MountMgrQueryDosVolumePath svn path=/trunk/; revision=61421 --- diff --git a/reactos/drivers/filters/mountmgr/device.c b/reactos/drivers/filters/mountmgr/device.c index 9efdf076e41..8d069c95fd7 100644 --- a/reactos/drivers/filters/mountmgr/device.c +++ b/reactos/drivers/filters/mountmgr/device.c @@ -27,6 +27,8 @@ #include "mntmgr.h" +#define MAX_DEVICES 0x3E8 /* Matches 1000 devices */ + #define NDEBUG #include @@ -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 diff --git a/reactos/drivers/filters/mountmgr/mountmgr.c b/reactos/drivers/filters/mountmgr/mountmgr.c index 2e78d4e3cbc..d955453ed1d 100644 --- a/reactos/drivers/filters/mountmgr/mountmgr.c +++ b/reactos/drivers/filters/mountmgr/mountmgr.c @@ -42,7 +42,6 @@ static const WCHAR Cunc[] = L"\\??\\C:"; /* * TODO: - * - MountMgrQueryDosVolumePath * - MountMgrQueryDosVolumePaths * - MountMgrQueryVolumePaths * - MountMgrValidateBackPointer