VBoxGuest-win-legacy.cpp revision eb4f1fa4c357485330370c0eaba27e5a2af7d9c4
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** @file
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VBoxGuest-win-legacy - Windows NT4 specifics.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Copyright (C) 2010 Oracle Corporation
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * available from http://www.virtualbox.org. This file is free software;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * General Public License (GPL) as published by the Free Software
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Header Files *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include "VBoxGuest-win.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include "VBoxGuestInternal.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/err.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/log.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/version.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/VBoxGuestLib.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Defined Constants And Macros *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* Reenable logging, this was #undef'ed on iprt/log.h for RING0. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define LOG_ENABLED
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifndef PCI_MAX_BUSES
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync# define PCI_MAX_BUSES 256
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Internal Functions *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRT_C_DECLS_BEGIN
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic NTSTATUS vboxguestwinnt4FindPCIDevice(PULONG pBusNumber, PPCI_SLOT_NUMBER pSlotNumber);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void vboxguestwinnt4FreeDeviceResources(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRT_C_DECLS_END
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef ALLOC_PRAGMA
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#pragma alloc_text (INIT, vboxguestwinnt4CreateDevice)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#pragma alloc_text (INIT, vboxguestwinnt4FindPCIDevice)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#pragma alloc_text (INIT, vboxguestwinnt4FreeDeviceResources)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Helper function to create the device object
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns NT status code
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncNTSTATUS vboxguestwinnt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int vrc = VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync NTSTATUS rc = STATUS_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4CreateDevice: pDrvObj=%x, pDevObj=%x, pRegPath=%x\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDrvObj, pDevObj, pRegPath));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Find our virtual PCI device
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ULONG uBusNumber, uSlotNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = vboxguestwinnt4FindPCIDevice(&uBusNumber, (PCI_SLOT_NUMBER*)&uSlotNumber);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (NT_ERROR(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Device not found!\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PDEVICE_OBJECT pDeviceObject = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (NT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Create device.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync UNICODE_STRING szDevName;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RtlInitUnicodeString(&szDevName, VBOXGUEST_DEVICE_NAME_NT);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXT), &szDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (NT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Device created\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync UNICODE_STRING DosName;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = IoCreateSymbolicLink(&DosName, &szDevName);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (NT_ERROR(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4CreateDevice: IoCreateSymbolicLink failed with rc = %#x\n", rc));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync //IoDeleteDevice(pDeviceObject);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Symlink created\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4CreateDevice: IoCreateDevice failed with rc = %#x\n", rc));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Setup the device extension.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PVBOXGUESTDEVEXT pDevExt = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (NT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Setting up device extension ...\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDevExt = (PVBOXGUESTDEVEXT)pDeviceObject->DeviceExtension;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Assert(pDevExt);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RtlZeroMemory(pDevExt, sizeof(VBOXGUESTDEVEXT));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( NT_SUCCESS(rc)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && pDevExt)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Store a reference to ourself. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDevExt->win.s.pDeviceObject = pDeviceObject;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Store bus and slot number we've queried before. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDevExt->win.s.busNumber = uBusNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDevExt->win.s.slotNumber = uSlotNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = hlpRegisterBugCheckCallback(pDevExt);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync #endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (NT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = vboxguestwinInit(pDrvObj, pDevObj, pRegPath);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Returning rc = 0x%x\n", rc));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Helper function to handle the PCI device lookup
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns NT error codes
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic NTSTATUS vboxguestwinnt4FindPCIDevice(PULONG pBusNumber, PPCI_SLOT_NUMBER pSlotNumber)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync NTSTATUS rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ULONG busNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ULONG deviceNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ULONG functionNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PCI_SLOT_NUMBER slotNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PCI_COMMON_CONFIG pciData;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4FindPCIDevice\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = STATUS_DEVICE_DOES_NOT_EXIST;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync slotNumber.u.AsULONG = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Scan each bus. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync for (busNumber = 0; busNumber < PCI_MAX_BUSES; busNumber++)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Scan each device. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync for (deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync slotNumber.u.bits.DeviceNumber = deviceNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Scan each function (not really required...). */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync for (functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync slotNumber.u.bits.FunctionNumber = functionNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Have a look at what's in this slot. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!HalGetBusData(PCIConfiguration, busNumber, slotNumber.u.AsULONG,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &pciData, sizeof(ULONG)))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* No such bus, we're done with it. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync deviceNumber = PCI_MAX_DEVICES;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pciData.VendorID == PCI_INVALID_VENDORID)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* We have to proceed to the next function. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Check if it's another device. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ((pciData.VendorID != VMMDEV_VENDORID) ||
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync (pciData.DeviceID != VMMDEV_DEVICEID))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Hooray, we've found it! */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxGuest::vboxguestwinnt4FindPCIDevice: Device found!\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pBusNumber = busNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pSlotNumber = slotNumber;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = STATUS_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync