接上篇还原为c的代码如下:
VOID FASTCALL IopfCompleteRequest(
IN PIRP Irp,
IN CCHAR PriorityBoost
)
{
UCHAR uControl;
PIRP masterIrp;
NTSTATUS status;
PIO_STACK_LOCATION stackPointer;
PIO_STACK_LOCATION bottomSp;
PDEVICE_OBJECT deviceObject;
PMDL mdl;
PETHREAD thread;
PFILE_OBJECT fileObject;
KIRQL irql;
PVOID saveAuxiliaryPointer = NULL;
NTSTATUS errorStatus;
/*检查请求包的栈单元域是否处理完 */
if (Irp->CurrentLocation > (CCHAR) (Irp->StackCount + 1) ||
Irp->Type != 6)
{
KeBugCheckEx( 0x44,(ULONG_PTR)Irp, 0x0D63, 0, 0 );
}
/* 如果栈单元没有耗尽,设置栈单元指针指向下一个栈单元并且如果当前栈单元中有完成例程,
则进行调用。清空栈单元。逐个检查每个栈单元,直到栈单元耗尽。
如果一个特殊的驱动中,当其需要执行大量的处理,或者需要在其他进程的上下文中执行,
调用完成例程完成IRP时,返回 STATUS_MORE_PROCESSING_REQUIRED 即:0x0C0000016。
如果当前完成例程返回STATUS_MORE_PROCESSING_REQUIRED,则停止处理这个请求包。
*/
for (stackPointer = IoGetCurrentIrpStackLocation( Irp ),
Irp->CurrentLocation++,
Irp->Tail.Overlay.CurrentStackLocation++;
Irp->CurrentLocation <= (CCHAR) (Irp->StackCount + 1);
stackPointer++,
Irp->CurrentLocation++,
Irp->Tail.Overlay.CurrentStackLocation++)
{
Irp->PendingReturned = stackPointer->Control & 1;
if ( (NT_SUCCESS( Irp->IoStatus.Status ) &&
stackPointer->Control & 0x40) ||
(!NT_SUCCESS( Irp->IoStatus.Status ) &&
stackPointer->Control & 0x80) ||
(Irp->Cancel &&
stackPointer->Control & 0x20)
)
{
stackPointer->MinorFunction = 0;
stackPointer->Flags = 0;
stackPointer->Control = 0;
stackPointer->Parameters.Others.Argument1 = 0;
stackPointer->Parameters.Others.Argument2 = 0;
stackPointer->Parameters.Others.Argument3 = 0;
stackPointer->FileObject = 0;
if (Irp->CurrentLocation == (CCHAR) (Irp->StackCount + 1))
{
deviceObject = NULL;
}
else
{
deviceObject = IoGetCurrentIrpStackLocation( Irp )->DeviceObject;
}
status = stackPointer->CompletionRoutine( deviceObject,
Irp,
stackPointer->Context );
if (status == 0x0C0000016)
{
return;
}
}
else
{
if (Irp->PendingReturned && Irp->CurrentLocation <= Irp->StackCount)
{
IoMarkIrpPending( Irp );
}
stackPointer->MinorFunction = 0;
stackPointer->Flags = 0;
stackPointer->Control = 0;
stackPointer->Parameters.Others.Argument1 = 0;
stackPointer->Parameters.Others.Argument2 = 0;
stackPointer->Parameters.Others.Argument3 = 0;
stackPointer->FileObject = 0;
}
}
/* 检查当前的IRP是否是一个关联的IRP。 如果是,主IRP计数递减。如果主IRP计数为0,
则按照正常IRP的完成步骤完成主IRP。如果计数仍然不是0,那么当前的IRP将被简单的释放. */
if (Irp->Flags & 8)
{
ULONG count;
masterIrp = Irp->AssociatedIrp.MasterIrp;
count = IopInterlockedDecrementUlong( 0x0A,
&masterIrp->AssociatedIrp.IrpCount );
IopFreeIrpAndMdls( Irp );
if (count == 1)
{
IoCompleteRequest( masterIrp, PriorityBoost ); //递归
}
return;
}
/* Check to see if we have a name junction*/
if ((Irp->IoStatus.Status == 0x104 ) &&
(Irp->IoStatus.Information > 1))
{
/* For name junctions, we save the pointer to the auxiliary
buffer and use it below.*/
if (Irp->IoStatus.Information == 0x0A0000003)
{
saveAuxiliaryPointer = (PVOID) Irp->Tail.Overlay.AuxiliaryBuffer;
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
}
else
{
Irp->IoStatus.Status = 0x0C0000279h ;
}
}
/*检查IRP中的辅助缓冲区指针,如果不为NULL,则释放*/
if (Irp->Tail.Overlay.AuxiliaryBuffer)
{
ExFreePoolWithTag (Irp->Tail.Overlay.AuxiliaryBuffer,0 );
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
}
/*如果这是一个内存分页的I/O或者是一个关闭操作,那么保存I/O状态块,并且把事件设置为信号态,
并取消事件的引用。如果是内存分页的I/O,还需要释放IRP.
*/
if (Irp->Flags & 0x402)
{
if (Irp->Flags & 0x440)
{
ULONG flags;
flags = Irp->Flags & 0x42;
*Irp->UserIosb = Irp->IoStatus;
(VOID) KeSetEvent( Irp->UserEvent, PriorityBoost, 0 );
if (flags)
{
if (IopIsReserveIrp(Irp))
{
IopFreeReserveIrp(PriorityBoost);
}
else
{
IoFreeIrp( Irp );
}
}
}
else
{
KeInitializeApc( &Irp->Tail.Apc,
Irp->Tail.Overlay.Thread,
Irp->ApcEnvironment,
IopCompletePageWrite,
(PKRUNDOWN_ROUTINE) NULL,
(PKNORMAL_ROUTINE) NULL,
KernelMode,
(PVOID) PriorityBoost );
(VOID) KeInsertQueueApc( &Irp->Tail.Apc,
(PVOID) NULL,
(PVOID) NULL,
PriorityBoost );
}
return;
}
/*页面解锁,如果需要,调用MmUnlockPages来释放MDL*/
if (Irp->MdlAddress != NULL)
{
mdl = Irp->MdlAddress;
while (mdl != NULL)
{
MmUnlockPages( mdl );
mdl = mdl->Next;
}
}
/*检查请求完成是否可以延迟完成,如果可以,当前的完成例程可以简单退出,直到原始的请求完成IRP,
通过初始化和派发APC到调用线程,可以避免很多的中断和排队处理。*/
if (Irp->Flags & IRP_DEFER_IO_COMPLETION && !Irp->PendingReturned)
{
if ((Irp->IoStatus.Status == 0x104 ) &&
(Irp->IoStatus.Information == 0x0A0000003))
{
Irp->Tail.Overlay.AuxiliaryBuffer = saveAuxiliaryPointer;
}
return;
}
//
fileObject = Irp->Tail.Overlay.OriginalFileObject;
if (!Irp->Cancel)
{
KeInitializeApc( &Irp->Tail.Apc,
&Irp->Tail.Overlay.Thread,
Irp->ApcEnvironment,
IopCompleteRequest,
IopAbortRequest,
(PKNORMAL_ROUTINE) NULL,
KernelMode,
(PVOID) NULL );
(VOID) KeInsertQueueApc( &Irp->Tail.Apc,
fileObject,
(PVOID) saveAuxiliaryPointer,
PriorityBoost );
}
else
{
/*IRP被取消时,派发APC到目标线程。*/
irql = KeRaiseIrqlToDpcLevel() ;
thread = Irp->Tail.Overlay.Thread;
if (thread)
{
KeInitializeApc( &Irp->Tail.Apc,
&thread,
Irp->ApcEnvironment,
IopCompleteRequest,
IopAbortRequest,
(PKNORMAL_ROUTINE) NULL,
KernelMode,
(PVOID) NULL );
(VOID) KeInsertQueueApc( &Irp->Tail.Apc,
fileObject,
(PVOID) saveAuxiliaryPointer,
PriorityBoost );
KfLowerIrql (irql );
}
else
{
KfLowerIrql (irql );
IopDropIrp( Irp, fileObject );
}
}
}
IoCompleteRequest深入学习之二
最新推荐文章于 2024-08-15 22:19:47 发布