VBoxMFInternal.cpp revision 59c511231e9864cb4ab5105e23e3e3617af92d34
/* $Id$ */
/** @file
* VBox Mouse filter internal functions
*/
/*
* Copyright (C) 2011 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.
*/
#include "VBoxMF.h"
#include <VBox/VBoxGuestLib.h>
#include <VBox/VBoxGuest.h>
typedef struct VBOXGDC
{
typedef struct _VBoxGlobalContext
{
volatile LONG cDevicesStarted;
volatile LONG fVBGLInited;
volatile LONG fVBGLInitFailed;
volatile LONG fHostInformed;
volatile LONG fHostMouseFound;
volatile PVBOXMOUSE_DEVEXT pCurrentDevExt;
volatile bool fIsNewProtEnabled;
static VBoxGlobalContext g_ctx = {};
/* Guest Device Communication API */
{
NTSTATUS Status = IoGetDeviceObjectPointer(&UniName, FILE_ALL_ACCESS, &g_ctx.Gdc.pFo, &g_ctx.Gdc.pDo);
if (!NT_SUCCESS(Status))
{
}
return Status;
}
{
}
{
return STATUS_SUCCESS;
/* this will dereference device object as well */
return STATUS_SUCCESS;
}
static NTSTATUS vboxGdcSubmitAsync(ULONG uCtl, PVOID pvBuffer, SIZE_T cbBuffer, PKEVENT pEvent, PIO_STATUS_BLOCK pIoStatus)
{
pIrp = IoBuildDeviceIoControlRequest(uCtl, g_ctx.Gdc.pDo, NULL, 0, NULL, 0, TRUE, pEvent, pIoStatus);
if (!pIrp)
{
WARN(("IoBuildDeviceIoControlRequest failed!!\n"));
pIoStatus->Information = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
return Status;
}
{
IO_STATUS_BLOCK IoStatus = {0};
if (Status == STATUS_PENDING)
{
}
return Status;
}
/* overwrites the previously set one, can be NULL to clear the event */
{
if (!VBoxGdcIsInitialized())
{
WARN(("Guest Device Communication not initialized"));
return STATUS_UNSUCCESSFUL;
}
NTSTATUS Status = vboxGdcSubmit(VBOXGUEST_IOCTL_INTERNAL_SET_MOUSE_NOTIFY_EVENT, pEvent, sizeof (pEvent));
if (!NT_SUCCESS(Status))
{
}
return Status;
}
/**
* helper function used for system thread creation
*/
static NTSTATUS vboxCreateSystemThread(PKTHREAD *ppThread, PKSTART_ROUTINE pfnStartRoutine, PVOID pvStartContext)
{
NTSTATUS Status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, (PKSTART_ROUTINE)pfnStartRoutine, pvStartContext);
if (Status == STATUS_SUCCESS)
{
Status = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)ppThread, NULL);
if (Status == STATUS_SUCCESS)
{
return STATUS_SUCCESS;
}
/* @todo: how would we fail in this case ?*/
}
return Status;
}
{
while (1)
{
NULL /* PLARGE_INTEGER Timeout */,
NULL /* PKWAIT_BLOCK WaitBlockArray */
);
if (Status != STATUS_WAIT_0)
{
/* terminate event */
break;
}
ULONG InputDataConsumed = 0;
PVBOXMOUSE_DEVEXT pDevExt = (PVBOXMOUSE_DEVEXT)ASMAtomicUoReadPtr((void * volatile *)&g_ctx.pCurrentDevExt);
if (pDevExt)
{
#define VBOXMOUSE_POLLERTAG 'PMBV'
if (NT_SUCCESS(Status))
{
VBoxDrvNotifyServiceCB(pDevExt, &g_ctx.LastReportedData, &g_ctx.LastReportedData + 1, &InputDataConsumed);
}
else
{
}
}
else
{
WARN(("no current pDevExt specified"));
}
}
}
static BOOLEAN vboxNewProtIsInitialized()
{
}
static BOOLEAN vboxNewProtIsStarted()
{
}
{
if (NT_SUCCESS(Status))
{
/* we assume the new prot data in g_ctx is zero-initialized (see g_ctx definition) */
if (NT_SUCCESS(Status))
{
return STATUS_SUCCESS;
}
}
return Status;
}
{
if (!vboxNewProtIsInitialized())
return STATUS_SUCCESS;
if (!NT_SUCCESS(Status))
{
return Status;
}
return Status;
}
{
if (!vboxNewProtIsInitialized())
return STATUS_UNSUCCESSFUL;
if (!g_ctx.pCurrentDevExt)
{
/* ensure the object is not deleted while it is being used by a poller thread */
}
if (fDoEventRegister)
{
/* to ensure we do not concur with vboxNewProtDeviceRemoved cleaning the event,
* do it in a loop until the cauuent state of fIsNewProtEnabled is false,
* setting one and the same event multiple times will not hutr */
do
{
if (!NT_SUCCESS(Status))
{
break;
}
if (NT_SUCCESS(Status))
{
/* signal the event to ensure we did not miss anything */
}
}
#ifdef DEBUG_misha
else
{
}
#endif
return Status;
}
#define PVBOXMOUSE_DEVEXT_FROM_LE(_pLe) ( (PVBOXMOUSE_DEVEXT)(((uint8_t*)(_pLe)) - RT_OFFSETOF(VBOXMOUSE_DEVEXT, ListEntry)) )
{
if (!vboxNewProtIsInitialized())
return STATUS_UNSUCCESSFUL;
{
{
/* ensure the object is not deleted while it is being used by a poller thread */
break;
}
}
if (fDoEventUnregister)
{
if (vboxNewProtIsStarted())
{
if (!NT_SUCCESS(Status))
{
}
}
}
return Status;
}
VOID VBoxDrvNotifyServiceCB(PVBOXMOUSE_DEVEXT pDevExt, PMOUSE_INPUT_DATA InputDataStart, PMOUSE_INPUT_DATA InputDataEnd, PULONG InputDataConsumed)
{
/* 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 */
{
if (RT_SUCCESS(rc))
{
{
while (pData<InputDataEnd)
{
if (vboxNewProtIsStarted())
pData++;
}
/* get the last data & cache it */
--pData;
}
}
else
{
}
}
/* Call original callback */
}
static BOOLEAN vboxIsVBGLInited(void)
{
}
static BOOLEAN vboxIsVBGLInitFailed (void)
{
}
static BOOLEAN vboxIsHostInformed(void)
{
}
static BOOLEAN vboxIsHostMouseFound(void)
{
}
{
LOGF_ENTER();
/* One time Vbgl initialization */
if (callCnt == 1)
{
if (!vboxIsVBGLInited() && !vboxIsVBGLInitFailed())
{
if (RT_SUCCESS(rc))
{
LOG(("VBGL init OK"));
}
else
{
}
}
}
if (!vboxIsHostMouseFound())
{
if (!NT_SUCCESS(rc))
{
return;
}
/* Check if device claims IO port 0x60 or int12 */
{
LOG(("FullDescriptor[%i]: IfType %d, Bus %d, Ver %d, Rev %d, Count %d",
{
CM_PARTIAL_RESOURCE_DESCRIPTOR *pPartialDescriptor = &pFullDescriptor->PartialResourceList.PartialDescriptors[j];
LOG(("PartialDescriptor[%d]: type %d, ShareDisposition %d, Flags 0x%04X, Start 0x%llx, length 0x%x",
switch(pPartialDescriptor->Type)
{
case CmResourceTypePort:
{
{
}
break;
}
case CmResourceTypeInterrupt:
{
{
}
break;
}
default:
{
break;
}
}
}
}
if (bDetected)
{
* For this device the filter will query absolute mouse coords from the host.
*/
LOG(("Host mouse found"));
}
}
LOGF_LEAVE();
}
{
LOGF_ENTER();
if (!vboxIsVBGLInited())
{
WARN(("!vboxIsVBGLInited"));
return;
}
/* Inform host we support absolute coordinates */
{
int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus);
if (RT_SUCCESS(rc))
{
if (vboxNewProtIsStarted())
req->pointerXPos = 0;
req->pointerYPos = 0;
if (RT_SUCCESS(rc))
{
}
else
{
}
}
else
{
}
}
/* Preallocate request to be used in VBoxServiceCB*/
{
int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevReqMouseStatus), VMMDevReq_GetMouseStatus);
if (RT_SUCCESS(rc))
{
}
else
{
}
}
LOGF_LEAVE();
}
{
LOGF_ENTER();
/* Save the allocated request pointer and clear the devExt. */
VMMDevReqMouseStatus *pSCReq = (VMMDevReqMouseStatus *) InterlockedExchangePointer((PVOID volatile *)&pDevExt->pSCReq, NULL);
{
// tell the VMM that from now on we can't handle absolute coordinates anymore
int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus);
if (RT_SUCCESS(rc))
{
req->mouseFeatures = 0;
req->pointerXPos = 0;
req->pointerYPos = 0;
if (RT_FAILURE(rc))
{
}
}
else
{
}
}
if (pSCReq)
{
}
if (callCnt == 0)
{
if (vboxIsVBGLInited())
{
/* Set the flag to prevent reinitializing of the VBGL. */
/* The VBGL is now in the not initialized state. */
}
}
LOGF_LEAVE();
}