Функция 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) |