WDK文档明确警告不推荐使用该函数。
MmIsAddressValid例程检测读或写作为参数的虚地址是否会发生缺页。
就算是MmIsAddressValid返回TRUE,访问参数地址仍然可能发生缺页,除非该地址是有效的非分页内存或者锁这块内存.
Syntax
BOOLEAN MmIsAddressValid( __in PVOID VirtualAddress );
Parameters
-
VirtualAddress [in]
-
A pointer to the nonpaged virtual address to check. The caller must ensure that this address cannot be paged out or deleted for the duration of this call. Even after the return from the call, you must not page out or delete this address. If you do page out or delete this address, the return value might be unreliable. Paging out or deleting this address might cause the computer to stop responding (that is,crash).
Return value
If no page fault would occur from reading or writing at the given virtual address, MmIsAddressValid returns TRUE.
一些讨论:
1、对于从User Mode传入的地址,使用ProbeForRead和ProbeForWrite检测。它会确保检测地址是有效的且是用户态的。也可以使用MmProbeAndLockPages
2、NTDEV常见一个问题(包括KMDF小组). MmIsAddressValid 从名字上看很有用,传入内核虚地址,如果有效则返回TRUE,否则返回FALSE。 似乎是可以用来在使用一个指针前先检测一下它是否有效,正如用户态的APIsIsBadReadPtr and IsBadWritePtr. (在用户态这俩函数should NEVER ever be used. 他们会掩盖错误并且很快会引起corruption)
不幸的是,这个函数完全不是你想的那样。
它真正的功能是:告诉你访问该地址是否会缺页,不是检测它是否有效。MmIsAddressValid仅仅是dereference一下VA, 所以它并不验证地址的有效性 (就像其它内核函数一样). Windows的有些版本, PagedPool在特定范围的地址区间, 理论上, MmIsAddressvalid可以简单的比较VA参数和PagedPool地址范围, 命中则返回TRUE(this is a drastic simplification, the actual implementation is much more complicated).
如果这个函数真的是检测参数VA是否有效,是否会大有用处? 答案是:否。同样地,IsBadReadPtr等函数也没有太大用处。原因在于时效性,在这个函数返回结果后,另外一个线程可能立刻释放该参数地址。 (as MSDN states for the user mode APIs)
结论: 你需要事先知道你的指针的有效性和正确性。当然在驱动中你必需验证所有使用的用户态地址,但你不可能随机拿来一个内核地址去验证它是否有效。 Like Raymond says, "programming is hard," and you must be 100% in your code or else BSOD the machine.
在内核态,关于内核指针,开发者需要知道一个内核指针是否有效。永远别在SEH区块内访问内核地址.