📄 intpnp.c
字号:
}
VOID
ProcessQueuedRequests(
IN OUT PDEVICE_EXTENSION DeviceExtension
)
/*++
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
Return Value:
None
--*/
{
KIRQL oldIrql;
PIRP nextIrp,
cancelledIrp;
PVOID cancelRoutine;
LIST_ENTRY cancelledIrpList;
PLIST_ENTRY listEntry;
KdPrint( ("ProcessQueuedRequests - begins\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 {
PIO_STACK_LOCATION irpStack;
KdPrint( ("ProcessQueuedRequests::"));
IntUsb_IoIncrement(DeviceExtension);
IoSkipCurrentIrpStackLocation(nextIrp);
IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
KdPrint( ("ProcessQueuedRequests::"));
IntUsb_IoDecrement(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);
}
KdPrint( ("ProcessQueuedRequests - ends\n"));
return;
}
NTSTATUS
IntUsb_GetRegistryDword(
IN PWCHAR RegPath,
IN PWCHAR ValueName,
IN OUT PULONG Value
)
/*++
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
--*/
{
ULONG defaultData;
WCHAR buffer[MAXIMUM_FILENAME_LENGTH];
NTSTATUS ntStatus;
UNICODE_STRING regPath;
RTL_QUERY_REGISTRY_TABLE paramTable[2];
KdPrint( ("IntUsb_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);
ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE |
RTL_REGISTRY_OPTIONAL,
regPath.Buffer,
paramTable,
NULL,
NULL);
if(NT_SUCCESS(ntStatus)) {
KdPrint( ("success Value = %X\n", *Value));
return STATUS_SUCCESS;
}
else {
*Value = 0;
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS
IntUsb_DispatchClean(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch routine for IRP_MJ_CLEANUP
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager
Return Value:
NT status value
--*/
{
PDEVICE_EXTENSION deviceExtension;
KIRQL oldIrql;
LIST_ENTRY cleanupList;
PLIST_ENTRY thisEntry,
nextEntry,
listHead;
PIRP pendingIrp;
PIO_STACK_LOCATION pendingIrpStack,
irpStack;
NTSTATUS ntStatus;
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
InitializeListHead(&cleanupList);
KdPrint( ("IntUsb_DispatchClean::"));
IntUsb_IoIncrement(deviceExtension);
//
// acquire queue lock
//
KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);
//
// remove all Irp's that belong to input Irp's fileobject
//
listHead = &deviceExtension->NewRequestsQueue;
for(thisEntry = listHead->Flink, nextEntry = thisEntry->Flink;
thisEntry != listHead;
thisEntry = nextEntry, nextEntry = thisEntry->Flink) {
pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
pendingIrpStack = IoGetCurrentIrpStackLocation(pendingIrp);
if(irpStack->FileObject == pendingIrpStack->FileObject) {
RemoveEntryList(thisEntry);
//
// set the cancel routine to NULL
//
if(NULL == IoSetCancelRoutine(pendingIrp, NULL)) {
InitializeListHead(thisEntry);
}
else {
InsertTailList(&cleanupList, thisEntry);
}
}
}
//
// Release the spin lock
//
KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
//
// walk thru the cleanup list and cancel all the Irps
//
while(!IsListEmpty(&cleanupList)) {
//
// complete the Irp
//
thisEntry = RemoveHeadList(&cleanupList);
pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
pendingIrp->IoStatus.Information = 0;
pendingIrp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
}
CleanupReadRequestQueue(deviceExtension, STATUS_CANCELLED, irpStack->FileObject);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KdPrint( ("IntUsb_DispatchClean::"));
IntUsb_IoDecrement(deviceExtension);
return STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
// @func Cleanup cached I/O control requests
// @parm Generic.sys device extension
// @parm Status code to use in completing requests
// @parm File object for which requests are to be completed. NULL if all cached
// requests for the calling driver are to be completed.
// @comm The main purpose of this routine is to help handle an IRP_MJ_CLEANUP when
// the file handle may have been used to submit pending control requests.
VOID CleanupReadRequestQueue(PDEVICE_EXTENSION deviceExtension, NTSTATUS status, PFILE_OBJECT fop)
{ // GenericCleanupControlRequests
//if (!(pdx->Flags & GENERIC_PENDING_IOCTLS))
// return; // didn't signup for pending ioctl service!
LIST_ENTRY cancellist;
KIRQL oldirql;
PLIST_ENTRY first;
PLIST_ENTRY next;
PIRP Irp;
PIRP Irp2;
PIO_STACK_LOCATION stack;
PLIST_ENTRY current;
InitializeListHead(&cancellist);
// Create a list of IRPs that belong to the same file object
KeAcquireSpinLock(&deviceExtension->Cachelock, &oldirql);
first = &deviceExtension->Pending_IOCTL_READINT_List;
if((first->Flink != NULL) && (first != first->Flink))
{
for (next = first->Flink; next != first; )
{ // for each queued IRP
Irp = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
stack = IoGetCurrentIrpStackLocation(Irp);
// Follow the chain to the next IRP now (so that the next iteration of
// the loop is properly setup whether we dequeue this IRP or not)
current = next;
next = next->Flink;
// Skip this IRP if it's not for the same file object as the
// current IRP_MJ_CLEANUP.
if (fop && stack->FileObject != fop)
continue; // not for same file object
// Set the CancelRoutine pointer to NULL and remove the IRP from the
// queue.
if (!IoSetCancelRoutine(Irp, NULL))
continue; // being cancelled right this instant
RemoveEntryList(current);
InsertTailList(&cancellist, current);
} // for each queued IRP
// Release the spin lock. We're about to undertake a potentially time-consuming
// operation that might conceivably result in a deadlock if we keep the lock.
KeReleaseSpinLock(&deviceExtension->Cachelock, oldirql);
// Complete the selected requests.
while (!IsListEmpty(&cancellist))
{ // cancel selected requests
next = RemoveHeadList(&cancellist);
Irp2 = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
Irp2->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp2, IO_NO_INCREMENT);
} // cancel selected requests
}
else
// Release the spin lock.
KeReleaseSpinLock(&deviceExtension->Cachelock, oldirql);
} // GenericCleanupControlRequests
///////////////////////////////////////////////////////////////////////////////
BOOLEAN
CanDeviceSuspend(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
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.
--*/
{
KdPrint( ("CanDeviceSuspend\n"));
if((DeviceExtension->OpenHandleCount == 0) &&
(DeviceExtension->OutStandingIO == 1)) {
return TRUE;
}
else {
return FALSE;
}
}
NTSTATUS
IntUsb_AbortPipes(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description
sends an abort pipe request for open pipes.
Arguments:
DeviceObject - pointer to device object
Return Value:
NT status value
--*/
{
PURB urb;
ULONG i;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PINTUSB_PIPE_CONTEXT pipeContext;
PUSBD_PIPE_INFORMATION pipeInformation;
PUSBD_INTERFACE_INFORMATION interfaceInfo;
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
pipeContext = deviceExtension->PipeContext;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -