Процедура CancelRoutine
Драйвер должен учитывать возможность того, что какой-либо из IRP запросов (текущий или находящийся в состоянии ожидания обработки) может быть отменен. Простейшая ситуация, которая к этому ведет, возникает, когда пользовательское приложение, не дождавшись отклика от устройства и драйвера, попросту снимается при помощи диспетчера задач. Тем временем драйвер, будто ничего не случилось, пытается завершить порученные ему задачи. Диспетчер ввода/вывода выполняет удаление IRP запросов, находящихся в ожидании обработки, и мог бы сообщить об этом драйверу вызовом callback процедуры CancelRoutine (под таким именем она фигурирует в документации DDK), если бы тот зарегистрировал ее при помощи вызова IoSetCancelRoutine. Особенность применения этих процедур состоит в том, что при помощи вызова IoSetCancelRoutine
можно назначать разные CancelRoutine процедуры для отслеживания разных экземпляров IRP пакетов. Более того, даже на разных уровнях работы драйвера можно заново определять процедуру CancelRoutine (необходимо только хранить указатели на интересующие IRP пакеты), а то и вовсе отменить отслеживание уничтожения IRP пакетов — указав NULL вместо адреса CancelRoutine при вызове IoSetCancelRoutine.
Другая ситуация удаления пакетов IRP, ожидающих обработки, возникает в случае, если пользовательское приложение применило вызов API функции CancelIo
(см. заголовочный файл winbase.h или документацию MSDN). Правда, применение этого вызова требует, чтобы доступ к драйверу был получен с использованием флага FILE_FLAG_OVERLAPPED, а этот прием программисты применяют крайне редко. Подробнее о CancelRoutine см. в 9 главе.