Função FsRtlCancellableWaitForSingleObject (ntifs.h)

A rotina FsRtlCancellableWaitForSingleObject executa uma operação de espera cancelável (uma espera que pode ser encerrada) em um objeto dispatcher.

Sintaxe

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

Parâmetros

[in] Object

Um ponteiro para um objeto dispatcher inicializado (evento, mutex, semáforo, thread ou temporizador) para o qual o chamador fornece o armazenamento.

[in, optional] Timeout

Um ponteiro para um valor de tempo limite opcional. Esse parâmetro especifica o tempo absoluto ou relativo, em 100 unidades nanossegundos, em que a espera deve ser concluída.

Se Timeout apontar para um valor zero (ou seja, *Timeout == 0), a rotina retornará sem esperar. Se o chamador fornecer um ponteiro NULL (ou seja, Timeout == NULL), a rotina aguardará indefinidamente até que o objeto seja definido como o estado sinalizado.

Um valor de Tempo limite positivo especifica um tempo absoluto, em relação a 1º de janeiro de 1601. Um valor de Tempo limite negativo especifica um intervalo relativo à hora atual. Os tempos de expiração absolutos acompanham as alterações na hora do sistema. Os tempos relativos de expiração não são afetados pelas alterações de tempo do sistema.

Se Timeout for especificado, a espera será atendida automaticamente se o objeto não estiver definido como o estado sinalizado quando o intervalo especificado expirar.

Um valor de tempo limite zero (ou seja, *Timeout == 0) permite testar um conjunto de condições de espera e executar condicionalmente quaisquer ações adicionais se a espera puder ser atendida imediatamente, como na aquisição de um mutex.

[in, optional] Irp

Um ponteiro para o IRP original que corresponde à operação de E/S emitida pelo usuário e que pode ser cancelada pelo usuário. O chamador deve garantir que o IRP permanecerá válido durante essa rotina e que o IRP não deve ter um conjunto de rotina de cancelamento (por exemplo, IoSetCancelRoutine não deve ter sido chamado no IRP). Observe que o IRP deve ser mantido pelo chamador, ele não pode ser passado para um driver de nível inferior.

Retornar valor

FsRtlCancellableWaitForSingleObject pode retornar um dos seguintes valores:

Código de retorno Descrição
STATUS_SUCCESS O objeto dispatcher especificado pelo parâmetro Object atendeu à espera.
STATUS_TIMEOUT Ocorreu um tempo limite antes de o objeto ser definido como um estado sinalizado. Esse valor pode ser retornado quando o conjunto especificado de condições de espera não pode ser atendido imediatamente e Timeout é definido como zero.
STATUS_ABANDONED_WAIT_0 O chamador tentou esperar por um mutex que foi abandonado.
STATUS_CANCELLED A espera foi interrompida por uma solicitação de cancelamento pendente no IRP especificado. Observe que esse valor será retornado somente se um IRP válido for passado para FsRtlCancellableWaitForSingleObject e o IRP for cancelado por CancelSynchronousIo.
STATUS_THREAD_IS_TERMINATING A espera foi interrompida quando o thread foi encerrado por um aplicativo ou pelo usuário.

O valor retornado indica apenas o status da espera. Se aplicável, o status real da solicitação de E/S deve ser obtido diretamente de outro IRP gerado no processo de manipulação do IRP do modo de usuário original.

Observe que a macro NT_SUCCESS retorna FALSE ("failure") para os valores STATUS_CANCELLED e STATUS_THREAD_IS_TERMINATING status e TRUE ("success") para todos os outros valores de status.

Comentários

A rotina FsRtlCancellableWaitForSingleObject executa uma operação de espera cancelável em um objeto dispatcher. Se o thread for encerrado pelo usuário ou pelo aplicativo ou se CancelSynchronousIo postar uma solicitação de cancelamento em um IRP threaded (IRP síncrono) associado ao thread, a espera será cancelada.

A rotina FsRtlCancellableWaitForSingleObject foi projetada para dar suporte às Diretrizes de Conclusão/Cancelamento de E/S começando com o Windows Vista. O objetivo dessas diretrizes é permitir que os usuários (ou aplicativos) encerrem rapidamente os aplicativos. Isso, por sua vez, requer que os aplicativos tenham a capacidade de encerrar rapidamente threads que estão executando E/S, bem como quaisquer operações de E/S atuais. Essa rotina fornece uma maneira de os threads de usuário bloquearem (ou seja, aguardar) no kernel para conclusão de E/S, um objeto dispatcher ou uma variável de sincronização de uma maneira que permita que a espera seja prontamente cancelada. Essa rotina também permite que a espera do thread seja encerrada se o thread for encerrado por um usuário ou um aplicativo.

Por exemplo, um redirecionador pode precisar criar um ou mais IRPs secundários para processar um IRP no modo de usuário e aguardar síncronamente a conclusão dos IRPs secundários. Uma maneira de fazer isso é configurar um evento que será sinalizado pela rotina de conclusão do IRP secundário e aguardar o evento ser sinalizado. Em seguida, para executar uma operação de espera cancelável, FsRtlCancellableWaitForSingleObject é chamado passando o evento associado ao IRP secundário, bem como o IRP do modo de usuário original. A espera do thread para que o evento seja sinalizado será cancelada se ocorrer um evento de encerramento pendente ou se o IRP do modo de usuário original for cancelado.

Observe que encerrar a espera não cancela automaticamente nenhuma operação de E/S emitida pelo chamador , que deve ser tratada separadamente pelo chamador.

Uma consideração especial se aplica quando o parâmetro Object passado para FsRtlCancellableWaitForSingleObject é um mutex. Se o objeto dispatcher que é aguardado for um mutex, a entrega do APC será a mesma que para todos os outros objetos dispatcher durante a espera. No entanto, uma vez que FsRtlCancellableWaitForSingleObjects retorna com STATUS_SUCCESS e o thread realmente contém o mutex, apenas APCs especiais no modo kernel são entregues. A entrega de todas as outras APCs, no modo kernel e no modo de usuário, está desabilitada. Essa restrição na entrega de APCs persiste até que o mutex seja liberado.

Um mutex pode ser adquirido recursivamente apenas em tempos MINLONG. Se esse limite for excedido, a rotina gerará uma exceção STATUS_MUTANT_LIMIT_EXCEEDED.

Veja a seguir um exemplo de como usar FsRtlCancellableWaitForSingleObject para dar suporte às Diretrizes de Conclusão/Cancelamento de 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 deve ser chamado em IRQL PASSIVE_LEVEL se o parâmetro Irp opcional apontar para um IRP válido. Se o parâmetro Irp não for usado, a rotina poderá ser chamada em IRQL menor ou igual a APC_LEVEL. ApCs de kernel normais podem ser desabilitadas pelo chamador, se necessário, chamando as rotinas KeEnterCriticalRegion ou FsRtlEnterFileSystem . No entanto, APCs de kernel especiais não devem ser desabilitadas.

FsRtlCancellableWaitForSingleObject será declarado em builds de depuração se o IRQL for maior ou igual a APC_LEVEL e o parâmetro irp opcional apontar para um IRP válido.

Requisitos

Requisito Valor
Cliente mínimo com suporte Windows Vista
Plataforma de Destino Universal
Cabeçalho ntifs.h (inclua Ntifs.h)
Biblioteca NtosKrnl.lib
DLL NtosKrnl.exe
IRQL Consulte a seção Observações.
Regras de conformidade de DDI HwStorPortProhibitedDIs(storport), SpNoWait(storport)

Confira também

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject