VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp@ 31148

Last change on this file since 31148 was 31148, checked in by vboxsync, 14 years ago

win adds burn fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.8 KB
Line 
1/** @file
2 * VBoxTray - Display Settings Interface abstraction for XPDM & WDDM
3 */
4
5/*
6 * Copyright (C) 2006-2010 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#include "VBoxDispIf.h"
18
19#include <iprt/log.h>
20#include <iprt/err.h>
21#include <iprt/assert.h>
22
23/* display driver interface abstraction for XPDM & WDDM
24 * with WDDM we can not use ExtEscape to communicate with our driver
25 * because we do not have XPDM display driver any more, i.e. escape requests are handled by cdd
26 * that knows nothing about us */
27DWORD VBoxDispIfInit(PVBOXDISPIF pIf)
28{
29 pIf->enmMode = VBOXDISPIF_MODE_XPDM;
30 return NO_ERROR;
31}
32
33DWORD VBoxDispIfTerm(PVBOXDISPIF pIf)
34{
35 pIf->enmMode = VBOXDISPIF_MODE_UNKNOWN;
36 return NO_ERROR;
37}
38
39static DWORD vboxDispIfEscapeXPDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
40{
41 HDC hdc = GetDC(HWND_DESKTOP);
42 VOID *pvData = cbData ? VBOXDISPIFESCAPE_DATA(pEscape, VOID) : NULL;
43 int iRet = ExtEscape(hdc, pEscape->escapeCode, cbData, (LPCSTR)pvData, 0, NULL);
44 ReleaseDC(HWND_DESKTOP, hdc);
45 if (iRet > 0)
46 return VINF_SUCCESS;
47 else if (iRet == 0)
48 return ERROR_NOT_SUPPORTED;
49 /* else */
50 return ERROR_GEN_FAILURE;
51}
52
53#ifdef VBOXWDDM
54static DWORD vboxDispIfSwitchToWDDM(PVBOXDISPIF pIf)
55{
56 DWORD err = NO_ERROR;
57 OSVERSIONINFO OSinfo;
58 OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
59 GetVersionEx (&OSinfo);
60 if (OSinfo.dwMajorVersion >= 6)
61 {
62 /* this is vista and up */
63 Log((__FUNCTION__": this is vista and up\n"));
64 HMODULE hGdi32 = GetModuleHandle("gdi32");
65 if (hGdi32 != NULL)
66 {
67 bool bSupported = true;
68 pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc = (PFND3DKMT_OPENADAPTERFROMHDC)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromHdc");
69 Log((__FUNCTION__"pfnD3DKMTOpenAdapterFromHdc = %p\n", pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc));
70 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc);
71
72 pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName = (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
73 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName = %p\n", pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName));
74 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName);
75
76 pIf->modeData.wddm.pfnD3DKMTCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(hGdi32, "D3DKMTCloseAdapter");
77 Log((__FUNCTION__": pfnD3DKMTCloseAdapter = %p\n", pIf->modeData.wddm.pfnD3DKMTCloseAdapter));
78 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTCloseAdapter);
79
80 pIf->modeData.wddm.pfnD3DKMTEscape = (PFND3DKMT_ESCAPE)GetProcAddress(hGdi32, "D3DKMTEscape");
81 Log((__FUNCTION__": pfnD3DKMTEscape = %p\n", pIf->modeData.wddm.pfnD3DKMTEscape));
82 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTCloseAdapter);
83
84 pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn = (PFND3DKMT_INVALIDATEACTIVEVIDPN)GetProcAddress(hGdi32, "D3DKMTInvalidateActiveVidPn");
85 Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn = %p\n", pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn));
86 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn);
87
88 if (!bSupported)
89 {
90 Log((__FUNCTION__": one of pfnD3DKMT function pointers failed to initialize\n"));
91 err = ERROR_NOT_SUPPORTED;
92 }
93 }
94 else
95 {
96 Log((__FUNCTION__": GetModuleHandle(gdi32) failed, err(%d)\n", GetLastError()));
97 err = ERROR_NOT_SUPPORTED;
98 }
99 }
100 else
101 {
102 Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
103 err = ERROR_NOT_SUPPORTED;
104 }
105
106 return err;
107}
108
109typedef DECLCALLBACK(BOOLEAN) FNVBOXDISPIFWDDM_ADAPTEROP(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, LPCWSTR pDevName, PVOID pContext);
110typedef FNVBOXDISPIFWDDM_ADAPTEROP *PFNVBOXDISPIFWDDM_ADAPTEROP;
111static DWORD vboxDispIfWDDMAdapterOp(PCVBOXDISPIF pIf, LPCWSTR pDevName, PFNVBOXDISPIFWDDM_ADAPTEROP pfnOp, PVOID pContext)
112{
113 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME OpenAdapterData = {0};
114 wcsncpy(OpenAdapterData.DeviceName, pDevName, RT_ELEMENTS(OpenAdapterData.DeviceName) - 1 /* the last one is always \0 */);
115 DWORD err = ERROR_GEN_FAILURE;
116 NTSTATUS Status = pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName(&OpenAdapterData);
117 if (!Status)
118 {
119 BOOLEAN bCloseAdapter = pfnOp(pIf, OpenAdapterData.hAdapter, OpenAdapterData.DeviceName, pContext);
120
121 if (bCloseAdapter)
122 {
123 D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
124 ClosaAdapterData.hAdapter = OpenAdapterData.hAdapter;
125 Status = pIf->modeData.wddm.pfnD3DKMTCloseAdapter(&ClosaAdapterData);
126 if (Status)
127 {
128 Log((__FUNCTION__": pfnD3DKMTCloseAdapter failed, Status (0x%x)\n", Status));
129 /* ignore */
130 Status = 0;
131 }
132 }
133 }
134 else
135 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName failed, Status (0x%x)\n", Status));
136
137 return err;
138}
139
140typedef struct
141{
142 NTSTATUS Status;
143 PVBOXDISPIFESCAPE pEscape;
144 int cbData;
145} VBOXDISPIFWDDM_ESCAPEOP_CONTEXT, *PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT;
146
147DECLCALLBACK(BOOLEAN) vboxDispIfEscapeWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, LPCWSTR pDevName, PVOID pContext)
148{
149 PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT)pContext;
150
151 D3DKMT_ESCAPE EscapeData = {0};
152 EscapeData.hAdapter = hAdapter;
153 //EscapeData.hDevice = NULL;
154 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
155 EscapeData.Flags.HardwareAccess = 1;
156 EscapeData.pPrivateDriverData = pCtx->pEscape;
157 EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(pCtx->cbData);
158 //EscapeData.hContext = NULL;
159
160 pCtx->Status = pIf->modeData.wddm.pfnD3DKMTEscape(&EscapeData);
161
162 return TRUE;
163}
164
165static DWORD vboxDispIfEscapeWDDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
166{
167 VBOXDISPIFWDDM_ESCAPEOP_CONTEXT Ctx = {0};
168 Ctx.pEscape = pEscape;
169 Ctx.cbData = cbData;
170 DWORD err = vboxDispIfWDDMAdapterOp(pIf, L"\\\\.\\DISPLAY1", vboxDispIfEscapeWDDMOp, &Ctx);
171 if (err == NO_ERROR)
172 {
173 if (!Ctx.Status)
174 err = NO_ERROR;
175 else
176 {
177 if (Ctx.Status == 0xC00000BBL) /* not supported */
178 err = ERROR_NOT_SUPPORTED;
179 else
180 err = ERROR_GEN_FAILURE;
181 Log((__FUNCTION__": pfnD3DKMTEscape failed, Status (0x%x)\n", Ctx.Status));
182 }
183 }
184 else
185 Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
186
187 return err;
188}
189
190typedef struct
191{
192 NTSTATUS Status;
193 VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO Info;
194} VBOXDISPIFWDDM_RESIZEOP_CONTEXT, *PVBOXDISPIFWDDM_RESIZEOP_CONTEXT;
195
196DECLCALLBACK(BOOLEAN) vboxDispIfResizeWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, LPCWSTR pDevName, PVOID pContext)
197{
198 PVBOXDISPIFWDDM_RESIZEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_RESIZEOP_CONTEXT)pContext;
199
200 D3DKMT_INVALIDATEACTIVEVIDPN IAVidPnData = {0};
201 uint32_t cbData = VBOXWDDM_RECOMMENDVIDPN_SIZE(1);
202 PVBOXWDDM_RECOMMENDVIDPN pData = (PVBOXWDDM_RECOMMENDVIDPN)malloc(cbData);
203 if (pData)
204 {
205 memset(pData, 0, cbData);
206 pData->cScreenInfos = 1;
207 memcpy(&pData->aScreenInfos[0], &pCtx->Info, sizeof (VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO));
208
209 IAVidPnData.hAdapter = hAdapter;
210 IAVidPnData.pPrivateDriverData = pData;
211 IAVidPnData.PrivateDriverDataSize = cbData;
212
213 pCtx->Status = pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn(&IAVidPnData);
214 if (pCtx->Status)
215 Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn failed, Status (0x%x)\n", pCtx->Status));
216
217 free(pData);
218 }
219 else
220 {
221 Log((__FUNCTION__": malloc failed\n"));
222 pCtx->Status = -1;
223 }
224
225 return TRUE;
226}
227
228static DWORD vboxDispIfResizeWDDM(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
229{
230 VBOXDISPIFWDDM_RESIZEOP_CONTEXT Ctx = {0};
231 Ctx.Info.Id = Id;
232 Ctx.Info.Width = Width;
233 Ctx.Info.Height = Height;
234 Ctx.Info.BitsPerPixel = BitsPerPixel;
235 DWORD err = vboxDispIfWDDMAdapterOp(pIf, L"\\\\.\\DISPLAY1", vboxDispIfResizeWDDMOp, &Ctx);
236 if (err == NO_ERROR)
237 {
238 if (!Ctx.Status)
239 err = NO_ERROR;
240 else
241 {
242 if (Ctx.Status == 0xC00000BBL) /* not supported */
243 err = ERROR_NOT_SUPPORTED;
244 else
245 err = ERROR_GEN_FAILURE;
246 Log((__FUNCTION__": vboxDispIfResizeWDDMOp failed, Status (0x%x)\n", Ctx.Status));
247 }
248 }
249 else
250 Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
251
252 return err;
253}
254#endif
255
256DWORD VBoxDispIfEscape(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
257{
258 switch (pIf->enmMode)
259 {
260 case VBOXDISPIF_MODE_XPDM_NT4:
261 case VBOXDISPIF_MODE_XPDM:
262 return vboxDispIfEscapeXPDM(pIf, pEscape, cbData);
263#ifdef VBOXWDDM
264 case VBOXDISPIF_MODE_WDDM:
265 return vboxDispIfEscapeWDDM(pIf, pEscape, cbData);
266#endif
267 default:
268 Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
269 return ERROR_INVALID_PARAMETER;
270 }
271}
272
273static DWORD vboxDispIfResizeXPDM(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
274{
275 return ERROR_NOT_SUPPORTED;
276}
277
278DWORD VBoxDispIfResize(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
279{
280 switch (pIf->enmMode)
281 {
282 case VBOXDISPIF_MODE_XPDM_NT4:
283 return ERROR_NOT_SUPPORTED;
284 case VBOXDISPIF_MODE_XPDM:
285 return vboxDispIfResizeXPDM(pIf, Id, Width, Height, BitsPerPixel);
286#ifdef VBOXWDDM
287 case VBOXDISPIF_MODE_WDDM:
288 return vboxDispIfResizeWDDM(pIf, Id, Width, Height, BitsPerPixel);
289#endif
290 default:
291 Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
292 return ERROR_INVALID_PARAMETER;
293 }
294}
295
296static DWORD vboxDispIfSwitchToXPDM_NT4(PVBOXDISPIF pIf)
297{
298 return NO_ERROR;
299}
300
301static DWORD vboxDispIfSwitchToXPDM(PVBOXDISPIF pIf)
302{
303 DWORD err = NO_ERROR;
304 AssertBreakpoint();
305 OSVERSIONINFO OSinfo;
306 OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
307 GetVersionEx (&OSinfo);
308 if (OSinfo.dwMajorVersion >= 5)
309 {
310 HMODULE hUser = GetModuleHandle("USER32");
311 if (NULL != hUser)
312 {
313 bool bSupported = true;
314 *(uintptr_t *)&pIf->modeData.xpdm.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
315 Log((__FUNCTION__": pfnChangeDisplaySettingsEx = %p\n", pIf->modeData.xpdm.pfnChangeDisplaySettingsEx));
316 bSupported &= !!(pIf->modeData.xpdm.pfnChangeDisplaySettingsEx);
317
318 if (!bSupported)
319 {
320 Log((__FUNCTION__": pfnChangeDisplaySettingsEx function pointer failed to initialize\n"));
321 err = ERROR_NOT_SUPPORTED;
322 }
323 }
324 else
325 {
326 Log((__FUNCTION__": failed to get USER32 handle, err (%d)\n", GetLastError()));
327 err = ERROR_NOT_SUPPORTED;
328 }
329 }
330 else
331 {
332 Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_XPDM, because os is not >= w2k\n"));
333 err = ERROR_NOT_SUPPORTED;
334 }
335
336 return err;
337}
338
339DWORD VBoxDispIfSwitchMode(PVBOXDISPIF pIf, VBOXDISPIF_MODE enmMode, VBOXDISPIF_MODE *penmOldMode)
340{
341 /* @todo: may need to addd synchronization in case we want to change modes dynamically
342 * i.e. currently the mode is supposed to be initialized once on service initialization */
343 if (penmOldMode)
344 *penmOldMode = pIf->enmMode;
345
346 if (enmMode == pIf->enmMode)
347 return VINF_ALREADY_INITIALIZED;
348
349 DWORD err = NO_ERROR;
350 switch (enmMode)
351 {
352 case VBOXDISPIF_MODE_XPDM_NT4:
353 Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_XPDM_NT4\n"));
354 err = vboxDispIfSwitchToXPDM_NT4(pIf);
355 if (err == NO_ERROR)
356 {
357 Log((__FUNCTION__": successfully switched to XPDM_NT4 mode\n"));
358 pIf->enmMode = VBOXDISPIF_MODE_XPDM_NT4;
359 }
360 else
361 Log((__FUNCTION__": failed to switch to XPDM_NT4 mode, err (%d)\n", err));
362 break;
363 case VBOXDISPIF_MODE_XPDM:
364 Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_XPDM\n"));
365 err = vboxDispIfSwitchToXPDM(pIf);
366 if (err == NO_ERROR)
367 {
368 Log((__FUNCTION__": successfully switched to XPDM mode\n"));
369 pIf->enmMode = VBOXDISPIF_MODE_XPDM;
370 }
371 else
372 Log((__FUNCTION__": failed to switch to XPDM mode, err (%d)\n", err));
373 break;
374#ifdef VBOXWDDM
375 case VBOXDISPIF_MODE_WDDM:
376 {
377 Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_WDDM\n"));
378 err = vboxDispIfSwitchToWDDM(pIf);
379 if (err == NO_ERROR)
380 {
381 Log((__FUNCTION__": successfully switched to WDDM mode\n"));
382 pIf->enmMode = VBOXDISPIF_MODE_WDDM;
383 }
384 else
385 Log((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
386 break;
387 }
388#endif
389 default:
390 err = ERROR_INVALID_PARAMETER;
391 break;
392 }
393 return err;
394}
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