Author: pschweitzer
Date: Sun Sep 13 22:52:07 2015
New Revision: 69221
URL: http://svn.reactos.org/svn/reactos?rev=69221&view=rev
Log:
[MOUNTMGR]
Implement the IOCTL IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED:
- Implement WriteRemoteDatabaseEntry()
- Implement MountMgrVolumeMountPointCreated()
Modified:
trunk/reactos/drivers/filters/mountmgr/database.c
trunk/reactos/drivers/filters/mountmgr/device.c
trunk/reactos/drivers/filters/mountmgr/mntmgr.h
trunk/reactos/drivers/filters/mountmgr/mountmgr.c
Modified: trunk/reactos/drivers/filters/mountmgr/database.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filters/mountmgr/database.c?rev=69221&r1=69220&r2=69221&view=diff
==============================================================================
--- trunk/reactos/drivers/filters/mountmgr/database.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filters/mountmgr/database.c [iso-8859-1] Sun Sep 13 22:52:07 2015
@@ -192,6 +192,39 @@
}
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;
}
/*
Modified: trunk/reactos/drivers/filters/mountmgr/device.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filters/mountmgr/device.c?rev=69221&r1=69220&r2=69221&view=diff
==============================================================================
--- trunk/reactos/drivers/filters/mountmgr/device.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filters/mountmgr/device.c [iso-8859-1] Sun Sep 13 22:52:07 2015
@@ -1688,15 +1688,242 @@
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
Modified: trunk/reactos/drivers/filters/mountmgr/mntmgr.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filters/mountmgr/mntmgr.h?rev=69221&r1=69220&r2=69221&view=diff
==============================================================================
--- trunk/reactos/drivers/filters/mountmgr/mntmgr.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filters/mountmgr/mntmgr.h [iso-8859-1] Sun Sep 13 22:52:07 2015
@@ -298,6 +298,36 @@
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 @@
IN BOOLEAN MarkOffline
);
+NTSTATUS
+MountMgrQuerySymbolicLink(
+ IN PUNICODE_STRING SymbolicName,
+ IN OUT PUNICODE_STRING LinkTarget
+);
+
#endif /* _MNTMGR_H_ */
Modified: trunk/reactos/drivers/filters/mountmgr/mountmgr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filters/mountmgr/mountmgr.c?rev=69221&r1=69220&r2=69221&view=diff
==============================================================================
--- trunk/reactos/drivers/filters/mountmgr/mountmgr.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filters/mountmgr/mountmgr.c [iso-8859-1] Sun Sep 13 22:52:07 2015
@@ -48,7 +48,6 @@
* - MountMgrQueryDosVolumePaths
* - MountMgrQueryVolumePaths
* - MountMgrValidateBackPointer
- * - MountMgrVolumeMountPointCreated
* - MountMgrVolumeMountPointDeleted
* - ReconcileThisDatabaseWithMasterWorker
*/