IRP_MN_EXECUTE_METHOD
データ ブロック内のメソッドをサポートするすべてのドライバーは、この IRP を処理する必要があります。 ドライバーは、「WMI 要求の処理」で説明されているように、WmiSystemControl を呼び出すか、ドライバー自身で IRP を処理することによって、WMI IRP を処理できます。
ドライバーが IRP_MN_EXECUTE_METHOD 要求を処理するために WmiSystemControl を呼び出すと、WMI はそのドライバーの DpWmiExecuteMethod ルーチンを呼び出します。
主要なコード
送信時
WMI は、この IRP を送信して、データ ブロックに関連付けられたメソッドを実行します。
WMI は任意のスレッド コンテキストで、IRQL = PASSIVE_LEVEL でこの IRP を送信します。
WMI は、IRP_MN_EXECUTE_METHODを送信する前に IRP_MN_QUERY_SINGLE_INSTANCE を送信します。 ドライバーが IRP_MN_EXECUTE_METHOD をサポートしている場合、そのドライバーには、メソッドが実行されているのと同じデータ ブロックの IRP_MN_QUERY_SINGLE_INSTANCE ハンドラーが必要です。
入力パラメーター
Parameters.WMI.ProviderId は、要求に応答する必要があるドライバーのデバイス オブジェクトを指します。 このポインターは、IRP のドライバーの I/O スタックの場所にあります。
Parameters.WMI.DataPath は、実行するメソッドに関連付けられているデータ ブロックを識別する GUID を指します。
Parameters.WMI.BufferSize は、Parameters.WMI.Buffer の非ページ バッファーのサイズを示します。これは、>= sizeof(WNODE_METHOD_ITEM) にメソッドの出力データのサイズを加算したものである必要があります。
Parameters.WMI.Buffer は、MethodID が実行するメソッドの識別子を示し、DataBlockOffset が構造体の先頭から入力データの最初のバイトまでのオフセット (ある場合) をバイト単位で示す、WNODE_METHOD_ITEM構造体を指します。 Parameters.WMI.Buffer->SizeDataBlock は、入力データを含む入力 WNODE_METHOD_ITEM のサイズをバイト単位で示します。入力がない場合は 0 を示します。
出力パラメーター
ドライバーが WmiSystemControl を呼び出して WMI IRP を処理すると、WMI はドライバーの DpWmiExecuteMethod ルーチンによって返されたデータを WNODE_METHOD_ITEM に入力します。
それ以外の場合は、ドライバーは Parameters.WMI.Buffer が指す WNODE_METHOD_ITEM 構造体を次のように入力します。
出力データを含む出力 WNODE_METHOD_ITEM のサイズで WnodeHeader.BufferSize を更新します。
SizeDataBlock を、出力データのサイズで指定します。出力データがない場合は 0 を指定します。
Parameters.WMI.Buffersize をチェックして、バッファーが、出力データを含む出力 WNODE_METHOD_ITEM を受信するのに十分な大きさであるかどうかを判断します。 バッファーが十分な大きさでない場合、ドライバーは Parameters.WMI.Buffer が指す WNODE_TOO_SMALL 構造体に必要なサイズを入力します。 バッファーが sizeof(WNODE_TOO_SMALL) より小さい場合、ドライバーは IRP に失敗し、STATUS_BUFFER_TOO_SMALL を返します。
DataBlockOffset 以降の入力データの上に出力データ (ある場合) を書き込みます。 ドライバーは、DataBlockOffset の入力値を変更することはできません。
I/O 状態ブロック
ドライバーが WmiSystemControl を呼び出して IRP を処理する場合、WMI は I/O 状態ブロックで Irp->IoStatus.Status と Irp->IoStatus.Information を設定します。
それ以外の場合、ドライバーは Irp->IoStatus.Status を STATUS_SUCCESS または次のような適切なエラー状態に設定します。
STATUS_BUFFER_TOO_SMALL
STATUS_WMI_GUID_NOT_FOUND
STATUS_WMI_INSTANCE_NOT_FOUND
STATUS_WMI_ITEMID_NOT_FOUND
成功した場合、ドライバーは Irp->IoStatus.Information を Parameters.WMI.Buffer でバッファーに書き込まれたバイト数に設定します。
操作
ドライバーは、「WMI 要求の処理」で説明されているように、WmiSystemControl を呼び出すか、ドライバー自身で IRP を処理することによって、WMI IRP を処理できます。
ドライバーが、WmiSystemControl を呼び出して WMI IRP を処理すると、そのルーチンはドライバーの DpWmiExecuteMethod ルーチンを呼び出します。ドライバーがそのルーチンを定義していない場合は、STATUS_INVALID_DEVICE_REQUEST を返します。
IRP_MN_EXECUTE_METHOD 要求をドライバー自身が処理する場合、Parameters.WMI.ProviderId が、ドライバーが IoWMIRegistrationControl に渡したポインターと同じデバイス オブジェクトを指している場合にのみ、ドライバーはこの処理を行う必要があります。 それ以外の場合、ドライバーは、次の下位ドライバーに要求を転送する必要があります。
ドライバーは、すべての入力値の検証を担当します。 具体的には、ドライバーは IRP 要求自体を処理する場合に、次の操作を行う必要があります。
静的な名前の場合は、WNODE_METHOD_ITEM 構造体の InstanceIndex メンバーが、データ ブロックのドライバーでサポートされているインスタンス インデックスの範囲内にあることを確認します。
動的な名前の場合は、インスタンス名の文字列が、ドライバーでサポートされているデータ ブロック インスタンスを識別することを確認します。
WNODE_METHOD_ITEM 構造体の MethodId メンバーが、データ ブロックのドライバーでサポートされているメソッド識別子の範囲内にあり、呼び出し元がメソッドの実行を許可されていることを確認します。
WNODE_METHOD_ITEM 構造体の DataBlockOffset メンバーと SizeDataBlock メンバーが、指定したメソッドのパラメーターを格納するのに十分な大きさのバッファーを記述していること、およびパラメーターがメソッドに対して有効であることを確認します。
Parameters.WMI.Buffersize が、出力データで更新された後に WNODE_METHOD_ITEM 構造体を受け取るのに十分な大きさのバッファーを指定していることを確認します。
スレッド コンテキストが、開始したユーザー モード アプリケーションのコンテキストであると想定しないでください。上位レベルのドライバーによって変更されている可能性があります。
要求を処理する前に、ドライバーは Parameters.WMI.DataPath がドライバーでサポートされている GUID を指しているかどうかを判断する必要があります。 指してない場合は、ドライバーは IRP に失敗し、STATUS_WMI_GUID_NOT_FOUND を返す必要があります。
ドライバーは、データ ブロックをサポートしている場合、Parameters.WMI.Buffer の入力 WNODE_METHOD_ITEM でインスタンス名を次のようにチェックします。
WNODE_FLAG_STATIC_INSTANCE_NAMES が WnodeHeader.Flags で設定されている場合は、ドライバーは、そのブロックの静的インスタンス名のドライバーのリストにインデックスとして InstanceIndex を使用します。 WMI は、ブロックを登録したときにドライバーによって提供された登録データからインデックスを取得します。
WnodeHeader.Flags で WNODE_FLAG_STATIC_INSTANCE_NAMES がクリアされている場合、ドライバーは OffsetInstanceName のオフセットを使用して、入力 WNODE_METHOD_ITEM 内のインスタンス名の文字列を検索します。 OffsetInstanceName は、構造体の先頭から、インスタンス名文字列のバイト単位 (文字ではない) での長さである USHORT までの、バイト単位のオフセットです。存在する場合は終端の null が含まれ、Unicode のインスタンス名文字列がその後に続きます。
ドライバーは、指定したインスタンスを見つけることができない場合、IRP に失敗して、STATUS_WMI_INSTANCE_NOT_FOUND を返す必要があります。 動的インスタンス名を持つインスタンスの場合、この状態はドライバーがインスタンスをサポートしていないことを示します。 そのため、WMI は他のデータ プロバイダーに対してクエリを実行し続けることができ、別のプロバイダーがインスタンスを見つけたが何らかの理由で要求を処理できない場合は、データ コンシューマーに適切なエラーを返すことができます。
その後、ドライバーは入力 WNODE_METHOD_ITEM のメソッド ID をチェックして、そのデータ ブロックの有効なメソッドであるかどうかを判断します。 有効でない場合、ドライバーは IRP に失敗して、STATUS_WMI_ITEMID_NOT_FOUND を返します。
メソッドが出力を生成する場合、ドライバーは、副次的影響が生じる可能性がある操作、または 2 回実行すべきでない操作を実行する前に、Parameters.WMI.BufferSize の出力バッファーのサイズをチェックする必要があります。 たとえば、メソッドがカウンターのグループの値を返し、カウンターをリセットする場合、ドライバーは、カウンターをリセットする前にバッファー サイズをチェックする必要があります (バッファーが小さすぎる場合は、IRP に失敗します)。 これにより、WMI は、より大きなバッファーで要求を安全に再送信できます。
インスタンスとメソッド ID が有効で、バッファーのサイズが十分な場合、ドライバーはメソッドを実行します。 入力 WNODE_METHOD_ITEM の SizeDataBlock が 0 以外の場合、ドライバーは DataBlockOffset 以降のデータをメソッドの入力として使用します。
メソッドが出力を生成する場合、ドライバーは DataBlockOffset で始まるバッファーに出力データを書き込み、出力 WNODE_METHOD_ITEM の SizeDataBlock を出力データのバイト数に設定します。 メソッドに出力データがない場合、ドライバーは SizeDataBlock を 0 に設定します。 ドライバーは、DataBlockOffset の入力値を変更することはできません。
インスタンスが有効であっても、ドライバーが要求を処理できない場合は、適切なエラー状態を返すことができます。
要件
ヘッダー |
Wdm.h (Wdm.h、Ntddk.h、Ntifs.h を含む) |