/* $Id: VBoxMPUtils.cpp $ */ /** @file * VBox Miniport utils */ /* * Copyright (C) 2011-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ #include "VBoxMPUtils.h" #ifdef VBOX_XPDM_MINIPORT RT_C_DECLS_BEGIN # include RT_C_DECLS_END #endif #include #include #ifdef DEBUG_misha /* specifies whether the vboxVDbgBreakF should break in the debugger * windbg seems to have some issues when there is a lot ( >~50) of sw breakpoints defined * to simplify things we just insert breaks for the case of intensive debugging WDDM driver*/ #ifndef VBOX_WDDM_WIN8 int g_bVBoxVDbgBreakF = false; int g_bVBoxVDbgBreakFv = false; #else int g_bVBoxVDbgBreakF = false; int g_bVBoxVDbgBreakFv = false; #endif #endif #pragma alloc_text(PAGE, VBoxQueryWinVersion) #pragma alloc_text(PAGE, VBoxGetHeightReduction) #pragma alloc_text(PAGE, VBoxLikesVideoMode) #pragma alloc_text(PAGE, VBoxQueryDisplayRequest) #pragma alloc_text(PAGE, VBoxQueryHostWantsAbsolute) #pragma alloc_text(PAGE, VBoxQueryPointerPos) /*Returns the windows version we're running on*/ vboxWinVersion_t VBoxQueryWinVersion() { ULONG major, minor, build; BOOLEAN checkedBuild; static vboxWinVersion_t s_WinVersion = UNKNOWN_WINVERSION; if (s_WinVersion != UNKNOWN_WINVERSION) return s_WinVersion; checkedBuild = PsGetVersion(&major, &minor, &build, NULL); LOG(("running on version %d.%d, build %d(checked=%d)", major, minor, build, (int)checkedBuild)); if(major == 6) { if (minor == 3) s_WinVersion = WIN81; else if (minor == 2) s_WinVersion = WIN8; else if (minor == 1) s_WinVersion = WIN7; else if (minor == 0) s_WinVersion = WINVISTA; /* Or Windows Server 2008. */ } else if (major == 5) s_WinVersion = (minor>=1) ? WINXP:WIN2K; else if (major == 4) s_WinVersion = WINNT4; else WARN(("NT4 required!")); return s_WinVersion; } 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; } 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; } 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; } 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; } /* Returns if the host wants us to take absolute pointer coordinates. */ bool VBoxQueryHostWantsAbsolute() { return VBoxQueryPointerPosInternal(NULL, NULL); } bool VBoxQueryPointerPos(uint16_t *pPosX, uint16_t *pPosY) { if (!pPosX || !pPosY) { return FALSE; } return VBoxQueryPointerPosInternal(pPosX, pPosY); }