VBoxGuest.cpp revision a9548d19b3c4982f701f70a2c1df35764c4841b8
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/** @file
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * VBoxGuest -- VirtualBox Win32 guest support driver
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Copyright (C) 2006-2007 innotek GmbH
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
681bb0bf6e9ab5a590d8afcdf37634e2fc29f595vboxsync * available from http://www.virtualbox.org. This file is free software;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * you can redistribute it and/or modify it under the terms of the GNU
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * General Public License as published by the Free Software Foundation,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync// enable backdoor logging
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync//#define LOG_ENABLED
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/*******************************************************************************
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync* Header Files *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync*******************************************************************************/
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include "VBoxGuest_Internal.h"
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#ifdef TARGET_NT4
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include "NTLegacy.h"
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include "VBoxGuestPnP.h"
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#endif
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include "Helper.h"
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include <excpt.h>
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include <VBox/err.h>
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include <iprt/assert.h>
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include <iprt/asm.h>
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include <stdio.h>
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include <VBox/VBoxGuestLib.h>
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#include <VBoxGuestInternal.h>
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/*******************************************************************************
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync* Defined Constants And Macros *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync*******************************************************************************/
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/*******************************************************************************
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync* Internal Functions *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync*******************************************************************************/
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncextern "C"
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic NTSTATUS VBoxGuestAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic void VBoxGuestUnload(PDRIVER_OBJECT pDrvObj);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic NTSTATUS VBoxGuestCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic NTSTATUS VBoxGuestClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic NTSTATUS VBoxGuestDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic NTSTATUS VBoxGuestSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic NTSTATUS VBoxGuestShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic NTSTATUS VBoxGuestNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic VOID vboxWorkerThread(PVOID context);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic VOID reserveHypervisorMemory(PVBOXGUESTDEVEXT pDevExt);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic VOID vboxIdleThread(PVOID context);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/*******************************************************************************
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync* Exported Functions *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync*******************************************************************************/
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync__BEGIN_DECLS
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync__END_DECLS
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#ifdef ALLOC_PRAGMA
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (INIT, DriverEntry)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, createThreads)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, unreserveHypervisorMemory)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, VBoxGuestAddDevice)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, VBoxGuestUnload)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, VBoxGuestCreate)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, VBoxGuestClose)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, VBoxGuestDeviceControl)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, VBoxGuestShutdown)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, VBoxGuestNotSupportedStub)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/* Note: at least the isr handler should be in non-pageable memory! */
681bb0bf6e9ab5a590d8afcdf37634e2fc29f595vboxsync/*#pragma alloc_text (PAGE, VBoxGuestDpcHandler)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync #pragma alloc_text (PAGE, VBoxGuestIsrHandler) */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, vboxWorkerThread)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, reserveHypervisorMemory)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#pragma alloc_text (PAGE, vboxIdleThread)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#endif
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncwinVersion_t winVersion;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Driver entry point.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @returns appropriate status code.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDrvObj Pointer to driver object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pRegPath Registry base path.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NTSTATUS rc = STATUS_SUCCESS;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
681bb0bf6e9ab5a590d8afcdf37634e2fc29f595vboxsync dprintf(("VBoxGuest::DriverEntry. Driver built: %s %s\n", __DATE__, __TIME__));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ULONG majorVersion;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ULONG minorVersion;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ULONG buildNumber;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PsGetVersion(&majorVersion, &minorVersion, &buildNumber, NULL);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::DriverEntry: running on Windows NT version %d.%d, build %d\n", majorVersion, minorVersion, buildNumber));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync switch (majorVersion)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case 6:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync winVersion = WINVISTA;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case 5:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync switch (minorVersion)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case 2:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync winVersion = WIN2K3;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case 1:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync winVersion = WINXP;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case 0:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync winVersion = WIN2K;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync default:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::DriverEntry: unknown version of Windows, refusing!\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return STATUS_DRIVER_UNABLE_TO_LOAD;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case 4:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync winVersion = WINNT4;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync default:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::DriverEntry: NT4 required!\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return STATUS_DRIVER_UNABLE_TO_LOAD;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /*
dcc162af9a2a47325b89f457ed215957415d3d3avboxsync * Setup the driver entry points in pDrvObj.
dcc162af9a2a47325b89f457ed215957415d3d3avboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->DriverUnload = VBoxGuestUnload;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxGuestCreate;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxGuestClose;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxGuestDeviceControl;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VBoxGuestDeviceControl;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_SHUTDOWN] = VBoxGuestShutdown;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_READ] = VBoxGuestNotSupportedStub;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_WRITE] = VBoxGuestNotSupportedStub;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#ifdef TARGET_NT4
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = ntCreateDevice(pDrvObj, NULL, pRegPath);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_PNP] = VBoxGuestPnP;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_POWER] = VBoxGuestPower;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = VBoxGuestSystemControl;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)VBoxGuestAddDevice;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync#endif
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::DriverEntry returning %#x\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return rc;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync#ifndef TARGET_NT4
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync/**
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync * Handle request from the Plug & Play subsystem
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync *
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync * @returns NT status code
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync * @param pDrvObj Driver object
681bb0bf6e9ab5a590d8afcdf37634e2fc29f595vboxsync * @param pDevObj Device object
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync */
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsyncstatic NTSTATUS VBoxGuestAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj)
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync{
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync NTSTATUS rc;
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync dprintf(("VBoxGuest::VBoxGuestAddDevice\n"));
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync /*
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync * Create device.
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync */
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync PDEVICE_OBJECT deviceObject = NULL;
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync UNICODE_STRING devName;
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync RtlInitUnicodeString(&devName, VBOXGUEST_DEVICE_NAME_NT);
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXT), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync if (!NT_SUCCESS(rc))
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestAddDevice: IoCreateDevice failed with rc=%#x!\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return rc;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync UNICODE_STRING win32Name;
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync rc = IoCreateSymbolicLink(&win32Name, &devName);
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync if (!NT_SUCCESS(rc))
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync {
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync dprintf(("VBoxGuest::VBoxGuestAddDevice: IoCreateSymbolicLink failed with rc=%#x!\n", rc));
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync IoDeleteDevice(deviceObject);
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync return rc;
c9ffb32f7bfe2b467ba3ae35d640ac7b97e50a30vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /*
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Setup the device extension.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)deviceObject->DeviceExtension;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync RtlZeroMemory(pDevExt, sizeof(VBOXGUESTDEVEXT));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->deviceObject = deviceObject;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->devState = STOPPED;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->nextLowerDriver = IoAttachDeviceToDeviceStack(deviceObject, pDevObj);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pDevExt->nextLowerDriver == NULL)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestAddDevice: IoAttachDeviceToDeviceStack did not give a nextLowerDrive\n"));
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync IoDeleteSymbolicLink(&win32Name);
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync IoDeleteDevice(deviceObject);
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync return STATUS_DEVICE_NOT_CONNECTED;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync }
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync // driver is ready now
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestAddDevice: returning with rc = 0x%x\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return rc;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#endif
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Unload the driver.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDrvObj Driver object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncvoid VBoxGuestUnload(PDRIVER_OBJECT pDrvObj)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestUnload\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#ifdef TARGET_NT4
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDrvObj->DeviceObject->DeviceExtension;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync unreserveHypervisorMemory(pDevExt);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pDevExt->workerThread)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestUnload: waiting for the worker thread to terminate...\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->stopThread = TRUE;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KeSetEvent(&pDevExt->workerThreadRequest, 0, FALSE);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KeWaitForSingleObject(pDevExt->workerThread,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Executive, KernelMode, FALSE, NULL);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestUnload: returned from KeWaitForSingleObject for worker thread\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pDevExt->idleThread)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestUnload: waiting for the idle thread to terminate...\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->stopThread = TRUE;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KeWaitForSingleObject(pDevExt->idleThread,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Executive, KernelMode, FALSE, NULL);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestUnload: returned from KeWaitForSingleObject for idle thread\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync hlpVBoxUnmapVMMDevMemory (pDevExt);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /*
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * I don't think it's possible to unload a driver which processes have
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * opened, at least we'll blindly assume that here.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync UNICODE_STRING win32Name;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NTSTATUS rc = IoDeleteSymbolicLink(&win32Name);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync IoDeleteDevice(pDrvObj->DeviceObject);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#endif
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestUnload: returning\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Create (i.e. Open) file entry point.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevObj Device object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pIrp Request packet.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncNTSTATUS VBoxGuestCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestCreate\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /*
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * We are not remotely similar to a directory...
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * (But this is possible.)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestCreate: we're not a directory!\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pIrp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pIrp->IoStatus.Information = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return STATUS_NOT_A_DIRECTORY;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NTSTATUS rcNt = pIrp->IoStatus.Status = STATUS_SUCCESS;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pIrp->IoStatus.Information = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestCreate: returning 0x%x\n", rcNt));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return rcNt;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Close file entry point.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevObj Device object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pIrp Request packet.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncNTSTATUS VBoxGuestClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestClose\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestClose: pDevExt=%p pFileObj=%p pSession=%p\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt, pFileObj, pFileObj->FsContext));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pFileObj->FsContext = NULL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pIrp->IoStatus.Information = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pIrp->IoStatus.Status = STATUS_SUCCESS;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return STATUS_SUCCESS;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#ifdef VBOX_HGCM
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncDECLVBGL(void) VBoxHGCMCallback (VMMDevHGCMRequestHeader *pHeader, void *pvData, uint32_t u32Data)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvData;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxHGCMCallback\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // this code is subject to "lost wakeup" bug
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // -- malc
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync while ((pHeader->fu32Flags & VBOX_HGCM_REQ_DONE) == 0)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* Specifying UserMode so killing the user process will abort the wait. */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NTSTATUS rc = KeWaitForSingleObject (&pDevExt->keventNotification, Executive,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync UserMode, TRUE, NULL /** @todo &timeout? */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync );
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxHGCMCallback: Wait returned %d\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (rc != STATUS_WAIT_0)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxHGCMCallback: The external event was signalled or the wait timed out or terminated.\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxHGCMCallback: fu32Flags = %08X\n", pHeader->fu32Flags));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncNTSTATUS vboxHGCMVerifyIOBuffers (PIO_STACK_LOCATION pStack, unsigned cb)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.OutputBufferLength < cb)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxHGCMVerifyIOBuffers: OutputBufferLength %d < %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength, cb));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return STATUS_INVALID_PARAMETER;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.InputBufferLength < cb)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxHGCMVerifyIOBuffers: InputBufferLength %d < %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.InputBufferLength, cb));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return STATUS_INVALID_PARAMETER;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return STATUS_SUCCESS;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#endif /* VBOX_HGCM */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic bool
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync__declspec (naked) __fastcall
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncTestAndClearEvent (PVBOXGUESTDEVEXT pDevExt, int iBitOffset)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync _asm {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync lock btr PVBOXGUESTDEVEXT[ecx].u32Events, edx;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync setc al;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync movzx eax, al;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ret;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic bool IsPowerOfTwo (uint32_t val)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return (val & (val - 1)) == 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic int __declspec (naked) __fastcall GetMsb32 (uint32_t val)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync _asm {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync bsf eax, ecx;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ret;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncstatic bool CtlGuestFilterMask (uint32_t u32OrMask, uint32_t u32NotMask)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync bool result = false;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevCtlGuestFilterMask *req;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync int rc = VbglGRAlloc ((VMMDevRequestHeader **) &req, sizeof (*req),
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevReq_CtlGuestFilterMask);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_SUCCESS (rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->u32OrMask = u32OrMask;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->u32NotMask = u32NotMask;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = VbglGRPerform (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE (rc) || VBOX_FAILURE (req->header.rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf (("VBoxGuest::VBoxGuestDeviceControl: error issuing request to VMMDev! "
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync "rc = %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync result = true;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VbglGRFree (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return result;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Device I/O Control entry point.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevObj Device object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pIrp Request packet.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncNTSTATUS VBoxGuestDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NTSTATUS Status = STATUS_SUCCESS;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync char *pBuf = (char *)pIrp->AssociatedIrp.SystemBuffer; /* all requests are buffered. */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync unsigned cbOut = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync switch (pStack->Parameters.DeviceIoControl.IoControlCode)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case IOCTL_VBOXGUEST_GETVMMDEVPORT:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: IOCTL_VBOXGUEST_GETVMMDEVPORT\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (VBoxGuestPortInfo))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_BUFFER_TOO_SMALL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VBoxGuestPortInfo *portInfo = (VBoxGuestPortInfo*)pBuf;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync portInfo->portAddress = pDevExt->startPortAddress;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync portInfo->pVMMDevMemory = pDevExt->pVMMDevMemory;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync cbOut = sizeof(VBoxGuestPortInfo);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case IOCTL_VBOXGUEST_WAITEVENT:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* Need to be extended to support multiple waiters for an event,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * array of counters for each event, event mask is computed, each
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * time a wait event is arrived.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: IOCTL_VBOXGUEST_WAITEVENT\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(VBoxGuestWaitEventInfo))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: OutputBufferLength %d < sizeof(VBoxGuestWaitEventInfo)\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(VBoxGuestWaitEventInfo)));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_BUFFER_TOO_SMALL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(VBoxGuestWaitEventInfo)) {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: InputBufferLength %d < sizeof(VBoxGuestWaitEventInfo)\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(VBoxGuestWaitEventInfo)));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_BUFFER_TOO_SMALL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VBoxGuestWaitEventInfo *eventInfo = (VBoxGuestWaitEventInfo *)pBuf;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (!eventInfo->u32EventMaskIn || !IsPowerOfTwo (eventInfo->u32EventMaskIn)) {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf (("VBoxGuest::VBoxGuestDeviceControl: Invalid input mask %#x\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync eventInfo->u32EventMaskIn));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_INVALID_PARAMETER;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync eventInfo->u32EventFlagsOut = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync int iBitOffset = GetMsb32 (eventInfo->u32EventMaskIn);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf (("mask = %d, iBitOffset = %d\n", iBitOffset, eventInfo->u32EventMaskIn));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync LARGE_INTEGER timeout;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync timeout.QuadPart = eventInfo->u32TimeoutIn;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync timeout.QuadPart *= -100000;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NTSTATUS rc = STATUS_SUCCESS;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync for (;;)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // following code is subject to "lost wakeup" bug
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // -- malc
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync bool fEventPending = TestAndClearEvent (pDevExt, iBitOffset);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (fEventPending)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync eventInfo->u32EventFlagsOut = 1 << iBitOffset;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = KeWaitForSingleObject (&pDevExt->keventNotification, Executive /** @todo UserRequest? */,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KernelMode, TRUE,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync eventInfo->u32TimeoutIn == ~0L ? NULL : &timeout);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("IOCTL_VBOXGUEST_WAITEVENT: Wait returned %d -> event %x\n", rc, eventInfo->u32EventFlagsOut));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (rc != STATUS_SUCCESS)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* There was a timeout or wait was interrupted, etc. */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf (("u32EventFlagsOut = %#x\n", eventInfo->u32EventFlagsOut));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync cbOut = sizeof(VBoxGuestWaitEventInfo);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case IOCTL_VBOXGUEST_VMMREQUEST:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: IOCTL_VBOXGUEST_VMMREQUEST\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#define CHECK_SIZE(s) \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.OutputBufferLength < s) \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync { \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: OutputBufferLength %d < %d\n", \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength, s)); \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_BUFFER_TOO_SMALL; \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break; \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync } \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.InputBufferLength < s) { \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: InputBufferLength %d < %d\n", \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.InputBufferLength, s)); \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_BUFFER_TOO_SMALL; \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break; \
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* get the request header */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync CHECK_SIZE(sizeof(VMMDevRequestHeader));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevRequestHeader *requestHeader = (VMMDevRequestHeader *)pBuf;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (!vmmdevGetRequestSize(requestHeader->requestType))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_INVALID_PARAMETER;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* make sure the buffers suit the request */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync CHECK_SIZE(vmmdevGetRequestSize(requestHeader->requestType));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* just perform the request */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevRequestHeader *req = NULL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, requestHeader->size, requestHeader->requestType);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_SUCCESS(rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* copy the request information */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync memcpy((void*)req, (void*)pBuf, requestHeader->size);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = VbglGRPerform(req);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE(rc) || VBOX_FAILURE(req->rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl IOCTL_VBOXGUEST_VMMREQUEST: error issuing request to VMMDev!"
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync "rc = %d, VMMDev rc = %Vrc\n", rc, req->rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_UNSUCCESSFUL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* copy result */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync memcpy((void*)pBuf, (void*)req, requestHeader->size);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync cbOut = requestHeader->size;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VbglGRFree(req);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_UNSUCCESSFUL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#undef CHECK_SIZE
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case IOCTL_VBOXGUEST_CTL_FILTER_MASK:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VBoxGuestFilterMaskInfo *maskInfo;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(VBoxGuestFilterMaskInfo)) {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf (("VBoxGuest::VBoxGuestDeviceControl: InputBufferLength %d < %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.InputBufferLength,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync sizeof (VBoxGuestFilterMaskInfo)));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_BUFFER_TOO_SMALL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync maskInfo = (VBoxGuestFilterMaskInfo *) pBuf;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (!CtlGuestFilterMask (maskInfo->u32OrMask, maskInfo->u32NotMask))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_UNSUCCESSFUL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#ifdef VBOX_HGCM
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* HGCM offers blocking IOCTLSs just like waitevent and actually
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * uses the same waiting code.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case IOCTL_VBOXGUEST_HGCM_CONNECT:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: IOCTL_VBOXGUEST_HGCM_CONNECT\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(VBoxGuestHGCMConnectInfo))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: OutputBufferLength %d != sizeof(VBoxGuestHGCMConnectInfo) %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(VBoxGuestHGCMConnectInfo)));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_INVALID_PARAMETER;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(VBoxGuestHGCMConnectInfo)) {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: InputBufferLength %d != sizeof(VBoxGuestHGCMConnectInfo) %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(VBoxGuestHGCMConnectInfo)));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_INVALID_PARAMETER;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VBoxGuestHGCMConnectInfo *ptr = (VBoxGuestHGCMConnectInfo *)pBuf;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* If request will be processed asynchronously, execution will
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * go to VBoxHGCMCallback. There it will wait for the request event, signalled from IRQ.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * On IRQ arrival, the VBoxHGCMCallback(s) will check the request memory and, if completion
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * flag is set, returns.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("a) ptr->u32ClientID = %d\n", ptr->u32ClientID));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync int rc = VbglHGCMConnect (ptr, VBoxHGCMCallback, pDevExt, 0);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("b) ptr->u32ClientID = %d\n", ptr->u32ClientID));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE(rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("IOCTL_VBOXGUEST_HGCM_CONNECT: vbox rc = %Vrc\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_UNSUCCESSFUL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync } break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case IOCTL_VBOXGUEST_HGCM_DISCONNECT:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: IOCTL_VBOXGUEST_HGCM_DISCONNECT\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(VBoxGuestHGCMDisconnectInfo))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: OutputBufferLength %d != sizeof(VBoxGuestHGCMDisconnectInfo) %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(VBoxGuestHGCMDisconnectInfo)));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_INVALID_PARAMETER;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(VBoxGuestHGCMDisconnectInfo)) {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: InputBufferLength %d != sizeof(VBoxGuestHGCMDisconnectInfo) %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(VBoxGuestHGCMDisconnectInfo)));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_INVALID_PARAMETER;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VBoxGuestHGCMDisconnectInfo *ptr = (VBoxGuestHGCMDisconnectInfo *)pBuf;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* If request will be processed asynchronously, execution will
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * go to VBoxHGCMCallback. There it will wait for the request event, signalled from IRQ.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * On IRQ arrival, the VBoxHGCMCallback(s) will check the request memory and, if completion
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync * flag is set, returns.
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync */
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync int rc = VbglHGCMDisconnect (ptr, VBoxHGCMCallback, pDevExt, 0);
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync if (VBOX_FAILURE(rc))
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync {
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync dprintf(("IOCTL_VBOXGUEST_HGCM_DISCONNECT: vbox rc = %Vrc\n", rc));
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync Status = STATUS_UNSUCCESSFUL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync } break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync case IOCTL_VBOXGUEST_HGCM_CALL:
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync {
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: IOCTL_VBOXGUEST_HGCM_CALL\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = vboxHGCMVerifyIOBuffers (pStack,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync sizeof (VBoxGuestHGCMCallInfo));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (Status != STATUS_SUCCESS)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: invalid parameter. Status: %p\n", Status));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VBoxGuestHGCMCallInfo *ptr = (VBoxGuestHGCMCallInfo *)pBuf;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync int rc = VbglHGCMCall (ptr, VBoxHGCMCallback, pDevExt, 0);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE(rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("IOCTL_VBOXGUEST_HGCM_CALL: vbox rc = %Vrc\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync Status = STATUS_UNSUCCESSFUL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync } break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#endif /* VBOX_HGCM */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#ifdef VBOX_WITH_VRDP_SESSION_HANDLING
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case IOCTL_VBOXGUEST_ENABLE_VRDP_SESSION:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (!pDevExt->fVRDPEnabled)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->fVRDPEnabled = TRUE;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->ulOldActiveConsoleId = pSharedUserData->ActiveConsoleId;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pSharedUserData->ActiveConsoleId = 2;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync case IOCTL_VBOXGUEST_DISABLE_VRDP_SESSION:
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pDevExt->fVRDPEnabled)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->fVRDPEnabled = FALSE;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pSharedUserData->ActiveConsoleId = pDevExt->ulOldActiveConsoleId;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->ulOldActiveConsoleId = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync break;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync }
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync#endif
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync default:
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync Status = STATUS_INVALID_PARAMETER;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync break;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync }
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync pIrp->IoStatus.Status = Status;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pIrp->IoStatus.Information = cbOut;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDeviceControl: returned cbOut=%d rc=%#x\n", cbOut, Status));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return Status;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * IRP_MJ_SYSTEM_CONTROL handler
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @returns NT status code
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevObj Device object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pIrp IRP.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncNTSTATUS VBoxGuestSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestSystemControl\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* Always pass it on to the next driver. */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync IoSkipCurrentIrpStackLocation(pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return IoCallDriver(pDevExt->nextLowerDriver, pIrp);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * IRP_MJ_SHUTDOWN handler
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @returns NT status code
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevObj Device object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pIrp IRP.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncNTSTATUS VBoxGuestShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevPowerStateRequest *req = NULL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestShutdown\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_SUCCESS(rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->powerState = VMMDevPowerState_PowerOff;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = VbglGRPerform (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE(rc) || VBOX_FAILURE(req->header.rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::PowerStateRequest: error performing request to VMMDev."
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync "rc = %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VbglGRFree (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync return STATUS_SUCCESS;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync}
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Stub function for functions we don't implemented.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @returns STATUS_NOT_SUPPORTED
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevObj Device object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pIrp IRP.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncNTSTATUS VBoxGuestNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestNotSupportedStub\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevObj = pDevObj;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pIrp->IoStatus.Information = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return STATUS_NOT_SUPPORTED;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * DPC handler
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param dpc DPC descriptor.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevObj Device object.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param irp Interrupt request packet.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param context Context specific pointer.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncVOID VBoxGuestDpcHandler(PKDPC dpc, PDEVICE_OBJECT pDevObj,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PIRP irp, PVOID context)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* Unblock handlers waiting for arrived events.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Events are very low things, there is one event flag (1 or more bit)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * for each event. Each event is processed by exactly one handler.
681bb0bf6e9ab5a590d8afcdf37634e2fc29f595vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Assume that we trust additions and that other drivers will
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * handle its respective events without trying to fetch all events.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Anyway design assures that wrong event processing will affect only guest.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Event handler calls VMMDev IOCTL for waiting an event.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * It supplies event mask. IOCTL blocks on EventNotification.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Here we just signal an the EventNotification to all waiting
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * threads, the IOCTL handler analyzes events and either
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * return to caller or blocks again.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * If we do not have too many events this is a simple and good
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * approach. Other way is to have as many Event objects as the callers
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * and wake up only callers waiting for the specific event.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Now with the 'wake up all' appoach we probably do not need the DPC
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * handler and can signal event directly from ISR.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestDpcHandler\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KePulseEvent(&pDevExt->keventNotification, 0, FALSE);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * ISR handler
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @return BOOLEAN indicates whether the IRQ came from us (TRUE) or not (FALSE)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param interrupt Interrupt that was triggered.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param serviceContext Context specific pointer.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncBOOLEAN VBoxGuestIsrHandler(PKINTERRUPT interrupt, PVOID serviceContext)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NTSTATUS rc;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)serviceContext;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync BOOLEAN fIRQTaken = FALSE;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestIsrHandler haveEvents = %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->pVMMDevMemory->V.V1_04.fHaveEvents));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /*
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * now we have to find out whether it was our IRQ. Read the event mask
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * from our device to see if there are any pending events
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pDevExt->pVMMDevMemory->V.V1_04.fHaveEvents)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* Acknowlegde events. */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevEvents *req = pDevExt->irqAckEvents;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = VbglGRPerform (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(req->header.rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestIsrHandler: acknowledge events succeeded %#x\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->events));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ASMAtomicOrU32((uint32_t *)&pDevExt->u32Events, req->events);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync IoRequestDpc(pDevExt->deviceObject, pDevExt->currentIrp, NULL);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* This can't be actually. This is sign of a serious problem. */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::VBoxGuestIsrHandler: "
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync "acknowledge events failed rc = %d, header rc = %d\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc, req->header.rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* Mark IRQ as taken, there were events for us. */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync fIRQTaken = TRUE;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return fIRQTaken;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Worker thread to do periodic things such as synchronize the
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync * system time and notify other drivers of events.
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync *
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync * @param pDevExt device extension pointer
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync */
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsyncVOID vboxWorkerThread(PVOID context)
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync{
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync PVBOXGUESTDEVEXT pDevExt;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync pDevExt = (PVBOXGUESTDEVEXT)context;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync dprintf(("VBoxGuest::vboxWorkerThread entered\n"));
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync VMMDevReqHostTime *req = NULL;
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevReqHostTime), VMMDevReq_GetHostTime);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE(rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxWorkerThread: could not allocate request buffer, exiting rc = %d!\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* perform the hypervisor address space reservation */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync reserveHypervisorMemory(pDevExt);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync do
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /*
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Do the time sync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync LARGE_INTEGER systemTime;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync #define TICKSPERSEC 10000000
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync #define TICKSPERMSEC 10000
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync #define SECSPERDAY 86400
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync #define SECS_1601_TO_1970 ((369 * 365 + 89) * (uint64_t)SECSPERDAY)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->header.rc = VERR_GENERAL_FAILURE;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = VbglGRPerform (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(req->header.rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync uint64_t hostTime = req->time;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // Windows was originally designed in 1601...
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync systemTime.QuadPart = hostTime * (uint64_t)TICKSPERMSEC + (uint64_t)TICKS_1601_TO_1970;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxWorkerThread: synching time with host time (msec/UTC): %llu\n", hostTime));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ZwSetSystemTime(&systemTime, NULL);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::PowerStateRequest: error performing request to VMMDev."
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync "rc = %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /*
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Go asleep unless we're supposed to terminate
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (!pDevExt->stopThread)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ULONG secWait = 60;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxWorkerThread: waiting for %u seconds...\n", secWait));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync LARGE_INTEGER dueTime;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dueTime.QuadPart = -10000 * 1000 * (int)secWait;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (KeWaitForSingleObject(&pDevExt->workerThreadRequest, Executive,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KernelMode, FALSE, &dueTime) == STATUS_SUCCESS)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KeResetEvent(&pDevExt->workerThreadRequest);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync } while (!pDevExt->stopThread);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxWorkerThread: we've been asked to terminate!\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* free our request buffer */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VbglGRFree (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (pDevExt->workerThread)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ObDereferenceObject(pDevExt->workerThread);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->workerThread = NULL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxWorkerThread: now really gone!\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Create driver worker threads
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @returns NTSTATUS NT status code
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevExt VBoxGuest device extension
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncNTSTATUS createThreads(PVBOXGUESTDEVEXT pDevExt)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NTSTATUS rc;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync HANDLE threadHandle;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync OBJECT_ATTRIBUTES objAttributes;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::createThreads\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // first setup the request semaphore
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KeInitializeEvent(&pDevExt->workerThreadRequest, SynchronizationEvent, FALSE);
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync// the API has slightly changed after NT4
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync#ifdef TARGET_NT4
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync#ifdef OBJ_KERNEL_HANDLE
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync#undef OBJ_KERNEL_HANDLE
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync#endif
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync#define OBJ_KERNEL_HANDLE 0
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync#endif
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync /*
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync * The worker thread
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync */
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync InitializeObjectAttributes(&objAttributes,
9f3a515a29d45728a5c5330459abd3429e35bda1vboxsync NULL,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync OBJ_KERNEL_HANDLE,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NULL,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NULL);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = PsCreateSystemThread(&threadHandle,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync THREAD_ALL_ACCESS,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync &objAttributes,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync (HANDLE)0L,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NULL,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync vboxWorkerThread,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::createThreads: PsCreateSystemThread for worker thread returned: 0x%x\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = ObReferenceObjectByHandle(threadHandle,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync THREAD_ALL_ACCESS,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NULL,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KernelMode,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync (PVOID*)&pDevExt->workerThread,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NULL);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ZwClose(threadHandle);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /*
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * The idle thread
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#if 0 /// @todo Windows "sees" that time is lost and reports 100% usage
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = PsCreateSystemThread(&threadHandle,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync THREAD_ALL_ACCESS,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync &objAttributes,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync (HANDLE)0L,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NULL,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync vboxIdleThread,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::createThreads: PsCreateSystemThread for idle thread returned: 0x%x\n", rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = ObReferenceObjectByHandle(threadHandle,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync THREAD_ALL_ACCESS,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NULL,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KernelMode,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync (PVOID*)&pDevExt->idleThread,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync NULL);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ZwClose(threadHandle);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync#endif
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return rc;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Helper routine to reserve address space for the hypervisor
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * and communicate its position.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevExt Device extension structure.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncVOID reserveHypervisorMemory(PVBOXGUESTDEVEXT pDevExt)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // @todo rc handling
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync uint32_t hypervisorSize;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevReqHypervisorInfo *req = NULL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
681bb0bf6e9ab5a590d8afcdf37634e2fc29f595vboxsync int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevReqHypervisorInfo), VMMDevReq_GetHypervisorInfo);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_SUCCESS(rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->hypervisorStart = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->hypervisorSize = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = VbglGRPerform (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(req->header.rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync hypervisorSize = req->hypervisorSize;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (!hypervisorSize)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::reserveHypervisorMemory: host returned 0, not doing anything\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::reserveHypervisorMemory: host wants %u bytes of hypervisor address space\n", hypervisorSize));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // Map fictive physical memory into the kernel address space to reserve virtual
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // address space. This API does not perform any checks but just allocate the
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // PTEs (which we don't really need/want but there isn't any other clean method).
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // The hypervisor only likes 4MB aligned virtual addresses, so we have to allocate
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // 4MB more than we are actually supposed to in order to guarantee that. Maybe we
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // can come up with a less lavish algorithm lateron.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PHYSICAL_ADDRESS physAddr;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync physAddr.QuadPart = HYPERVISOR_PHYSICAL_START;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->hypervisorMappingSize = hypervisorSize + 0x400000;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->hypervisorMapping = MmMapIoSpace(physAddr,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt->hypervisorMappingSize,
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync MmNonCached);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (!pDevExt->hypervisorMapping)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::reserveHypervisorMemory: MmMapIoSpace returned NULL!\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::reserveHypervisorMemory: MmMapIoSpace returned %p\n", pDevExt->hypervisorMapping));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::reserveHypervisorMemory: communicating %p to host\n",
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync ALIGNP(pDevExt->hypervisorMapping, 0x400000)));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* align at 4MB */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->hypervisorStart = (RTGCPTR)ALIGNP(pDevExt->hypervisorMapping, 0x400000);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->header.requestType = VMMDevReq_SetHypervisorInfo;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->header.rc = VERR_GENERAL_FAILURE;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* issue request */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = VbglGRPerform (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE(rc) || VBOX_FAILURE(req->header.rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::reserveHypervisorMemory: error communicating physical address to VMMDev!"
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync "rc = %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync else
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::reserveHypervisorMemory: request failed with rc %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VbglGRFree (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Helper function to unregister a virtual address space mapping
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevExt Device extension
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncVOID unreserveHypervisorMemory(PVBOXGUESTDEVEXT pDevExt)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevReqHypervisorInfo *req = NULL;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevReqHypervisorInfo), VMMDevReq_SetHypervisorInfo);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_SUCCESS(rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* tell the hypervisor that the mapping is no longer available */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->hypervisorStart = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync req->hypervisorSize = 0;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync rc = VbglGRPerform (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE(rc) || VBOX_FAILURE(req->header.rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::unreserveHypervisorMemory: error communicating physical address to VMMDev!"
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync "rc = %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VbglGRFree (&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (!pDevExt->hypervisorMapping)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::unreserveHypervisorMemory: there is no mapping, returning\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync // unmap fictive IO space
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync MmUnmapIoSpace(pDevExt->hypervisorMapping, pDevExt->hypervisorMappingSize);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::unreserveHypervisorMemmory: done\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync/**
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * Idle thread that runs at the lowest priority possible
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * and whenever scheduled, makes a VMMDev call to give up
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * timeslices. This is so prevent Windows from thinking that
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * nothing is happening on the machine and doing stupid things
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * that would steal time from other VMs it doesn't know of.
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync *
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync * @param pDevExt device extension pointer
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsyncVOID vboxIdleThread(PVOID context)
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync{
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync PVBOXGUESTDEVEXT pDevExt;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync pDevExt = (PVBOXGUESTDEVEXT)context;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxIdleThread entered\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* set priority as low as possible */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync KeSetPriorityThread(KeGetCurrentThread(), LOW_PRIORITY);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* allocate VMMDev request structure */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VMMDevReqIdle *req;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync int rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof (VMMDevReqHypervisorInfo), VMMDevReq_Idle);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync if (VBOX_FAILURE(rc))
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxIdleThread: error %Vrc allocating request structure!\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync return;
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync }
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync do
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync {
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync //dprintf(("VBoxGuest: performing idle request..\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync /* perform idle request */
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VbglGRPerform(&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync } while (!pDevExt->stopThread);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync VbglGRFree(&req->header);
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync dprintf(("VBoxGuest::vboxIdleThread leaving\n"));
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync}
c0d22c23d3289cef0332f4d61ab15df48ed34979vboxsync