Программирование драйверов Windows


Исполняемый код драйвера - часть 16


Для этого используется практически не применяемый разработчиками вызов IoCreateSynchronizationEvent

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

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

Данный драйвер (и первый, и второй варианты) в том виде как они приведены, не позволяют одновременно получить доступ к нему из нескольких приложений, поскольку объект устройства создается для эксклюзивного доступа. По этой причине Win32 вызов CreateFile, который должен получить дескриптор доступа к драйверу, завершается с ошибкой 5 (отказано в доступе). Для того чтобы исправить ситуацию необходимо предпоследний параметр вызова IoCreateDevice в драйверной функции CreateDevice задать равным FALSE (вместо TRUE, как указано изначально).

Еще один вопрос-опасение, который может возникнуть у внимательного читателя: как обстоят дела с доступом ко входным буферам с данными и для данных в смысле корректности уровня IRQL, на которых к ним обращается драйвер? Например, копирование в пользовательский буфер полученных данных по IOCTL запросу IOCTL_SEND_TO_USER производится функцией TransferToUserSafely, защищенной KeSynchronizeExecution, то есть работающей на уровне IRQL, равном IRQL процедуры обслуживания прерывания Isr. Почему не происходит сбоя, поскольку достоверно известно, что пользовательские области находятся в странично организованной памяти?

Ответ состоит в том, что в обоих драйверах используется буферизованный метод передачи данных при обращениях клиента к драйверу:

  • в первом варианте драйвера было указано, что объект устройства имеет метод буферизации при запросах на запись/чтение pDevObj-&#62Flags |= DO_BUFFERED_IO;
  • во втором варианте аналогичное указание Диспетчер ввод/вывода получает в каждом IOCTL коде, когда при его определении явно указывается METHOD_BUFFERED.

В обоих случаях указание на буферизацию приводит к тому, что между передачами клиент/драйвер Диспетчер ввода/вывода вставляет копирование в/из буферных областей, которые специально выделяются в нестранично организованной памяти, допускающей обращение к ней из кода, работающего на повышенных уровнях IRQL.




Начало  Назад  Вперед