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