Функция FsRtlCancellableWaitForSingleObject (ntifs.h)

Подпрограмма FsRtlCancellableWaitForSingleObject выполняет отменяемую операцию ожидания (ожидание, которое может быть завершено) для объекта диспетчера.

Синтаксис

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

Параметры

[in] Object

Указатель на инициализированный объект диспетчера (событие, мьютекс, семафор, поток или таймер), для которого вызывающий объект предоставляет хранилище.

[in, optional] Timeout

Указатель на необязательное значение времени ожидания. Этот параметр задает абсолютное или относительное время (в 100 наносекундных единицах), в течение которого должно быть завершено ожидание.

Если timeout указывает на нулевое значение (то есть *Timeout == 0), подпрограмма возвращается без ожидания. Если вызывающий объект предоставляет указатель NULL (то есть Timeout == NULL), подпрограмма ожидает неограниченное время, пока объект не перейдет в состояние сигнала.

Положительное значение времени ожидания указывает абсолютное время относительно 1 января 1601 г. Отрицательное значение времени ожидания указывает интервал относительно текущего времени. Абсолютное время истечения срока действия отслеживает любые изменения системного времени. Изменения системного времени не влияют на относительный срок действия.

Если задано время ожидания , ожидание будет автоматически выполнено, если объект не установлен в состояние сигнала по истечении заданного интервала.

Значение времени ожидания, равное нулю (то есть *Timeout == 0) позволяет протестировать набор условий ожидания и условно выполнять любые дополнительные действия, если ожидание может быть немедленно выполнено, как при приобретении мьютекса.

[in, optional] Irp

Указатель на исходную операцию ввода-вывода, которая соответствует операции ввода-вывода, выданной пользователем и которая может быть отменена пользователем. Вызывающий объект должен убедиться, что IRP будет оставаться действительным в течение этой процедуры и что IRP не должен иметь набор подпрограмм отмены (например, IoSetCancelRoutine не должен вызываться для IRP). Обратите внимание, что IRP должен храниться вызывающим абонентом. Он не может быть передан драйверу более низкого уровня.

Возвращаемое значение

FsRtlCancellableWaitForSingleObject может возвращать одно из следующих значений:

Код возврата Описание
STATUS_SUCCESS Объект диспетчера, заданный параметром Object , выполнил ожидание.
STATUS_TIMEOUT Время ожидания истекло до того, как объект был установлен в состояние сигнала. Это значение может быть возвращено, если указанный набор условий ожидания не может быть немедленно выполнен, а время ожидания равно нулю.
STATUS_ABANDONED_WAIT_0 Вызывающий попытался дождаться мьютекса, который был оставлен.
STATUS_CANCELLED Ожидание было прервано запросом на отмену для указанного IRP. Обратите внимание, что это значение возвращается только в том случае, если допустимый IRP передается в FsRtlCancellableWaitForSingleObject и IRP был отменен CancelSynchronousIo.
STATUS_THREAD_IS_TERMINATING Ожидание было прервано, так как поток был прерван приложением или пользователем.

Возвращаемое значение указывает только состояние ожидания. Если применимо, фактическое состояние запроса ввода-вывода должно быть получено непосредственно из другого IRP, созданного в процессе обработки исходного IRP в пользовательском режиме.

Обратите внимание, что макрос NT_SUCCESS возвращает false ("сбой") для STATUS_CANCELLED и STATUS_THREAD_IS_TERMINATING значения состояния и TRUE ("успешно") для всех остальных значений состояния.

Комментарии

Подпрограмма FsRtlCancellableWaitForSingleObject выполняет отменяемую операцию ожидания для объекта диспетчера. Если поток завершается пользователем или приложением или если CancelSynchronousIo отправляет запрос на отмену в потоковый IRP (синхронный IRP), связанный с потоком, ожидание отменяется.

Подпрограмма FsRtlCancellableWaitForSingleObject была разработана для поддержки рекомендаций по завершению и отмене ввода-вывода , начиная с Windows Vista. Цель этих рекомендаций — разрешить пользователям (или приложениям) быстро завершать работу приложений. Это, в свою очередь, требует, чтобы приложения имели возможность быстро завершать потоки, выполняющие операции ввода-вывода, а также любые текущие операции ввода-вывода. Эта подпрограмма позволяет пользовательским потокам блокировать (т. е. ожидать) в ядре для завершения ввода-вывода, объекта диспетчера или переменной синхронизации таким образом, чтобы ожидание было легко отменено. Эта подпрограмма также позволяет завершить ожидание потока, если поток завершается пользователем или приложением.

Например, перенаправлению может потребоваться создать одну или несколько вторичных irP, чтобы обработать IRP в пользовательском режиме и синхронно дождаться завершения дополнительных IRP. Один из способов сделать это — настроить событие, которое будет сигнализироваться подпрограммой завершения вторичного IRP, а затем дождаться передачи сигнала о событии. Затем для выполнения операции ожидания с возможностью отмены вызывается FsRtlCancellableWaitForSingleObject , передавая событие, связанное со вторичным IRP, а также исходный IRP в пользовательском режиме. Ожидание события в потоке отменяется при возникновении ожидающего завершения или при отмене исходного IRP в пользовательском режиме.

Обратите внимание, что завершение ожидания не отменяет автоматически никаких операций ввода-вывода, выполняемых вызывающим абонентом, которые должны обрабатываться отдельно.

Особое внимание следует учитывать, если параметр Object , передаваемый в FsRtlCancellableWaitForSingleObject , является мьютексом. Если ожидающий объект диспетчера является мьютексом, доставка APC будет такой же, как и для всех остальных объектов диспетчера во время ожидания. Однако после того, как FsRtlCancellableWaitForSingleObjects возвращает с STATUS_SUCCESS и поток фактически содержит мьютекс, доставляются только специальные APC в режиме ядра. Доставка всех остальных APC, как в режиме ядра, так и в пользовательском режиме, отключена. Это ограничение на доставку APC сохраняется до тех пор, пока мьютекс не будет освобожден.

Мьютекс можно рекурсивно получить только раз MINLONG. Если это ограничение превышено, подпрограмма вызывает исключение STATUS_MUTANT_LIMIT_EXCEEDED.

Ниже приведен пример использования FsRtlCancellableWaitForSingleObject для поддержки рекомендаций по завершению и отмене ввода-вывода.

//
// 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 должен вызываться на PASSIVE_LEVEL IRQL, если необязательный параметр Irp указывает на допустимое значение IRP. Если параметр Irp не используется, подпрограмму можно вызвать в irQL меньше или равно APC_LEVEL. При необходимости вызывающий объект может отключить обычные APC ядра, вызвав подпрограммы KeEnterCriticalRegion или FsRtlEnterFileSystem . Однако специальные APC ядра не должны быть отключены.

FsRtlCancellableWaitForSingleObject будет утверждать в отладочных сборках, если IRQL больше или равен APC_LEVEL а необязательный параметр Irp указывает на допустимый IRP.

Требования

Требование Значение
Минимальная версия клиента Windows Vista
Целевая платформа Универсальное
Верхняя часть ntifs.h (включая Ntifs.h)
Библиотека NtosKrnl.lib
DLL NtosKrnl.exe
IRQL См. раздел "Примечания".
Правила соответствия DDI HwStorPortProhibitedDIs(storport), SpNoWait(storport)

См. также раздел

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject