From: Pierre Schweitzer Date: Sun, 13 Sep 2015 22:52:07 +0000 (+0000) Subject: [MOUNTMGR] X-Git-Tag: ReactOS-0.4.0~826 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=06cad138ea9f1a6c774491217d8f539c36856835 [MOUNTMGR] Implement the IOCTL IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED: - Implement WriteRemoteDatabaseEntry() - Implement MountMgrVolumeMountPointCreated() svn path=/trunk/; revision=69221 --- diff --git a/reactos/drivers/filters/mountmgr/database.c b/reactos/drivers/filters/mountmgr/database.c index 77b9e214623..a2e5fcd1a49 100644 --- a/reactos/drivers/filters/mountmgr/database.c +++ b/reactos/drivers/filters/mountmgr/database.c @@ -194,6 +194,39 @@ GetRemoteDatabaseEntry(IN HANDLE Database, return Entry; } +/* + * @implemented + */ +NTSTATUS +WriteRemoteDatabaseEntry(IN HANDLE Database, + IN LONG Offset, + IN PDATABASE_ENTRY Entry) +{ + NTSTATUS Status; + LARGE_INTEGER ByteOffset; + IO_STATUS_BLOCK IoStatusBlock; + + ByteOffset.QuadPart = Offset; + Status = ZwWriteFile(Database, + NULL, + NULL, + NULL, + &IoStatusBlock, + Entry, + Entry->EntrySize, + &ByteOffset, + NULL); + if (NT_SUCCESS(Status)) + { + if (IoStatusBlock.Information < Entry->EntrySize) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + return Status; +} + /* * @implemented */ diff --git a/reactos/drivers/filters/mountmgr/device.c b/reactos/drivers/filters/mountmgr/device.c index de6b6350c33..7c2ec7f052f 100644 --- a/reactos/drivers/filters/mountmgr/device.c +++ b/reactos/drivers/filters/mountmgr/device.c @@ -1688,15 +1688,242 @@ Cleanup: return Status; } +/* + * @implemented + */ NTSTATUS MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN NTSTATUS LockStatus) { - UNREFERENCED_PARAMETER(DeviceExtension); - UNREFERENCED_PARAMETER(Irp); - UNREFERENCED_PARAMETER(LockStatus); - return STATUS_NOT_IMPLEMENTED; + LONG Offset; + BOOLEAN Found; + NTSTATUS Status; + HANDLE RemoteDatabase; + PMOUNTDEV_UNIQUE_ID UniqueId; + PDATABASE_ENTRY DatabaseEntry; + PASSOCIATED_DEVICE_ENTRY AssociatedEntry; + PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation; + UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName; + + /* Initialize string */ + LinkTarget.Length = 0; + LinkTarget.MaximumLength = 0xC8; + LinkTarget.Buffer = AllocatePool(LinkTarget.MaximumLength); + if (LinkTarget.Buffer == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* If the mount point was created, then, it changed! + * Also use it to query some information + */ + Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName); + /* Pending means DB are under synchronization, bail out */ + if (Status == STATUS_PENDING) + { + FreePool(LinkTarget.Buffer); + FreePool(SourceDeviceName.Buffer); + FreePool(SourceSymbolicName.Buffer); + return STATUS_PENDING; + } + else if (!NT_SUCCESS(Status)) + { + FreePool(LinkTarget.Buffer); + return Status; + } + + /* Query the device information */ + Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation); + if (!NT_SUCCESS(Status)) + { + /* If it failed, first try to get volume name */ + Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName); + if (!NT_SUCCESS(Status)) + { + /* Then, try to read the symlink */ + Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget); + if (!NT_SUCCESS(Status)) + { + FreePool(LinkTarget.Buffer); + FreePool(SourceDeviceName.Buffer); + FreePool(SourceSymbolicName.Buffer); + return Status; + } + } + else + { + FreePool(VolumeName.Buffer); + } + + FreePool(SourceDeviceName.Buffer); + + SourceDeviceName.Length = LinkTarget.Length; + SourceDeviceName.MaximumLength = LinkTarget.MaximumLength; + SourceDeviceName.Buffer = LinkTarget.Buffer; + + /* Now that we have the correct source, reattempt to query information */ + Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation); + if (!NT_SUCCESS(Status)) + { + FreePool(SourceDeviceName.Buffer); + FreePool(SourceSymbolicName.Buffer); + return Status; + } + } + + FreePool(SourceDeviceName.Buffer); + + /* Get information about target device */ + Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation); + if (!NT_SUCCESS(Status)) + { + FreePool(SourceSymbolicName.Buffer); + return Status; + } + + /* Notify if not disabled */ + if (!TargetDeviceInformation->SkipNotifications) + { + PostOnlineNotification(DeviceExtension, &TargetDeviceInformation->SymbolicName); + } + + /* Open the remote database */ + RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE); + if (RemoteDatabase == 0) + { + FreePool(SourceSymbolicName.Buffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Browse all the entries */ + Offset = 0; + Found = FALSE; + for (;;) + { + DatabaseEntry = GetRemoteDatabaseEntry(RemoteDatabase, Offset); + if (DatabaseEntry == NULL) + { + break; + } + + /* Try to find ourselves */ + DbName.MaximumLength = DatabaseEntry->SymbolicNameLength; + DbName.Length = DbName.MaximumLength; + DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset); + if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE)) + { + ++DatabaseEntry->DatabaseOffset; + Status = WriteRemoteDatabaseEntry(RemoteDatabase, Offset, DatabaseEntry); + FreePool(DatabaseEntry); + Found = TRUE; + break; + } + + Offset += DatabaseEntry->EntrySize; + FreePool(DatabaseEntry); + } + + /* We couldn't find ourselves, we'll have to add ourselves */ + if (!Found) + { + ULONG EntrySize; + PUNIQUE_ID_REPLICATE UniqueIdReplicate; + + /* Query the device unique ID */ + Status = QueryDeviceInformation(&TargetVolumeName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL); + if (!NT_SUCCESS(Status)) + { + FreePool(SourceSymbolicName.Buffer); + CloseRemoteDatabase(RemoteDatabase); + return Status; + } + + /* Allocate a database entry */ + EntrySize = UniqueId->UniqueIdLength + TargetVolumeName.Length + sizeof(DATABASE_ENTRY); + DatabaseEntry = AllocatePool(EntrySize); + if (DatabaseEntry == NULL) + { + FreePool(UniqueId); + FreePool(SourceSymbolicName.Buffer); + CloseRemoteDatabase(RemoteDatabase); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Fill it in */ + DatabaseEntry->EntrySize = EntrySize; + DatabaseEntry->DatabaseOffset = 1; + DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY); + DatabaseEntry->SymbolicNameLength = TargetVolumeName.Length; + DatabaseEntry->UniqueIdOffset = TargetVolumeName.Length + sizeof(DATABASE_ENTRY); + DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength; + RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + sizeof(DATABASE_ENTRY)), TargetVolumeName.Buffer, DatabaseEntry->SymbolicNameLength); + RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength); + + /* And write it down */ + Status = AddRemoteDatabaseEntry(RemoteDatabase, DatabaseEntry); + FreePool(DatabaseEntry); + if (!NT_SUCCESS(Status)) + { + FreePool(UniqueId); + FreePool(SourceSymbolicName.Buffer); + CloseRemoteDatabase(RemoteDatabase); + return Status; + } + + /* And now, allocate an Unique ID item */ + UniqueIdReplicate = AllocatePool(sizeof(UNIQUE_ID_REPLICATE)); + if (UniqueIdReplicate == NULL) + { + FreePool(UniqueId); + FreePool(SourceSymbolicName.Buffer); + CloseRemoteDatabase(RemoteDatabase); + return Status; + } + + /* To associate it with the device */ + UniqueIdReplicate->UniqueId = UniqueId; + InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &UniqueIdReplicate->ReplicatedUniqueIdsListEntry); + } + + /* We're done with the remote database */ + CloseRemoteDatabase(RemoteDatabase); + + /* Check we were find writing the entry */ + if (!NT_SUCCESS(Status)) + { + FreePool(SourceSymbolicName.Buffer); + return Status; + } + + /* This is the end, allocate an associated entry */ + AssociatedEntry = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY)); + if (AssociatedEntry == NULL) + { + FreePool(SourceSymbolicName.Buffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Initialize its source name string */ + AssociatedEntry->String.Length = SourceSymbolicName.Length; + AssociatedEntry->String.MaximumLength = AssociatedEntry->String.Length + sizeof(UNICODE_NULL); + AssociatedEntry->String.Buffer = AllocatePool(AssociatedEntry->String.MaximumLength); + if (AssociatedEntry->String.Buffer == NULL) + { + FreePool(AssociatedEntry); + FreePool(SourceSymbolicName.Buffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Copy data & insert in list */ + RtlCopyMemory(AssociatedEntry->String.Buffer, SourceSymbolicName.Buffer, SourceSymbolicName.Length); + AssociatedEntry->String.Buffer[SourceSymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL; + AssociatedEntry->DeviceInformation = DeviceInformation; + InsertTailList(&TargetDeviceInformation->AssociatedDevicesHead, &AssociatedEntry->AssociatedDevicesEntry); + + /* We're done! */ + FreePool(SourceSymbolicName.Buffer); + return STATUS_SUCCESS; } NTSTATUS diff --git a/reactos/drivers/filters/mountmgr/mntmgr.h b/reactos/drivers/filters/mountmgr/mntmgr.h index 6f1d2f4ccdc..144249b8f3c 100644 --- a/reactos/drivers/filters/mountmgr/mntmgr.h +++ b/reactos/drivers/filters/mountmgr/mntmgr.h @@ -298,6 +298,36 @@ QueryVolumeName( OUT PUNICODE_STRING VolumeName ); +HANDLE +OpenRemoteDatabase( + IN PDEVICE_INFORMATION DeviceInformation, + IN BOOLEAN MigrateDatabase +); + +PDATABASE_ENTRY +GetRemoteDatabaseEntry( + IN HANDLE Database, + IN LONG StartingOffset +); + +NTSTATUS +WriteRemoteDatabaseEntry( + IN HANDLE Database, + IN LONG Offset, + IN PDATABASE_ENTRY Entry +); + +NTSTATUS +CloseRemoteDatabase( + IN HANDLE Database +); + +NTSTATUS +AddRemoteDatabaseEntry( + IN HANDLE Database, + IN PDATABASE_ENTRY Entry +); + /* device.c */ DRIVER_DISPATCH MountMgrDeviceControl; @@ -458,4 +488,10 @@ DeleteSymbolicLinkNameFromMemory( IN BOOLEAN MarkOffline ); +NTSTATUS +MountMgrQuerySymbolicLink( + IN PUNICODE_STRING SymbolicName, + IN OUT PUNICODE_STRING LinkTarget +); + #endif /* _MNTMGR_H_ */ diff --git a/reactos/drivers/filters/mountmgr/mountmgr.c b/reactos/drivers/filters/mountmgr/mountmgr.c index 0a20d4eee27..e018a57cb64 100644 --- a/reactos/drivers/filters/mountmgr/mountmgr.c +++ b/reactos/drivers/filters/mountmgr/mountmgr.c @@ -48,7 +48,6 @@ static const WCHAR Cunc[] = L"\\??\\C:"; * - MountMgrQueryDosVolumePaths * - MountMgrQueryVolumePaths * - MountMgrValidateBackPointer - * - MountMgrVolumeMountPointCreated * - MountMgrVolumeMountPointDeleted * - ReconcileThisDatabaseWithMasterWorker */