Отправка запросов состояния COPP
[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]
Чтобы отправить запрос о состоянии протокола COPP, заполните структуру AMCOPPStatusInput данными запроса. Элементы структуры:
- rApp. 128-разрядное случайное число, введенное в виде GUID. В ответе драйвера возвращается тот же номер. Следует выделить случайное число в куче, а затем скопировать его в структуру. Это защищает от атак, когда злоумышленник изменяет содержимое структуры AMCOPPStatusInput .
- guidStatusRequestID. Идентификатор GUID, идентифицирующий запрос. См. справочник по запросам COPP.
- dwSequence. Порядковый номер состояния. Увеличьте это значение после каждого запроса состояния. (В разделе Инициализация сеанса COPP это значение отображается как uStatusSeq в примерах кода.)
- cbSizeData. Размер (в байтах) всех дополнительных данных, необходимых для запроса.
- StatusData. Данные для запроса состояния.
Передайте структуру AMCOPPStatusInput методу IAMCertifiedOutputProtection::P rotectionStatus . Например, следующий код отправляет запрос состояния, который запрашивает доступные механизмы защиты:
AMCOPPStatusInput input;
AMCOPPStatusOutput output;
// Create a 128-bit random number.
GUID *pGuid = new GUID();
if (pGuid == NULL)
{
// Handle out-of-memory condition.
}
CryptGenRandom(hCSP, sizeof(GUID), (BYTE*)pGuid);
// Copy the random number into the command structure.
memcpy(&input.rApp, pGuid, sizeof(GUID));
// Fill in the other data.
input.guidStatusRequestID = DXVA_COPPQueryProtectionType; // Request type.
input.dwSequence = uStatusSeq; // Status sequence number.
input.cbSizeData = 0 // No other data for this query.
// Send the request.
hr = pCOPP->ProtectionStatus(&input, &output);
// Increment the sequence number each time.
++uStatusSeq;
Ответ записывается в элемент COPPStatus структуры AMCOPPStatusOutput . Размер допустимых данных в ответе указан в элементе cbSizeData . Чтобы обеспечить целостность сообщения, драйвер вычисляет код проверки подлинности сообщения (MAC) с помощью алгоритма OMAC 1 и возвращает это значение в элементе macKDI структуры. Приложение должно проверить это значение следующим образом:
- Вычислите тег OMAC для блока данных, который отображается после элемента macKDI структуры AMCOPPStatusOutput (другими словами, cbSizeData плюс COPPStatus).
- Сравните этот тег со значением в macKDI, используя прямую метку memcmp.
Алгоритм OMAC 1 подробно описан на странице https://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html. COPP использует следующие параметры OMAC-1:
- E = AES
- t = 128 бит
Данные, возвращаемые из запроса состояния, всегда начинаются с двух элементов:
- То же значение rApp , которое было передано приложением. Убедитесь, что это значение совпадает с исходным значением, хранящимся в куче.
- Значение COPP_StatusFlags , указывающее, изменилось ли состояние защиты выходных данных.
Так как подключение может быть потеряно или перенастроено, приложение должно периодически опрашивать драйвер на наличие текущего состояния. Если установлен флаг COPP_RenegotiationRequired, приложение должно попытаться сбросить уровень защиты. Если установлен флаг COPP_LinkLost, приложение должно прекратить воспроизведение содержимого. Например, флаг COPP_LinkLost может быть возвращен, так как пользователь отключил выходной соединитель. Приложение должно освободить текущий экземпляр VMR, создать новый экземпляр VMR и установить новый сеанс COPP (включая обмен ключами и проверку сертификатов).
Связанные темы