/*
* Complete the IRP
*
*/
Irp->IoStatus.Status = NtStatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
....
NTSTATUS ExampleFilter_CompletionRoutine(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
DbgPrint("ExampleFilter_CompletionRoutine Called \r\n");
/*
* We need to return
* "STATUS_MORE_PROCESSING_REQUIRED" so that we can
* use the IRP in our driver.If we complete this here we
* would not be able to use it and the IRP would be completed. This
* also means that our driver
* must also complete the IRP since it has not been completed yet.
*/
return STATUS_MORE_PROCESSING_REQUIRED;
}
由于我们返回STATUS_MORE_PROCESSING_REQUIRED给I/O管理器,IRP没有被完成。现在你可以在IoCallDriver后操作IRP. 然而现在当我们用完后,我们必须要完成它。这是因为我们停止了IRP地完成。记住,我们的例子中不要考虑STATUS_PENDING ,因为我们拥有所有的端点,并且我们尽力想让例子简单。
过滤例子
本篇过滤驱动例子,把自己挂在了我们在第三篇中创建的设备栈上。如果你记得实现,我们能在两个用户模式进程间进行交互。一个问题是,如果你输入大量的字符串,当读它的时候,用户模式应用程序仅仅显示一条字符串。这个问题,即便在用户模式应用中改正起来很简单,然而又有多大的意思呢?
相反,我们创建一个过滤驱动程序在读后直接截取IRP,并且操作IRP返回参数。他去掉字符串中所有的终止符(null字符),用空格替换。然后在字符串最后无效终止。显然这不是个完美的例子,我们覆盖了最后的字符,却不去检查是否需要。毕竟这仅仅是个简单的例子。
使用例子
为了使用这个例子,你需要做的事情跟第三篇中的一样,唯一不同的是,现在有另一种加载程序,你可在加载example.sys后运行它。它会加载examplefilter.sys ,并且会附加到example.sys上,不过是否加载examplefilter.sys,用户模式程序都可以运行。你可以在两种情况下运行看看他们的不同。入口点都有调试信息,你可以跟踪这些代码信息看看。
结束语
在本篇文章中,我们更多的学习了一些处理IRP和设备栈的知识。另外,我们还学习了如何实现一个简单的过滤驱动。在每一篇文章中,我们都努力在这些基本概念上构建驱动,所以我们可以更进一步的理解驱动是怎样工作的?以及如何开发驱动?