VBoxGuest-win-pnp.cpp revision 485e602154df33e5466e0dcca16d8f97914ce41d
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/** @file
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * VBoxGuest-win-pnp - Windows Plug'n'Play specifics.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Copyright (C) 2010 Oracle Corporation
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * available from http://www.virtualbox.org. This file is free software;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * General Public License (GPL) as published by the Free Software
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/*******************************************************************************
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync* Header Files *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync*******************************************************************************/
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#include "VBoxGuest-win.h"
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#include "VBoxGuestInternal.h"
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#include <VBox/err.h>
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#include <VBox/log.h>
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#include <VBox/version.h>
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#include <VBox/VBoxGuestLib.h>
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/*******************************************************************************
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync* Defined Constants And Macros *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync*******************************************************************************/
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncextern winVersion_t g_winVersion;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncRT_C_DECLS_BEGIN
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncstatic NTSTATUS vboxguestwinSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pIrp, BOOLEAN fStrict);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncstatic NTSTATUS vboxguestwinPnPIrpComplete(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncstatic VOID vboxguestwinShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncRT_C_DECLS_END
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#ifdef ALLOC_PRAGMA
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#pragma alloc_text (PAGE, vboxguestwinPnP)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#pragma alloc_text (PAGE, vboxguestwinPower)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#pragma alloc_text (PAGE, vboxguestwinSendIrpSynchronously)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#pragma alloc_text (PAGE, vboxguestwinShowDeviceResources)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#endif
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/* Reenable logging, this was #undef'ed on iprt/log.h for RING0. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#define LOG_ENABLED
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/*******************************************************************************
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync* Internal Functions *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync*******************************************************************************/
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/**
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Irp completion routine for PnP Irps we send.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pDevObj Device object.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pIrp Request packet.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param event Semaphore.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @return NT status code
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncstatic NTSTATUS vboxguestwinPnpIrpComplete(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync{
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync KeSetEvent(pEvent, 0, FALSE);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync return STATUS_MORE_PROCESSING_REQUIRED;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync}
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/**
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Helper to send a PnP IRP and wait until it's done.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pDevObj Device object.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pIrp Request packet.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param fStrict When set, returns an error if the IRP gives an error.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @return NT status code
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncstatic NTSTATUS vboxguestwinSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pIrp, BOOLEAN fStrict)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync{
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync KEVENT event;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync KeInitializeEvent(&event, SynchronizationEvent, FALSE);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoCopyCurrentIrpStackLocationToNext(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoSetCompletionRoutine(pIrp, (PIO_COMPLETION_ROUTINE)vboxguestwinPnpIrpComplete,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync &event, TRUE, TRUE, TRUE);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync NTSTATUS rc = IoCallDriver(pDevObj, pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (rc == STATUS_PENDING)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync rc = pIrp->IoStatus.Status;
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync }
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (!fStrict
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync && (rc == STATUS_NOT_SUPPORTED || rc == STATUS_INVALID_DEVICE_REQUEST))
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync rc = STATUS_SUCCESS;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinSendIrpSynchronously: Returning 0x%x\n", rc));
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync return rc;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync}
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync/**
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync * PnP Request handler.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pDevObj Device object.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pIrp Request packet.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
87c5113417e917cdf64545d4f8e0a27047cea783vboxsyncNTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync{
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#ifdef LOG_ENABLED
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync static char* aszFnctName[] =
dc45a8f3e936581748c248e00ce572cfe3ea331evboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_START_DEVICE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_REMOVE_DEVICE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_REMOVE_DEVICE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_CANCEL_REMOVE_DEVICE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_STOP_DEVICE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_STOP_DEVICE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_CANCEL_STOP_DEVICE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_DEVICE_RELATIONS",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_INTERFACE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_CAPABILITIES",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_RESOURCES",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_DEVICE_TEXT",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_READ_CONFIG",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_WRITE_CONFIG",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_EJECT",
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync "IRP_MN_SET_LOCK",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_ID",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_PNP_DEVICE_STATE",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_QUERY_BUS_INFORMATION",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_DEVICE_USAGE_NOTIFICATION",
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "IRP_MN_SURPRISE_REMOVAL",
87c5113417e917cdf64545d4f8e0a27047cea783vboxsync };
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: MinorFunction: %s\n",
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync pStack->MinorFunction < (sizeof(aszFnctName) / sizeof(aszFnctName[0]))
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync ? aszFnctName[pStack->MinorFunction]
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync : "Unknown"));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync#endif
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync NTSTATUS rc = STATUS_SUCCESS;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync switch (pStack->MinorFunction)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case IRP_MN_START_DEVICE:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* This must be handled first by the lower driver. */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync if ( NT_SUCCESS(rc)
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync && NT_SUCCESS(pIrp->IoStatus.Status))
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE: pStack->Parameters.StartDevice.AllocatedResources = %p\n",
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync pStack->Parameters.StartDevice.AllocatedResources));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync if (!pStack->Parameters.StartDevice.AllocatedResources)
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE: No resources, pDevExt = %p, nextLowerDriver = %p!\n",
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync pDevExt, pDevExt ? pDevExt->win.s.pNextLowerDriver : NULL));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync rc = STATUS_UNSUCCESSFUL;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync else
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync rc = vboxguestwinInit(pDevObj, pIrp);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync if (NT_ERROR(rc))
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: START_DEVICE: Error: rc = 0x%x\n", rc));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* Need to unmap memory in case of errors ... */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync vboxguestwinUnmapVMMDevMemory(pDevExt);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync break;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync case IRP_MN_CANCEL_REMOVE_DEVICE:
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: CANCEL_REMOVE_DEVICE\n"));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* This must be handled first by the lower driver. */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync if (NT_SUCCESS(rc) && pDevExt->win.s.devState == PENDINGREMOVE)
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* Return to the state prior to receiving the IRP_MN_QUERY_REMOVE_DEVICE request. */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync pDevExt->win.s.devState = pDevExt->win.s.prevDevState;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* Complete the IRP. */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync break;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync case IRP_MN_SURPRISE_REMOVAL:
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: IRP_MN_SURPRISE_REMOVAL\n"));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync VBOXGUEST_UPDATE_DEVSTATE(pDevExt, SURPRISEREMOVED);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* Do nothing here actually. Cleanup is done in IRP_MN_REMOVE_DEVICE.
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync * This request is not expected for VBoxGuest.
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync LogRel(("VBoxGuest: unexpected device removal\n"));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* Pass to the lower driver. */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync pIrp->IoStatus.Status = STATUS_SUCCESS;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync IoSkipCurrentIrpStackLocation(pIrp);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* Do not complete the IRP. */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync return rc;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync case IRP_MN_QUERY_REMOVE_DEVICE:
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: QUERY_REMOVE_DEVICE\n"));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync#ifdef VBOX_REBOOT_ON_UNINSTALL
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n"));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync rc = STATUS_UNSUCCESSFUL;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync#endif /* VBOX_REBOOT_ON_UNINSTALL */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync if (NT_SUCCESS(rc))
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync VBOXGUEST_UPDATE_DEVSTATE(pDevExt, PENDINGREMOVE);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* This IRP passed down to lower driver. */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync pIrp->IoStatus.Status = STATUS_SUCCESS;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync IoSkipCurrentIrpStackLocation(pIrp);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* we must not do anything here after doing IoSkip & CallDriver
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync * since the driver below us will complete (or already have completed) the IRP.
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync * I.e. just return the status we got from IoCallDriver */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync return rc;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync /* Complete the IRP on failure. */
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync break;
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync }
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync case IRP_MN_REMOVE_DEVICE:
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync {
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: REMOVE_DEVICE\n"));
50671c30431539dd7d6ff6a5f2ceb6c9f9f471b2vboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync VBOXGUEST_UPDATE_DEVSTATE(pDevExt, REMOVED);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Free hardware resources. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* @todo this should actually free I/O ports, interrupts, etc. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync rc = vboxguestwinCleanup(pDevObj);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: vboxguestwinCleanup rc = 0x%08X\n", rc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /*
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * We need to send the remove down the stack before we detach,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * but we don't need to wait for the completion of this operation
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * (and to register a completion routine).
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pIrp->IoStatus.Status = STATUS_SUCCESS;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoSkipCurrentIrpStackLocation(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoDetachDevice(pDevExt->win.s.pNextLowerDriver);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Removing device ...\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Destroy device extension and clean up everything else. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync VBoxGuestDeleteDevExt(pDevExt);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Remove DOS device + symbolic link. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync UNICODE_STRING win32Name;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoDeleteSymbolicLink(&win32Name);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Deleting device ...\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Last action: Delete our device! pDevObj is *not* failed
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * anymore after this call! */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoDeleteDevice(pDevObj);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Device removed!\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Propagating rc from IoCallDriver. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync return rc; /* Make sure that we don't do anything below here anymore! */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case IRP_MN_CANCEL_STOP_DEVICE:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: CANCEL_STOP_DEVICE\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* This must be handled first by the lower driver. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (NT_SUCCESS(rc) && pDevExt->win.s.devState == PENDINGSTOP)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Return to the state prior to receiving the IRP_MN_QUERY_STOP_DEVICE request. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pDevExt->win.s.devState = pDevExt->win.s.prevDevState;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Complete the IRP. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case IRP_MN_QUERY_STOP_DEVICE:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: QUERY_STOP_DEVICE\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#ifdef VBOX_REBOOT_ON_UNINSTALL
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_STOP_DEVICE: Device cannot be stopped without a reboot!\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync#endif /* VBOX_REBOOT_ON_UNINSTALL */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (NT_SUCCESS(rc))
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync VBOXGUEST_UPDATE_DEVSTATE(pDevExt, PENDINGSTOP);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* This IRP passed down to lower driver. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pIrp->IoStatus.Status = STATUS_SUCCESS;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoSkipCurrentIrpStackLocation(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* we must not do anything here after doing IoSkip & CallDriver
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * since the driver below us will complete (or already have completed) the IRP.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * I.e. just return the status we got from IoCallDriver */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync return rc;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Complete the IRP on failure. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case IRP_MN_STOP_DEVICE:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: STOP_DEVICE\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync VBOXGUEST_UPDATE_DEVSTATE(pDevExt, STOPPED);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Free hardware resources. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* @todo this should actually free I/O ports, interrupts, etc. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync rc = vboxguestwinCleanup(pDevObj);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: STOP_DEVICE: cleaning up, rc = 0x%x\n", rc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Pass to the lower driver. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pIrp->IoStatus.Status = STATUS_SUCCESS;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoSkipCurrentIrpStackLocation(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync return rc;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync default:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoSkipCurrentIrpStackLocation(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync return rc;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pIrp->IoStatus.Status = rc;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoCompleteRequest(pIrp, IO_NO_INCREMENT);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPnp: Returning with rc = 0x%x\n", rc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync return rc;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync}
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/**
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Handle the power completion event.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @returns NT status code.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pDevObj Targetted device object.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pIrp IO request packet.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pContext Context value passed to IoSetCompletionRoutine in VBoxGuestPower.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncNTSTATUS vboxguestwinPowerComplete(IN PDEVICE_OBJECT pDevObj,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IN PIRP pIrp, IN PVOID pContext)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync{
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync PIO_STACK_LOCATION pIrpSp;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pContext;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync ASSERT(pDevExt);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync ASSERT(pDevExt->signature == DEVICE_EXTENSION_SIGNATURE);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (pIrpSp)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync ASSERT(pIrpSp->MajorFunction == IRP_MJ_POWER);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (NT_SUCCESS(pIrp->IoStatus.Status))
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync switch (pIrpSp->MinorFunction)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case IRP_MN_SET_POWER:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync switch (pIrpSp->Parameters.Power.Type)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case DevicePowerState:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync switch (pIrpSp->Parameters.Power.State.DeviceState)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case PowerDeviceD0:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync return STATUS_SUCCESS;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync}
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync/**
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Handle the Power requests.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync *
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @returns NT status code
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pDevObj device object
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * @param pIrp IRP
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsyncNTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync{
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync POWER_STATE_TYPE powerType;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync POWER_STATE powerState;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync POWER_ACTION powerAction;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync powerType = pStack->Parameters.Power.Type;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync powerAction = pStack->Parameters.Power.ShutdownType;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync powerState = pStack->Parameters.Power.State;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync switch (pStack->MinorFunction)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case IRP_MN_SET_POWER:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower: IRP_MN_SET_POWER, type= %d\n", powerType));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync switch (powerType)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case SystemPowerState:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower: SystemPowerState, action = %d, state = %d\n", powerAction, powerState));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync switch (powerAction)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case PowerActionSleep:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* System now is in a working state. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (powerState.SystemState == PowerSystemWorking)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if ( pDevExt
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync && pDevExt->win.s.LastSystemPowerAction == PowerActionHibernate)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower: Returning from hibernation!\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync int rc = VBoxGuestReinitDevExtAfterHibernation(pDevExt, vboxguestwinVersionToOSType(g_winVersion));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (RT_FAILURE(rc))
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower: Cannot re-init VMMDev chain, rc = %d!\n", rc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case PowerActionShutdownReset:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower: Power action reset!\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Tell the VMM that we no longer support mouse pointer integration. */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync VMMDevReqMouseStatus *pReq = NULL;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof (VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (RT_SUCCESS(vrc))
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pReq->mouseFeatures = 0;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pReq->pointerXPos = 0;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pReq->pointerYPos = 0;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync vrc = VbglGRPerform(&pReq->header);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (RT_FAILURE(vrc))
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::PowerStateRequest: error communicating new power status to VMMDev. "
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "vrc = %Rrc\n", vrc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync VbglGRFree(&pReq->header);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* Don't do any cleanup here; there might be still coming in some IOCtls after we got this
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * power action and would assert/crash when we already cleaned up all the stuff! */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case PowerActionShutdown:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case PowerActionShutdownOff:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower: Power action shutdown!\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (powerState.SystemState >= PowerSystemShutdown)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower: Telling the VMMDev to close the VM ...\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync VMMDevPowerStateRequest *pReq = pDevExt->win.s.pPowerStateRequest;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync int vrc = VERR_NOT_IMPLEMENTED;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (pReq)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pReq->header.requestType = VMMDevReq_SetPowerStatus;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pReq->powerState = VMMDevPowerState_PowerOff;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync vrc = VbglGRPerform(&pReq->header);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (RT_FAILURE(vrc))
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync {
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::PowerStateRequest: Error communicating new power status to VMMDev. "
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync "vrc = %Rrc\n", vrc));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /* No need to do cleanup here; at this point we should've been
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * turned off by VMMDev already! */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync case PowerActionHibernate:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync Log(("VBoxGuest::vboxguestwinGuestPower: Power action hibernate!\n"));
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /*
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Save the current system power action for later use.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * This becomes handy when we return from hibernation for example.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync if (pDevExt)
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync pDevExt->win.s.LastSystemPowerAction = powerAction;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync default:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync default:
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync break;
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync }
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /*
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Whether we are completing or relaying this power IRP,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * we must call PoStartNextPowerIrp.
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync PoStartNextPowerIrp(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync /*
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * Send the IRP down the driver stack,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync * using PoCallDriver (not IoCallDriver, as for non-power irps).
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync */
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoCopyCurrentIrpStackLocationToNext(pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync IoSetCompletionRoutine(pIrp,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync vboxguestwinPowerComplete,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync (PVOID)pDevExt,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync TRUE,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync TRUE,
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync TRUE);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync return PoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync}
9888fffcfbe2d41dce14a1249b12cb88cc9b149fvboxsync