VirtualBox

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

Last change on this file since 75556 was 75556, checked in by vboxsync, 6 years ago

VBoxWddmUmHlp: update.

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