📄 pnp.c
字号:
DPRINT(("HandleQueryCapabilities - begins\n"));
//
// initialize variables
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
//
// We will provide here an example of an IRP that is processed
// both on its way down and on its way up: there might be no need for
// a function driver process this Irp (the bus driver will do that).
// The driver will wait for the lower drivers (the bus driver among
// them) to process this IRP, then it processes it again.
//
if(pdc->Version < 1 || pdc->Size < sizeof(DEVICE_CAPABILITIES)) {
DPRINT(("HandleQueryCapabilities::request failed\n"));
ntS = STATUS_UNSUCCESSFUL;
return ntS;
}
//
// Add in the SurpriseRemovalOK bit before passing it down.
//
pdc->SurpriseRemovalOK = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, IrpCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
if(ntS == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
ntS = Irp->IoStatus.Status;
}
//
// initialize PowerDownLevel to disabled
//
DevExt->PowerDownLevel = PowerDeviceUnspecified;
if(NT_SUCCESS(ntS)) {
DevExt->DeviceCapabilities = *pdc;
for (i = PowerSystemSleeping1; i <= PowerSystemSleeping3; i++) {
if(DevExt->DeviceCapabilities.DeviceState[i] < PowerDeviceD3) {
DevExt->PowerDownLevel = DevExt->DeviceCapabilities.DeviceState[i];
}
}
//
// since its safe to surprise-remove this device, we shall
// set the SurpriseRemoveOK flag to supress any dialog to
// user.
//
pdc->SurpriseRemovalOK = 1;
}
if (DevExt->PowerDownLevel == PowerDeviceUnspecified ||
DevExt->PowerDownLevel <= PowerDeviceD0)
{
DevExt->PowerDownLevel = PowerDeviceD2;
}
DPRINT(("HandleQueryCapabilities - ends\n"));
return ntS;
}
/*********************************************************************
*
* ProcessQueuedRequests
*
* Routine Description:
* Remove and process the entries in the queue. If this routine is called
* when processing IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE
* or IRP_MN_START_DEVICE, the requests are passed to the next lower driver.
* If the routine is called when IRP_MN_REMOVE_DEVICE is received, the IRPs
* are complete with STATUS_DELETE_PENDING
*
* Arguments:
* DeviceExtension - pointer to device extension
*/
VOID ProcessQueuedRequests( IN OUT DEVICE_EXTENSION * DeviceExtension) {
KIRQL oldIrql;
IRP * nextIrp,
* cancelledIrp;
VOID * cancelRoutine;
LIST_ENTRY cancelledIrpList;
PLIST_ENTRY listEntry;
DPRINT(("<usb> -> ProcessQueuedRequests\n"));
//
// initialize variables
//
cancelRoutine = NULL;
InitializeListHead(&cancelledIrpList);
//
// 1. dequeue the entries in the queue
// 2. reset the cancel routine
// 3. process them
// 3a. if the device is active, send them down
// 3b. else complete with STATUS_DELETE_PENDING
//
while(1) {
KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
if(IsListEmpty(&DeviceExtension->NewRequestsQueue)) {
KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
break;
}
//
// Remove a request from the queue
//
listEntry = RemoveHeadList(&DeviceExtension->NewRequestsQueue);
nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
//
// set the cancel routine to NULL
//
cancelRoutine = IoSetCancelRoutine(nextIrp, NULL);
//
// check if its already cancelled
//
if (nextIrp->Cancel) {
if (cancelRoutine) {
//
// the cancel routine for this IRP hasnt been called yet
// so queue the IRP in the cancelledIrp list and complete
// after releasing the lock
//
InsertTailList(&cancelledIrpList, listEntry);
} else {
//
// the cancel routine has run
// it must be waiting to hold the queue lock
// so initialize the IRPs listEntry
//
InitializeListHead(listEntry);
}
KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
} else {
KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
if(FailRequests == DeviceExtension->QueueState) {
nextIrp->IoStatus.Information = 0;
nextIrp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
} else {
DPRINT(("ProcessQueuedRequests::"));
DevIoIncrement(DeviceExtension);
IoSkipCurrentIrpStackLocation(nextIrp);
IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
DPRINT(("ProcessQueuedRequests::"));
DevIoDecrement(DeviceExtension);
}
}
} // while loop
//
// walk through the cancelledIrp list and cancel them
//
while(!IsListEmpty(&cancelledIrpList)) {
PLIST_ENTRY listEntry = RemoveHeadList(&cancelledIrpList);
cancelledIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
cancelledIrp->IoStatus.Information = 0;
IoCompleteRequest(cancelledIrp, IO_NO_INCREMENT);
}
DPRINT(("<usb> <- ProcessQueuedRequests\n"));
return;
}
/*********************************************************************
*
* BulkUsb_GetRegistryDword
*
* Routine Description:
*
* This routine reads the specified reqistry value.
*
* Arguments:
*
* RegPath - registry path
* ValueName - property to be fetched from the registry
* Value - corresponding value read from the registry.
*
* Return Value:
*
* NT status value
*/
NTSTATUS BulkUsb_GetRegistryDword(IN PWCHAR RegPath, IN PWCHAR ValueName, IN OUT PULONG Value ) {
ULONG defaultData;
WCHAR buffer[MAXIMUM_FILENAME_LENGTH];
NTSTATUS ntS;
UNICODE_STRING regPath;
RTL_QUERY_REGISTRY_TABLE paramTable[2];
DPRINT(("BulkUsb_GetRegistryDword - begins\n"));
regPath.Length = 0;
regPath.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
regPath.Buffer = buffer;
RtlZeroMemory(regPath.Buffer, regPath.MaximumLength);
RtlMoveMemory(regPath.Buffer, RegPath, wcslen(RegPath) * sizeof(WCHAR));
RtlZeroMemory(paramTable, sizeof(paramTable));
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[0].Name = ValueName;
paramTable[0].EntryContext = Value;
paramTable[0].DefaultType = REG_DWORD;
paramTable[0].DefaultData = &defaultData;
paramTable[0].DefaultLength = sizeof(ULONG);
ntS = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, regPath.Buffer, paramTable, NULL,NULL);
if(NT_SUCCESS(ntS)) {
DPRINT(("success Value = %X\n", *Value));
return STATUS_SUCCESS;
} else {
*Value = 0;
return STATUS_UNSUCCESSFUL;
}
}
/*********************************************************************
*
* _CanDeviceSuspend
*
* Routine Description:
*
* This is the routine where we check if the device
* can selectively suspend.
*
* Arguments:
* DeviceExtension - pointer to device extension
*
* Return Value:
* TRUE - if the device can suspend
* FALSE - otherwise.
*
*/
#if 0
static BOOLEAN _CanDeviceSuspend(IN DEVICE_EXTENSION * DeviceExtension ) {
DPRINT(("CanDeviceSuspend\n"));
if((DeviceExtension->OpenHandleCount == 0) && (DeviceExtension->OutStandingIO == 1)) {
return TRUE;
} else {
return FALSE;
}
}
#endif
/*********************************************************************
*
* Routine Description
* sends an abort pipe request for open pipes.
*
* Arguments:
* DeviceObject - pointer to device object
*
* Return Value:
* NT status value
*
*/
NTSTATUS BulkUsb_AbortPipes(IN PDEVICE_OBJECT DeviceObject) {
PURB urb;
ULONG i;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
PUSB_PIPE_CONTEXT pipeContext;
PUSBD_INTERFACE_INFORMATION interfaceInfo;
//
// initialize variables
//
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
pipeContext = DevExt->PipeContext;
interfaceInfo = DevExt->UsbInterface;
DPRINT(("BulkUsb_AbortPipes - begins\n"));
if(interfaceInfo == NULL || pipeContext == NULL) {
return STATUS_SUCCESS;
}
for(i=0; i<interfaceInfo->NumberOfPipes; i++) {
if(pipeContext[i].PipeOpen) {
DPRINT(("Aborting open pipe %d\n", i));
urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
if(urb) {
urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
urb->UrbPipeRequest.PipeHandle = interfaceInfo->Pipes[i].PipeHandle;
ntS = CallUSBD(DeviceObject, urb);
ExFreePool(urb);
} else {
DPRINT(("Failed to alloc memory for urb\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
return ntS;
}
if(NT_SUCCESS(ntS)) {
pipeContext[i].PipeOpen = FALSE;
}
}
}
DPRINT(("BulkUsb_AbortPipes - ends\n"));
return STATUS_SUCCESS;
}
/*********************************************************************
*
* Routine Description:
This routine bumps up the I/O count.
This routine is typically invoked when any of the
dispatch routines handle new irps for the driver.
Arguments:
DeviceExtension - pointer to device extension
Return Value:
new value
--*/
LONG DevIoIncrement(IN OUT DEVICE_EXTENSION * DeviceExtension) {
LONG result = 0;
KIRQL oldIrql;
KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
result = InterlockedIncrement(&DeviceExtension->OutStandingIO);
//
// when OutStandingIO bumps from 1 to 2, clear the StopEvent
//
if(result == 2) {
KeClearEvent(&DeviceExtension->StopEvent);
}
KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
//DPRINT(("DevIoIncrement::%d\n", result));
return result;
}
/*********************************************************************
*
* DevIoDecrement
*
* Routine Description:
*
* This routine decrements the outstanding I/O count
* This is typically invoked after the dispatch routine
* has finished processing the irp.
*
* Arguments:
* DeviceExtension - pointer to device extension
*
* Return Value:
* new value
*
*/
LONG DevIoDecrement(IN OUT DEVICE_EXTENSION * pDeviceExtension) {
LONG result = 0;
KIRQL oldIrql;
KeAcquireSpinLock(&pDeviceExtension->IOCountLock, &oldIrql);
result = InterlockedDecrement(&pDeviceExtension->OutStandingIO);
if(result == 1) {
KeSetEvent(&pDeviceExtension->StopEvent, IO_NO_INCREMENT, FALSE);
}
if(result == 0) {
ASSERT(Removed == pDeviceExtension->DeviceState);
KeSetEvent(&pDeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE);
}
KeReleaseSpinLock(&pDeviceExtension->IOCountLock, oldIrql);
//DPRINT(("DevIoDecrement::%d\n", result));
return result;
}
NTSTATUS BulkUsb_DispatchPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
PIO_STACK_LOCATION irpStack;
DEVICE_EXTENSION * DevExt;
NTSTATUS ntS;
DPRINT(("<usb> -> BulkUsb_DispatchPnP\n"));
irpStack = IoGetCurrentIrpStackLocation(Irp);
DevExt = DeviceObject->DeviceExtension;
if (Removed == DevExt->DeviceState) {
DPRINT(("<usb> <- BulkUsb_DispatchPnP (aerly out ... Device is removed)\n"));
return(CompleteRequest(Irp, STATUS_DELETE_PENDING, 0));
}
DevIoIncrement(DevExt);
switch(irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
DPRINT(("<usb> IRP_MN_START_DEVICE\n"));
ntS = HandleStartDevice(DeviceObject, Irp);
break;
case IRP_MN_QUERY_STOP_DEVICE:
DPRINT(("<usb> IRP_MN_QUERY_STOP_DEVICE\n"));
ntS = _CanStopDevice(DeviceObject, Irp);
if(NT_SUCCESS(ntS)) {
ntS = HandleQueryStopDevice(DeviceObject, Irp);
DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
return(ntS);
}
break;
case IRP_MN_CANCEL_STOP_DEVICE:
DPRINT(("<usb> IRP_MN_CANCEL_STOP_DEVICE\n"));
ntS = HandleCancelStopDevice(DeviceObject, Irp);
break;
case IRP_MN_STOP_DEVICE:
DPRINT(("<usb> IRP_MN_STOP_DEVICE\n"));
ntS = HandleStopDevice(DeviceObject, Irp);
DevIoDecrement(DevExt);
DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
return(ntS);
case IRP_MN_QUERY_REMOVE_DEVICE:
DPRINT(("<usb> IRP_MN_QUERY_REMOVE_DEVICE\n"));
ntS = HandleQueryRemoveDevice(DeviceObject, Irp);
DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
return(ntS);
case IRP_MN_CANCEL_REMOVE_DEVICE:
DPRINT(("<usb> IRP_MN_CANCEL_REMOVE_DEVICE\n"));
ntS = HandleCancelRemoveDevice(DeviceObject, Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
DPRINT(("<usb> IRP_MN_SURPRISE_REMOVAL\n"));
ntS = HandleSurpriseRemoval(DeviceObject, Irp);
DevIoDecrement(DevExt);
DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
return(ntS);
case IRP_MN_REMOVE_DEVICE:
DPRINT(("<usb> IRP_MN_REMOVE_DEVICE\n"));
ntS = HandleRemoveDevice(DeviceObject, Irp);
DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
return(ntS);
case IRP_MN_QUERY_CAPABILITIES:
DPRINT(("<usb> IRP_MN_QUERY_CAPABILITIES\n"));
ntS = HandleQueryCapabilities(DeviceObject, Irp);
break;
default:
DPRINT(("<usb> Dispatching unhandled PNP func: 0x%x", irpStack->MinorFunction));
IoSkipCurrentIrpStackLocation(Irp);
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
DevIoDecrement(DevExt);
DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
return(ntS);
}
CompleteRequest(Irp, ntS, 0);
DevIoDecrement(DevExt);
DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
return(ntS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -