VirtualBox

source: vbox/trunk/src/VBox/Additions/3D/win/VBoxWddmUmHlp/D3DKMT.cpp@ 101359

Last change on this file since 101359 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1/* $Id: D3DKMT.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * WDDM Kernel Mode Thunks helpers.
4 */
5
6/*
7 * Copyright (C) 2018-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* We're unable to use standard r3 vbgl-based backdoor logging API because win8 Metro apps
29 * can not do CreateFile/Read/Write by default.
30 * This is why we use miniport escape functionality to issue backdoor log string to the miniport
31 * and submit it to host via standard r0 backdoor logging api accordingly
32 */
33
34#include "UmHlpInternal.h"
35
36
37/** Loads a system DLL.
38 *
39 * @returns Module handle or NULL
40 * @param pszName The DLL name.
41 */
42DECLCALLBACK(HMODULE) VBoxWddmLoadSystemDll(const char *pszName)
43{
44 char szPath[MAX_PATH];
45 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
46 size_t cbName = strlen(pszName) + 1;
47 if (cchPath + 1 + cbName > sizeof(szPath))
48 {
49 SetLastError(ERROR_FILENAME_EXCED_RANGE);
50 return NULL;
51 }
52 szPath[cchPath] = '\\';
53 memcpy(&szPath[cchPath + 1], pszName, cbName);
54 return LoadLibraryA(szPath);
55}
56
57DECLCALLBACK(void) VBoxWddmLoadAdresses(HMODULE hmod, VBOXWDDMDLLPROC *paProcs)
58{
59 struct VBOXWDDMDLLPROC *pIter = paProcs;
60 while (pIter->pszName)
61 {
62 FARPROC pfn = GetProcAddress(hmod, pIter->pszName);
63 *pIter->ppfn = pfn;
64 ++pIter;
65 }
66}
67
68/*
69 * Kernel Mode Thunks (KMT) initialization.
70 */
71
72#define D3DKMT_LOAD_ENTRY(a) { #a, (FARPROC *)&g_D3DKMT.pfn##a }
73
74static D3DKMTFUNCTIONS g_D3DKMT = { 0 };
75static VBOXWDDMDLLPROC g_D3DKMTLoadTable[] =
76{
77 D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromHdc),
78 D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromDeviceName),
79 D3DKMT_LOAD_ENTRY(D3DKMTCloseAdapter),
80 D3DKMT_LOAD_ENTRY(D3DKMTQueryAdapterInfo),
81 D3DKMT_LOAD_ENTRY(D3DKMTEscape),
82 D3DKMT_LOAD_ENTRY(D3DKMTCreateDevice),
83 D3DKMT_LOAD_ENTRY(D3DKMTDestroyDevice),
84 D3DKMT_LOAD_ENTRY(D3DKMTCreateContext),
85 D3DKMT_LOAD_ENTRY(D3DKMTDestroyContext),
86 D3DKMT_LOAD_ENTRY(D3DKMTCreateAllocation),
87 D3DKMT_LOAD_ENTRY(D3DKMTDestroyAllocation),
88 D3DKMT_LOAD_ENTRY(D3DKMTRender),
89 D3DKMT_LOAD_ENTRY(D3DKMTPresent),
90 D3DKMT_LOAD_ENTRY(D3DKMTGetSharedPrimaryHandle),
91 D3DKMT_LOAD_ENTRY(D3DKMTQueryResourceInfo),
92 D3DKMT_LOAD_ENTRY(D3DKMTOpenResource),
93 D3DKMT_LOAD_ENTRY(D3DKMTEnumAdapters),
94 D3DKMT_LOAD_ENTRY(D3DKMTOpenAdapterFromLuid),
95 {NULL, NULL},
96};
97
98#undef D3DKMT_LOAD_ENTRY
99
100/** Initialize Kernel Mode Thunks (KMT) pointers in the g_D3DKMT structure.
101 *
102 * @returns True if successful.
103 */
104DECLCALLBACK(int) D3DKMTLoad(void)
105{
106 /* Modules which use D3DKMT must link with gdi32. */
107 HMODULE hmod = GetModuleHandleA("gdi32.dll");
108 Assert(hmod);
109 if (hmod)
110 {
111 VBoxWddmLoadAdresses(hmod, g_D3DKMTLoadTable);
112 }
113 return hmod != NULL;
114}
115
116DECLCALLBACK(D3DKMTFUNCTIONS const *) D3DKMTFunctions(void)
117{
118 return &g_D3DKMT;
119}
120
121
122/*
123 * Getting VirtualBox Graphics Adapter handle.
124 */
125
126static NTSTATUS vboxDispKmtOpenAdapterFromHdc(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
127{
128 *phAdapter = 0;
129
130 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
131 if (d3dkmt->pfnD3DKMTOpenAdapterFromHdc == NULL)
132 return STATUS_NOT_SUPPORTED;
133
134 D3DKMT_OPENADAPTERFROMHDC OpenAdapterData;
135 memset(&OpenAdapterData, 0, sizeof(OpenAdapterData));
136
137 for (int i = 0; ; ++i)
138 {
139 DISPLAY_DEVICEA dd;
140 memset(&dd, 0, sizeof(dd));
141 dd.cb = sizeof(dd);
142
143 if (!EnumDisplayDevicesA(NULL, i, &dd, 0))
144 break;
145
146 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
147 {
148 OpenAdapterData.hDc = CreateDCA(NULL, dd.DeviceName, NULL, NULL);
149 break;
150 }
151 }
152
153 Assert(OpenAdapterData.hDc);
154
155 NTSTATUS Status;
156 if (OpenAdapterData.hDc)
157 {
158 Status = d3dkmt->pfnD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
159 Assert(Status == STATUS_SUCCESS);
160 if (Status == STATUS_SUCCESS)
161 {
162 *phAdapter = OpenAdapterData.hAdapter;
163 if (pLuid)
164 {
165 *pLuid = OpenAdapterData.AdapterLuid;
166 }
167 }
168
169 DeleteDC(OpenAdapterData.hDc);
170 }
171 else
172 {
173 Status = STATUS_NOT_SUPPORTED;
174 }
175
176 return Status;
177}
178
179static NTSTATUS vboxDispKmtOpenAdapterFromLuid(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
180{
181 *phAdapter = 0;
182
183 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
184 if ( d3dkmt->pfnD3DKMTOpenAdapterFromLuid == NULL
185 || d3dkmt->pfnD3DKMTEnumAdapters == NULL)
186 return STATUS_NOT_SUPPORTED;
187
188 D3DKMT_ENUMADAPTERS EnumAdaptersData;
189 memset(&EnumAdaptersData, 0, sizeof(EnumAdaptersData));
190 EnumAdaptersData.NumAdapters = RT_ELEMENTS(EnumAdaptersData.Adapters);
191
192 NTSTATUS Status = d3dkmt->pfnD3DKMTEnumAdapters(&EnumAdaptersData);
193 Assert(Status == STATUS_SUCCESS);
194 if (Status == STATUS_SUCCESS)
195 {
196 Assert(EnumAdaptersData.NumAdapters);
197
198 /* Try the same twice: if we fail to open the adapter containing present sources,
199 * then try to open any adapter.
200 */
201 for (int iPass = 0; iPass < 2 && *phAdapter == 0; ++iPass)
202 {
203 for (ULONG i = 0; i < EnumAdaptersData.NumAdapters; ++i)
204 {
205 if (iPass > 0 || EnumAdaptersData.Adapters[i].NumOfSources)
206 {
207 D3DKMT_OPENADAPTERFROMLUID OpenAdapterData;
208 memset(&OpenAdapterData, 0, sizeof(OpenAdapterData));
209 OpenAdapterData.AdapterLuid = EnumAdaptersData.Adapters[i].AdapterLuid;
210
211 Status = d3dkmt->pfnD3DKMTOpenAdapterFromLuid(&OpenAdapterData);
212 Assert(Status == STATUS_SUCCESS);
213 if (Status == STATUS_SUCCESS)
214 {
215 *phAdapter = OpenAdapterData.hAdapter;
216 if (pLuid)
217 {
218 *pLuid = EnumAdaptersData.Adapters[i].AdapterLuid;
219 }
220 break;
221 }
222 }
223 }
224 }
225 }
226
227 return Status;
228}
229
230NTSTATUS vboxDispKmtOpenAdapter2(D3DKMT_HANDLE *phAdapter, LUID *pLuid)
231{
232 NTSTATUS Status = vboxDispKmtOpenAdapterFromLuid(phAdapter, pLuid);
233 if (Status != STATUS_SUCCESS)
234 {
235 /* Fallback for pre-Windows8 */
236 Status = vboxDispKmtOpenAdapterFromHdc(phAdapter, pLuid);
237 }
238
239 return Status;
240}
241
242NTSTATUS vboxDispKmtOpenAdapter(D3DKMT_HANDLE *phAdapter)
243{
244 return vboxDispKmtOpenAdapter2(phAdapter, NULL);
245}
246
247NTSTATUS vboxDispKmtCloseAdapter(D3DKMT_HANDLE hAdapter)
248{
249 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
250 if (d3dkmt->pfnD3DKMTCloseAdapter == NULL)
251 return STATUS_NOT_SUPPORTED;
252
253 D3DKMT_CLOSEADAPTER CloseAdapterData;
254 CloseAdapterData.hAdapter = hAdapter;
255
256 NTSTATUS Status = d3dkmt->pfnD3DKMTCloseAdapter(&CloseAdapterData);
257 Assert(Status == STATUS_SUCCESS);
258
259 return Status;
260}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette