FsRtlCancellableWaitForSingleObject 関数 (ntifs.h)
FsRtlCancellableWaitForSingleObject ルーチンは、ディスパッチャー オブジェクトに対してキャンセル可能な待機操作 (終了可能な待機) を実行します。
構文
NTSTATUS FsRtlCancellableWaitForSingleObject(
[in] PVOID Object,
[in, optional] PLARGE_INTEGER Timeout,
[in, optional] PIRP Irp
);
パラメーター
[in] Object
呼び出し元がストレージを提供する初期化されたディスパッチャー オブジェクト (イベント、ミューテックス、セマフォ、スレッド、またはタイマー) へのポインター。
[in, optional] Timeout
省略可能なタイムアウト値へのポインター。 このパラメーターは、待機が完了する絶対時間または相対時間を 100 ナノ秒単位で指定します。
Timeout がゼロ値 (つまり、 *Timeout == 0) を指している場合、ルーチンは待機せずに戻ります。 呼び出し元が NULL ポインター (つまり、Timeout == NULL) を指定した場合、ルーチンはオブジェクトがシグナル状態に設定されるまで無期限に待機します。
正の タイムアウト 値は、1601 年 1 月 1 日を基準とした絶対時間を指定します。 タイムアウト 値
タイムアウト が指定されている場合、指定された間隔の有効期限が切れたときにオブジェクトがシグナル状態に設定されていない場合、待機は自動的に満たされます。
タイムアウト値 0 (つまり、*Timeout == 0) を使用すると、一連の待機条件をテストし、ミューテックスの取得のように、待機をすぐに満たすことができる場合は、条件付きで追加のアクションを実行できます。
[in, optional] Irp
ユーザーによって発行され、ユーザーが取り消すことができる I/O 操作に対応する元の IRP へのポインター。 呼び出し元は、IRP がこのルーチンの期間中有効であり、IRP がキャンセル ルーチンセットを持つ必要がないことを確認する必要があります (たとえば、IoSetCancelRoutine が IRP で呼び出されていない必要があります)。 IRP は呼び出し元が保持する必要があります。下位レベルのドライバーに渡すことはできません。
戻り値
FsRtlCancellableWaitForSingleObject は、次のいずれかの値を返すことができます。
リターン コード | 形容 |
---|---|
STATUS_SUCCESS | Object パラメーターで指定されたディスパッチャー オブジェクトが待機を満たしました。 |
STATUS_TIMEOUT | オブジェクトがシグナル状態に設定される前にタイムアウトが発生しました。 この値は、指定した待機条件のセットをすぐに満たすことができないときに、タイムアウト が 0 に設定 |
STATUS_ABANDONED_WAIT_0 | 呼び出し元が、破棄されたミューテックスを待機しようとしました。 |
STATUS_CANCELLED | 待機は、指定された IRP の保留中のキャンセル要求によって中断されました。 この値は、有効な IRP FsRtlCancellableWaitForSingleObject に渡され、CancelSynchronousIoによって IRP が取り消された場合にのみ返されることに注意してください。 |
STATUS_THREAD_IS_TERMINATING | スレッドがアプリケーションまたはユーザーによって終了されたため、待機が中断されました。 |
戻り値は、待機の状態のみを示します。 該当する場合は、元のユーザー モード IRP を処理するプロセスで生成された別の IRP から、I/O 要求の実際の状態を直接取得する必要があります。
NT_SUCCESS マクロは、STATUS_CANCELLEDおよびSTATUS_THREAD_IS_TERMINATING状態値に対して FALSE ("failure") を返し、その他のすべての状態値に対して TRUE ("success") を返します。
備考
FsRtlCancellableWaitForSingleObject ルーチンは、ディスパッチャー オブジェクトに対してキャンセル可能な待機操作を実行します。 スレッドがユーザーまたはアプリケーションによって終了された場合、または CancelSynchronousIo がスレッドに関連付けられているスレッド IRP (同期 IRP) にキャンセル要求を投稿した場合、待機は取り消されます。
たとえば、リダイレクターは、ユーザー モード IRP を処理し、セカンダリ IRP が完了するまで同期的に待機するために、1 つ以上のセカンダリ IRP を作成する必要がある場合があります。 これを行う 1 つの方法は、セカンダリ IRP の完了ルーチンによって通知されるイベントを設定し、イベントが通知されるまで待機することです。 次に、キャンセル可能な待機操作を実行するために、fsRtlCancellableWaitForSingleObject
待機を終了しても、呼び出し元によって発行された I/O 操作は自動的に取り消されません。呼び出し元が個別に処理する必要があります。
FsRtlCancellableWaitForSingleObject に渡される Object パラメーターがミューテックスである場合は、特別な考慮事項が適用されます。 待機中のディスパッチャー オブジェクトがミューテックスの場合、APC 配信は待機中の他のすべてのディスパッチャー オブジェクトの場合と同じです。 ただし、fsRtlCancellableWaitForSingleObjects が STATUS_SUCCESS で返され、スレッドが実際にミューテックスを保持すると、特殊なカーネル モードの APC のみが配信されます。 カーネル モードとユーザー モードの両方の他のすべての API の配信は無効になっています。 APC の配信に関するこの制限は、ミューテックスが解放されるまで保持されます。
ミューテックスは、MINLONG 回だけ再帰的に取得できます。 この制限を超えると、ルーチンはSTATUS_MUTANT_LIMIT_EXCEEDED例外を発生させます。
I/O 完了/取り消しガイドラインをサポートするために、FsRtlCancellableWaitForSingleObject を使用する方法の例を次に示します。
//
// sample calling routine
//
NTSTATUS ProcessIrpFromUserMode( PIRP pOriginalIrp, ... )
{
NTSTATUS Status;
NTSTATUS WaitStatus;
KEVENT Event;
LARGE_INTEGERTimeout;
PIRP pAdditionalIrp;
BOOLEAN Cancelled;
//
// Allocate the additional IRP here:
//
KeInitializeEvent( &Event,
SynchronizationEvent,
FALSE );
pContext->pEvent = &Event; // Driver specific context structure.
IoSetCompletionRoutine( pAdditionalIrp,
FunctionCompletionRoutine,
pContext,
TRUE,
TRUE,
TRUE);
Status = IoCallDriver( pDeviceObject, pAdditionalIrp );
if (Status == STATUS_PENDING) {
//
// Initialize Timeout variable here. If no timeout is needed, pass NULL for
// that parameter instead.
//
WaitStatus = FsRtlCancellableWaitForSingleObject( &Event,
&Timeout,
pOriginalIrp );
if ((WaitStatus == STATUS_CANCELLED) || (WaitStatus == STATUS_THREAD_IS_TERMINATING)) {
//
// Thread is terminating. IRP was canceled.
// Cancel the additional IRP passed to the lower level driver, cleanup, and return quickly.
//
Cancelled = IoCancelIrp( pAdditionalIrp );
if (!Cancelled || KeReadStateEvent( &Event ) == 0) {
//
// Wait for the IRP to complete.
// If cancel was posted successfully on the IRP, this shouldn't take a long time.
//
(VOID) KeWaitForSingleObject( &Event,
Executive,
KernelMode, // WaitMode
FALSE, // Alertable
(PLARGE_INTEGER) NULL );
}
} else if (WaitStatus == STATUS_TIMEOUT) {
//
// Wait timed out. The IRP was canceled or the API
// waited for the I/O to complete.
//
} else {
ASSERT( WaitStatus == STATUS_SUCCESS );
//
// The wait completed without timeout
// or being canceled.
//
}
}
//
// IRP is valid and needs to be handled here.
// pAdditionalIrp->IoStatus.Status contains the status of the IRP.
// Finally, pOriginal IRP needs to be completed appropriately as well.
//
}
//
// Sample completion routine:
//
NTSTATUS
FunctionCompletionRoutine(
IN PDEVICE_OBJECT pDeviceObject,
INOUT PIRP pAdditionalIrp,
IN PVOID pContext)
{
if (pAdditionalIrp->PendingReturned) {
KeSetEvent( pContext->pEvent, 0, FALSE );
}
//
// Discontinue I/O completion.
// Dispatch routine will deal with IRP.
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
省略可能な Irp パラメーターが有効な IRP を指している場合は、FsRtlCancellableWaitForSingleObject を IRQL PASSIVE_LEVELで呼び出す必要があります。 Irp パラメーターを使用しない場合は、IRQL でAPC_LEVEL以下でルーチンを呼び出すことができます。 通常のカーネル APCs は、必要に応じて、KeEnterCriticalRegion または FsRtlEnterFileSystem ルーチンを呼び出すことによって、呼び出し元によって無効にすることができます。 ただし、特殊なカーネル API は無効にしないでください。
FsRtlCancellableWaitForSingleObject は、IRQL がAPC_LEVEL以上で、オプションの Irp パラメーターが有効な IRP を指している場合、デバッグ ビルドでアサートされます。
必要条件
要件 | 価値 |
---|---|
サポートされる最小クライアント | Windows Vista |
ターゲット プラットフォーム の |
万国 |
ヘッダー | ntifs.h (Ntifs.h を含む) |
ライブラリ | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | 「解説」セクションを参照してください。 |
DDI コンプライアンス規則 を |
HwStorPortProhibitedDDIs(storport), SpNoWait(storport) |
関連項目
ExInitializeFastMutex の
FsRtlCancellableWaitForMultipleObjects
KeInitializeTimer の