FsRtlCancellableWaitForSingleObject 函式 (ntifs.h)

FsRtlCancellableWaitForSingleObject 例程會執行可取消的等候作業, (可以在發送器對象上終止) 等候。

語法

NTSTATUS FsRtlCancellableWaitForSingleObject(
  [in]           PVOID          Object,
  [in, optional] PLARGE_INTEGER Timeout,
  [in, optional] PIRP           Irp
);

參數

[in] Object

初始化發送器物件的指標, (事件、mutex、號誌、線程或定時器) ,呼叫者會為其提供記憶體。

[in, optional] Timeout

選擇性逾時值的指標。 此參數會以 100 奈秒的單位指定絕對或相對時間,等候完成。

如果 Timeout 指向零值 (即 *Timeout == 0) ,則例程會傳回而不等候。 如果呼叫端 (提供 NULL 指標,也就是 Timeout == NULL) ,則例程會無限期等候,直到物件設定為訊號狀態為止。

逾時 值會指定絕對時間,相對於 1601 年 1 月 1 日。 負 逾時 值會指定相對於目前時間的間隔。 絕對到期時間會追蹤系統時間中的任何變更。 相對到期時間不會受到系統時間變更的影響。

如果指定 Timeout ,當指定的間隔到期時,如果物件未設定為訊號狀態,就會自動滿足等候。

零 (逾時值,也就是 *Timeout == 0) 可讓您測試一組等候條件,並在等候可立即滿足時有條件地執行任何其他動作,如同取得 mutex 一樣。

[in, optional] Irp

與使用者發出且可由使用者取消之 I/O 作業相對應之原始 IRP 的指標。 呼叫端必須確定 IRP 在這段例程期間仍有效,而且 IRP 不能有取消例程集 (例如 ,IoSetCancelRoutine 不得在 IRP) 上呼叫。 請注意,呼叫端必須持有 IRP,它無法傳遞至較低層級的驅動程式。

傳回值

FsRtlCancellableWaitForSingleObject 可以傳回下列其中一個值:

傳回碼 Description
STATUS_SUCCESS Object 參數所指定的發送器對象滿足等候。
STATUS_TIMEOUT 物件設定為訊號狀態之前發生逾時。 當指定的等候條件集無法立即符合且 Timeout 設定為零時,可以傳回此值。
STATUS_ABANDONED_WAIT_0 呼叫端嘗試等候已放棄的 Mutex。
STATUS_CANCELLED 等候因指定 IRP 上的擱置取消要求而中斷。 請注意,只有當有效的 IRP 傳遞至 FsRtlCancellableWaitForSingleObject取消了 CancelSynchronousIo 取消 IRP 時,才會傳回此值。
STATUS_THREAD_IS_TERMINATING 等候已中斷,因為線程已由應用程式或用戶終止。

傳回值只會指出等候的狀態。 如果適用,應該直接從處理原始使用者模式 IRP 的過程中所產生的另一個 IRP 取得 I/O 要求的實際狀態。

請注意,NT_SUCCESS宏會針對 STATUS_CANCELLED其他所有狀態值傳回 FALSE (“failure”) ,STATUS_THREAD_IS_TERMINATING狀態值和 TRUE (“success”) 。

備註

FsRtlCancellableWaitForSingleObject 例程會在發送器對象上執行可取消的等候作業。 如果使用者或應用程式終止線程,或 CancelSynchronousIo 在線程的 IRP 上張貼取消要求, (與線程相關聯的同步 IRP) ,則會取消等候。

FsRtlCancellableWaitForSingleObject 例程的設計目的是為了支援從 Windows Vista 開始的 I/O 完成/取消指導方針。 這些指導方針的目標是允許使用者 (或應用程式) 快速終止應用程式。 接著,這需要應用程式能夠快速終止執行 I/O 的線程,以及任何目前的 I/O 作業。 此例程提供一種方式,讓使用者線程封鎖 (,也就是) 在核心中等候 I/O 完成、發送器物件或同步處理變數,以允許立即取消等候的方式。 如果線程由使用者或應用程式終止,此例程也允許線程的等候終止。

例如,重新導向器可能需要建立一或多個次要 IRP,才能處理使用者模式 IRP,並同步等候次要 IRP 完成。 其中一個做法是設定事件,該事件將由次要 IRP 的完成例程發出訊號,然後等候事件收到訊號。 然後,若要執行可取消的等候作業,則會呼叫 FsRtlCancellableWaitForSingleObject 傳入與次要 IRP 相關聯的事件,以及原始使用者模式 IRP。 如果發生擱置終止事件或原始使用者模式 IRP 已取消,線程等候事件發出訊號就會取消。

請注意,終止等候不會自動取消呼叫端所發出的任何 I/O 作業, 必須由呼叫端個別處理。

當傳遞至 FsRtlCancellableWaitForSingleObjectObject 參數是 mutex 時,適用特殊考慮。 如果等候的發送器對像是 mutex,則 APC 傳遞與等候期間所有其他發送器物件相同。 不過,一旦 FsRtlCancellableWaitForSingleObjects 傳回STATUS_SUCCESS,且線程實際上會保存 mutex,只會傳遞特殊的內核模式 APC。 已停用核心模式和使用者模式的所有其他 APC 傳遞。 在釋放 mutex 之前,傳遞 APC 的限制會持續存在。

Mutex 只能以遞歸方式取得MINLONG時間。 如果超過此限制,例程會引發STATUS_MUTANT_LIMIT_EXCEEDED例外狀況。

以下是如何使用 FsRtlCancellableWaitForSingleObject 來支援 I/O 完成/取消指導方針的範例

//
// 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,則必須在 IRQL PASSIVE_LEVEL呼叫 FsRtlCancellableWaitForSingleObject。 如果未使用 Irp 參數,可以在 IRQL 中呼叫例程小於或等於APC_LEVEL。 呼叫者可以視需要呼叫 KeEnterCriticalRegionFsRtlEnterFileSystem 例程來停用一般核心 APC。 不過,不得停用特殊核心 APC。

如果 IRQL 大於或等於APC_LEVEL,且選擇性 Irp 參數指向有效的 IRP,FsRtlCancellableWaitForSingleObject 將會判斷提示偵錯組建。

規格需求

需求
最低支援的用戶端 Windows Vista
目標平台 Universal
標頭 ntifs.h (包含 Ntifs.h)
程式庫 NtosKrnl.lib
Dll NtosKrnl.exe
IRQL 請參閱一節。
DDI 合規性規則 HwStorPortProhibitedDIS (storport) SpNoWait (storport)

另請參閱

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject