HGCMInternal.cpp revision 29cbc19ceba9f32676013814929486503e2bbb4d
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/* $Revision$ */
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * VBoxGuestLib - Host-Guest Communication Manager internal functions, implemented by VBoxGuest
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Copyright (C) 2006-2007 Oracle Corporation
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * available from http://www.virtualbox.org. This file is free software;
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * General Public License (GPL) as published by the Free Software
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * The contents of this file may alternatively be used under the terms
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * of the Common Development and Distribution License Version 1.0
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * VirtualBox OSE distribution, in which case the provisions of the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * CDDL are applicable instead of those of the GPL.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * You may elect to license modified versions of this file under the
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync * terms and conditions of either the GPL or the CDDL or both.
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/* Entire file is ifdef'ed with VBGL_VBOXGUEST */
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync/*******************************************************************************
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync* Header Files *
14ea49401f3c8c61422aefbda43809e275f60c6cvboxsync*******************************************************************************/
#ifdef RT_OS_LINUX
# define USE_BOUNCE_BUFFERS
struct VbglR0ParmInfo
#ifdef USE_BOUNCE_BUFFERS
void *pvSmallBuf;
int rc;
return VERR_INVALID_PARAMETER;
rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMConnect, sizeof (VMMDevHGCMConnect), VMMDevReq_HGCMConnect);
return rc;
int rc;
return VERR_INVALID_PARAMETER;
rc = VbglGRAlloc ((VMMDevRequestHeader **)&pHGCMDisconnect, sizeof (VMMDevHGCMDisconnect), VMMDevReq_HGCMDisconnect);
return rc;
static int vbglR0HGCMInternalPreprocessCall(VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo,
*pcbExtra = 0;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
if (fIsUser)
return VERR_INVALID_PARAMETER;
if (cb)
AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
AssertMsgReturn(pPgLst->offFirstPage < PAGE_SIZE, ("#x\n", pPgLst->offFirstPage), VERR_INVALID_PARAMETER);
AssertMsgReturn(VBOX_HGCM_F_PARM_ARE_VALID(pPgLst->flags), ("%#x\n", pPgLst->flags), VERR_INVALID_PARAMETER);
while (u32-- > 0)
if (fIsUser)
return VERR_INVALID_PARAMETER;
if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
if (cb != 0)
if (cb != 0)
#ifdef USE_BOUNCE_BUFFERS
int rc;
if (!fIsUser)
AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
return rc;
return VERR_OUT_OF_RANGE;
#ifndef USE_BOUNCE_BUFFERS
rc = RTR0MemObjLockUser(&hObj, (RTR3PTR)pSrcParm->u.Pointer.u.linearAddr, cb, fAccess, NIL_RTR0PROCESS);
return rc;
return VERR_NO_MEMORY;
if (fCopyIn)
return rc;
return rc;
return rc;
if (!fCopyIn)
return rc;
#ifdef USE_BOUNCE_BUFFERS
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
static HGCMFunctionParameterType vbglR0HGCMInternalConvertLinAddrType(HGCMFunctionParameterType enmType)
switch (enmType)
return VMMDevHGCMParmType_LinAddr_In;
return VMMDevHGCMParmType_LinAddr_Out;
return VMMDevHGCMParmType_LinAddr;
return enmType;
switch (enmType)
default: AssertFailed();
return VBOX_HGCM_F_PARM_DIRECTION_BOTH;
static void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo,
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
HGCMPageListInfo const *pSrcPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + pSrcParm->u.PageList.offset);
if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
#ifdef USE_BOUNCE_BUFFERS
#ifdef USE_BOUNCE_BUFFERS
if (fIsUser)
#ifdef USE_BOUNCE_BUFFERS
if (fIsUser)
iLockBuf++;
AssertFailed();
static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, PFNVBGLHGCMCALLBACK pfnAsyncCallback,
int rc;
*pfLeakIt = false;
int rc2 = VbglGRAlloc((VMMDevRequestHeader **)&pCancelReq, sizeof(*pCancelReq), VMMDevReq_HGCMCancel2);
if (RT_SUCCESS(rc)) rc = VERR_INTERRUPTED; /** @todo weed this out from the WINNT VBoxGuest code. */
static unsigned s_cErrors = 0;
LogRel(("vbglR0HGCMInternalDoCall: Leaking %u bytes. Pending call to %u with %u parms. (rc2=%Rrc)\n",
*pfLeakIt = true;
Log(("vbglR0HGCMInternalDoCall: Cancel race ended with rc=%Rrc (rc2=%Rrc) after %llu ms\n", rc, rc2, cElapsed));
return rc;
static int vbglR0HGCMInternalCopyBackResult(VBoxGuestHGCMCallInfo *pCallInfo, VMMDevHGCMCall const *pHGCMCall,
#ifdef USE_BOUNCE_BUFFERS
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
#ifdef USE_BOUNCE_BUFFERS
if ( fIsUser
iLockBuf++;
if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST())
#ifdef USE_BOUNCE_BUFFERS
if (fIsUser)
if (cbOut)
int rc2;
cbOut);
return rc2;
iLockBuf++;
iLockBuf++;
AssertFailed();
#ifdef USE_BOUNCE_BUFFERS
return rc;
DECLR0VBGL(int) VbglR0HGCMInternalCall(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
int rc;
|| !pfnAsyncCallback
pCallInfo->u32ClientID, pCallInfo->u32ClientID, pCallInfo->u32Function, pCallInfo->cParms, cbCallInfo, fFlags));
bool fLeakIt;
static unsigned s_cErrors = 0;
if (!fLeakIt)
#ifdef USE_BOUNCE_BUFFERS
return rc;
DECLR0VBGL(int) VbglR0HGCMInternalCall32(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
|| !pfnAsyncCallback
Log(("VbglR0HGCMInternalCall32: cParms=%d, u32Function=%d, fFlags=%#x\n", cParms, pCallInfo->u32Function, fFlags));
pCallInfo64 = (VBoxGuestHGCMCallInfo *)RTMemTmpAllocZ(sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter));
if (!pCallInfo64)
return VERR_NO_TMP_MEMORY;
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
rc = VbglR0HGCMInternalCall(pCallInfo64, sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter), fFlags,
case VMMDevHGCMParmType_32bit:
case VMMDevHGCMParmType_64bit:
static unsigned s_cErrors = 0;
static unsigned s_cErrors = 0;
return rc;