Partager via


FsRtlCancellableWaitForSingleObject, fonction (ntifs.h)

La routine FsRtlCancellableWaitForSingleObject exécute une opération d’attente annulable (une attente pouvant être arrêtée) sur un objet répartiteur.

Syntaxe

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

Paramètres

[in] Object

Pointeur vers un objet de répartiteur initialisé (événement, mutex, sémaphore, thread ou minuteur) pour lequel l’appelant fournit le stockage.

[in, optional] Timeout

Pointeur vers une valeur de délai d’attente facultative. Ce paramètre spécifie l’heure absolue ou relative, en 100 nanosecondes, à laquelle l’attente doit être terminée.

Si délai d’expiration pointe vers une valeur zéro (autrement dit, *Délai d’expiration == 0), la routine est retournée sans attendre. Si l’appelant fournit un pointeur NULL (autrement dit, Délai d’expiration == NULL), la routine attend indéfiniment jusqu’à ce que l’objet soit défini sur l’état signalé.

Une valeur timeout positive spécifie une heure absolue, par rapport au 1er janvier 1601. Une valeur timeout négative spécifie un intervalle par rapport à l’heure actuelle. Les heures d’expiration absolues suivent les modifications apportées à l’heure système. Les délais d’expiration relatifs ne sont pas affectés par les modifications de temps système.

Si délai d’expiration est spécifié, l’attente est automatiquement satisfaite si l’objet n’est pas défini sur l’état signalé lorsque l’intervalle donné expire.

Une valeur de délai d’attente égale à zéro (autrement dit, *Délai d’expiration == 0) vous permet de tester un ensemble de conditions d’attente et d’effectuer de manière conditionnelle toutes les actions supplémentaires si l’attente peut être immédiatement satisfaite, comme dans l’acquisition d’un mutex.

[in, optional] Irp

Pointeur vers l’IRP d’origine qui correspond à l’opération d’E/S qui a été émise par l’utilisateur et qui peut être annulée par l’utilisateur. L’appelant doit s’assurer que l’IRP restera valide pendant la durée de cette routine et que l’IRP ne doit pas avoir de routine d’annulation définie (par exemple, IoSetCancelRoutine ne doit pas avoir été appelé sur l’IRP). Notez que l’IRP doit être détenu par l’appelant, il ne peut pas être transmis à un pilote de niveau inférieur.

Valeur de retour

FsRtlCancellableWaitForSingleObject pouvez retourner l’une des valeurs suivantes :

Retourner le code Description
STATUS_SUCCESS L’objet répartiteur spécifié par le paramètre Object satisfait l’attente.
STATUS_TIMEOUT Un délai d’attente s’est produit avant que l’objet ait été défini sur un état signalé. Cette valeur peut être retournée lorsque l’ensemble spécifié de conditions d’attente ne peut pas être immédiatement rempli et délai d’expiration est défini sur zéro.
STATUS_ABANDONED_WAIT_0 L’appelant a tenté d’attendre un mutex abandonné.
STATUS_CANCELLED L’attente a été interrompue par une demande d’annulation en attente sur l’IRP spécifié. Notez que cette valeur est retournée uniquement si un IRP valide est transmis à FsRtlCancellableWaitForSingleObject et que l’IRP a été annulé par CancelSynchronousIo.
STATUS_THREAD_IS_TERMINATING L’attente a été interrompue, car le thread a été arrêté par une application ou l’utilisateur.

La valeur de retour indique uniquement l’état de l’attente. Le cas échéant, l’état réel de la demande d’E/S doit être obtenu directement à partir d’un autre IRP généré dans le processus de gestion de l’IRP en mode utilisateur d’origine.

Notez que la macro NT_SUCCESS retourne FALSE (« échec ») pour les valeurs d’état STATUS_CANCELLED et STATUS_THREAD_IS_TERMINATING et TRUE (« réussite ») pour toutes les autres valeurs d’état.

Remarques

La routine FsRtlCancellableWaitForSingleObject exécute une opération d’attente annulable sur un objet répartiteur. Si le thread est arrêté par l’utilisateur ou par l’application, ou si CancelSynchronousIo publie une demande d’annulation sur un IRP threadé (IRP synchrone) associé au thread, l’attente est annulée.

La routine FsRtlCancellableWaitForSingleObject a été conçue pour prendre en charge les instructions d’achèvement/annulation des E/S à partir de Windows Vista. L’objectif de ces instructions est de permettre aux utilisateurs (ou applications) de mettre rapidement fin aux applications. Cela nécessite que les applications aient la possibilité de mettre fin rapidement aux threads qui exécutent des E/S ainsi qu’à toutes les opérations d’E/S actuelles. Cette routine permet aux threads utilisateur de bloquer (c’est-à-dire d’attendre) dans le noyau pour l’achèvement des E/S, d’un objet de répartiteur ou d’une variable de synchronisation d’une manière qui permet d’annuler facilement l’attente. Cette routine autorise également l’arrêt de l’attente du thread si le thread est arrêté par un utilisateur ou une application.

Par exemple, un redirecteur peut avoir besoin de créer un ou plusieurs IRP secondaires afin de traiter un IRP en mode utilisateur et d’attendre de façon synchrone que les IRP secondaires se terminent. Pour ce faire, vous devez configurer un événement qui sera signalé par la routine d’achèvement de l’IRP secondaire, puis attendez que l’événement soit signalé. Ensuite, pour effectuer une opération d’attente annulable, FsRtlCancellableWaitForSingleObject est appelée transmission de l’événement associé à l’IRP secondaire, ainsi que l’IRP en mode utilisateur d’origine. L’attente du thread pour que l’événement soit signalé est annulé si un événement d’arrêt en attente se produit ou si l’IRP en mode utilisateur d’origine est annulé.

Notez que la fin de l’attente n’annule pas automatiquement toutes les opérations d’E/S émises par l’appelant, qui doivent être gérées séparément par l’appelant.

Une considération particulière s’applique lorsque le paramètre Object passé à FsRtlCancellableWaitForSingleObject est un mutex. Si l’objet répartiteur sur lequel l’attente est activée est un mutex, la remise d’APC est la même que pour tous les autres objets de répartiteur pendant l’attente. Toutefois, une fois FsRtlCancellableWaitForSingleObjects retourne avec STATUS_SUCCESS et le thread contient réellement le mutex, seules les API en mode noyau spécial sont remises. La remise de toutes les autres API, en mode noyau et en mode utilisateur, est désactivée. Cette restriction sur la remise des API persiste jusqu’à ce que le mutex soit libéré.

Un mutex peut être acquis de manière récursive uniquement à des heures MINLONG. Si cette limite est dépassée, la routine déclenche une exception STATUS_MUTANT_LIMIT_EXCEEDED.

Voici un exemple d’utilisation de FsRtlCancellableWaitForSingleObject à la prise en charge des instructions d’achèvement/annulation d’E/S .

//
// 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 doit être appelée au PASSIVE_LEVEL IRQL si le paramètre Irp facultatif pointe vers un I RP valide. Si le paramètre Irp n’est pas utilisé, la routine peut être appelée au niveau irQL inférieur ou égal à APC_LEVEL. Les API de noyau normales peuvent être désactivées par l’appelant, si nécessaire, en appelant les routines KeEnterCriticalRegion ou FsRtlEnterFileSystem. Toutefois, les API de noyau spéciales ne doivent pas être désactivées.

FsRtlCancellableWaitForSingleObject s’affirme sur les builds de débogage si le runtime d’intégration est supérieur ou égal à APC_LEVEL et que le paramètre facultatif Irp pointe vers un IRP valide.

Exigences

Exigence Valeur
client minimum pris en charge Windows Vista
plateforme cible Universel
d’en-tête ntifs.h (include Ntifs.h)
bibliothèque NtosKrnl.lib
DLL NtosKrnl.exe
IRQL Voir la section Remarques.
règles de conformité DDI HwStorPortProhibitedDDIs(storport), SpNoWait(storport)

Voir aussi

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject