WDK中出现的特殊代码
WDK中出现的特殊代码
我们用本章的最后一个小节来介绍一些在WDK示例代码中见到的特殊形式编码。这些代码在Win32应用程序的编程中很少见到,读者需要首先熟悉一下。
首先是参数说明宏。参数说明宏一般都是空宏,最常见的是IN和OUT。其实定义很简单,如下所示:
#define IN
#define OUT
这样一来,IN和OUT就被定义成了空。无论出现在代码中的任何地方,对代码都不会有什么实质的影响。在WDK的代码中,用来作为函数的说明。IN表示这个参数用于输入;OUT表示这个参数用来返回结果。比如下面的例子:
NTSTATUS
ZwQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
IN和OUT是比较传统的参数说明宏。在WDK中到处可见更复杂的参数说明宏,比如下面的例子:
VOID
NdisProtStatus(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS GeneralStatus,
__in_bcount(StatusBufferSize) IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
其中的__in_bcount不但说明参数StatusBuffer是一个输入参数,而且说明了StatusBuffer作为一个缓冲区,它的字节长度被另一个参数StatusBufferSize所指定。读者再见到类似的说明宏,就以字面意思理解即可。
然后是指定函数位置的预编译指令。比如下面的例子:
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, NdisProtUnload)
#pragma alloc_text(PAGE, NdisProtOpen)
#pragma alloc_text(PAGE, NdisProtClose)
#pragma alloc_text这个宏仅仅用来指定某个函数的可执行代码在编译出来后在sys文件中的位置。内核模块编译出来之后是一个PE格式的sys文件,这个 文件的代码段(text段)中有不同的节(Section),不同的节被加载到内存中之后处理情况不同。读者需要关心的主要是3种节:INIT节的特点是 在初始化完毕之后就被释放。也就是说,就不再占用内存空间了。PAGE节的特点是位于可以进行分页交换的内存空间,这些空间在内存紧张时可以被交换到硬盘 上以节省内存。如果未用上述的预编译指令处理,则代码默认位于PAGELK节,加载后位于不可分页交换的内存空间中。
函数DriverEntry显然只需要在初始化阶段执行一次,因此这个函数一般都用#pragma alloc_text(INIT, DriverEntry)使之位于初始化后立刻释放的空间内。为了节约内存,可以把很多函数放在PAGE节中。但是要注意:放在PAGE节中的函数不可以 在Dispatch级调用,因为这种函数的调用可能诱发缺页中断。但是缺页中断处理不能在Dispatch级完成。为此,一般都用一个宏 PAGED_CODE()进行测试。如果发现当前中断级为Dispatch级,则程序直接报异常,让程序员及早发现。示例如下:
#pragma alloc_text(PAGE, SfAttachToMountedDevice)
……
NTSTATUS
SfAttachToMountedDevice (
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT SFilterDeviceObject
)
{
PSFILTER_DEVICE_EXTENSION newDevExt =
SFilterDeviceObject->DeviceExtension;
NTSTATUS status;
ULONG i;
PAGED_CODE();
…
更多精彩资源:
web开发专栏:http://blog.csdn.net/broadviewwebdev
数据库开发专栏:http://blog.csdn.net/broadviewdatabase
程序设计专栏:http://blog.csdn.net/broadviewprograming
嵌入式专栏:http://blog.mcuol.com/Broadview/index.htm