共用方式為


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 == 0),例程會傳回而不等候。 如果呼叫端提供 NULL 指標(也就是 Timeout == NULL),則例程會無限期等候,直到物件設定為訊號狀態為止。

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

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

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

[in, optional] Irp

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

傳回值

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

傳回碼 描述
STATUS_SUCCESS Object 參數所指定的發送器物件滿足等候。
STATUS_TIMEOUT 物件設定為訊號狀態之前發生逾時。 當無法立即符合指定的等候條件集,且 逾時 設為零時,就可以傳回此值。
STATUS_ABANDONED_WAIT_0 呼叫端嘗試等候已放棄的 Mutex。
STATUS_CANCELLED 等候因指定 IRP 上的擱置取消要求而中斷。 請注意,只有當有效的 IRP 傳遞至 FsRtlCancellableWaitForSingleObject,且 IRP 已由 cancelSynchronousIo 取消時,才會傳回此值。
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;
}

FsRtlCancellableWaitForSingleObject 必須在 IRQL PASSIVE_LEVEL呼叫,如果選擇性 Irp 參數指向有效的 IRP。 如果未使用 Irp 參數,則可以在 IRQL 呼叫例程,或小於或等於 APC_LEVEL。 呼叫端可以視需要呼叫 KeEnterCriticalRegionFsRtlEnterFileSystem 例程來停用一般核心 APC。 不過,不得停用特殊核心 APC。

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

要求

要求 價值
最低支援的用戶端 Windows Vista
目標平臺 普遍
標頭 ntifs.h (include Ntifs.h)
連結庫 NtosKrnl.lib
DLL NtosKrnl.exe
IRQL 請參閱一節。
DDI 合規性規則 HwStorPortProhibitedDIs(storport)SpNoWait(storport)

另請參閱

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject