Changeset 10797 in vbox for trunk/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp
- Timestamp:
- Jul 22, 2008 8:12:42 AM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 33575
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxControl/VBoxControl.cpp
r10236 r10797 25 25 * Header Files * 26 26 *******************************************************************************/ 27 #include <iprt/ thread.h>27 #include <iprt/mem.h> 28 28 #include <iprt/string.h> 29 29 #include <iprt/stream.h> 30 30 #include <iprt/path.h> 31 31 #include <iprt/initterm.h> 32 #include <VBox/log.h> 32 33 #include <VBox/VBoxGuest.h> 33 34 #include <VBox/version.h> 34 #ifdef VBOX_WITH_INFO_SVC 35 # include <VBox/HostServices/VBoxInfoSvc.h> 35 #ifdef RT_OS_WINDOWS 36 # include <windows.h> 37 # include <malloc.h> /* for alloca */ 38 #endif 39 #ifdef VBOX_WITH_GUEST_PROPS 40 # include <VBox/HostServices/GuestPropertySvc.h> 36 41 #endif 37 42 #include "VBoxControl.h" … … 57 62 static void doUsage(char const *line, char const *name = "", char const *command = "") 58 63 { 59 RTPrintf("%s %-*s%s", name, 3 0- strlen(name), command, line);64 RTPrintf("%s %-*s%s", name, 32 - strlen(name), command, line); 60 65 } 61 66 … … 63 68 enum g_eUsage 64 69 { 65 #ifdef VBOX_WITH_INFO_SVC 70 #ifdef RT_OS_WINDOWS 71 GET_VIDEO_ACCEL, 72 SET_VIDEO_ACCEL, 73 LIST_CUST_MODES, 74 ADD_CUST_MODE, 75 REMOVE_CUST_MODE, 76 SET_VIDEO_MODE, 77 #endif 78 #ifdef VBOX_WITH_GUEST_PROPS 66 79 GET_GUEST_PROP, 67 80 SET_GUEST_PROP, … … 73 86 { 74 87 RTPrintf("Usage:\n\n"); 75 RTPrintf("%s [-v|--version] print version number and exit\n", g_pszProgName); 76 RTPrintf("%s --nologo ... suppress the logo\n\n", g_pszProgName); 77 78 #ifdef VBOX_WITH_INFO_SVC 88 RTPrintf("%s [-v|--version] print version number and exit\n", g_pszProgName); 89 RTPrintf("%s --nologo ... suppress the logo\n\n", g_pszProgName); 90 91 #ifdef RT_OS_WINDOWS 92 if ((GET_VIDEO_ACCEL == eWhich) || (USAGE_ALL == eWhich)) 93 doUsage("\n", g_pszProgName, "getvideoacceleration"); 94 if ((SET_VIDEO_ACCEL == eWhich) || (USAGE_ALL == eWhich)) 95 doUsage("<on|off>\n", g_pszProgName, "setvideoacceleration"); 96 if ((LIST_CUST_MODES == eWhich) || (USAGE_ALL == eWhich)) 97 doUsage("\n", g_pszProgName, "listcustommodes"); 98 if ((ADD_CUST_MODE == eWhich) || (USAGE_ALL == eWhich)) 99 doUsage("<width> <height> <bpp>\n", g_pszProgName, "addcustommode"); 100 if ((REMOVE_CUST_MODE == eWhich) || (USAGE_ALL == eWhich)) 101 doUsage("<width> <height> <bpp>\n", g_pszProgName, "removecustommode"); 102 if ((SET_VIDEO_MODE == eWhich) || (USAGE_ALL == eWhich)) 103 doUsage("<width> <height> <bpp> <screen>\n", g_pszProgName, "setvideomode"); 104 #endif 105 #ifdef VBOX_WITH_GUEST_PROPS 79 106 if ((GET_GUEST_PROP == eWhich) || (USAGE_ALL == eWhich)) 80 doUsage("< key>\n", g_pszProgName, "getguestproperty");107 doUsage("<name>\n", g_pszProgName, "getguestproperty"); 81 108 if ((SET_GUEST_PROP == eWhich) || (USAGE_ALL == eWhich)) 82 doUsage("< key> [<value>] (no value deletes key)\n", g_pszProgName, "setguestproperty");109 doUsage("<name> [<value>] (no value deletes property)\n", g_pszProgName, "setguestproperty"); 83 110 #endif 84 111 } … … 101 128 } 102 129 103 #ifdef VBOX_WITH_INFO_SVC 130 #ifdef RT_OS_WINDOWS 131 132 LONG (WINAPI * gpfnChangeDisplaySettingsEx)(LPCTSTR lpszDeviceName, LPDEVMODE lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam); 133 134 static unsigned nextAdjacentRectXP (RECTL *paRects, unsigned nRects, unsigned iRect) 135 { 136 unsigned i; 137 for (i = 0; i < nRects; i++) 138 { 139 if (paRects[iRect].right == paRects[i].left) 140 { 141 return i; 142 } 143 } 144 return ~0; 145 } 146 147 static unsigned nextAdjacentRectXN (RECTL *paRects, unsigned nRects, unsigned iRect) 148 { 149 unsigned i; 150 for (i = 0; i < nRects; i++) 151 { 152 if (paRects[iRect].left == paRects[i].right) 153 { 154 return i; 155 } 156 } 157 return ~0; 158 } 159 160 static unsigned nextAdjacentRectYP (RECTL *paRects, unsigned nRects, unsigned iRect) 161 { 162 unsigned i; 163 for (i = 0; i < nRects; i++) 164 { 165 if (paRects[iRect].bottom == paRects[i].top) 166 { 167 return i; 168 } 169 } 170 return ~0; 171 } 172 173 unsigned nextAdjacentRectYN (RECTL *paRects, unsigned nRects, unsigned iRect) 174 { 175 unsigned i; 176 for (i = 0; i < nRects; i++) 177 { 178 if (paRects[iRect].top == paRects[i].bottom) 179 { 180 return i; 181 } 182 } 183 return ~0; 184 } 185 186 void resizeRect(RECTL *paRects, unsigned nRects, unsigned iPrimary, unsigned iResized, int NewWidth, int NewHeight) 187 { 188 RECTL *paNewRects = (RECTL *)alloca (sizeof (RECTL) * nRects); 189 memcpy (paNewRects, paRects, sizeof (RECTL) * nRects); 190 paNewRects[iResized].right += NewWidth - (paNewRects[iResized].right - paNewRects[iResized].left); 191 paNewRects[iResized].bottom += NewHeight - (paNewRects[iResized].bottom - paNewRects[iResized].top); 192 193 /* Verify all pairs of originally adjacent rectangles for all 4 directions. 194 * If the pair has a "good" delta (that is the first rectangle intersects the second) 195 * at a direction and the second rectangle is not primary one (which can not be moved), 196 * move the second rectangle to make it adjacent to the first one. 197 */ 198 199 /* X positive. */ 200 unsigned iRect; 201 for (iRect = 0; iRect < nRects; iRect++) 202 { 203 /* Find the next adjacent original rect in x positive direction. */ 204 unsigned iNextRect = nextAdjacentRectXP (paRects, nRects, iRect); 205 Log(("next %d -> %d\n", iRect, iNextRect)); 206 207 if (iNextRect == ~0 || iNextRect == iPrimary) 208 { 209 continue; 210 } 211 212 /* Check whether there is an X intesection between these adjacent rects in the new rectangles 213 * and fix the intersection if delta is "good". 214 */ 215 int delta = paNewRects[iRect].right - paNewRects[iNextRect].left; 216 217 if (delta > 0) 218 { 219 Log(("XP intersection right %d left %d, diff %d\n", 220 paNewRects[iRect].right, paNewRects[iNextRect].left, 221 delta)); 222 223 paNewRects[iNextRect].left += delta; 224 paNewRects[iNextRect].right += delta; 225 } 226 } 227 228 /* X negative. */ 229 for (iRect = 0; iRect < nRects; iRect++) 230 { 231 /* Find the next adjacent original rect in x negative direction. */ 232 unsigned iNextRect = nextAdjacentRectXN (paRects, nRects, iRect); 233 Log(("next %d -> %d\n", iRect, iNextRect)); 234 235 if (iNextRect == ~0 || iNextRect == iPrimary) 236 { 237 continue; 238 } 239 240 /* Check whether there is an X intesection between these adjacent rects in the new rectangles 241 * and fix the intersection if delta is "good". 242 */ 243 int delta = paNewRects[iRect].left - paNewRects[iNextRect].right; 244 245 if (delta < 0) 246 { 247 Log(("XN intersection left %d right %d, diff %d\n", 248 paNewRects[iRect].left, paNewRects[iNextRect].right, 249 delta)); 250 251 paNewRects[iNextRect].left += delta; 252 paNewRects[iNextRect].right += delta; 253 } 254 } 255 256 /* Y positive (in the computer sence, top->down). */ 257 for (iRect = 0; iRect < nRects; iRect++) 258 { 259 /* Find the next adjacent original rect in y positive direction. */ 260 unsigned iNextRect = nextAdjacentRectYP (paRects, nRects, iRect); 261 Log(("next %d -> %d\n", iRect, iNextRect)); 262 263 if (iNextRect == ~0 || iNextRect == iPrimary) 264 { 265 continue; 266 } 267 268 /* Check whether there is an Y intesection between these adjacent rects in the new rectangles 269 * and fix the intersection if delta is "good". 270 */ 271 int delta = paNewRects[iRect].bottom - paNewRects[iNextRect].top; 272 273 if (delta > 0) 274 { 275 Log(("YP intersection bottom %d top %d, diff %d\n", 276 paNewRects[iRect].bottom, paNewRects[iNextRect].top, 277 delta)); 278 279 paNewRects[iNextRect].top += delta; 280 paNewRects[iNextRect].bottom += delta; 281 } 282 } 283 284 /* Y negative (in the computer sence, down->top). */ 285 for (iRect = 0; iRect < nRects; iRect++) 286 { 287 /* Find the next adjacent original rect in x negative direction. */ 288 unsigned iNextRect = nextAdjacentRectYN (paRects, nRects, iRect); 289 Log(("next %d -> %d\n", iRect, iNextRect)); 290 291 if (iNextRect == ~0 || iNextRect == iPrimary) 292 { 293 continue; 294 } 295 296 /* Check whether there is an Y intesection between these adjacent rects in the new rectangles 297 * and fix the intersection if delta is "good". 298 */ 299 int delta = paNewRects[iRect].top - paNewRects[iNextRect].bottom; 300 301 if (delta < 0) 302 { 303 Log(("YN intersection top %d bottom %d, diff %d\n", 304 paNewRects[iRect].top, paNewRects[iNextRect].bottom, 305 delta)); 306 307 paNewRects[iNextRect].top += delta; 308 paNewRects[iNextRect].bottom += delta; 309 } 310 } 311 312 memcpy (paRects, paNewRects, sizeof (RECTL) * nRects); 313 return; 314 } 315 316 /* Returns TRUE to try again. */ 317 static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel) 318 { 319 BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0); 320 321 DISPLAY_DEVICE DisplayDevice; 322 323 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); 324 DisplayDevice.cb = sizeof(DisplayDevice); 325 326 /* Find out how many display devices the system has */ 327 DWORD NumDevices = 0; 328 DWORD i = 0; 329 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) 330 { 331 Log(("[%d] %s\n", i, DisplayDevice.DeviceName)); 332 333 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 334 { 335 Log(("Found primary device. err %d\n", GetLastError ())); 336 NumDevices++; 337 } 338 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 339 { 340 341 Log(("Found secondary device. err %d\n", GetLastError ())); 342 NumDevices++; 343 } 344 345 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); 346 DisplayDevice.cb = sizeof(DisplayDevice); 347 i++; 348 } 349 350 Log(("Found total %d devices. err %d\n", NumDevices, GetLastError ())); 351 352 if (NumDevices == 0 || Id >= NumDevices) 353 { 354 Log(("Requested identifier %d is invalid. err %d\n", Id, GetLastError ())); 355 return FALSE; 356 } 357 358 DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices); 359 DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices); 360 RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices); 361 362 /* Fetch information about current devices and modes. */ 363 DWORD DevNum = 0; 364 DWORD DevPrimaryNum = 0; 365 366 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); 367 DisplayDevice.cb = sizeof(DISPLAY_DEVICE); 368 369 i = 0; 370 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) 371 { 372 Log(("[%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName)); 373 374 BOOL bFetchDevice = FALSE; 375 376 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 377 { 378 Log(("Found primary device. err %d\n", GetLastError ())); 379 DevPrimaryNum = DevNum; 380 bFetchDevice = TRUE; 381 } 382 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 383 { 384 385 Log(("Found secondary device. err %d\n", GetLastError ())); 386 bFetchDevice = TRUE; 387 } 388 389 if (bFetchDevice) 390 { 391 if (DevNum >= NumDevices) 392 { 393 Log(("%d >= %d\n", NumDevices, DevNum)); 394 return FALSE; 395 } 396 397 paDisplayDevices[DevNum] = DisplayDevice; 398 399 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE)); 400 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE); 401 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName, 402 ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum])) 403 { 404 Log(("EnumDisplaySettings err %d\n", GetLastError ())); 405 return FALSE; 406 } 407 408 Log(("%dx%d at %d,%d\n", 409 paDeviceModes[DevNum].dmPelsWidth, 410 paDeviceModes[DevNum].dmPelsHeight, 411 paDeviceModes[DevNum].dmPosition.x, 412 paDeviceModes[DevNum].dmPosition.y)); 413 414 paRects[DevNum].left = paDeviceModes[DevNum].dmPosition.x; 415 paRects[DevNum].top = paDeviceModes[DevNum].dmPosition.y; 416 paRects[DevNum].right = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth; 417 paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight; 418 DevNum++; 419 } 420 421 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); 422 DisplayDevice.cb = sizeof(DISPLAY_DEVICE); 423 i++; 424 } 425 426 if (Width == 0) 427 { 428 Width = paRects[Id].right - paRects[Id].left; 429 } 430 431 if (Height == 0) 432 { 433 Height = paRects[Id].bottom - paRects[Id].top; 434 } 435 436 /* Check whether a mode reset or a change is requested. */ 437 if ( !fModeReset 438 && paRects[Id].right - paRects[Id].left == Width 439 && paRects[Id].bottom - paRects[Id].top == Height 440 && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel) 441 { 442 Log(("VBoxDisplayThread : already at desired resolution.\n")); 443 return FALSE; 444 } 445 446 resizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height); 447 #ifdef Log 448 for (i = 0; i < NumDevices; i++) 449 { 450 Log(("[%d]: %d,%d %dx%d\n", 451 i, paRects[i].left, paRects[i].top, 452 paRects[i].right - paRects[i].left, 453 paRects[i].bottom - paRects[i].top)); 454 } 455 #endif /* Log */ 456 457 /* Without this, Windows will not ask the miniport for its 458 * mode table but uses an internal cache instead. 459 */ 460 DEVMODE tempDevMode; 461 ZeroMemory (&tempDevMode, sizeof (tempDevMode)); 462 tempDevMode.dmSize = sizeof(DEVMODE); 463 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode); 464 465 /* Assign the new rectangles to displays. */ 466 for (i = 0; i < NumDevices; i++) 467 { 468 paDeviceModes[i].dmPosition.x = paRects[i].left; 469 paDeviceModes[i].dmPosition.y = paRects[i].top; 470 paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left; 471 paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top; 472 473 paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH; 474 475 if ( i == Id 476 && BitsPerPixel != 0) 477 { 478 paDeviceModes[i].dmFields |= DM_BITSPERPEL; 479 paDeviceModes[i].dmBitsPerPel = BitsPerPixel; 480 } 481 Log(("calling pfnChangeDisplaySettingsEx %x\n", gpfnChangeDisplaySettingsEx)); 482 gpfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName, 483 &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL); 484 Log(("ChangeDisplaySettings position err %d\n", GetLastError ())); 485 } 486 487 /* A second call to ChangeDisplaySettings updates the monitor. */ 488 LONG status = ChangeDisplaySettings(NULL, 0); 489 Log(("ChangeDisplaySettings update status %d\n", status)); 490 if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE) 491 { 492 /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */ 493 return FALSE; 494 } 495 496 /* Retry the request. */ 497 return TRUE; 498 } 499 500 int handleSetVideoMode(int argc, char *argv[]) 501 { 502 if (argc != 3 && argc != 4) 503 { 504 usage(SET_VIDEO_MODE); 505 return 1; 506 } 507 508 DWORD xres = atoi(argv[0]); 509 DWORD yres = atoi(argv[1]); 510 DWORD bpp = atoi(argv[2]); 511 DWORD scr = 0; 512 513 if (argc == 4) 514 { 515 scr = atoi(argv[3]); 516 } 517 518 HMODULE hUser = GetModuleHandle("USER32"); 519 520 if (hUser) 521 { 522 *(uintptr_t *)&gpfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA"); 523 Log(("VBoxService: pChangeDisplaySettingsEx = %p\n", gpfnChangeDisplaySettingsEx)); 524 525 if (gpfnChangeDisplaySettingsEx) 526 { 527 /* The screen index is 0 based in the ResizeDisplayDevice call. */ 528 scr = scr > 0? scr - 1: 0; 529 530 /* Horizontal resolution must be a multiple of 8, round down. */ 531 xres &= ~0x7; 532 533 ResizeDisplayDevice(scr, xres, yres, bpp); 534 } 535 } 536 return 0; 537 } 538 539 HKEY getVideoKey(bool writable) 540 { 541 HKEY hkeyDeviceMap = 0; 542 HKEY hkeyVideo = 0; 543 LONG status; 544 545 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkeyDeviceMap); 546 if ((status != ERROR_SUCCESS) || !hkeyDeviceMap) 547 { 548 VBoxControlError("Error opening video device map registry key!\n"); 549 return 0; 550 } 551 char szVideoLocation[256]; 552 DWORD dwKeyType; 553 szVideoLocation[0] = 0; 554 DWORD len = sizeof(szVideoLocation); 555 status = RegQueryValueExA(hkeyDeviceMap, "\\Device\\Video0", NULL, &dwKeyType, (LPBYTE)szVideoLocation, &len); 556 /* 557 * This value will start with a weird value: \REGISTRY\Machine 558 * Make sure this is true. 559 */ 560 if ( (status == ERROR_SUCCESS) 561 && (dwKeyType == REG_SZ) 562 && (_strnicmp(szVideoLocation, "\\REGISTRY\\Machine", 17) == 0)) 563 { 564 /* open that branch */ 565 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, &szVideoLocation[18], 0, KEY_READ | (writable ? KEY_WRITE : 0), &hkeyVideo); 566 } 567 else 568 { 569 VBoxControlError("Error opening registry key '%s'\n", &szVideoLocation[18]); 570 } 571 RegCloseKey(hkeyDeviceMap); 572 return hkeyVideo; 573 } 574 575 int handleGetVideoAcceleration(int argc, char *argv[]) 576 { 577 ULONG status; 578 HKEY hkeyVideo = getVideoKey(false); 579 580 if (hkeyVideo) 581 { 582 /* query the actual value */ 583 DWORD fAcceleration = 1; 584 DWORD len = sizeof(fAcceleration); 585 DWORD dwKeyType; 586 status = RegQueryValueExA(hkeyVideo, "EnableVideoAccel", NULL, &dwKeyType, (LPBYTE)&fAcceleration, &len); 587 if (status != ERROR_SUCCESS) 588 RTPrintf("Video acceleration: default\n"); 589 else 590 RTPrintf("Video acceleration: %s\n", fAcceleration ? "on" : "off"); 591 RegCloseKey(hkeyVideo); 592 } 593 return 0; 594 } 595 596 int handleSetVideoAcceleration(int argc, char *argv[]) 597 { 598 ULONG status; 599 HKEY hkeyVideo; 600 601 /* must have exactly one argument: the new offset */ 602 if ( (argc != 1) 603 || ( strcmp(argv[0], "on") 604 && strcmp(argv[0], "off"))) 605 { 606 usage(SET_VIDEO_ACCEL); 607 return 1; 608 } 609 610 hkeyVideo = getVideoKey(true); 611 612 if (hkeyVideo) 613 { 614 int fAccel = 0; 615 if (!strcmp(argv[0], "on")) 616 fAccel = 1; 617 /* set a new value */ 618 status = RegSetValueExA(hkeyVideo, "EnableVideoAccel", 0, REG_DWORD, (LPBYTE)&fAccel, sizeof(fAccel)); 619 if (status != ERROR_SUCCESS) 620 { 621 VBoxControlError("Error %d writing video acceleration status!\n", status); 622 } 623 RegCloseKey(hkeyVideo); 624 } 625 return 0; 626 } 627 628 #define MAX_CUSTOM_MODES 128 629 630 /* the table of custom modes */ 631 struct 632 { 633 DWORD xres; 634 DWORD yres; 635 DWORD bpp; 636 } customModes[MAX_CUSTOM_MODES] = {0}; 637 638 void getCustomModes(HKEY hkeyVideo) 639 { 640 ULONG status; 641 int curMode = 0; 642 643 /* null out the table */ 644 memset(customModes, 0, sizeof(customModes)); 645 646 do 647 { 648 char valueName[20]; 649 DWORD xres, yres, bpp = 0; 650 DWORD dwType; 651 DWORD dwLen = sizeof(DWORD); 652 653 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dWidth", curMode); 654 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&xres, &dwLen); 655 if (status != ERROR_SUCCESS) 656 break; 657 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dHeight", curMode); 658 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&yres, &dwLen); 659 if (status != ERROR_SUCCESS) 660 break; 661 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dBPP", curMode); 662 status = RegQueryValueExA(hkeyVideo, valueName, NULL, &dwType, (LPBYTE)&bpp, &dwLen); 663 if (status != ERROR_SUCCESS) 664 break; 665 666 /* check if the mode is OK */ 667 if ( (xres > (1 << 16)) 668 && (yres > (1 << 16)) 669 && ( (bpp != 16) 670 || (bpp != 24) 671 || (bpp != 32))) 672 break; 673 674 /* add mode to table */ 675 customModes[curMode].xres = xres; 676 customModes[curMode].yres = yres; 677 customModes[curMode].bpp = bpp; 678 679 ++curMode; 680 681 if (curMode >= MAX_CUSTOM_MODES) 682 break; 683 } while(1); 684 } 685 686 void writeCustomModes(HKEY hkeyVideo) 687 { 688 ULONG status; 689 int tableIndex = 0; 690 int modeIndex = 0; 691 692 /* first remove all values */ 693 for (int i = 0; i < MAX_CUSTOM_MODES; i++) 694 { 695 char valueName[20]; 696 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dWidth", i); 697 RegDeleteValueA(hkeyVideo, valueName); 698 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dHeight", i); 699 RegDeleteValueA(hkeyVideo, valueName); 700 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dBPP", i); 701 RegDeleteValueA(hkeyVideo, valueName); 702 } 703 704 do 705 { 706 if (tableIndex >= MAX_CUSTOM_MODES) 707 break; 708 709 /* is the table entry present? */ 710 if ( (!customModes[tableIndex].xres) 711 || (!customModes[tableIndex].yres) 712 || (!customModes[tableIndex].bpp)) 713 { 714 tableIndex++; 715 continue; 716 } 717 718 RTPrintf("writing mode %d (%dx%dx%d)\n", modeIndex, customModes[tableIndex].xres, customModes[tableIndex].yres, customModes[tableIndex].bpp); 719 char valueName[20]; 720 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dWidth", modeIndex); 721 status = RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].xres, 722 sizeof(customModes[tableIndex].xres)); 723 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dHeight", modeIndex); 724 RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].yres, 725 sizeof(customModes[tableIndex].yres)); 726 RTStrPrintf(valueName, sizeof(valueName), "CustomMode%dBPP", modeIndex); 727 RegSetValueExA(hkeyVideo, valueName, 0, REG_DWORD, (LPBYTE)&customModes[tableIndex].bpp, 728 sizeof(customModes[tableIndex].bpp)); 729 730 modeIndex++; 731 tableIndex++; 732 733 } while(1); 734 735 } 736 737 int handleListCustomModes(int argc, char *argv[]) 738 { 739 if (argc != 0) 740 { 741 usage(LIST_CUST_MODES); 742 return 1; 743 } 744 745 HKEY hkeyVideo = getVideoKey(false); 746 747 if (hkeyVideo) 748 { 749 getCustomModes(hkeyVideo); 750 for (int i = 0; i < (sizeof(customModes) / sizeof(customModes[0])); i++) 751 { 752 if ( !customModes[i].xres 753 || !customModes[i].yres 754 || !customModes[i].bpp) 755 continue; 756 757 RTPrintf("Mode: %d x %d x %d\n", 758 customModes[i].xres, customModes[i].yres, customModes[i].bpp); 759 } 760 RegCloseKey(hkeyVideo); 761 } 762 return 0; 763 } 764 765 int handleAddCustomMode(int argc, char *argv[]) 766 { 767 if (argc != 3) 768 { 769 usage(ADD_CUST_MODE); 770 return 1; 771 } 772 773 DWORD xres = atoi(argv[0]); 774 DWORD yres = atoi(argv[1]); 775 DWORD bpp = atoi(argv[2]); 776 777 /** @todo better check including xres mod 8 = 0! */ 778 if ( (xres > (1 << 16)) 779 && (yres > (1 << 16)) 780 && ( (bpp != 16) 781 || (bpp != 24) 782 || (bpp != 32))) 783 { 784 VBoxControlError("Error: invalid mode specified!\n"); 785 return 1; 786 } 787 788 HKEY hkeyVideo = getVideoKey(true); 789 790 if (hkeyVideo) 791 { 792 int i; 793 int fModeExists = 0; 794 getCustomModes(hkeyVideo); 795 for (i = 0; i < MAX_CUSTOM_MODES; i++) 796 { 797 /* mode exists? */ 798 if ( customModes[i].xres == xres 799 && customModes[i].yres == yres 800 && customModes[i].bpp == bpp 801 ) 802 { 803 fModeExists = 1; 804 } 805 } 806 if (!fModeExists) 807 { 808 for (i = 0; i < MAX_CUSTOM_MODES; i++) 809 { 810 /* item free? */ 811 if (!customModes[i].xres) 812 { 813 customModes[i].xres = xres; 814 customModes[i].yres = yres; 815 customModes[i].bpp = bpp; 816 break; 817 } 818 } 819 writeCustomModes(hkeyVideo); 820 } 821 RegCloseKey(hkeyVideo); 822 } 823 return 0; 824 } 825 826 int handleRemoveCustomMode(int argc, char *argv[]) 827 { 828 if (argc != 3) 829 { 830 usage(REMOVE_CUST_MODE); 831 return 1; 832 } 833 834 DWORD xres = atoi(argv[0]); 835 DWORD yres = atoi(argv[1]); 836 DWORD bpp = atoi(argv[2]); 837 838 HKEY hkeyVideo = getVideoKey(true); 839 840 if (hkeyVideo) 841 { 842 getCustomModes(hkeyVideo); 843 for (int i = 0; i < MAX_CUSTOM_MODES; i++) 844 { 845 /* correct item? */ 846 if ( (customModes[i].xres == xres) 847 && (customModes[i].yres == yres) 848 && (customModes[i].bpp == bpp)) 849 { 850 RTPrintf("found mode at index %d\n", i); 851 memset(&customModes[i], 0, sizeof(customModes[i])); 852 break; 853 } 854 } 855 writeCustomModes(hkeyVideo); 856 RegCloseKey(hkeyVideo); 857 } 858 } 859 860 #endif /* RT_OS_WINDOWS */ 861 862 #ifdef VBOX_WITH_GUEST_PROPS 104 863 /** 105 * Retrieves a value from the host/guest configuration registry.106 * This is accessed through the "VBox SharedInfoSvc" HGCM service.864 * Retrieves a value from the guest property store. 865 * This is accessed through the "VBoxGuestPropSvc" HGCM service. 107 866 * 108 867 * @returns 0 on success, 1 on failure 109 * @param key (string) the key which the value is stored under.868 * @param name (string) the name of the property. 110 869 */ 111 870 int getGuestProperty(int argc, char **argv) 112 871 { 113 using namespace svcInfo; 872 using namespace guestProp; 873 874 if (argc != 1) 875 { 876 usage(GET_GUEST_PROP); 877 return 1; 878 } 114 879 115 880 uint32_t u32ClientID = 0; 116 881 int rc = VINF_SUCCESS; 117 char *pszKey = NULL; 118 char szValue[KEY_MAX_VALUE_LEN]; 119 120 if (argc != 1) 121 { 122 usage(GET_GUEST_PROP); 123 return 1; 124 } 125 rc = RTStrCurrentCPToUtf8(&pszKey, argv[0]); 882 char *pszName = argv[0]; 883 char *pszValue = NULL; 884 885 rc = VbglR3GuestPropConnect(&u32ClientID); 126 886 if (!RT_SUCCESS(rc)) 127 VBoxControlError("Failed to con vert the key name to Utf8, error %Rrc\n", rc);887 VBoxControlError("Failed to connect to the guest property service, error %Rrc\n", rc); 128 888 if (RT_SUCCESS(rc)) 129 889 { 130 rc = VbglR3InfoSvcConnect(&u32ClientID); 131 if (!RT_SUCCESS(rc)) 132 VBoxControlError("Failed to connect to the guest property service, error %Rrc\n", rc); 133 } 134 if (RT_SUCCESS(rc)) 135 { 136 rc = VbglR3InfoSvcReadKey(u32ClientID, argv[0], szValue, sizeof(szValue), NULL); 890 rc = VbglR3GuestPropReadValueAlloc(u32ClientID, pszName, &pszValue); 137 891 if (!RT_SUCCESS(rc) && (rc != VERR_NOT_FOUND)) 138 892 VBoxControlError("Failed to retrieve the property value, error %Rrc\n", rc); … … 141 895 RTPrintf("No value set!\n"); 142 896 if (RT_SUCCESS(rc)) 143 RTPrintf("Value: %S\n", szValue);897 RTPrintf("Value: %S\n", pszValue); 144 898 if (u32ClientID != 0) 145 VbglR3 InfoSvcDisconnect(u32ClientID);146 RTStrFree(pszKey);899 VbglR3GuestPropDisconnect(u32ClientID); 900 VbglR3GuestPropReadValueFree(pszValue); 147 901 return RT_SUCCESS(rc) ? 0 : 1; 148 902 } … … 150 904 151 905 /** 152 * Writes a value to the host/guest configuration registry.153 * This is accessed through the "VBox SharedInfoSvc" HGCM service.906 * Writes a value to the guest property store. 907 * This is accessed through the "VBoxGuestPropSvc" HGCM service. 154 908 * 155 909 * @returns 0 on success, 1 on failure 156 * @param key (string) the key which the value is stored under.157 * @param value (string) the value to write. If empty, the key will be910 * @param name (string) the name of the property. 911 * @param value (string) the value to write. If empty, the property will be 158 912 * removed. 159 913 */ 160 914 static int setGuestProperty(int argc, char *argv[]) 161 915 { 916 if (argc != 1 && argc != 2) 917 { 918 usage(SET_GUEST_PROP); 919 return 1; 920 } 921 162 922 uint32_t u32ClientID = 0; 163 923 int rc = VINF_SUCCESS; 164 char *psz Key = NULL;924 char *pszName = argv[0]; 165 925 char *pszValue = NULL; 166 167 if (argc != 1 && argc != 2) 168 { 169 usage(); 170 return 1; 171 } 172 rc = RTStrCurrentCPToUtf8(&pszKey, argv[0]); 926 if (2 == argc) 927 pszValue = argv[1]; 928 929 rc = VbglR3GuestPropConnect(&u32ClientID); 173 930 if (!RT_SUCCESS(rc)) 174 VBoxControlError("Failed to convert the key name to Utf8, error %Rrc\n", rc); 175 if (RT_SUCCESS(rc) && (2 == argc)) 176 { 177 rc = RTStrCurrentCPToUtf8(&pszValue, argv[1]); 178 if (!RT_SUCCESS(rc)) 179 VBoxControlError("Failed to convert the key value to Utf8, error %Rrc\n", rc); 180 } 931 VBoxControlError("Failed to connect to the guest property service, error %Rrc\n", rc); 181 932 if (RT_SUCCESS(rc)) 182 933 { 183 rc = VbglR3InfoSvcConnect(&u32ClientID); 184 if (!RT_SUCCESS(rc)) 185 VBoxControlError("Failed to connect to the host/guest registry service, error %Rrc\n", rc); 186 } 187 if (RT_SUCCESS(rc)) 188 { 189 rc = VbglR3InfoSvcWriteKey(u32ClientID, argv[0], pszValue); 934 rc = VbglR3GuestPropWriteValue(u32ClientID, pszName, pszValue); 190 935 if (!RT_SUCCESS(rc)) 191 936 VBoxControlError("Failed to store the property value, error %Rrc\n", rc); 192 937 } 193 938 if (u32ClientID != 0) 194 VbglR3InfoSvcDisconnect(u32ClientID); 195 RTStrFree(pszKey); 196 RTStrFree(pszValue); 939 VbglR3GuestPropDisconnect(u32ClientID); 197 940 return RT_SUCCESS(rc) ? 0 : 1; 198 941 } … … 210 953 } g_commandHandlers[] = 211 954 { 212 #ifdef VBOX_WITH_INFO_SVC 955 #ifdef RT_OS_WINDOWS 956 { "getvideoacceleration", handleGetVideoAcceleration }, 957 { "setvideoacceleration", handleSetVideoAcceleration }, 958 { "listcustommodes", handleListCustomModes }, 959 { "addcustommode", handleAddCustomMode }, 960 { "removecustommode", handleRemoveCustomMode }, 961 { "setvideomode", handleSetVideoMode }, 962 #endif 963 #ifdef VBOX_WITH_GUEST_PROPS 213 964 { "getguestproperty", getGuestProperty }, 214 965 { "setguestproperty", setGuestProperty }, … … 243 994 if ( (0 == strcmp(argv[iArg], "-v")) 244 995 || (0 == strcmp(argv[iArg], "--version")) 996 || (0 == strcmp(argv[iArg], "-version")) 997 || (0 == strcmp(argv[iArg], "getversion")) 245 998 ) 246 999 { … … 311 1064 if (!onlyinfo && (0 == rc)) 312 1065 { 1066 /* 1067 * The input is in the guest OS'es codepage (NT guarantees ACP). 1068 * For VBox we use UTF-8. For simplicity, just convert the argv[] array 1069 * here. 1070 */ 1071 for (int i = iArg; i < argc; i++) 1072 { 1073 char *converted; 1074 RTStrCurrentCPToUtf8(&converted, argv[i]); 1075 argv[i] = converted; 1076 } 1077 313 1078 if (argc > iArg) 314 1079 { … … 340 1105 usage(); 341 1106 } 1107 1108 /* 1109 * Free converted argument vector 1110 */ 1111 for (int i = iArg; i < argc; i++) 1112 RTStrFree(argv[i]); 1113 342 1114 } 343 1115
Note:
See TracChangeset
for help on using the changeset viewer.