8ad79874169cc981a694a15e8a806b9a39133673vboxsync/* $Id$ */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/** @file
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VBoxGuest - Windows specifics.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync/*
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync * Copyright (C) 2010-2015 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>
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync#include <iprt/asm-amd64-x86.h>
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#include <VBox/log.h>
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#include <VBox/VBoxGuestLib.h>
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync#include <iprt/string.h>
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * XP DDK #defines ExFreePool to ExFreePoolWithTag. The latter does not exist
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * on NT4, so... The same for ExAllocatePool.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync#ifdef TARGET_NT4
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync# undef ExAllocatePool
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync# undef ExFreePool
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync* Internal Functions *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncRT_C_DECLS_BEGIN
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtUnload(PDRIVER_OBJECT pDrvObj);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp);
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef DEBUG
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtDoTests(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
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(INIT, DriverEntry)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(PAGE, vbgdNtAddDevice)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(PAGE, vbgdNtUnload)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(PAGE, vbgdNtCreate)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(PAGE, vbgdNtClose)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(PAGE, vbgdNtShutdown)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(PAGE, vbgdNtNotSupportedStub)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync# pragma alloc_text(PAGE, vbgdNtScanPCIResourceList)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync/*******************************************************************************
8ad79874169cc981a694a15e8a806b9a39133673vboxsync* Global Variables *
8ad79874169cc981a694a15e8a806b9a39133673vboxsync*******************************************************************************/
8ad79874169cc981a694a15e8a806b9a39133673vboxsync/** The detected NT (windows) version. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncVBGDNTVER g_enmVbgdNtVer = VBGDNTVER_INVALID;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync
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
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFunc(("Driver built: %s %s\n", __DATE__, __TIME__));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync /*
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * Check if the the NT version is supported and initializing
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * g_enmVbgdNtVer in the process.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync ULONG ulMajorVer;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync ULONG ulMinorVer;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync ULONG ulBuildNo;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync BOOLEAN fCheckedBuild = PsGetVersion(&ulMajorVer, &ulMinorVer, &ulBuildNo, NULL);
063595c74276001ecaa7ee2cf27471729212ab78vboxsync
063595c74276001ecaa7ee2cf27471729212ab78vboxsync /* Use RTLogBackdoorPrintf to make sure that this goes to VBox.log */
063595c74276001ecaa7ee2cf27471729212ab78vboxsync RTLogBackdoorPrintf("VBoxGuest: Windows version %u.%u, build %u\n", ulMajorVer, ulMinorVer, ulBuildNo);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync if (fCheckedBuild)
063595c74276001ecaa7ee2cf27471729212ab78vboxsync RTLogBackdoorPrintf("VBoxGuest: Windows checked build\n");
063595c74276001ecaa7ee2cf27471729212ab78vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef DEBUG
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtDoTests();
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
8ad79874169cc981a694a15e8a806b9a39133673vboxsync switch (ulMajorVer)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
063595c74276001ecaa7ee2cf27471729212ab78vboxsync case 10:
063595c74276001ecaa7ee2cf27471729212ab78vboxsync switch (ulMinorVer)
063595c74276001ecaa7ee2cf27471729212ab78vboxsync {
063595c74276001ecaa7ee2cf27471729212ab78vboxsync case 0:
063595c74276001ecaa7ee2cf27471729212ab78vboxsync /* Windows 10 Preview builds starting with 9926. */
063595c74276001ecaa7ee2cf27471729212ab78vboxsync default:
063595c74276001ecaa7ee2cf27471729212ab78vboxsync /* Also everything newer. */
063595c74276001ecaa7ee2cf27471729212ab78vboxsync g_enmVbgdNtVer = VBGDNTVER_WIN10;
063595c74276001ecaa7ee2cf27471729212ab78vboxsync break;
063595c74276001ecaa7ee2cf27471729212ab78vboxsync }
063595c74276001ecaa7ee2cf27471729212ab78vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 6: /* Windows Vista or Windows 7 (based on minor ver) */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync switch (ulMinorVer)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 0: /* Note: Also could be Windows 2008 Server! */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync g_enmVbgdNtVer = VBGDNTVER_WINVISTA;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 1: /* Note: Also could be Windows 2008 Server R2! */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync g_enmVbgdNtVer = VBGDNTVER_WIN7;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync case 2:
8ad79874169cc981a694a15e8a806b9a39133673vboxsync g_enmVbgdNtVer = VBGDNTVER_WIN8;
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync break;
cba644d3694119a648f130178a8d84d70ba3f88dvboxsync case 3:
d548194f74175bd02f817e8a95fccdec9604b938vboxsync g_enmVbgdNtVer = VBGDNTVER_WIN81;
cba644d3694119a648f130178a8d84d70ba3f88dvboxsync break;
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync case 4:
063595c74276001ecaa7ee2cf27471729212ab78vboxsync /* Windows 10 Preview builds. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
063595c74276001ecaa7ee2cf27471729212ab78vboxsync /* Also everything newer. */
063595c74276001ecaa7ee2cf27471729212ab78vboxsync g_enmVbgdNtVer = VBGDNTVER_WIN10;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 5:
8ad79874169cc981a694a15e8a806b9a39133673vboxsync switch (ulMinorVer)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
063595c74276001ecaa7ee2cf27471729212ab78vboxsync default:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 2:
8ad79874169cc981a694a15e8a806b9a39133673vboxsync g_enmVbgdNtVer = VBGDNTVER_WIN2K3;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 1:
8ad79874169cc981a694a15e8a806b9a39133673vboxsync g_enmVbgdNtVer = VBGDNTVER_WINXP;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 0:
8ad79874169cc981a694a15e8a806b9a39133673vboxsync g_enmVbgdNtVer = VBGDNTVER_WIN2K;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case 4:
8ad79874169cc981a694a15e8a806b9a39133673vboxsync g_enmVbgdNtVer = VBGDNTVER_WINNT4;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
063595c74276001ecaa7ee2cf27471729212ab78vboxsync if (ulMajorVer > 6)
063595c74276001ecaa7ee2cf27471729212ab78vboxsync {
063595c74276001ecaa7ee2cf27471729212ab78vboxsync /* "Windows 10 mode" for Windows 8.1+. */
063595c74276001ecaa7ee2cf27471729212ab78vboxsync g_enmVbgdNtVer = VBGDNTVER_WIN10;
063595c74276001ecaa7ee2cf27471729212ab78vboxsync }
8ad79874169cc981a694a15e8a806b9a39133673vboxsync else
063595c74276001ecaa7ee2cf27471729212ab78vboxsync {
063595c74276001ecaa7ee2cf27471729212ab78vboxsync if (ulMajorVer < 4)
063595c74276001ecaa7ee2cf27471729212ab78vboxsync LogRelFunc(("At least Windows NT4 required! (%u.%u)\n", ulMajorVer, ulMinorVer));
063595c74276001ecaa7ee2cf27471729212ab78vboxsync else
063595c74276001ecaa7ee2cf27471729212ab78vboxsync LogRelFunc(("Unknown version %u.%u!\n", ulMajorVer, ulMinorVer));
063595c74276001ecaa7ee2cf27471729212ab78vboxsync rc = STATUS_DRIVER_UNABLE_TO_LOAD;
063595c74276001ecaa7ee2cf27471729212ab78vboxsync }
8ad79874169cc981a694a15e8a806b9a39133673vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (NT_SUCCESS(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Setup the driver entry points in pDrvObj.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->DriverUnload = vbgdNtUnload;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_CREATE] = vbgdNtCreate;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_CLOSE] = vbgdNtClose;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vbgdNtIOCtl;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vbgdNtInternalIOCtl;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_SHUTDOWN] = vbgdNtShutdown;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_READ] = vbgdNtNotSupportedStub;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_WRITE] = vbgdNtNotSupportedStub;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef TARGET_NT4
91fdb167bd5c9417d9507c1317ae121864fdc9cbvboxsync rc = vbgdNt4CreateDevice(pDrvObj, NULL /* pDevObj */, pRegPath);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#else
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_PNP] = vbgdNtPnP;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_POWER] = vbgdNtPower;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vbgdNtSystemControl;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)vbgdNtAddDevice;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#endif
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("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 */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS rc;
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFuncEnter();
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create device.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync UNICODE_STRING DevName;
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync RtlInitUnicodeString(&DevName, VBOXGUEST_DEVICE_NAME_NT);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PDEVICE_OBJECT pDeviceObject = NULL;
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (NT_SUCCESS(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Create symbolic link (DOS devices).
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync UNICODE_STRING DosName;
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync rc = IoCreateSymbolicLink(&DosName, &DevName);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (NT_SUCCESS(rc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /*
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Setup the device extension.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension;
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync RT_ZERO(*pDevExt);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeInitializeSpinLock(&pDevExt->MouseEventAccessLock);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->pDeviceObject = pDeviceObject;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->prevDevState = STOPPED;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->devState = STOPPED;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj);
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync if (pDevExt->pNextLowerDriver != NULL)
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync {
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync /*
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * If we reached this point we're fine with the basic driver setup,
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync * so continue to init our own things.
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync vbgdNtBugCheckCallback(pDevExt); /* Ignore failure! */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync#endif
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync if (NT_SUCCESS(rc))
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync {
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync /* VBoxGuestPower is pageable; ensure we are not called at elevated IRQL */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync pDeviceObject->Flags |= DO_POWER_PAGABLE;
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync /* Driver is ready now. */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("Returning with rc=0x%x (success)\n", rc));
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync return rc;
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync }
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync IoDetachDevice(pDevExt->pNextLowerDriver);
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync }
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n"));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = STATUS_DEVICE_NOT_CONNECTED;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync /* bail out */
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync IoDeleteSymbolicLink(&DosName);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("IoCreateSymbolicLink failed with rc=%#x!\n", rc));
04ae74690b2f07a5cb3490babe3fd5e0cbdda226vboxsync IoDeleteDevice(pDeviceObject);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("IoCreateDevice failed with rc=%#x!\n", rc));
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("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 */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync{
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef LOG_ENABLED
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync PCM_PARTIAL_RESOURCE_DESCRIPTOR pResource = pResourceList->PartialDescriptors;
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync ULONG cResources = pResourceList->Count;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync for (ULONG i = 0; i < cResources; ++i, ++pResource)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync ULONG uType = pResource->Type;
0c6fd0fa9727d13b7ba687dd94169ce829723522vboxsync static char const * const s_apszName[] =
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeNull",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypePort",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeInterrupt",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeMemory",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDma",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDeviceSpecific",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeBusNumber",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeDevicePrivate",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeAssignedResource",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync "CmResourceTypeSubAllocateFrom",
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync };
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Type=%s", uType < RT_ELEMENTS(s_apszName) ? s_apszName[uType] : "Unknown"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync switch (uType)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync case CmResourceTypePort:
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync case CmResourceTypeMemory:
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Start %8X%8.8lX, length=%X\n",
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pResource->u.Port.Start.HighPart, pResource->u.Port.Start.LowPart,
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pResource->u.Port.Length));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync break;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync case CmResourceTypeInterrupt:
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Level=%X, vector=%X, affinity=%X\n",
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pResource->u.Interrupt.Level, pResource->u.Interrupt.Vector,
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pResource->u.Interrupt.Affinity));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync break;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync case CmResourceTypeDma:
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Channel %d, Port %X\n",
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pResource->u.Dma.Channel, pResource->u.Dma.Port));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync break;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync default:
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("\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
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#else
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync{
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifndef TARGET_NT4
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFuncEnter();
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync int rc = STATUS_SUCCESS; /** @todo r=bird: s/rc/rcNt/ and s/int/NTSTATUS/. gee. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef TARGET_NT4
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /*
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * Let's have a look at what our PCI adapter offers.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync */
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("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,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PCIBus, pDevExt->busNumber, pDevExt->slotNumber,
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync &pResourceList);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (pResourceList && pResourceList->Count > 0)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtShowDeviceResources(&pResourceList->List[0].PartialResourceList);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
8ad79874169cc981a694a15e8a806b9a39133673vboxsync rc = vbgdNtScanPCIResourceList(pResourceList, pDevExt);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#else
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (pStack->Parameters.StartDevice.AllocatedResources->Count > 0)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtShowDeviceResources(&pStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync rc = vbgdNtScanPCIResourceList(pStack->Parameters.StartDevice.AllocatedResourcesTranslated, 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;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync rc = vbgdNtMapVMMDevMemory(pDevExt,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->vmmDevPhysMemoryAddress,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->vmmDevPhysMemoryLength,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync &pvMMIOBase,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync &cbMMIO);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.pVMMDevMemory = (VMMDevMemory *)pvMMIOBase;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("pvMMIOBase=0x%p, pDevExt=0x%p, pDevExt->Core.pVMMDevMemory=0x%p\n",
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pvMMIOBase, pDevExt, pDevExt ? pDevExt->Core.pVMMDevMemory : NULL));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync int vrc = VbgdCommonInitDevExt(&pDevExt->Core,
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync pDevExt->Core.IOPortBase,
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync pvMMIOBase, cbMMIO,
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync vbgdNtVersionToOSType(g_enmVbgdNtVer),
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (RT_FAILURE(vrc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Could not init device extension, rc=%Rrc\n", vrc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = STATUS_DEVICE_CONFIGURATION_ERROR;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync else
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Could not map physical address of VMMDev, rc=0x%x\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pDevExt->pPowerStateRequest,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync sizeof(VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (RT_FAILURE(vrc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("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 */
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("Initializing DPC/ISR ...\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync IoInitializeDpcRequest(pDevExt->pDeviceObject, vbgdNtDpcHandler);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef TARGET_NT4
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync ULONG uInterruptVector;
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync KIRQL irqLevel;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Get an interrupt vector. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Only proceed if the device provides an interrupt. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if ( pDevExt->interruptLevel
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync || pDevExt->interruptVector)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("Getting interrupt vector (HAL): Bus=%u, IRQL=%u, Vector=%u\n",
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync pDevExt->busNumber, pDevExt->interruptLevel, pDevExt->interruptVector));
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync uInterruptVector = HalGetInterruptVector(PCIBus,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->busNumber,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptLevel,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptVector,
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync &irqLevel,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync &pDevExt->interruptAffinity);
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("HalGetInterruptVector returns vector=%u\n", uInterruptVector));
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync if (uInterruptVector == 0)
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFunc(("No interrupt vector found!\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync else
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Device does not provide an interrupt!\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pDevExt->interruptVector)
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("Connecting interrupt ...\n"));
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync rc = IoConnectInterrupt(&pDevExt->pInterruptObject, /* Out: interrupt object. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync (PKSERVICE_ROUTINE)vbgdNtIsrHandler, /* Our ISR handler. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt, /* Device context. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync NULL, /* Optional spinlock. */
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync#ifdef TARGET_NT4
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync uInterruptVector, /* Interrupt vector. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync irqLevel, /* Interrupt level. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync irqLevel, /* Interrupt level. */
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync#else
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptVector, /* Interrupt vector. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync (KIRQL)pDevExt->interruptLevel, /* Interrupt level. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync (KIRQL)pDevExt->interruptLevel, /* Interrupt level. */
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync#endif
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptMode, /* LevelSensitive or Latched. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync TRUE, /* Shareable interrupt. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptAffinity, /* CPU affinity. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync FALSE); /* Don't save FPU stack. */
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (NT_ERROR(rc))
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Could not connect interrupt, rc=0x%x\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync else
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("No interrupt vector found!\n"));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#ifdef VBOX_WITH_HGCM
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFunc(("Allocating kernel session data ...\n"));
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync int vrc = VbgdCommonCreateKernelSession(&pDevExt->Core, &pDevExt->pKernelSession);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (RT_FAILURE(vrc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Failed to allocated kernel session data, rc=%Rrc\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync rc = STATUS_UNSUCCESSFUL;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync#endif
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync if (RT_SUCCESS(rc))
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync {
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync ULONG ulValue = 0;
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync NTSTATUS rcNt = vbgdNtRegistryReadDWORD(RTL_REGISTRY_SERVICES,
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync L"VBoxGuest", L"LoggingEnabled", &ulValue);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync if (NT_SUCCESS(rcNt))
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync {
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.fLoggingEnabled = ulValue >= 0xFF;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pDevExt->Core.fLoggingEnabled)
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogRelFunc(("Logging to host log enabled (0x%x)", ulValue));
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync }
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync /* Ready to rumble! */
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogRelFunc(("Device is ready!\n"));
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync VBOXGUEST_UPDATE_DEVSTATE(pDevExt, WORKING);
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync }
4b79f1e3db952307a2b19933efb97ccb871157cfvboxsync else
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->pInterruptObject = NULL;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync /** @todo r=bird: The error cleanup here is completely missing. We'll leak a
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * whole bunch of things... */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Returned with rc=0x%x\n", rc));
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync return rc;
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync}
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync/**
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * Cleans up hardware resources.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * Do not delete DevExt here.
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync *
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * @param pDrvObj Driver object.
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtCleanup(PDEVICE_OBJECT pDevObj)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync{
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFuncEnter();
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync if (pDevExt)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync {
92de700c41f3803fd020736400a84b4105590eb6vboxsync
92de700c41f3803fd020736400a84b4105590eb6vboxsync#if 0 /* @todo: test & enable cleaning global session data */
92de700c41f3803fd020736400a84b4105590eb6vboxsync#ifdef VBOX_WITH_HGCM
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pDevExt->pKernelSession)
3a828bb90d1afb1dc3184bd90192750a87562d2dvboxsync {
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync VbgdCommonCloseSession(pDevExt, pDevExt->pKernelSession);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->pKernelSession = NULL;
3a828bb90d1afb1dc3184bd90192750a87562d2dvboxsync }
92de700c41f3803fd020736400a84b4105590eb6vboxsync#endif
92de700c41f3803fd020736400a84b4105590eb6vboxsync#endif
92de700c41f3803fd020736400a84b4105590eb6vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pDevExt->pInterruptObject)
92de700c41f3803fd020736400a84b4105590eb6vboxsync {
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync IoDisconnectInterrupt(pDevExt->pInterruptObject);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->pInterruptObject = NULL;
92de700c41f3803fd020736400a84b4105590eb6vboxsync }
92de700c41f3803fd020736400a84b4105590eb6vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync /** @todo: cleanup the rest stuff */
92de700c41f3803fd020736400a84b4105590eb6vboxsync
92de700c41f3803fd020736400a84b4105590eb6vboxsync
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. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtUnmapVMMDevMemory(pDevExt);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync }
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync return STATUS_SUCCESS;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync}
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Unload the driver.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDrvObj Driver object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtUnload(PDRIVER_OBJECT pDrvObj)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFuncEnter();
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef TARGET_NT4
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtCleanup(pDrvObj->DeviceObject);
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync /* Destroy device extension and clean up everything else. */
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync if (pDrvObj->DeviceObject && pDrvObj->DeviceObject->DeviceExtension)
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync VbgdCommonDeleteDevExt((PVBOXGUESTDEVEXT)pDrvObj->DeviceObject->DeviceExtension);
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync
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 */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync UNICODE_STRING DosName;
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync NTSTATUS rc = IoDeleteSymbolicLink(&DosName);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoDeleteDevice(pDrvObj->DeviceObject);
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync#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). */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync#endif /* !TARGET_NT4 */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("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 */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo AssertPtrReturn(pIrp); */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** @todo AssertPtrReturn(pStack); */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync NTSTATUS rc = STATUS_SUCCESS;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pDevExt->devState != WORKING)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Device is not working currently, state=%d\n", pDevExt->devState));
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync rc = STATUS_UNSUCCESSFUL;
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync }
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync else if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync {
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync /*
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * We are not remotely similar to a directory...
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * (But this is possible.)
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync */
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("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 {
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("File object type=%d\n", pFileObj->Type));
ce95f18112057771f68abe58df709edd7c467db1vboxsync
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 */
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync vrc = VbgdCommonCreateUserSession(&pDevExt->Core, &pSession);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* ... otherwise we've been called from R0! */
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync vrc = VbgdCommonCreateKernelSession(&pDevExt->Core, &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
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("Returning rc=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 */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("pDevExt=0x%p, pFileObj=0x%p, FsContext=0x%p\n",
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync 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)
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync VbgdCommonCloseSession(&pDevExt->Core, 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 */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync NTSTATUS Status = STATUS_SUCCESS;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync unsigned int uCmd = (unsigned int)pStack->Parameters.DeviceIoControl.IoControlCode;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync char *pBuf = (char *)pIrp->AssociatedIrp.SystemBuffer; /* All requests are buffered. */
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync size_t cbData = pStack->Parameters.DeviceIoControl.InputBufferLength;
220e5884905c24f2f04cb78947913b0e79309b6dvboxsync size_t cbOut = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Do we have a file object associated?*/
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync PFILE_OBJECT pFileObj = pStack->FileObject;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync PVBOXGUESTSESSION pSession = NULL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pFileObj) /* ... then we might have a session object as well! */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pSession = (PVBOXGUESTSESSION)pFileObj->FsContext;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("uCmd=%u, pDevExt=0x%p, pSession=0x%p\n",
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync 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. */
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync /** @todo r=bird: What on earth is this supposed to be? Each kernel session
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * shall have its own context of course, no hacks, pleeease. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pSession == NULL)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("XXX: BUGBUG: FIXME: Using ugly kernel session data hack ...\n"));
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync#ifdef DEBUG_andy
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync RTLogBackdoorPrintf("XXX: BUGBUG: FIXME: Using ugly kernel session data hack ... Please don't forget to fix this one, Andy!\n");
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync#endif
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pSession = pDevExt->pKernelSession;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync /* Verify that it's a buffered CTL. */
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync if ((pStack->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync /*
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync * Process the common IOCtls.
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync */
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync size_t cbDataReturned;
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync int vrc = VbgdCommonIoCtl(uCmd, &pDevExt->Core, pSession, pBuf, cbData, &cbDataReturned);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync LogFlowFunc(("rc=%Rrc, pBuf=0x%p, cbData=%u, cbDataReturned=%u\n",
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync vrc, pBuf, cbData, cbDataReturned));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync if (RT_SUCCESS(vrc))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync if (RT_UNLIKELY( cbDataReturned > cbData
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync || cbDataReturned > pStack->Parameters.DeviceIoControl.OutputBufferLength))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Too much output data %u - expected %u!\n", cbDataReturned, cbData));
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync cbDataReturned = cbData;
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync Status = STATUS_BUFFER_TOO_SMALL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync if (cbDataReturned > 0)
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync cbOut = cbDataReturned;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync if ( vrc == VERR_NOT_SUPPORTED
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync || vrc == VERR_INVALID_PARAMETER)
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync Status = STATUS_INVALID_PARAMETER;
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync else if (vrc == VERR_OUT_OF_RANGE)
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync Status = STATUS_INVALID_BUFFER_SIZE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync Status = STATUS_UNSUCCESSFUL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync else
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Not buffered request (%#x) - not supported\n", pStack->Parameters.DeviceIoControl.IoControlCode));
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync Status = STATUS_NOT_SUPPORTED;
f0ee209770f633d122076f798c039ab21c55c4bcvboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pIrp->IoStatus.Status = Status;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pIrp->IoStatus.Information = cbOut;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync //LogFlowFunc(("Returned cbOut=%d rc=%#x\n", cbOut, Status));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return Status;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync/**
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * Internal Device I/O Control entry point.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync *
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * @param pDevObj Device object.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * @param pIrp Request packet.
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic NTSTATUS vbgdNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync{
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync NTSTATUS Status = STATUS_SUCCESS;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync unsigned int uCmd = (unsigned int)pStack->Parameters.DeviceIoControl.IoControlCode;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync bool fProcessed = false;
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync unsigned Info = 0;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync /*
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync * Override common behavior of some operations.
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync */
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync /** @todo r=bird: Better to add dedicated worker functions for this! */
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync switch (uCmd)
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync {
147b6ddff14ec450da8593696cf60c4258d61613vboxsync case VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK:
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync {
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync PVOID pvBuf = pStack->Parameters.Others.Argument1;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync size_t cbData = (size_t)pStack->Parameters.Others.Argument2;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync fProcessed = true;
2906c2554adf12dac04c4bdd7e44ec9f960f0390vboxsync if (cbData != sizeof(VBoxGuestMouseSetNotifyCallback))
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync {
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync AssertFailed();
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync Status = STATUS_INVALID_PARAMETER;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync break;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync }
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
2906c2554adf12dac04c4bdd7e44ec9f960f0390vboxsync VBoxGuestMouseSetNotifyCallback *pInfo = (VBoxGuestMouseSetNotifyCallback*)pvBuf;
c676658a234a45bfe783320e8a13f6fd4f0425dbvboxsync
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync /* we need a lock here to avoid concurrency with the set event functionality */
c676658a234a45bfe783320e8a13f6fd4f0425dbvboxsync KIRQL OldIrql;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeAcquireSpinLock(&pDevExt->MouseEventAccessLock, &OldIrql);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.MouseNotifyCallback = *pInfo;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeReleaseSpinLock(&pDevExt->MouseEventAccessLock, OldIrql);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync Status = STATUS_SUCCESS;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync break;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync }
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync default:
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync break;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync }
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync if (fProcessed)
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync {
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pIrp->IoStatus.Status = Status;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync pIrp->IoStatus.Information = Info;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync return Status;
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync }
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync /*
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync * No override, go to common code.
060bf5e6f4ef4f8008cde90ed72d96a514664b25vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync return vbgdNtIOCtl(pDevObj, pIrp);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync}
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * IRP_MJ_SYSTEM_CONTROL handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns NT status code
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pIrp IRP.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFuncEnter();
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Always pass it on to the next driver. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync IoSkipCurrentIrpStackLocation(pIrp);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync return IoCallDriver(pDevExt->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 */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFuncEnter();
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync VMMDevPowerStateRequest *pReq = pDevExt->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))
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Error performing request to VMMDev, rc=%Rrc\n", rc));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync
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 */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFuncEnter();
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/**
ce95f18112057771f68abe58df709edd7c467db1vboxsync * DPC handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pDPC DPC descriptor.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevObj Device object.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pIrp Interrupt request packet.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pContext Context specific pointer.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncvoid vbgdNtDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension;
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync Log3Func(("pDevExt=0x%p\n", pDevExt));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync /* Test & reset the counter. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (ASMAtomicXchgU32(&pDevExt->Core.u32MousePosChangedSeq, 0))
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync {
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync /* we need a lock here to avoid concurrency with the set event ioctl handler thread,
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * i.e. to prevent the event from destroyed while we're using it */
6724f34fdfee01d77d13f23d907d7b79d80e435dvboxsync Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeAcquireSpinLockAtDpcLevel(&pDevExt->MouseEventAccessLock);
6724f34fdfee01d77d13f23d907d7b79d80e435dvboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pDevExt->Core.MouseNotifyCallback.pfnNotify)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.MouseNotifyCallback.pfnNotify(pDevExt->Core.MouseNotifyCallback.pvUser);
6724f34fdfee01d77d13f23d907d7b79d80e435dvboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KeReleaseSpinLockFromDpcLevel(&pDevExt->MouseEventAccessLock);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync }
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync
ce95f18112057771f68abe58df709edd7c467db1vboxsync /* Process the wake-up list we were asked by the scheduling a DPC
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * in vbgdNtIsrHandler(). */
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync VbgdCommonWaitDoWakeUps(&pDevExt->Core);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * ISR handler.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @return BOOLEAN Indicates whether the IRQ came from us (TRUE) or not (FALSE).
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pInterrupt Interrupt that was triggered.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pServiceContext Context specific pointer.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncBOOLEAN vbgdNtIsrHandler(PKINTERRUPT pInterrupt, PVOID pServiceContext)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pServiceContext;
6de26a0709c5a075db3c7532e7702444cd35afd6vboxsync if (pDevExt == NULL)
6de26a0709c5a075db3c7532e7702444cd35afd6vboxsync return FALSE;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync /*Log3Func(("pDevExt=0x%p, pVMMDevMemory=0x%p\n", pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL));*/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
ce95f18112057771f68abe58df709edd7c467db1vboxsync /* Enter the common ISR routine and do the actual work. */
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsync BOOLEAN fIRQTaken = VbgdCommonISR(&pDevExt->Core);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
ce95f18112057771f68abe58df709edd7c467db1vboxsync /* If we need to wake up some events we do that in a DPC to make
ce95f18112057771f68abe58df709edd7c467db1vboxsync * sure we're called at the right IRQL. */
6de26a0709c5a075db3c7532e7702444cd35afd6vboxsync if (fIRQTaken)
6de26a0709c5a075db3c7532e7702444cd35afd6vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync Log3Func(("IRQ was taken! pInterrupt=0x%p, pDevExt=0x%p\n", pInterrupt, pDevExt));
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync if (ASMAtomicUoReadU32( &pDevExt->Core.u32MousePosChangedSeq)
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync || !RTListIsEmpty(&pDevExt->Core.WakeUpList))
6de26a0709c5a075db3c7532e7702444cd35afd6vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync Log3Func(("Requesting DPC ...\n"));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync IoRequestDpc(pDevExt->pDeviceObject, pDevExt->pCurrentIrp, NULL);
6de26a0709c5a075db3c7532e7702444cd35afd6vboxsync }
6de26a0709c5a075db3c7532e7702444cd35afd6vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return fIRQTaken;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync/**
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * Overridden routine for mouse polling events.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevExt Device extension structure.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
e1ed9baf425f4c757302ec417a815aab945fdbf0vboxsyncvoid VbgdNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NOREF(pDevExt);
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync /* nothing to do here - i.e. since we can not KeSetEvent from ISR level,
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * we rely on the pDevExt->u32MousePosChangedSeq to be set to a non-zero value on a mouse event
46ff7af86c9b48efa8270af373c8d5dcfa7d05c5vboxsync * and queue the DPC in our ISR routine in that case doing KeSetEvent from the DPC routine */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync/**
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * Queries (gets) a DWORD value from the registry.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync *
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @return NTSTATUS
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @param ulRoot Relative path root. See RTL_REGISTRY_SERVICES or RTL_REGISTRY_ABSOLUTE.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @param pwszPath Path inside path root.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @param pwszName Actual value name to look up.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * @param puValue On input this can specify the default value (if RTL_REGISTRY_OPTIONAL is
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * not specified in ulRoot), on output this will retrieve the looked up
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync * registry value if found.
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync */
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncNTSTATUS vbgdNtRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue)
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync{
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync if (!pwszPath || !pwszName || !puValue)
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync return STATUS_INVALID_PARAMETER;
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync ULONG ulDefault = *puValue;
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync RTL_QUERY_REGISTRY_TABLE tblQuery[2];
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync RtlZeroMemory(tblQuery, sizeof(tblQuery));
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync /** @todo Add RTL_QUERY_REGISTRY_TYPECHECK! */
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync tblQuery[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync tblQuery[0].Name = pwszName;
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync tblQuery[0].EntryContext = puValue;
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync tblQuery[0].DefaultType = REG_DWORD;
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync tblQuery[0].DefaultData = &ulDefault;
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync tblQuery[0].DefaultLength = sizeof(ULONG);
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync return RtlQueryRegistryValues(ulRoot,
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync pwszPath,
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync &tblQuery[0],
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync NULL /* Context */,
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync NULL /* Environment */);
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync}
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync
7796e8b1dcbbe95e91b6f56842324ef07d99f977vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/**
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Helper to scan the PCI resource list and remember stuff.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pResList Resource list
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pDevExt Device extension
b2640405e06105d868b5fc8f7b676bb680884380vboxsync */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncNTSTATUS vbgdNtScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXTWIN pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Enumerate the resource list. */
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("Found %d resources\n",
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync 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;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync PVBOXGUESTWINBASEADDRESS pBaseAddress = pDevExt->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 {
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("I/O range: Base=%08x:%08x, length=%08x\n",
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync pPartialData->u.Port.Start.HighPart,
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync pPartialData->u.Port.Start.LowPart,
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync pPartialData->u.Port.Length));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save the IO port base. */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync /** @todo Not so good.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * Update/bird: What is not so good? That we just consider the last range? */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.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
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("I/O range for VMMDev found! Base=%08x:%08x, length=%08x\n",
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->u.Port.Start.HighPart,
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->u.Port.Start.LowPart,
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->u.Port.Length));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Next item ... */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rangeCount++; pBaseAddress++;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case CmResourceTypeInterrupt:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Interrupt: Level=%x, vector=%x, mode=%x\n",
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->u.Interrupt.Level,
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->u.Interrupt.Vector,
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->Flags));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save information. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptLevel = pPartialData->u.Interrupt.Level;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptVector = pPartialData->u.Interrupt.Vector;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptAffinity = pPartialData->u.Interrupt.Affinity;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Check interrupt mode. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pPartialData->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptMode = Latched;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->interruptMode = LevelSensitive;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync case CmResourceTypeMemory:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Overflow protection. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (rangeCount < PCI_TYPE0_ADDRESSES)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("Memory range: Base=%08x:%08x, length=%08x\n",
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync pPartialData->u.Memory.Start.HighPart,
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync pPartialData->u.Memory.Start.LowPart,
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync 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. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->vmmDevPhysMemoryAddress = pPartialData->u.Memory.Start;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->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
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Memory range for VMMDev found! Base = %08x:%08x, Length = %08x\n",
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->u.Memory.Start.HighPart,
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->u.Memory.Start.LowPart,
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync pPartialData->u.Memory.Length));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Next item ... */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rangeCount++; pBaseAddress++; cMMIORange++;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Ignoring memory: Flags=%08x\n", pPartialData->Flags));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Unhandled resource found, type=%d\n", pPartialData->Type));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Memorize the number of resources found. */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->pciAddressCount = rangeCount;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
ce95f18112057771f68abe58df709edd7c467db1vboxsync/**
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Maps the I/O space from VMMDev to virtual kernel address space.
ce95f18112057771f68abe58df709edd7c467db1vboxsync *
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @return NTSTATUS
ce95f18112057771f68abe58df709edd7c467db1vboxsync *
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pDevExt The device extension.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @param PhysAddr Physical address to map.
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync * @param cbToMap Number of bytes to map.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param ppvMMIOBase Pointer of mapped I/O base.
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pcbMMIO Length of mapped I/O base.
ce95f18112057771f68abe58df709edd7c467db1vboxsync */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsyncNTSTATUS vbgdNtMapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt, PHYSICAL_ADDRESS PhysAddr, ULONG cbToMap,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync 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;
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync if (PhysAddr.LowPart > 0) /* We're mapping below 4GB. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync VMMDevMemory *pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace(PhysAddr, cbToMap, MmNonCached);
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("pVMMDevMemory = 0x%x\n", pVMMDevMemory));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pVMMDevMemory)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("VMMDevMemory: Version = 0x%x, Size = %d\n", pVMMDevMemory->u32Version, pVMMDevMemory->u32Size));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Check version of the structure; do we have the right memory version? */
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync if (pVMMDevMemory->u32Version == VMMDEV_MEMORY_VERSION)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Save results. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *ppvMMIOBase = pVMMDevMemory;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pcbMMIO) /* Optional. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync *pcbMMIO = pVMMDevMemory->u32Size;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFlowFunc(("VMMDevMemory found and mapped! pvMMIOBase = 0x%p\n", *ppvMMIOBase));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync else
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync {
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync /* Not our version, refuse operation and unmap the memory. */
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync LogFunc(("Wrong version (%u), refusing operation!\n", pVMMDevMemory->u32Version));
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync vbgdNtUnmapVMMDevMemory(pDevExt);
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync rc = STATUS_UNSUCCESSFUL;
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync else
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = STATUS_UNSUCCESSFUL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return rc;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
ce95f18112057771f68abe58df709edd7c467db1vboxsync/**
ce95f18112057771f68abe58df709edd7c467db1vboxsync * Unmaps the VMMDev I/O range from kernel space.
ce95f18112057771f68abe58df709edd7c467db1vboxsync *
ce95f18112057771f68abe58df709edd7c467db1vboxsync * @param pDevExt The device extension.
ce95f18112057771f68abe58df709edd7c467db1vboxsync */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncvoid vbgdNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
79f1ee8626f01a1f80d0235790ab91deba73af88vboxsync LogFlowFunc(("pVMMDevMemory = 0x%x\n", pDevExt->Core.pVMMDevMemory));
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pDevExt->Core.pVMMDevMemory)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync MmUnmapIoSpace((void*)pDevExt->Core.pVMMDevMemory, pDevExt->vmmDevPhysMemoryLength);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->Core.pVMMDevMemory = NULL;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->vmmDevPhysMemoryAddress.QuadPart = 0;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pDevExt->vmmDevPhysMemoryLength = 0;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncVBOXOSTYPE vbgdNtVersionToOSType(VBGDNTVER enmNtVer)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync VBOXOSTYPE enmOsType;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync switch (enmNtVer)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync {
8ad79874169cc981a694a15e8a806b9a39133673vboxsync case VBGDNTVER_WINNT4:
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync enmOsType = VBOXOSTYPE_WinNT4;
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync case VBGDNTVER_WIN2K:
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync enmOsType = VBOXOSTYPE_Win2k;
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync case VBGDNTVER_WINXP:
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#if ARCH_BITS == 64
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync enmOsType = VBOXOSTYPE_WinXP_x64;
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#else
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync enmOsType = VBOXOSTYPE_WinXP;
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#endif
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync case VBGDNTVER_WIN2K3:
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#if ARCH_BITS == 64
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync enmOsType = VBOXOSTYPE_Win2k3_x64;
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#else
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync enmOsType = VBOXOSTYPE_Win2k3;
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#endif
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync case VBGDNTVER_WINVISTA:
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#if ARCH_BITS == 64
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync enmOsType = VBOXOSTYPE_WinVista_x64;
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#else
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync enmOsType = VBOXOSTYPE_WinVista;
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#endif
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync case VBGDNTVER_WIN7:
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#if ARCH_BITS == 64
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync enmOsType = VBOXOSTYPE_Win7_x64;
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#else
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync enmOsType = VBOXOSTYPE_Win7;
b394f699c1a81998b6216e59bac82704a937e4f5vboxsync#endif
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsync case VBGDNTVER_WIN8:
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync#if ARCH_BITS == 64
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync enmOsType = VBOXOSTYPE_Win8_x64;
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync#else
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync enmOsType = VBOXOSTYPE_Win8;
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync#endif
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync break;
b4a81d521ea7f88aca6f77b2725541e58a2dc018vboxsync
d548194f74175bd02f817e8a95fccdec9604b938vboxsync case VBGDNTVER_WIN81:
d548194f74175bd02f817e8a95fccdec9604b938vboxsync#if ARCH_BITS == 64
d548194f74175bd02f817e8a95fccdec9604b938vboxsync enmOsType = VBOXOSTYPE_Win81_x64;
d548194f74175bd02f817e8a95fccdec9604b938vboxsync#else
d548194f74175bd02f817e8a95fccdec9604b938vboxsync enmOsType = VBOXOSTYPE_Win81;
d548194f74175bd02f817e8a95fccdec9604b938vboxsync#endif
d548194f74175bd02f817e8a95fccdec9604b938vboxsync break;
d548194f74175bd02f817e8a95fccdec9604b938vboxsync
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync case VBGDNTVER_WIN10:
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync#if ARCH_BITS == 64
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync enmOsType = VBOXOSTYPE_Win10_x64;
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync#else
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync enmOsType = VBOXOSTYPE_Win10;
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync#endif
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync break;
6fd13c2e3e855d7f5a7147cb0414af050e1503e6vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync default:
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync /* We don't know, therefore NT family. */
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync enmOsType = VBOXOSTYPE_WinNT;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync break;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync }
5b9474ab4fc24402eb9e352fb2845b036f0736b6vboxsync return enmOsType;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
b2640405e06105d868b5fc8f7b676bb680884380vboxsync
b2640405e06105d868b5fc8f7b676bb680884380vboxsync#ifdef DEBUG
32a1f7401e3441c55312b37daa1a82a28fcbcc92vboxsync
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync/**
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync * A quick implementation of AtomicTestAndClear for uint32_t and multiple bits.
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync */
ce95f18112057771f68abe58df709edd7c467db1vboxsyncstatic uint32_t vboxugestwinAtomicBitsTestAndClear(void *pu32Bits, uint32_t u32Mask)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync{
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync AssertPtrReturn(pu32Bits, 0);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync LogFlowFunc(("*pu32Bits=0x%x, u32Mask=0x%x\n", *(uint32_t *)pu32Bits, 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
ce95f18112057771f68abe58df709edd7c467db1vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtTestAtomicTestAndClearBitsU32(uint32_t u32Mask, uint32_t u32Bits, uint32_t u32Exp)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
b2640405e06105d868b5fc8f7b676bb680884380vboxsync ULONG u32Bits2 = u32Bits;
ce95f18112057771f68abe58df709edd7c467db1vboxsync uint32_t u32Result = vboxugestwinAtomicBitsTestAndClear(&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
ce95f18112057771f68abe58df709edd7c467db1vboxsync
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic void vbgdNtDoTests(void)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync{
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x00, 0x23, 0);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0, 0);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x22, 0);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x23, 0x1);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x32, 0x10);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync vbgdNtTestAtomicTestAndClearBitsU32(0x22, 0x23, 0x22);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync}
32a1f7401e3441c55312b37daa1a82a28fcbcc92vboxsync
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync#endif /* DEBUG */
5a9cd9ff1147e9845e0d3fc020973df2d3e66daavboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync#ifdef VBOX_WITH_DPC_LATENCY_CHECKER
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync/*
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * DPC latency checker.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync/**
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * One DPC latency sample.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync */
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsynctypedef struct DPCSAMPLE
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync{
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync LARGE_INTEGER PerfDelta;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync LARGE_INTEGER PerfCounter;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync LARGE_INTEGER PerfFrequency;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync uint64_t u64TSC;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync} DPCSAMPLE;
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsyncAssertCompileSize(DPCSAMPLE, 4*8);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync/**
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * The DPC latency measurement workset.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync */
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsynctypedef struct DPCDATA
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync{
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KDPC Dpc;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KTIMER Timer;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync KSPIN_LOCK SpinLock;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync ULONG ulTimerRes;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync bool volatile fFinished;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync /** The timer interval (relative). */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync LARGE_INTEGER DueTime;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync LARGE_INTEGER PerfCounterPrev;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync /** Align the sample array on a 64 byte boundrary just for the off chance
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * that we'll get cache line aligned memory backing this structure. */
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync uint32_t auPadding[ARCH_BITS == 32 ? 5 : 7];
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync int cSamples;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync DPCSAMPLE aSamples[8192];
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync} DPCDATA;
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsyncAssertCompileMemberAlignment(DPCDATA, aSamples, 64);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync# define VBOXGUEST_DPC_TAG 'DPCS'
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync/**
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * DPC callback routine for the DPC latency measurement code.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync *
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @param pDpc The DPC, not used.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @param pvDeferredContext Pointer to the DPCDATA.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @param SystemArgument1 System use, ignored.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @param SystemArgument2 System use, ignored.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync */
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsyncstatic VOID vbgdNtDpcLatencyCallback(PKDPC pDpc, PVOID pvDeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync{
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync DPCDATA *pData = (DPCDATA *)pvDeferredContext;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync KeAcquireSpinLockAtDpcLevel(&pData->SpinLock);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (pData->cSamples >= RT_ELEMENTS(pData->aSamples))
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pData->fFinished = true;
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync else
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync {
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync DPCSAMPLE *pSample = &pData->aSamples[pData->cSamples++];
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pSample->u64TSC = ASMReadTSC();
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pSample->PerfCounter = KeQueryPerformanceCounter(&pSample->PerfFrequency);
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pSample->PerfDelta.QuadPart = pSample->PerfCounter.QuadPart - pData->PerfCounterPrev.QuadPart;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pData->PerfCounterPrev.QuadPart = pSample->PerfCounter.QuadPart;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync KeSetTimer(&pData->Timer, pData->DueTime, &pData->Dpc);
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync }
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync KeReleaseSpinLockFromDpcLevel(&pData->SpinLock);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync}
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync/**
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Handles the DPC latency checker request.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync *
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * @returns VBox status code.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync */
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsyncint VbgdNtIOCtl_DpcLatencyChecker(void)
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync{
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync /*
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Allocate a block of non paged memory for samples and related data.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync */
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync DPCDATA *pData = (DPCDATA *)ExAllocatePoolWithTag(NonPagedPool, sizeof(DPCDATA), VBOXGUEST_DPC_TAG);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync if (!pData)
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync {
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync RTLogBackdoorPrintf("VBoxGuest: DPC: DPCDATA allocation failed.\n");
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync return VERR_NO_MEMORY;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync }
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync /*
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Initialize the data.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync */
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync KeInitializeDpc(&pData->Dpc, vbgdNtDpcLatencyCallback, pData);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync KeInitializeTimer(&pData->Timer);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync KeInitializeSpinLock(&pData->SpinLock);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync pData->fFinished = false;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pData->cSamples = 0;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync pData->PerfCounterPrev.QuadPart = 0;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync pData->ulTimerRes = ExSetTimerResolution(1000 * 10, 1);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync pData->DueTime.QuadPart = -(int64_t)pData->ulTimerRes / 10;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync /*
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Start the DPC measurements and wait for a full set.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync */
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync KeSetTimer(&pData->Timer, pData->DueTime, &pData->Dpc);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync while (!pData->fFinished)
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync {
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync LARGE_INTEGER Interval;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync Interval.QuadPart = -100 * 1000 * 10;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync KeDelayExecutionThread(KernelMode, TRUE, &Interval);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync }
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync ExSetTimerResolution(0, 0);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync /*
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync * Log everything to the host.
63b5b2edb3bb80b9bdef27c089e87072f6175b42vboxsync */
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync RTLogBackdoorPrintf("DPC: ulTimerRes = %d\n", pData->ulTimerRes);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync for (int i = 0; i < pData->cSamples; i++)
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync {
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync DPCSAMPLE *pSample = &pData->aSamples[i];
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync RTLogBackdoorPrintf("[%d] pd %lld pc %lld pf %lld t %lld\n",
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync i,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pSample->PerfDelta.QuadPart,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pSample->PerfCounter.QuadPart,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pSample->PerfFrequency.QuadPart,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync pSample->u64TSC);
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync }
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync ExFreePoolWithTag(pData, VBOXGUEST_DPC_TAG);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync return VINF_SUCCESS;
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync}
6b8a22f9d63cec76b67809cf0bbccae1832fa215vboxsync
258511aa4b33ed962c316ae5934e400edf09d3d6vboxsync#endif /* VBOX_WITH_DPC_LATENCY_CHECKER */
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync