📄 usb2com.read.cpp
字号:
//********************************************************************
// created: 11:7:2008 21:29
// file: usb2com.read.cpp
// author: tiamo
// purpose: read
//********************************************************************
#include "stdafx.h"
//
// read dispatch routine
//
NTSTATUS Usb2ComRead(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp)
{
PUSB2COM_DEVICE_EXTENSION DevExt = static_cast<PUSB2COM_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status = STATUS_SUCCESS;
//
// check zero-length
//
if(!IrpSp->Parameters.Read.Length)
{
Irp->IoStatus.Status = Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
//
// acquire remove lock
//
Status = IoAcquireRemoveLock(&DevExt->RemoveLock,Irp);
if(!NT_SUCCESS(Status))
{
//
// we are removing
//
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
//
// set information with zero
//
Irp->IoStatus.Information = 0;
//
// protected by read lock
//
KIRQL SavedIrql;
KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);
//
// current read irp is pending,just queue this one
//
if(DevExt->CurrentReadIrp)
{
//
// setup a cancel routine
//
PDRIVER_CANCEL OldCancel = IoSetCancelRoutine(Irp,&Usb2ComQueuedReadIrpCancel);
ASSERT(!OldCancel);
//
// IoCancelIrp called
//
if(Irp->Cancel)
{
OldCancel = IoSetCancelRoutine(Irp,0);
if(OldCancel)
{
//
// our cancel routine has not been called
//
ASSERT(OldCancel == &Usb2ComQueuedReadIrpCancel);
KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
Status = STATUS_CANCELLED;
}
else
{
//
// our cancel routine will be called as soon as we release read lock
//
IoMarkIrpPending(Irp);
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
Status = STATUS_PENDING;
}
}
else
{
//
// mark it pending and queue it
//
IoMarkIrpPending(Irp);
InsertTailList(&DevExt->ReadQueueListHead,&Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
Status = STATUS_PENDING;
}
}
else
{
//
// set as the current read irp,and start it
//
DevExt->CurrentReadIrp = Irp;
LIST_ENTRY CompleteIrpListHead;
InitializeListHead(&CompleteIrpListHead);
Status = Usb2ComProcessPendingReadIrps(DevExt,&CompleteIrpListHead,TRUE);
KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
while(!IsListEmpty(&CompleteIrpListHead))
{
PLIST_ENTRY ListEntry = RemoveHeadList(&CompleteIrpListHead);
PIRP Irp = CONTAINING_RECORD(ListEntry,IRP,Tail.Overlay.ListEntry);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
}
}
return Status;
}
//
// cancel all read irps
//
VOID Usb2ComCancelAllReadIrps(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
KIRQL SavedIrql;
KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);
LIST_ENTRY CompleteIrpListHead;
InitializeListHead(&CompleteIrpListHead);
PIRP Irp = Usb2ComGetNextReadIrp(DevExt);
while(Irp)
{
InsertTailList(&CompleteIrpListHead,&Irp->Tail.Overlay.ListEntry);
Irp = Usb2ComGetNextReadIrp(DevExt);
}
Irp = DevExt->CurrentReadIrp;
if(Irp)
{
PDRIVER_CANCEL OldCancel = IoSetCancelRoutine(Irp,0);
if(OldCancel)
InsertTailList(&CompleteIrpListHead,&Irp->Tail.Overlay.ListEntry);
DevExt->CurrentReadIrp = 0;
}
KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
while(!IsListEmpty(&CompleteIrpListHead))
{
PLIST_ENTRY ListEntry = RemoveHeadList(&CompleteIrpListHead);
PIRP Irp = CONTAINING_RECORD(ListEntry,IRP,Tail.Overlay.ListEntry);
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
}
}
//
// reset read info
//
VOID Usb2ComResetReadBufferInfo(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
KIRQL SavedIrql;
KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);
DevExt->FirstReadCharSlot = 0;
DevExt->ReadBufferCharsCount = 0;
KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
}
//
// current read irp cancel routine
//
VOID Usb2ComCurrentReadIrpCancel(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp)
{
PUSB2COM_DEVICE_EXTENSION DevExt = static_cast<PUSB2COM_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
//
// release global spin lock
//
IoReleaseCancelSpinLock(Irp->CancelIrql);
//
// acquire our read queue lock
//
KIRQL SavedIrql;
KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
LIST_ENTRY CompleteIrpListHead;
InitializeListHead(&CompleteIrpListHead);
InsertTailList(&CompleteIrpListHead,&Irp->Tail.Overlay.ListEntry);
//
// if it is the current read irp,complete it and start the next one
//
if(Irp == DevExt->CurrentWriteIrp)
{
DevExt->CurrentReadIrp = Usb2ComGetNextReadIrp(DevExt);
Usb2ComProcessPendingReadIrps(DevExt,&CompleteIrpListHead,TRUE);
}
KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
while(!IsListEmpty(&CompleteIrpListHead))
{
PLIST_ENTRY ListEntry = RemoveHeadList(&CompleteIrpListHead);
PIRP Irp = CONTAINING_RECORD(ListEntry,IRP,Tail.Overlay.ListEntry);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
}
}
//
// queued read irp cancel routine
//
VOID Usb2ComQueuedReadIrpCancel(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp)
{
PUSB2COM_DEVICE_EXTENSION DevExt = static_cast<PUSB2COM_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
//
// release global spin lock
//
IoReleaseCancelSpinLock(Irp->CancelIrql);
//
// acquire our read queue lock
//
KIRQL SavedIrql;
KeAcquireSpinLock(&DevExt->ReadLock,&SavedIrql);
//
// remove the irp from read queue
//
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&DevExt->ReadLock,SavedIrql);
//
// complete this irp with canceled
//
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
//
// release remove lock on this irp
//
IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
}
//
// get next read irp
//
PIRP Usb2ComGetNextReadIrp(__in PUSB2COM_DEVICE_EXTENSION DevExt)
{
PIRP Irp = 0;
while(!Irp && !IsListEmpty(&DevExt->ReadQueueListHead))
{
PLIST_ENTRY ListEntry = RemoveHeadList(&DevExt->ReadQueueListHead);
Irp = CONTAINING_RECORD(ListEntry,IRP,Tail.Overlay.ListEntry);
//
// handle irp cancel
//
PDRIVER_CANCEL OldCancelRoutine = IoSetCancelRoutine(Irp,0);
//
// IoCancelIrp could just been called on this irp,
//
if(OldCancelRoutine)
{
//
// our cancel routine has not been called,return it
//
ASSERT(OldCancelRoutine == &Usb2ComQueuedReadIrpCancel);
}
else
{
//
// our cancel routine will be called on this irp,reinitialize list entry to make cancel routine happy
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -