📄 isopnp.c
字号:
// 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;
IsoUsb_DbgPrint(3, ("ProcessQueuedRequests::"));
IsoUsb_IoIncrement(DeviceExtension);
IoSkipCurrentIrpStackLocation(nextIrp);
IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
IsoUsb_DbgPrint(3, ("ProcessQueuedRequests::"));
IsoUsb_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);
}
IsoUsb_DbgPrint(3, ("ProcessQueuedRequests - ends\n"));
return;
}
VOID
GetBusInterfaceVersion(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine queries the bus interface version
Arguments:
DeviceExtension
Return Value:
VOID
--*/
{
PIRP irp;
KEVENT event;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION nextStack;
USB_BUS_INTERFACE_USBDI_V1 busInterfaceVer1;
//
// initialize vars
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
IsoUsb_DbgPrint(3, ("GetBusInterfaceVersion - begins\n"));
irp = IoAllocateIrp(deviceExtension->TopOfStackDeviceObject->StackSize,
FALSE);
if(NULL == irp) {
IsoUsb_DbgPrint(1, ("Failed to alloc irp in GetBusInterfaceVersion\n"));
return;
}
//
// All pnp Irp's need the status field initialized to
// STATUS_NOT_SUPPORTED
//
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(irp,
(PIO_COMPLETION_ROUTINE) IrpCompletionRoutine,
&event,
TRUE,
TRUE,
TRUE);
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack);
nextStack->MajorFunction = IRP_MJ_PNP;
nextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
//
// Allocate memory for an interface of type
// USB_BUS_INTERFACE_USBDI_V0 and have the IRP point to it:
//
nextStack->Parameters.QueryInterface.Interface =
(PINTERFACE) &busInterfaceVer1;
//
// Assign the InterfaceSpecificData member of the IRP to be NULL
//
nextStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
//
// Set the interface type to the appropriate GUID
//
nextStack->Parameters.QueryInterface.InterfaceType =
&USB_BUS_INTERFACE_USBDI_GUID;
//
// Set the size and version of interface in the IRP
// Currently, there is only one valid version of
// this interface available to clients.
//
nextStack->Parameters.QueryInterface.Size =
sizeof(USB_BUS_INTERFACE_USBDI_V1);
nextStack->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_1;
IsoUsb_IoIncrement(deviceExtension);
ntStatus = IoCallDriver(DeviceObject,
irp);
if(STATUS_PENDING == ntStatus) {
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
ntStatus = irp->IoStatus.Status;
}
if(NT_SUCCESS(ntStatus)) {
deviceExtension->IsDeviceHighSpeed =
busInterfaceVer1.IsDeviceHighSpeed(
busInterfaceVer1.BusContext);
IsoUsb_DbgPrint(1, ("IsDeviceHighSpeed = %x\n",
deviceExtension->IsDeviceHighSpeed));
}
IoFreeIrp(irp);
IsoUsb_DbgPrint(3, ("GetBusInterfaceVersion::"));
IsoUsb_IoDecrement(deviceExtension);
IsoUsb_DbgPrint(3, ("GetBusInterfaceVersion - ends\n"));
}
NTSTATUS
IrpCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is a completion routine.
In this routine we set an event.
Since the completion routine returns
STATUS_MORE_PROCESSING_REQUIRED, the Irps,
which set this routine as the completion routine,
should be marked pending.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Context -
Return Value:
NT status value
--*/
{
PKEVENT event = Context;
KeSetEvent(event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
IsoUsb_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];
IsoUsb_DbgPrint(3, ("IsoUsb_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)) {
IsoUsb_DbgPrint(3, ("success Value = %X\n", *Value));
return STATUS_SUCCESS;
}
else {
*Value = 0;
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS
IsoUsb_AbortPipes(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine sends an irp/urb pair with
URB_FUNCTION_ABORT_PIPE request down the stack
Arguments:
DeviceObject - pointer to device object
Return Value:
NT status value
--*/
{
PURB urb;
ULONG i;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PUSBD_PIPE_INFORMATION pipeInformation;
PUSBD_INTERFACE_INFORMATION interfaceInfo;
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
interfaceInfo = deviceExtension->UsbInterface;
IsoUsb_DbgPrint(3, ("IsoUsb_AbortPipes - begins\n"));
if(interfaceInfo == NULL) {
return STATUS_SUCCESS;
}
for(i = 0; i < interfaceInfo->NumberOfPipes; 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;
ntStatus = CallUSBD(DeviceObject, urb);
ExFreePool(urb);
}
else {
IsoUsb_DbgPrint(1, ("Failed to alloc memory for urb for input pipe\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
return ntStatus;
}
}
IsoUsb_DbgPrint(3, ("IsoUsb_AbortPipes - ends\n"));
return STATUS_SUCCESS;
}
NTSTATUS
IsoUsb_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;
PFILE_OBJECT fileObject;
PFILE_OBJECT_CONTENT fileObjectContent;
PISOUSB_STREAM_OBJECT tempStreamObject;
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
IsoUsb_DbgPrint(3, ("IsoUsb_DispatchClean::"));
IsoUsb_IoIncrement(deviceExtension);
//
// check if any stream objects need to be cleaned
//
if(fileObject && fileObject->FsContext) {
fileObjectContent = (PFILE_OBJECT_CONTENT)
fileObject->FsContext;
if(fileObjectContent->StreamInformation) {
tempStreamObject = (PISOUSB_STREAM_OBJECT)
InterlockedExchangePointer(
&fileObjectContent->StreamInformation,
NULL);
if(tempStreamObject &&
(tempStreamObject->DeviceObject == DeviceObject)) {
IsoUsb_DbgPrint(3, ("clean dispatch routine"
" found a stream object match\n"));
IsoUsb_StreamObjectCleanup(tempStreamObject, deviceExtension);
}
}
}
InitializeListHead(&cleanupList);
//
// acquire queue lock
//
KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);
//
// remove all Irp's that belong to input Irp's fileobject
//
listHead = &deviceExtension->NewRequestsQueue;
for(thisEntry = listHead->Flin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -