Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611/* * ReactOS kernel * Copyright (C) 2011-2012 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/filesystem/mountmgr/point.c * PURPOSE: Mount Manager - Mount points * PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org) */
#include "mntmgr.h"
#define NDEBUG#include <debug.h>
/* * @implemented */NTSTATUSMountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName){ NTSTATUS Status; PLIST_ENTRY DeviceEntry; PMOUNTDEV_UNIQUE_ID UniqueId; PSYMLINK_INFORMATION SymlinkInformation; UNICODE_STRING SymLink, TargetDeviceName; PDEVICE_INFORMATION DeviceInformation = NULL, DeviceInfo;
/* Get device name */ Status = QueryDeviceInformation(DeviceName, &TargetDeviceName, NULL, NULL, NULL, NULL, NULL, NULL); if (!NT_SUCCESS(Status)) { return Status; }
/* First of all, try to find device */ for (DeviceEntry = DeviceExtension->DeviceListHead.Flink; DeviceEntry != &(DeviceExtension->DeviceListHead); DeviceEntry = DeviceEntry->Flink) { DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
if (RtlEqualUnicodeString(&TargetDeviceName, &(DeviceInformation->DeviceName), TRUE)) { break; } }
/* Copy symbolic link name and null terminate it */ SymLink.Buffer = AllocatePool(SymbolicLinkName->Length + sizeof(UNICODE_NULL)); if (!SymLink.Buffer) { FreePool(TargetDeviceName.Buffer); return STATUS_INSUFFICIENT_RESOURCES; }
RtlCopyMemory(SymLink.Buffer, SymbolicLinkName->Buffer, SymbolicLinkName->Length); SymLink.Buffer[SymbolicLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL; SymLink.Length = SymbolicLinkName->Length; SymLink.MaximumLength = SymbolicLinkName->Length + sizeof(UNICODE_NULL);
/* If we didn't find device */ if (DeviceEntry == &(DeviceExtension->DeviceListHead)) { /* Then, try with unique ID */ Status = QueryDeviceInformation(SymbolicLinkName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL); if (!NT_SUCCESS(Status)) { FreePool(TargetDeviceName.Buffer); FreePool(SymLink.Buffer); return Status; }
/* Create a link to the device */ Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName); if (!NT_SUCCESS(Status)) { FreePool(UniqueId); FreePool(TargetDeviceName.Buffer); FreePool(SymLink.Buffer); return Status; }
/* If caller provided driver letter, delete it */ if (IsDriveLetter(&SymLink)) { DeleteRegistryDriveLetter(UniqueId); }
/* Device will be identified with its unique ID */ Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, DatabasePath, SymLink.Buffer, REG_BINARY, UniqueId->UniqueId, UniqueId->UniqueIdLength);
FreePool(UniqueId); FreePool(TargetDeviceName.Buffer); FreePool(SymLink.Buffer); return Status; }
/* If call provided a driver letter whereas device already has one * fail, this is not doable */ if (IsDriveLetter(&SymLink) && HasDriveLetter(DeviceInformation)) { FreePool(TargetDeviceName.Buffer); FreePool(SymLink.Buffer); return STATUS_INVALID_PARAMETER; }
/* Now, create a link */ Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName); FreePool(TargetDeviceName.Buffer); if (!NT_SUCCESS(Status)) { FreePool(SymLink.Buffer); return Status; }
/* Associate Unique ID <-> symbolic name */ UniqueId = DeviceInformation->UniqueId; Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, DatabasePath, SymLink.Buffer, REG_BINARY, UniqueId->UniqueId, UniqueId->UniqueIdLength); if (!NT_SUCCESS(Status)) { GlobalDeleteSymbolicLink(&SymLink); FreePool(SymLink.Buffer); return Status; }
/* Now, prepare to save the link with the device */ SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION)); if (!SymlinkInformation) { Status = STATUS_INSUFFICIENT_RESOURCES; GlobalDeleteSymbolicLink(&SymLink); FreePool(SymLink.Buffer); return Status; }
SymlinkInformation->Name.Length = SymLink.Length; SymlinkInformation->Name.MaximumLength = SymLink.Length + sizeof(UNICODE_NULL); SymlinkInformation->Name.Buffer = AllocatePool(SymlinkInformation->Name.MaximumLength); if (!SymlinkInformation->Name.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; FreePool(SymlinkInformation); GlobalDeleteSymbolicLink(&SymLink); FreePool(SymLink.Buffer); return Status; }
/* Save the link and mark it online */ RtlCopyMemory(SymlinkInformation->Name.Buffer, SymLink.Buffer, SymlinkInformation->Name.Length); SymlinkInformation->Name.Buffer[SymlinkInformation->Name.Length / sizeof(WCHAR)] = UNICODE_NULL; SymlinkInformation->Online = TRUE; InsertTailList(&DeviceInformation->SymbolicLinksListHead, &SymlinkInformation->SymbolicLinksListEntry); SendLinkCreated(&(SymlinkInformation->Name));
/* If we have a drive letter */ if (IsDriveLetter(&SymLink)) { /* Then, delete the no drive letter entry */ DeleteNoDriveLetterEntry(UniqueId);
/* And post online notification if asked */ if (!DeviceInformation->SkipNotifications) { PostOnlineNotification(DeviceExtension, &DeviceInformation->SymbolicName); } }
/* If that's a volume with automatic drive letter, it's now time to resync databases */ if (MOUNTMGR_IS_VOLUME_NAME(&SymLink) && DeviceExtension->AutomaticDriveLetter) { for (DeviceEntry = DeviceExtension->DeviceListHead.Flink; DeviceEntry != &(DeviceExtension->DeviceListHead); DeviceEntry = DeviceEntry->Flink) { DeviceInfo = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
/* If there's one, ofc! */ if (!DeviceInfo->NoDatabase) { ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInfo); } } }
/* Notify & quit */ FreePool(SymLink.Buffer); MountMgrNotify(DeviceExtension);
if (!DeviceInformation->ManuallyRegistered) { MountMgrNotifyNameChange(DeviceExtension, DeviceName, FALSE); }
return Status;}
/* * @implemented */NTSTATUSQueryPointsFromMemory(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL, IN PUNICODE_STRING SymbolicName OPTIONAL){ NTSTATUS Status; PIO_STACK_LOCATION Stack; UNICODE_STRING DeviceName; PMOUNTMGR_MOUNT_POINTS MountPoints; PDEVICE_INFORMATION DeviceInformation; PLIST_ENTRY DeviceEntry, SymlinksEntry; PSYMLINK_INFORMATION SymlinkInformation; USHORT UniqueIdLength, DeviceNameLength; ULONG TotalSize, TotalSymLinks, UniqueIdOffset, DeviceNameOffset;
/* If we got a symbolic link, query device */ if (SymbolicName) { Status = QueryDeviceInformation(SymbolicName, &DeviceName, NULL, NULL, NULL, NULL, NULL, NULL); if (!NT_SUCCESS(Status)) { return Status; } }
/* Browse all the links to count number of links & size used */ TotalSize = 0; TotalSymLinks = 0; for (DeviceEntry = DeviceExtension->DeviceListHead.Flink; DeviceEntry != &(DeviceExtension->DeviceListHead); DeviceEntry = DeviceEntry->Flink) { DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
/* If we were given an unique ID, it has to match */ if (UniqueId) { if (UniqueId->UniqueIdLength != DeviceInformation->UniqueId->UniqueIdLength) { continue; }
if (RtlCompareMemory(UniqueId->UniqueId, DeviceInformation->UniqueId->UniqueId, UniqueId->UniqueIdLength) != UniqueId->UniqueIdLength) { continue; } } /* Or, if we had a symlink, it has to match */ else if (SymbolicName) { if (!RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE)) { continue; } }
/* Once here, it matched, save device name & unique ID size */ TotalSize += DeviceInformation->DeviceName.Length + DeviceInformation->UniqueId->UniqueIdLength;
/* And count number of symlinks (and their size) */ for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink; SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead); SymlinksEntry = SymlinksEntry->Flink) { SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
TotalSize += SymlinkInformation->Name.Length; TotalSymLinks++; }
/* We had a specific item to find * if we reach that point, we found it, no need to continue */ if (UniqueId || SymbolicName) { break; } }
/* If we were looking for specific item, ensure we found it */ if (UniqueId || SymbolicName) { if (DeviceEntry == &(DeviceExtension->DeviceListHead)) { if (SymbolicName) { FreePool(DeviceName.Buffer); }
return STATUS_INVALID_PARAMETER; } }
/* Now, ensure output buffer can hold everything */ Stack = IoGetCurrentIrpStackLocation(Irp); MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer; RtlZeroMemory(MountPoints, Stack->Parameters.DeviceIoControl.OutputBufferLength);
/* Ensure we set output to let user reallocate! */ MountPoints->Size = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalSymLinks * sizeof(MOUNTMGR_MOUNT_POINT) + TotalSize; MountPoints->NumberOfMountPoints = TotalSymLinks; Irp->IoStatus.Information = MountPoints->Size;
if (MountPoints->Size > Stack->Parameters.DeviceIoControl.OutputBufferLength) { Irp->IoStatus.Information = sizeof(MOUNTMGR_MOUNT_POINTS);
if (SymbolicName) { FreePool(DeviceName.Buffer); }
return STATUS_BUFFER_OVERFLOW; }
/* Now, start putting mount points */ TotalSize = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalSymLinks * sizeof(MOUNTMGR_MOUNT_POINT); TotalSymLinks = 0; for (DeviceEntry = DeviceExtension->DeviceListHead.Flink; DeviceEntry != &(DeviceExtension->DeviceListHead); DeviceEntry = DeviceEntry->Flink) { DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
/* Find back correct mount point */ if (UniqueId) { if (UniqueId->UniqueIdLength != DeviceInformation->UniqueId->UniqueIdLength) { continue; }
if (RtlCompareMemory(UniqueId->UniqueId, DeviceInformation->UniqueId->UniqueId, UniqueId->UniqueIdLength) != UniqueId->UniqueIdLength) { continue; } } else if (SymbolicName) { if (!RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE)) { continue; } }
/* Save our information about shared data */ UniqueIdOffset = TotalSize; UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength; DeviceNameOffset = TotalSize + UniqueIdLength; DeviceNameLength = DeviceInformation->DeviceName.Length;
/* Initialize first symlink */ MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset = UniqueIdOffset; MountPoints->MountPoints[TotalSymLinks].UniqueIdLength = UniqueIdLength; MountPoints->MountPoints[TotalSymLinks].DeviceNameOffset = DeviceNameOffset; MountPoints->MountPoints[TotalSymLinks].DeviceNameLength = DeviceNameLength;
/* And copy data */ RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + UniqueIdOffset), DeviceInformation->UniqueId->UniqueId, UniqueIdLength); RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + DeviceNameOffset), DeviceInformation->DeviceName.Buffer, DeviceNameLength);
TotalSize += DeviceInformation->UniqueId->UniqueIdLength + DeviceInformation->DeviceName.Length;
/* Now we've got it, but all the data */ for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink; SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead); SymlinksEntry = SymlinksEntry->Flink) { SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
/* First, set shared data */
/* Only put UniqueID if online */ if (SymlinkInformation->Online) { MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset = UniqueIdOffset; MountPoints->MountPoints[TotalSymLinks].UniqueIdLength = UniqueIdLength; } else { MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset = 0; MountPoints->MountPoints[TotalSymLinks].UniqueIdLength = 0; }
MountPoints->MountPoints[TotalSymLinks].DeviceNameOffset = DeviceNameOffset; MountPoints->MountPoints[TotalSymLinks].DeviceNameLength = DeviceNameLength;
/* And now, copy specific symlink info */ MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameOffset = TotalSize; MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameLength = SymlinkInformation->Name.Length;
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameOffset), SymlinkInformation->Name.Buffer, SymlinkInformation->Name.Length);
/* Update counters */ TotalSymLinks++; TotalSize += SymlinkInformation->Name.Length; }
if (UniqueId || SymbolicName) { break; } }
if (SymbolicName) { FreePool(DeviceName.Buffer); }
return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSQueryPointsFromSymbolicLinkName(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN PIRP Irp){ NTSTATUS Status; ULONG TotalLength; PIO_STACK_LOCATION Stack; UNICODE_STRING DeviceName; PMOUNTMGR_MOUNT_POINTS MountPoints; PDEVICE_INFORMATION DeviceInformation = NULL; PLIST_ENTRY DeviceEntry, SymlinksEntry; PSYMLINK_INFORMATION SymlinkInformation;
/* Find device */ Status = QueryDeviceInformation(SymbolicName, &DeviceName, NULL, NULL, NULL, NULL, NULL, NULL); if (NT_SUCCESS(Status)) { /* Look for the device information */ for (DeviceEntry = DeviceExtension->DeviceListHead.Flink; DeviceEntry != &(DeviceExtension->DeviceListHead); DeviceEntry = DeviceEntry->Flink) { DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
if (RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE)) { break; } }
FreePool(DeviceName.Buffer);
if (DeviceEntry == &(DeviceExtension->DeviceListHead)) { return STATUS_INVALID_PARAMETER; }
/* Check for the link */ for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink; SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead); SymlinksEntry = SymlinksEntry->Flink) { SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
if (RtlEqualUnicodeString(SymbolicName, &SymlinkInformation->Name, TRUE)) { break; } }
if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead)) { return STATUS_INVALID_PARAMETER; } } else { /* Browse all the devices to try to find the one * that has the given link... */ for (DeviceEntry = DeviceExtension->DeviceListHead.Flink; DeviceEntry != &(DeviceExtension->DeviceListHead); DeviceEntry = DeviceEntry->Flink) { DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink; SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead); SymlinksEntry = SymlinksEntry->Flink) { SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
if (RtlEqualUnicodeString(SymbolicName, &SymlinkInformation->Name, TRUE)) { break; } }
if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead)) { break; } }
/* Even that way we didn't find, give up! */ if (DeviceEntry == &(DeviceExtension->DeviceListHead)) { return STATUS_OBJECT_NAME_NOT_FOUND; } }
/* Get output buffer */ Stack = IoGetCurrentIrpStackLocation(Irp); MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
/* Compute output length */ TotalLength = DeviceInformation->UniqueId->UniqueIdLength + SymlinkInformation->Name.Length + DeviceInformation->DeviceName.Length;
/* Give length to allow reallocation */ MountPoints->Size = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalLength; MountPoints->NumberOfMountPoints = 1; Irp->IoStatus.Information = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalLength;
if (MountPoints->Size > Stack->Parameters.DeviceIoControl.OutputBufferLength) { Irp->IoStatus.Information = sizeof(MOUNTMGR_MOUNT_POINTS);
return STATUS_BUFFER_OVERFLOW; }
/* Write out data */ MountPoints->MountPoints[0].SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS); MountPoints->MountPoints[0].SymbolicLinkNameLength = SymlinkInformation->Name.Length; /* If link is online write it's unique ID, otherwise, forget about it */ if (SymlinkInformation->Online) { MountPoints->MountPoints[0].UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINTS) + SymlinkInformation->Name.Length; MountPoints->MountPoints[0].UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength; } else { MountPoints->MountPoints[0].UniqueIdOffset = 0; MountPoints->MountPoints[0].UniqueIdLength = 0; }
MountPoints->MountPoints[0].DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS) + SymlinkInformation->Name.Length + DeviceInformation->UniqueId->UniqueIdLength; MountPoints->MountPoints[0].DeviceNameLength = DeviceInformation->DeviceName.Length;
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].SymbolicLinkNameOffset), SymlinkInformation->Name.Buffer, SymlinkInformation->Name.Length);
if (SymlinkInformation->Online) { RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].UniqueIdOffset), DeviceInformation->UniqueId->UniqueId, DeviceInformation->UniqueId->UniqueIdLength); }
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].DeviceNameOffset), DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);
return STATUS_SUCCESS;}