Lol, make sure not to implement the huge vulnerability Microsoft patched
two months ago (win2k->xp-style database migration).

Best regards,
Alex Ionescu

On Sun, Sep 13, 2015 at 6:52 PM, <[email protected]> wrote:

> 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
>   */
>
>
>
_______________________________________________
Ros-dev mailing list
[email protected]
http://www.reactos.org/mailman/listinfo/ros-dev

Reply via email to