Función FsRtlCancellableWaitForSingleObject (ntifs.h)
La rutina FsRtlCancellableWaitForSingleObject ejecuta una operación de espera cancelable (una espera que se puede finalizar) en un objeto distribuidor.
Sintaxis
NTSTATUS FsRtlCancellableWaitForSingleObject(
[in] PVOID Object,
[in, optional] PLARGE_INTEGER Timeout,
[in, optional] PIRP Irp
);
Parámetros
[in] Object
Puntero a un objeto de distribuidor inicializado (evento, exclusión mutua, semáforo, subproceso o temporizador) para el que el autor de la llamada proporciona el almacenamiento.
[in, optional] Timeout
Puntero a un valor de tiempo de espera opcional. Este parámetro especifica el tiempo absoluto o relativo, en 100 unidades nanosegundas, en las que se va a completar la espera.
Si Timeout apunta a un valor cero (es decir, *Timeout == 0), la rutina devuelve sin esperar. Si el autor de la llamada proporciona un puntero NULL (es decir, Timeout == NULL), la rutina espera indefinidamente hasta que el objeto se establece en el estado señalado.
Un valor de tiempo de espera positivo especifica una hora absoluta, con respecto al 1 de enero de 1601. Un valor de tiempo de espera negativo especifica un intervalo relativo a la hora actual. Los tiempos de expiración absolutos realizan un seguimiento de los cambios en la hora del sistema. Los tiempos de expiración relativos no se ven afectados por los cambios de hora del sistema.
Si se especifica Timeout , la espera se cumplirá automáticamente si el objeto no está establecido en el estado señalado cuando expire el intervalo especificado.
Un valor de tiempo de espera de cero (es decir, *Timeout == 0) permite probar un conjunto de condiciones de espera y realizar condicionalmente cualquier acción adicional si la espera se puede satisfacer inmediatamente, como en la adquisición de una exclusión mutua.
[in, optional] Irp
Puntero al IRP original que corresponde a la operación de E/S emitida por el usuario y que el usuario puede cancelar. El autor de la llamada debe asegurarse de que el IRP permanecerá válido durante la duración de esta rutina y que el IRP no debe tener un conjunto de rutinas de cancelación (por ejemplo, No se debe haber llamado a IoSetCancelRoutine en el IRP). Tenga en cuenta que el IRP debe ser mantenido por el autor de la llamada, no se puede pasar a un controlador de nivel inferior.
Valor devuelto
FsRtlCancellableWaitForSingleObject puede devolver uno de los siguientes valores:
Código devuelto | Descripción |
---|---|
STATUS_SUCCESS | El objeto distribuidor especificado por el parámetro Object cumplió la espera. |
STATUS_TIMEOUT | Se ha agotado el tiempo de espera antes de establecer el objeto en un estado señalado. Este valor se puede devolver cuando no se puede cumplir inmediatamente el conjunto especificado de condiciones de espera y Timeout se establece en cero. |
STATUS_ABANDONED_WAIT_0 | El autor de la llamada intentó esperar a una exclusión mutua que se ha abandonado. |
STATUS_CANCELLED | La espera se interrumpió mediante una solicitud de cancelación pendiente en el IRP especificado. Tenga en cuenta que este valor solo se devuelve si se pasa un IRP válido a FsRtlCancellableWaitForSingleObject y CancelSynchronousIo canceló el IRP. |
STATUS_THREAD_IS_TERMINATING | La espera se interrumpió cuando una aplicación o el usuario han terminado el subproceso. |
El valor devuelto solo indica el estado de la espera. Si procede, el estado real de la solicitud de E/S debe obtenerse directamente de otro IRP generado en el proceso de control del IRP en modo usuario original.
Tenga en cuenta que la macro de NT_SUCCESS devuelve FALSE ("error") para el STATUS_CANCELLED y STATUS_THREAD_IS_TERMINATING valores de estado y TRUE ("correcto") para todos los demás valores de estado.
Comentarios
La rutina FsRtlCancellableWaitForSingleObject ejecuta una operación de espera cancelable en un objeto distribuidor. Si el usuario o la aplicación finalizan el subproceso, o si CancelSynchronousIo publica una solicitud de cancelación en un IRP (IRP sincrónico) asociado al subproceso, se cancela la espera.
La rutina FsRtlCancellableWaitForSingleObject se diseñó para admitir las directrices de finalización o cancelación de E/S a partir de Windows Vista. El objetivo de estas directrices es permitir que los usuarios (o aplicaciones) finalicen rápidamente las aplicaciones. Esto, a su vez, requiere que las aplicaciones tengan la capacidad de finalizar rápidamente los subprocesos que ejecutan E/S, así como las operaciones de E/S actuales. Esta rutina proporciona una manera de que los subprocesos de usuario bloqueen (es decir, espere) en el kernel para la finalización de E/S, un objeto de distribuidor o una variable de sincronización de forma que permita que la espera se cancele fácilmente. Esta rutina también permite finalizar la espera del subproceso si un usuario o una aplicación finalizan el subproceso.
Por ejemplo, un redirector puede necesitar crear uno o varios IRP secundarios para procesar un IRP en modo de usuario y esperar sincrónicamente a que se completen los IRP secundarios. Una manera de hacerlo es configurar un evento que se indicará mediante la rutina de finalización del IRP secundario y, a continuación, esperar a que se señale el evento. A continuación, para realizar una operación de espera cancelable, se llama A FsRtlCancellableWaitForSingleObject pasando el evento asociado al IRP secundario, así como al IRP en modo usuario original. La espera del subproceso para que se indique el evento se cancela si se produce un evento de terminación pendiente o si se cancela el IRP en modo de usuario original.
Tenga en cuenta que la terminación de la espera no cancela automáticamente ninguna operación de E/S emitida por el autor de la llamada, que debe controlarse por separado por el autor de la llamada.
Se aplica una consideración especial cuando el parámetro Object pasado a FsRtlCancellableWaitForSingleObject es una exclusión mutua. Si el objeto dispatcher que se espera es una exclusión mutua, la entrega de APC es la misma que para todos los demás objetos de distribuidor durante la espera. Sin embargo, una vez que FsRtlCancellableWaitForSingleObjects devuelve con STATUS_SUCCESS y el subproceso contiene realmente la exclusión mutua, solo se entregan las API de modo kernel especiales. La entrega de todas las demás API, tanto en modo kernel como en modo usuario, está deshabilitada. Esta restricción en la entrega de APCs persiste hasta que se libera la exclusión mutua.
Una exclusión mutua solo se puede adquirir de forma recursiva solo las veces de MINLONG. Si se supera este límite, la rutina genera una excepción de STATUS_MUTANT_LIMIT_EXCEEDED.
A continuación se muestra un ejemplo de cómo usar FsRtlCancellableWaitForSingleObject en compatibilidad con las directrices de finalización/cancelación 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;
}
Se debe llamar a FsRtlCancellableWaitForSingleObject en IRQL PASSIVE_LEVEL si el parámetro Irp opcional apunta a un IRP válido. Si no se usa el parámetro Irp , se puede llamar a la rutina en IRQL menor o igual que APC_LEVEL. Las API normales del kernel se pueden deshabilitar mediante el autor de la llamada, si es necesario, llamando a las rutinas KeEnterCriticalRegion o FsRtlEnterFileSystem . Sin embargo, las API especiales del kernel no deben estar deshabilitadas.
FsRtlCancellableWaitForSingleObject se afirmará en las compilaciones de depuración si IRQL es mayor o igual que APC_LEVEL y el parámetro Irp opcional apunta a un IRP válido.
Requisitos
Requisito | Value |
---|---|
Cliente mínimo compatible | Windows Vista |
Plataforma de destino | Universal |
Encabezado | ntifs.h (incluya Ntifs.h) |
Library | NtosKrnl.lib |
Archivo DLL | NtosKrnl.exe |
IRQL | vea la sección Comentarios. |
Reglas de cumplimiento de DDI | HwStorPortProhibitedDIs(storport), SpNoWait(storport) |