/** * Retrieve mouse coordinates and features from the host. * * @remarks Ring-0. * @returns VBox status code. * * @param pfFeatures Where to store the mouse features. * @param px Where to store the X co-ordinate. * @param py Where to store the Y co-ordinate. */ DECLVBGL(int) VbglGetMouseStatus(uint32_t *pfFeatures, uint32_t *px, uint32_t *py) { VMMDevReqMouseStatus Req; VBGLDRIVER *pDriver; int rc; rc = vbglGetDriver(&pDriver); if (RT_FAILURE(rc)) return rc; vmmdevInitRequest(&Req.header, VMMDevReq_GetMouseStatus); Req.mouseFeatures = 0; Req.pointerXPos = 0; Req.pointerYPos = 0; rc = vbglDriverIOCtl(pDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(Req)), &Req.header, sizeof(Req)); if (RT_FAILURE(rc)) return rc; if (RT_FAILURE(Req.header.rc)) return Req.header.rc; if (pfFeatures) *pfFeatures = Req.mouseFeatures; if (px) *px = Req.pointerXPos; if (py) *py = Req.pointerYPos; return VINF_SUCCESS; }
VBGLR3DECL(int) VbglR3GRPerform(VMMDevRequestHeader *pReq) { DWORD cbReturned; DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(pReq->size), pReq, pReq->size, pReq, pReq->size, &cbReturned, NULL); return VINF_SUCCESS; }
/** * dprintf worker using VBoxGuest.sys and VMMDevReq_LogString. */ static void WriteLog(const char *pszFormat, ...) { /* * Open VBox guest driver once. */ static HANDLE s_hVBoxGuest = INVALID_HANDLE_VALUE; HANDLE hVBoxGuest = s_hVBoxGuest; if (hVBoxGuest == INVALID_HANDLE_VALUE) { hVBoxGuest = CreateFile(VBOXGUEST_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hVBoxGuest == INVALID_HANDLE_VALUE) return; s_hVBoxGuest = hVBoxGuest; } /* * We're apparently afraid of using stack here, so we use a static buffer * instead and pray we won't be here at the same time on two threads... */ static union { VMMDevReqLogString Req; uint8_t abBuf[1024]; } s_uBuf; vmmdevInitRequest(&s_uBuf.Req.header, VMMDevReq_LogString); va_list va; va_start(va, pszFormat); size_t cch = vsprintf(s_uBuf.Req.szString, pszFormat, va); va_end(va); s_uBuf.Req.header.size += (uint32_t)cch; if (s_uBuf.Req.header.size > sizeof(s_uBuf)) __debugbreak(); DWORD cbReturned; DeviceIoControl(hVBoxGuest, VBOXGUEST_IOCTL_VMMREQUEST(s_uBuf.Req.size), &s_uBuf.Req, s_uBuf.Req.header.size, &s_uBuf.Req, s_uBuf.Req.header.size, &cbReturned, NULL); }
/** * Thread function to wait for and process seamless mode change * requests */ unsigned __stdcall VBoxSeamlessThread(void *pInstance) { VBOXSEAMLESSCONTEXT *pCtx = (VBOXSEAMLESSCONTEXT *)pInstance; HANDLE gVBoxDriver = pCtx->pEnv->hDriver; bool fTerminate = false; VBoxGuestFilterMaskInfo maskInfo; DWORD cbReturned; BOOL fWasScreenSaverActive = FALSE, ret; maskInfo.u32OrMask = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; maskInfo.u32NotMask = 0; if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) { Log(("VBoxTray: VBoxSeamlessThread: DeviceIOControl(CtlMask - or) succeeded\n")); } else { Log(("VBoxTray: VBoxSeamlessThread: DeviceIOControl(CtlMask) failed, SeamlessChangeThread exited\n")); return 0; } do { /* wait for a seamless change event */ VBoxGuestWaitEventInfo waitEvent; waitEvent.u32TimeoutIn = 5000; waitEvent.u32EventMaskIn = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL)) { Log(("VBoxTray: VBoxSeamlessThread: DeviceIOControl succeeded\n")); /* are we supposed to stop? */ if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 0) == WAIT_OBJECT_0) break; Log(("VBoxTray: VBoxSeamlessThread: checking event\n")); /* did we get the right event? */ if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST) { Log(("VBoxTray: VBoxTray: going to get seamless change information\n")); /* We got at least one event. Read the requested resolution * and try to set it until success. New events will not be seen * but a new resolution will be read in this poll loop. */ for (;;) { /* get the seamless change request */ VMMDevSeamlessChangeRequest seamlessChangeRequest = {0}; vmmdevInitRequest((VMMDevRequestHeader*)&seamlessChangeRequest, VMMDevReq_GetSeamlessChangeRequest); seamlessChangeRequest.eventAck = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; BOOL fSeamlessChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(seamlessChangeRequest)), &seamlessChangeRequest, sizeof(seamlessChangeRequest), &seamlessChangeRequest, sizeof(seamlessChangeRequest), &cbReturned, NULL); if (fSeamlessChangeQueried) { Log(("VBoxTray: VBoxSeamlessThread: mode change to %d\n", seamlessChangeRequest.mode)); switch(seamlessChangeRequest.mode) { case VMMDev_Seamless_Disabled: if (fWasScreenSaverActive) { Log(("VBoxTray: Re-enabling the screensaver\n")); ret = SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, NULL, 0); if (!ret) Log(("VBoxTray: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %d\n", GetLastError())); } PostMessage(ghwndToolWindow, WM_VBOX_SEAMLESS_DISABLE, 0, 0); break; case VMMDev_Seamless_Visible_Region: ret = SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &fWasScreenSaverActive, 0); if (!ret) Log(("VBoxTray: SystemParametersInfo SPI_GETSCREENSAVEACTIVE failed with %d\n", GetLastError())); if (fWasScreenSaverActive) Log(("VBoxTray: Disabling the screensaver\n")); ret = SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0); if (!ret) Log(("VBoxTray: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %d\n", GetLastError())); PostMessage(ghwndToolWindow, WM_VBOX_SEAMLESS_ENABLE, 0, 0); break; case VMMDev_Seamless_Host_Window: break; default: AssertFailed(); break; } break; } else { Log(("VBoxTray: VBoxSeamlessThread: error from DeviceIoControl VBOXGUEST_IOCTL_VMMREQUEST\n")); } /* sleep a bit to not eat too much CPU while retrying */ /* are we supposed to stop? */ if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 50) == WAIT_OBJECT_0) { fTerminate = true; break; } } } } else { Log(("VBoxTray: VBoxTray: error 0 from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n")); /* sleep a bit to not eat too much CPU in case the above call always fails */ if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0) { fTerminate = true; break; } } } while (!fTerminate); maskInfo.u32OrMask = 0; maskInfo.u32NotMask = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) { Log(("VBoxTray: VBoxSeamlessThread: DeviceIOControl(CtlMask - not) succeeded\n")); } else { Log(("VBoxTray: VBoxSeamlessThread: DeviceIOControl(CtlMask) failed\n")); } Log(("VBoxTray: VBoxSeamlessThread: finished seamless change request thread\n")); return 0; }
VBGLR3DECL(int) vbglR3GRPerform(VMMDevRequestHeader *pReq) { return vbglR3DoIOCtl(VBOXGUEST_IOCTL_VMMREQUEST(pReq->size), pReq, pReq->size); }
/** * Thread function to wait for and process seamless mode change * requests */ static DECLCALLBACK(int) VBoxSeamlessWorker(void *pInstance, bool volatile *pfShutdown) { AssertPtrReturn(pInstance, VERR_INVALID_POINTER); LogFlowFunc(("pInstance=%p\n", pInstance)); /* * Tell the control thread that it can continue * spawning services. */ RTThreadUserSignal(RTThreadSelf()); PVBOXSEAMLESSCONTEXT pCtx = (PVBOXSEAMLESSCONTEXT)pInstance; HANDLE gVBoxDriver = pCtx->pEnv->hDriver; VBoxGuestFilterMaskInfo maskInfo; DWORD cbReturned; BOOL fWasScreenSaverActive = FALSE, fRet; maskInfo.u32OrMask = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; maskInfo.u32NotMask = 0; if (!DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) { DWORD dwErr = GetLastError(); LogRel(("Seamless: DeviceIOControl(CtlMask) failed with %ld, exiting ...\n", dwErr)); return RTErrConvertFromWin32(dwErr); } int rc = VINF_SUCCESS; for (;;) { /* wait for a seamless change event */ VBoxGuestWaitEventInfo waitEvent; waitEvent.u32TimeoutIn = 5000; waitEvent.u32EventMaskIn = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL)) { /* are we supposed to stop? */ if (*pfShutdown) break; /* did we get the right event? */ if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST) { /* We got at least one event. Read the requested resolution * and try to set it until success. New events will not be seen * but a new resolution will be read in this poll loop. */ for (;;) { /* get the seamless change request */ VMMDevSeamlessChangeRequest seamlessChangeRequest = {0}; vmmdevInitRequest((VMMDevRequestHeader*)&seamlessChangeRequest, VMMDevReq_GetSeamlessChangeRequest); seamlessChangeRequest.eventAck = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; BOOL fSeamlessChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(seamlessChangeRequest)), &seamlessChangeRequest, sizeof(seamlessChangeRequest), &seamlessChangeRequest, sizeof(seamlessChangeRequest), &cbReturned, NULL); if (fSeamlessChangeQueried) { LogFlowFunc(("Mode changed to %d\n", seamlessChangeRequest.mode)); switch(seamlessChangeRequest.mode) { case VMMDev_Seamless_Disabled: if (fWasScreenSaverActive) { LogRel(("Seamless: Re-enabling the screensaver\n")); fRet = SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, NULL, 0); if (!fRet) LogRel(("Seamless: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %ld\n", GetLastError())); } PostMessage(g_hwndToolWindow, WM_VBOX_SEAMLESS_DISABLE, 0, 0); break; case VMMDev_Seamless_Visible_Region: fRet = SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &fWasScreenSaverActive, 0); if (!fRet) LogRel(("Seamless: SystemParametersInfo SPI_GETSCREENSAVEACTIVE failed with %ld\n", GetLastError())); if (fWasScreenSaverActive) LogRel(("Seamless: Disabling the screensaver\n")); fRet = SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0); if (!fRet) LogRel(("Seamless: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %ld\n", GetLastError())); PostMessage(g_hwndToolWindow, WM_VBOX_SEAMLESS_ENABLE, 0, 0); break; case VMMDev_Seamless_Host_Window: break; default: AssertFailed(); break; } break; } else LogRel(("Seamless: DeviceIoControl(ChangeReq) failed with %ld\n", GetLastError())); if (*pfShutdown) break; /* sleep a bit to not eat too much CPU while retrying */ RTThreadSleep(10); } } } else { /* sleep a bit to not eat too much CPU in case the above call always fails */ RTThreadSleep(10); } if (*pfShutdown) break; } maskInfo.u32OrMask = 0; maskInfo.u32NotMask = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; if (!DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) LogRel(("Seamless: DeviceIOControl(CtlMask) failed with %ld\n", GetLastError())); LogFlowFuncLeaveRC(rc); return rc; }
/** * Thread function to wait for and process mode change requests */ unsigned __stdcall VBoxVRDPThread(void *pInstance) { VBOXVRDPCONTEXT *pCtx = (VBOXVRDPCONTEXT *)pInstance; HANDLE gVBoxDriver = pCtx->pEnv->hDriver; bool fTerminate = false; VBoxGuestFilterMaskInfo maskInfo; DWORD cbReturned; maskInfo.u32OrMask = VMMDEV_EVENT_VRDP; maskInfo.u32NotMask = 0; if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) { Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask - or) succeeded\n")); } else { Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask) failed\n")); return 0; } do { /* wait for the event */ VBoxGuestWaitEventInfo waitEvent; waitEvent.u32TimeoutIn = 5000; waitEvent.u32EventMaskIn = VMMDEV_EVENT_VRDP; if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL)) { Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl succeeded\n")); /* are we supposed to stop? */ if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 0) == WAIT_OBJECT_0) break; Log(("VBoxTray: VBoxVRDPThread: checking event\n")); /* did we get the right event? */ if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_VRDP) { /* Call the host to get VRDP status and the experience level. */ VMMDevVRDPChangeRequest vrdpChangeRequest = {0}; vrdpChangeRequest.header.size = sizeof(VMMDevVRDPChangeRequest); vrdpChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION; vrdpChangeRequest.header.requestType = VMMDevReq_GetVRDPChangeRequest; vrdpChangeRequest.u8VRDPActive = 0; vrdpChangeRequest.u32VRDPExperienceLevel = 0; if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevVRDPChangeRequest)), &vrdpChangeRequest, sizeof(VMMDevVRDPChangeRequest), &vrdpChangeRequest, sizeof(VMMDevVRDPChangeRequest), &cbReturned, NULL)) { Log(("VBoxTray: VBoxVRDPThread: u8VRDPActive = %d, level %d\n", vrdpChangeRequest.u8VRDPActive, vrdpChangeRequest.u32VRDPExperienceLevel)); if (vrdpChangeRequest.u8VRDPActive) { pCtx->level = vrdpChangeRequest.u32VRDPExperienceLevel; vboxExperienceSet (pCtx->level); if (pCtx->level == VRDP_EXPERIENCE_LEVEL_ZERO && pCtx->pfnEnableTheming && pCtx->pfnIsThemeActive) { pCtx->fSavedThemeEnabled = pCtx->pfnIsThemeActive (); Log(("VBoxTray: VBoxVRDPThread: pCtx->fSavedThemeEnabled = %d\n", pCtx->fSavedThemeEnabled)); if (pCtx->fSavedThemeEnabled) { pCtx->pfnEnableTheming (FALSE); } } } else { if (pCtx->level == VRDP_EXPERIENCE_LEVEL_ZERO && pCtx->pfnEnableTheming && pCtx->pfnIsThemeActive) { if (pCtx->fSavedThemeEnabled) { /* @todo the call returns S_OK but theming remains disabled. */ HRESULT hrc = pCtx->pfnEnableTheming (TRUE); Log(("VBoxTray: VBoxVRDPThread: enabling theme rc = 0x%08X\n", hrc)); pCtx->fSavedThemeEnabled = FALSE; } } vboxExperienceRestore (pCtx->level); pCtx->level = VRDP_EXPERIENCE_LEVEL_FULL; } } else { Log(("VBoxTray: VBoxVRDPThread: Error from DeviceIoControl VBOXGUEST_IOCTL_VMMREQUEST\n")); /* sleep a bit to not eat too much CPU in case the above call always fails */ if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0) { fTerminate = true; break; } } } } else { Log(("VBoxTray: VBoxVRDPThread: Error from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n")); /* sleep a bit to not eat too much CPU in case the above call always fails */ if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0) { fTerminate = true; break; } } } while (!fTerminate); maskInfo.u32OrMask = 0; maskInfo.u32NotMask = VMMDEV_EVENT_VRDP; if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) { Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask - not) succeeded\n")); } else { Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask) failed\n")); } Log(("VBoxTray: VBoxVRDPThread: Finished VRDP change request thread\n")); return 0; }