VBoxGuest-win.cpp revision eb4f1fa4c357485330370c0eaba27e5a2af7d9c4
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/** @file
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VBoxGuest - Windows specifics.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Copyright (C) 2010 Oracle Corporation
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * available from http://www.virtualbox.org. This file is free software;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * General Public License (GPL) as published by the Free Software
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Header Files *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#define LOG_GROUP LOG_GROUP_SUP_DRV
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#include "VBoxGuest-win.h"
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#include "VBoxGuestInternal.h"
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#include <iprt/asm.h>
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#include <VBox/log.h>
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#include <VBox/VBoxGuestLib.h>
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#include <VBoxGuestInternal.h>
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef TARGET_NT4
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * XP DDK #defines ExFreePool to ExFreePoolWithTag. The latter does not exist
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * on NT4, so... The same for ExAllocatePool.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#undef ExAllocatePool
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#undef ExFreePool
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Defined Constants And Macros *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Entry Points *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncRT_C_DECLS_BEGIN
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic NTSTATUS vboxguestwinAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic void vboxguestwinUnload(PDRIVER_OBJECT pDrvObj);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic NTSTATUS vboxguestwinClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic NTSTATUS vboxguestwinSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic NTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic NTSTATUS vboxguestwinNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncRT_C_DECLS_END
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Internal Functions *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncRT_C_DECLS_BEGIN
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef DEBUG
b2640405e06105d868b5fc8f7b676bb680884380vboxsync static VOID vboxguestwinDoTests(VOID);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncRT_C_DECLS_END
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Exported Functions *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncRT_C_DECLS_BEGIN
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncRT_C_DECLS_END
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef ALLOC_PRAGMA
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (INIT, DriverEntry)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (PAGE, vboxguestwinAddDevice)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (PAGE, vboxguestwinUnload)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (PAGE, vboxguestwinCreate)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (PAGE, vboxguestwinClose)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (PAGE, vboxguestwinIOCtl)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (PAGE, vboxguestwinShutdown)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (PAGE, vboxguestwinNotSupportedStub)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#pragma alloc_text (PAGE, vboxguestwinScanPCIResourceList)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/** The detected Windows version. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncwinVersion_t g_winVersion;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Driver entry point.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns appropriate status code.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDrvObj Pointer to driver object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pRegPath Registry base path.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS rc = STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry. Driver built: %s %s\n", __DATE__, __TIME__));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync ULONG majorVersion;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync ULONG minorVersion;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync ULONG buildNumber;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync BOOLEAN bCheckedBuild = PsGetVersion(&majorVersion, &minorVersion, &buildNumber, NULL);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry: Running on Windows NT version %d.%d, build %d\n", majorVersion, minorVersion, buildNumber));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (bCheckedBuild)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry: Running on a Windows checked build (debug)!\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef DEBUG
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinDoTests();
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync switch (majorVersion)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 6: /* Windows Vista or Windows 7 (based on minor ver) */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync switch (minorVersion)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 0: /* Note: Also could be Windows 2008 Server! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync g_winVersion = WINVISTA;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 1: /* Note: Also could be Windows 2008 Server R2! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync g_winVersion = WIN7;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync majorVersion, minorVersion));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = STATUS_DRIVER_UNABLE_TO_LOAD;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 5:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync switch (minorVersion)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 2:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync g_winVersion = WIN2K3;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 1:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync g_winVersion = WINXP;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 0:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync g_winVersion = WIN2K;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync majorVersion, minorVersion));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = STATUS_DRIVER_UNABLE_TO_LOAD;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 4:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync g_winVersion = WINNT4;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry: At least Windows NT4 required!\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = STATUS_DRIVER_UNABLE_TO_LOAD;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (NT_SUCCESS(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Setup the driver entry points in pDrvObj.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->DriverUnload = vboxguestwinUnload;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_CREATE] = vboxguestwinCreate;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_CLOSE] = vboxguestwinClose;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vboxguestwinIOCtl;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vboxguestwinIOCtl;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_SHUTDOWN] = vboxguestwinShutdown;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_READ] = vboxguestwinNotSupportedStub;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_WRITE] = vboxguestwinNotSupportedStub;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef TARGET_NT4
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = vboxguestwinnt4CreateDevice(pDrvObj, NULL /* pDevObj */, pRegPath);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_PNP] = vboxguestwinPnP;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_POWER] = vboxguestwinPower;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vboxguestwinSystemControl;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)vboxguestwinAddDevice;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::DriverEntry returning %#x\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifndef TARGET_NT4
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Handle request from the Plug & Play subsystem.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns NT status code
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDrvObj Driver object
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic NTSTATUS vboxguestwinAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestAddDevice\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create device.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PDEVICE_OBJECT pDeviceObject = NULL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTDEVEXT pDevExt = NULL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync UNICODE_STRING devName;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync UNICODE_STRING win32Name;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync RtlInitUnicodeString(&devName, VBOXGUEST_DEVICE_NAME_NT);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXT), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (NT_SUCCESS(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create symbolic link (DOS devices).
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = IoCreateSymbolicLink(&win32Name, &devName);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (NT_SUCCESS(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Setup the device extension.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt = (PVBOXGUESTDEVEXT)pDeviceObject->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync RtlZeroMemory(pDevExt, sizeof(VBOXGUESTDEVEXT));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.pDeviceObject = pDeviceObject;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.devState = STOPPED;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pDevExt->win.s.pNextLowerDriver == NULL)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = STATUS_DEVICE_NOT_CONNECTED;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoCreateSymbolicLink failed with rc=%#x!\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoCreateDevice failed with rc=%#x!\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (NT_SUCCESS(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * If we reached this point we're fine with the basic driver setup,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * so continue to init our own things.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinBugCheckCallback(pDevExt); /* Ignore failure! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* VBoxGuestPower is pageable; ensure we are not called at elevated IRQL */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDeviceObject->Flags |= DO_POWER_PAGABLE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Driver is ready now. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Cleanup on error. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (NT_ERROR(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pDevExt->win.s.pNextLowerDriver)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoDetachDevice(pDevExt->win.s.pNextLowerDriver);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoDeleteSymbolicLink(&win32Name);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pDeviceObject)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoDeleteDevice(pDeviceObject);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestAddDevice: returning with rc = 0x%x\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync/**
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Debug helper to dump a device resource list.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync *
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pResourceList list of device resources.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncstatic VOID vboxguestwinShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync{
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef LOG_ENABLED
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = pResourceList->PartialDescriptors;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync ULONG nres = pResourceList->Count;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync ULONG i;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync for (i = 0; i < nres; ++i, ++resource)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync ULONG uType = resource->Type;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync static char* aszName[] =
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeNull",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypePort",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeInterrupt",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeMemory",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDma",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDeviceSpecific",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeBusNumber",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDevicePrivate",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeAssignedResource",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeSubAllocateFrom",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync };
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinShowDeviceResources: Type %s",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync uType < (sizeof(aszName) / sizeof(aszName[0]))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync ? aszName[uType] : "Unknown"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync switch (uType)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync case CmResourceTypePort:
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync case CmResourceTypeMemory:
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinShowDeviceResources: Start %8X%8.8lX length %X\n",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync resource->u.Port.Start.HighPart, resource->u.Port.Start.LowPart,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync resource->u.Port.Length));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync break;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync case CmResourceTypeInterrupt:
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinShowDeviceResources: Level %X, Vector %X, Affinity %X\n",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync resource->u.Interrupt.Level, resource->u.Interrupt.Vector,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync resource->u.Interrupt.Affinity));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync break;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync case CmResourceTypeDma:
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinShowDeviceResources: Channel %d, Port %X\n",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync resource->u.Dma.Channel, resource->u.Dma.Port));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync break;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync default:
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync break;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync}
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync/**
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Global initialisation stuff (PnP + NT4 legacy).
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync *
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pDevObj Device object.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @param pIrp Request packet.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifndef TARGET_NT4
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNTSTATUS vboxguestwinInit(PDEVICE_OBJECT pDevObj, PIRP pIrp)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#else
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync{
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifndef TARGET_NT4
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync int rc = STATUS_SUCCESS;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef TARGET_NT4
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /*
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Let's have a look at what our PCI adapter offers.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Starting to scan PCI resources of VBoxGuest ...\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Assign the PCI resources. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PCM_RESOURCE_LIST pResourceList = NULL;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync UNICODE_STRING classNameString;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync RtlInitUnicodeString(&classNameString, L"VBoxGuestAdapter");
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = HalAssignSlotResources(pRegPath, &classNameString,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDrvObj, pDevObj,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync PCIBus, pDevExt->win.s.busNumber, pDevExt->win.s.slotNumber,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync &pResourceList);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (pResourceList && pResourceList->Count > 0)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync vboxguestwinShowDeviceResources(&pResourceList->List[0].PartialResourceList);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = vboxguestwinScanPCIResourceList(pResourceList, pDevExt);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#else
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (pStack->Parameters.StartDevice.AllocatedResources->Count > 0)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync vboxguestwinShowDeviceResources(&pStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = vboxguestwinScanPCIResourceList(pStack->Parameters.StartDevice.AllocatedResourcesTranslated,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /*
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Map physical address of VMMDev memory into MMIO region
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * and init the common device extension bits.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync void *pvMMIOBase = NULL;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync uint32_t cbMMIO = 0;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = vboxguestwinMapVMMDevMemory(pDevExt,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.vmmDevPhysMemoryAddress,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.vmmDevPhysMemoryLength,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync &pvMMIOBase,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync &cbMMIO);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->pVMMDevMemory = (VMMDevMemory *)pvMMIOBase;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: pvMMIOBase = 0x%p, pDevExt = 0x%p, pDevExt->pVMMDevMemory = 0x%p\n",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pvMMIOBase, pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync int vrc = VBoxGuestInitDevExt(pDevExt,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->IOPortBase,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pvMMIOBase, cbMMIO,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync vboxguestwinVersionToOSType(g_winVersion),
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (RT_FAILURE(vrc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Could not init device extension, rc = %Rrc!\n", vrc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = STATUS_DEVICE_CONFIGURATION_ERROR;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync else
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Could not map physical address of VMMDev, rc = 0x%x!\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pDevExt->win.s.pPowerStateRequest,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync sizeof (VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (RT_FAILURE(vrc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Alloc for pPowerStateRequest failed, rc = %Rrc\n", vrc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = STATUS_UNSUCCESSFUL;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /*
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Register DPC and ISR.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Initializing DPC/ISR ...\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync IoInitializeDpcRequest(pDevExt->win.s.pDeviceObject, vboxguestwinDpcHandler);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef TARGET_NT4
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Get an interrupt vector. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Only proceed if the device provides an interrupt. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if ( pDevExt->win.s.interruptLevel
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync || pDevExt->win.s.interruptVector)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.interruptVector = HalGetInterruptVector(PCIBus,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.busNumber,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.interruptLevel,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.interruptVector,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync (PKIRQL)pDevExt->win.s.interruptLevel,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync &pDevExt->win.s.interruptAffinity);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync else
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Device does not provide an interrupt!\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (pDevExt->win.s.interruptVector)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = IoConnectInterrupt(&pDevExt->win.s.pInterruptObject, /* Out: interrupt object. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync (PKSERVICE_ROUTINE)vboxguestwinIsrHandler, /* Our ISR handler. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt, /* Device context. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync NULL, /* Optional spinlock. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.interruptVector, /* Interrupt vector. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync (KIRQL)pDevExt->win.s.interruptLevel, /* Interrupt level. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync (KIRQL)pDevExt->win.s.interruptLevel, /* Interrupt level. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.interruptMode, /* LevelSensitive or Latched. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync TRUE, /* Shareable interrupt. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.interruptAffinity, /* CPU affinity. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync FALSE); /* Don't save FPU stack. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_ERROR(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Could not connect interrupt, rc = 0x%x\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync else
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: No interrupt vector found!\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef VBOX_WITH_HGCM
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Initialize the HGCM event notification semaphore. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync KeInitializeEvent(&pDevExt->win.s.hgcm.s.keventNotification, NotificationEvent, FALSE);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Preallocated constant timeout 250ms for HGCM async waiter. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.hgcm.s.WaitTimeout.QuadPart = 250;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.hgcm.s.WaitTimeout.QuadPart *= -10000; /* Relative in 100ns units. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync int vrc = VBoxGuestCreateKernelSession(pDevExt, &pDevExt->win.s.pKernelSession);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (RT_FAILURE(vrc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Failed to allocated kernel session data! rc = %Rrc\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = STATUS_UNSUCCESSFUL;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (RT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Ready to rumble! */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Device is ready!\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync pDevExt->win.s.devState = WORKING;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync Log(("VBoxGuest::vboxguestwinInit: Returned with rc = 0x%x\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync return rc;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync}
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync/**
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * Cleans up all data (like device extension and guest mapping).
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync *
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * @param pDrvObj Driver object.
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsyncNTSTATUS vboxguestwinCleanup(PDEVICE_OBJECT pDevObj)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync{
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync Log(("VBoxGuest::vboxguestwinCleanup\n"));
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync if (pDevExt)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync hlpDeregisterBugCheckCallback(pDevExt); /* ignore failure! */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync /* According to MSDN we have to unmap previously mapped memory. */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync vboxguestwinUnmapVMMDevMemory(pDevExt);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync /* Destroy device extension and clean up everything else. */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync VBoxGuestDeleteDevExt(pDevExt);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync }
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync return STATUS_SUCCESS;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync}
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Unload the driver.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDrvObj Driver object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncvoid vboxguestwinUnload(PDRIVER_OBJECT pDrvObj)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestUnload\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef TARGET_NT4
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync vboxguestwinCleanup(pDrvObj->DeviceObject);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * I don't think it's possible to unload a driver which processes have
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * opened, at least we'll blindly assume that here.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync UNICODE_STRING win32Name;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS rc = IoDeleteSymbolicLink(&win32Name);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoDeleteDevice(pDrvObj->DeviceObject);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync#else /* TARGET_NT4 */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync /* On a PnP driver this routine will be called after
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * IRP_MN_REMOVE_DEVICE (where we already did the cleanup),
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * so don't do anything here (yet). */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestUnload: returning\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create (i.e. Open) file entry point.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp Request packet.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestCreate\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo AssertPtrReturn(pIrp); */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo AssertPtrReturn(pStack); */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS rc = STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * We are not remotely similar to a directory...
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * (But this is possible.)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestCreate: Uhm, we're not a directory!\n"));
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync rc = STATUS_NOT_A_DIRECTORY;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef VBOX_WITH_HGCM
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pFileObj)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync int vrc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTSESSION pSession;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pFileObj->Type == 5 /* File Object */)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create a session object if we have a valid file object. This session object
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * exists for every R3 process.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vrc = VBoxGuestCreateUserSession(pDevExt, &pSession);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* ... otherwise we've been called from R0! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vrc = VBoxGuestCreateKernelSession(pDevExt, &pSession);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (RT_SUCCESS(vrc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pFileObj->FsContext = pSession;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Complete the request! */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync pIrp->IoStatus.Information = 0;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync pIrp->IoStatus.Status = rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync Log(("VBoxGuest::vboxguestwinGuestCreate: Returning 0x%x\n", rc));
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync return rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Close file entry point.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp Request packet.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNTSTATUS vboxguestwinClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestClose: pDevExt=0x%p pFileObj=0x%p FsContext=0x%p\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt, pFileObj, pFileObj->FsContext));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef VBOX_WITH_HGCM
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Close both, R0 and R3 sessions. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pFileObj->FsContext;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pSession)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync VBoxGuestCloseSession(pDevExt, pSession);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pFileObj->FsContext = NULL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pIrp->IoStatus.Information = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pIrp->IoStatus.Status = STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Device I/O Control entry point.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp Request packet.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS Status = STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync unsigned int uCmd = (unsigned int)pStack->Parameters.DeviceIoControl.IoControlCode;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync char *pBuf = (char *)pIrp->AssociatedIrp.SystemBuffer; /* All requests are buffered. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync size_t cbData = pStack->Parameters.DeviceIoControl.InputBufferLength;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync unsigned cbOut = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Do we have a file object associated?*/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTSESSION pSession = NULL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pFileObj) /* ... then we might have a session object as well! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pSession = (PVBOXGUESTSESSION)pFileObj->FsContext;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinIOCtl: uCmd=%u, pDevExt=0x%p, pSession=0x%p\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uCmd, pDevExt, pSession));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* We don't have a session associated with the file object? So this seems
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * to be a kernel call then. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pSession == NULL)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinIOCtl: Using kernel session data ...\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pSession = pDevExt->win.s.pKernelSession;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * First process Windows specific stuff which cannot be handled
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * by the common code used on all other platforms. In the default case
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * we then finally handle the common cases.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync switch (uCmd)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef VBOX_WITH_VRDP_SESSION_HANDLING
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case VBOXGUEST_IOCTL_ENABLE_VRDP_SESSION:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync LogRel(("VBoxGuest::vboxguestwinIOCtl: ENABLE_VRDP_SESSION: Currently: %sabled\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->fVRDPEnabled? "en": "dis"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (!pDevExt->fVRDPEnabled)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->fVRDPEnabled = TRUE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync LogRel(("VBoxGuest::vboxguestwinIOCtl: ENABLE_VRDP_SESSION: Current active console ID: 0x%08X\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pSharedUserData->ActiveConsoleId));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->ulOldActiveConsoleId = pSharedUserData->ActiveConsoleId;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pSharedUserData->ActiveConsoleId = 2;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case VBOXGUEST_IOCTL_DISABLE_VRDP_SESSION:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync LogRel(("VBoxGuest::vboxguestwinIOCtl: DISABLE_VRDP_SESSION: Currently: %sabled\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->fVRDPEnabled? "en": "dis"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pDevExt->fVRDPEnabled)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->fVRDPEnabled = FALSE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinIOCtl: DISABLE_VRDP_SESSION: Current active console ID: 0x%08X\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pSharedUserData->ActiveConsoleId));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pSharedUserData->ActiveConsoleId = pDevExt->ulOldActiveConsoleId;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->ulOldActiveConsoleId = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Add at least one (bogus) fall through case to shut up MSVC! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 0:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Process the common IOCtls.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync size_t cbDataReturned;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync int vrc = VBoxGuestCommonIOCtl(uCmd, pDevExt, pSession, (void*)pBuf, cbData, &cbDataReturned);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestDeviceControl: rc=%Rrc, pBuf=0x%p, cbData=%u, cbDataReturned=%u\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vrc, pBuf, cbData, cbDataReturned));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (RT_SUCCESS(vrc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (RT_UNLIKELY(cbDataReturned > cbData))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestDeviceControl: Too much output data %u - expected %u!\n", cbDataReturned, cbData));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync cbDataReturned = cbData;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Status = STATUS_BUFFER_TOO_SMALL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (cbDataReturned > 0)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync cbOut = cbDataReturned;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if ( vrc == VERR_NOT_SUPPORTED
b2640405e06105d868b5fc8f7b676bb680884380vboxsync || vrc == VERR_INVALID_PARAMETER)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Status = STATUS_INVALID_PARAMETER;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pIrp->IoStatus.Status = Status;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pIrp->IoStatus.Information = cbOut;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync //Log(("VBoxGuest::vboxguestwinGuestDeviceControl: returned cbOut=%d rc=%#x\n", cbOut, Status));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return Status;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IRP_MJ_SYSTEM_CONTROL handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns NT status code
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp IRP.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNTSTATUS vboxguestwinSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestSystemControl\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Always pass it on to the next driver. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoSkipCurrentIrpStackLocation(pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IRP_MJ_SHUTDOWN handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns NT status code
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp IRP.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestShutdown\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync VMMDevPowerStateRequest *pReq = pDevExt->win.s.pPowerStateRequest;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pReq)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pReq->header.requestType = VMMDevReq_SetPowerStatus;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pReq->powerState = VMMDevPowerState_PowerOff;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync int rc = VbglGRPerform(&pReq->header);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (RT_FAILURE(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestShutdown: Error performing request to VMMDev! "
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "rc = %Rrc\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Stub function for functions we don't implemented.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns STATUS_NOT_SUPPORTED
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp IRP.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNTSTATUS vboxguestwinNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestNotSupportedStub\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevObj = pDevObj;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pIrp->IoStatus.Information = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return STATUS_NOT_SUPPORTED;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * DPC handler
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param dpc DPC descriptor.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param irp Interrupt request packet.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param context Context specific pointer.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncVOID vboxguestwinDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PIRP pIrp, PVOID pContext)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Unblock handlers waiting for arrived events.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Events are very low things, there is one event flag (1 or more bit)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * for each event. Each event is processed by exactly one handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Assume that we trust additions and that other drivers will
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * handle its respective events without trying to fetch all events.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Anyway design assures that wrong event processing will affect only guest.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Event handler calls VMMDev IOCTL for waiting an event.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * It supplies event mask. IOCTL blocks on EventNotification.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Here we just signal an the EventNotification to all waiting
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * threads, the IOCTL handler analyzes events and either
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * return to caller or blocks again.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * If we do not have too many events this is a simple and good
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * approach. Other way is to have as many Event objects as the callers
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * and wake up only callers waiting for the specific event.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Now with the 'wake up all' appoach we probably do not need the DPC
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * handler and can signal event directly from ISR.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestDpcHandler: pDevExt=0x%p\n", pDevExt));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef VBOX_WITH_HGCM
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync KePulseEvent(&pDevExt->win.s.hgcm.s.keventNotification, 0, FALSE);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * ISR handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @return BOOLEAN Indicates whether the IRQ came from us (TRUE) or not (FALSE).
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param interrupt Interrupt that was triggered.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param serviceContext Context specific pointer.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncBOOLEAN vboxguestwinIsrHandler(PKINTERRUPT interrupt, PVOID serviceContext)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)serviceContext;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync BOOLEAN fIRQTaken = FALSE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestIsrHandler: pDevExt = 0x%p, pVMMDevMemory = 0x%p\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (VBoxGuestCommonISR(pDevExt))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinGuestIsrHandler: IRQ was taken! pDeviceObject = 0x%p, pCurrentIrp = 0x%p\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.pDeviceObject, pDevExt->win.s.pCurrentIrp));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoRequestDpc(pDevExt->win.s.pDeviceObject, pDevExt->win.s.pCurrentIrp, NULL);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync fIRQTaken = TRUE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return fIRQTaken;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Overriden routine for mouse polling events. Not
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * used at the moment on Windows.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevExt Device extension structure.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncvoid VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NOREF(pDevExt);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Helper to scan the PCI resource list and remember stuff.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pResList Resource list
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevExt Device extension
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXT pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Enumerate the resource list. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Found %d resources\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pResList->List->PartialResourceList.Count));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS rc = STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialData = NULL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync ULONG rangeCount = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync ULONG cMMIORange = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PVBOXGUESTWINBASEADDRESS pBaseAddress = pDevExt->win.s.pciBaseAddress;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync for (ULONG i = 0; i < pResList->List->PartialResourceList.Count; i++)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData = &pResList->List->PartialResourceList.PartialDescriptors[i];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync switch (pPartialData->Type)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case CmResourceTypePort:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Overflow protection. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (rangeCount < PCI_TYPE0_ADDRESSES)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinScanPCIResourceList: I/O range: Base = %08x:%08x, Length = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Port.Start.HighPart,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Port.Start.LowPart,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Port.Length));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save the IO port base. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo Not so good. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->IOPortBase = (RTIOPORT)pPartialData->u.Port.Start.LowPart;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save resource information. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeStart = pPartialData->u.Port.Start;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeLength = pPartialData->u.Port.Length;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeInMemory = FALSE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->ResourceMapped = FALSE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinScanPCIResourceList: I/O range for VMMDev found! Base = %08x:%08x, Length = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Port.Start.HighPart,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Port.Start.LowPart,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Port.Length));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Next item ... */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rangeCount++; pBaseAddress++;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case CmResourceTypeInterrupt:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Interrupt: Level = %x, Vector = %x, Mode = %x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Interrupt.Level,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Interrupt.Vector,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->Flags));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save information. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.interruptLevel = pPartialData->u.Interrupt.Level;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.interruptVector = pPartialData->u.Interrupt.Vector;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.interruptAffinity = pPartialData->u.Interrupt.Affinity;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Check interrupt mode. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pPartialData->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.interruptMode = Latched;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.interruptMode = LevelSensitive;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case CmResourceTypeMemory:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Overflow protection. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (rangeCount < PCI_TYPE0_ADDRESSES)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Memory range: Base = %08x:%08x, Length = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Memory.Start.HighPart,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Memory.Start.LowPart,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Memory.Length));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* We only care about read/write memory. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo Reconsider memory type. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if ( cMMIORange == 0 /* Only care about the first MMIO range (!!!). */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync && (pPartialData->Flags & VBOX_CM_PRE_VISTA_MASK) == CM_RESOURCE_MEMORY_READ_WRITE)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save physical MMIO base + length for VMMDev. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.vmmDevPhysMemoryAddress = pPartialData->u.Memory.Start;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.vmmDevPhysMemoryLength = (ULONG)pPartialData->u.Memory.Length;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save resource information. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeStart = pPartialData->u.Memory.Start;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeLength = pPartialData->u.Memory.Length;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->RangeInMemory = TRUE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pBaseAddress->ResourceMapped = FALSE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Memory range for VMMDev found! Base = %08x:%08x, Length = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Memory.Start.HighPart,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Memory.Start.LowPart,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->u.Memory.Length));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Next item ... */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rangeCount++; pBaseAddress++; cMMIORange++;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Ignoring memory: Flags = %08x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pPartialData->Flags));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Unhandled resource found, type = %d\n", pPartialData->Type));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Memorize the number of resources found. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.pciAddressCount = rangeCount;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncNTSTATUS vboxguestwinMapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt, PHYSICAL_ADDRESS physicalAdr, ULONG ulLength,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync void **ppvMMIOBase, uint32_t *pcbMMIO)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync AssertPtrReturn(ppvMMIOBase, VERR_INVALID_POINTER);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* pcbMMIO is optional. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS rc = STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (physicalAdr.LowPart > 0) /* We're mapping below 4GB. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync VMMDevMemory *pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace(physicalAdr, ulLength, MmNonCached);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: pVMMDevMemory = 0x%x\n", pVMMDevMemory));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pVMMDevMemory)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: VMMDevMemory: Version = 0x%x, Size = %d\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pVMMDevMemory->u32Version, pVMMDevMemory->u32Size));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Check version of the structure; do we have the right memory version? */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pVMMDevMemory->u32Version != VMMDEV_MEMORY_VERSION)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: Wrong version (%u), refusing operation!\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pVMMDevMemory->u32Version));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Not our version, refuse operation and unmap the memory. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinUnmapVMMDevMemory(pDevExt);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = STATUS_UNSUCCESSFUL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save results. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *ppvMMIOBase = pVMMDevMemory;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pcbMMIO) /* Optional. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *pcbMMIO = pVMMDevMemory->u32Size;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: VMMDevMemory found and mapped! pvMMIOBase = 0x%p\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *ppvMMIOBase));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = STATUS_UNSUCCESSFUL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncvoid vboxguestwinUnmapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync Log(("VBoxGuest::vboxguestwinUnmapVMMDevMemory: pVMMDevMemory = 0x%x\n", pDevExt->pVMMDevMemory));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pDevExt->pVMMDevMemory)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync MmUnmapIoSpace((void*)pDevExt->pVMMDevMemory, pDevExt->win.s.vmmDevPhysMemoryLength);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->pVMMDevMemory = NULL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.vmmDevPhysMemoryAddress.QuadPart = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pDevExt->win.s.vmmDevPhysMemoryLength = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncVBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync switch (winVer)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case WINNT4:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return VBOXOSTYPE_WinNT4;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case WIN2K:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return VBOXOSTYPE_Win2k;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case WINXP:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return VBOXOSTYPE_WinXP;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case WIN2K3:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return VBOXOSTYPE_Win2k3;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case WINVISTA:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return VBOXOSTYPE_WinVista;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case WIN7:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return VBOXOSTYPE_Win7;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* We don't know, therefore NT family. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return VBOXOSTYPE_WinNT;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef DEBUG
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync/** A quick implementation of AtomicTestAndClear for uint32_t and multiple
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * bits.
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsyncstatic uint32_t guestAtomicBitsTestAndClear(void *pu32Bits, uint32_t u32Mask)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync{
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync AssertPtrReturn(pu32Bits, 0);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync LogFlowFunc(("*pu32Bits=0x%x, u32Mask=0x%x\n", *(long *)pu32Bits,
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync u32Mask));
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync uint32_t u32Result = 0;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync uint32_t u32WorkingMask = u32Mask;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync int iBitOffset = ASMBitFirstSetU32 (u32WorkingMask);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync while (iBitOffset > 0)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync {
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync bool fSet = ASMAtomicBitTestAndClear(pu32Bits, iBitOffset - 1);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync if (fSet)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync u32Result |= 1 << (iBitOffset - 1);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync u32WorkingMask &= ~(1 << (iBitOffset - 1));
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync iBitOffset = ASMBitFirstSetU32 (u32WorkingMask);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync }
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync LogFlowFunc(("Returning 0x%x\n", u32Result));
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync return u32Result;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync}
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic VOID vboxguestwinTestAtomicTestAndClearBitsU32(uint32_t u32Mask, uint32_t u32Bits,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t u32Exp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync ULONG u32Bits2 = u32Bits;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t u32Result = guestAtomicBitsTestAndClear(&u32Bits2, u32Mask);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if ( u32Result != u32Exp
b2640405e06105d868b5fc8f7b676bb680884380vboxsync || (u32Bits2 & u32Mask)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync || (u32Bits2 & u32Result)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync || ((u32Bits2 | u32Result) != u32Bits)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync )
b2640405e06105d868b5fc8f7b676bb680884380vboxsync AssertLogRelMsgFailed(("%s: TEST FAILED: u32Mask=0x%x, u32Bits (before)=0x%x, u32Bits (after)=0x%x, u32Result=0x%x, u32Exp=ox%x\n",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync __PRETTY_FUNCTION__, u32Mask, u32Bits, u32Bits2,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync u32Result));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic VOID vboxguestwinDoTests(VOID)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinTestAtomicTestAndClearBitsU32(0x00, 0x23, 0);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0, 0);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x22, 0);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x23, 0x1);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x32, 0x10);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync vboxguestwinTestAtomicTestAndClearBitsU32(0x22, 0x23, 0x22);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif