Переадресация идентификаторов содержимого DRM
Системный драйвер DRMK распаковывает поток воспроизведения звука, содержащий защищенное содержимое. DRMK реализует фильтр KS, который принимает входной поток, содержащий схватки данных, распаковывает их и передает нераскрытый поток в путь к данным, состоящий из некоторого количества модулей, резидентных ядром. Эти модули могут быть фильтрами KS или другими типами драйверов. Путь к данным обычно заканчивается устройством отрисовки звука, которое преобразует цифровое содержимое в аналоговый сигнал, который можно воспроизводить через динамики.
Перед тем как разрешить нераскрытому содержимому войти в путь к данным, DRMK проверяет, что путь к данным является безопасным. Для этого DRMK проверяет подлинность каждого модуля в пути к данным, начиная с модуля в вышестоящий конце пути к данным и перемещаясь вниз на другой конец пути к данным. Этот процесс показан на следующем рисунке.
На предыдущем рисунке сплошные стрелки представляют путь к данным, а пунктирные стрелки — связи, необходимые для проверки безопасности пути к данным. Нераскрытые данные поступают в путь только после завершения проверки подлинности всех модулей в этом пути.
После проверки подлинности каждого модуля DRMK этот модуль предоставляет DRMK сведения о следующем модуле в пути к данным, чтобы его также можно было пройти проверку подлинности. По мере проверки подлинности каждый модуль получает идентификатор содержимого DRM, который идентифицирует поток.
Начиная с вышестоящий конце пути безопасных данных DRMK перенаправит идентификатор содержимого в модуль A, который, в свою очередь, перенаправит идентификатор содержимого в модуль B. Этот процесс продолжается до тех пор, пока идентификатор содержимого не будет перенаправлен в модуль Z, последний модуль в безопасном пути к данным.
На следующем рисунке показана пара смежных модулей в пути к данным.
Модуль на стороне вышестоящий вызывает одну из следующих функций DRM, чтобы предоставить DRMK сведения о подчиненном модуле и перенаправить идентификатор содержимого в этот модуль:
DrmForwardContentToDeviceObject
Каждая из этих функций "пересылки" предоставляет DRMK с идентификатором содержимого DRM, который идентифицирует защищенный поток, и сведениями, которые DRMK необходимы для проверки подлинности подчиненного модуля. Выбор того, какую из этих трех функций вызывать, зависит от типа интерфейса, который два смежных модуля используют для взаимодействия друг с другом при управлении передачей защищенного содержимого:
Если модуль вышестоящий вызывает IoCallDriver для взаимодействия с подчиненным модулем, нисходящий модуль является частью драйвера WDM. В этом случае модуль вышестоящий вызывает DrmForwardContentToDeviceObject, чтобы предоставить DRMK объект устройства, представляющий подчиненный модуль. DRMK использует объект устройства для проверки подлинности подчиненного модуля.
Если два модуля взаимодействуют через COM-интерфейс, который реализует подчиненный модуль, модуль вышестоящий вызывает DrmForwardContentToInterface. Этот вызов предоставляет DRMK с указателем на COM-интерфейс нижестоящего модуля. DRMK вызывает только методы IUnknown в этом интерфейсе и не делает никаких предположений о других методах, хотя два модуля сами должны согласиться с тем, что делают эти методы. DRMK проверяет, принадлежит ли точка входа для каждого метода в интерфейсе модулю, прошедшему проверку подлинности. Если точки входа распределены между несколькими модулями, DRMK выполняет проверку подлинности всех этих модулей.
Если два модуля не используют ни COM-интерфейс, ни функцию IoCallDriver для обмена данными, модуль вышестоящий вызывает DrmAddContentHandlers, чтобы предоставить DRMK список точек входа для "обработчиков содержимого", реализованных в нисходящем модуле. DRMK не вызывает обработчики содержимого и не делает никаких предположений относительно выполняемых ими функций. Однако DRMK выполняет проверку подлинности модуля (или модулей), в котором находятся точки входа.
После проверки подлинности подчиненный модуль должен получить следующие сведения:
Идентификатор содержимого DRM, который идентифицирует поток, содержащий защищенное содержимое. Модулю требуется этот идентификатор, чтобы сообщить DRMK о любом модуле, в который он планирует отправить защищенное содержимое.
Права на содержимое DRM, связанные с защищенным содержимым. Модуль требует прав на содержимое, чтобы обеспечить соответствующий уровень безопасности.
Каждая из трех функций пересылки предоставляет эти сведения модулю немного по-разному:
Функция DrmForwardContentToDeviceObject отправляет запрос KSPROPERTY_DRMAUDIOSTREAM_CONTENTID set-property объекту устройства подчиненного модуля. Этот запрос перенаправит идентификатор содержимого потока и права на содержимое в нижестоящий модуль.
Функция DrmForwardContentToInterface запрашивает COM-интерфейс нижестоящего модуля для интерфейса IDrmAudioStream . Если запрос выполнен успешно, функция вызывает метод IDrmAudioStream::SetContentId для пересылки идентификатора содержимого и прав содержимого в подчиненный модуль.
В случае с функцией DrmAddContentHandlers вызывающий объект (модуль вышестоящий) отвечает за пересылку идентификатора содержимого потока и прав на содержимое в подчиненный модуль. После того как DrmAddContentHandlers возвращает код успешного выполнения, указывающий, что нисходящий модуль прошел проверку подлинности, модуль вышестоящий передает идентификатор содержимого и права на содержимое нижестоящему модулю, вызывая один из его обработчиков содержимого.
Если модуль вышестоящий является драйвером miniport WaveCyclic или WavePci, он может вызвать соответствующую функцию DRM косвенно с помощью одного из следующих методов:
IDrmPort2::ForwardContentToDeviceObject
IDrmPort::ForwardContentToInterface
Дополнительные сведения см. в разделе Функции DRM.
Для простоты в предыдущем обсуждении предполагается, что каждый модуль в пути к данным принимает поток из одного источника и перенаправит этот поток в не более одного нисходящего модуля. На самом деле модуль может перенаправлять поток в два или более нисходящих модуля, но сначала он должен пройти проверку подлинности каждого нижестоящего модуля, вызвав одну из трех функций пересылки. Аналогичным образом модуль может смешивать несколько входных потоков, но он должен соблюдать права на содержимое входных потоков, обеспечивая соответствующий уровень защиты для смешанного выходного потока. Дополнительные сведения см. в описании функции DrmCreateContentMixed в разделе Идентификаторы содержимого и права на содержимое.
Типичный безопасный путь к данным состоит из системного драйвера KMixer , за которым следует волновой фильтр, представляющий устройство отрисовки звука. Фильтр реализуется как драйвер miniport WaveCyclic или WavePci в сочетании с соответствующим драйвером порта. Чтобы убедиться, что путь к данным защищен, DRMK перенаправит идентификатор содержимого в KMixer, который, в свою очередь, перенаправит идентификатор содержимого в фильтр. Драйвер порта, реализующий функцию универсального фильтра, получает идентификатор содержимого и пересылает его драйверу мини-порта. В частности, драйвер порта вызывает функцию DrmForwardContentToInterface для пересылки идентификатора содержимого в объект потока, экземпляр которого драйвер мини-порта создал для представления волнового выходного контакта на устройстве отрисовки звука. Одним из значений параметра для этого вызова является указатель на интерфейс IMiniportWaveCyclicStream или IMiniportWavePciStream объекта потока. Через этот интерфейс функция запрашивает объект потока для своего интерфейса IDrmAudioStream и вызывает метод SetContentId этого интерфейса.
Дополнительные сведения см. в разделе Реализации метода SetContentId в примере драйвера Sysvad, который рассматривается в разделе Примеры аудиодрайверов.