mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:35:41 +00:00
[MOUNTMGR]
Implement the IOCTL IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED: - Implement WriteRemoteDatabaseEntry() - Implement MountMgrVolumeMountPointCreated() svn path=/trunk/; revision=69221
This commit is contained in:
parent
d320870f3f
commit
06cad138ea
4 changed files with 300 additions and 5 deletions
|
@ -194,6 +194,39 @@ GetRemoteDatabaseEntry(IN HANDLE Database,
|
||||||
return Entry;
|
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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1688,15 +1688,242 @@ Cleanup:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension,
|
MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension,
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
IN NTSTATUS LockStatus)
|
IN NTSTATUS LockStatus)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(DeviceExtension);
|
LONG Offset;
|
||||||
UNREFERENCED_PARAMETER(Irp);
|
BOOLEAN Found;
|
||||||
UNREFERENCED_PARAMETER(LockStatus);
|
NTSTATUS Status;
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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
|
NTSTATUS
|
||||||
|
|
|
@ -298,6 +298,36 @@ QueryVolumeName(
|
||||||
OUT PUNICODE_STRING VolumeName
|
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 */
|
/* device.c */
|
||||||
|
|
||||||
DRIVER_DISPATCH MountMgrDeviceControl;
|
DRIVER_DISPATCH MountMgrDeviceControl;
|
||||||
|
@ -458,4 +488,10 @@ DeleteSymbolicLinkNameFromMemory(
|
||||||
IN BOOLEAN MarkOffline
|
IN BOOLEAN MarkOffline
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MountMgrQuerySymbolicLink(
|
||||||
|
IN PUNICODE_STRING SymbolicName,
|
||||||
|
IN OUT PUNICODE_STRING LinkTarget
|
||||||
|
);
|
||||||
|
|
||||||
#endif /* _MNTMGR_H_ */
|
#endif /* _MNTMGR_H_ */
|
||||||
|
|
|
@ -48,7 +48,6 @@ static const WCHAR Cunc[] = L"\\??\\C:";
|
||||||
* - MountMgrQueryDosVolumePaths
|
* - MountMgrQueryDosVolumePaths
|
||||||
* - MountMgrQueryVolumePaths
|
* - MountMgrQueryVolumePaths
|
||||||
* - MountMgrValidateBackPointer
|
* - MountMgrValidateBackPointer
|
||||||
* - MountMgrVolumeMountPointCreated
|
|
||||||
* - MountMgrVolumeMountPointDeleted
|
* - MountMgrVolumeMountPointDeleted
|
||||||
* - ReconcileThisDatabaseWithMasterWorker
|
* - ReconcileThisDatabaseWithMasterWorker
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue