PreviousMode

ユーザー モード アプリケーションが Nt または Zw バージョンのネイティブ システム サービス ルーチンを呼び出すと、システム呼び出しメカニズムでは呼び出し元のスレッドがカーネル モードにトラップされます。 パラメーター値がユーザー モードで発生したことを示すために、システム呼び出しのトラップ ハンドラーは、呼び出し元のスレッド オブジェクトPreviousMode フィールドを UserMode に設定します。 ネイティブ システム サービス ルーチンは、呼び出し元スレッドの PreviousMode フィールドをチェックして、パラメーターがユーザー モード ソースからのものかどうかを判断します。

カーネル モード ドライバーがネイティブ システム サービス ルーチンを呼び出し、カーネル モード ソースからのものであるルーチンにパラメーター値を渡す場合、ドライバーは、現在のスレッド オブジェクトの PreviousMode フィールドが KernelMode に設定されていることを確認する必要があります。

カーネル モード ドライバーは任意のスレッドのコンテキストで実行できるため、このスレッドの PreviousMode フィールドが UserMode に設定されている可能性があります。 この状況では、カーネル モード ドライバーは、Zw バージョンのネイティブ システム サービス ルーチンを呼び出して、パラメーター値が信頼されたカーネル モード ソースからのものであることをルーチンに通知することができます。 Zw 呼び出しは、現在のスレッド オブジェクトの PreviousMode 値をオーバーライドするシン ラッパー関数に移行します。 ラッパー関数は、PreviousModeKernelMode に設定し、Nt バージョンのルーチンを呼び出します。 Nt バージョンのルーチンからの復帰時に、ラッパー関数はスレッド オブジェクトの元の PreviousMode 値を復元してから復帰します。

カーネル モード ドライバーは、Nt バージョンのネイティブ システム サービス ルーチンを直接呼び出すことができます。 カーネル モード ドライバーは、ユーザー モードまたはカーネル モードで発生する I/O 要求を処理するとき、現在のスレッドの PreviousMode 値が呼び出し中に変更されないように、Nt バージョンのルーチンを呼び出すことができます。 NtXxx ルーチンは、呼び出し元のスレッドの PreviousMode 値をチェックして、パラメーター値がユーザー モード アプリケーションまたはカーネル モード コンポーネントからのものかどうかを判断し、それに応じて処理します。

カーネル モード ドライバーが NtXxx ルーチンを呼び出し、現在のスレッド オブジェクトの PreviousMode 値が、ユーザー モードまたはカーネル モードソースからのパラメーター値かどうかを正確に示していない場合に、エラーが発生する可能性があります。

たとえば、カーネル モード ドライバーが任意のスレッドのコンテキストで実行中で、このスレッドの PreviousMode 値が UserMode に設定されているとします。 ドライバーが NtClose ルーチンにカーネル モード ファイル ハンドルを渡す場合、このルーチンは PreviousMode 値をチェックし、ハンドルがユーザー モード ハンドルでなければならないことが決まります。 NtClose は、そのハンドルがユーザー モード ハンドル テーブルに見つからない場合、STATUS_INVALID_HANDLE エラー コードを返します。 一方、ドライバーは、閉じていないカーネル モード ハンドルをリークします。

別の例として、NtXxx ルーチンのパラメーターに入力バッファーまたは出力バッファーが含まれている場合で、PreviousMode = UserMode の場合、このルーチンは ProbeForRead ルーチンまたは ProbeForWrite ルーチンを呼び出してバッファーを検証します。 バッファーがユーザー モード メモリではなくシステム メモリに割り当てられた場合、ProbeForXxx ルーチンは例外を発生させ、NtXxx ルーチンは STATUS_ACCESS_VIOLATION エラー コードを返します。

必要に応じて、ドライバーは ExGetPreviousMode ルーチンを呼び出して、現在のスレッド オブジェクトから PreviousMode 値を取得できます。 または、ドライバーが、要求された I/O 操作を記述する IRP 構造体から RequestorMode フィールドを読み取ることができます。 RequestorMode フィールドには、操作を要求したスレッドからの PreviousMode 値のコピーが含まれています。