/* $Id$ */
/** @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 <ntddk.h>
RT_C_DECLS_END
#endif
#include <VBox/VMMDev.h>
#include <VBox/VBoxGuestLib.h>
#ifdef DEBUG_misha
/* specifies whether the vboxVDbgBreakF should break in the debugger
* windbg seems to have some issues when there is a lot ( >32) 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 = 0;
int g_bVBoxVDbgBreakFv = 0;
#else
int g_bVBoxVDbgBreakF = 0;
int g_bVBoxVDbgBreakFv = 0;
#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 = WINVERSION_UNKNOWN;
if (s_WinVersion != WINVERSION_UNKNOWN)
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)
{
/* Everything newer than Windows 8.1, i.e. Windows 10 with major == 10. */
s_WinVersion = WINVERSION_10;
}
else if (major == 6)
{
if (minor >= 4)
s_WinVersion = WINVERSION_10;
else if (minor == 3)
s_WinVersion = WINVERSION_81;
else if (minor == 2)
s_WinVersion = WINVERSION_8;
else if (minor == 1)
s_WinVersion = WINVERSION_7;
else if (minor == 0)
s_WinVersion = WINVERSION_VISTA; /* Or Windows Server 2008. */
}
else if (major == 5)
s_WinVersion = (minor>=1) ? WINVERSION_XP: WINVERSION_2K;
else if (major == 4)
s_WinVersion = WINVERSION_NT4;
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);
}