Changeset 4264 in vbox
- Timestamp:
- Aug 21, 2007 3:23:28 PM (17 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT/VBoxService
- Files:
-
- 3 deleted
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxService/Makefile.kmk
r4263 r4264 30 30 VBoxSeamless.cpp \ 31 31 VBoxClipboard.cpp \ 32 VBoxDisplay.cpp \33 32 helpers.cpp \ 34 33 VBoxService.rc -
trunk/src/VBox/Additions/WINNT/VBoxService/VBoxService.cpp
r4263 r4264 17 17 #include "VBoxService.h" 18 18 #include "VBoxSeamless.h" 19 #include "VBoxClipboard.h"20 #include "VBoxDisplay.h"21 19 #include <VBoxHook.h> 22 20 #include "resource.h" … … 70 68 71 69 70 /* The shared clipboard service prototypes. */ 71 int VBoxClipboardInit (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread); 72 unsigned __stdcall VBoxClipboardThread (void *pInstance); 73 void VBoxClipboardDestroy (const VBOXSERVICEENV *pEnv, void *pInstance); 74 72 75 /* The service table. */ 73 76 static VBOXSERVICEINFO vboxServiceTable[] = 74 77 { 75 {76 "Display",77 VBoxDisplayInit,78 VBoxDisplayThread,79 VBoxDisplayDestroy,80 },81 78 { 82 79 "Shared Clipboard", … … 299 296 } 300 297 298 /* create display change thread */ 299 HANDLE hDisplayChangeThread; 300 if (status == NO_ERROR) 301 { 302 hDisplayChangeThread = (HANDLE)_beginthread(DisplayChangeThread, 0, NULL); 303 if ((int)hDisplayChangeThread == -1L) 304 status = ERROR_GEN_FAILURE; 305 } 306 307 dprintf(("VBoxService: hDisplayChangeThread h %p, st %p\n", hDisplayChangeThread, status)); 308 301 309 /* terminate service if something went wrong */ 302 310 if (status != NO_ERROR) … … 372 380 dprintf(("VBoxService: waiting for display change thread...\n")); 373 381 382 /* wait for the display change thread to terminate */ 383 WaitForSingleObject(hDisplayChangeThread, INFINITE); 384 374 385 vboxStopServices (&svcEnv, vboxServiceTable); 375 386 … … 401 412 } 402 413 414 static bool isVBoxDisplayDriverActive (void) 415 { 416 bool result = false; 417 418 DISPLAY_DEVICE dispDevice; 419 420 FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0); 421 422 dispDevice.cb = sizeof(DISPLAY_DEVICE); 423 424 INT devNum = 0; 425 426 while (EnumDisplayDevices(NULL, 427 devNum, 428 &dispDevice, 429 0)) 430 { 431 DDCLOG(("DevNum:%d\nName:%s\nString:%s\nID:%s\nKey:%s\nFlags=%08X\n\n", 432 devNum, 433 &dispDevice.DeviceName[0], 434 &dispDevice.DeviceString[0], 435 &dispDevice.DeviceID[0], 436 &dispDevice.DeviceKey[0], 437 dispDevice.StateFlags)); 438 439 if (dispDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 440 { 441 DDCLOG(("Primary device.\n")); 442 443 if (strcmp(&dispDevice.DeviceString[0], "VirtualBox Graphics Adapter") == 0) 444 { 445 DDCLOG(("VBox display driver is active.\n")); 446 result = true; 447 } 448 449 break; 450 } 451 452 FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0); 453 454 dispDevice.cb = sizeof(DISPLAY_DEVICE); 455 456 devNum++; 457 } 458 459 return result; 460 } 461 462 /* ChangeDisplaySettingsEx does not exist in NT. ResizeDisplayDevice uses the function. */ 463 typedef LONG WINAPI defChangeDisplaySettingsEx(LPCTSTR lpszDeviceName, LPDEVMODE lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam); 464 static defChangeDisplaySettingsEx *pChangeDisplaySettingsEx = NULL; 465 466 /* Returns TRUE to try again. */ 467 static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel) 468 { 469 BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0); 470 471 DISPLAY_DEVICE DisplayDevice; 472 473 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); 474 DisplayDevice.cb = sizeof(DisplayDevice); 475 476 /* Find out how many display devices the system has */ 477 DWORD NumDevices = 0; 478 DWORD i = 0; 479 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) 480 { 481 DDCLOG(("[%d] %s\n", i, DisplayDevice.DeviceName)); 482 483 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 484 { 485 DDCLOG(("Found primary device. err %d\n", GetLastError ())); 486 NumDevices++; 487 } 488 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 489 { 490 491 DDCLOG(("Found secondary device. err %d\n", GetLastError ())); 492 NumDevices++; 493 } 494 495 ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); 496 DisplayDevice.cb = sizeof(DisplayDevice); 497 i++; 498 } 499 500 DDCLOG(("Found total %d devices. err %d\n", NumDevices, GetLastError ())); 501 502 if (NumDevices == 0 || Id >= NumDevices) 503 { 504 DDCLOG(("Requested identifier %d is invalid. err %d\n", Id, GetLastError ())); 505 return FALSE; 506 } 507 508 DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices); 509 DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices); 510 RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices); 511 512 /* Fetch information about current devices and modes. */ 513 DWORD DevNum = 0; 514 DWORD DevPrimaryNum = 0; 515 516 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); 517 DisplayDevice.cb = sizeof(DISPLAY_DEVICE); 518 519 i = 0; 520 while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) 521 { 522 DDCLOG(("[%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName)); 523 524 BOOL bFetchDevice = FALSE; 525 526 if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 527 { 528 DDCLOG(("Found primary device. err %d\n", GetLastError ())); 529 DevPrimaryNum = DevNum; 530 bFetchDevice = TRUE; 531 } 532 else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 533 { 534 535 DDCLOG(("Found secondary device. err %d\n", GetLastError ())); 536 bFetchDevice = TRUE; 537 } 538 539 if (bFetchDevice) 540 { 541 if (DevNum >= NumDevices) 542 { 543 DDCLOG(("%d >= %d\n", NumDevices, DevNum)); 544 return FALSE; 545 } 546 547 paDisplayDevices[DevNum] = DisplayDevice; 548 549 ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE)); 550 paDeviceModes[DevNum].dmSize = sizeof(DEVMODE); 551 if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName, 552 ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum])) 553 { 554 DDCLOG(("EnumDisplaySettings err %d\n", GetLastError ())); 555 return FALSE; 556 } 557 558 DDCLOG(("%dx%d at %d,%d\n", 559 paDeviceModes[DevNum].dmPelsWidth, 560 paDeviceModes[DevNum].dmPelsHeight, 561 paDeviceModes[DevNum].dmPosition.x, 562 paDeviceModes[DevNum].dmPosition.y)); 563 564 paRects[DevNum].left = paDeviceModes[DevNum].dmPosition.x; 565 paRects[DevNum].top = paDeviceModes[DevNum].dmPosition.y; 566 paRects[DevNum].right = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth; 567 paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight; 568 DevNum++; 569 } 570 571 ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); 572 DisplayDevice.cb = sizeof(DISPLAY_DEVICE); 573 i++; 574 } 575 576 if (Width == 0) 577 { 578 Width = paRects[Id].right - paRects[Id].left; 579 } 580 581 if (Height == 0) 582 { 583 Height = paRects[Id].bottom - paRects[Id].top; 584 } 585 586 /* Check whether a mode reset or a change is requested. */ 587 if ( !fModeReset 588 && paRects[Id].right - paRects[Id].left == Width 589 && paRects[Id].bottom - paRects[Id].top == Height 590 && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel) 591 { 592 DDCLOG(("VBoxService: already at desired resolution.\n")); 593 return FALSE; 594 } 595 596 resizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height); 597 #ifdef DDCLOG 598 for (i = 0; i < NumDevices; i++) 599 { 600 DDCLOG(("[%d]: %d,%d %dx%d\n", 601 i, paRects[i].left, paRects[i].top, 602 paRects[i].right - paRects[i].left, 603 paRects[i].bottom - paRects[i].top)); 604 } 605 #endif /* DDCLOG */ 606 607 /* Without this, Windows will not ask the miniport for its 608 * mode table but uses an internal cache instead. 609 */ 610 DEVMODE tempDevMode; 611 ZeroMemory (&tempDevMode, sizeof (tempDevMode)); 612 tempDevMode.dmSize = sizeof(DEVMODE); 613 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode); 614 615 /* Assign the new rectangles to displays. */ 616 for (i = 0; i < NumDevices; i++) 617 { 618 paDeviceModes[i].dmPosition.x = paRects[i].left; 619 paDeviceModes[i].dmPosition.y = paRects[i].top; 620 paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left; 621 paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top; 622 623 paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH; 624 625 if ( i == Id 626 && BitsPerPixel != 0) 627 { 628 paDeviceModes[i].dmFields |= DM_BITSPERPEL; 629 paDeviceModes[i].dmBitsPerPel = BitsPerPixel; 630 } 631 632 pChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName, 633 &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL); 634 DDCLOG(("ChangeDisplaySettings position err %d\n", GetLastError ())); 635 } 636 637 /* A second call to ChangeDisplaySettings updates the monitor. */ 638 LONG status = ChangeDisplaySettings(NULL, 0); 639 DDCLOG(("ChangeDisplaySettings update status %d\n", status)); 640 if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE) 641 { 642 /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */ 643 return FALSE; 644 } 645 646 /* Retry the request. */ 647 return TRUE; 648 } 649 650 /** 651 * Thread function to wait for and process display change 652 * requests 653 */ 654 VOID DisplayChangeThread(void *dummy) 655 { 656 bool fTerminate = false; 657 VBoxGuestFilterMaskInfo maskInfo; 658 DWORD cbReturned; 659 660 HMODULE hUser = GetModuleHandle("USER32"); 661 662 if (hUser) 663 { 664 pChangeDisplaySettingsEx = (defChangeDisplaySettingsEx *)GetProcAddress(hUser, "ChangeDisplaySettingsExA"); 665 DDCLOG(("VBoxService: pChangeDisplaySettingsEx = %p\n", pChangeDisplaySettingsEx)); 666 } 667 668 maskInfo.u32OrMask = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST; 669 maskInfo.u32NotMask = 0; 670 if (DeviceIoControl (gVBoxDriver, IOCTL_VBOXGUEST_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) 671 { 672 DDCLOG(("VBoxService: DeviceIOControl(CtlMask - or) succeeded\n")); 673 } 674 else 675 { 676 dprintf(("VBoxService: DeviceIOControl(CtlMask) failed, DisplayChangeThread exited\n")); 677 return; 678 } 679 680 do 681 { 682 /* wait for a display change event */ 683 VBoxGuestWaitEventInfo waitEvent; 684 waitEvent.u32TimeoutIn = 100; 685 waitEvent.u32EventMaskIn = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST; 686 if (DeviceIoControl(gVBoxDriver, IOCTL_VBOXGUEST_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL)) 687 { 688 DDCLOG(("VBoxService: DeviceIOControl succeded\n")); 689 690 /* are we supposed to stop? */ 691 if (WaitForSingleObject(gStopSem, 0) == WAIT_OBJECT_0) 692 break; 693 694 DDCLOG(("VBoxService: checking event\n")); 695 696 /* did we get the right event? */ 697 if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST) 698 { 699 DDCLOG(("VBoxService: going to get display change information.\n")); 700 701 /* We got at least one event. Read the requested resolution 702 * and try to set it until success. New events will not be seen 703 * but a new resolution will be read in this poll loop. 704 */ 705 for (;;) 706 { 707 /* get the display change request */ 708 VMMDevDisplayChangeRequest2 displayChangeRequest = {0}; 709 displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest2); 710 displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION; 711 displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest2; 712 displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST; 713 BOOL fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, IOCTL_VBOXGUEST_VMMREQUEST, &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2), 714 &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2), &cbReturned, NULL); 715 if (!fDisplayChangeQueried) 716 { 717 /* Try the old version of the request for old VBox hosts. */ 718 displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest); 719 displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION; 720 displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest; 721 displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST; 722 fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, IOCTL_VBOXGUEST_VMMREQUEST, &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest), 723 &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest), &cbReturned, NULL); 724 displayChangeRequest.display = 0; 725 } 726 727 if (fDisplayChangeQueried) 728 { 729 DDCLOG(("VBoxService: VMMDevReq_GetDisplayChangeRequest2: %dx%dx%d at %d\n", displayChangeRequest.xres, displayChangeRequest.yres, displayChangeRequest.bpp, displayChangeRequest.display)); 730 731 /* Horizontal resolution must be a multiple of 8, round down. */ 732 displayChangeRequest.xres &= 0xfff8; 733 734 /* 735 * Only try to change video mode if the active display driver is VBox additions. 736 */ 737 if (isVBoxDisplayDriverActive ()) 738 { 739 if (pChangeDisplaySettingsEx != 0) 740 { 741 /* W2K or later. */ 742 if (!ResizeDisplayDevice(displayChangeRequest.display, 743 displayChangeRequest.xres, 744 displayChangeRequest.yres, 745 displayChangeRequest.bpp)) 746 { 747 break; 748 } 749 } 750 else 751 { 752 /* Single monitor NT. */ 753 DEVMODE devMode; 754 memset (&devMode, 0, sizeof (devMode)); 755 devMode.dmSize = sizeof(DEVMODE); 756 757 /* get the current screen setup */ 758 if (EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &devMode)) 759 { 760 dprintf(("VBoxService: Current mode: %dx%dx%d at %d,%d\n", devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel, devMode.dmPosition.x, devMode.dmPosition.y)); 761 762 /* Check whether a mode reset or a change is requested. */ 763 if (displayChangeRequest.xres || displayChangeRequest.yres || displayChangeRequest.bpp) 764 { 765 /* A change is requested. 766 * Set values which are not to be changed to the current values. 767 */ 768 if (!displayChangeRequest.xres) 769 displayChangeRequest.xres = devMode.dmPelsWidth; 770 if (!displayChangeRequest.yres) 771 displayChangeRequest.yres = devMode.dmPelsHeight; 772 if (!displayChangeRequest.bpp) 773 displayChangeRequest.bpp = devMode.dmBitsPerPel; 774 } 775 else 776 { 777 /* All zero values means a forced mode reset. Do nothing. */ 778 } 779 780 /* Verify that the mode is indeed changed. */ 781 if ( devMode.dmPelsWidth == displayChangeRequest.xres 782 && devMode.dmPelsHeight == displayChangeRequest.yres 783 && devMode.dmBitsPerPel == displayChangeRequest.bpp) 784 { 785 dprintf(("VBoxService: already at desired resolution.\n")); 786 break; 787 } 788 789 // without this, Windows will not ask the miniport for its 790 // mode table but uses an internal cache instead 791 DEVMODE tempDevMode = {0}; 792 tempDevMode.dmSize = sizeof(DEVMODE); 793 EnumDisplaySettings(NULL, 0xffffff, &tempDevMode); 794 795 /* adjust the values that are supposed to change */ 796 if (displayChangeRequest.xres) 797 devMode.dmPelsWidth = displayChangeRequest.xres; 798 if (displayChangeRequest.yres) 799 devMode.dmPelsHeight = displayChangeRequest.yres; 800 if (displayChangeRequest.bpp) 801 devMode.dmBitsPerPel = displayChangeRequest.bpp; 802 803 DDCLOG(("VBoxService: setting the new mode %dx%dx%d\n", devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel)); 804 805 /* set the new mode */ 806 LONG status = ChangeDisplaySettings(&devMode, CDS_UPDATEREGISTRY); 807 if (status != DISP_CHANGE_SUCCESSFUL) 808 { 809 dprintf(("VBoxService: error from ChangeDisplaySettings: %d\n", status)); 810 811 if (status == DISP_CHANGE_BADMODE) 812 { 813 /* Our driver can not set the requested mode. Stop trying. */ 814 break; 815 } 816 } 817 else 818 { 819 /* Successfully set new video mode. */ 820 break; 821 } 822 } 823 else 824 { 825 dprintf(("VBoxService: error from EnumDisplaySettings: %d\n", GetLastError ())); 826 break; 827 } 828 } 829 } 830 else 831 { 832 dprintf(("VBoxService: vboxDisplayDriver is not active.\n")); 833 } 834 835 /* Retry the change a bit later. */ 836 /* are we supposed to stop? */ 837 if (WaitForSingleObject(gStopSem, 1000) == WAIT_OBJECT_0) 838 { 839 fTerminate = true; 840 break; 841 } 842 } 843 else 844 { 845 dprintf(("VBoxService: error from DeviceIoControl IOCTL_VBOXGUEST_VMMREQUEST\n")); 846 /* sleep a bit to not eat too much CPU while retrying */ 847 /* are we supposed to stop? */ 848 if (WaitForSingleObject(gStopSem, 50) == WAIT_OBJECT_0) 849 { 850 fTerminate = true; 851 break; 852 } 853 } 854 } 855 } 856 } else 857 { 858 dprintf(("VBoxService: error 0 from DeviceIoControl IOCTL_VBOXGUEST_WAITEVENT\n")); 859 /* sleep a bit to not eat too much CPU in case the above call always fails */ 860 if (WaitForSingleObject(gStopSem, 10) == WAIT_OBJECT_0) 861 { 862 fTerminate = true; 863 break; 864 } 865 } 866 } while (!fTerminate); 867 868 maskInfo.u32OrMask = 0; 869 maskInfo.u32NotMask = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST; 870 if (DeviceIoControl (gVBoxDriver, IOCTL_VBOXGUEST_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) 871 { 872 DDCLOG(("VBoxService: DeviceIOControl(CtlMask - not) succeeded\n")); 873 } 874 else 875 { 876 dprintf(("VBoxService: DeviceIOControl(CtlMask) failed\n")); 877 } 878 879 dprintf(("VBoxService: finished display change request thread\n")); 880 } 881 403 882 /** 404 883 * Window procedure for our tool window
Note:
See TracChangeset
for help on using the changeset viewer.