mirror of
https://github.com/reactos/reactos.git
synced 2024-07-10 06:35:06 +00:00
[MOUNTMGR]
Implement ReconcileThisDatabaseWithMasterWorker() which was the last missing bit of our MountMgr :-) svn path=/trunk/; revision=69292
This commit is contained in:
parent
88648de586
commit
582d858bfd
|
@ -394,11 +394,750 @@ ReleaseRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
|
||||||
KeReleaseSemaphore(&(DeviceExtension->RemoteDatabaseLock), IO_NO_INCREMENT, 1, FALSE);
|
KeReleaseSemaphore(&(DeviceExtension->RemoteDatabaseLock), IO_NO_INCREMENT, 1, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
QueryUniqueIdQueryRoutine(IN PWSTR ValueName,
|
||||||
|
IN ULONG ValueType,
|
||||||
|
IN PVOID ValueData,
|
||||||
|
IN ULONG ValueLength,
|
||||||
|
IN PVOID Context,
|
||||||
|
IN PVOID EntryContext)
|
||||||
|
{
|
||||||
|
PMOUNTDEV_UNIQUE_ID IntUniqueId;
|
||||||
|
PMOUNTDEV_UNIQUE_ID * UniqueId;
|
||||||
|
|
||||||
|
UNREFERENCED_PARAMETER(ValueName);
|
||||||
|
UNREFERENCED_PARAMETER(ValueType);
|
||||||
|
UNREFERENCED_PARAMETER(EntryContext);
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
if (ValueLength >= 0x10000)
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the Unique ID */
|
||||||
|
IntUniqueId = AllocatePool(sizeof(UniqueId) + ValueLength);
|
||||||
|
if (IntUniqueId)
|
||||||
|
{
|
||||||
|
/* Copy data & return */
|
||||||
|
IntUniqueId->UniqueIdLength = (USHORT)ValueLength;
|
||||||
|
RtlCopyMemory(&(IntUniqueId->UniqueId), ValueData, ValueLength);
|
||||||
|
|
||||||
|
UniqueId = Context;
|
||||||
|
*UniqueId = IntUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
QueryUniqueIdFromMaster(IN PDEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN PUNICODE_STRING SymbolicName,
|
||||||
|
OUT PMOUNTDEV_UNIQUE_ID * UniqueId)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PDEVICE_INFORMATION DeviceInformation;
|
||||||
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
||||||
|
|
||||||
|
/* Query the unique ID */
|
||||||
|
RtlZeroMemory(QueryTable, sizeof(QueryTable));
|
||||||
|
QueryTable[0].QueryRoutine = QueryUniqueIdQueryRoutine;
|
||||||
|
QueryTable[0].Name = SymbolicName->Buffer;
|
||||||
|
|
||||||
|
*UniqueId = NULL;
|
||||||
|
RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
||||||
|
DatabasePath,
|
||||||
|
QueryTable,
|
||||||
|
UniqueId,
|
||||||
|
NULL);
|
||||||
|
/* Unique ID found, no need to go farther */
|
||||||
|
if (*UniqueId)
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, find associate device information */
|
||||||
|
Status = FindDeviceInfo(DeviceExtension, SymbolicName, FALSE, &DeviceInformation);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*UniqueId = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
|
||||||
|
if (!*UniqueId)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return this unique ID (better than nothing) */
|
||||||
|
(*UniqueId)->UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
|
||||||
|
RtlCopyMemory(&((*UniqueId)->UniqueId), &(DeviceInformation->UniqueId->UniqueId), (*UniqueId)->UniqueIdLength);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
WriteUniqueIdToMaster(IN PDEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN PDATABASE_ENTRY DatabaseEntry)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PWCHAR SymbolicName;
|
||||||
|
PLIST_ENTRY NextEntry;
|
||||||
|
UNICODE_STRING SymbolicString;
|
||||||
|
PDEVICE_INFORMATION DeviceInformation;
|
||||||
|
|
||||||
|
/* Create symbolic name from database entry */
|
||||||
|
SymbolicName = AllocatePool(DatabaseEntry->SymbolicNameLength + sizeof(WCHAR));
|
||||||
|
if (!SymbolicName)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlCopyMemory(SymbolicName,
|
||||||
|
(PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset),
|
||||||
|
DatabaseEntry->SymbolicNameLength);
|
||||||
|
SymbolicName[DatabaseEntry->SymbolicNameLength / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
|
|
||||||
|
/* Associate the unique ID with the name from remote database */
|
||||||
|
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
||||||
|
DatabasePath,
|
||||||
|
SymbolicName,
|
||||||
|
REG_BINARY,
|
||||||
|
(PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
|
||||||
|
DatabaseEntry->UniqueIdLength);
|
||||||
|
FreePool(SymbolicName);
|
||||||
|
|
||||||
|
/* Reget symbolic name */
|
||||||
|
SymbolicString.Length = DatabaseEntry->SymbolicNameLength;
|
||||||
|
SymbolicString.MaximumLength = DatabaseEntry->SymbolicNameLength;
|
||||||
|
SymbolicString.Buffer = (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
|
||||||
|
|
||||||
|
/* Find the device using this unique ID */
|
||||||
|
for (NextEntry = DeviceExtension->DeviceListHead.Flink;
|
||||||
|
NextEntry != &(DeviceExtension->DeviceListHead);
|
||||||
|
NextEntry = NextEntry->Flink)
|
||||||
|
{
|
||||||
|
DeviceInformation = CONTAINING_RECORD(NextEntry,
|
||||||
|
DEVICE_INFORMATION,
|
||||||
|
DeviceListEntry);
|
||||||
|
|
||||||
|
if (DeviceInformation->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RtlCompareMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
|
||||||
|
DeviceInformation->UniqueId->UniqueId,
|
||||||
|
DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If found, create a mount point */
|
||||||
|
if (NextEntry != &(DeviceExtension->DeviceListHead))
|
||||||
|
{
|
||||||
|
MountMgrCreatePointWorker(DeviceExtension, &SymbolicString, &(DeviceInformation->DeviceName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ReconcileThisDatabaseWithMasterWorker(IN PVOID Parameter)
|
ReconcileThisDatabaseWithMasterWorker(IN PVOID Parameter)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(Parameter);
|
ULONG Offset;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
PMOUNTDEV_UNIQUE_ID UniqueId;
|
||||||
|
PDATABASE_ENTRY DatabaseEntry;
|
||||||
|
HANDLE DatabaseHandle, Handle;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
PDEVICE_INFORMATION ListDeviceInfo;
|
||||||
|
PLIST_ENTRY Entry, EntryInfo, NextEntry;
|
||||||
|
PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
|
||||||
|
BOOLEAN HardwareErrors, Restart, FailedFinding;
|
||||||
|
WCHAR FileNameBuffer[0x8], SymbolicNameBuffer[100];
|
||||||
|
UNICODE_STRING ReparseFile, FileName, SymbolicName, VolumeName;
|
||||||
|
FILE_REPARSE_POINT_INFORMATION ReparsePointInformation, SavedReparsePointInformation;
|
||||||
|
PDEVICE_EXTENSION DeviceExtension = ((PRECONCILE_WORK_ITEM_CONTEXT)Parameter)->DeviceExtension;
|
||||||
|
PDEVICE_INFORMATION DeviceInformation = ((PRECONCILE_WORK_ITEM_CONTEXT)Parameter)->DeviceInformation;
|
||||||
|
|
||||||
|
/* We're unloading, do nothing */
|
||||||
|
if (Unloading)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock remote DB */
|
||||||
|
if (!NT_SUCCESS(WaitForRemoteDatabaseSemaphore(DeviceExtension)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recheck for unloading */
|
||||||
|
if (Unloading)
|
||||||
|
{
|
||||||
|
goto ReleaseRDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the DB to reconcile */
|
||||||
|
KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
|
||||||
|
for (Entry = DeviceExtension->DeviceListHead.Flink;
|
||||||
|
Entry != &DeviceExtension->DeviceListHead;
|
||||||
|
Entry = Entry->Flink)
|
||||||
|
{
|
||||||
|
ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
|
||||||
|
if (ListDeviceInfo == DeviceInformation)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If not found, or if removable, bail out */
|
||||||
|
if (Entry == &DeviceExtension->DeviceListHead || DeviceInformation->Removable)
|
||||||
|
{
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
goto ReleaseRDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get our device object */
|
||||||
|
Status = IoGetDeviceObjectPointer(&ListDeviceInfo->DeviceName, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
goto ReleaseRDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceObject->Flags & 1)
|
||||||
|
{
|
||||||
|
_InterlockedExchangeAdd(&ListDeviceInfo->MountState, 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
|
||||||
|
/* Force default: no DB, and need for reconcile */
|
||||||
|
DeviceInformation->NeedsReconcile = TRUE;
|
||||||
|
DeviceInformation->NoDatabase = TRUE;
|
||||||
|
FailedFinding = FALSE;
|
||||||
|
|
||||||
|
/* Remove any associated device that refers to the DB to reconcile */
|
||||||
|
for (Entry = DeviceExtension->DeviceListHead.Flink;
|
||||||
|
Entry != &DeviceExtension->DeviceListHead;
|
||||||
|
Entry = Entry->Flink)
|
||||||
|
{
|
||||||
|
ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
|
||||||
|
|
||||||
|
EntryInfo = ListDeviceInfo->AssociatedDevicesHead.Flink;
|
||||||
|
while (EntryInfo != &ListDeviceInfo->AssociatedDevicesHead)
|
||||||
|
{
|
||||||
|
AssociatedDevice = CONTAINING_RECORD(EntryInfo, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
|
||||||
|
NextEntry = EntryInfo->Flink;
|
||||||
|
|
||||||
|
if (AssociatedDevice->DeviceInformation == DeviceInformation)
|
||||||
|
{
|
||||||
|
RemoveEntryList(&AssociatedDevice->AssociatedDevicesEntry);
|
||||||
|
FreePool(AssociatedDevice->String.Buffer);
|
||||||
|
FreePool(AssociatedDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntryInfo = NextEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the remote database */
|
||||||
|
DatabaseHandle = OpenRemoteDatabase(DeviceInformation, FALSE);
|
||||||
|
|
||||||
|
/* Prepare a string with reparse point index */
|
||||||
|
ReparseFile.Length = DeviceInformation->DeviceName.Length + ReparseIndex.Length;
|
||||||
|
ReparseFile.MaximumLength = ReparseFile.Length + sizeof(UNICODE_NULL);
|
||||||
|
ReparseFile.Buffer = AllocatePool(ReparseFile.MaximumLength);
|
||||||
|
if (ReparseFile.Buffer == NULL)
|
||||||
|
{
|
||||||
|
if (DatabaseHandle != 0)
|
||||||
|
{
|
||||||
|
CloseRemoteDatabase(DatabaseHandle);
|
||||||
|
}
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
goto ReleaseRDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RtlCopyMemory(ReparseFile.Buffer, DeviceInformation->DeviceName.Buffer,
|
||||||
|
DeviceInformation->DeviceName.Length);
|
||||||
|
RtlCopyMemory((PVOID)((ULONG_PTR)ReparseFile.Buffer + DeviceInformation->DeviceName.Length),
|
||||||
|
ReparseFile.Buffer, ReparseFile.Length);
|
||||||
|
ReparseFile.Buffer[ReparseFile.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&ReparseFile,
|
||||||
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Open reparse point directory */
|
||||||
|
HardwareErrors = IoSetThreadHardErrorMode(FALSE);
|
||||||
|
Status = ZwOpenFile(&Handle,
|
||||||
|
FILE_GENERIC_READ,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
FILE_SYNCHRONOUS_IO_ALERT);
|
||||||
|
IoSetThreadHardErrorMode(HardwareErrors);
|
||||||
|
|
||||||
|
FreePool(ReparseFile.Buffer);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
if (DatabaseHandle != 0)
|
||||||
|
{
|
||||||
|
TruncateRemoteDatabase(DatabaseHandle, 0);
|
||||||
|
CloseRemoteDatabase(DatabaseHandle);
|
||||||
|
}
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
goto ReleaseRDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Query reparse point information
|
||||||
|
* We only pay attention to mout point
|
||||||
|
*/
|
||||||
|
RtlZeroMemory(FileNameBuffer, sizeof(FileNameBuffer));
|
||||||
|
FileName.Buffer = FileNameBuffer;
|
||||||
|
FileName.Length = sizeof(FileNameBuffer);
|
||||||
|
FileName.MaximumLength = sizeof(FileNameBuffer);
|
||||||
|
((PULONG)FileNameBuffer)[0] = IO_REPARSE_TAG_MOUNT_POINT;
|
||||||
|
Status = ZwQueryDirectoryFile(Handle,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&ReparsePointInformation,
|
||||||
|
sizeof(FILE_REPARSE_POINT_INFORMATION),
|
||||||
|
FileReparsePointInformation,
|
||||||
|
TRUE,
|
||||||
|
&FileName,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ZwClose(Handle);
|
||||||
|
if (DatabaseHandle != 0)
|
||||||
|
{
|
||||||
|
TruncateRemoteDatabase(DatabaseHandle, 0);
|
||||||
|
CloseRemoteDatabase(DatabaseHandle);
|
||||||
|
}
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
goto ReleaseRDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we failed to open the remote DB previously,
|
||||||
|
* retry this time allowing migration (and thus, creation if required)
|
||||||
|
*/
|
||||||
|
if (DatabaseHandle == 0)
|
||||||
|
{
|
||||||
|
DatabaseHandle = OpenRemoteDatabase(DeviceInformation, TRUE);
|
||||||
|
if (DatabaseHandle == 0)
|
||||||
|
{
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
goto ReleaseRDS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
|
||||||
|
/* Reset all the references to our DB entries */
|
||||||
|
Offset = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
|
||||||
|
if (DatabaseEntry == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseEntry->EntryReferences = 0;
|
||||||
|
Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
goto CloseReparse;
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset += DatabaseEntry->EntrySize;
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init string for QueryVolumeName call */
|
||||||
|
SymbolicName.MaximumLength = sizeof(SymbolicNameBuffer);
|
||||||
|
SymbolicName.Length = 0;
|
||||||
|
SymbolicName.Buffer = SymbolicNameBuffer;
|
||||||
|
Restart = TRUE;
|
||||||
|
|
||||||
|
/* Start looping on reparse points */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
RtlCopyMemory(&SavedReparsePointInformation, &ReparsePointInformation, sizeof(FILE_REPARSE_POINT_INFORMATION));
|
||||||
|
Status = ZwQueryDirectoryFile(Handle,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&ReparsePointInformation,
|
||||||
|
sizeof(FILE_REPARSE_POINT_INFORMATION),
|
||||||
|
FileReparsePointInformation,
|
||||||
|
TRUE,
|
||||||
|
Restart ? &FileName : NULL,
|
||||||
|
Restart);
|
||||||
|
/* Restart only once */
|
||||||
|
if (Restart)
|
||||||
|
{
|
||||||
|
Restart = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If we get the same one, we're done, bail out */
|
||||||
|
if (ReparsePointInformation.FileReference == SavedReparsePointInformation.FileReference &&
|
||||||
|
ReparsePointInformation.Tag == SavedReparsePointInformation.Tag)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If querying failed, or if onloading, or if not returning mount points, bail out */
|
||||||
|
if (!NT_SUCCESS(Status) || Unloading || ReparsePointInformation.Tag != IO_REPARSE_TAG_MOUNT_POINT)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the volume name associated to the mount point */
|
||||||
|
Status = QueryVolumeName(Handle, &ReparsePointInformation, 0, &SymbolicName, &VolumeName);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Browse the DB to find the name */
|
||||||
|
Offset = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UNICODE_STRING DbName;
|
||||||
|
|
||||||
|
DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
|
||||||
|
if (DatabaseEntry == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
|
||||||
|
DbName.Length = DbName.MaximumLength;
|
||||||
|
DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
|
||||||
|
/* Found, we're done! */
|
||||||
|
if (RtlEqualUnicodeString(&DbName, &SymbolicName, TRUE))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset += DatabaseEntry->EntrySize;
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we found the mount point.... */
|
||||||
|
if (DatabaseEntry != NULL)
|
||||||
|
{
|
||||||
|
/* If it was referenced, reference it once more and update to remote */
|
||||||
|
if (DatabaseEntry->EntryReferences)
|
||||||
|
{
|
||||||
|
++DatabaseEntry->EntryReferences;
|
||||||
|
Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto FreeDBEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Query the Unique ID associated to that mount point in case it changed */
|
||||||
|
KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = QueryUniqueIdFromMaster(DeviceExtension, &SymbolicName, &UniqueId);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* If we failed doing so, reuse the old Unique ID and push it to master */
|
||||||
|
Status = WriteUniqueIdToMaster(DeviceExtension, DatabaseEntry);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto ReleaseDeviceLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And then, reference & write the entry */
|
||||||
|
++DatabaseEntry->EntryReferences;
|
||||||
|
Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto ReleaseDeviceLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
}
|
||||||
|
/* If the Unique ID didn't change */
|
||||||
|
else if (UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
|
||||||
|
RtlCompareMemory(UniqueId->UniqueId,
|
||||||
|
(PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
|
||||||
|
UniqueId->UniqueIdLength) == UniqueId->UniqueIdLength)
|
||||||
|
{
|
||||||
|
/* Reference the entry, and update to remote */
|
||||||
|
++DatabaseEntry->EntryReferences;
|
||||||
|
Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto FreeUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool(UniqueId);
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
}
|
||||||
|
/* Would, by chance, the Unique ID be present elsewhere? */
|
||||||
|
else if (IsUniqueIdPresent(DeviceExtension, DatabaseEntry))
|
||||||
|
{
|
||||||
|
/* Push the ID to master */
|
||||||
|
Status = WriteUniqueIdToMaster(DeviceExtension, DatabaseEntry);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto FreeUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And then, reference & write the entry */
|
||||||
|
++DatabaseEntry->EntryReferences;
|
||||||
|
Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto FreeUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool(UniqueId);
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* OK, at that point, we're facing a totally unknown unique ID
|
||||||
|
* So, get rid of the old entry, and recreate a new one with
|
||||||
|
* the know unique ID
|
||||||
|
*/
|
||||||
|
Status = DeleteRemoteDatabaseEntry(DatabaseHandle, Offset);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto FreeUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
/* Allocate a new entry big enough */
|
||||||
|
DatabaseEntry = AllocatePool(UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY));
|
||||||
|
if (DatabaseEntry == NULL)
|
||||||
|
{
|
||||||
|
goto FreeUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure it */
|
||||||
|
DatabaseEntry->EntrySize = UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY);
|
||||||
|
DatabaseEntry->EntryReferences = 1;
|
||||||
|
DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
|
||||||
|
DatabaseEntry->SymbolicNameLength = SymbolicName.Length;
|
||||||
|
DatabaseEntry->UniqueIdOffset = SymbolicName.Length + sizeof(DATABASE_ENTRY);
|
||||||
|
DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
|
||||||
|
RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset), SymbolicName.Buffer, DatabaseEntry->SymbolicNameLength);
|
||||||
|
RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
|
||||||
|
|
||||||
|
/* And write it remotely */
|
||||||
|
Status = AddRemoteDatabaseEntry(DatabaseHandle, DatabaseEntry);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
goto FreeUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool(UniqueId);
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We failed finding it remotely
|
||||||
|
* So, let's allocate a new remote DB entry
|
||||||
|
*/
|
||||||
|
KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
|
||||||
|
/* To be able to do so, we need the device Unique ID, ask master */
|
||||||
|
Status = QueryUniqueIdFromMaster(DeviceExtension, &SymbolicName, &UniqueId);
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Allocate a new entry big enough */
|
||||||
|
DatabaseEntry = AllocatePool(UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY));
|
||||||
|
if (DatabaseEntry != NULL)
|
||||||
|
{
|
||||||
|
/* Configure it */
|
||||||
|
DatabaseEntry->EntrySize = UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY);
|
||||||
|
DatabaseEntry->EntryReferences = 1;
|
||||||
|
DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
|
||||||
|
DatabaseEntry->SymbolicNameLength = SymbolicName.Length;
|
||||||
|
DatabaseEntry->UniqueIdOffset = SymbolicName.Length + sizeof(DATABASE_ENTRY);
|
||||||
|
DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
|
||||||
|
RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset), SymbolicName.Buffer, DatabaseEntry->SymbolicNameLength);
|
||||||
|
RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
|
||||||
|
|
||||||
|
/* And write it remotely */
|
||||||
|
Status = AddRemoteDatabaseEntry(DatabaseHandle, DatabaseEntry);
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
FreePool(UniqueId);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto FreeVolume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FreePool(UniqueId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find info about the device associated associated with the mount point */
|
||||||
|
KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &ListDeviceInfo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
FailedFinding = TRUE;
|
||||||
|
FreePool(VolumeName.Buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Associate the device with the currrent DB */
|
||||||
|
AssociatedDevice = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY));
|
||||||
|
if (AssociatedDevice == NULL)
|
||||||
|
{
|
||||||
|
FreePool(VolumeName.Buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AssociatedDevice->DeviceInformation = DeviceInformation;
|
||||||
|
AssociatedDevice->String.Length = VolumeName.Length;
|
||||||
|
AssociatedDevice->String.MaximumLength = VolumeName.MaximumLength;
|
||||||
|
AssociatedDevice->String.Buffer = VolumeName.Buffer;
|
||||||
|
InsertTailList(&ListDeviceInfo->AssociatedDevicesHead, &AssociatedDevice->AssociatedDevicesEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we don't have to skip notifications, notify */
|
||||||
|
if (!ListDeviceInfo->SkipNotifications)
|
||||||
|
{
|
||||||
|
PostOnlineNotification(DeviceExtension, &ListDeviceInfo->SymbolicName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't need mount points any longer */
|
||||||
|
ZwClose(Handle);
|
||||||
|
|
||||||
|
/* Look for the DB again */
|
||||||
|
KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
|
||||||
|
for (Entry = DeviceExtension->DeviceListHead.Flink;
|
||||||
|
Entry != &DeviceExtension->DeviceListHead;
|
||||||
|
Entry = Entry->Flink)
|
||||||
|
{
|
||||||
|
ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
|
||||||
|
if (ListDeviceInfo == DeviceInformation)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Entry == &DeviceExtension->DeviceListHead)
|
||||||
|
{
|
||||||
|
ListDeviceInfo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the pruning loop */
|
||||||
|
Offset = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* Get the entry */
|
||||||
|
DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
|
||||||
|
if (DatabaseEntry == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It's not referenced anylonger? Prune it */
|
||||||
|
if (DatabaseEntry->EntryReferences == 0)
|
||||||
|
{
|
||||||
|
Status = DeleteRemoteDatabaseEntry(DatabaseHandle, Offset);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
goto CloseRDB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Update the Unique IDs to reflect the changes we might have done previously */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ListDeviceInfo != NULL)
|
||||||
|
{
|
||||||
|
UpdateReplicatedUniqueIds(ListDeviceInfo, DatabaseEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset += DatabaseEntry->EntrySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We do have a DB now :-) */
|
||||||
|
if (ListDeviceInfo != NULL && !FailedFinding)
|
||||||
|
{
|
||||||
|
DeviceInformation->NoDatabase = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
|
||||||
|
goto CloseRDB;
|
||||||
|
|
||||||
|
FreeUniqueId:
|
||||||
|
FreePool(UniqueId);
|
||||||
|
ReleaseDeviceLock:
|
||||||
|
KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
|
||||||
|
FreeDBEntry:
|
||||||
|
FreePool(DatabaseEntry);
|
||||||
|
FreeVolume:
|
||||||
|
FreePool(VolumeName.Buffer);
|
||||||
|
CloseReparse:
|
||||||
|
ZwClose(Handle);
|
||||||
|
CloseRDB:
|
||||||
|
CloseRemoteDatabase(DatabaseHandle);
|
||||||
|
ReleaseRDS:
|
||||||
|
ReleaseRemoteDatabaseSemaphore(DeviceExtension);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1247,165 +1986,6 @@ OpenRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation,
|
||||||
return Database;
|
return Database;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
QueryUniqueIdQueryRoutine(IN PWSTR ValueName,
|
|
||||||
IN ULONG ValueType,
|
|
||||||
IN PVOID ValueData,
|
|
||||||
IN ULONG ValueLength,
|
|
||||||
IN PVOID Context,
|
|
||||||
IN PVOID EntryContext)
|
|
||||||
{
|
|
||||||
PMOUNTDEV_UNIQUE_ID IntUniqueId;
|
|
||||||
PMOUNTDEV_UNIQUE_ID * UniqueId;
|
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(ValueName);
|
|
||||||
UNREFERENCED_PARAMETER(ValueType);
|
|
||||||
UNREFERENCED_PARAMETER(EntryContext);
|
|
||||||
|
|
||||||
/* Sanity check */
|
|
||||||
if (ValueLength >= 0x10000)
|
|
||||||
{
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate the Unique ID */
|
|
||||||
IntUniqueId = AllocatePool(sizeof(UniqueId) + ValueLength);
|
|
||||||
if (IntUniqueId)
|
|
||||||
{
|
|
||||||
/* Copy data & return */
|
|
||||||
IntUniqueId->UniqueIdLength = (USHORT)ValueLength;
|
|
||||||
RtlCopyMemory(&(IntUniqueId->UniqueId), ValueData, ValueLength);
|
|
||||||
|
|
||||||
UniqueId = Context;
|
|
||||||
*UniqueId = IntUniqueId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
NTSTATUS
|
|
||||||
QueryUniqueIdFromMaster(IN PDEVICE_EXTENSION DeviceExtension,
|
|
||||||
IN PUNICODE_STRING SymbolicName,
|
|
||||||
OUT PMOUNTDEV_UNIQUE_ID * UniqueId)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PDEVICE_INFORMATION DeviceInformation;
|
|
||||||
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
|
||||||
|
|
||||||
/* Query the unique ID */
|
|
||||||
RtlZeroMemory(QueryTable, sizeof(QueryTable));
|
|
||||||
QueryTable[0].QueryRoutine = QueryUniqueIdQueryRoutine;
|
|
||||||
QueryTable[0].Name = SymbolicName->Buffer;
|
|
||||||
|
|
||||||
*UniqueId = NULL;
|
|
||||||
RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
||||||
DatabasePath,
|
|
||||||
QueryTable,
|
|
||||||
UniqueId,
|
|
||||||
NULL);
|
|
||||||
/* Unique ID found, no need to go farther */
|
|
||||||
if (*UniqueId)
|
|
||||||
{
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, find associate device information */
|
|
||||||
Status = FindDeviceInfo(DeviceExtension, SymbolicName, FALSE, &DeviceInformation);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
*UniqueId = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
|
|
||||||
if (!*UniqueId)
|
|
||||||
{
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return this unique ID (better than nothing) */
|
|
||||||
(*UniqueId)->UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
|
|
||||||
RtlCopyMemory(&((*UniqueId)->UniqueId), &(DeviceInformation->UniqueId->UniqueId), (*UniqueId)->UniqueIdLength);
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
NTSTATUS
|
|
||||||
WriteUniqueIdToMaster(IN PDEVICE_EXTENSION DeviceExtension,
|
|
||||||
IN PDATABASE_ENTRY DatabaseEntry)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PWCHAR SymbolicName;
|
|
||||||
PLIST_ENTRY NextEntry;
|
|
||||||
UNICODE_STRING SymbolicString;
|
|
||||||
PDEVICE_INFORMATION DeviceInformation;
|
|
||||||
|
|
||||||
/* Create symbolic name from database entry */
|
|
||||||
SymbolicName = AllocatePool(DatabaseEntry->SymbolicNameLength + sizeof(WCHAR));
|
|
||||||
if (!SymbolicName)
|
|
||||||
{
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlCopyMemory(SymbolicName,
|
|
||||||
(PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset),
|
|
||||||
DatabaseEntry->SymbolicNameLength);
|
|
||||||
SymbolicName[DatabaseEntry->SymbolicNameLength / sizeof(WCHAR)] = UNICODE_NULL;
|
|
||||||
|
|
||||||
/* Associate the unique ID with the name from remote database */
|
|
||||||
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
|
||||||
DatabasePath,
|
|
||||||
SymbolicName,
|
|
||||||
REG_BINARY,
|
|
||||||
(PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
|
|
||||||
DatabaseEntry->UniqueIdLength);
|
|
||||||
FreePool(SymbolicName);
|
|
||||||
|
|
||||||
/* Reget symbolic name */
|
|
||||||
SymbolicString.Length = DatabaseEntry->SymbolicNameLength;
|
|
||||||
SymbolicString.MaximumLength = DatabaseEntry->SymbolicNameLength;
|
|
||||||
SymbolicString.Buffer = (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
|
|
||||||
|
|
||||||
/* Find the device using this unique ID */
|
|
||||||
for (NextEntry = DeviceExtension->DeviceListHead.Flink;
|
|
||||||
NextEntry != &(DeviceExtension->DeviceListHead);
|
|
||||||
NextEntry = NextEntry->Flink)
|
|
||||||
{
|
|
||||||
DeviceInformation = CONTAINING_RECORD(NextEntry,
|
|
||||||
DEVICE_INFORMATION,
|
|
||||||
DeviceListEntry);
|
|
||||||
|
|
||||||
if (DeviceInformation->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RtlCompareMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
|
|
||||||
DeviceInformation->UniqueId->UniqueId,
|
|
||||||
DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If found, create a mount point */
|
|
||||||
if (NextEntry != &(DeviceExtension->DeviceListHead))
|
|
||||||
{
|
|
||||||
MountMgrCreatePointWorker(DeviceExtension, &SymbolicString, &(DeviceInformation->DeviceName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -420,6 +420,18 @@ HasNoDriveLetterEntry(
|
||||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
UpdateReplicatedUniqueIds(
|
||||||
|
IN PDEVICE_INFORMATION DeviceInformation,
|
||||||
|
IN PDATABASE_ENTRY DatabaseEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
IsUniqueIdPresent(
|
||||||
|
IN PDEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN PDATABASE_ENTRY DatabaseEntry
|
||||||
|
);
|
||||||
|
|
||||||
/* point.c */
|
/* point.c */
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
MountMgrCreatePointWorker(
|
MountMgrCreatePointWorker(
|
||||||
|
|
|
@ -43,11 +43,6 @@ LONG Unloading;
|
||||||
|
|
||||||
static const WCHAR Cunc[] = L"\\??\\C:";
|
static const WCHAR Cunc[] = L"\\??\\C:";
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO:
|
|
||||||
* - ReconcileThisDatabaseWithMasterWorker
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue