1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/* -*- 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 <d3d9.h> // needed to prevent re-definition of enums
# include <stdio.h>
# include <string>
# include <vector>
# include <windows.h>
# 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<std::string>* failureMsgs = (std::vector<std::string>*)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<std::string> 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
|