📄 driverentry.cpp
字号:
/*
Function name:
AllowRequests
Routine Description:
Begin accepting new requests to the queue.
Arguments:
pdq - Address of queue object
Return Value:
*/
VOID AllowRequests(PDEVQUEUE pdq)
{
KdPrint(("SIWDM - AllowRequests\n"));
pdq->abortstatus = STATUS_SUCCESS;
}
/*
Function name:
AreRequestsBeingAborted
Routine Description:
Determine if new requests to the queue are being rejected.
Arguments:
pdq - Address of queue object
Return Value:
STATUS_SUCCESS if successful
ntStatus code otherwise.
*/
NTSTATUS AreRequestsBeingAborted(PDEVQUEUE pdq)
{
KdPrint(("SIWDM - AreRequestsBeingAborted\n"));
return pdq->abortstatus;
}
/*
Function name:
CancelRequests
Routine Description:
Handles cancellation of an Irp. Should be called from a cancel routine while
still owning the spin lock.
Arguments:
pdq - Address of queue object
Irp - that is being cancelled
Return Value:
*/
VOID CancelRequest(PDEVQUEUE pdq, PIRP Irp)
{
KIRQL oldirql = Irp->CancelIrql;
KdPrint(("SIWDM - Entering CancelRequests\n"));
IoReleaseCancelSpinLock(DISPATCH_LEVEL);
KeAcquireSpinLockAtDpcLevel(&pdq->lock);
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&pdq->lock, oldirql);
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KdPrint(("SIWDM - Exiting CancelRequests\n"));
}
/*
Function name:
CheckBusyAndStall
Routine Description:
Stalls the queue if no Irps are being processed.
Arguments:
pdq - Address of queue object
Return Value:
TRUE if queue busy.
FALSE if queue empty.
*/
BOOLEAN CheckBusyAndStall(PDEVQUEUE pdq)
{
KIRQL oldirql;
KdPrint(("SIWDM - Entering CheckBusyAndStall\n"));
KeAcquireSpinLock(&pdq->lock, &oldirql);
BOOLEAN busy = pdq->CurrentIrp != NULL;
if (!busy)
InterlockedIncrement(&pdq->stallcount);
KeReleaseSpinLock(&pdq->lock, oldirql);
KdPrint(("SIWDM - Exiting CheckBusyAndStall\n"));
return busy;
}
/*
Function name:
CleanupRequests
Routine Description:
Completes the requests for a given file object.
Arguments:
pdq - Address of queue object
fop - Pointer to the file object, NULL completes all requests on the queue.
ntStatus - Status to which complete requests
Return Value:
*/
VOID CleanupRequests(PDEVQUEUE pdq, PFILE_OBJECT fop, NTSTATUS status)
{
LIST_ENTRY cancellist;
KIRQL oldirql;
PLIST_ENTRY first = &pdq->head;
PLIST_ENTRY next;
KdPrint(("SIWDM - Entering CleanupRequests\n"));
InitializeListHead(&cancellist);
KeAcquireSpinLock(&pdq->lock, &oldirql);
for(next=first->Flink;next!=first; )
{
PIRP Irp = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
PLIST_ENTRY current = next;
next = next->Flink;
if(fop && stack->FileObject != fop)
continue;
if(!IoSetCancelRoutine(Irp, NULL))
continue;
RemoveEntryList(current);
InsertTailList(&cancellist, current);
}
KeReleaseSpinLock(&pdq->lock, oldirql);
while(!IsListEmpty(&cancellist))
{
next = RemoveHeadList(&cancellist);
PIRP Irp = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
KdPrint(("SIWDM - Exiting CleanupRequests\n"));
}
/*
Function name:
GetCurrentIrp
Routine Description:
Determines the current Irp for the queue
Arguments:
pdq - Address of queue object
Return Value:
A pointer to an Irp
*/
PIRP GetCurrentIrp(PDEVQUEUE pdq)
{
KdPrint(("SIWDM - GetCurrentIrp\n"));
return pdq->CurrentIrp;
}
/*
Function name:
InitializeQueue
Routine Description:
Initializes the queue and sets the StartIo routine.
Arguments:
pdq - Address of queue object
StartIo - Addres of the StartIo routine
Return Value:
*/
VOID InitializeQueue(PDEVQUEUE pdq, PDRIVER_STARTIO StartIo)
{
KdPrint(("SIWDM - Entering InitializeQueue\n"));
InitializeListHead(&pdq->head);
KeInitializeSpinLock(&pdq->lock);
pdq->StartIo = StartIo;
pdq->stallcount = 1;
pdq->CurrentIrp = NULL;
KeInitializeEvent(&pdq->evStop, NotificationEvent, FALSE);
pdq->abortstatus = (NTSTATUS) 0;
pdq->notify = NULL;
pdq->notifycontext = 0;
KdPrint(("SIWDM - Exiting InitializeQueue\n"));
}
/*
Function name:
RestartRequests
Routine Description:
Restarts a stalled queue.
Arguments:
pdq - Address of queue object
fdo - Address of the device object
Return Value:
*/
VOID RestartRequests(PDEVQUEUE pdq, PDEVICE_OBJECT fdo)
{
KdPrint(("SIWDM - Entering RestartRequests\n"));
if(InterlockedDecrement(&pdq->stallcount) > 0)
return;
StartNextPacket(pdq, fdo);
KdPrint(("SIWDM - Exiting RestartRequests\n"));
}
/*
Function name:
StallRequests
Routine Description:
Stalls requests in the queue.
Arguments:
pdq - Address of queue object
Return Value:
*/
VOID StallRequests(PDEVQUEUE pdq)
{
KdPrint(("SIWDM - StallRequests\n"));
InterlockedIncrement(&pdq->stallcount);
}
/*
Function name:
StallRequestsAndNotify
Routine Description:
Stalls requests in the queue and notifies when current Irp is complete.
Arguments:
pdq - Address of queue object
notify - Address of the notify function.
context - arguement passed to notify function.
Return Value:
STATUS_SUCCESS if stalled
STATUS_PENDING if waiting for IRP to complete
STATUS_INVALID_DEVICE_REQUEST if call already pending for queue
*/
NTSTATUS StallRequestsAndNotify(PDEVQUEUE pdq, PQNOTIFYFUNC notify, PVOID context)
{
NTSTATUS ntStatus;
KIRQL oldirql;
KdPrint(("SIWDM - Entering StallRequestsAndNotify\n"));
KeAcquireSpinLock(&pdq->lock, &oldirql);
if(pdq->notify)
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
else
{
InterlockedIncrement(&pdq->stallcount);
if(pdq->CurrentIrp)
{
pdq->notify = notify;
pdq->notifycontext = context;
ntStatus = STATUS_PENDING;
}
else
ntStatus = STATUS_SUCCESS;
}
KeReleaseSpinLock(&pdq->lock, oldirql);
KdPrint(("SIWDM - Exiting StallRequestsAndNotify\n"));
return ntStatus;
}
/*
Function name:
StartNextPacket
Routine Description:
Starts the next packet in the queue.
Arguments:
pdq - Address of queue object
fdo - Address of the device object
Return Value:
Address of the Irp with which the device was busy.
*/
PIRP StartNextPacket(PDEVQUEUE pdq, PDEVICE_OBJECT fdo)
{
KIRQL oldirql;
KdPrint(("SIWDM - Entering StartNextPacket\n"));
KeAcquireSpinLock(&pdq->lock, &oldirql);
PIRP CurrentIrp = (PIRP) InterlockedExchangePointer(&pdq->CurrentIrp, NULL);
if(CurrentIrp)
KeSetEvent(&pdq->evStop, 0, FALSE);
PQNOTIFYFUNC notify = pdq->notify;
PVOID notifycontext = pdq->notifycontext;
pdq->notify = NULL;
while(!pdq->stallcount && !pdq->abortstatus && !IsListEmpty(&pdq->head))
{
PLIST_ENTRY next = RemoveHeadList(&pdq->head);
PIRP Irp = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
if(!IoSetCancelRoutine(Irp, NULL))
{
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
continue;
}
pdq->CurrentIrp = Irp;
KeReleaseSpinLockFromDpcLevel(&pdq->lock);
(*pdq->StartIo)(fdo, Irp);
KeLowerIrql(oldirql);
return CurrentIrp;
}
KeReleaseSpinLock(&pdq->lock, oldirql);
if(notify)
(*notify)(notifycontext);
KdPrint(("SIWDM - Exiting StartNextPacket\n"));
return CurrentIrp;
}
/*
Function name:
StartPacket
Routine Description:
Sends the Irp to the StartIo routine or places the Irp in the queue.
Arguments:
pdq - Address of queue object
fdo - Address of the device object
Irp - Irp that starts the queue or is being placed in the queue.
cancel - Cancel routine for active Irps
Return Value:
*/
VOID StartPacket(PDEVQUEUE pdq, PDEVICE_OBJECT fdo, PIRP Irp, PDRIVER_CANCEL cancel)
{
KIRQL oldirql;
KeAcquireSpinLock(&pdq->lock, &oldirql);
NTSTATUS abortstatus = pdq->abortstatus;
KdPrint(("SIWDM - Entering StartPacket\n"));
if(abortstatus)
{
KeReleaseSpinLock(&pdq->lock, oldirql);
Irp->IoStatus.Status = abortstatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
else if(pdq->CurrentIrp || pdq->stallcount)
{
IoSetCancelRoutine(Irp, cancel);
if(Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
{
KeReleaseSpinLock(&pdq->lock, oldirql);
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
else
{
InsertTailList(&pdq->head, &Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&pdq->lock, oldirql);
}
}
else
{
pdq->CurrentIrp = Irp;
KeReleaseSpinLock(&pdq->lock, DISPATCH_LEVEL);
(*pdq->StartIo)(fdo, Irp);
KeLowerIrql(oldirql);
}
KdPrint(("SIWDM - Exiting StartPacket\n"));
}
/*
Function name:
WaitForCurrentIrp
Routine Description:
Waits for the current Irp to finish.
Arguments:
pdq - Address of queue object
Return Value:
*/
VOID WaitForCurrentIrp(PDEVQUEUE pdq)
{
KdPrint(("SIWDM - Entering WaitForCurrentIrp\n"));
KeClearEvent(&pdq->evStop);
KIRQL oldirql;
KeAcquireSpinLock(&pdq->lock, &oldirql);
BOOLEAN mustwait = pdq->CurrentIrp != NULL;
KeReleaseSpinLock(&pdq->lock, oldirql);
if(mustwait)
KeWaitForSingleObject(&pdq->evStop, Executive, KernelMode, FALSE, NULL);
KdPrint(("SIWDM - Exiting WaitForCurrentIrp\n"));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -