bool VBoxLikesVideoMode(uint32_t display, uint32_t width, uint32_t height, uint32_t bpp) { bool bRC = FALSE; VMMDevVideoModeSupportedRequest2 *req2 = NULL; int rc = VbglGRAlloc((VMMDevRequestHeader**)&req2, sizeof(VMMDevVideoModeSupportedRequest2), VMMDevReq_VideoModeSupported2); if (RT_FAILURE(rc)) { LOG(("ERROR allocating request, rc = %#xrc", rc)); /* Most likely the VBoxGuest driver is not loaded. * To get at least the video working, report the mode as supported. */ bRC = TRUE; } else { req2->display = display; req2->width = width; req2->height = height; req2->bpp = bpp; rc = VbglGRPerform(&req2->header); if (RT_SUCCESS(rc)) { bRC = req2->fSupported; } else { /* Retry using old interface. */ AssertCompile(sizeof(VMMDevVideoModeSupportedRequest2) >= sizeof(VMMDevVideoModeSupportedRequest)); VMMDevVideoModeSupportedRequest *req = (VMMDevVideoModeSupportedRequest *)req2; req->header.size = sizeof(VMMDevVideoModeSupportedRequest); req->header.version = VMMDEV_REQUEST_HEADER_VERSION; req->header.requestType = VMMDevReq_VideoModeSupported; req->header.rc = VERR_GENERAL_FAILURE; req->header.reserved1 = 0; req->header.reserved2 = 0; req->width = width; req->height = height; req->bpp = bpp; rc = VbglGRPerform(&req->header); if (RT_SUCCESS(rc)) { bRC = req->fSupported; } else { WARN(("ERROR querying video mode supported status from VMMDev. rc = %#xrc", rc)); } } VbglGRFree(&req2->header); } LOG(("width: %d, height: %d, bpp: %d -> %s", width, height, bpp, (bRC == 1) ? "OK" : "FALSE")); return bRC; }
void VbgdNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) { #ifdef VBOXGUEST_WITH_INPUT_DRIVER int rc; #endif NOREF(pDevExt); /* * Wake up everyone that's in a poll() and post anyone that has * subscribed to async notifications. */ Log3(("VbgdNativeISRMousePollEvent: wake_up_all\n")); wake_up_all(&g_PollEventQueue); Log3(("VbgdNativeISRMousePollEvent: kill_fasync\n")); kill_fasync(&g_pFAsyncQueue, SIGIO, POLL_IN); #ifdef VBOXGUEST_WITH_INPUT_DRIVER /* Report events to the kernel input device */ g_pMouseStatusReq->mouseFeatures = 0; g_pMouseStatusReq->pointerXPos = 0; g_pMouseStatusReq->pointerYPos = 0; rc = VbglGRPerform(&g_pMouseStatusReq->header); if (RT_SUCCESS(rc)) { input_report_abs(g_pInputDevice, ABS_X, g_pMouseStatusReq->pointerXPos); input_report_abs(g_pInputDevice, ABS_Y, g_pMouseStatusReq->pointerYPos); # ifdef EV_SYN input_sync(g_pInputDevice); # endif } #endif Log3(("VbgdNativeISRMousePollEvent: done\n")); }
uint32_t VBoxGetHeightReduction() { uint32_t retHeight = 0; int rc; LOGF_ENTER(); VMMDevGetHeightReductionRequest *req = NULL; rc = VbglGRAlloc((VMMDevRequestHeader**)&req, sizeof(VMMDevGetHeightReductionRequest), VMMDevReq_GetHeightReduction); if (RT_FAILURE(rc)) { WARN(("ERROR allocating request, rc = %#xrc", rc)); } else { rc = VbglGRPerform(&req->header); if (RT_SUCCESS(rc)) { retHeight = req->heightReduction; } else { WARN(("ERROR querying height reduction value from VMMDev. rc = %#xrc", rc)); } VbglGRFree(&req->header); } LOGF_LEAVE(); return retHeight; }
static bool VBoxQueryPointerPosInternal(uint16_t *pPosX, uint16_t *pPosY) { bool bRC = FALSE; VMMDevReqMouseStatus *req = NULL; int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevReqMouseStatus), VMMDevReq_GetMouseStatus); if (RT_FAILURE(rc)) { LOG(("ERROR allocating request, rc = %#xrc", rc)); } else { rc = VbglGRPerform(&req->header); if (RT_SUCCESS(rc)) { if (req->mouseFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE) { if (pPosX) { *pPosX = req->pointerXPos; } if (pPosY) { *pPosY = req->pointerYPos; } bRC = TRUE; } } else { LOG(("ERROR querying mouse capabilities from VMMDev. rc = %#xrc", rc)); } VbglGRFree(&req->header); } return bRC; }
bool VBoxQueryDisplayRequest(uint32_t *xres, uint32_t *yres, uint32_t *bpp, uint32_t *pDisplayId) { bool bRC = FALSE; VMMDevDisplayChangeRequest2 *req = NULL; LOGF_ENTER(); int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevDisplayChangeRequest2), VMMDevReq_GetDisplayChangeRequest2); if (RT_FAILURE(rc)) { LOG(("ERROR allocating request, rc = %#xrc", rc)); } else { req->eventAck = 0; rc = VbglGRPerform (&req->header); if (RT_SUCCESS(rc)) { if (xres) *xres = req->xres; if (yres) *yres = req->yres; if (bpp) *bpp = req->bpp; if (pDisplayId) *pDisplayId = req->display; LOG(("returning %d x %d @ %d for %d", req->xres, req->yres, req->bpp, req->display)); bRC = TRUE; } else { WARN(("ERROR querying display request from VMMDev. rc = %#xrc", rc)); } VbglGRFree (&req->header); } LOGF_LEAVE(); return bRC; }
VOID VBoxDrvNotifyServiceCB(PVBOXMOUSE_DEVEXT pDevExt, PMOUSE_INPUT_DATA InputDataStart, PMOUSE_INPUT_DATA InputDataEnd, PULONG InputDataConsumed) { KIRQL Irql; /* we need to avoid concurrency between the poller thread and our ServiceCB. * this is perhaps not the best way of doing things, but the most easiest to avoid concurrency * and to ensure the pfnServiceCB is invoked at DISPATCH_LEVEL */ KeAcquireSpinLock(&g_ctx.SyncLock, &Irql); if (pDevExt->pSCReq) { int rc = VbglGRPerform(&pDevExt->pSCReq->header); if (RT_SUCCESS(rc)) { if (pDevExt->pSCReq->mouseFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE) { PMOUSE_INPUT_DATA pData = InputDataStart; while (pData<InputDataEnd) { pData->LastX = pDevExt->pSCReq->pointerXPos; pData->LastY = pDevExt->pSCReq->pointerYPos; pData->Flags = MOUSE_MOVE_ABSOLUTE; if (vboxNewProtIsEnabled()) pData->Flags |= MOUSE_VIRTUAL_DESKTOP; pData++; } /* get the last data & cache it */ --pData; g_ctx.LastReportedData.UnitId = pData->UnitId; } } else { WARN(("VbglGRPerform failed with rc=%#x", rc)); } } /* Call original callback */ pDevExt->OriginalConnectData.pfnServiceCB(pDevExt->OriginalConnectData.pDO, InputDataStart, InputDataEnd, InputDataConsumed); KeReleaseSpinLock(&g_ctx.SyncLock, Irql); }
/** * Used by vbglQueryDriverInfo and VbglInit to try get the host feature mask and * version information (g_vbgldata::hostVersion). * * This was first implemented by the host in 3.1 and we quietly ignore failures * for that reason. */ static void vbglR0QueryHostVersion (void) { VMMDevReqHostVersion *pReq; int rc = VbglGRAlloc ((VMMDevRequestHeader **) &pReq, sizeof (*pReq), VMMDevReq_GetHostVersion); if (RT_SUCCESS (rc)) { rc = VbglGRPerform (&pReq->header); if (RT_SUCCESS (rc)) { g_vbgldata.hostVersion = *pReq; Log (("vbglR0QueryHostVersion: %u.%u.%ur%u %#x\n", pReq->major, pReq->minor, pReq->build, pReq->revision, pReq->features)); } VbglGRFree (&pReq->header); } }
/** * IRP_MJ_SHUTDOWN handler. * * @returns NT status code * @param pDevObj Device object. * @param pIrp IRP. */ NTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp) { PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; Log(("VBoxGuest::vboxguestwinGuestShutdown\n")); VMMDevPowerStateRequest *pReq = pDevExt->win.s.pPowerStateRequest; if (pReq) { pReq->header.requestType = VMMDevReq_SetPowerStatus; pReq->powerState = VMMDevPowerState_PowerOff; int rc = VbglGRPerform(&pReq->header); if (RT_FAILURE(rc)) { Log(("VBoxGuest::vboxguestwinGuestShutdown: Error performing request to VMMDev! " "rc = %Rrc\n", rc)); } } return STATUS_SUCCESS; }
static DECLCALLBACK(void) VBoxVbvaFlush(void *pvFlush) { LOGF_ENTER(); PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT)pvFlush; PVBOXMP_DEVEXT pPrimary = pExt? pExt->pPrimary: NULL; if (pPrimary) { VMMDevVideoAccelFlush *req = (VMMDevVideoAccelFlush *)pPrimary->u.primary.pvReqFlush; if (req) { int rc = VbglGRPerform (&req->header); if (RT_FAILURE(rc)) { WARN(("rc = %#xrc!", rc)); } } } LOGF_LEAVE(); }
/* Called for IOCTL_VIDEO_VBOX_SETVISIBLEREGION. * Sends visible regions information to the host. */ BOOLEAN VBoxMPSetVisibleRegion(uint32_t cRects, RTRECT *pRects, PSTATUS_BLOCK pStatus) { int rc; BOOLEAN bRC = FALSE; LOGF_ENTER(); VMMDevVideoSetVisibleRegion *req = NULL; rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT), VMMDevReq_VideoSetVisibleRegion); if (RT_SUCCESS(rc)) { req->cRect = cRects; memcpy(&req->Rect, pRects, cRects*sizeof(RTRECT)); rc = VbglGRPerform(&req->header); if (RT_SUCCESS(rc)) { bRC=TRUE; } VbglGRFree(&req->header); } else { WARN(("VbglGRAlloc rc = %#xrc", rc)); } if (!bRC) { pStatus->Status = ERROR_INVALID_FUNCTION; } LOGF_LEAVE(); return bRC; }
int VBoxVbvaEnable(PVBOXMP_DEVEXT pExt, BOOLEAN bEnable, VBVAENABLERESULT *pResult) { int rc = VINF_SUCCESS; LOGF_ENTER(); VMMDevMemory *pVMMDevMemory = NULL; rc = VbglQueryVMMDevMemory (&pVMMDevMemory); if (RT_FAILURE(rc)) { WARN(("VbglQueryVMMDevMemory rc = %#xrc", rc)); LOGF_LEAVE(); return rc; } if (pExt->iDevice>0) { PVBOXMP_DEVEXT pPrimary = pExt->pPrimary; LOGF(("skipping non-primary display %d", pExt->iDevice)); if (bEnable && pPrimary->u.primary.ulVbvaEnabled && pVMMDevMemory) { pResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory; pResult->pfnFlush = VBoxVbvaFlush; pResult->pvFlush = pExt; } else { VideoPortZeroMemory(&pResult, sizeof(VBVAENABLERESULT)); } LOGF_LEAVE(); return rc; } /* Allocate the memory block for VMMDevReq_VideoAccelFlush request. */ if (pExt->u.primary.pvReqFlush == NULL) { VMMDevVideoAccelFlush *req = NULL; rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevVideoAccelFlush), VMMDevReq_VideoAccelFlush); if (RT_SUCCESS(rc)) { pExt->u.primary.pvReqFlush = req; } else { WARN(("VbglGRAlloc(VMMDevVideoAccelFlush) rc = %#xrc", rc)); LOGF_LEAVE(); return rc; } } ULONG ulEnabled = 0; VMMDevVideoAccelEnable *req = NULL; rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevVideoAccelEnable), VMMDevReq_VideoAccelEnable); if (RT_SUCCESS(rc)) { req->u32Enable = bEnable; req->cbRingBuffer = VBVA_RING_BUFFER_SIZE; req->fu32Status = 0; rc = VbglGRPerform(&req->header); if (RT_SUCCESS(rc)) { if (req->fu32Status & VBVA_F_STATUS_ACCEPTED) { LOG(("accepted")); /* Initialize the result information and VBVA memory. */ if (req->fu32Status & VBVA_F_STATUS_ENABLED) { pResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory; pResult->pfnFlush = VBoxVbvaFlush; pResult->pvFlush = pExt; ulEnabled = 1; } else { VideoPortZeroMemory(&pResult, sizeof(VBVAENABLERESULT)); } } else { LOG(("rejected")); /* Disable VBVA for old hosts. */ req->u32Enable = 0; req->cbRingBuffer = VBVA_RING_BUFFER_SIZE; req->fu32Status = 0; VbglGRPerform(&req->header); rc = VERR_NOT_SUPPORTED; } } else { WARN(("rc = %#xrc", rc)); } VbglGRFree(&req->header); } else { WARN(("VbglGRAlloc(VMMDevVideoAccelEnable) rc = %#xrc", rc)); } pExt->u.primary.ulVbvaEnabled = ulEnabled; LOGF_LEAVE(); return rc; }
/** * Handle the Power requests. * * @returns NT status code * @param pDevObj device object * @param pIrp IRP */ NTSTATUS vbgdNtPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) { PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; POWER_STATE_TYPE enmPowerType = pStack->Parameters.Power.Type; POWER_STATE PowerState = pStack->Parameters.Power.State; POWER_ACTION enmPowerAction = pStack->Parameters.Power.ShutdownType; Log(("VBoxGuest::vbgdNtGuestPower\n")); switch (pStack->MinorFunction) { case IRP_MN_SET_POWER: { Log(("VBoxGuest::vbgdNtGuestPower: IRP_MN_SET_POWER, type= %d\n", enmPowerType)); switch (enmPowerType) { case SystemPowerState: { Log(("VBoxGuest::vbgdNtGuestPower: SystemPowerState, action = %d, state = %d/%d\n", enmPowerAction, PowerState.SystemState, PowerState.DeviceState)); switch (enmPowerAction) { case PowerActionSleep: /* System now is in a working state. */ if (PowerState.SystemState == PowerSystemWorking) { if ( pDevExt && pDevExt->LastSystemPowerAction == PowerActionHibernate) { Log(("VBoxGuest::vbgdNtGuestPower: Returning from hibernation!\n")); int rc = VbgdCommonReinitDevExtAfterHibernation(&pDevExt->Core, vbgdNtVersionToOSType(g_enmVbgdNtVer)); if (RT_FAILURE(rc)) Log(("VBoxGuest::vbgdNtGuestPower: Cannot re-init VMMDev chain, rc = %d!\n", rc)); } } break; case PowerActionShutdownReset: { Log(("VBoxGuest::vbgdNtGuestPower: Power action reset!\n")); /* Tell the VMM that we no longer support mouse pointer integration. */ VMMDevReqMouseStatus *pReq = NULL; int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof (VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus); if (RT_SUCCESS(vrc)) { pReq->mouseFeatures = 0; pReq->pointerXPos = 0; pReq->pointerYPos = 0; vrc = VbglGRPerform(&pReq->header); if (RT_FAILURE(vrc)) { Log(("VBoxGuest::PowerStateRequest: error communicating new power status to VMMDev. vrc = %Rrc\n", vrc)); } VbglGRFree(&pReq->header); } /* Don't do any cleanup here; there might be still coming in some IOCtls after we got this * power action and would assert/crash when we already cleaned up all the stuff! */ break; } case PowerActionShutdown: case PowerActionShutdownOff: { Log(("VBoxGuest::vbgdNtGuestPower: Power action shutdown!\n")); if (PowerState.SystemState >= PowerSystemShutdown) { Log(("VBoxGuest::vbgdNtGuestPower: Telling the VMMDev to close the VM ...\n")); VMMDevPowerStateRequest *pReq = pDevExt->pPowerStateRequest; int vrc = VERR_NOT_IMPLEMENTED; if (pReq) { pReq->header.requestType = VMMDevReq_SetPowerStatus; pReq->powerState = VMMDevPowerState_PowerOff; vrc = VbglGRPerform(&pReq->header); } if (RT_FAILURE(vrc)) Log(("VBoxGuest::PowerStateRequest: Error communicating new power status to VMMDev. vrc = %Rrc\n", vrc)); /* No need to do cleanup here; at this point we should've been * turned off by VMMDev already! */ } break; } case PowerActionHibernate: Log(("VBoxGuest::vbgdNtGuestPower: Power action hibernate!\n")); break; } /* * Save the current system power action for later use. * This becomes handy when we return from hibernation for example. */ if (pDevExt) pDevExt->LastSystemPowerAction = enmPowerAction; break; } default: break; } break; } default: break; } /* * Whether we are completing or relaying this power IRP, * we must call PoStartNextPowerIrp. */ PoStartNextPowerIrp(pIrp); /* * Send the IRP down the driver stack, using PoCallDriver * (not IoCallDriver, as for non-power irps). */ IoCopyCurrentIrpStackLocationToNext(pIrp); IoSetCompletionRoutine(pIrp, vbgdNtPowerComplete, (PVOID)pDevExt, TRUE, TRUE, TRUE); return PoCallDriver(pDevExt->pNextLowerDriver, pIrp); }
VOID VBoxDeviceRemoved(PVBOXMOUSE_DEVEXT pDevExt) { LOGF_ENTER(); /* Save the allocated request pointer and clear the devExt. */ VMMDevReqMouseStatus *pSCReq = (VMMDevReqMouseStatus *) InterlockedExchangePointer((PVOID volatile *)&pDevExt->pSCReq, NULL); if (pDevExt->bHostMouse && vboxIsHostInformed()) { // tell the VMM that from now on we can't handle absolute coordinates anymore VMMDevReqMouseStatus *req = NULL; int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus); if (RT_SUCCESS(rc)) { req->mouseFeatures = 0; req->pointerXPos = 0; req->pointerYPos = 0; rc = VbglGRPerform(&req->header); if (RT_FAILURE(rc)) { WARN(("VbglGRPerform failed with rc=%#x", rc)); } VbglGRFree(&req->header); } else { WARN(("VbglGRAlloc failed with rc=%#x", rc)); } InterlockedExchange(&g_ctx.fHostInformed, FALSE); } if (pSCReq) { VbglGRFree(&pSCReq->header); } LONG callCnt = InterlockedDecrement(&g_ctx.cDevicesStarted); vboxNewProtDeviceRemoved(pDevExt); if (callCnt == 0) { if (vboxIsVBGLInited()) { /* Set the flag to prevent reinitializing of the VBGL. */ InterlockedExchange(&g_ctx.fVBGLInitFailed, TRUE); VbglTerminate(); /* The VBGL is now in the not initialized state. */ InterlockedExchange(&g_ctx.fVBGLInited, FALSE); InterlockedExchange(&g_ctx.fVBGLInitFailed, FALSE); } } LOGF_LEAVE(); }
VOID VBoxInformHost(PVBOXMOUSE_DEVEXT pDevExt) { LOGF_ENTER(); if (!vboxIsVBGLInited()) { WARN(("!vboxIsVBGLInited")); return; } /* Inform host we support absolute coordinates */ if (pDevExt->bHostMouse && !vboxIsHostInformed()) { VMMDevReqMouseStatus *req = NULL; int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus); if (RT_SUCCESS(rc)) { req->mouseFeatures = VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE; if (vboxNewProtIsEnabled()) req->mouseFeatures |= VMMDEV_MOUSE_NEW_PROTOCOL; req->pointerXPos = 0; req->pointerYPos = 0; rc = VbglGRPerform(&req->header); if (RT_SUCCESS(rc)) { InterlockedExchange(&g_ctx.fHostInformed, TRUE); } else { WARN(("VbglGRPerform failed with rc=%#x", rc)); } VbglGRFree(&req->header); } else { WARN(("VbglGRAlloc failed with rc=%#x", rc)); } } /* Preallocate request to be used in VBoxServiceCB*/ if (pDevExt->bHostMouse && !pDevExt->pSCReq) { VMMDevReqMouseStatus *req = NULL; int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevReqMouseStatus), VMMDevReq_GetMouseStatus); if (RT_SUCCESS(rc)) { InterlockedExchangePointer((PVOID volatile *)&pDevExt->pSCReq, req); } else { WARN(("VbglGRAlloc for service callback failed with rc=%#x", rc)); } } LOGF_LEAVE(); }