1、Summary of Kernel-Mode Support Routines
http://msdn.microsoft.com/en-us/library/ff563889%28VS.85%29.aspx
決不在核心模式服務函數的參數中使用帶有側效的運算式。
2、異常
對使用者模式虛擬記憶體直接引用的程式碼片段應該用結構化異常幀保護起來。這樣的引用通常發生在調用MmProbeAndLockPages、ProbeForRead,和ProbeForWrite函數時。
當異常發生時,作業系統通過掃描堆棧異常幀來尋找相應的例外處理常式。
圖示 結構化異常處理邏輯
顯示了對過濾函數的兩次調用。一次為了定位例外處理常式,另一次為了回卷堆棧。
如果你需要獲得更多的關於異常的資訊,有兩個函數可以在__except的求值運算式中調用,它們可以提供本次異常的相關資訊。實際上,這兩個函數是在Microsoft編譯器的內部實現的,所以僅能用於特定時刻:
•GetExceptionCode() 返回當前異常的數值代碼。該值是一個NTSTATUS值。該函數僅在__except運算式和其後的異常處理代碼中有效。
•GetExceptionInformation() 返回EXCEPTION_POINTERS結構的地址,該結構包含異常的所有詳細資料,在哪發生、發生時寄存器的內容,等等。該函數僅在__except運算式中有效。
產生異常
僅當你知道存在一個異常處理代碼並知道你真正在做什麼時,才可以在非任意線程上下文下產生一個異常。
RaiseException
ExRaiseStatus
ExRaiseAccessViolation
ExRaiseDatatypeMisalignment
有一個地方必須使用結構化異常處理機制,那就是當調用MmProbeAndLockPages函數鎖定被MDL(記憶體描述符表)使用的記憶體頁時,必須建立一個異常處理常式。對於WDM驅動程式,這個問題不經常出現,因為通常你使用的MDL都已經被其它程式探測並鎖定(probe-and-lock)過。但是,由於你可以定義使用METHOD_NEITHER緩衝方法的I/O控制(IOCTL)操作,所以你必須按下面方式寫代碼:
PMDL mdl = MmCreateMdl(...);
__try
{
MmProbeAndLockPages(mdl, ...);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
NTSTATUS status = GetExceptionCode();
ExFreePool((PVOID) mdl);
return CompleteRequest(Irp, status, 0);
}
程式可以在任何IRQL上調用KeBugCheckEx。如果程式發現一個不可恢複的錯誤,並且該程式繼續運行將會破壞系統,那麼該程式就調用KeBugCheckEx函數,這個函數將使系統以一種可控制的方式關閉。