VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp@ 24391

Last change on this file since 24391 was 24320, checked in by vboxsync, 15 years ago

more RT_ZERO()

  • Property svn:eol-style set to native
File size: 26.4 KB
Line 
1/* $Id: $ */
2/** @file
3 * VBoxSeamless - Display notifications.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21#define _WIN32_WINNT 0x0500
22#include <windows.h>
23#include "VBoxTray.h"
24#include "VBoxSeamless.h"
25#include <VBoxHook.h>
26#include <VBoxDisplay.h>
27#include <VBox/VMMDev.h>
28#include <iprt/assert.h>
29#include "helpers.h"
30#include <malloc.h>
31
32typedef struct _VBOXDISPLAYCONTEXT
33{
34 const VBOXSERVICEENV *pEnv;
35
36 /* ChangeDisplaySettingsEx does not exist in NT. ResizeDisplayDevice uses the function. */
37 LONG (WINAPI * pfnChangeDisplaySettingsEx)(LPCTSTR lpszDeviceName, LPDEVMODE lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam);
38
39 /* EnumDisplayDevices does not exist in NT. isVBoxDisplayDriverActive et al. are using these functions. */
40 BOOL (WINAPI * pfnEnumDisplayDevices)(IN LPCSTR lpDevice, IN DWORD iDevNum, OUT PDISPLAY_DEVICEA lpDisplayDevice, IN DWORD dwFlags);
41
42} VBOXDISPLAYCONTEXT;
43
44static VBOXDISPLAYCONTEXT gCtx = {0};
45
46int VBoxDisplayInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
47{
48 OSVERSIONINFO OSinfo;
49 OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
50 GetVersionEx (&OSinfo);
51
52 HMODULE hUser = GetModuleHandle("USER32");
53
54 gCtx.pEnv = pEnv;
55
56 if (NULL == hUser)
57 {
58 Log(("VBoxTray: Could not get module handle of USER32.DLL!\n"));
59 return VERR_NOT_IMPLEMENTED;
60 }
61 else if (OSinfo.dwMajorVersion >= 5) /* APIs available only on W2K and up! */
62 {
63 *(uintptr_t *)&gCtx.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
64 Log(("VBoxTray: pfnChangeDisplaySettingsEx = %p\n", gCtx.pfnChangeDisplaySettingsEx));
65
66 *(uintptr_t *)&gCtx.pfnEnumDisplayDevices = (uintptr_t)GetProcAddress(hUser, "EnumDisplayDevicesA");
67 Log(("VBoxTray: pfnEnumDisplayDevices = %p\n", gCtx.pfnEnumDisplayDevices));
68 }
69 else if (OSinfo.dwMajorVersion <= 4) /* Windows NT 4.0 */
70 {
71 /* Nothing to do here yet */
72 }
73 else /* Unsupported platform */
74 {
75 Log(("VBoxTray: Warning, display for platform not handled yet!\n"));
76 return VERR_NOT_IMPLEMENTED;
77 }
78
79 Log(("VBoxTray: Display init successful.\n"));
80
81 *pfStartThread = true;
82 *ppInstance = (void *)&gCtx;
83 return VINF_SUCCESS;
84}
85
86void VBoxDisplayDestroy (const VBOXSERVICEENV *pEnv, void *pInstance)
87{
88 return;
89}
90
91static bool isVBoxDisplayDriverActive (VBOXDISPLAYCONTEXT *pCtx)
92{
93 bool result = false;
94
95 if( pCtx->pfnEnumDisplayDevices )
96 {
97 INT devNum = 0;
98 DISPLAY_DEVICE dispDevice;
99 FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0);
100 dispDevice.cb = sizeof(DISPLAY_DEVICE);
101
102 Log(("Checking for active VBox display driver (W2K+)...\n"));
103
104 while (EnumDisplayDevices(NULL,
105 devNum,
106 &dispDevice,
107 0))
108 {
109 Log(("DevNum:%d\nName:%s\nString:%s\nID:%s\nKey:%s\nFlags=%08X\n\n",
110 devNum,
111 &dispDevice.DeviceName[0],
112 &dispDevice.DeviceString[0],
113 &dispDevice.DeviceID[0],
114 &dispDevice.DeviceKey[0],
115 dispDevice.StateFlags));
116
117 if (dispDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
118 {
119 Log(("Primary device.\n"));
120
121 if (strcmp(&dispDevice.DeviceString[0], "VirtualBox Graphics Adapter") == 0)
122 result = true;
123
124 break;
125 }
126
127 FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0);
128
129 dispDevice.cb = sizeof(DISPLAY_DEVICE);
130
131 devNum++;
132 }
133 }
134 else /* This must be NT 4 or something really old, so don't use EnumDisplayDevices() here ... */
135 {
136 Log(("Checking for active VBox display driver (NT or older)...\n"));
137
138 DEVMODE tempDevMode;
139 ZeroMemory (&tempDevMode, sizeof (tempDevMode));
140 tempDevMode.dmSize = sizeof(DEVMODE);
141 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &tempDevMode); /* Get current display device settings */
142
143 /* Check for the short name, because all long stuff would be truncated */
144 if (strcmp((char*)&tempDevMode.dmDeviceName[0], "VBoxDisp") == 0)
145 result = true;
146 }
147
148 return result;
149}
150
151/* Returns TRUE to try again. */
152static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
153{
154 BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0);
155
156 DISPLAY_DEVICE DisplayDevice;
157
158 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
159 DisplayDevice.cb = sizeof(DisplayDevice);
160
161 /* Find out how many display devices the system has */
162 DWORD NumDevices = 0;
163 DWORD i = 0;
164 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
165 {
166 Log(("[%d] %s\n", i, DisplayDevice.DeviceName));
167
168 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
169 {
170 Log(("ResizeDisplayDevice: Found primary device. err %d\n", GetLastError ()));
171 NumDevices++;
172 }
173 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
174 {
175
176 Log(("ResizeDisplayDevice: Found secondary device. err %d\n", GetLastError ()));
177 NumDevices++;
178 }
179
180 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
181 DisplayDevice.cb = sizeof(DisplayDevice);
182 i++;
183 }
184
185 Log(("ResizeDisplayDevice: Found total %d devices. err %d\n", NumDevices, GetLastError ()));
186
187 if (NumDevices == 0 || Id >= NumDevices)
188 {
189 Log(("ResizeDisplayDevice: Requested identifier %d is invalid. err %d\n", Id, GetLastError ()));
190 return FALSE;
191 }
192
193 DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
194 DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
195 RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices);
196
197 /* Fetch information about current devices and modes. */
198 DWORD DevNum = 0;
199 DWORD DevPrimaryNum = 0;
200
201 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
202 DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
203
204 i = 0;
205 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
206 {
207 Log(("ResizeDisplayDevice: [%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName));
208
209 BOOL bFetchDevice = FALSE;
210
211 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
212 {
213 Log(("ResizeDisplayDevice: Found primary device. err %d\n", GetLastError ()));
214 DevPrimaryNum = DevNum;
215 bFetchDevice = TRUE;
216 }
217 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
218 {
219
220 Log(("ResizeDisplayDevice: Found secondary device. err %d\n", GetLastError ()));
221 bFetchDevice = TRUE;
222 }
223
224 if (bFetchDevice)
225 {
226 if (DevNum >= NumDevices)
227 {
228 Log(("ResizeDisplayDevice: %d >= %d\n", NumDevices, DevNum));
229 return FALSE;
230 }
231
232 paDisplayDevices[DevNum] = DisplayDevice;
233
234 /* First try to get the video mode stored in registry (ENUM_REGISTRY_SETTINGS).
235 * A secondary display could be not active at the moment and would not have
236 * a current video mode (ENUM_CURRENT_SETTINGS).
237 */
238 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE));
239 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE);
240 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
241 ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum]))
242 {
243 Log(("ResizeDisplayDevice: EnumDisplaySettings err %d\n", GetLastError ()));
244 return FALSE;
245 }
246
247 if ( paDeviceModes[DevNum].dmPelsWidth == 0
248 || paDeviceModes[DevNum].dmPelsHeight == 0)
249 {
250 /* No ENUM_REGISTRY_SETTINGS yet. Seen on Vista after installation.
251 * Get the current video mode then.
252 */
253 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE));
254 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE);
255 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
256 ENUM_CURRENT_SETTINGS, &paDeviceModes[DevNum]))
257 {
258 /* ENUM_CURRENT_SETTINGS returns FALSE when the display is not active:
259 * for example a disabled secondary display.
260 * Do not return here, ignore the error and set the display info to 0x0x0.
261 */
262 Log(("EnumDisplaySettings(ENUM_CURRENT_SETTINGS) err %d\n", GetLastError ()));
263 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE));
264 }
265 }
266
267 Log(("ResizeDisplayDevice: %dx%dx%d at %d,%d\n",
268 paDeviceModes[DevNum].dmPelsWidth,
269 paDeviceModes[DevNum].dmPelsHeight,
270 paDeviceModes[DevNum].dmBitsPerPel,
271 paDeviceModes[DevNum].dmPosition.x,
272 paDeviceModes[DevNum].dmPosition.y));
273
274 paRects[DevNum].left = paDeviceModes[DevNum].dmPosition.x;
275 paRects[DevNum].top = paDeviceModes[DevNum].dmPosition.y;
276 paRects[DevNum].right = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
277 paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
278 DevNum++;
279 }
280
281 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
282 DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
283 i++;
284 }
285
286 /* Width, height equal to 0 means that this value must be not changed.
287 * Update input parameters if necessary.
288 * Note: BitsPerPixel is taken into account later, when new rectangles
289 * are assigned to displays.
290 */
291 if (Width == 0)
292 {
293 Width = paRects[Id].right - paRects[Id].left;
294 }
295
296 if (Height == 0)
297 {
298 Height = paRects[Id].bottom - paRects[Id].top;
299 }
300
301 /* Check whether a mode reset or a change is requested. */
302 if ( !fModeReset
303 && paRects[Id].right - paRects[Id].left == Width
304 && paRects[Id].bottom - paRects[Id].top == Height
305 && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel)
306 {
307 Log(("ResizeDisplayDevice: Already at desired resolution.\n"));
308 return FALSE;
309 }
310
311 resizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height);
312#ifdef Log
313 for (i = 0; i < NumDevices; i++)
314 {
315 Log(("ResizeDisplayDevice: [%d]: %d,%d %dx%d\n",
316 i, paRects[i].left, paRects[i].top,
317 paRects[i].right - paRects[i].left,
318 paRects[i].bottom - paRects[i].top));
319 }
320#endif /* Log */
321
322 /* Without this, Windows will not ask the miniport for its
323 * mode table but uses an internal cache instead.
324 */
325 DEVMODE tempDevMode;
326 ZeroMemory (&tempDevMode, sizeof (tempDevMode));
327 tempDevMode.dmSize = sizeof(DEVMODE);
328 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode);
329
330 /* Assign the new rectangles to displays. */
331 for (i = 0; i < NumDevices; i++)
332 {
333 paDeviceModes[i].dmPosition.x = paRects[i].left;
334 paDeviceModes[i].dmPosition.y = paRects[i].top;
335 paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left;
336 paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top;
337
338 /* On Vista one must specify DM_BITSPERPEL.
339 * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
340 */
341 paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
342
343 if ( i == Id
344 && BitsPerPixel != 0)
345 {
346 /* Change dmBitsPerPel if requested. */
347 paDeviceModes[i].dmBitsPerPel = BitsPerPixel;
348 }
349
350 Log(("ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
351 gCtx.pfnChangeDisplaySettingsEx,
352 paDeviceModes[i].dmPelsWidth,
353 paDeviceModes[i].dmPelsHeight,
354 paDeviceModes[i].dmBitsPerPel,
355 paDeviceModes[i].dmPosition.x,
356 paDeviceModes[i].dmPosition.y));
357
358 gCtx.pfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
359 &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
360 Log(("ResizeDisplayDevice: ChangeDisplaySettingsEx position err %d\n", GetLastError ()));
361 }
362
363 /* A second call to ChangeDisplaySettings updates the monitor. */
364 LONG status = ChangeDisplaySettings(NULL, 0);
365 Log(("ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status));
366 if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE)
367 {
368 /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */
369 return FALSE;
370 }
371
372 /* Retry the request. */
373 return TRUE;
374}
375
376/**
377 * Thread function to wait for and process display change
378 * requests
379 */
380unsigned __stdcall VBoxDisplayThread (void *pInstance)
381{
382 VBOXDISPLAYCONTEXT *pCtx = (VBOXDISPLAYCONTEXT *)pInstance;
383 HANDLE gVBoxDriver = pCtx->pEnv->hDriver;
384 bool fTerminate = false;
385 VBoxGuestFilterMaskInfo maskInfo;
386 DWORD cbReturned;
387
388 maskInfo.u32OrMask = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED;
389 maskInfo.u32NotMask = 0;
390 if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
391 {
392 Log(("VBoxDisplayThread : DeviceIOControl(CtlMask - or) succeeded\n"));
393 }
394 else
395 {
396 Log(("VBoxDisplayThread : DeviceIOControl(CtlMask) failed, DisplayChangeThread exited\n"));
397 return -1;
398 }
399
400 do
401 {
402 /* wait for a display change event */
403 VBoxGuestWaitEventInfo waitEvent;
404 waitEvent.u32TimeoutIn = 1000;
405 waitEvent.u32EventMaskIn = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED;
406 if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL))
407 {
408 /*Log(("VBoxDisplayThread : DeviceIOControl succeded\n"));*/
409
410 if (NULL == pCtx) {
411 Log(("VBoxDisplayThread : Invalid context detected!\n"));
412 break;
413 }
414
415 if (NULL == pCtx->pEnv) {
416 Log(("VBoxDisplayThread : Invalid context environment detected!\n"));
417 break;
418 }
419
420 /* are we supposed to stop? */
421 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 0) == WAIT_OBJECT_0)
422 break;
423
424 /*Log(("VBoxDisplayThread : checking event\n"));*/
425
426 /* did we get the right event? */
427 if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
428 {
429 Log(("VBoxDisplayThread : going to get display change information.\n"));
430
431 /* We got at least one event. Read the requested resolution
432 * and try to set it until success. New events will not be seen
433 * but a new resolution will be read in this poll loop.
434 */
435 for (;;)
436 {
437 /* get the display change request */
438 VMMDevDisplayChangeRequest2 displayChangeRequest = {0};
439 displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest2);
440 displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION;
441 displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest2;
442 displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
443 BOOL fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest2)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2),
444 &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2), &cbReturned, NULL);
445 if (!fDisplayChangeQueried)
446 {
447 /* Try the old version of the request for old VBox hosts. */
448 displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest);
449 displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION;
450 displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest;
451 displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
452 fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest),
453 &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest), &cbReturned, NULL);
454 displayChangeRequest.display = 0;
455 }
456
457 if (fDisplayChangeQueried)
458 {
459 Log(("VBoxDisplayThread : VMMDevReq_GetDisplayChangeRequest2: %dx%dx%d at %d\n", displayChangeRequest.xres, displayChangeRequest.yres, displayChangeRequest.bpp, displayChangeRequest.display));
460
461 /* Horizontal resolution must be a multiple of 8, round down. */
462 displayChangeRequest.xres &= 0xfff8;
463
464 /*
465 * Only try to change video mode if the active display driver is VBox additions.
466 */
467 if (isVBoxDisplayDriverActive (pCtx))
468 {
469 Log(("VBoxDisplayThread : Display driver is active!\n"));
470
471 if (pCtx->pfnChangeDisplaySettingsEx != 0)
472 {
473 Log(("VBoxDisplayThread : Detected W2K or later.\n"));
474
475 /* W2K or later. */
476 if (!ResizeDisplayDevice(displayChangeRequest.display,
477 displayChangeRequest.xres,
478 displayChangeRequest.yres,
479 displayChangeRequest.bpp))
480 {
481 break;
482 }
483 }
484 else
485 {
486 Log(("VBoxDisplayThread : Detected NT.\n"));
487
488 /* Single monitor NT. */
489 DEVMODE devMode;
490 RT_ZERO(devMode);
491 devMode.dmSize = sizeof(DEVMODE);
492
493 /* get the current screen setup */
494 if (EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &devMode))
495 {
496 Log(("VBoxDisplayThread : Current mode: %dx%dx%d at %d,%d\n", devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel, devMode.dmPosition.x, devMode.dmPosition.y));
497
498 /* Check whether a mode reset or a change is requested. */
499 if (displayChangeRequest.xres || displayChangeRequest.yres || displayChangeRequest.bpp)
500 {
501 /* A change is requested.
502 * Set values which are not to be changed to the current values.
503 */
504 if (!displayChangeRequest.xres)
505 displayChangeRequest.xres = devMode.dmPelsWidth;
506 if (!displayChangeRequest.yres)
507 displayChangeRequest.yres = devMode.dmPelsHeight;
508 if (!displayChangeRequest.bpp)
509 displayChangeRequest.bpp = devMode.dmBitsPerPel;
510 }
511 else
512 {
513 /* All zero values means a forced mode reset. Do nothing. */
514 Log(("VBoxDisplayThread : Forced mode reset.\n"));
515 }
516
517 /* Verify that the mode is indeed changed. */
518 if ( devMode.dmPelsWidth == displayChangeRequest.xres
519 && devMode.dmPelsHeight == displayChangeRequest.yres
520 && devMode.dmBitsPerPel == displayChangeRequest.bpp)
521 {
522 Log(("VBoxDisplayThread : already at desired resolution.\n"));
523 break;
524 }
525
526 // without this, Windows will not ask the miniport for its
527 // mode table but uses an internal cache instead
528 DEVMODE tempDevMode = {0};
529 tempDevMode.dmSize = sizeof(DEVMODE);
530 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode);
531
532 /* adjust the values that are supposed to change */
533 if (displayChangeRequest.xres)
534 devMode.dmPelsWidth = displayChangeRequest.xres;
535 if (displayChangeRequest.yres)
536 devMode.dmPelsHeight = displayChangeRequest.yres;
537 if (displayChangeRequest.bpp)
538 devMode.dmBitsPerPel = displayChangeRequest.bpp;
539
540 Log(("VBoxDisplayThread : setting the new mode %dx%dx%d\n", devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel));
541
542 /* set the new mode */
543 LONG status = ChangeDisplaySettings(&devMode, CDS_UPDATEREGISTRY);
544 if (status != DISP_CHANGE_SUCCESSFUL)
545 {
546 Log(("VBoxDisplayThread : error from ChangeDisplaySettings: %d\n", status));
547
548 if (status == DISP_CHANGE_BADMODE)
549 {
550 /* Our driver can not set the requested mode. Stop trying. */
551 break;
552 }
553 }
554 else
555 {
556 /* Successfully set new video mode. */
557 break;
558 }
559 }
560 else
561 {
562 Log(("VBoxDisplayThread : error from EnumDisplaySettings: %d\n", GetLastError ()));
563 break;
564 }
565 }
566 }
567 else
568 {
569 Log(("VBoxDisplayThread : vboxDisplayDriver is not active.\n"));
570 }
571
572 /* Retry the change a bit later. */
573 /* are we supposed to stop? */
574 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
575 {
576 fTerminate = true;
577 break;
578 }
579 }
580 else
581 {
582 Log(("VBoxDisplayThread : error from DeviceIoControl VBOXGUEST_IOCTL_VMMREQUEST\n"));
583 /* sleep a bit to not eat too much CPU while retrying */
584 /* are we supposed to stop? */
585 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 50) == WAIT_OBJECT_0)
586 {
587 fTerminate = true;
588 break;
589 }
590 }
591 }
592 }
593 if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED)
594 VBoxServiceReloadCursor();
595 } else
596 {
597 Log(("VBoxDisplayThread : error 0 from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n"));
598 /* sleep a bit to not eat too much CPU in case the above call always fails */
599 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0)
600 {
601 fTerminate = true;
602 break;
603 }
604 }
605 } while (!fTerminate);
606
607 maskInfo.u32OrMask = 0;
608 maskInfo.u32NotMask = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED;
609 if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
610 {
611 Log(("VBoxDisplayThread : DeviceIOControl(CtlMask - not) succeeded\n"));
612 }
613 else
614 {
615 Log(("VBoxDisplayThread : DeviceIOControl(CtlMask) failed\n"));
616 }
617
618 Log(("VBoxDisplayThread : finished display change request thread\n"));
619 return 0;
620}
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