Freigeben über


FsRtlCancellableWaitForSingleObject-Funktion (ntifs.h)

Die FsRtlCancellableWaitForSingleObject-Routine führt einen abbruchbaren Wartevorgang (eine Wartezeit, die beendet werden kann) für ein Dispatcherobjekt aus.

Syntax

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

Parameter

[in] Object

Ein Zeiger auf ein initialisiertes Dispatcherobjekt (Ereignis, Mutex, Semaphor, Thread oder Timer), für das der Aufrufer den Speicher bereitstellt.

[in, optional] Timeout

Ein Zeiger auf einen optionalen Timeoutwert. Dieser Parameter gibt die absolute oder relative Zeit in 100 Nanosekundeneinheiten an, bei der die Wartezeit abgeschlossen werden soll.

Wenn Timeout auf einen Nullwert (d. h. *Timeout == 0) verweist, wird die Routine ohne Wartezeit zurückgegeben. Wenn der Aufrufer einen NULL-Zeiger (d. h. Timeout == NULL) bereitstellt, wartet die Routine unbegrenzt, bis das Objekt auf den signalierten Zustand festgelegt ist.

Ein positiver Timeoutwert gibt eine absolute Zeit im Verhältnis zum 1. Januar 1601 an. Ein negativer Timeoutwert gibt ein Intervall relativ zur aktuellen Zeit an. Absolute Ablaufzeiten verfolgen alle Änderungen der Systemzeit nach. Relative Ablaufzeiten werden von Systemzeitänderungen nicht beeinflusst.

Wenn Timeout angegeben wird, wird die Wartezeit automatisch erfüllt, wenn das Objekt beim Ablauf des angegebenen Intervalls nicht auf den signalierten Zustand festgelegt ist.

Ein Timeoutwert von 0 (d. h. *Timeout == 0) ermöglicht es Ihnen, eine Reihe von Wartebedingungen zu testen und alle zusätzlichen Aktionen bedingt auszuführen, wenn die Wartezeit sofort erfüllt werden kann, wie beim Erwerb eines Mutex.

[in, optional] Irp

Ein Zeiger auf den ursprünglichen IRP, der dem E/A-Vorgang entspricht, der vom Benutzer ausgegeben wurde und vom Benutzer abgebrochen werden kann. Der Aufrufer muss sicherstellen, dass die IRP für die Dauer dieser Routine gültig bleibt und dass die IRP keinen Abbruchroutinsatz aufweisen darf (z. B. darf IoSetCancelRoutine nicht auf der IRP aufgerufen worden sein). Beachten Sie, dass die IRP vom Aufrufer gehalten werden muss und nicht an einen Treiber auf niedrigerer Ebene übergeben werden kann.

Rückgabewert

FsRtlCancellableWaitForSingleObject kann einen der folgenden Werte zurückgeben:

Rückgabecode Beschreibung
STATUS_SUCCESS Das vom Object-Parameter angegebene Dispatcherobjekt hat die Wartezeit erfüllt.
STATUS_TIMEOUT Ein Timeout ist aufgetreten, bevor das Objekt auf einen Signalzustand festgelegt wurde. Dieser Wert kann zurückgegeben werden, wenn der angegebene Satz von Wartebedingungen nicht sofort erfüllt werden kann und timeout auf 0 festgelegt ist.
STATUS_ABANDONED_WAIT_0 Der Aufrufer hat versucht, auf einen Mutex zu warten, der verlassen wurde.
STATUS_CANCELLED Die Wartezeit wurde durch eine ausstehende Abbruchanforderung für die angegebene IRP unterbrochen. Beachten Sie, dass dieser Wert nur zurückgegeben wird, wenn ein gültiger IRP an FsRtlCancellableWaitForSingleObject übergeben wird und der IRP von CancelSynchronousIo abgebrochen wurde.
STATUS_THREAD_IS_TERMINATING Die Wartezeit wurde unterbrochen, da der Thread von einer Anwendung oder dem Benutzer beendet wurde.

Der Rückgabewert gibt nur die status der Wartezeit an. Falls zutreffend, sollte die tatsächliche status der E/A-Anforderung direkt von einem anderen IRP abgerufen werden, das bei der Verarbeitung der ursprünglichen Benutzermodus-IRP generiert wurde.

Beachten Sie, dass das makro NT_SUCCESS false ("fehler") für die werte STATUS_CANCELLED und STATUS_THREAD_IS_TERMINATING status und true ("success") für alle anderen status werte zurückgibt.

Hinweise

Die FsRtlCancellableWaitForSingleObject-Routine führt einen abbruchbaren Wartevorgang für ein Dispatcherobjekt aus. Wenn der Thread vom Benutzer oder von der Anwendung beendet wird oder CancelSynchronousIo eine Abbruchanforderung für eine dem Thread zugeordnete IRP (synchrone IRP) sendet, wird die Wartezeit abgebrochen.

Die FsRtlCancellableWaitForSingleObject-Routine wurde für die Unterstützung der E/A-Vervollständigungs-/Abbruchrichtlinien ab Windows Vista entwickelt. Ziel dieser Richtlinien ist es, Benutzern (oder Anwendungen) das schnelle Beenden von Anwendungen zu ermöglichen. Dies setzt wiederum voraus, dass Anwendungen in der Lage sind, Threads, die E/A-Vorgänge ausführen, sowie alle aktuellen E/A-Vorgänge schnell zu beenden. Diese Routine bietet eine Möglichkeit für Benutzerthreads, im Kernel für die E/A-Vervollständigung, ein Dispatcherobjekt oder eine Synchronisierungsvariable zu blockieren (d. h. warten), sodass die Wartezeit problemlos abgebrochen werden kann. Diese Routine ermöglicht es auch, dass die Wartezeit des Threads beendet wird, wenn der Thread von einem Benutzer oder einer Anwendung beendet wird.

Beispielsweise muss ein Redirector möglicherweise mindestens eine sekundäre IRPs erstellen, um eine Benutzermodus-IRP zu verarbeiten, und synchron warten, bis die sekundären IRPs abgeschlossen sind. Eine Möglichkeit besteht darin, ein Ereignis einzurichten, das von der Abschlussroutine des sekundären IRP signalisiert wird, und dann zu warten, bis das Ereignis signalisiert wird. Um dann einen abbruchbaren Wartevorgang auszuführen, wird FsRtlCancellableWaitForSingleObject im Ereignis übergeben genannt, das dem sekundären IRP zugeordnet ist, sowie das ursprüngliche Benutzermodus-IRP. Die Wartezeit des Threads auf die Signalisierung des Ereignisses wird abgebrochen, wenn ein ausstehendes Beendigungsereignis auftritt oder das ursprüngliche Benutzermodus-IRP abgebrochen wird.

Beachten Sie, dass das Beenden der Wartezeit nicht automatisch alle E/A-Vorgänge abbricht, die vom Aufrufer ausgegeben werden. Dies muss vom Aufrufer separat behandelt werden.

Ein besonderer Aspekt gilt, wenn der anFsRtlCancellableWaitForSingleObject übergebene Object-Parameter ein Mutex ist. Wenn das Dispatcherobjekt, für das gewartet wird, ein Mutex ist, ist die APC-Übermittlung identisch mit allen anderen Dispatcherobjekten während der Wartezeit. Sobald FsRtlCancellableWaitForSingleObjects mit STATUS_SUCCESS zurückgegeben wird und der Thread tatsächlich den Mutex enthält, werden nur spezielle Kernelmodus-APCs bereitgestellt. Die Übermittlung aller anderen APCs, sowohl im Kernelmodus als auch im Benutzermodus, ist deaktiviert. Diese Einschränkung für die Übermittlung von APCs bleibt bestehen, bis der Mutex freigegeben wird.

Ein Mutex kann nur minlong-mal rekursiv erworben werden. Wenn dieser Grenzwert überschritten wird, löst die Routine eine STATUS_MUTANT_LIMIT_EXCEEDED Ausnahme aus.

Im Folgenden finden Sie ein Beispiel für die Verwendung von FsRtlCancellableWaitForSingleObject zur Unterstützung der E/A-Vervollständigungs-/Abbruchrichtlinien.

//
// 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 muss am IRQL-PASSIVE_LEVEL aufgerufen werden, wenn der optionale Irp-Parameter auf eine gültige IRP verweist. Wenn der Irp-Parameter nicht verwendet wird, kann die Routine bei IRQL kleiner oder gleich APC_LEVEL aufgerufen werden. Normale Kernel-APCs können vom Aufrufer bei Bedarf deaktiviert werden, indem die Routinen KeEnterCriticalRegion oder FsRtlEnterFileSystem aufgerufen werden. Spezielle Kernel-APCs dürfen jedoch nicht deaktiviert werden.

FsRtlCancellableWaitForSingleObject wird bei Debugbuilds behauptet, wenn der IRQL größer oder gleich APC_LEVEL ist und der optionale Irp-Parameter auf eine gültige IRP verweist.

Anforderungen

Anforderung Wert
Unterstützte Mindestversion (Client) Windows Vista
Zielplattform Universell
Header ntifs.h (include Ntifs.h)
Bibliothek NtosKrnl.lib
DLL NtosKrnl.exe
IRQL Weitere Informationen finden Sie im Abschnitt mit den Hinweisen.
DDI-Complianceregeln HwStorPortProhibitedDDIs(storport), SpNoWait(storport)

Weitere Informationen

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphor

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject