- Timestamp:
- Sep 21, 2007 5:59:13 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxControl/VBoxControl.cpp
r4071 r4968 16 16 #include <windows.h> 17 17 #include <stdio.h> 18 #include <stdarg.h> 19 #include <malloc.h> 18 20 19 21 void printHelp() … … 27 29 "VBoxControl addcustommode <width> <height> <bpp>\n" 28 30 "\n" 29 "VBoxControl removecustommode <width> <height> <bpp>\n"); 30 } 31 31 "VBoxControl removecustommode <width> <height> <bpp>\n" 32 "\n" 33 "VBoxControl setvideomode <width> <height> <bpp> <screen>\n"); 34 } 35 36 #if defined(DEBUG) || defined(LOG_ENABLED) 37 #define dprintf(a) do { int err = GetLastError (); printf a; SetLastError (err); } while (0) 38 #else 39 #define dprintf(a) do {} while (0) 40 #endif /* DEBUG */ 41 42 LONG (WINAPI * gpfnChangeDisplaySettingsEx)(LPCTSTR lpszDeviceName, LPDEVMODE lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam); 43 44 static unsigned nextAdjacentRectXP (RECTL *paRects, unsigned nRects, unsigned iRect) 45 { 46 unsigned i; 47 for (i = 0; i < nRects; i++) 48 { 49 if (paRects[iRect].right == paRects[i].left) 50 { 51 return i; 52 } 53 } 54 return ~0; 55 } 56 57 static unsigned nextAdjacentRectXN (RECTL *paRects, unsigned nRects, unsigned iRect) 58 { 59 unsigned i; 60 for (i = 0; i < nRects; i++) 61 { 62 if (paRects[iRect].left == paRects[i].right) 63 { 64 return i; 65 } 66 } 67 return ~0; 68 } 69 70 static unsigned nextAdjacentRectYP (RECTL *paRects, unsigned nRects, unsigned iRect) 71 { 72 unsigned i; 73 for (i = 0; i < nRects; i++) 74 { 75 if (paRects[iRect].bottom == paRects[i].top) 76 { 77 return i; 78 } 79 } 80 return ~0; 81 } 82 83 unsigned nextAdjacentRectYN (RECTL *paRects, unsigned nRects, unsigned iRect) 84 { 85 unsigned i; 86 for (i = 0; i < nRects; i++) 87 { 88 if (paRects[iRect].top == paRects[i].bottom) 89 { 90 return i; 91 } 92 } 93 return ~0; 94 } 95 96 void resizeRect(RECTL *paRects, unsigned nRects, unsigned iPrimary, unsigned iResized, int NewWidth, int NewHeight) 97 { 98 RECTL *paNewRects = (RECTL *)alloca (sizeof (RECTL) * nRects); 99 memcpy (paNewRects, paRects, sizeof (RECTL) * nRects); 100 paNewRects[iResized].right += NewWidth - (paNewRects[iResized].right - paNewRects[iResized].left); 101 paNewRects[iResized].bottom += NewHeight - (paNewRects[iResized].bottom - paNewRects[iResized].top); 102 103 /* Verify all pairs of originally adjacent rectangles for all 4 directions. 104 * If the pair has a "good" delta (that is the first rectangle intersects the second) 105 * at a direction and the second rectangle is not primary one (which can not be moved), 106 * move the second rectangle to make it adjacent to the first one. 107 */ 108 109 /* X positive. */ 110 unsigned iRect; 111 for (iRect = 0; iRect < nRects; iRect++) 112 { 113 /* Find the next adjacent original rect in x positive direction. */ 114 unsigned iNextRect = nextAdjacentRectXP (paRects, nRects, iRect); 115 dprintf(("next %d -> %d\n", iRect, iNextRect)); 116 117 if (iNextRect == ~0 || iNextRect == iPrimary) 118 { 119 continue; 120 } 121 122 /* Check whether there is an X intesection between these adjacent rects in the new rectangles 123 * and fix the intersection if delta is "good". 124 */ 125 int delta = paNewRects[iRect].right - paNewRects[iNextRect].left; 126 127 if (delta > 0) 128 { 129 dprintf(("XP intersection right %d left %d, diff %d\n", 130 paNewRects[iRect].right, paNewRects[iNextRect].left, 131 delta)); 132 133 paNewRects[iNextRect].left += delta; 134 paNewRects[iNextRect].right += delta; 135 } 136 } 137 138 /* X negative. */ 139 for (iRect = 0; iRect < nRects; iRect++) 140 { 141 /* Find the next adjacent original rect in x negative direction. */ 142 unsigned iNextRect = nextAdjacentRectXN (paRects, nRects, iRect); 143 dprintf(("next %d -> %d\n", iRect, iNextRect)); 144 145 if (iNextRect == ~0 || iNextRect == iPrimary) 146 { 147 continue; 148 } 149 150 /* Check whether there is an X intesection between these adjacent rects in the new rectangles 151 * and fix the intersection if delta is "good". 152 */ 153 int delta = paNewRects[iRect].left - paNewRects[iNextRect].right; 154 155 if (delta < 0) 156 { 157 dprintf(("XN intersection left %d right %d, diff %d\n", 158 paNewRects[iRect].left, paNewRects[iNextRect].right, 159 delta)); 160 161 paNewRects[iNextRect].left += delta; 162 paNewRects[iNextRect].right += delta; 163 } 164 } 165 166 /* Y positive (in the computer sence, top->down). */ 167 for (iRect = 0; iRect < nRects; iRect++) 168 { 169 /* Find the next adjacent original rect in y positive direction. */ 170 unsigned iNextRect = nextAdjacentRectYP (paRects, nRects, iRect); 171 dprintf(("next %d -> %d\n", iRect, iNextRect)); 172 173 if (iNextRect == ~0 || iNextRect == iPrimary) 174 { 175 continue; 176 } 177 178 /* Check whether there is an Y intesection between these adjacent rects in the new rectangles 179 * and fix the intersection if delta is "good". 180 */ 181 int delta = paNewRects[iRect].bottom - paNewRects[iNextRect].top; 182 183 if (delta > 0) 184 { 185 dprintf(("YP intersection bottom %d top %d, diff %d\n", 186 paNewRects[iRect].bottom, paNewRects[iNextRect].top, 187 delta)); 188 189 paNewRects[iNextRect].top += delta; 190 paNewRects[iNextRect].bottom += delta; 191 } 192 } 193 194 /* Y negative (in the computer sence, down->top). */ 195 for (iRect = 0; iRect < nRects; iRect++) 196 { 197 /* Find the next adjacent original rect in x negative direction. */ 198 unsigned iNextRect = nextAdjacentRectYN (paRects, nRects, iRect); 199 dprintf(("next %d -> %d\n", iRect, iNextRect)); 200 201 if (iNextRect == ~0 || iNextRect == iPrimary) 202 { 203 continue; 204 } 205 206 /* Check whether there is an Y intesection between these adjacent rects in the new rectangles 207 * and fix the intersection if delta is "good". 208 */ 209 int delta = paNewRects[iRect].top - paNewRects[iNextRect].bottom; 210 211 if (delta < 0) 212 { 213 dprintf(("YN intersection top %d bottom %d, diff %d\n", 214 paNewRects[iRect].top, paNewRects[iNextRect].bottom, 215 delta)); 216 217 paNewRects[iNextRect].top += delta; 218 paNewRects[iNextRect].bottom += delta; 219 } 220 } 221 222 memcpy (paRects, paNewRects, sizeof (RECTL) * nRects); 223 return; 224 } 225 226 /* Returns TRUE to try again. */ 227 static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel) 228 { 229 BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0); 230 231 DISPLAY_DEVICE DisplayDevice; 232 233 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); 234 DisplayDevice.cb = sizeof(DisplayDevice); 235 236 /* Find out how many display devices the system has */ 237 DWORD NumDevices = 0; 238 DWORD i = 0; 239 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) 240 { 241 dprintf(("[%d] %s\n", i, DisplayDevice.DeviceName)); 242 243 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 244 { 245 dprintf(("Found primary device. err %d\n", GetLastError ())); 246 NumDevices++; 247 } 248 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 249 { 250 251 dprintf(("Found secondary device. err %d\n", GetLastError ())); 252 NumDevices++; 253 } 254 255 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); 256 DisplayDevice.cb = sizeof(DisplayDevice); 257 i++; 258 } 259 260 dprintf(("Found total %d devices. err %d\n", NumDevices, GetLastError ())); 261 262 if (NumDevices == 0 || Id >= NumDevices) 263 { 264 dprintf(("Requested identifier %d is invalid. err %d\n", Id, GetLastError ())); 265 return FALSE; 266 } 267 268 DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices); 269 DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices); 270 RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices); 271 272 /* Fetch information about current devices and modes. */ 273 DWORD DevNum = 0; 274 DWORD DevPrimaryNum = 0; 275 276 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); 277 DisplayDevice.cb = sizeof(DISPLAY_DEVICE); 278 279 i = 0; 280 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) 281 { 282 dprintf(("[%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName)); 283 284 BOOL bFetchDevice = FALSE; 285 286 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 287 { 288 dprintf(("Found primary device. err %d\n", GetLastError ())); 289 DevPrimaryNum = DevNum; 290 bFetchDevice = TRUE; 291 } 292 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 293 { 294 295 dprintf(("Found secondary device. err %d\n", GetLastError ())); 296 bFetchDevice = TRUE; 297 } 298 299 if (bFetchDevice) 300 { 301 if (DevNum >= NumDevices) 302 { 303 dprintf(("%d >= %d\n", NumDevices, DevNum)); 304 return FALSE; 305 } 306 307 paDisplayDevices[DevNum] = DisplayDevice; 308 309 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE)); 310 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE); 311 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName, 312 ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum])) 313 { 314 dprintf(("EnumDisplaySettings err %d\n", GetLastError ())); 315 return FALSE; 316 } 317 318 dprintf(("%dx%d at %d,%d\n", 319 paDeviceModes[DevNum].dmPelsWidth, 320 paDeviceModes[DevNum].dmPelsHeight, 321 paDeviceModes[DevNum].dmPosition.x, 322 paDeviceModes[DevNum].dmPosition.y)); 323 324 paRects[DevNum].left = paDeviceModes[DevNum].dmPosition.x; 325 paRects[DevNum].top = paDeviceModes[DevNum].dmPosition.y; 326 paRects[DevNum].right = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth; 327 paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight; 328 DevNum++; 329 } 330 331 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); 332 DisplayDevice.cb = sizeof(DISPLAY_DEVICE); 333 i++; 334 } 335 336 if (Width == 0) 337 { 338 Width = paRects[Id].right - paRects[Id].left; 339 } 340 341 if (Height == 0) 342 { 343 Height = paRects[Id].bottom - paRects[Id].top; 344 } 345 346 /* Check whether a mode reset or a change is requested. */ 347 if ( !fModeReset 348 && paRects[Id].right - paRects[Id].left == Width 349 && paRects[Id].bottom - paRects[Id].top == Height 350 && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel) 351 { 352 dprintf(("VBoxDisplayThread : already at desired resolution.\n")); 353 return FALSE; 354 } 355 356 resizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height); 357 #ifdef dprintf 358 for (i = 0; i < NumDevices; i++) 359 { 360 dprintf(("[%d]: %d,%d %dx%d\n", 361 i, paRects[i].left, paRects[i].top, 362 paRects[i].right - paRects[i].left, 363 paRects[i].bottom - paRects[i].top)); 364 } 365 #endif /* dprintf */ 366 367 /* Without this, Windows will not ask the miniport for its 368 * mode table but uses an internal cache instead. 369 */ 370 DEVMODE tempDevMode; 371 ZeroMemory (&tempDevMode, sizeof (tempDevMode)); 372 tempDevMode.dmSize = sizeof(DEVMODE); 373 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode); 374 375 /* Assign the new rectangles to displays. */ 376 for (i = 0; i < NumDevices; i++) 377 { 378 paDeviceModes[i].dmPosition.x = paRects[i].left; 379 paDeviceModes[i].dmPosition.y = paRects[i].top; 380 paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left; 381 paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top; 382 383 paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH; 384 385 if ( i == Id 386 && BitsPerPixel != 0) 387 { 388 paDeviceModes[i].dmFields |= DM_BITSPERPEL; 389 paDeviceModes[i].dmBitsPerPel = BitsPerPixel; 390 } 391 dprintf(("calling pfnChangeDisplaySettingsEx %x\n", gpfnChangeDisplaySettingsEx)); 392 gpfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName, 393 &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL); 394 dprintf(("ChangeDisplaySettings position err %d\n", GetLastError ())); 395 } 396 397 /* A second call to ChangeDisplaySettings updates the monitor. */ 398 LONG status = ChangeDisplaySettings(NULL, 0); 399 dprintf(("ChangeDisplaySettings update status %d\n", status)); 400 if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE) 401 { 402 /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */ 403 return FALSE; 404 } 405 406 /* Retry the request. */ 407 return TRUE; 408 } 409 410 void handleSetVideoMode(int argc, char *argv[]) 411 { 412 if (argc != 3 && argc != 4) 413 { 414 printf("Error: not enough parameters!\n"); 415 return; 416 } 417 418 DWORD xres = atoi(argv[0]); 419 DWORD yres = atoi(argv[1]); 420 DWORD bpp = atoi(argv[2]); 421 DWORD scr = 0; 422 423 if (argc == 4) 424 { 425 scr = atoi(argv[3]); 426 } 427 428 HMODULE hUser = GetModuleHandle("USER32"); 429 430 if (hUser) 431 { 432 *(uintptr_t *)&gpfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA"); 433 dprintf(("VBoxService: pChangeDisplaySettingsEx = %p\n", gpfnChangeDisplaySettingsEx)); 434 435 if (gpfnChangeDisplaySettingsEx) 436 { 437 /* The screen index is 0 based in the ResizeDisplayDevice call. */ 438 scr = scr > 0? scr - 1: 0; 439 440 /* Horizontal resolution must be a multiple of 8, round down. */ 441 xres &= ~0x7; 442 443 ResizeDisplayDevice(scr, xres, yres, bpp); 444 } 445 } 446 } 32 447 33 448 HKEY getVideoKey(bool writable) … … 365 780 handleRemoveCustomMode(argc - 2, &argv[2]); 366 781 } 782 else if (strcmp(argv[1], "setvideomode") == 0) 783 { 784 handleSetVideoMode(argc - 2, &argv[2]); 785 } 367 786 else 368 787 {
Note:
See TracChangeset
for help on using the changeset viewer.