Função FsRtlCancellableWaitForSingleObject (ntifs.h)
A rotina
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, nas quais a espera deve ser concluída.
Se Tempo Limite apontar para um valor zero (ou seja, *Tempo limite == 0), a rotina retornará sem esperar. Se o chamador fornecer um ponteiro NULL (ou seja, Tempo limite == NULL), a rotina aguardará indefinidamente até que o objeto seja definido como o estado sinalizado.
Um valor Timeout positivo especifica um tempo absoluto, em relação a 1º de janeiro de 1601. Um valor de de tempo limite de
Se tempo limite for especificado, a espera será atendida automaticamente se o objeto não estiver definido como o estado sinalizado quando o intervalo determinado expirar.
Um valor de tempo limite zero (ou seja, *Tempo limite == 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.
Valor de retorno
FsRtlCancellableWaitForSingleObject pode retornar um dos seguintes valores:
Código de retorno | Descrição |
---|---|
STATUS_SUCCESS | O objeto dispatcher especificado pelo parâmetro Object satisfize a 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 puder ser atendido imediatamente e Tempo Limite estiver 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 tiver sido 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 de status STATUS_CANCELLED e STATUS_THREAD_IS_TERMINATING e TRUE ("success") para todos os outros valores de status.
Observações
A rotina
A rotina de
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 até que os IRPs secundários sejam concluídos. Uma maneira de fazer isso é configurar um evento que será sinalizado pela rotina de conclusão do IRP secundário e aguardar que o evento seja 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 objeto
Um mutex pode ser adquirido recursivamente apenas por tempo MINLONG. Se esse limite for excedido, a rotina gerará uma exceção STATUS_MUTANT_LIMIT_EXCEEDED.
Veja a seguir um exemplo de como usar
//
// 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 no IRQL PASSIVE_LEVEL se o parâmetro irp opcional aponta 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. As APCs de kernel normais podem ser desabilitadas pelo chamador, se necessário, chamando a KeEnterCriticalRegion
Requisitos
Requisito | Valor |
---|---|
de cliente com suporte mínimo | Windows Vista |
da Plataforma de Destino |
Universal |
cabeçalho | ntifs.h (inclua Ntifs.h) |
biblioteca | NtosKrnl.lib |
de DLL |
NtosKrnl.exe |
IRQL | Consulte a seção Comentários. |
regras de conformidade de DDI | HwStorPortProhibitedDIs(storport), SpNoWait(storport) |