Changeset 4266 in vbox
- Timestamp:
- Aug 21, 2007 3:45:55 PM (17 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT/VBoxService
- Files:
-
- 3 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxService/Makefile.kmk
r4264 r4266 30 30 VBoxSeamless.cpp \ 31 31 VBoxClipboard.cpp \ 32 VBoxDisplay.cpp \ 32 33 helpers.cpp \ 33 34 VBoxService.rc -
trunk/src/VBox/Additions/WINNT/VBoxService/VBoxService.cpp
r4264 r4266 17 17 #include "VBoxService.h" 18 18 #include "VBoxSeamless.h" 19 #include "VBoxClipboard.h" 20 #include "VBoxDisplay.h" 19 21 #include <VBoxHook.h> 20 22 #include "resource.h" … … 68 70 69 71 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 75 72 /* The service table. */ 76 73 static VBOXSERVICEINFO vboxServiceTable[] = 77 74 { 75 { 76 "Display", 77 VBoxDisplayInit, 78 VBoxDisplayThread, 79 VBoxDisplayDestroy, 80 }, 78 81 { 79 82 "Shared Clipboard", … … 296 299 } 297 300 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 309 301 /* terminate service if something went wrong */ 310 302 if (status != NO_ERROR) … … 380 372 dprintf(("VBoxService: waiting for display change thread...\n")); 381 373 382 /* wait for the display change thread to terminate */383 WaitForSingleObject(hDisplayChangeThread, INFINITE);384 385 374 vboxStopServices (&svcEnv, vboxServiceTable); 386 375 … … 412 401 } 413 402 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 ( !fModeReset588 && paRects[Id].right - paRects[Id].left == Width589 && paRects[Id].bottom - paRects[Id].top == Height590 && 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 DDCLOG598 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 its608 * 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 == Id626 && 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 change652 * requests653 */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 else675 {676 dprintf(("VBoxService: DeviceIOControl(CtlMask) failed, DisplayChangeThread exited\n"));677 return;678 }679 680 do681 {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 resolution702 * and try to set it until success. New events will not be seen703 * 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 else751 {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 else776 {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.xres782 && devMode.dmPelsHeight == displayChangeRequest.yres783 && 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 its790 // mode table but uses an internal cache instead791 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 else818 {819 /* Successfully set new video mode. */820 break;821 }822 }823 else824 {825 dprintf(("VBoxService: error from EnumDisplaySettings: %d\n", GetLastError ()));826 break;827 }828 }829 }830 else831 {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 else844 {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 } else857 {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 else875 {876 dprintf(("VBoxService: DeviceIOControl(CtlMask) failed\n"));877 }878 879 dprintf(("VBoxService: finished display change request thread\n"));880 }881 882 403 /** 883 404 * Window procedure for our tool window
Note:
See TracChangeset
for help on using the changeset viewer.