Поделиться через


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

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

Синтаксис

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

Параметры

[in] Object

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

[in, optional] Timeout

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

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

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

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

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

[in, optional] Irp

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

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

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

Возвращаемый код Описание
STATUS_SUCCESS Объект диспетчера, указанный параметром объекта , удовлетворил ожидание.
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, а поток фактически содержит мьютекс, доставляются только специальные API режима ядра. Доставка всех остальных API, как в режиме ядра, так и в пользовательском режиме, отключена. Это ограничение на доставку API сохраняется до тех пор, пока мьютекс не будет освобожден.

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

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

Требования

Требование Ценность
минимальные поддерживаемые клиентские Windows Vista
целевая платформа Всеобщий
заголовка ntifs.h (include Ntifs.h)
библиотеки NtosKrnl.lib
DLL NtosKrnl.exe
IRQL См. раздел "Примечания".
правил соответствия DDI HwStorPortProhibitedDIs(storport), SpNoWait(storport)

См. также

ExInitializeFastMutex

FsRtlCancellableWaitForMultipleObjects

KeInitializeEvent

KeInitializeMutex

KeInitializeSemaphore

KeInitializeTimer

KeWaitForMultipleObjects

KeWaitForSingleObject