vboxhgcm.c revision 7704ab3cf2fe38a3307d6abee1f097fa4346e20e
/* $Id$ */
/** @file
* VBox HGCM connection
*/
/*
* Copyright (C) 2008 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* 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.
*/
#ifdef RT_OS_WINDOWS
#include <windows.h>
#include <ddraw.h>
#else
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#endif
#include "cr_error.h"
#include "cr_net.h"
#include "cr_bufpool.h"
#include "cr_mem.h"
#include "cr_string.h"
#include "cr_endian.h"
#include "cr_threads.h"
#include "net_internals.h"
#if 1 /** @todo Try use the Vbgl interface instead of talking directly to the driver? */
# include <VBox/VBoxGuest.h>
#else
# include <VBox/VBoxGuestLib.h>
#endif
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
#include <VBox/VBoxCrHgsmi.h>
#endif
#ifdef DEBUG_misha
#ifdef CRASSERT
#endif
#endif
//#define IN_GUEST
//#if defined(IN_GUEST)
//#define VBOX_WITH_CRHGSMIPROFILE
//#endif
#ifdef VBOX_WITH_CRHGSMIPROFILE
#include <stdio.h>
typedef struct VBOXCRHGSMIPROFILE
{
#define VBOXCRHGSMIPROFILE_GET_TIME_NANO() RTTimeNanoTS()
#define VBOXCRHGSMIPROFILE_GET_TIME_MILLI() RTTimeMilliTS()
/* 10 sec */
#define VBOXCRHGSMIPROFILE_LOG_STEP_TIME (10000000000.)
{
pProfile->cStepsTime = 0;
}
{
}
typedef struct VBOXCRHGSMIPROFILE_SCOPE
{
// bool bDisable;
static VBOXCRHGSMIPROFILE g_VBoxProfile;
static void vboxCrHgsmiLog(char * szString, ...)
{
char szBuffer[4096] = {0};
#ifdef VBOX_WITH_CRHGSMI
#else
#endif
}
{
}
{
// pScope->bDisable = false;
}
{
// if (!pScope->bDisable)
{
{
}
}
}
#define VBOXCRHGSMIPROFILE_TERM() do {} while (0)
#define VBOXCRHGSMIPROFILE_FUNC_PROLOGUE() \
#define VBOXCRHGSMIPROFILE_FUNC_EPILOGUE() \
#else
#define VBOXCRHGSMIPROFILE_INIT() do {} while (0)
#define VBOXCRHGSMIPROFILE_TERM() do {} while (0)
#define VBOXCRHGSMIPROFILE_FUNC_PROLOGUE() do {} while (0)
#define VBOXCRHGSMIPROFILE_FUNC_EPILOGUE() do {} while (0)
#endif
typedef struct {
int initialized;
int num_conns;
#ifdef CHROMIUM_THREADSAFE
#endif
#ifdef RT_OS_WINDOWS
#else
int iGuestDrv;
#endif
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
bool bHgsmiOn;
#endif
static CRVBOXHGCMDATA g_crvboxhgcm = {0,};
typedef enum {
#ifdef RT_OS_WINDOWS
#endif
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
#endif
#define CR_VBOXHGCM_BUFFER_MAGIC 0xABCDE321
typedef struct CRVBOXHGCMBUFFER {
union
{
struct
{
};
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
#endif
};
#ifdef RT_OS_WINDOWS
#endif
#ifndef RT_OS_WINDOWS
#define TRUE true
#define FALSE false
#define INVALID_HANDLE_VALUE (-1)
#endif
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
/* add sizeof header + page align */
#define CRVBOXHGSMI_BUF_HDR_SIZE() (sizeof (CRVBOXHGCMBUFFER))
{
int rc;
NULL,
&pClient->pCmdBuffer);
if (RT_SUCCESS(rc))
{
NULL,
if (RT_SUCCESS(rc))
{
return VINF_SUCCESS;
}
}
return rc;
}
void _crVBoxHGSMIBufferFree(void *data)
{
}
{
{
}
if (pClient->pCmdBuffer)
{
}
if (ppHgsmi)
{
}
return VINF_SUCCESS;
}
#ifdef VBOX_CRHGSMI_WITH_D3DDEV
{
if (pClient)
{
if (RT_SUCCESS(rc))
return (HVBOXCRHGSMI_CLIENT)pClient;
}
return NULL;
}
{
}
#endif
{
#ifdef VBOX_CRHGSMI_WITH_D3DDEV
return pClient;
#else
return &conn->HgsmiClient;
{
if (pHgsmi)
{
if (RT_SUCCESS(rc))
{
return &conn->HgsmiClient;
}
}
}
return NULL;
#endif
}
{
int rc;
if (!buf)
{
crDebug("Buffer pool %p was empty; allocating new %d byte buffer.",
cbSize);
&buf);
if (RT_FAILURE(rc))
}
return buf;
}
{
int rc;
if (RT_FAILURE(rc))
{
return NULL;
}
return pBuf;
}
{
}
{
/* in theory it is OK to use one cmd buffer for asynch cmd submission
* because bDiscard flag should result in allocating a new memory backend if the
* allocation is still in use.
* However, NOTE: since one and the same semaphore synch event is used for completion notification,
* for the notification mechanism working as expected
* 1. host must complete commands in the same order as it receives them
* (to avoid situation when guest receives notification for another command completion)
* 2. guest must eventually wait for command completion unless he specified bDoNotSignalCompletion
* 3. guest must wait for command completion in the same order as it submits them
* in case we can not satisfy any of the above, we should introduce multiple command buffers */
int rc;
if (RT_SUCCESS(rc))
return pHdr;
return NULL;
}
{
/* in theory it is OK to use one cmd buffer for asynch cmd submission
* because bDiscard flag should result in allocating a new memory backend if the
* allocation is still in use.
* However, NOTE: since one and the same semaphore synch event is used for completion notification,
* for the notification mechanism working as expected
* 1. host must complete commands in the same order as it receives them
* (to avoid situation when guest receives notification for another command completion)
* 2. guest must eventually wait for command completion unless he specified bDoNotSignalCompletion
* 3. guest must wait for command completion in the same order as it submits them
* in case we can not satisfy any of the above, we should introduce multiple command buffers */
int rc;
if (RT_FAILURE(rc))
return pHdr;
}
{
if (RT_FAILURE(rc))
}
{
int rc;
if (RT_FAILURE(rc))
{
return rc;
}
return rc;
}
{
if (pClient->pvHGBuffer)
{
if (RT_FAILURE(rc))
{
return NULL;
}
}
}
{
int rc;
if (RT_SUCCESS(rc))
{
return pClient->pvHGBuffer;
}
return NULL;
}
DECLINLINE(void) _crVBoxHGSMIFillCmd(VBOXUHGSMI_BUFFER_SUBMIT *pSubm, PCRVBOXHGSMI_CLIENT pClient, uint32_t cbData)
{
// pSubm->fFlags.bDoNotSignalCompletion = 1; /* <- we do not need that actually since
// * in case we want completion,
// * we will block in _crVBoxHGSMICmdBufferGetRc (when locking the buffer)
// * which is needed for getting the result */
}
#ifdef RT_OS_WINDOWS
#else
# error "Port Me!!"
#endif
{
}
#endif
/* Some forward declarations */
#ifndef IN_GUEST
{
return FALSE;
return TRUE;
}
#endif
/*@todo get rid of it*/
{
/* make sure there's host buffer and it's clear */
{
crDebug("Host buffer too small %d out of requested %d bytes, reallocating", conn->cbHostBufferAllocated, len);
if (!conn->pHostBuffer)
{
conn->cbHostBufferAllocated = 0;
return FALSE;
}
}
return TRUE;
}
/**
* Send an HGCM request
*
* @return VBox status code
* @param pvData Data pointer
* @param cbData Data size
*/
/** @todo use vbglR3DoIOCtl here instead */
{
#ifdef IN_GUEST
# ifdef RT_OS_WINDOWS
NULL))
{
return VINF_SUCCESS;
}
return VERR_NOT_SUPPORTED;
# else
int rc;
# if defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
# if HC_ARCH_BITS == 32
Hdr.u32Padding = 0;
# endif
# else
# endif
# ifdef RT_OS_LINUX
if (rc == 0)
# else
if (rc >= 0)
# endif
{
return VINF_SUCCESS;
}
# ifdef RT_OS_LINUX
if (rc >= 0) /* positive values are negated VBox error status codes. */
{
if (rc==VINF_INTERRUPTED)
{
int i;
{
if (rc==0)
{
return VINF_SUCCESS;
}
else if (rc==VINF_INTERRUPTED)
{
continue;
}
else
{
break;
}
}
}
}
else
# endif
return VERR_NOT_SUPPORTED;
# endif /*#ifdef RT_OS_WINDOWS*/
#else /*#ifdef IN_GUEST*/
crError("crVBoxHGCMCall called on host side!");
return VERR_NOT_SUPPORTED;
#endif
}
{
#ifdef CHROMIUM_THREADSAFE
#endif
if (!buf)
{
crDebug("Buffer pool %p was empty; allocating new %d byte buffer.",
(void *) g_crvboxhgcm.bufpool,
#if defined(IN_GUEST) && defined(RT_OS_WINDOWS)
/* Try to start DDRAW on guest side */
if (!g_crvboxhgcm.pDirectDraw && 0)
{
{
}
else
{
{
}
crDebug("Created DirectDraw and set CooperativeLevel successfully\n");
}
}
/* Try to allocate buffer via DDRAW */
if (g_crvboxhgcm.pDirectDraw)
{
/* @todo DDSCAPS_VIDEOMEMORY ain't working for some reason
* also, it would be better to request dwLinearSize but it fails too
* ddsd.dwLinearSize = sizeof(CRVBOXHGCMBUFFER) + conn->buffer_size;
*/
/* use 1 byte per pixel format */
/* request given buffer size, rounded to 1k */
{
}
else
{
{
}
else
{
}
}
}
#endif
/* We're either on host side, or we failed to allocate DDRAW buffer */
if (!buf)
{
crDebug("Using system malloc\n");
#ifdef RT_OS_WINDOWS
#endif
}
}
#ifdef CHROMIUM_THREADSAFE
#endif
return (void *)( buf + 1 );
}
{
void *pvBuff;
return pvBuff;
}
{
int rc;
#ifdef IN_GUEST
if (conn->u32InjectClientID)
{
}
else
#endif
{
}
{
}
}
{
}
{
int rc;
{
return;
}
{
//conn->pBuffer = (uint8_t*) parms.pBuffer.u.Pointer.u.linearAddr;
}
}
/* Same as crVBoxHGCMWriteExact, but combined with read of writeback data.
* This halves the number of HGCM calls we do,
* most likely crVBoxHGCMPollHost shouldn't be called at all now.
*/
static void
crVBoxHGCMWriteReadExact(CRConnection *conn, const void *buf, unsigned int len, CRVBOXHGCMBUFFERKIND bufferKind)
{
int rc;
//if (bufferKind != CR_VBOXHGCM_DDRAW_SURFACE)
{
}
/*else ///@todo it fails badly, have to check why. bird: This fails because buf isn't a physical address?
{
parms.pBuffer.type = VMMDevHGCMParmType_PhysAddr;
parms.pBuffer.u.Pointer.size = len;
parms.pBuffer.u.Pointer.u.physAddr = (uintptr_t) buf;
}*/
{
{
/* reallocate buffer and retry */
crDebug("Reallocating host buffer from %d to %d bytes", conn->cbHostBufferAllocated, parms.cbWriteback.u.value32);
return;
}
else
{
return;
}
}
{
//conn->pBuffer = (uint8_t*) parms.pWriteback.u.Pointer.u.linearAddr;
}
}
{
if (!bufp) /* We're sending a user-allocated buffer. */
{
#ifndef IN_GUEST
//@todo remove temp buffer allocation in unpacker
/* we're at the host side, so just store data until guest polls us */
#else
#endif
return;
}
/* The region [start .. start + len + 1] lies within a buffer that
* was allocated with crVBoxHGCMAlloc() and can be put into the free
* buffer pool when we're done sending it.
*/
/* Length would be passed as part of HGCM pointer description
* No need to prepend it to the buffer
*/
#ifdef IN_GUEST
if (conn->u32InjectClientID)
{
}
else
#endif
/* Reclaim this pointer for reuse */
#ifdef CHROMIUM_THREADSAFE
#endif
#ifdef CHROMIUM_THREADSAFE
#endif
/* Since the buffer's now in the 'free' buffer pool, the caller can't
* use it any more. Setting bufp to NULL will make sure the caller
* doesn't try to re-use the buffer.
*/
}
{
int rc;
{
return;
}
{
}
}
{
}
{
/*@todo wrong len for redir buffers*/
switch (hgcm_buffer->kind)
{
case CR_VBOXHGCM_MEMORY:
#ifdef RT_OS_WINDOWS
#endif
#ifdef CHROMIUM_THREADSAFE
#endif
if (g_crvboxhgcm.bufpool) {
//@todo o'rly?
/* pool may have been deallocated just a bit earlier in response
* to a SIGPIPE (Broken Pipe) signal.
*/
}
#ifdef CHROMIUM_THREADSAFE
#endif
break;
case CR_VBOXHGCM_MEMORY_BIG:
crFree( hgcm_buffer );
break;
default:
}
}
{
}
{
#ifndef IN_GUEST
if (conn->allow_redir_ptr)
{
#endif //IN_GUEST
#ifndef IN_GUEST
}
else
{
{
/* put in pre-allocated buffer */
}
else
{
/* allocate new buffer,
* not using pool here as it's most likely one time transfer of huge texture
*/
# ifdef RT_OS_WINDOWS
# endif
}
}
#endif //IN_GUEST
conn->recv_count++;
/* CR_MESSAGE_OPCODES is freed in crserverlib/server_stream.c with crNetFree.
* OOB messages are the programmer's problem. -- Humper 12/17/01
*/
if (cached_type != CR_MESSAGE_OPCODES
&& cached_type != CR_MESSAGE_OOB
&& cached_type != CR_MESSAGE_GATHER)
{
}
}
{
}
/*
* Called on host side only, to "accept" client connection
*/
{
#ifdef IN_GUEST
#endif
}
{
int rc;
{
crWarning("Host doesn't accept our version %d.%d. Make sure you have appropriate additions installed!",
return FALSE;
}
return TRUE;
}
/**
* The function that actually connects. This should only be called by clients,
* guests in vbox case.
* Servers go through crVBoxHGCMAccept;
*/
/*@todo use vbglR3Something here */
{
#ifdef IN_GUEST
#ifdef RT_OS_WINDOWS
{
/* open VBox guest driver */
NULL,
NULL);
/* @todo check if we could rollback to softwareopengl */
{
return FALSE;
}
}
#else
{
{
return FALSE;
}
}
#endif
#ifdef RT_OS_WINDOWS
NULL))
# if HC_ARCH_BITS == 32
Hdr.u32Padding = 0;
# endif
#else
/*@todo it'd fail */
#endif
{
{
}
else
{
return FALSE;
}
}
else
{
#ifdef RT_OS_WINDOWS
#else
#endif
return FALSE;
}
return TRUE;
#else /*#ifdef IN_GUEST*/
crError("crVBoxHGCMDoConnect called on host side!");
return FALSE;
#endif
}
/*@todo same, replace DeviceIoControl with vbglR3DoIOCtl */
{
#ifdef IN_GUEST
# ifdef RT_OS_WINDOWS
# endif
int i;
#endif
if (conn->pHostBuffer)
{
conn->cbHostBuffer = 0;
conn->cbHostBufferAllocated = 0;
}
//@todo hold lock here?
{
{
}
}
#ifndef IN_GUEST
#else /* IN_GUEST */
if (conn->u32ClientID)
{
# ifdef RT_OS_WINDOWS
NULL) )
{
}
# if HC_ARCH_BITS == 32
Hdr.u32Padding = 0;
# endif
# else
{
}
# endif
conn->u32ClientID = 0;
}
/* see if any connections remain */
for (i = 0; i < g_crvboxhgcm.num_conns; i++)
break;
/* close guest additions driver*/
if (i>=g_crvboxhgcm.num_conns)
{
# ifdef RT_OS_WINDOWS
# else
# endif
}
#endif /* IN_GUEST */
}
{
}
{
}
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
bool _crVBoxHGSMIInit()
{
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
static
#endif
int bHasHGSMI = -1;
if (bHasHGSMI < 0)
{
int rc;
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
rc = VBoxCrHgsmiInit();
#else
#endif
if (RT_SUCCESS(rc))
bHasHGSMI = 1;
else
bHasHGSMI = 0;
}
return bHasHGSMI;
}
void _crVBoxHGSMITearDown()
{
}
{
int rc;
if (buf)
{
if (RT_SUCCESS(rc))
{
}
else
{
}
return CRVBOXHGSMI_BUF_DATA(pData);
}
/* fall back */
return _crVBoxHGCMAlloc(conn);
}
{
{
}
else
{
}
}
{
void *pvBuf;
if (pClient)
{
}
else
{
}
return pvBuf;
}
{
}
{
int rc;
// parms->hdr.u32Reserved = 0;
if (!pRecvBuffer)
return;
if (RT_FAILURE(rc))
{
return;
}
if (!parms)
{
crWarning("_crVBoxHGSMICmdBufferLockRo failed\n");
return;
}
else
cbBuffer = 0;
if (cbBuffer)
{
if (pvData)
{
}
}
}
{
}
/* Same as crVBoxHGCMWriteExact, but combined with read of writeback data.
* This halves the number of HGCM calls we do,
* most likely crVBoxHGCMPollHost shouldn't be called at all now.
*/
static void
_crVBoxHGSMIWriteReadExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, void *buf, uint32_t offBuffer, unsigned int len, bool bIsBuffer)
{
CRVBOXHGSMIWRITEREAD *parms = (CRVBOXHGSMIWRITEREAD*)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));
int rc;
// uint32_t cbBuffer;
// parms->hdr.u32Reserved = 0;
parms->cbWriteback = 0;
if (!bIsBuffer)
{
void *pvBuf;
if (!pBuf)
{
/* fallback */
return;
}
offBuffer = 0;
if (RT_SUCCESS(rc))
{
}
else
{
/* fallback */
return;
}
}
else
{
}
do
{
if (!pRecvBuffer)
{
break;
}
if (RT_FAILURE(rc))
{
break;
}
if (parms)
{
#ifdef DEBUG
#endif
if (RT_SUCCESS(rc))
{
if (cbWriteback)
{
if (pvData)
{
}
}
}
else if (VERR_BUFFER_OVERFLOW == rc)
{
if (RT_SUCCESS(rc))
{
}
else
{
}
}
else
{
}
}
else
{
crWarning("_crVBoxHGSMICmdBufferLockRo failed\n");
break;
}
} while (0);
if (!bIsBuffer)
return;
}
static void _crVBoxHGSMIWriteExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, PVBOXUHGSMI_BUFFER pBuf, uint32_t offStart, unsigned int len)
{
int rc;
#ifdef IN_GUEST
if (conn->u32InjectClientID)
{
CRVBOXHGSMIINJECT *parms = (CRVBOXHGSMIINJECT *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));
if (!parms)
{
return;
}
// parms->hdr.u32Reserved = 0;
if (RT_SUCCESS(rc))
{
/* @todo: do we need to wait for completion actually?
* NOTE: in case we do not need completion,
* we MUST specify bDoNotSignalCompletion flag for the command buffer */
// CRVBOXHGSMI_BUF_WAIT(pClient->pCmdBuffer);
}
}
else
#endif
{
CRVBOXHGSMIWRITE * parms = (CRVBOXHGSMIWRITE *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));;
// parms->hdr.u32Reserved = 0;
if (RT_SUCCESS(rc))
{
/* @todo: do we need to wait for completion actually?
* NOTE: in case we do not need completion,
* we MUST specify bDoNotSignalCompletion flag for the command buffer */
// CRVBOXHGSMI_BUF_WAIT(pClient->pCmdBuffer);
}
}
{
}
}
{
if (!bufp) /* We're sending a user-allocated buffer. */
{
if (pClient)
{
#ifndef IN_GUEST
//@todo remove temp buffer allocation in unpacker
/* we're at the host side, so just store data until guest polls us */
#else
#endif
return;
}
/* fallback */
return;
}
{
/* fallback */
return;
}
/* The region [start .. start + len + 1] lies within a buffer that
* was allocated with crVBoxHGCMAlloc() and can be put into the free
* buffer pool when we're done sending it.
*/
if (!pBuf)
{
return;
}
/* Length would be passed as part of HGCM pointer description
* No need to prepend it to the buffer
*/
#ifdef IN_GUEST
if (conn->u32InjectClientID)
{
_crVBoxHGSMIWriteExact(conn, pClient, pBuf, CRVBOXHGSMI_BUF_OFFSET(start, *bufp) + CRVBOXHGSMI_BUF_HDR_SIZE(), len);
}
else
#endif
{
_crVBoxHGSMIWriteReadExact(conn, pClient, pBuf, CRVBOXHGSMI_BUF_OFFSET(start, *bufp) + CRVBOXHGSMI_BUF_HDR_SIZE(), len, true);
}
/* Reclaim this pointer for reuse */
/* Since the buffer's now in the 'free' buffer pool, the caller can't
* use it any more. Setting bufp to NULL will make sure the caller
* doesn't try to re-use the buffer.
*/
}
{
Assert(0);
CRASSERT(0);
// PCRVBOXHGSMI_CLIENT pClient;
// PVBOXUHGSMI_BUFFER pBuf = _crVBoxHGSMIBufFromMemPtr(buf);
// if (!pBuf)
// return;
// pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData;
// _crVBoxHGSMIWriteExact(conn, pClient, pBuf, 0, len);
// _crVBoxHGSMIBufFree(pClient, pBuf);
}
{
// PCRVBOXHGSMI_CLIENT pClient;
// PVBOXUHGSMI_BUFFER pBuf;
// pBuf = _crVBoxHGSMIBufFromMemPtr(buf);
// Assert(pBuf);
Assert(0);
CRASSERT(0);
// if (!pBuf)
// {
// VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
// return;
// }
// pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData;
// _crVBoxHGSMIReadExact(conn, pClient);
}
{
Assert(0);
}
/*
* Called on host side only, to "accept" client connection
*/
{
Assert(0);
#ifdef IN_GUEST
#endif
}
{
return crVBoxHGCMDoConnect(conn);
}
{
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
{
}
#endif
}
{
Assert(0);
}
{
Assert(0);
}
#endif
{
(void) mtu;
if (g_crvboxhgcm.initialized)
{
return;
}
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
#endif
g_crvboxhgcm.num_conns = 0;
/* Can't open VBox guest driver here, because it gets called for host side as well */
/*@todo as we have 2 dll versions, can do it now.*/
#ifdef RT_OS_WINDOWS
#else
#endif
#ifdef CHROMIUM_THREADSAFE
#endif
}
/* Callback function used to free buffer pool entries */
void crVBoxHGCMBufferFree(void *data)
{
#ifdef RT_OS_WINDOWS
#endif
switch (hgcm_buffer->kind)
{
case CR_VBOXHGCM_MEMORY:
crFree( hgcm_buffer );
break;
#ifdef RT_OS_WINDOWS
break;
#endif
case CR_VBOXHGCM_MEMORY_BIG:
crFree( hgcm_buffer );
break;
default:
}
}
void crVBoxHGCMTearDown(void)
{
if (!g_crvboxhgcm.initialized) return;
/* Connection count would be changed in calls to crNetDisconnect, so we have to store original value.
* Walking array backwards is not a good idea as it could cause some issues if we'd disconnect clients not in the
* order of their connection.
*/
for (i=0; i<cCons; i++)
{
/* Note that [0] is intended, as the connections array would be shifted in each call to crNetDisconnect */
}
#ifdef CHROMIUM_THREADSAFE
#endif
if (g_crvboxhgcm.bufpool)
g_crvboxhgcm.initialized = 0;
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
if (g_crvboxhgcm.bHgsmiOn)
{
}
#endif
#ifdef RT_OS_WINDOWS
if (g_crvboxhgcm.pDirectDraw)
{
crDebug("DirectDraw released\n");
}
#endif
}
{
int i, found = 0;
int n_bytes;
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
if (g_crvboxhgcm.bHgsmiOn)
{
}
else
#endif
{
}
conn->krecv_buf_size = 0;
//@todo remove this crap at all later
conn->cbHostBuffer = 0;
/* Find a free slot */
for (i = 0; i < g_crvboxhgcm.num_conns; i++) {
found = 1;
break;
}
}
/* Realloc connection stack if we couldn't find a free slot */
if (found == 0) {
}
}
int crVBoxHGCMRecv(void)
{
int32_t i;
#ifdef IN_GUEST
/* we're on guest side, poll host if it got something for us */
for (i=0; i<g_crvboxhgcm.num_conns; i++)
{
continue;
{
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
{
}
else
#endif
{
}
}
}
#endif
for (i=0; i<g_crvboxhgcm.num_conns; i++)
{
continue;
{
}
}
return 0;
}
{
return g_crvboxhgcm.conns;
}