/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #if defined(XP_WIN) # include // needed to prevent re-definition of enums # include # include # include # include # include "opmapi.h" #endif namespace mozilla::cdmtest { #if defined(XP_WIN) typedef HRESULT(STDAPICALLTYPE* OPMGetVideoOutputsFromHMONITORProc)( HMONITOR, OPM_VIDEO_OUTPUT_SEMANTICS, ULONG*, IOPMVideoOutput***); static OPMGetVideoOutputsFromHMONITORProc sOPMGetVideoOutputsFromHMONITORProc = nullptr; static BOOL CALLBACK EnumDisplayMonitorsCallback(HMONITOR hMonitor, HDC hdc, LPRECT lprc, LPARAM pData) { std::vector* failureMsgs = (std::vector*)pData; MONITORINFOEXA miex; ZeroMemory(&miex, sizeof(miex)); miex.cbSize = sizeof(miex); if (!GetMonitorInfoA(hMonitor, &miex)) { failureMsgs->push_back("FAIL GetMonitorInfoA call failed"); } ULONG numVideoOutputs = 0; IOPMVideoOutput** opmVideoOutputArray = nullptr; HRESULT hr = sOPMGetVideoOutputsFromHMONITORProc( hMonitor, OPM_VOS_OPM_SEMANTICS, &numVideoOutputs, &opmVideoOutputArray); if (S_OK != hr) { if ((HRESULT)0x8007001f != hr && (HRESULT)0x80070032 != hr && (HRESULT)0xc02625e5 != hr) { char msg[100]; sprintf( msg, "FAIL OPMGetVideoOutputsFromHMONITOR call failed: HRESULT=0x%08lx", hr); failureMsgs->push_back(msg); } return true; } DISPLAY_DEVICEA dd; ZeroMemory(&dd, sizeof(dd)); dd.cb = sizeof(dd); if (!EnumDisplayDevicesA(miex.szDevice, 0, &dd, 1)) { failureMsgs->push_back("FAIL EnumDisplayDevicesA call failed"); } for (ULONG i = 0; i < numVideoOutputs; ++i) { OPM_RANDOM_NUMBER opmRandomNumber; BYTE* certificate = nullptr; ULONG certificateLength = 0; hr = opmVideoOutputArray[i]->StartInitialization( &opmRandomNumber, &certificate, &certificateLength); if (S_OK != hr) { char msg[100]; sprintf(msg, "FAIL StartInitialization call failed: HRESULT=0x%08lx", hr); failureMsgs->push_back(msg); } if (certificate) { CoTaskMemFree(certificate); } opmVideoOutputArray[i]->Release(); } if (opmVideoOutputArray) { CoTaskMemFree(opmVideoOutputArray); } return true; } #endif static void RunOutputProtectionAPITests() { #if defined(XP_WIN) // Get hold of OPMGetVideoOutputsFromHMONITOR function. HMODULE hDvax2DLL = GetModuleHandleW(L"dxva2.dll"); if (!hDvax2DLL) { FakeDecryptor::Message("FAIL GetModuleHandleW call failed for dxva2.dll"); return; } sOPMGetVideoOutputsFromHMONITORProc = (OPMGetVideoOutputsFromHMONITORProc)GetProcAddress( hDvax2DLL, "OPMGetVideoOutputsFromHMONITOR"); if (!sOPMGetVideoOutputsFromHMONITORProc) { FakeDecryptor::Message( "FAIL GetProcAddress call failed for OPMGetVideoOutputsFromHMONITOR"); return; } // Test EnumDisplayMonitors. // Other APIs are tested in the callback function. std::vector failureMsgs; if (!EnumDisplayMonitors(NULL, NULL, EnumDisplayMonitorsCallback, (LPARAM)&failureMsgs)) { FakeDecryptor::Message("FAIL EnumDisplayMonitors call failed"); } // Report any failures in the callback function. for (size_t i = 0; i < failureMsgs.size(); i++) { FakeDecryptor::Message(failureMsgs[i]); } #endif } static void TestOuputProtectionAPIs() { RunOutputProtectionAPITests(); FakeDecryptor::Message("OP tests completed"); } } // namespace mozilla::cdmtest