VirtualBox

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

Last change on this file since 20894 was 20201, checked in by vboxsync, 16 years ago

Fixed a regression in VBoxTray: setvideomodehint was ignored if there was an inactive secondary display.

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