📄 pnp.c
字号:
/*++
Copyright (c) 2004 Chingachguk & Denger2k All rights reserved.
Module Name:
PNP.C
Abstract:
This module handles plug & play calls for the virtual USB bus controller FDO.
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include <ntddk.h>
#include <initguid.h>
#include ".\Include\driver.h"
#include "vusb.h"
#include "stdio.h"
#include <wdmguid.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, Bus_AddDevice)
#pragma alloc_text (PAGE, Bus_PnP)
#pragma alloc_text (PAGE, Bus_PlugInDevice)
#pragma alloc_text (PAGE, Bus_InitializePdo)
#pragma alloc_text (PAGE, Bus_UnPlugDevice)
#pragma alloc_text (PAGE, Bus_DestroyPdo)
#pragma alloc_text (PAGE, Bus_RemoveFdo)
#pragma alloc_text (PAGE, Bus_FDO_PnP)
#pragma alloc_text (PAGE, Bus_StartFdo)
#pragma alloc_text (PAGE, Bus_SendIrpSynchronously)
#endif
NTSTATUS
Bus_AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description.
Our virtual USB bus has been found. Attach our FDO to it.
Allocate any required resources. Set things up.
And be prepared for the ``start device''
Arguments:
DriverObject - pointer to driver object.
PhysicalDeviceObject - Device object representing the bus to which we
will attach a new FDO.
--*/
{
NTSTATUS status;
PDEVICE_OBJECT deviceObject;
PFDO_DEVICE_DATA deviceData;
#if DBG
PWCHAR deviceName;
ULONG nameLength;
#endif
PAGED_CODE ();
Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Add Device: 0x%x\n",
PhysicalDeviceObject));
status = IoCreateDevice (
DriverObject, // our driver object
sizeof (FDO_DEVICE_DATA), // device object extension size
NULL, // FDOs do not have names
FILE_DEVICE_BUS_EXTENDER, // We are a bus
FILE_DEVICE_SECURE_OPEN, //
TRUE, // our FDO is exclusive
&deviceObject); // The device object created
if (!NT_SUCCESS (status))
{
return status;
}
deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA));
//
// Set the initial state of the FDO
//
INITIALIZE_PNP_STATE(deviceData);
deviceData->DebugLevel = VUsbDebugLevel;
deviceData->IsFDO = TRUE;
deviceData->Self = deviceObject;
ExInitializeFastMutex (&deviceData->Mutex);
InitializeListHead (&deviceData->ListOfPDOs);
// Set the PDO for use with PlugPlay functions
deviceData->UnderlyingPDO = PhysicalDeviceObject;
//
// Set the initial powerstate of the FDO
//
deviceData->DevicePowerState = PowerDeviceUnspecified;
deviceData->SystemPowerState = PowerSystemWorking;
//
// Biased to 1. Transition to zero during remove device
// means IO is finished. Transition to 1 means the device
// can be stopped.
//
deviceData->OutstandingIO = 1;
//
// Initialize the remove event to Not-Signaled. This event
// will be set when the OutstandingIO will become 0.
//
KeInitializeEvent(&deviceData->RemoveEvent,
SynchronizationEvent,
FALSE);
//
// Initialize the stop event to Signaled:
// there are no Irps that prevent the device from being
// stopped. This event will be set when the OutstandingIO
// will become 0.
//
KeInitializeEvent(&deviceData->StopEvent,
SynchronizationEvent,
TRUE);
deviceObject->Flags |= DO_POWER_PAGABLE;
//
// Tell the Plug & Play system that this device will need a
// device interface.
//
status = IoRegisterDeviceInterface (
PhysicalDeviceObject,
(LPGUID) &GUID_DEVINTERFACE_VUSB,
NULL,
&deviceData->InterfaceName);
if (!NT_SUCCESS (status)) {
Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
("AddDevice: IoRegisterDeviceInterface failed (%x)", status));
IoDeleteDevice (deviceObject);
return status;
}
//
// Attach our filter driver to the device stack.
// The return value of IoAttachDeviceToDeviceStack is the top of the
// attachment chain. This is where all the IRPs should be routed.
//
deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack (
deviceObject,
PhysicalDeviceObject);
if(NULL == deviceData->NextLowerDriver) {
IoDeleteDevice(deviceObject);
return STATUS_NO_SUCH_DEVICE;
}
#if DBG
//
// We will demonstrate here the step to retrieve the name of the PDO
//
status = IoGetDeviceProperty (PhysicalDeviceObject,
DevicePropertyPhysicalDeviceObjectName,
0,
NULL,
&nameLength);
if (status != STATUS_BUFFER_TOO_SMALL)
{
Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
("AddDevice:IoGDP failed (0x%x)\n", status));
goto Error;
}
deviceName = ExAllocatePoolWithTag (NonPagedPool,
nameLength, VUSB_POOL_TAG);
if (NULL == deviceName) {
Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength));
status = STATUS_INSUFFICIENT_RESOURCES;
goto Error;
}
status = IoGetDeviceProperty (PhysicalDeviceObject,
DevicePropertyPhysicalDeviceObjectName,
nameLength,
deviceName,
&nameLength);
if (!NT_SUCCESS (status)) {
Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
("AddDevice:IoGDP(2) failed (0x%x)", status));
goto Error;
}
Bus_KdPrint (deviceData, BUS_DBG_SS_TRACE,
("AddDevice: %x to %x->%x (%ws) \n",
deviceObject,
deviceData->NextLowerDriver,
PhysicalDeviceObject,
deviceName));
ExFreePool(deviceName);
#endif
//
// Set "Auto insert all dumps at startup" flag
//
#ifdef DEBUG_FULL
deviceData->isAutoInsert=0;
#else
deviceData->isAutoInsert=INSERT_ALL_KEYS_ON_STARTUP;
#endif
//
// We are done with initializing, so let's indicate that and return.
// This should be the final step in the AddDevice process.
//
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// Invalidate device relations, so we can
// scan registry and add HASP keys dumps
//
IoInvalidateDeviceRelations (PhysicalDeviceObject, BusRelations);
return status;
#if DBG
Error:
IoDetachDevice (deviceData->NextLowerDriver);
IoDeleteDevice (deviceObject);
return status;
#endif
}
NTSTATUS
Bus_PnP (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handles PnP Irps sent to both FDO and child PDOs.
Arguments:
DeviceObject - Pointer to deviceobject
Irp - Pointer to a PnP Irp.
Return Value:
NT Status is returned.
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
PCOMMON_DEVICE_DATA commonData;
PAGED_CODE ();
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT (IRP_MJ_PNP == irpStack->MajorFunction);
commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
//
// If the device has been removed, the driver should
// not pass the IRP down to the next lower driver.
//
if (commonData->DevicePnPState == Deleted) {
Irp->IoStatus.Status = status = STATUS_DELETE_PENDING;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
if (commonData->IsFDO) {
Bus_KdPrint (commonData, BUS_DBG_PNP_TRACE,
("FDO %s IRP:0x%x\n",
PnPMinorFunctionString(irpStack->MinorFunction),
Irp));
//
// Request is for the bus FDO
//
status = Bus_FDO_PnP (
DeviceObject,
Irp,
irpStack,
(PFDO_DEVICE_DATA) commonData);
} else {
Bus_KdPrint (commonData, BUS_DBG_PNP_TRACE,
("PDO %s IRP: 0x%x\n",
PnPMinorFunctionString(irpStack->MinorFunction),
Irp));
//
// Request is for the child PDO.
//
status = Bus_PDO_PnP (
DeviceObject,
Irp,
irpStack,
(PPDO_DEVICE_DATA) commonData);
}
return status;
}
NTSTATUS
Bus_FDO_PnP (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack,
IN PFDO_DEVICE_DATA DeviceData
)
/*++
Routine Description:
Handle requests from the Plug & Play system for the BUS itself
--*/
{
NTSTATUS status;
ULONG length, prevcount, numPdosPresent;
PLIST_ENTRY entry, listHead, nextEntry;
PPDO_DEVICE_DATA pdoData;
PFDO_DEVICE_DATA fdoData;
PDEVICE_RELATIONS relations, oldRelations;
PAGED_CODE ();
Bus_IncIoCount (DeviceData);
switch (IrpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
//
// Send the Irp down and wait for it to come back.
// Do not touch the hardware until then.
//
status = Bus_SendIrpSynchronously (DeviceData->NextLowerDriver, Irp);
if (NT_SUCCESS(status)) {
//
// Initialize your device with the resources provided
// by the PnP manager to your device.
//
status = Bus_StartFdo (DeviceData, Irp);
}
//
// We must now complete the IRP, since we stopped it in the
// completion routine with MORE_PROCESSING_REQUIRED.
//
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
Bus_DecIoCount (DeviceData);
return status;
case IRP_MN_QUERY_STOP_DEVICE:
//
// The PnP manager is trying to stop the device
// for resource rebalancing. Fail this now if you
// cannot stop the device in response to STOP_DEVICE.
//
SET_NEW_PNP_STATE(DeviceData, StopPending);
Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP.
break;
case IRP_MN_CANCEL_STOP_DEVICE:
//
// The PnP Manager sends this IRP, at some point after an
// IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a
// device that the device will not be stopped for
// resource reconfiguration.
//
//
// First check to see whether you have received cancel-stop
// without first receiving a query-stop. This could happen if
// someone above us fails a query-stop and passes down the subsequent
// cancel-stop.
//
if(StopPending == DeviceData->DevicePnPState)
{
//
// We did receive a query-stop, so restore.
//
RESTORE_PREVIOUS_PNP_STATE(DeviceData);
ASSERT(DeviceData->DevicePnPState == Started);
}
Irp->IoStatus.Status = STATUS_SUCCESS; // We must not fail the IRP.
break;
case IRP_MN_STOP_DEVICE:
//
// Stop device means that the resources given during Start device
// are now revoked. Note: You must not fail this Irp.
// But before you relieve resources make sure there are no I/O in
// progress. Wait for the existing ones to be finished.
// To do that, first we will decrement this very operation.
// When the counter goes to 1, Stop event is set.
//
Bus_DecIoCount(DeviceData);
KeWaitForSingleObject(
&DeviceData->StopEvent,
Executive, // Waiting reason of a driver
KernelMode, // Waiting in kernel mode
FALSE, // No allert
NULL); // No timeout
//
// Increment the counter back because this IRP has to
// be sent down to the lower stack.
//
Bus_IncIoCount (DeviceData);
//
// Free resources given by start device.
//
SET_NEW_PNP_STATE(DeviceData, Stopped);
//
// We don't need a completion routine so fire and forget.
//
// Set the current stack location to the next stack location and
// call the next device object.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
//
// If we were to fail this call then we would need to complete the
// IRP here. Since we are not, set the status to SUCCESS and
// call the next driver.
//
SET_NEW_PNP_STATE(DeviceData, RemovePending);
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
//
// If we were to fail this call then we would need to complete the
// IRP here. Since we are not, set the status to SUCCESS and
// call the next driver.
//
//
// First check to see whether you have received cancel-remove
// without first receiving a query-remove. This could happen if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -