589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/* $Id$ */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/** @file
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * VBoxGuest-win-legacy - Windows NT4 specifics.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/*
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Copyright (C) 2010-2015 Oracle Corporation
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * available from http://www.virtualbox.org. This file is free software;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * General Public License (GPL) as published by the Free Software
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/*******************************************************************************
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync* Header Files *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync*******************************************************************************/
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync#include "VBoxGuest-win.h"
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync#include "VBoxGuestInternal.h"
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#include <VBox/err.h>
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#include <VBox/log.h>
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#include <VBox/version.h>
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#include <VBox/VBoxGuestLib.h>
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#include <iprt/string.h>
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/*******************************************************************************
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync* Defined Constants And Macros *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync*******************************************************************************/
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#ifndef PCI_MAX_BUSES
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync# define PCI_MAX_BUSES 256
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#endif
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/*******************************************************************************
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync* Internal Functions *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync*******************************************************************************/
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsyncRT_C_DECLS_BEGIN
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsyncstatic NTSTATUS vbgdNt4FindPciDevice(PULONG pulBusNumber, PPCI_SLOT_NUMBER pSlotNumber);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsyncRT_C_DECLS_END
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#ifdef ALLOC_PRAGMA
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync# pragma alloc_text(INIT, vbgdNt4CreateDevice)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync# pragma alloc_text(INIT, vbgdNt4FindPciDevice)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync#endif
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/**
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Legacy helper function to create the device object.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @returns NT status code.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pDrvObj The driver object.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pDevObj Unused. NULL. Dunno why it's here, makes no sense.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pRegPath The driver registry path.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsyncNTSTATUS vbgdNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync{
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: pDrvObj=%p, pDevObj=%p, pRegPath=%p\n", pDrvObj, pDevObj, pRegPath));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /*
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Find our virtual PCI device
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync ULONG uBusNumber;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync PCI_SLOT_NUMBER SlotNumber;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync NTSTATUS rc = vbgdNt4FindPciDevice(&uBusNumber, &SlotNumber);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync if (NT_ERROR(rc))
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync {
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: Device not found!\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync return rc;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /*
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Create device.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync UNICODE_STRING szDevName;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync RtlInitUnicodeString(&szDevName, VBOXGUEST_DEVICE_NAME_NT);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync PDEVICE_OBJECT pDeviceObject = NULL;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &szDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync if (NT_SUCCESS(rc))
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync {
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: Device created\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync UNICODE_STRING DosName;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync rc = IoCreateSymbolicLink(&DosName, &szDevName);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync if (NT_SUCCESS(rc))
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync {
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: Symlink created\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /*
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Setup the device extension.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: Setting up device extension ...\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync RT_ZERO(*pDevExt);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: Device extension created\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Store a reference to ourself. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync pDevExt->pDeviceObject = pDeviceObject;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Store bus and slot number we've queried before. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync pDevExt->busNumber = uBusNumber;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync pDevExt->slotNumber = SlotNumber.u.AsULONG;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync rc = hlpRegisterBugCheckCallback(pDevExt);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync#endif
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync /* Do the actual VBox init ... */
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if (NT_SUCCESS(rc))
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync {
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync rc = vbgdNtInit(pDrvObj, pDeviceObject, pRegPath);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if (NT_SUCCESS(rc))
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync {
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync return rc;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* bail out */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync IoDeleteSymbolicLink(&DosName);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync else
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: IoCreateSymbolicLink failed with rc = %#x\n", rc));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync IoDeleteDevice(pDeviceObject);
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync else
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: IoCreateDevice failed with rc = %#x\n", rc));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4CreateDevice: Returning rc = 0x%x\n", rc));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync return rc;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync}
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync/**
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * Helper function to handle the PCI device lookup.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @returns NT status code.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pulBusNumber Where to return the bus number on success.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * @param pSlotNumber Where to return the slot number on success.
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsyncstatic NTSTATUS vbgdNt4FindPciDevice(PULONG pulBusNumber, PPCI_SLOT_NUMBER pSlotNumber)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync{
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4FindPciDevice\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync PCI_SLOT_NUMBER SlotNumber;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync SlotNumber.u.AsULONG = 0;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Scan each bus. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync for (ULONG ulBusNumber = 0; ulBusNumber < PCI_MAX_BUSES; ulBusNumber++)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync {
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Scan each device. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync for (ULONG deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync {
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync SlotNumber.u.bits.DeviceNumber = deviceNumber;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Scan each function (not really required...). */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync for (ULONG functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync {
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync SlotNumber.u.bits.FunctionNumber = functionNumber;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Have a look at what's in this slot. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync PCI_COMMON_CONFIG PciData;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync if (!HalGetBusData(PCIConfiguration, ulBusNumber, SlotNumber.u.AsULONG, &PciData, sizeof(ULONG)))
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync {
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* No such bus, we're done with it. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync deviceNumber = PCI_MAX_DEVICES;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync break;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync if (PciData.VendorID == PCI_INVALID_VENDORID)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* We have to proceed to the next function. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync continue;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Check if it's another device. */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync if ( PciData.VendorID != VMMDEV_VENDORID
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync || PciData.DeviceID != VMMDEV_DEVICEID)
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync continue;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Hooray, we've found it! */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync Log(("VBoxGuest::vbgdNt4FindPciDevice: Device found!\n"));
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *pulBusNumber = ulBusNumber;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync *pSlotNumber = SlotNumber;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync return STATUS_SUCCESS;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync }
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync return STATUS_DEVICE_DOES_NOT_EXIST;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync}
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync