Partager via


Fonction FsRtlCancellableWaitForSingleObject (ntifs.h)

La routine FsRtlCancellableWaitForSingleObject exécute une opération d’attente annulable (une attente qui peut être terminée) sur un objet de 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 unités de 100 nanosecondes, à laquelle l’attente doit être terminée.

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

Une valeur de délai d’expiration positive spécifie une heure absolue, par rapport au 1er janvier 1601. Une valeur de délai d’attente 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 heures d’expiration relatives ne sont pas affectées par les changements d’heure système.

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

Une valeur de délai d’attente égale à zéro (autrement dit, *Délai d’attente == 0) vous permet de tester un ensemble de conditions d’attente et d’effectuer de manière conditionnelle des 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 reste 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 conservé par l’appelant. Il ne peut pas être passé à un pilote de niveau inférieur.

Valeur retournée

FsRtlCancellableWaitForSingleObject peut retourner l’une des valeurs suivantes :

Code de retour Description
STATUS_SUCCESS L’objet dispatcher spécifié par le paramètre Object a satisfait à l’attente.
STATUS_TIMEOUT Un délai d’attente s’est produit avant que l’objet soit défini sur un état signalé. Cette valeur peut être retournée lorsque l’ensemble de conditions d’attente spécifié ne peut pas être immédiatement rempli et que le délai d’expiration est défini sur zéro.
STATUS_ABANDONED_WAIT_0 L’appelant a tenté d’attendre un mutex qui a été 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 passé à FsRtlCancellableWaitForSingleObject et si 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 le status de l’attente. Le cas échéant, la status réelle de la demande d’E/S doit être obtenue 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 STATUS_CANCELLED et STATUS_THREAD_IS_TERMINATING status et TRUE (« réussite ») pour toutes les autres valeurs status.

Remarques

La routine FsRtlCancellableWaitForSingleObject exécute une opération d’attente annulable sur un objet dispatcher. 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 la prise en charge des instructions d’achèvement/annulation d’E/S à partir de Windows Vista. L’objectif de ces recommandations est de permettre aux utilisateurs (ou aux applications) d’arrêter rapidement les applications. Cela, à son tour, nécessite que les applications aient la possibilité d’arrêter rapidement les threads qui exécutent des E/S, ainsi que 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 de manière à ce que l’attente soit facilement annulée. Cette routine permet également d’arrêter 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. L’une des façons de procéder consiste à configurer un événement qui sera signalé par la routine d’achèvement de l’IRP secondaire, puis d’attendre que l’événement soit signalé. Ensuite, pour effectuer une opération d’attente annulable, FsRtlCancellableWaitForSingleObject est appelé en passant dans 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ée 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 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 attendu est un mutex, la remise APC est la même que pour tous les autres objets de répartiteur pendant l’attente. Toutefois, une fois que FsRtlCancellableWaitForSingleObjects retourne avec STATUS_SUCCESS et que le thread contient réellement le mutex, seuls les API en mode noyau spéciales sont livrées. La remise de tous 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 ne peut être acquis de manière récursive que des fois 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 pour prendre en charge les 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é au PASSIVE_LEVEL IRQL si le paramètre Irp facultatif pointe vers un IRP 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 l’IRQL est supérieur ou égal à APC_LEVEL et que le paramètre Irp facultatif pointe vers un IRP valide.

Configuration requise

Condition requise Valeur
Client minimal pris en charge Windows Vista
Plateforme cible Universal
En-tête ntifs.h (inclure Ntifs.h)
Bibliothèque NtosKrnl.lib
DLL NtosKrnl.exe
IRQL Consultez la section Notes.
Règles de conformité DDI HwStorPortProhibitedDDIs(storport), SpNoWait(storport)

Voir aussi

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject