1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #if defined(XP_WIN)
8 #include <d3d9.h> // needed to prevent re-definition of enums
9 #include <stdio.h>
10 #include <string>
11 #include <vector>
12 #include <windows.h>
13
14 #include "opmapi.h"
15 #endif
16
17 namespace mozilla {
18 namespace gmptest {
19
20 #if defined(XP_WIN)
21 typedef HRESULT(STDAPICALLTYPE * OPMGetVideoOutputsFromHMONITORProc)
22 (HMONITOR, OPM_VIDEO_OUTPUT_SEMANTICS, ULONG*, IOPMVideoOutput***);
23
24 static OPMGetVideoOutputsFromHMONITORProc sOPMGetVideoOutputsFromHMONITORProc = nullptr;
25
EnumDisplayMonitorsCallback(HMONITOR hMonitor,HDC hdc,LPRECT lprc,LPARAM pData)26 static BOOL CALLBACK EnumDisplayMonitorsCallback(HMONITOR hMonitor, HDC hdc,
27 LPRECT lprc, LPARAM pData)
28 {
29 std::vector<std::string>* failureMsgs = (std::vector<std::string>*)pData;
30
31 MONITORINFOEXA miex;
32 ZeroMemory(&miex, sizeof(miex));
33 miex.cbSize = sizeof(miex);
34 if (!GetMonitorInfoA(hMonitor, &miex)) {
35 failureMsgs->push_back("FAIL GetMonitorInfoA call failed");
36 }
37
38 ULONG numVideoOutputs = 0;
39 IOPMVideoOutput** opmVideoOutputArray = nullptr;
40 HRESULT hr = sOPMGetVideoOutputsFromHMONITORProc(hMonitor,
41 OPM_VOS_OPM_SEMANTICS,
42 &numVideoOutputs,
43 &opmVideoOutputArray);
44 if (S_OK != hr) {
45 if (0x8007001f != hr && 0x80070032 != hr && 0xc02625e5 != hr) {
46 char msg[100];
47 sprintf(msg, "FAIL OPMGetVideoOutputsFromHMONITOR call failed: HRESULT=0x%08x", hr);
48 failureMsgs->push_back(msg);
49 }
50 return true;
51 }
52
53 DISPLAY_DEVICEA dd;
54 ZeroMemory(&dd, sizeof(dd));
55 dd.cb = sizeof(dd);
56 if (!EnumDisplayDevicesA(miex.szDevice, 0, &dd, 1)) {
57 failureMsgs->push_back("FAIL EnumDisplayDevicesA call failed");
58 }
59
60 for (ULONG i = 0; i < numVideoOutputs; ++i) {
61 OPM_RANDOM_NUMBER opmRandomNumber;
62 BYTE* certificate = nullptr;
63 ULONG certificateLength = 0;
64 hr = opmVideoOutputArray[i]->StartInitialization(&opmRandomNumber,
65 &certificate,
66 &certificateLength);
67 if (S_OK != hr) {
68 char msg[100];
69 sprintf(msg, "FAIL StartInitialization call failed: HRESULT=0x%08x", hr);
70 failureMsgs->push_back(msg);
71 }
72
73 if (certificate) {
74 CoTaskMemFree(certificate);
75 }
76
77 opmVideoOutputArray[i]->Release();
78 }
79
80 if (opmVideoOutputArray) {
81 CoTaskMemFree(opmVideoOutputArray);
82 }
83
84 return true;
85 }
86 #endif
87
88 static void
RunOutputProtectionAPITests()89 RunOutputProtectionAPITests()
90 {
91 #if defined(XP_WIN)
92 // Get hold of OPMGetVideoOutputsFromHMONITOR function.
93 HMODULE hDvax2DLL = GetModuleHandleW(L"dxva2.dll");
94 if (!hDvax2DLL) {
95 FakeDecryptor::Message("FAIL GetModuleHandleW call failed for dxva2.dll");
96 return;
97 }
98
99 sOPMGetVideoOutputsFromHMONITORProc = (OPMGetVideoOutputsFromHMONITORProc)
100 GetProcAddress(hDvax2DLL, "OPMGetVideoOutputsFromHMONITOR");
101 if (!sOPMGetVideoOutputsFromHMONITORProc) {
102 FakeDecryptor::Message("FAIL GetProcAddress call failed for OPMGetVideoOutputsFromHMONITOR");
103 return;
104 }
105
106 // Test EnumDisplayMonitors.
107 // Other APIs are tested in the callback function.
108 std::vector<std::string> failureMsgs;
109 if (!EnumDisplayMonitors(NULL, NULL, EnumDisplayMonitorsCallback,
110 (LPARAM) &failureMsgs)) {
111 FakeDecryptor::Message("FAIL EnumDisplayMonitors call failed");
112 }
113
114 // Report any failures in the callback function.
115 for (size_t i = 0; i < failureMsgs.size(); i++) {
116 FakeDecryptor::Message(failureMsgs[i]);
117 }
118 #endif
119 }
120
121 static void
TestOuputProtectionAPIs()122 TestOuputProtectionAPIs()
123 {
124 RunOutputProtectionAPITests();
125 FakeDecryptor::Message("OP tests completed");
126 return;
127 }
128
129 } // namespace gmptest
130 } // namespace mozilla
131