VirtualBox

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

Last change on this file since 49891 was 49891, checked in by vboxsync, 11 years ago

Merged private draganddrop branch into trunk.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 43.8 KB
Line 
1/* $Id: VBoxDisplay.cpp 49891 2013-12-12 20:09:20Z vboxsync $ */
2/** @file
3 * VBoxSeamless - Display notifications.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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#define _WIN32_WINNT 0x0500
18#include "VBoxTray.h"
19#include "VBoxHelpers.h"
20#include "VBoxSeamless.h"
21#include <VBoxHook.h>
22#include <VBoxDisplay.h>
23#include <VBox/VMMDev.h>
24#include <iprt/assert.h>
25#include <malloc.h>
26#include <VBoxGuestInternal.h>
27#ifdef VBOX_WITH_WDDM
28#include <iprt/asm.h>
29#endif
30
31typedef struct _VBOXDISPLAYCONTEXT
32{
33 const VBOXSERVICEENV *pEnv;
34
35 BOOL fAnyX;
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} VBOXDISPLAYCONTEXT;
43
44static VBOXDISPLAYCONTEXT gCtx = {0};
45
46#ifdef VBOX_WITH_WDDM
47typedef enum
48{
49 VBOXDISPLAY_DRIVER_TYPE_UNKNOWN = 0,
50 VBOXDISPLAY_DRIVER_TYPE_XPDM = 1,
51 VBOXDISPLAY_DRIVER_TYPE_WDDM = 2
52} VBOXDISPLAY_DRIVER_TYPE;
53
54static VBOXDISPLAY_DRIVER_TYPE getVBoxDisplayDriverType (VBOXDISPLAYCONTEXT *pCtx);
55#endif
56
57int VBoxDisplayInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
58{
59 Log(("VBoxTray: VBoxDisplayInit ...\n"));
60
61 OSVERSIONINFO OSinfo;
62 OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
63 GetVersionEx (&OSinfo);
64
65 HMODULE hUser = GetModuleHandle("user32.dll");
66
67 gCtx.pEnv = pEnv;
68
69 if (NULL == hUser)
70 {
71 Log(("VBoxTray: VBoxDisplayInit: Could not get module handle of USER32.DLL!\n"));
72 return VERR_NOT_IMPLEMENTED;
73 }
74 else if (OSinfo.dwMajorVersion >= 5) /* APIs available only on W2K and up! */
75 {
76 *(uintptr_t *)&gCtx.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
77 Log(("VBoxTray: VBoxDisplayInit: pfnChangeDisplaySettingsEx = %p\n", gCtx.pfnChangeDisplaySettingsEx));
78
79 *(uintptr_t *)&gCtx.pfnEnumDisplayDevices = (uintptr_t)GetProcAddress(hUser, "EnumDisplayDevicesA");
80 Log(("VBoxTray: VBoxDisplayInit: pfnEnumDisplayDevices = %p\n", gCtx.pfnEnumDisplayDevices));
81
82#ifdef VBOX_WITH_WDDM
83 if (OSinfo.dwMajorVersion >= 6)
84 {
85 /* this is vista and up, check if we need to switch the display driver if to WDDM mode */
86 Log(("VBoxTray: VBoxDisplayInit: this is Windows Vista and up\n"));
87 VBOXDISPLAY_DRIVER_TYPE enmType = getVBoxDisplayDriverType (&gCtx);
88 if (enmType == VBOXDISPLAY_DRIVER_TYPE_WDDM)
89 {
90 Log(("VBoxTray: VBoxDisplayInit: WDDM driver is installed, switching display driver if to WDDM mode\n"));
91 /* this is hacky, but the most easiest way */
92 VBOXDISPIF_MODE enmMode = (OSinfo.dwMajorVersion > 6 || OSinfo.dwMinorVersion > 0) ? VBOXDISPIF_MODE_WDDM_W7 : VBOXDISPIF_MODE_WDDM;
93 DWORD err = VBoxDispIfSwitchMode(const_cast<PVBOXDISPIF>(&pEnv->dispIf), enmMode, NULL /* old mode, we don't care about it */);
94 if (err == NO_ERROR)
95 Log(("VBoxTray: VBoxDisplayInit: DispIf switched to WDDM mode successfully\n"));
96 else
97 Log(("VBoxTray: VBoxDisplayInit: Failed to switch DispIf to WDDM mode, err (%d)\n", err));
98 }
99 }
100#endif
101 }
102 else if (OSinfo.dwMajorVersion <= 4) /* Windows NT 4.0 */
103 {
104 /* Nothing to do here yet */
105 }
106 else /* Unsupported platform */
107 {
108 Log(("VBoxTray: VBoxDisplayInit: Warning, display for platform not handled yet!\n"));
109 return VERR_NOT_IMPLEMENTED;
110 }
111
112 VBOXDISPIFESCAPE_ISANYX IsAnyX = {0};
113 IsAnyX.EscapeHdr.escapeCode = VBOXESC_ISANYX;
114 DWORD err = VBoxDispIfEscapeInOut(&pEnv->dispIf, &IsAnyX.EscapeHdr, sizeof (uint32_t));
115 if (err == NO_ERROR)
116 gCtx.fAnyX = !!IsAnyX.u32IsAnyX;
117 else
118 gCtx.fAnyX = TRUE;
119
120 Log(("VBoxTray: VBoxDisplayInit: Display init successful\n"));
121
122 *pfStartThread = true;
123 *ppInstance = (void *)&gCtx;
124 return VINF_SUCCESS;
125}
126
127void VBoxDisplayDestroy (const VBOXSERVICEENV *pEnv, void *pInstance)
128{
129 return;
130}
131
132#ifdef VBOX_WITH_WDDM
133static VBOXDISPLAY_DRIVER_TYPE getVBoxDisplayDriverType(VBOXDISPLAYCONTEXT *pCtx)
134#else
135static bool isVBoxDisplayDriverActive(VBOXDISPLAYCONTEXT *pCtx)
136#endif
137{
138#ifdef VBOX_WITH_WDDM
139 VBOXDISPLAY_DRIVER_TYPE enmType = VBOXDISPLAY_DRIVER_TYPE_UNKNOWN;
140#else
141 bool result = false;
142#endif
143
144 if( pCtx->pfnEnumDisplayDevices )
145 {
146 INT devNum = 0;
147 DISPLAY_DEVICE dispDevice;
148 FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0);
149 dispDevice.cb = sizeof(DISPLAY_DEVICE);
150
151 Log(("VBoxTray: isVBoxDisplayDriverActive: Checking for active VBox display driver (W2K+) ...\n"));
152
153 while (EnumDisplayDevices(NULL,
154 devNum,
155 &dispDevice,
156 0))
157 {
158 Log(("VBoxTray: isVBoxDisplayDriverActive: DevNum:%d\nName:%s\nString:%s\nID:%s\nKey:%s\nFlags=%08X\n\n",
159 devNum,
160 &dispDevice.DeviceName[0],
161 &dispDevice.DeviceString[0],
162 &dispDevice.DeviceID[0],
163 &dispDevice.DeviceKey[0],
164 dispDevice.StateFlags));
165
166 if (dispDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
167 {
168 Log(("VBoxTray: isVBoxDisplayDriverActive: Primary device\n"));
169
170 if (strcmp(&dispDevice.DeviceString[0], "VirtualBox Graphics Adapter") == 0)
171#ifndef VBOX_WITH_WDDM
172 result = true;
173#else
174 enmType = VBOXDISPLAY_DRIVER_TYPE_XPDM;
175 /* WDDM driver can now have multiple incarnations,
176 * if the driver name contains VirtualBox, and does NOT match the XPDM name,
177 * assume it to be WDDM */
178 else if (strstr(&dispDevice.DeviceString[0], "VirtualBox"))
179 enmType = VBOXDISPLAY_DRIVER_TYPE_WDDM;
180#endif
181 break;
182 }
183
184 FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0);
185
186 dispDevice.cb = sizeof(DISPLAY_DEVICE);
187
188 devNum++;
189 }
190 }
191 else /* This must be NT 4 or something really old, so don't use EnumDisplayDevices() here ... */
192 {
193 Log(("VBoxTray: isVBoxDisplayDriverActive: Checking for active VBox display driver (NT or older) ...\n"));
194
195 DEVMODE tempDevMode;
196 ZeroMemory (&tempDevMode, sizeof (tempDevMode));
197 tempDevMode.dmSize = sizeof(DEVMODE);
198 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &tempDevMode); /* Get current display device settings */
199
200 /* Check for the short name, because all long stuff would be truncated */
201 if (strcmp((char*)&tempDevMode.dmDeviceName[0], "VBoxDisp") == 0)
202#ifndef VBOX_WITH_WDDM
203 result = true;
204#else
205 enmType = VBOXDISPLAY_DRIVER_TYPE_XPDM;
206#endif
207 }
208
209#ifndef VBOX_WITH_WDDM
210 return result;
211#else
212 return enmType;
213#endif
214}
215
216DWORD EnableAndResizeDispDev(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD totalDispNum, UINT Id, DWORD aWidth, DWORD aHeight,
217 DWORD aBitsPerPixel, DWORD aPosX, DWORD aPosY, BOOL fEnabled, BOOL fExtDispSup)
218{
219 DISPLAY_DEVICE displayDeviceTmp;
220 DISPLAY_DEVICE displayDevice;
221 DEVMODE deviceMode;
222 DWORD dwStatus = DISP_CHANGE_SUCCESSFUL;
223 DWORD iter ;
224
225 deviceMode = paDeviceModes[Id];
226 displayDevice = paDisplayDevices[Id];
227
228 for (iter = 0; iter < totalDispNum; iter++)
229 {
230 if (iter != 0 && iter != Id && !(paDisplayDevices[iter].StateFlags & DISPLAY_DEVICE_ACTIVE))
231 {
232 LogRel(("VBoxTray:Initially disabling the monitor with id = %d . Total Monitor=%d\n", iter, totalDispNum));
233 DEVMODE deviceModeTmp;
234 ZeroMemory(&deviceModeTmp, sizeof(DEVMODE));
235 deviceModeTmp.dmSize = sizeof(DEVMODE);
236 deviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
237 | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
238 displayDeviceTmp = paDisplayDevices[iter];
239 gCtx.pfnChangeDisplaySettingsEx(displayDeviceTmp.DeviceName, &deviceModeTmp, NULL,
240 (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
241 }
242 }
243
244 if (fExtDispSup) /* Extended Display Support possible*/
245 {
246 if (fEnabled)
247 {
248 /* Special case for enabling the secondary monitor. */
249 if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE))
250 {
251 LogRel(("VBoxTray: Secondary Monitor with ID=%d and name=%s Not Enabled. Enabling it.\n", Id, displayDevice.DeviceName));
252 deviceMode.dmPosition.x = paDeviceModes[0].dmPelsWidth;
253 deviceMode.dmPosition.y = 0;
254 deviceMode.dmBitsPerPel = 32;
255 OSVERSIONINFO OSinfo;
256 OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
257 GetVersionEx (&OSinfo);
258
259 if (OSinfo.dwMajorVersion < 6)
260 /* dont any more flags here as, only DM_POISITON is used to enable the secondary display */
261 deviceMode.dmFields = DM_POSITION;
262 else /* for win 7 and above */
263 /* for vista and above DM_BITSPERPEL is necessary */
264 deviceMode.dmFields = DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
265
266 dwStatus = gCtx.pfnChangeDisplaySettingsEx((LPSTR)displayDevice.DeviceName,&deviceMode, NULL, (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
267 /* A second call to ChangeDisplaySettings updates the monitor.*/
268 gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL);
269 }
270 else /* secondary monitor already enabled. Request to change the resolution or position. */
271 {
272 if (aWidth !=0 && aHeight != 0)
273 {
274 LogRel(("VBoxTray: Display : %s , Change Height: %d & Width: %d\n", displayDevice.DeviceName, aWidth, aHeight));
275 deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL
276 | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
277 deviceMode.dmPelsWidth = aWidth;
278 deviceMode.dmPelsHeight = aHeight;
279 deviceMode.dmBitsPerPel = aBitsPerPixel;
280 }
281 if (aPosX != 0 || aPosY != 0)
282 {
283 LogRel(("VBoxTray: Display: %s PosX: %d, PosY: %d\n", displayDevice.DeviceName, aPosX, aPosY));
284 deviceMode.dmFields |= DM_POSITION;
285 deviceMode.dmPosition.x = aPosX;
286 deviceMode.dmPosition.y = aPosY;
287 }
288 dwStatus = gCtx.pfnChangeDisplaySettingsEx((LPSTR)displayDevice.DeviceName,
289 &deviceMode, NULL, CDS_NORESET|CDS_UPDATEREGISTRY, NULL);
290 /* A second call to ChangeDisplaySettings updates the monitor. */
291 gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL);
292 }
293 }
294 else /* Request is there to disable the monitor with ID = Id*/
295 {
296 LogRel(("VBoxTray: Disable the Display: %d\n", displayDevice.DeviceName));
297
298 DEVMODE deviceModeTmp;
299 ZeroMemory(&deviceModeTmp, sizeof(DEVMODE));
300 deviceModeTmp.dmSize = sizeof(DEVMODE);
301 deviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
302 | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
303 displayDeviceTmp = paDisplayDevices[Id];
304 dwStatus = gCtx.pfnChangeDisplaySettingsEx(displayDeviceTmp.DeviceName, &deviceModeTmp, NULL,
305 (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
306 gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL);
307 }
308 }
309 return dwStatus;
310}
311
312DWORD VBoxGetDisplayConfigCount()
313{
314 DISPLAY_DEVICE DisplayDevice;
315
316 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
317 DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
318
319 /* Find out how many display devices the system has */
320 DWORD NumDevices = 0;
321 DWORD i = 0;
322 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
323 {
324 Log(("VBoxTray: ResizeDisplayDevice: [%d] %s\n", i, DisplayDevice.DeviceName));
325
326 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
327 {
328 Log(("VBoxTray: ResizeDisplayDevice: Found primary device. err %d\n", GetLastError ()));
329 NumDevices++;
330 }
331 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
332 {
333
334 Log(("VBoxTray: ResizeDisplayDevice: Found secondary device. err %d\n", GetLastError ()));
335 NumDevices++;
336 }
337
338 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
339 DisplayDevice.cb = sizeof(DisplayDevice);
340 i++;
341 }
342
343 return NumDevices;
344}
345
346DWORD VBoxGetDisplayConfig(const DWORD NumDevices, DWORD *pDevPrimaryNum, DWORD *pNumDevices, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes)
347{
348 /* Fetch information about current devices and modes. */
349 DWORD DevNum = 0;
350 DWORD DevPrimaryNum = 0;
351
352 DISPLAY_DEVICE DisplayDevice;
353
354 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
355 DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
356
357 DWORD i = 0;
358 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
359 {
360 Log(("VBoxTray: ResizeDisplayDevice: [%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName));
361
362 BOOL bFetchDevice = FALSE;
363
364 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
365 {
366 Log(("VBoxTray: ResizeDisplayDevice: Found primary device. err %d\n", GetLastError ()));
367 DevPrimaryNum = DevNum;
368 bFetchDevice = TRUE;
369 }
370 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
371 {
372
373 Log(("VBoxTray: ResizeDisplayDevice: Found secondary device. err %d\n", GetLastError ()));
374 bFetchDevice = TRUE;
375 }
376
377 if (bFetchDevice)
378 {
379 if (DevNum >= NumDevices)
380 {
381 WARN(("VBoxTray: ResizeDisplayDevice: %d >= %d\n", NumDevices, DevNum));
382 return ERROR_BUFFER_OVERFLOW;
383 }
384
385 paDisplayDevices[DevNum] = DisplayDevice;
386
387 /* First try to get the video mode stored in registry (ENUM_REGISTRY_SETTINGS).
388 * A secondary display could be not active at the moment and would not have
389 * a current video mode (ENUM_CURRENT_SETTINGS).
390 */
391 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE));
392 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE);
393 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
394 ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum]))
395 {
396 Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings error %d\n", GetLastError ()));
397 }
398
399 if ( paDeviceModes[DevNum].dmPelsWidth == 0
400 || paDeviceModes[DevNum].dmPelsHeight == 0)
401 {
402 /* No ENUM_REGISTRY_SETTINGS yet. Seen on Vista after installation.
403 * Get the current video mode then.
404 */
405 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE));
406 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE);
407 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
408 ENUM_CURRENT_SETTINGS, &paDeviceModes[DevNum]))
409 {
410 /* ENUM_CURRENT_SETTINGS returns FALSE when the display is not active:
411 * for example a disabled secondary display.
412 * Do not return here, ignore the error and set the display info to 0x0x0.
413 */
414 Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) error %d\n", GetLastError ()));
415 }
416 }
417
418
419 DevNum++;
420 }
421
422 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
423 DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
424 i++;
425 }
426
427 *pNumDevices = DevNum;
428
429 return NO_ERROR;
430}
431
432/* Returns TRUE to try again. */
433static BOOL ResizeDisplayDevice(UINT Id, DWORD Width, DWORD Height, DWORD BitsPerPixel,
434 BOOL fEnabled, DWORD dwNewPosX, DWORD dwNewPosY,
435 VBOXDISPLAYCONTEXT *pCtx, BOOL fExtDispSup)
436{
437 BOOL fDispAlreadyEnabled = false; /* check whether the monitor with ID is already enabled. */
438 BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0 &&
439 dwNewPosX == 0 && dwNewPosY == 0);
440 DWORD dmFields = 0;
441
442 Log(("VBoxTray: ResizeDisplayDevice Width= %d, Height=%d , PosX=%d and PosY=%d \
443 fEnabled = %d, fExtDisSup = %d\n",
444 Width, Height, dwNewPosX, dwNewPosY, fEnabled, fExtDispSup));
445
446 if (!gCtx.fAnyX)
447 Width &= 0xFFF8;
448
449 VBoxDispIfCancelPendingResize(&pCtx->pEnv->dispIf);
450
451 DWORD NumDevices = VBoxGetDisplayConfigCount();
452
453 if (NumDevices == 0 || Id >= NumDevices)
454 {
455 WARN(("VBoxTray: ResizeDisplayDevice: Requested identifier %d is invalid. err %d\n", Id, GetLastError ()));
456 return FALSE;
457 }
458
459 Log(("VBoxTray: ResizeDisplayDevice: Found total %d devices. err %d\n", NumDevices, GetLastError ()));
460
461 DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
462 DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
463 RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices);
464 DWORD DevNum = 0;
465 DWORD DevPrimaryNum = 0;
466 DWORD dwStatus = VBoxGetDisplayConfig(NumDevices, &DevPrimaryNum, &DevNum, paDisplayDevices, paDeviceModes);
467 if (dwStatus != NO_ERROR)
468 {
469 WARN(("VBoxTray: ResizeDisplayDevice: VBoxGetDisplayConfig failed, %d\n", dwStatus));
470 return dwStatus;
471 }
472
473 if (NumDevices != DevNum)
474 WARN(("VBoxTray: ResizeDisplayDevice: NumDevices(%d) != DevNum(%d)\n", NumDevices, DevNum));
475
476 DWORD i = 0;
477
478 for (i = 0; i < DevNum; ++i)
479 {
480 if (fExtDispSup)
481 {
482 LogRel(("VBoxTray: Extended Display Support.\n"));
483 Log(("VBoxTray: ResizeDisplayDevice1: %dx%dx%d at %d,%d . Id = %d and DevNum=%d, fEnabled=%d\n",
484 paDeviceModes[Id].dmPelsWidth,
485 paDeviceModes[Id].dmPelsHeight,
486 paDeviceModes[Id].dmBitsPerPel,
487 paDeviceModes[Id].dmPosition.x,
488 paDeviceModes[Id].dmPosition.y,
489 Id, DevNum, fEnabled));
490 }
491 else
492 {
493 LogRel(("VBoxTray: NO Ext Display Support \n"));
494 }
495
496 paRects[i].left = paDeviceModes[i].dmPosition.x;
497 paRects[i].top = paDeviceModes[i].dmPosition.y;
498 paRects[i].right = paDeviceModes[i].dmPosition.x + paDeviceModes[i].dmPelsWidth;
499 paRects[i].bottom = paDeviceModes[i].dmPosition.y + paDeviceModes[i].dmPelsHeight;
500 }
501
502 /* Keep a record if the display with ID is already active or not. */
503 if (paDisplayDevices[Id].StateFlags & DISPLAY_DEVICE_ACTIVE)
504 {
505 LogRel(("VBoxTray: Display with ID=%d already enabled\n", Id));
506 fDispAlreadyEnabled = TRUE;
507 }
508
509 /* Width, height equal to 0 means that this value must be not changed.
510 * Update input parameters if necessary.
511 * Note: BitsPerPixel is taken into account later, when new rectangles
512 * are assigned to displays.
513 */
514 if (Width == 0)
515 Width = paRects[Id].right - paRects[Id].left;
516 else
517 dmFields |= DM_PELSWIDTH;
518
519 if (Height == 0)
520 Height = paRects[Id].bottom - paRects[Id].top;
521 else
522 dmFields |= DM_PELSHEIGHT;
523
524 if (BitsPerPixel == 0)
525 BitsPerPixel = paDeviceModes[Id].dmBitsPerPel;
526 else
527 dmFields |= DM_BITSPERPEL;
528
529 if (!dwNewPosX && !dwNewPosY)
530 {
531 /* @fixme: zero position is a valid state, so another values should be used as a special case !!! */
532 dwNewPosX = paRects[Id].left;
533 dwNewPosY = paRects[Id].top;
534 }
535 else
536 dmFields |= DM_POSITION;
537
538 /* Check whether a mode reset or a change is requested.
539 * Rectangle position is recalculated only if fEnabled is 1.
540 * For non extended supported modes (old Host VMs), fEnabled
541 * is always 1.
542 */
543 /* Handled the case where previouseresolution of secondary monitor
544 * was for eg. 1024*768*32 and monitor was in disabled state.
545 * User gives the command
546 * setvideomode 1024 768 32 1 yes.
547 * Now in this case the resolution request is same as previous one but
548 * monitor is going from disabled to enabled state so the below condition
549 * shour return false
550 * The below condition will only return true , if no mode reset has
551 * been requested AND fEnabled is 1 and fDispAlreadyEnabled is also 1 AND
552 * all rect conditions are true. Thus in this case nothing has to be done.
553 */
554 if ( !fModeReset && (!fEnabled == !fDispAlreadyEnabled)
555 && paRects[Id].left == dwNewPosX
556 && paRects[Id].top == dwNewPosY
557 && paRects[Id].right - paRects[Id].left == Width
558 && paRects[Id].bottom - paRects[Id].top == Height
559 && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel)
560 {
561 LogRel(("VBoxTray: Already at desired resolution. No Change.\n"));
562 return FALSE;
563 }
564
565 hlpResizeRect(paRects, NumDevices, DevPrimaryNum, Id,
566 fEnabled ? Width : 0, fEnabled ? Height : 0, dwNewPosX, dwNewPosY);
567#ifdef Log
568 for (i = 0; i < NumDevices; i++)
569 {
570 Log(("VBoxTray: ResizeDisplayDevice: [%d]: %d,%d %dx%d\n",
571 i, paRects[i].left, paRects[i].top,
572 paRects[i].right - paRects[i].left,
573 paRects[i].bottom - paRects[i].top));
574 }
575#endif /* Log */
576
577#ifdef VBOX_WITH_WDDM
578 VBOXDISPLAY_DRIVER_TYPE enmDriverType = getVBoxDisplayDriverType (pCtx);
579 if (enmDriverType == VBOXDISPLAY_DRIVER_TYPE_WDDM)
580 {
581 /* Assign the new rectangles to displays. */
582 for (i = 0; i < NumDevices; i++)
583 {
584 paDeviceModes[i].dmPosition.x = paRects[i].left;
585 paDeviceModes[i].dmPosition.y = paRects[i].top;
586 paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left;
587 paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top;
588
589 if (i == Id)
590 paDeviceModes[i].dmBitsPerPel = BitsPerPixel;
591
592 paDeviceModes[i].dmFields |= dmFields;
593
594 /* On Vista one must specify DM_BITSPERPEL.
595 * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
596 */
597 if (!(paDeviceModes[i].dmFields & DM_BITSPERPEL))
598 {
599 WARN(("VBoxTray: (WDDM) no DM_BITSPERPEL\n"));
600 paDeviceModes[i].dmFields |= DM_BITSPERPEL;
601 paDeviceModes[i].dmBitsPerPel = 32;
602 }
603
604 Log(("VBoxTray: (WDDM) ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
605 gCtx.pfnChangeDisplaySettingsEx,
606 paDeviceModes[i].dmPelsWidth,
607 paDeviceModes[i].dmPelsHeight,
608 paDeviceModes[i].dmBitsPerPel,
609 paDeviceModes[i].dmPosition.x,
610 paDeviceModes[i].dmPosition.y));
611 }
612
613 Log(("VBoxTray: (WDDM) Request to resize the displa\n"));
614 DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, fEnabled, fExtDispSup, paDisplayDevices, paDeviceModes, DevNum);
615 if (err == NO_ERROR || err != ERROR_RETRY)
616 {
617 if (err == NO_ERROR)
618 Log(("VBoxTray: VBoxDisplayThread: (WDDM) VBoxDispIfResizeModes succeeded\n"));
619 else
620 WARN(("VBoxTray: VBoxDisplayThread: (WDDM) Failure VBoxDispIfResizeModes (%d)\n", err));
621 return FALSE;
622 }
623
624 Log(("VBoxTray: ResizeDisplayDevice: (WDDM) RETRY requested\n"));
625 return TRUE;
626 }
627#endif
628 /* Without this, Windows will not ask the miniport for its
629 * mode table but uses an internal cache instead.
630 */
631 for (i = 0; i < NumDevices; i++)
632 {
633 DEVMODE tempDevMode;
634 ZeroMemory (&tempDevMode, sizeof (tempDevMode));
635 tempDevMode.dmSize = sizeof(DEVMODE);
636 EnumDisplaySettings((LPSTR)paDisplayDevices[i].DeviceName, 0xffffff, &tempDevMode);
637 Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings last error %d\n", GetLastError ()));
638 }
639
640 /* Assign the new rectangles to displays. */
641 for (i = 0; i < NumDevices; i++)
642 {
643 paDeviceModes[i].dmPosition.x = paRects[i].left;
644 paDeviceModes[i].dmPosition.y = paRects[i].top;
645 paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left;
646 paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top;
647
648 /* On Vista one must specify DM_BITSPERPEL.
649 * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
650 */
651 paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
652
653 if ( i == Id
654 && BitsPerPixel != 0)
655 {
656 /* Change dmBitsPerPel if requested. */
657 paDeviceModes[i].dmBitsPerPel = BitsPerPixel;
658 }
659
660 Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx Current MonitorId=%d: %dx%dx%d at %d,%d\n",
661 i,
662 paDeviceModes[i].dmPelsWidth,
663 paDeviceModes[i].dmPelsHeight,
664 paDeviceModes[i].dmBitsPerPel,
665 paDeviceModes[i].dmPosition.x,
666 paDeviceModes[i].dmPosition.y));
667
668 LONG status = gCtx.pfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
669 &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
670 Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", status, GetLastError ()));
671 }
672
673 Log(("VBoxTray: Enable And Resize Device. Id = %d, Width=%d Height=%d, \
674 dwNewPosX = %d, dwNewPosY = %d fEnabled=%d & fExtDispSupport = %d \n",
675 Id, Width, Height, dwNewPosX, dwNewPosY, fEnabled, fExtDispSup));
676 dwStatus = EnableAndResizeDispDev(paDeviceModes, paDisplayDevices, DevNum, Id, Width, Height, BitsPerPixel,
677 dwNewPosX, dwNewPosY, fEnabled, fExtDispSup);
678 if (dwStatus == DISP_CHANGE_SUCCESSFUL || dwStatus == DISP_CHANGE_BADMODE)
679 {
680 /* Successfully set new video mode or our driver can not set
681 * the requested mode. Stop trying.
682 */
683 return FALSE;
684 }
685 /* Retry the request. */
686 return TRUE;
687}
688
689/**
690 * Thread function to wait for and process display change
691 * requests
692 */
693unsigned __stdcall VBoxDisplayThread(void *pInstance)
694{
695 Log(("VBoxTray: VBoxDisplayThread: Entered\n"));
696
697 VBOXDISPLAYCONTEXT *pCtx = (VBOXDISPLAYCONTEXT *)pInstance;
698 HANDLE gVBoxDriver = pCtx->pEnv->hDriver;
699 bool fTerminate = false;
700 VBoxGuestFilterMaskInfo maskInfo;
701 DWORD cbReturned;
702
703 maskInfo.u32OrMask = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED;
704 maskInfo.u32NotMask = 0;
705 if (!DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
706 {
707 Log(("VBoxTray: VBoxDisplayThread: DeviceIOControl(CtlMask - or) failed, thread exiting\n"));
708 return 0;
709 }
710
711 PostMessage(ghwndToolWindow, WM_VBOX_GRAPHICS_SUPPORTED, 0, 0);
712
713 VBoxDispIfResizeStarted(&pCtx->pEnv->dispIf);
714
715 do
716 {
717 BOOL fExtDispSup = TRUE;
718 /* Wait for a display change event. */
719 VBoxGuestWaitEventInfo waitEvent;
720 waitEvent.u32TimeoutIn = 1000;
721 waitEvent.u32EventMaskIn = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED;
722 if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL))
723 {
724 /*Log(("VBoxTray: VBoxDisplayThread: DeviceIOControl succeeded\n"));*/
725
726 if (NULL == pCtx) {
727 Log(("VBoxTray: VBoxDisplayThread: Invalid context detected!\n"));
728 break;
729 }
730
731 if (NULL == pCtx->pEnv) {
732 Log(("VBoxTray: VBoxDisplayThread: Invalid context environment detected!\n"));
733 break;
734 }
735
736 /* are we supposed to stop? */
737 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 0) == WAIT_OBJECT_0)
738 break;
739
740 /*Log(("VBoxTray: VBoxDisplayThread: checking event\n"));*/
741
742 /* did we get the right event? */
743 if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
744 {
745 Log(("VBoxTray: VBoxDisplayThread: going to get display change information\n"));
746 BOOL fDisplayChangeQueried;
747
748
749 /* We got at least one event. Read the requested resolution
750 * and try to set it until success. New events will not be seen
751 * but a new resolution will be read in this poll loop.
752 */
753 /* Try if extended mode display information is available from the host. */
754 VMMDevDisplayChangeRequestEx displayChangeRequest = {0};
755 fExtDispSup = TRUE;
756 displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequestEx);
757 displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION;
758 displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequestEx;
759 displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
760 fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequestEx)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequestEx),
761 &displayChangeRequest, sizeof(VMMDevDisplayChangeRequestEx), &cbReturned, NULL);
762
763 if (!fDisplayChangeQueried)
764 {
765 Log(("VBoxTray: Extended Display Not Supported. Trying VMMDevDisplayChangeRequest2\n"));
766 fExtDispSup = FALSE; /* Extended display Change request is not supported */
767
768 displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest2);
769 displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION;
770 displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest2;
771 displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
772 fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest2)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2),
773 &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2), &cbReturned, NULL);
774 displayChangeRequest.cxOrigin = 0;
775 displayChangeRequest.cyOrigin = 0;
776 displayChangeRequest.fChangeOrigin = 0;
777 displayChangeRequest.fEnabled = 1; /* Always Enabled for old VMs on Host.*/
778 }
779
780 if (!fDisplayChangeQueried)
781 {
782 Log(("VBoxTray: Extended Display Not Supported. Trying VMMDevDisplayChangeRequest\n"));
783 fExtDispSup = FALSE; /*Extended display Change request is not supported */
784 /* Try the old version of the request for old VBox hosts. */
785 displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest);
786 displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION;
787 displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest;
788 displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
789 fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest),
790 &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest), &cbReturned, NULL);
791 displayChangeRequest.display = 0;
792 displayChangeRequest.cxOrigin = 0;
793 displayChangeRequest.cyOrigin = 0;
794 displayChangeRequest.fChangeOrigin = 0;
795 displayChangeRequest.fEnabled = 1; /* Always Enabled for old VMs on Host.*/
796 }
797
798 if (fDisplayChangeQueried)
799 {
800 /* Try to set the requested video mode. Repeat until it is successful or is rejected by the driver. */
801 for (;;)
802 {
803 Log(("VBoxTray: VBoxDisplayThread: VMMDevReq_GetDisplayChangeRequest2: %dx%dx%d at %d\n", displayChangeRequest.xres, displayChangeRequest.yres, displayChangeRequest.bpp, displayChangeRequest.display));
804
805 /*
806 * Only try to change video mode if the active display driver is VBox additions.
807 */
808#ifdef VBOX_WITH_WDDM
809 VBOXDISPLAY_DRIVER_TYPE enmDriverType = getVBoxDisplayDriverType (pCtx);
810
811 if (enmDriverType == VBOXDISPLAY_DRIVER_TYPE_WDDM)
812 Log(("VBoxTray: VBoxDisplayThread: Detected WDDM Driver\n"));
813
814 if (enmDriverType != VBOXDISPLAY_DRIVER_TYPE_UNKNOWN)
815#else
816 if (isVBoxDisplayDriverActive (pCtx))
817#endif
818 {
819 Log(("VBoxTray: VBoxDisplayThread: Display driver is active!\n"));
820
821 if (pCtx->pfnChangeDisplaySettingsEx != 0)
822 {
823 Log(("VBoxTray: VBoxDisplayThread: Detected W2K or later\n"));
824 /* W2K or later. */
825 Log(("DisplayChangeReqEx parameters aDisplay=%d x xRes=%d x yRes=%d x bpp=%d x SecondayMonEnb=%d x NewOriginX=%d x NewOriginY=%d x ChangeOrigin=%d\n",
826 displayChangeRequest.display,
827 displayChangeRequest.xres,
828 displayChangeRequest.yres,
829 displayChangeRequest.bpp,
830 displayChangeRequest.fEnabled,
831 displayChangeRequest.cxOrigin,
832 displayChangeRequest.cyOrigin,
833 displayChangeRequest.fChangeOrigin));
834 if (!ResizeDisplayDevice(displayChangeRequest.display,
835 displayChangeRequest.xres,
836 displayChangeRequest.yres,
837 displayChangeRequest.bpp,
838 displayChangeRequest.fEnabled,
839 displayChangeRequest.cxOrigin,
840 displayChangeRequest.cyOrigin,
841 pCtx,
842 fExtDispSup
843 ))
844 {
845 Log(("ResizeDipspalyDevice return 0\n"));
846 break;
847 }
848
849 }
850 else
851 {
852 Log(("VBoxTray: VBoxDisplayThread: Detected NT\n"));
853
854 /* Single monitor NT. */
855 DEVMODE devMode;
856 RT_ZERO(devMode);
857 devMode.dmSize = sizeof(DEVMODE);
858
859 /* get the current screen setup */
860 if (EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &devMode))
861 {
862 Log(("VBoxTray: VBoxDisplayThread: Current mode: %d x %d x %d at %d,%d\n",
863 devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel, devMode.dmPosition.x, devMode.dmPosition.y));
864
865 /* Check whether a mode reset or a change is requested. */
866 if (displayChangeRequest.xres || displayChangeRequest.yres || displayChangeRequest.bpp)
867 {
868 /* A change is requested.
869 * Set values which are not to be changed to the current values.
870 */
871 if (!displayChangeRequest.xres)
872 displayChangeRequest.xres = devMode.dmPelsWidth;
873 if (!displayChangeRequest.yres)
874 displayChangeRequest.yres = devMode.dmPelsHeight;
875 if (!displayChangeRequest.bpp)
876 displayChangeRequest.bpp = devMode.dmBitsPerPel;
877 }
878 else
879 {
880 /* All zero values means a forced mode reset. Do nothing. */
881 Log(("VBoxTray: VBoxDisplayThread: Forced mode reset\n"));
882 }
883
884 /* Verify that the mode is indeed changed. */
885 if ( devMode.dmPelsWidth == displayChangeRequest.xres
886 && devMode.dmPelsHeight == displayChangeRequest.yres
887 && devMode.dmBitsPerPel == displayChangeRequest.bpp)
888 {
889 Log(("VBoxTray: VBoxDisplayThread: already at desired resolution\n"));
890 break;
891 }
892
893 // without this, Windows will not ask the miniport for its
894 // mode table but uses an internal cache instead
895 DEVMODE tempDevMode = {0};
896 tempDevMode.dmSize = sizeof(DEVMODE);
897 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode);
898
899 /* adjust the values that are supposed to change */
900 if (displayChangeRequest.xres)
901 devMode.dmPelsWidth = displayChangeRequest.xres;
902 if (displayChangeRequest.yres)
903 devMode.dmPelsHeight = displayChangeRequest.yres;
904 if (displayChangeRequest.bpp)
905 devMode.dmBitsPerPel = displayChangeRequest.bpp;
906
907 Log(("VBoxTray: VBoxDisplayThread: setting new mode %d x %d, %d BPP\n",
908 devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel));
909
910 /* set the new mode */
911 LONG status = ChangeDisplaySettings(&devMode, CDS_UPDATEREGISTRY);
912 if (status != DISP_CHANGE_SUCCESSFUL)
913 {
914 Log(("VBoxTray: VBoxDisplayThread: error from ChangeDisplaySettings: %d\n", status));
915
916 if (status == DISP_CHANGE_BADMODE)
917 {
918 /* Our driver can not set the requested mode. Stop trying. */
919 break;
920 }
921 }
922 else
923 {
924 /* Successfully set new video mode. */
925 break;
926 }
927 }
928 else
929 {
930 Log(("VBoxTray: VBoxDisplayThread: error from EnumDisplaySettings: %d\n", GetLastError ()));
931 break;
932 }
933 }
934 }
935 else
936 {
937 Log(("VBoxTray: VBoxDisplayThread: vboxDisplayDriver is not active\n"));
938 }
939
940 /* Retry the change a bit later. */
941 /* are we supposed to stop? */
942 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
943 {
944 fTerminate = true;
945 break;
946 }
947 }
948 }
949 else
950 {
951 Log(("VBoxTray: VBoxDisplayThread: error from DeviceIoControl VBOXGUEST_IOCTL_VMMREQUEST\n"));
952 /* sleep a bit to not eat too much CPU while retrying */
953 /* are we supposed to stop? */
954 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 50) == WAIT_OBJECT_0)
955 {
956 fTerminate = true;
957 break;
958 }
959 }
960 }
961 if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED)
962 hlpReloadCursor();
963 }
964 else
965 {
966#ifndef DEBUG_andy /* Too noisy for me. */
967 Log(("VBoxTray: VBoxDisplayThread: error 0 from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n"));
968#endif
969 /* sleep a bit to not eat too much CPU in case the above call always fails */
970 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0)
971 {
972 fTerminate = true;
973 break;
974 }
975 }
976 } while (!fTerminate);
977
978 /*
979 * Remove event filter and graphics capability report.
980 */
981 maskInfo.u32OrMask = 0;
982 maskInfo.u32NotMask = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED;
983 if (!DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
984 Log(("VBoxTray: VBoxDisplayThread: DeviceIOControl(CtlMask - not) failed\n"));
985 PostMessage(ghwndToolWindow, WM_VBOX_GRAPHICS_UNSUPPORTED, 0, 0);
986
987 Log(("VBoxTray: VBoxDisplayThread: finished display change request thread\n"));
988 return 0;
989}
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