Пример #1
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
MountMgrTargetDeviceNotification(IN PVOID NotificationStructure,
                                 IN PVOID Context)
{
    PDEVICE_EXTENSION DeviceExtension;
    PDEVICE_INFORMATION DeviceInformation;
    PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification;

    DeviceInformation = Context;
    DeviceExtension = DeviceInformation->DeviceExtension;
    Notification = NotificationStructure;

    /* If it's to signal that removal is complete, then, execute the function */
    if (IsEqualGUID(&(Notification->Event), &GUID_TARGET_DEVICE_REMOVE_COMPLETE))
    {
        MountMgrMountedDeviceRemoval(DeviceExtension, Notification->SymbolicLinkName);
    }
    /* It it's to signal that a volume has been mounted
     * Verify if a database sync is required and execute it
     */
    else if (IsEqualGUID(&(Notification->Event), &GUID_IO_VOLUME_MOUNT))
    {
        if (InterlockedCompareExchange(&(DeviceInformation->MountState),
                                       FALSE,
                                       TRUE) == TRUE)
        {
            InterlockedDecrement(&(DeviceInformation->MountState));
        }
        else
        {
            if (DeviceInformation->NeedsReconcile)
            {
                DeviceInformation->NeedsReconcile = FALSE;
                ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
            }
        }
    }

    return STATUS_SUCCESS;
}
Пример #2
0
/*
 * @implemented
 */
NTSTATUS
MountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension,
                          IN PUNICODE_STRING SymbolicLinkName,
                          IN PUNICODE_STRING DeviceName)
{
    NTSTATUS Status;
    PLIST_ENTRY DeviceEntry;
    PMOUNTDEV_UNIQUE_ID UniqueId;
    PSYMLINK_INFORMATION SymlinkInformation;
    UNICODE_STRING SymLink, TargetDeviceName;
    PDEVICE_INFORMATION DeviceInformation = NULL, DeviceInfo;

    /* Get device name */
    Status = QueryDeviceInformation(SymbolicLinkName,
                                    &TargetDeviceName,
                                    NULL, NULL, NULL,
                                    NULL, NULL, NULL);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    /* First of all, try to find device */
    for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
         DeviceEntry != &(DeviceExtension->DeviceListHead);
         DeviceEntry = DeviceEntry->Flink)
    {
        DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);

        if (RtlCompareUnicodeString(&TargetDeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
        {
            break;
        }
    }

    /* Copy symbolic link name and null terminate it */
    SymLink.Buffer = AllocatePool(SymbolicLinkName->Length + sizeof(UNICODE_NULL));
    if (!SymLink.Buffer)
    {
        FreePool(TargetDeviceName.Buffer);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyMemory(SymLink.Buffer, SymbolicLinkName->Buffer, SymbolicLinkName->Length);
    SymLink.Buffer[SymbolicLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL;
    SymLink.Length = SymbolicLinkName->Length;
    SymLink.MaximumLength = SymbolicLinkName->Length + sizeof(UNICODE_NULL);

    /* If we didn't find device */
    if (DeviceEntry == &(DeviceExtension->DeviceListHead))
    {
        /* Then, try with unique ID */
        Status = QueryDeviceInformation(SymbolicLinkName,
                                        NULL, &UniqueId,
                                        NULL, NULL, NULL,
                                        NULL, NULL);
        if (!NT_SUCCESS(Status))
        {
            FreePool(TargetDeviceName.Buffer);
            FreePool(SymLink.Buffer);
            return Status;
        }

        /* Create a link to the device */
        Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName);
        if (!NT_SUCCESS(Status))
        {
            FreePool(UniqueId);
            FreePool(TargetDeviceName.Buffer);
            FreePool(SymLink.Buffer);
            return Status;
        }

        /* If caller provided driver letter, delete it */
        if (IsDriveLetter(&SymLink))
        {
            DeleteRegistryDriveLetter(UniqueId);
        }

        /* Device will be identified with its unique ID */
        Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
                                       DatabasePath,
                                       SymLink.Buffer,
                                       REG_BINARY,
                                       UniqueId->UniqueId,
                                       UniqueId->UniqueIdLength);

        FreePool(UniqueId);
        FreePool(TargetDeviceName.Buffer);
        FreePool(SymLink.Buffer);
        return Status;
    }

    /* If call provided a driver letter whereas device already has one
     * fail, this is not doable
     */
    if (IsDriveLetter(&SymLink) && HasDriveLetter(DeviceInformation))
    {
        FreePool(TargetDeviceName.Buffer);
        FreePool(SymLink.Buffer);
        return STATUS_INVALID_PARAMETER;
    }

    /* Now, create a link */
    Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName);
    FreePool(TargetDeviceName.Buffer);
    if (!NT_SUCCESS(Status))
    {
        FreePool(SymLink.Buffer);
        return Status;
    }

    /* Associate Unique ID <-> symbolic name */
    UniqueId = DeviceInformation->UniqueId;
    Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
                                   DatabasePath,
                                   SymLink.Buffer,
                                   REG_BINARY,
                                   UniqueId->UniqueId,
                                   UniqueId->UniqueIdLength);
    if (!NT_SUCCESS(Status))
    {
        GlobalDeleteSymbolicLink(&SymLink);
        FreePool(SymLink.Buffer);
        return Status;
    }

    /* Now, prepare to save the link with the device */
    SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
    if (!SymlinkInformation)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        GlobalDeleteSymbolicLink(&SymLink);
        FreePool(SymLink.Buffer);
        return Status;
    }

    SymlinkInformation->Name.Length = SymLink.Length;
    SymlinkInformation->Name.MaximumLength = SymLink.Length + sizeof(UNICODE_NULL);
    SymlinkInformation->Name.Buffer = AllocatePool(SymlinkInformation->Name.MaximumLength);
    if (!SymlinkInformation->Name.Buffer)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        FreePool(SymlinkInformation);
        GlobalDeleteSymbolicLink(&SymLink);
        FreePool(SymLink.Buffer);
        return Status;
    }

    /* Save the link and mark it online */
    RtlCopyMemory(SymlinkInformation->Name.Buffer, SymLink.Buffer, SymlinkInformation->Name.Length);
    SymlinkInformation->Name.Buffer[SymlinkInformation->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
    SymlinkInformation->Online = TRUE;
    InsertTailList(&DeviceInformation->SymbolicLinksListHead, &SymlinkInformation->SymbolicLinksListEntry);
    SendLinkCreated(&(SymlinkInformation->Name));

    /* If we have a drive letter */
    if (IsDriveLetter(&SymLink))
    {
        /* Then, delete the no drive letter entry */
        DeleteNoDriveLetterEntry(UniqueId);

        /* And post online notification if asked */
        if (!DeviceInformation->SkipNotifications)
        {
            PostOnlineNotification(DeviceExtension, &DeviceInformation->SymbolicName);
        }
    }

    /* If that's a volume with automatic drive letter, it's now time to resync databases */
    if (MOUNTMGR_IS_VOLUME_NAME(&SymLink) && DeviceExtension->AutomaticDriveLetter)
    {
        for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
             DeviceEntry != &(DeviceExtension->DeviceListHead);
             DeviceEntry = DeviceEntry->Flink)
        {
            DeviceInfo = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);

            /* If there's one, ofc! */
            if (!DeviceInfo->NoDatabase)
            {
                ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInfo);
            }
        }
    }

    /* Notify & quit */
    FreePool(SymLink.Buffer);
    MountMgrNotify(DeviceExtension);

    if (!DeviceInformation->Volume)
    {
        MountMgrNotifyNameChange(DeviceExtension, DeviceName, FALSE);
    }

    return Status;
}
Пример #3
0
/*
 * @implemented
 */
VOID
MountMgrUniqueIdChangeRoutine(IN PDEVICE_EXTENSION DeviceExtension,
                              IN PMOUNTDEV_UNIQUE_ID OldUniqueId,
                              IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
{
    NTSTATUS Status;
    BOOLEAN ResyncNeeded;
    PUNIQUE_ID_REPLICATE DuplicateId;
    PDEVICE_INFORMATION DeviceInformation;
    RTL_QUERY_REGISTRY_TABLE QueryTable[2];
    PMOUNTDEV_UNIQUE_ID UniqueId, NewDuplicateId;
    PLIST_ENTRY ListHead, NextEntry, ReplicatedHead, NextReplicated;

    /* Synchronise with remote databases */
    Status = WaitForRemoteDatabaseSemaphore(DeviceExtension);
    KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);

    RtlZeroMemory(QueryTable, sizeof(QueryTable));
    QueryTable[0].QueryRoutine = ChangeUniqueIdRoutine;
    QueryTable[0].EntryContext = NewUniqueId;

    /* Write new data */
    RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
                           DatabasePath,
                           QueryTable,
                           OldUniqueId,
                           NULL);

    /* Browse all the devices to find the one that
     * owns the old unique ID
     */
    ListHead = &(DeviceExtension->DeviceListHead);
    NextEntry = ListHead->Flink;
    while (ListHead != NextEntry)
    {
        DeviceInformation = CONTAINING_RECORD(NextEntry,
                                              DEVICE_INFORMATION,
                                              DeviceListEntry);

        if (DeviceInformation->UniqueId->UniqueIdLength == OldUniqueId->UniqueIdLength &&
            RtlCompareMemory(OldUniqueId->UniqueId,
                             DeviceInformation->UniqueId->UniqueId,
                             OldUniqueId->UniqueIdLength) == OldUniqueId->UniqueIdLength)
        {
            break;
        }

        NextEntry = NextEntry->Flink;
    }

    /* If we didn't find any release everything and quit */
    if (ListHead == NextEntry)
    {
        KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
                           1, FALSE);

        if (NT_SUCCESS(Status))
        {
            ReleaseRemoteDatabaseSemaphore(DeviceExtension);
        }

        return;
    }

    /* If lock failed, then, just update this database */
    if (!NT_SUCCESS(Status))
    {
        ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
        KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
                           1, FALSE);
        return;
    }

    /* Allocate new unique ID */
    UniqueId = AllocatePool(NewUniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
    if (!UniqueId)
    {
        KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
                           1, FALSE);
        ReleaseRemoteDatabaseSemaphore(DeviceExtension);
        return;
    }

    /* Release old one */
    FreePool(DeviceInformation->UniqueId);
    /* And set new one */
    DeviceInformation->UniqueId = UniqueId;
    UniqueId->UniqueIdLength = NewUniqueId->UniqueIdLength;
    RtlCopyMemory(UniqueId->UniqueId, NewUniqueId->UniqueId, NewUniqueId->UniqueIdLength);

    /* Now, check if it's required to update replicated unique IDs as well */
    ListHead = &(DeviceExtension->DeviceListHead);
    NextEntry = ListHead->Flink;
    while (ListHead != NextEntry)
    {
        DeviceInformation = CONTAINING_RECORD(NextEntry,
                                              DEVICE_INFORMATION,
                                              DeviceListEntry);
        ResyncNeeded = FALSE;

        ReplicatedHead = &(DeviceInformation->ReplicatedUniqueIdsListHead);
        NextReplicated = ReplicatedHead->Flink;
        while (ReplicatedHead != NextReplicated)
        {
            DuplicateId = CONTAINING_RECORD(NextReplicated,
                                            UNIQUE_ID_REPLICATE,
                                            ReplicatedUniqueIdsListEntry);

            if (DuplicateId->UniqueId->UniqueIdLength == OldUniqueId->UniqueIdLength)
            {
                if (RtlCompareMemory(DuplicateId->UniqueId->UniqueId,
                                     OldUniqueId->UniqueId,
                                     OldUniqueId->UniqueIdLength) == OldUniqueId->UniqueIdLength)
                {
                    /* It was our old unique ID */
                    NewDuplicateId = AllocatePool(NewUniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
                    if (NewDuplicateId)
                    {
                        /* Update it */
                        ResyncNeeded = TRUE;
                        FreePool(DuplicateId->UniqueId);

                        DuplicateId->UniqueId = NewDuplicateId;
                        DuplicateId->UniqueId->UniqueIdLength = NewUniqueId->UniqueIdLength;
                        RtlCopyMemory(NewDuplicateId->UniqueId, NewUniqueId->UniqueId, NewUniqueId->UniqueIdLength);
                    }
                }
            }

            NextReplicated = NextReplicated->Flink;
        }

        /* If resync is required on this device, do it */
        if (ResyncNeeded)
        {
            ChangeRemoteDatabaseUniqueId(DeviceInformation, OldUniqueId, NewUniqueId);
        }

        NextEntry = NextEntry->Flink;
    }

    KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
    ReleaseRemoteDatabaseSemaphore(DeviceExtension);

    return;
}