这个完成函数小弟我看不太明白
这个完成函数我看不太明白
这个完成函数我看不太明白,首先我不明白在什么时候会出现irp->CurrentLocation <= 的情况,我发现将完成函数设置到了本层上。通过IoSkipCurrentIrpStackLocation + IoSetCompletionRoutine完成。在这个完成函数中做的一系列操作我看不明白,请大牛指点,谢谢
/*
* completion routine for case if we use IoSkipCurrentIrpStackLocation way
*/
NTSTATUS
tdi_skip_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
TDI_SKIP_CTX *ctx = (TDI_SKIP_CTX *)Context;
NTSTATUS status;
PIO_STACK_LOCATION irps;
if (Irp->IoStatus.Status != STATUS_SUCCESS)
FilterDebugPrint(("%s: status 0x%x\n", __FUNCTION__, Irp->IoStatus.Status));
// restore IRP for using in our completion
Irp->CurrentLocation--;
Irp->Tail.Overlay.CurrentStackLocation--;
irps = IoGetCurrentIrpStackLocation(Irp);
DeviceObject = irps->DeviceObject;
if (ctx->new_cr != NULL) {
// restore fileobject (it's NULL)
irps->FileObject = ctx->fileobj;
// set new device object in irps
irps->DeviceObject = ctx->new_devobj;
// call new completion
status = ctx->new_cr(ctx->new_devobj, Irp, ctx->new_context);//(C)ctx->new_context = context;(B)completion->context = query_irp;(A) query_irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION,//生成一个空的请求
}
else
{
//i need to release the counter at here.((:(
status = STATUS_SUCCESS;
}
/* patch IRP back */
// restore routine and context (and even control!)
irps->CompletionRoutine = ctx->old_cr;
irps->Context = ctx->old_context;
irps->Control = ctx->old_control;
// restore device object
irps->DeviceObject = DeviceObject;
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation++;
if (ctx->old_cr != NULL) {
if (status != STATUS_MORE_PROCESSING_REQUIRED) {
// call old completion (see the old control)
BOOLEAN b_call = FALSE;
if (Irp->Cancel) {
// cancel
if (ctx->old_control & SL_INVOKE_ON_CANCEL)
b_call = TRUE;
} else {
if (Irp->IoStatus.Status >= STATUS_SUCCESS) {
// success
if (ctx->old_control & SL_INVOKE_ON_SUCCESS)
b_call = TRUE;
} else {
// error
if (ctx->old_control & SL_INVOKE_ON_ERROR)
b_call = TRUE;
}
}
if (b_call)
status = ctx->old_cr(DeviceObject, Irp, ctx->old_context);
} else {
/*
* patch IRP to set IoManager to call completion next time
*/
// restore Control
irps->Control = ctx->old_control;
}
}
ExFreePool(ctx);
return status;
}
引用它的地方:
if (cr == NULL || irp->CurrentLocation <= 1/*前提建立在cr!=0时*/) // WINDBG时:irp->CurrentLocation = 2 一个是过滤设备,下一个是Tcp&Udp原设备
{
/*
* we use _THIS_ way of sending IRP to old driver
* a) to avoid NO_MORE_STACK_LOCATIONS
这个完成函数我看不太明白,首先我不明白在什么时候会出现irp->CurrentLocation <= 的情况,我发现将完成函数设置到了本层上。通过IoSkipCurrentIrpStackLocation + IoSetCompletionRoutine完成。在这个完成函数中做的一系列操作我看不明白,请大牛指点,谢谢
/*
* completion routine for case if we use IoSkipCurrentIrpStackLocation way
*/
NTSTATUS
tdi_skip_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
TDI_SKIP_CTX *ctx = (TDI_SKIP_CTX *)Context;
NTSTATUS status;
PIO_STACK_LOCATION irps;
if (Irp->IoStatus.Status != STATUS_SUCCESS)
FilterDebugPrint(("%s: status 0x%x\n", __FUNCTION__, Irp->IoStatus.Status));
// restore IRP for using in our completion
Irp->CurrentLocation--;
Irp->Tail.Overlay.CurrentStackLocation--;
irps = IoGetCurrentIrpStackLocation(Irp);
DeviceObject = irps->DeviceObject;
if (ctx->new_cr != NULL) {
// restore fileobject (it's NULL)
irps->FileObject = ctx->fileobj;
// set new device object in irps
irps->DeviceObject = ctx->new_devobj;
// call new completion
status = ctx->new_cr(ctx->new_devobj, Irp, ctx->new_context);//(C)ctx->new_context = context;(B)completion->context = query_irp;(A) query_irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION,//生成一个空的请求
}
else
{
//i need to release the counter at here.((:(
status = STATUS_SUCCESS;
}
/* patch IRP back */
// restore routine and context (and even control!)
irps->CompletionRoutine = ctx->old_cr;
irps->Context = ctx->old_context;
irps->Control = ctx->old_control;
// restore device object
irps->DeviceObject = DeviceObject;
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation++;
if (ctx->old_cr != NULL) {
if (status != STATUS_MORE_PROCESSING_REQUIRED) {
// call old completion (see the old control)
BOOLEAN b_call = FALSE;
if (Irp->Cancel) {
// cancel
if (ctx->old_control & SL_INVOKE_ON_CANCEL)
b_call = TRUE;
} else {
if (Irp->IoStatus.Status >= STATUS_SUCCESS) {
// success
if (ctx->old_control & SL_INVOKE_ON_SUCCESS)
b_call = TRUE;
} else {
// error
if (ctx->old_control & SL_INVOKE_ON_ERROR)
b_call = TRUE;
}
}
if (b_call)
status = ctx->old_cr(DeviceObject, Irp, ctx->old_context);
} else {
/*
* patch IRP to set IoManager to call completion next time
*/
// restore Control
irps->Control = ctx->old_control;
}
}
ExFreePool(ctx);
return status;
}
引用它的地方:
if (cr == NULL || irp->CurrentLocation <= 1/*前提建立在cr!=0时*/) // WINDBG时:irp->CurrentLocation = 2 一个是过滤设备,下一个是Tcp&Udp原设备
{
/*
* we use _THIS_ way of sending IRP to old driver
* a) to avoid NO_MORE_STACK_LOCATIONS