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 denen die Wartezeit abgeschlossen werden soll.

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

Ein positiver Timeout-wert gibt eine absolute Zeit relativ zum 1. Januar 1601 an. Ein negativer Timeout-wert gibt ein Intervall relativ zur aktuellen Uhrzeit an. Absolute Ablaufzeiten verfolgen alle Änderungen in der Systemzeit. Relative Ablaufzeiten sind von Systemzeitänderungen nicht betroffen.

Wenn Timeout- angegeben ist, wird die Wartezeit automatisch erfüllt, wenn das Objekt nicht auf den signalierten Zustand festgelegt ist, wenn das angegebene Intervall abläuft.

Ein Timeoutwert von Null (d. h. *Timeout == 0) ermöglicht es Ihnen, eine Reihe von Wartezeitbedingungen 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 das ursprüngliche IRP, das dem vom Benutzer ausgestellten E/A-Vorgang entspricht und vom Benutzer abgebrochen werden kann. Der Aufrufer muss sicherstellen, dass das IRP für die Dauer dieser Routine gültig bleibt und dass der IRP keinen Abbruchroutinsatz aufweisen darf (z. B. IoSetCancelRoutine nicht für das IRP aufgerufen worden sein darf). Beachten Sie, dass das IRP vom Aufrufer gehalten werden muss, es kann nicht an einen Treiber auf niedrigerer Ebene übergeben werden.

Rückgabewert

FsRtlCancellableWaitForSingleObject kann einen der folgenden Werte zurückgeben:

Rückgabecode Beschreibung
STATUS_SUCCESS Das dispatcher-Objekt, das vom parameter Object angegeben wird, erfüllte die Wartezeit.
STATUS_TIMEOUT Ein Timeout ist aufgetreten, bevor das Objekt auf einen signalgesteuerten Zustand festgelegt wurde. Dieser Wert kann zurückgegeben werden, wenn der angegebene Satz von Wartebedingungen nicht sofort erfüllt werden kann, und Timeout- auf Null festgelegt ist.
STATUS_ABANDONED_WAIT_0 Der Aufrufer hat versucht, auf einen Mutex zu warten, der abgebrochen wurde.
STATUS_CANCELLED Die Wartezeit wurde durch eine ausstehende Abbruchanforderung für das angegebene IRP unterbrochen. Beachten Sie, dass dieser Wert nur zurückgegeben wird, wenn ein gültiges IRP an FsRtlCancellableWaitForSingleObject übergeben wird und das IRP von CancelSynchronousIoabgebrochen 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 den Status der Wartezeit an. Falls zutreffend, sollte der tatsächliche Status der E/A-Anforderung direkt von einem anderen IRP abgerufen werden, das beim Verarbeiten des ursprünglichen Benutzermodus-IRP generiert wird.

Beachten Sie, dass das NT_SUCCESS Makro FALSCH ("Fehler") für die STATUS_CANCELLED und STATUS_THREAD_IS_TERMINATING Statuswerte und WAHR ("Erfolg") für alle anderen Statuswerte zurückgibt.

Bemerkungen

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 wenn CancelSynchronousIo eine Abbruchanforderung für einen Thread-IRP (synchrones IRP) veröffentlicht, der dem Thread zugeordnet ist, wird die Wartezeit abgebrochen.

Die FsRtlCancellableWaitForSingleObject Routine wurde für die Unterstützung der I/O Completion/Cancellation Guidelines beginnend mit Windows Vista entwickelt. Ziel dieser Richtlinien ist es, Benutzern (oder Anwendungen) das schnelle Beenden von Anwendungen zu ermöglichen. Dies wiederum erfordert, dass Anwendungen die Möglichkeit haben, Threads, die E/A sowie aktuelle E/A-Vorgänge ausführen, schnell zu beenden. Diese Routine bietet eine Möglichkeit für Benutzerthreads zum Blockieren (d. h. Warten) im Kernel für den Abschluss von E/A, ein Verteilerobjekt oder eine Synchronisierungsvariable auf eine Weise, mit der die Wartezeit leicht abgebrochen werden kann. Diese Routine ermöglicht auch, dass die Wartezeit des Threads beendet wird, wenn der Thread von einem Benutzer oder einer Anwendung beendet wird.

Beispielsweise muss ein Umleitungsmodul einen oder mehrere sekundäre IRPs erstellen, um einen Benutzermodus-IRP zu verarbeiten und synchron zu warten, bis die sekundären IRPs abgeschlossen sind. Eine Möglichkeit hierfür ist das Einrichten eines Ereignisses, das durch die Abschlussroutine des sekundären IRP signalisiert wird und dann darauf wartet, dass das Ereignis signalisiert wird. Um dann einen abbruchbaren Wartevorgang auszuführen, wird FsRtlCancellableWaitForSingleObject aufgerufen, das dem sekundären IRP zugeordnete Ereignis sowie das ursprüngliche Benutzermodus-IRP zu übergeben. Die Wartezeit des Threads, bis das Ereignis signalisiert wird, wird abgebrochen, wenn ein ausstehendes Beendigungsereignis auftritt oder das ursprüngliche Benutzermodus-IRP abgebrochen wird.

Beachten Sie, dass das Beenden der Wartezeit keinen E/A-Vorgang, der vom Anrufer ausgegeben wird, automatisch abbricht – der vom Anrufer separat behandelt werden muss.

Eine besondere Berücksichtigung gilt, wenn der Object-Parameter, der an FsRtlCancellableWaitForSingleObject übergeben wird, ein Mutex ist. Wenn das dispatcher-Objekt, auf das gewartet wird, ein Mutex ist, ist die APC-Zustellung identisch mit allen anderen Dispatcherobjekten während der Wartezeit. Sobald FsRtlCancellableWaitForSingleObjects jedoch 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 vom Kernelmodus als auch vom Benutzermodus, ist deaktiviert. Diese Einschränkung für die Bereitstellung von APCs bleibt bestehen, bis der Mutex freigegeben wird.

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

Im Folgenden sehen Sie ein Beispiel für die Verwendung FsRtlCancellableWaitForSingleObject- zur Unterstützung der Richtlinien für Abschluss/Abbruch.

//
// 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 bei IRQL-PASSIVE_LEVEL aufgerufen werden, wenn der optionale Irp Parameter auf ein gültiges 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 bei Bedarf vom Aufrufer deaktiviert werden, indem die KeEnterCriticalRegion oder FsRtlEnterFileSystem Routinen aufgerufen werden. Spezielle Kernel-APCs dürfen jedoch nicht deaktiviert werden.

FsRtlCancellableWaitForSingleObject wird auf Debugbuilds bestätigt, wenn die IRQL größer oder gleich APC_LEVEL ist und der optionale Irp Parameter auf ein gültiges IRP verweist.

Anforderungen

Anforderung Wert
mindestens unterstützte Client- Windows Vista
Zielplattform- Universal
Header- ntifs.h (einschließlich Ntifs.h)
Library NtosKrnl.lib
DLL- NtosKrnl.exe
IRQL- Siehe Abschnitt "Hinweise".
DDI-Complianceregeln HwStorPortProhibitedDIs(storport), SpNoWait(storport)

Siehe auch

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex-

KeInitializeSemaphor

KeInitializeTimer-

KeWaitForMultipleObjects

KeWaitForSingleObject