Реферат: Протоколирование обмена информацией между компьютером и внешним запоминающим USB-устройством

Факультет«Информатика и системы управления»

Кафедра «Программноеобеспечение ЭВМ и информационные технологии»

Курсовой проект

по системномупрограммированию

Расчётно-пояснительнаязаписка

Тема:

«Протоколирование обменаинформациеймежду компьютером и внешним запоминающим USB‑устройством»



Оглавление

Введение. 3

1. Аналитический раздел. 4

1.1 Постановка задачи. 4

1.2 Архитектура Windows NT 5. 4

1.3 Шина USB… 7

1.3.1 Внутренняя организация шины USB… 8

1.4 Драйверная модель WDM… 16

1.4.1 Драйверные слои. 17

1.4.2 Точки входа WDM-драйвера. 19

1.5 Пакет запроса ввода / вывода (IRP) 20

1.6 Уровни запроса прерываний. 24

1.7 Уведомление о завершении запроса нижестоящимдрайвером. 25

1.8 Работа с файлами в режиме ядра. 26

1.9 Работа с реестром в режиме ядра. 29

1.10 MDL‑списки. 31

2. Конструкторский раздел. 32

2.1 Точки входа разрабатываемого драйвера. 32

2.1.1 Функция DriverEntry. 32

2.1.2 Функция AddDevice. 32

2.1.3 Функция DriverUnload. 33

2.1.4 Функция DispatchRoutine. 33

2.1.5 Функция DispatchInternalDeviceControl 33

2.2 Размещение кода драйвера в памяти. 35

2.3 Установка драйвера в системе. 35

3. Технологический раздел. 38

3.1 Выбор языка и средств программирования. 38

3.1.1 Драйвер-фильтр. 38

3.1.2 Управляющее приложение. 39

3.2 Структуры данных драйвера-фильтра. 39

3.2 Интерфейс управляющего приложения. 41

3.3 Тестирование драйвера-фильтра. 42

Заключение. 44

Список литературы и интернет-ресурсов. 45


Введение

При решении широкого круга задач возникает необходимость вполучении информации о функционировании какого-либо внешнего устройствакомпьютера. К категории этих задач можно отнести разработку системинформационной безопасности, что очень актуально в современном мире, гдеинформация является одним из важнейших ресурсов.

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


/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>/>1.Аналитический раздел

 

1.1 Постановка задачи

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

Перечислим требования, предъявляемые к программному комплексу:

·    Разрабатываемый комплекс должен отслеживать запросы на чтение и запись,приходящие к устройству;

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

·    Сохраняемая информация должна обладать структурированностью, такимобразом, что при анализе лог-файла можно было определить, передавалась илипринималась информация и в каком количестве;

·    Программный комплекс не должен приводить к сбоям в работе операционнойсистемы;

·    Программа установки должна корректно обрабатывать попыткуустановки на одно устройство в двух экземплярах.

 

1.2 Архитектура Windows NT 5

Архитектура Windows NT 5 соответствует классическим представлениям о проектированииоперационных систем. Наиболее распространены реализации данной ОС для платформыIntel x86 в одно- или многопроцессорных конфигурациях, однако существуюттакже версии для DEC Alpha и MIPS. Данная операционная система использует защищённый режимцентрального процессора, реализует механизмы виртуальной памяти и многозадачности.

Исполняемый код в Windows NT 5 имеет два уровня привилегий: код пользовательского режима и кодрежима ядра. Уровень привилегий накладывает определённые ограничения: впользовательском режиме не могут выполняться привилегированные инструкциипроцессора, не разрешено обращение к защищённым страницам памяти. Эти ограничениянакладываются для обеспечения безопасности работы системы. Пользовательскоеприложение не должно иметь возможность в результате ошибки или преднамеренновносить изменения в критические таблицы операционной системы или в памятьдругих приложений. В частности, такие ограничения запрещают пользовательскомуприложению напрямую управлять внешними устройствами, потому что каждое из нихявляется разделяемым ресурсом.

В Windows NT 5 обеспечение обмена данными и управление доступом к внешнемуустройству как к разделяемому ресурсу возлагается на его драйвер. Ввод и выводв драйверах осуществляется посредством IRP‑пакетов (Input/Output Request Packet). Запросы на ввод / вывод,посылаемые приложениями или другими драйверами, обрабатываются драйвером, послечего запрашивающей программе в том же пакете посылается статус завершенияоперации. Подробнее о пакетах ввода / вывода будет сказано далее, общий жепринцип взаимодействия проиллюстрирован на Рис. 1.2.1.


/>

Рис. 1.2.1 Архитектура ввода /вывода Windows NT 5

Применительно к поставленной задаче, из вышеизложенного следует,что полное протоколирования обмена данными с внешним устройством может бытьосуществлено только на уровне драйвера.

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

Обобщённая классификация драйверов Windows NT 5 может быть представленаследующим образом:

·    Драйверырежима ядра:

o Унаследованныедрайверы;

o Драйверыфайловой системы;

o Видеодрайверы;

o Драйверы PnP (Plug AndPlay):

§  Драйверы WDM.

·    Драйверыпользовательского режима.


1.3 Шина USB

Спецификация USB была разработана консорциумом компаний, включая Intel и Microsoft. Целью нового стандартабыло обеспечение организации недорогой среднескоростной шины в таких областяхприменения, как передача цифровых изображений, компьютерная телефония имультимедийные игры. Текущими версиями спецификации USB является версии 1.1 и 2.0(во вторую заложены более высокие скоростные характеристики).

Предельная скорость передачи данных по шине USB спецификации 1.1 составляет12 Мбит/с (Full Speed). Медленные устройства используют низкую скорость передачи – 1,5 Мбит/с(Low Speed). Стандарт USB версии 2.0 поддерживает физическую скорость передачи до 480Мбит/с (High Speed). Данные передаются последовательно по паре проводников. Питаниедля некоторых устройств доступно по отдельным проводникам питания и заземления(для устройств с небольшим энергопотреблением).

Устройства USB могут быть подключены 5-метровым кабелем (а практически – и более длинным). Использование USB‑хаба (hub – концентратор) позволяет увеличить дальность размещения устройствот хост-контроллера, а так же количество устройств, подключаемых к одной шине USB. Последовательно можно подключитьдо пяти хабов, обеспечив длину соединения 30 метров. К хост-контроллеру можно подключить до 127 устройств, шинный адрес которых устанавливаетсядинамически при подключении устройств.

На рисунке 1.3.1 приведен пример конфигурации сети USB‑устройств:


/>

Рис. 1.3.1 Сеть USB‑устройств

Работа программиста, создающего драйвер внешнего (не находящегосяна материнской плате) USB устройства сводится к тому, чтобы воспользоваться программныминтерфейсом системных драйверов шины USB, общение с которым происходит при помощи пакетов, называемых URB (USB Request Block) пакетами. Работа срегистрами USB контроллеров на материнской плате теперь стала уделом узкогокруга специалистов – разработчиков материнских плат и операционных систем. Всемостальным разработчикам USB‑устройств в операционной системе Windows предлагается достаточноразвитый программный интерфейс WDM‑драйверов, которые берут на себя всеаппаратно-ориентированные операции.

1.3.1 Внутренняя организация шины USB

Все операции по передаче данных по шине USB инициируются хостом. Периферийныеустройства не могут сами начать обмен данными, они могут только реагировать накоманды хоста. Рассмотрим общую схему обмена данными по шине USB.

Система USB разделяется на три логических уровня с определенными правиламивзаимодействия. Устройство USB содержит интерфейсную, логическую и функциональную части. Хосттоже делится на три части: интерфейсную, системную и программное обеспечение.Каждая часть отвечает только за определенный круг задач. Логическое и реальноевзаимодействие между ними показано на рисунке 1.3.1.1.

/>

Рис. 1.3.1.1 Взаимодействие компонентов USB

Таким образом, операция обмена данными между прикладной программойи шиной USB выполняется путем передачи буферов памяти через следующие уровни:

·    уровень клиентского программного обеспечения в хосте – обычно представляетсядрайвером устройства USB, обеспечивает взаимодействие пользователя с операционной системойс одной стороны и системным драйвером с другой;

·    уровень системного программного обеспечения USB в хосте (USBD, Universal Serial Bus Driver) – управляет нумерациейустройств на шине, управляет распределением пропускной способности шины имощности питания, обрабатывает запросы пользовательских драйверов;

·    хост-контроллер интерфейса шины USB (HCD, Host Controller Driver) – преобразует запросыввода / вывода в структуры данных, по которым хост-контроллер выполняетфизические транзакции, работает с регистрами хост-контроллера.

Уровень клиентского программного обеспечения определяет типпередачи данных, необходимый для выполнения затребованной прикладной программойоперации. После определения типа передачи данных этот уровень передает системномууровню следующее:

·    буфер памяти, называемый клиентским буфером;

·    пакет IRP, указывающий тип необходимой операции. Непосредственной обработкойзапроса занимается системный драйвер USB.

Уровень системного драйвера USB необходим для управленияресурсами USB. Он отвечает за выполнение следующих действий:

·    распределение полосы пропускания шины USB;

·    назначение логических адресов устройств каждому физическому USB‑устройству;

·    планирование транзакций.

Логическое устройство USB представляет собой набор независимых конечных точек, с которымиклиентское программное обеспечение обменивается информацией. Каждому логическомуустройству USB назначается свой адрес, уникальный на данной шине USB. Каждая конечная точкалогического устройства идентифицируется своим номером и направлением передачи (IN – передача к хосту, OUT – от хоста).

Транзакция на шине USB – это последовательность обмена пакетами между хостом ипериферийным устройством, в ходе которой может быть передан или принят одинпакет данных. Когда клиентское программное обеспечение передает IRP уровню системного драйвера,USB‑драйверпреобразует их в одну или несколько транзакций шины и затем передаетполучившийся перечень транзакций драйверу контроллера хоста.

Системный драйвер USB состоит из драйвера USB и драйвера хост-контроллера. Когда клиентский уровень передает IRP уровню системного обеспеченияUSB, USB‑драйвер преобразуетих в одну или несколько транзакций шины и затем передает получившийся переченьтранзакций драйверу контроллера хоста. Драйвер контроллера хоста принимает отсистемного драйвера шины перечень транзакций и выполняет следующие действия:

·    планирует исполнение полученных транзакций, добавляя их к спискутранзакций;

·    извлекает из списка очередную транзакцию и передает ее уровнюхост-контроллера интерфейса шины USB;

·    отслеживает состояние каждой транзакции вплоть до ее завершения.

При выполнении всех связанных с командным пакетом транзакцийсистемный уровень уведомляет об этом клиентский уровень.

Уровень хост-контроллера интерфейса шины USB получает отдельные транзакцииот драйвера контроллера хоста (в составе уровня системного обеспечения USB) и преобразует их всоответствующую последовательность операций шины. В результате этого USB‑пакеты передаютсявдоль всей физической иерархии хабов до периферийного USB‑устройства.

Нижний уровень периферийного USB‑устройства называетсяуровнем интерфейса шины USB. Он взаимодействует с интерфейсным уровнем шины USB на стороне хоста и передаетпакеты данных от хоста к периферийному устройству в формате, определяемомспецификацией USB. Затем он передает пакеты вверх – уровню логического USB‑устройства.

Средний уровень периферийного устройства USB‑устройства называетсяуровнем логического USB‑устройства. Каждое логическое USB‑устройство представляетсянабором своих конечных точек, с которыми может взаимодействовать системныйуровень USB‑хоста. Эти точки являются источниками и приемниками всехкоммуникационных потоков между хостом и периферийными USB‑устройствами.

Самый верхний уровень периферийного USB‑устройства называетсяфункциональным уровнем. Этот уровень соответствует уровню клиентскогообеспечения хоста. С точки зрения клиентского уровня, нижележащие уровни нужныдля организации между ним и конечными точками прямых «каналов данных», которыеидут вплоть до функционального уровня. А с точки зрения нашей схемыфункциональный уровень выполняет следующие действия:

·    получает данные, посылаемые клиентским уровнем хоста из конечных точекканалов данных нижележащего уровня логического USB‑устройства;

·    посылает данные клиентскому уровню хоста, направляя их в конечныеточки каналов данных нижележащего уровня логического USB‑устройства.

Логически передача данных между конечнойточкой и программным обеспечением производится с помощью выделения канала иобмена данными по этому каналу, а с точки зрения представленных уровней,передача данных выглядит следующим образом:

/>

Рис. 1.3.1.2 Уровни передачи данных

Конечная точка (Endpoint) – это часть USB‑устройства, котораяимеет уникальный идентификатор и является получателем или отправителеминформации, передаваемой по шине USB. Проще говоря, это буфер, сохраняющий несколько байт. Обычно этоблок данных в памяти или регистр микроконтроллера. Данные, хранящиеся в конечнойточке, могут быть либо принятыми данными, либо данными, ожидающими передачу.Хост также имеет буфер для приема и передачи данных, но хост не имеет конечныхточек.

Конечная точка имеет следующие основные параметры:

·    частота доступа к шине;

·    допустимая величина задержки обслуживания;

·    требуемая ширина полосы пропускания канала;

·    номер конечной точки;

·    способ обработки ошибок;

·    максимальный размер пакета, который конечная точка может приниматьили отправлять;

·    используемый конечной точкой тип посылок;

·    направление передачи данных.

Любое USB‑устройство имеет конечную точку с нулевым номером (Endpoint Zero). Эта точка позволяет хостуопрашивать устройство с целью определения его типа и параметров, выполнятьинициализацию и конфигурирование устройства.

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

Нулевая точка устройства доступна после того, как устройствоподключено к шине, включено и получило сигнал сброса по шине (bus reset). Все остальные конечныеточки после включения питания или сброса находятся в неопределенном состоянии инедоступны для работы до тех пор, пока хост не выполнит процедуру конфигурированияустройства.

Спецификация шины определяет четыре различных типа передачи данныхдля конечных точек:

·    управляющие передачи (Control Transfers) – используются хостом для конфигурированияустройства во время подключения, для управления устройством и получениястатусной информации в процессе работы. Протокол обеспечивает гарантированнуюдоставку таких посылок;

·    передачи массивов данных (Bulk Data Transfers) – применяются при необходимостиобеспечения гарантированной доставки данных от хоста к функции или от функции кхосту, но время доставки не ограничено;

·    передачи по прерываниям (Interrupt Transfers) – используются в том случае,когда требуется передавать одиночные пакеты данных небольшого размера. Каждыйпакет требуется передать за ограниченное время. Операции передачи носятспонтанный характер и должны обслуживаться не медленнее, чем того требуетустройство;

·    изохронные передачи (Isochronous Transfers) – применяются для обменаданными в «реальном времени», когда на каждом временном интервале требуетсяпередавать строго определенное количество данных, но доставка информации негарантирована (передача данных ведется без повторения при сбоях, допускается потеряпакетов).

Канал(pipe) – это логическоесоединение между конечной точкой устройства и ПО хоста. Существует две моделиканалов:

·    потоковый канал (или просто поток, streaming pipe) – это канал для передачиданных, структура которых определяется клиентским ПО. Потоки используются дляпередачи массивов данных, передачи данных по прерываниям и изохронной передачиданных. Поток всегда однонаправленный. Один и тот же номер конечной точки можетиспользоваться для двух разных потоковых каналов – ввода и вывода. Передачиданных в потоковых каналах подчиняются следующим правилам:

·    запросы клиентских драйверов для разных каналов, поставленные вопределенном порядке друг относительно друга, могут выполняться в другом порядке;

·    запросы для одного канала будут исполняться строго в порядке ихпоступления;

·    если во время выполнения какого-либо запроса происходит серьезнаяошибка (STALL), поток останавливается;

·    канал сообщений (message pipe или control pipe) – это канал для передачи данных, структура которых определяетсяспецификацией USB. Каналы этого типа двунаправленные и применяются для передачиуправляющих посылок. Каналы сообщений строго синхронизированы – спецификация USB запрещает одновременнуюобработку нескольких запросов: нельзя начинать передачу нового сообщения, покане завершена обработка предыдущего. В случае возникновения ошибки передачасообщения может быть прервана хостом, после чего хост может начать передачунового сообщения.

Основными характеристиками каналов являются:

·    полоса пропускания канала;

·    используемый каналом тип передачи данных;

·    характеристики, соответствующие конечной точке: направлениепередачи данных и максимальный размер пакета.

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

Канал сообщений, связанный с нулевой конечной точкой, называется Основнымканалом сообщений (Default Control Pipe или Control Pipe 0). Владельцем этого канала является USBD, и он используется дляконфигурирования устройства. Основной канал сообщений поддерживает толькоуправляющие передачи. Остальные каналы (они называются клиентскими каналами, Client Pipe) создаются в процессеконфигурирования устройства. Их владельцами являются драйверы устройств. Поклиентским каналам могут передаваться как потоки, так и сообщения с помощьюлюбых типов передач.

Набор клиентских каналов, с которыми работает драйвер устройства,называется интерфейсом устройства или связкой клиентских каналов.

1.4 Драйверная модель WDM

WDM (Windows Driver Model) – новая модель архитектурыдрайверов, предложенная Microsoft для Windows 2000, хотя эта архитектура развивалась, начиная с Windows 3.11, продолжая развиватьсяи в Windows 98 и Windows NT, но по-настоящему полной она стала только в Windows 2000.

С точки зрения WDM, существует три типа драйверов:

·    Драйвершины – драйвер, обслуживающий контроллер шины, адаптер, мост или любые другиеустройства, имеющие дочерние устройства. Для каждого типа шины в операционнойсистеме имеется свой драйвер;

·    Функциональныйдрайвер – основной драйвер устройства, предоставляющий его функциональныйинтерфейс. Этот драйвер обязателен кроме тех случаев, когда ввод-выводосуществляется драйвером шины или драйвером фильтров шины. Функциональныйдрайвер по определению обладает наиболее полной информацией о своем устройстве.Обычно только этот драйвер имеет доступ к специфическим регистрам устройства;

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

В среде WDM один драйвер не может контролировать все аспекты устройства: драйвершины информирует диспетчера PnP об устройствах, подключенных к шине, в то время какфункциональный драйвер управляет устройством.

/>1.4.1 Драйверные слои

Согласно перечисленным выше типам драйверов, существует три типа
объектов:

·    Объектыфизических устройств (PDO, Physical Device Object) – эти объекты создаютсядля каждого физически идентифицируемого элемента аппаратуры, подключенного кшине данных;

·    Объектыфункциональных устройств (FDO, Functional Device Object) – подразумевает единицулогической функциональности устройства;

·    Объектыфильтров устройств (FiDO, Filter Device Object) – предоставляют дополнительнуюфункциональность.

В Windows NT 5 последовательность загрузки драйверов устройств такая:

1.   Во время загрузкиоперационной системы производится загрузка шинных драйверов для каждойизвестной системе шины (список шин создается при установке операционной системыи сохраняется в реестре);

2.   Вызывается DriverEntry, а затем AddDevice для каждого шинногодрайвера. В AddDevice создается FDO для драйвера системной шины. Затем на созданный FDO отправляется запрос IRP_MN_START_DEVICE;

3.   Шинный драйвер составляетсписок всех устройств, подключенных к шине. Для каждого найденного устройствасоздается объект PDO;

4.   На каждый PDO посылается запрос IRP_MN_QUERY_DEVICE_RELATION, в ответ на которыйшинный драйвер возвращает идентификаторы всех найденных устройств;

5.   На эти PDO посылают запрос IRP_MN_QUERY_ID, в ответ на которыйдрайвер системной шины сообщает идентификаторы этих устройств;

6.   Получив идентификаторы,система пытается найти и загрузить драйверы устройств;

7.   Найдя драйвер дляустройств, система загружает его в память, вызывая его DriverEntry. Потом вызывается AddDevice, где создается FDO для устройства. Еслиустройств, управляемых этим драйвером, несколько, то AddDevice будет вызвана длякаждого устройства. Если в реестре зарегистрированы дополнительные фильтры, тоони также загружаются в память. Затем система посылает на FDO запрос IRP_MN_START_DEVICE;

8.   Происходит посылка на FDO запроса IRP_MN_QUERY_DEVICE_RELATIONS. Если устройство самоявляется шиной или держит на себе другие устройства, которыми само неуправляет, то для устройства на нем повторяется вся последовательностьдействий, начиная с пункта 5.

Функция AddDevice, вызываемая для каждого FDO, вызывает IoCreateDevice и IoAttachDeviceToStack, обеспечивая построениестека устройств. Стек устройств обеспечивает прохождение запросов отпользовательских программ до аппаратного (нижнего) уровня драйверов (Рис. 1.4.1.1).

/>

Рис. 1.4.1.1 Стек устройств


Из вышесказанного становится понятным, что разрабатываемый драйвердолжен являться драйвером-фильтром нижнего уровня, связанным с клиентскимдрайвером USB‑накопителя. Необходимость работы с клиентским USB‑драйвером объясняетсятем, что именно на этом уровне перехватываемая информация обладает требуемойструктурированностью – передаются именно файлы, а не блоки информации (кадрыили составленные из них транзакции), определяемые протоколом обмена по USB.

 

1.4.2 Точки входа WDM-драйвера

WDM‑драйверы отличаютсяот унаследованных драйверов тем, что должны содержать дополнительные точкивхода для поддержки PnP, и, в целом, они более логичны по структуре. Приведем списокточек входа и кратко охарактеризуем их назначение:

NTSTATUS DriverEntry(

IN PDRIVER_OBJECT DriverObject, // указатель наобъект драйвера

IN PUNICODE_STRING RegistryPath) // путь кподразделу регистра,

 // относящегосяк драйверу

Эта функция выполняется при загрузке драйвера операционнойсистемой. В WDM‑драйверах на DriverEntry возложены обязанности по регистрации всех остальных точек входадрайвера.

NTSTATUSAddDevice (

INPDRIVER_OBJECT DriverObject, // указатель на объект драйвера

IN PDEVICE_OBJECT PhysicalDeviceObject) // указатель народительский PDO

В драйверах, поддерживающих PnP, через эту точку входаменеджер PnP посылает драйверу уведомление об обнаружении устройства, закоторое должен отвечать драйвер. ФункцияAddDevice должна создать объектустройства с помощью вызова IoCreateDeviceи при необходимостиприсоединить его к стеку устройств с помощью IoAttachDeviceToDeviceStack.

NTSTATUSDriverUnload (

INPDRIVER_OBJECT DriverObject) // указатель на объект драйвера

Вызывается при выгрузке драйвера. В этой функции должны осво
бождаться все затребованные драйвером ресурсы. Драйверы WDM‑модели
выполняют эти действия в обработчике запросов IRP_MJ_PNP с субкодом IRP_MN_REMOVE_DEVICE, то есть при удалении устройстваиз системы.

Следует выделить отдельный класс точек входа драйвера, которыепредназначены для обработки IRP‑пакетов с различными кодами операций. Эти точки входарегистрируются при загрузке драйвера в функции DriverEntry. Регистрация производитсяпутем заполнения элементов массива MajorFunction адресами диспетчеризуемых функций. Индексом в этом массивеявляются коды IRP_MJ_XXX, то есть описанные числами типы пакетов IRP. Диспетчер ввода / вывода,ориентируясь на заполнение этого массива, вызывает нужные функции драйвера.

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

/>1.5 Пакетзапроса ввода / вывода (IRP)

Пакеты ввода / вывода (IRP‑пакеты) используютсядля передачи запросов к драйверу от его клиентов. Они являются структурамиданных переменной длины, и состоят из стандартного заголовка, содержащего общуюучетную информацию, и одного или нескольких блоков параметров, называемыхячейками стека ввода / вывода (I/O Stack Location).

Приведем структуру заголовка IRP‑пакета:

Таблица 1.5.1.Структура заголовка IRP‑пакета.

Поля

Описание

IO_STATUS_BLOCK IoStatus Статус запроса PVOID AssociatedIrp. SystemBuffer Указатель на системный буфер для случая, если устройство поддерживает буферизованный ввод / вывод PMDL MdlAddress Указатель на MDL‑список в случае, если устройство поддерживает прямой ввод / вывод PVOID UserBuffer Адрес пользовательского буфера для ввода / вывода BOOLEAN Cancel Индикатор того, что IRP‑пакет должен быть аннулирован

Основное назначение ячеек стека ввода / вывода состоит в том,чтобы хранить функциональный код и параметры запроса на ввод / вывод.Ниже, в таблице 1.5.2 приводятся поля ячеек стека ввода / вывода, ккоторым драйвер может обращаться непосредственно по указателю (чего нерекомендуется делать для остальных полей):

Таблица 1.5.2.Структура ячейки стека ввода / вывода

Поля

Описание

UCHAR MajorFunction Код IRP_MJ_XXX, описывающий назначение операции UCHAR MinorFunction Субкод операции PDEVICE_OBJECT DeviceObject Указатель на объект устройства, которому был адресован данный объект IRP PFILE_OBJECT FileObject Файловый объект для данного запроса, если он задан union Parameters (трактовка определяется значением MajorFunction) struct Read

Параметры для IRP типа IRP_MJ_READ:

ULONG Length

ULONG Key

LARGE_INTEGER ByteOffset

struct Write

Параметры для IRP типа IRP_MJ_WRITE:

ULONG Length

ULONG Key

LARGE_INTEGER ByteOffset

struct DeviceControl

Параметры для IRP типа IRP_MJ_DEVICE_CONTROL:

ULONG OutputBufferLength

ULONG InputBufferLength

ULONG IoControlCode

PVOID Type3InputBuffer

Приведем графическое представление структуры IRP‑пакета:


/>

Рис. 1.5.1Структура IRP пакета

Общение с USB‑накопителями в ОС Windows NT 5 на уровне драйверов, как уже было сказано в разделе 1.3.1,происходит посредством передачи URB‑пакетов. Указатели на URB‑пакеты содержатячейки стека IRP‑пакета, доступ к этим указателям осуществляется следующимобразом:

PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);

PURB Urb = IrpSp->Parameters. Others. Argument1;

Приведем частичное объявление структуры из справочной документацииMicrosoft.Отметим только поля, использование которых необходимо в рамках данной курсовойработы:

typedef struct _URB {

union {

struct _URB_HEADER UrbHeader;

struct _URB_SELECT_INTERFACE UrbSelectInterface;

struct _URB_SELECT_CONFIGURATION UrbSelectConfiguration;

struct _URB_BULK_OR_INTERRUPT_TRANSFER UrbBulkOrInterruptTransfer;

}

} URB, *PURB;

Поле UrbHeader хранит информацию о коде URB‑пакета, по которомуможно определить, какая операция запрашивается.

Поля UrbSelectInterface и UrbSelectConfiguration служат для запроса по выбору интерфейса и конфигурацииустройства, которые будут использоваться при работе с устройством. Пакеты этойструктуры отправляются хостом к устройству в начале его работы, приконфигурировании.

Поле UrbBulkOrInterruptTransfer несет наиболее важную в рамках данной курсовой работы информацию– указатели на блоки ввода / вывода USB‑устройства. Приведем описание структуры _URB_BULK_OR_INTERRUPT_TRANSFER:

struct _URB_BULK_OR_INTERRUPT_TRANSFER {

struct _URB_HEADER Hdr;

USBD_PIPE_HANDLE PipeHandle;

ULONG TransferFlags;

ULONG TransferBufferLength;

PVOID TransferBuffer;

PMDL TransferBufferMDL;};

Поля этой структуры описаны в следующей таблице:

Таблица 1.5.3 Поля структурыURB_BULK_OR_INTERRUPT_TRANSFER

Поле

Описание

struct _URB_HEADER Hdr Стандартный заголовок URB‑пакета, содержащий код запроса USBD_PIPE_HANDLE PipeHandle Дескриптор канала, на который передаются данные ULONG TransferFlags Флаги, определяющие направление передачи данных и способ обработки ошибок ULONG TransferBufferLength Длина передаваемого блока данных в байтах PVOID TransferBuffer Указатель на передаваемый буфер. Буфер находится в нестраничной памяти PMDL TransferBufferMDL Указатель на MDL‑список, несущий передаваемую информацию. Буфер находится в страничной памяти

Следует отметить, что один из указателей TransferBuffer или TransferBufferMDL равен NULL, то есть в пределах одногопакета передается только одна порция данных.

Задача протоколирования обмена информацией сводится к перехвату исохранению буферов TransferBuffer и TransferBufferMDL.

1.6 Уровни запроса прерываний

В каждый момент времени центральный процессор находится на одномиз уровней IRQL (Interrupt Request Level – уровень запросов прерываний). Уровни IRQL располагаются в порядкеубывания от HIGHEST_LEVEL до PASSIVE_LEVEL. Каждому из прерываний (прерывания от внешних устройств,системные часы, и т.д.) соответствует свой уровень IRQL. Специальным действиямоперационной системы также назначены IRQL. Они отмечены в нижней части приведённой таблицы:

Таблица 1.6.1. Уровни запросов прерываний.

Уровень

Назначение

HIGHEST_LEVEL Наивысший уровень. Все прерывания заблокированы POWER_LEVEL Прерывания по отказу питания IPI_LEVEL Межпроцессорное взаимодействие CLOCK2_LEVEL Прерывание по системному таймеру 2 СLOCK1_LEVEL Прерывание по системному таймеру 1 PROFILE_LEVEL Прерывание по таймеру замера производительности уровни DRQL Обычные прерывания устройств DISPATCH_LEVEL Диспетчеризация потоков и выполнение отложенных процедур APC_LEVEL Выполнение асинхронного вызова процедуры PASSIVE_LEVEL Обычное исполнение кода потока

Общее правило обработки уровней запросов прерываний гласит, чтопрерывания с IRQL, меньшим, чем у выполняемого в данный момент кода, маскируются.Во время исполнения кода потока (пользовательского или системного) устанавливаетсянаименьший IRQL = 0 (PASSIVE_LEVEL). Работа драйвера чаще всего выполняется на уровне IRQL = 2 (DISPATCH_LEVEL). Уровни, лежащие над ним,называются DIRQL (Device IRQL) и выставляются для обработчиков прерываний от внешних устройств(ISR – interrupt service routine). Даже во время выполнения ISR драйвера может произойтипрерывание с большим IRQL, например, принадлежащее другому драйверу.

Чем выше текущий уровень IRQL исполняемого кода, тем меньше функций ему доступно. Так,например, диспетчер потоков работает на уровне
DISPATCH_LEVEL, и, следовательно, не будетвызываться, пока на процессоре с уровнем большим или равным DISPATCH_LEVEL исполняется другой код.Таким образом, на уровнях DISPATCH_LEVEL и выше отключается переключение потоков. Функции ожиданиядиспетчерских объектов (события, мьютексы, семафоры) с отличным от нуля временем,обращение к файлам, подкачка отсутствующих в физической памяти страниц – всёэто также становится недоступным. Для корректного сохранения запросов в файлефильтр в таких случаях должен применять специальную методику.

/>1.7Уведомление о завершении запроса нижестоящим драйвером

При отслеживании обмена данными драйвер-фильтр может получатьуведомления о том, что некоторый переданный запрос был завершён нижестоящим драйвером.Механизм уведомления заключается в том, что вызовом специальной функции IoSetCompletionRoutine фильтр обращается к стеку в пакете IRP. В позиции стека, следующейза текущей позицией, он устанавливает в специальном поле адрес функциизавершения (completion routine). Затем при передаче пакета по цепочке позиция стека увеличивается.

Когда нижестоящий драйвер отправляет пакет запроса на завершение(вызовом IoCompleteRequest), подсистема ввода / вывода начинает просматривать стеквнутри этого пакета от конца к началу. Если в какой-то позиции стека определенафункция завершения, управление передаётся ей. Отработав, функция возвращаетрезультат, сигнализирующий об успехе, ошибке или необходимости дальнейшей обработкизапроса.

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

При третьем же варианте просмотр стека немедленно прекращается изапрос не будет завершён. Эта возможность реализована для того, чтобыдрайвер-фильтр мог выполнить какие-либо действия над пакетом запроса послетого, как тот будет обработан в нижестоящем драйвере. После такой«дополнительной обработки» пакет снова должен быть отправлен на завершение.

1.8 Работа с файлами в режиме ядра

Поскольку протоколируемая информация должна сохраняться в файле надиске, следует рассмотреть основные функции уровня ядра, используемые при работес файлами.

Для открытия файла из драйвера режима ядра используется универсальнаяфункция ZwCreateFile. Универсальность этой функции состоит в том, что с ее помощьюпроизводится и открытие существующих файлов, и создание новых.

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

Представим основные параметры функции ZwCreateFile в следующей таблице:

 

Таблица 1.8.1. Параметры функции ZwCreateFile

Тип параметра

Описание параметра

OUT PHANDLE pHandle Указатель на переменную, куда следует поместить дескриптор открытого объекта IN ACCESS_MASK DesiredAccess

Характеристика доступа к объекту. Для фалов чаще всего используются значения

GENERIC_READ или GENERIC_WRITE

IN POBJECT_ATTRIBUTES

pObjAttributes

Указатель на заполненную вызывающим кодом структуру данных, которая описывает имя, местоположение и некоторые другие характеристики открываемого объекта OUT PIO_STATUS_BLOCK pIOStatus Указатель на буфер, в котором будет размещена информация об открытом объекте в формате структуры IO_STATUS_BLOCK IN PLARGE_INTEGER AllocationSize Начальный размер файла в байтах. Ненулевое значение принимается во внимание только при создании и перезаписи файла IN ULONG FileAttributes Атрибуты открываемого файла. Типовым является значение FILE_ATTRIBUTE_NORMAL IN ULONG SharedAccessFlags Описывает, разрешен ли совместный доступ, например, FILE_SHARE_READ – для чтения IN ULONG CreateDispositionFlags Способ открытия файла, например, FILE_OPEN_IF – если не существует, создать IN ULONG CreateOptions Комбинация флагов создания, например, FILE_SYNCHONOUS_IO_NONALERT – все операции над файлом выполняются как синхронные (DesiredAccess должен включать флаг SYNCHRONIZE) IN PVOID EaBuffer Для драйверов устройств следует указывать NULL IN ULONG EaLength Для драйверов устройств следует указывать 0

Для заполнения структуры атрибутов объекта используется функция
InitializeObjectAttributes. Опишем ее параметры в следующей таблице:

 

Таблица 1.8.2. Параметры функции InitializeObjectAttributes

Тип параметра

Описание параметра

OUT POBJECT_ATTRIBUTES pObjAttributes Указатель на переменную, куда следует поместить атрибуты объекта IN PUNICODE_STRING ObjectName Имя объекта, HANDLE которого создается IN ULONG Attributes Флаги атрибутов объекта, при открытии файла как правило используются флаги OBJ_CASE_INSENSITIVE и OBJ_KERNEL_HANDLE IN HANDLE RootDirectory Дескриптор корневой директории для объекта, описатель атрибутов которого создается. Если ObjectName полностью описывает путь к объекту, то значению RootDirectory присваивается NULL IN PSECURITY_DESCRIPTOR SecurityDescriptor Дескриптор безопасности. Если указано NULL, то применяется стандартный дескриптор

Запись в файл выполняется системной функцией ZwWriteFile:

 

Таблица 1.8.3. Параметры функции ZwWriteFile

Тип параметра

Описание параметра

IN HANDLE FileHandle Дескриптор открытого или модифицированного файлового объекта IN HANDLE Event Для драйверов устройств следует указывать NULL IN PIO_APC_ROUTINE Для драйверов устройств следует указывать NULL IN PVOID ApcContext Для драйверов устройств следует указывать NULL OUT PIO_STATUS_BLOCK pioStatusBlock В поле pIoStatusBlock->Information по завершении вызова находится число реально записанных байт IN PVOID Buffer Буфер с данными для записи IN ULONG Length Размер записываемой порции данных IN PLARGE_INTEGER pByteOffset Указатель на переменную где содержится смещение в файле от его начала, по которому следует производить запись IN PULONG Key Для драйверов устройств следует указывать NULL

Для закрытия дескриптора объекта следует применять функцию ZwCloseKey.

Следует отметить, что функции работы с файлами могут работатьтолько на уровне IRQL, равном PASSIVE_LEVEL. Это приводит к необходимости применения специальной методики припротоколировании обмена данными с USB‑накопителем.

1.9 Работа с реестром в режиме ядра

Работа с реестром из драйвера уровня ядра необходима, так какименно в системном реестре хранится информация о настройках протоколирования.Информация о настройках хранится в ключе реестра, связанном с устройством, ккоторому подключается драйвер-фильтр. Имя этого устройства соответствуетшаблону HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\XXX\XXX\DeviceParameters.

Доступ ключу устройства в реестре в драйвере предоставляетсяфункцией IoOpenDeviceRegistryKey. Перечислим ее параметры:

 

Таблица 1.9.1. Параметры функции IoOpenDeviceRegistry

Тип параметра

Описание параметра

IN PDEVICE_OBJECT DeviceObject Указатель на объект физического устройства, ключ которого должен быть открыт IN ULONG DevInstKeyType Параметр определяющий, связан ли открываемый ключ непосредственно с физ. устройством или его программным обеспечением IN ACCESS_MASK DesiredAccess Этот параметр определяет права доступа к ключу OUT PHANDLE DevInstRegKey Указатель на переменную, куда следует поместить дескриптор открытого ключа

Открыв основной ключ, следует получить доступ к вложенному в негоключу с параметрами протоколирования. Для этого используется функция ZwOpenKey. Перечислим еепараметры:


Таблица 1.9.2. Параметры функции ZwOpenKey

Тип параметра

Описание параметра

OUT PHANDLE KeyHandle Указатель на переменную, куда следует поместить дескриптор открытого ключа IN ACCESS_MASK DesiredAccess Этот параметр определяет права доступа к ключу IN POBJECT_ATTRIBUTES pObjectAttributes Указатель на заполненную вызывающим кодом структуру данных, которая при использовании в данной функции должна содержать имя открываемого ключа

Открыв ключ собственных параметров драйверу необходимо считатьнастройки протоколирования. Для чтения значения параметров ключа реестраиспользуется функция ZwQueryValueKey. Перечислим ее параметры:

Таблица 1.9.3. Параметры функции ZwQueryValueKey

Тип параметра

Описание параметра

IN HANDLE KeyHandle Дескриптор ключа, которому принадлежит считываемый параметр IN PUNICODE_STRING ValueName Строка юникод-символов, содержащая имя параметра ключа

IN KEY_VALUE_INFORMATION_CLASS

KeyValueInformationClass

Этот параметр принимает одно их трех значений в зависимости от полноты информации о параметре:

KeyValueBasicInformation

KeyValueFullInformation

KeyValuePartialInformation

OUT PVOID KeyInformation Указатель на буфер, выделенный вызывающим кодом, в который должна быть помещена запрашиваемая информация IN ULONG Length Длина предоставленного буфера OUT PULONG ResultLength Указатель на переменную, содержащую число реально записанных в KeyInformation байт

После того, как работа с ключом реестра закончена, его дескрипторследует освободить вызовом функции ZwClose.


1.10 MDL‑списки

MDL‑список – этоструктура, хранящая отображение блока виртуальной памяти на физическую память. MDL‑список используется вразрабатываемом драйвере для хранения информации из URB‑пакетов, связанных свводом / выводом USB‑устройства. Кроме того, обмен информацией с USB‑устройством в режимепрямого доступа к памяти ведется именно посредством MDL‑списков.

Перед использовании MDL‑списка в драйвере необходимо провести ряд подготовительныхдействий:

·    выделить область в страничной памяти с помощью вызова функции
ExAllocatePool;

·    вызвать функцию MmCreateMdl, создающую и инициализирующую MDL‑список;

·    выполнить фиксацию страниц, описанных в MDL‑списке, в физическойпамяти с помощью вызова функции MmProbeAndLockPages.

После завершения использования MDL‑списка его следуетосвободить:

·    отменить фиксацию страниц страничной памяти в оперативной памяти вызовомфункции MmUnlockPages;

·    очистить MDL‑список, вызвав функцию IoFreeMdl;

·    освободить выделенную под список страничную память вызовом
 ExFreePool.


2.Конструкторский раздел

2.1 Точки входа разрабатываемогодрайвера

Разрабатываемый драйвер является драйвером нижнего уровня. В стекедрайверов USB‑накопителя он находится непосредственно под драйверомустройства, если после его загрузки не произойдет установки какого-либо другогодрайвера-фильтра нижнего уровня.

Разрабатываемый драйвер включает в себя следующие точки входа:

·    DriverEntry;

·    AddDevice;

·    DriverUnload;

·    Функции обработки IRP‑пакетов:

·    обработка IRP‑пакетов с кодами IRP_MJ_INTERNAL_DEVICE_CONTROL – функция DispatchInternalDeviceControl;

·    обработка IRP пакетов с прочими кодами – функция DispatchRoutine.

Рассмотрим каждую из них более подробно.

2.1.1 Функция DriverEntry

В этой функции происходит регистрация всех стандартных точек входадрайвера и обработчиков IRP‑пакетов. В разрабатываемом драйвере пакеты IRP c кодами, не равными IRP_MJ_INTERNAL_DEVICE_CONTROL обрабатываются функцией DispatchRoutine.

2.1.2 Функция AddDevice

Управление этой функции передается диспетчером ввода / выводапосле того, как завершает свою работу DriverEntry. AddDevice создает функциональныйобъект устройства с помощью вызова IoCreateDevice и подключает его к стеку драйверов выбранного устройства (вызовомIoAttachDeviceToDeviceStack). Кроме того, в этой функции производятся действия по подготовкек протоколированию: считываются настройки из системного реестра, выделяетсябуфер для сбора протоколируемой информации, создается лог-файл.

2.1.3 Функция DriverUnload

Функция DriverUnload необходима для того, чтобы сделать драйвер выгружаемым. Вунаследованных драйверах на эту функцию возложен весь процесс выгрузки драйвера:удаление символьных ссылок, объектов устройств драйвера, отключение прерыванийот объектов, освобождение выделенной памяти. В WDM‑драйверах все этидействия возложены на функцию-обработчик пакетов с кодом IRP_MJ_PNP.

2.1.4 Функция DispatchRoutine

На эту функцию возложены обязанности по обработке IRP‑пакетов с различнымикодами, хотя в разрабатываемом драйвере существует необходимость в обработкетолько двух типов запросов. Все запросы с кодом, отличным от IRP_MJ_PNP передаются по стекудрайверов без изменений. Запросы же IRP_MJ_PNP диспетчеризуются по суб-кодам в функции PnP_Dispatch. Необходимостьдиспетчеризации по суб-кодам запросов IRP_MJ_PNP вызвана тем, что драйвер не должен нарушать порядка работыоперационной системы и обязан подчиняться PnP‑менеджеру, то есть вдрайвере должны корректно обрабатываться события старта и удаления устройства.

2.1.5 Функция DispatchInternalDeviceControl

Запросы ввода / вывода к USB‑накопителю передаются в составе IRP‑пакетов с кодом IRP_MN_INTERNAL_DEVICE_CONTROL. Этот пакет содержит полную информацию о направлении и характерепередаваемых данных. То есть для протоколирования обмена информацией с USB‑носителем следуетперехватывать пакеты именно этого типа.

Для того чтобы перехватывать информацию, передаваемую в обоихнаправлениях, следует установить функцию обратного вызова диспетчера ввода /вывода. Методика установки этой функции была описана в разделе 1.7. При наличииэтой функции разрабатываемый драйвер-фильтр получит возможность перехвата данных,передаваемых от устройства к хосту.

Для сохранения протоколируемой информации используется, как ужебыло сказано в разделе 1.10, MDL‑список. Этот MDL‑список создается в функции AddDevice. Объем памяти,выделяемой под список, совпадает с максимальным размером лог-файла, задаваемымв пользовательском приложении. После создания список фиксируется в страничнойпамяти, что предотвращает его выгрузку на жесткий диск во время работыдрайвера. После этих подготовительных действий список используется в функции DispatchInternalDeviceControl– он заполняется перехватываемойинформацией.

Запись накопленного буфера в лог-файл происходит при удаленииустройства.

Такая методика выбрана из-за того, что функция DispatchInternalDeviceControl работаетна уровне запроса прерываний, равном DISPATCH_LEVEL, что сильно затрудняет использование механизмов синхронизации,которые могли бы позволить перейти на уровень запроса прерываний, равный PASSIVE_LEVEL, где становятся доступнымифункции работы с файлами. Если бы это было достигнуто в разрабатываемомдрайвере, то отпала бы необходимость выделения больших объемов нестраничнойпамяти для хранения протокола.

Запись файла на диск в момент удаления устройства возможна, таккак это событие инициализируется PnP‑менеджером, запросы которого всегда происходят на уровне IRQL, равном PASSIVE_LEVEL.


2.2 Размещение кода драйвера в памяти

Некоторые функции драйвера, например те, которые выполняютинициализацию, выгодно выполнить и освободить память, занимаемую ими. В языке C есть специальная директива #pragma_alloc_text(<тип секции>, <имя размещаемой функции>), позволяющаяуправлять размещением кода. В качестве типа секции могут указываться значения «INIT» или «PAGE».

Функции с размещением в секции «INIT» выгружаются, и память,занимаемая ими, освобождается сразу по завершении их работы. В разрабатываемомдрайвере в секции «INIT» размещена точка входа DriverEntry, поскольку онавыполняется единожды при загрузке драйвера.

Точки входа AddDevice и DriverUnload располагаются в секции «PAGE», то есть в страничной памяти, поскольку они гарантированновызываются на уровне привилегий, равном PASSIVE_LEVEL и, даже оказавшисьвыгруженными на диск, будут немедленно загружены в физическую память менеджеромстраничной памяти (который способен работать только на уровне PASSIVE_LEVEL).

Остальные же точки входа (DispatchRoutineиDispatchInternalDeviceControl) располагаются по умолчанию, в нестраничной памяти, поскольку ихработа зависит от клиентского драйвера USB‑устройства, подкоторым в стеке драйверов располагается разрабатываемый драйвер-фильтр. Уровеньпривилегий его запросов слабо предсказуем и может быть равен DISPATCH_LEVEL. На этом уровне подкачкастраниц невозможна, что при обращении к выгруженной функции приведет к краху системы.

2.3 Установка драйвера в системе

Для установки драйвера следует создать его ключ в системномреестре.
 Имя ключа должно иметь следующий вид:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\driver_name.

Последняя часть имени специфична для устанавливаемого драйвера.Создаваемый ключ должен содержать следующие параметры:

·    DisplayName – значение этого параметра описывает текст, используемый в служебныхпрограммах;

·    ErrorControl – этот параметр предписывает операционной системе способ поведенияв той ситуации, когда при загрузке драйвера произошла ошибка;

·    ImagePath – описывает полный путь к файлу с исполняемым кодом драйвера;

·    Start – описывает стадию загрузки операционной системы, когда следуетзагружать драйвер;

·    Type – определяет тип драйвера.

Возможные значения указанных параметров можно узнать издокументации MSDN.

Таким образом, первая стадия установки драйвера в системузаключается
в том, что должен быть создан ключ драйвера в реестре, а сам драйвер
скопирован в каталог, описываемый строкой ImagePath (как правило -%SystemRoot%\System32\Drivers\driver_name.sys).

Далее должно быть выбрано устройство, на которое будет установленфильтр. Выбранному устройству в системном реестре соответствует ключ с именемвида HKLM\CurrentControlSet\Enum\USB\XXX\YYY.

Последняя часть ключа (XXX\YYY) определяется именем устройства. При установке драйвера фильтранижнего уровня в разделе YYY создается строковый параметр LowerFilters, которому присваиваетсязначение, совпадающее с именем драйвера, для которого был создан ключ в …\Services. Таким образом, при подключенииустройства к системе для него будет создан стек драйверов, в состав которого вкачестве фильтра нижнего уровня будет загружен устанавливаемый драйвер.

Кроме того, в ключе, связанном с устройством, при установкедрайвера создается дополнительный раздел MyFilterParams, который хранит двапараметра:

·    MaxLogSize – максимальный размер лог-файла;

·    LogFileName – имя лог-файла.


3.Технологический раздел

3.1 Выбор языка и средств программирования

Разрабатываемый программный комплекс состоит из двух частей:

·    Драйвера-фильтра;

·    Управляющего приложения для установки фильтра и ввода параметровпротоколирования.

Каждая из программ, осуществляет общение с операционной системойна разном уровне. Соответственно необходим разный подход к этим задачам и специальныйподбор средств разработки.

 

3.1.1 Драйвер-фильтр

От разрабатываемого драйвера-фильтра требуется высокая скоростьработы и надежность. При его работе осуществляется множество манипуляций спамятью, операций с указателями, преобразований типов. Важно представлятьструктуру скомпилированного продукта, чтобы правильно представить себе логикуего работы. Среди языков программирования, удовлетворяющих этим требованиям,известны языки С и ассемблер. Для написания драйвера предпочтение было отданоязыку C. Такой выбор был сделан по следующим причинам:

·    Существует специальный компилятор C, поставляемый в составе пакета DDK, предназначенный специальнодля компиляции драйверов. Он содержит множество макроопределений и библиотек,позволяющих сделать процесс написания драйвера более легким. Microsoft рекомендует его какосновную среду для разработки драйверов для Windows;

·    Программы на ассемблере работают быстрее, чем программы, написанныена C. Норазница в скорости между этими языками не очень велика. Зато производительностьтруда при использовании C намного выше, чем при использовании ассемблера.


3.1.2 Управляющее приложение

Управляющее приложение было создано в среде разработки Borland C++ Builder, поскольку эта средапрограммирования предоставляет широкие возможности по созданиюпользовательского интерфейса и ускоряет процесс разработки программныхпродуктов. Данная среда программирования содержит множество стандартныхэлементов оконного пользовательского интерфейса, использование которыхпозволило сделать управляющее приложение простым и понятным для пользователя.Для рассматриваемого приложения скорость работы и объем исполняемого файла неявляются критичными факторами, поэтому выбор среды Borland C++ Builder можно считать вполнеобоснованным.

3.2 Структуры данных драйвера-фильтра

Для сбора информации о вводе / выводе устройства используетсяструктура BUFFER, объявленная в драйвере следующим образом:

typedef struct _BUFFER

{

PVOID Buffer;

PMDL Mdl;

ULONG MaxSize;

ULONG CurrentSize;

} BUFFER, *PBUFFER;

Поясним значения полей структуры:

·    Buffer – указатель на буфер, хранящий информацию;

·    Mdl – указатель на MDL‑список, хранящийотображение буфера на системные страницы в памяти;

·    MaxSize – максимальный размер буфера в байтах;

·    CurrentSize – текущий размер буфера в байтах.

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

В разрабатываемом драйвере в расширении устройства расположена следующаяинформация:

typedef struct _DEVICE_EXTENSION

{BUFFER UrbPackets;

HANDLE LogFileHandle;

BOOLEAN PreparedToLog;

PURB Urb;

ULONG UrbCount;

PDEVICE_OBJECT topDevObject;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

Поясним назначение указанных переменных:

·    UrbPackets – буфер для протоколирования;

·    LogFileHandle – дескриптор файла, в который записывается информация о вводе /выводе;

·    PreparedToLog – флаг, указывающий на то, что подготовка к протоколированиюпрошла успешно;

·    Urb – пакет, информация о котором переносится в буфер UrbPackets;

·    UrbCount – число URB‑пакетов, прошедших через фильтр;

·    topDevObject – объект устройства, находящийся в стеке под нашим устройством.


3.2 Интерфейс управляющего приложения

Управляющее приложение предназначено для установкидрайвера-фильтра в системе и передачи ему параметров протоколирования черезсистемный реестр.

Интерфейс управляющего приложения состоит из главного окна,представленного на рисунке 3.2.1:

/>

Рис. 3.2.2 Интерфейс управляющего приложения

В левой части окна расположен список, в котором отображаются именаустройств, присутствующих в системе.

Перед установкой драйвера-фильтра на некоторый USB‑накопитель, следуетсоздать ключ драйвера в системном реестре. Для этого следует разместить файлдрайвера MyUSBFlt.sys в корневом каталоге управляющего приложения и нажать кнопку«Создать ключ драйвера». По окончании операции будет выдано сообщение о еерезультате.

Установка драйвера-фильтра допускается только на устройства типа«Запоминающее устройство USB». Для этого устройство следует выделить в списке, а затем ввестимаксимальный размер лог-файла и путь к нему. После этого следует нажать кнопку«Установить драйвер». В зависимости от результата установки будет выданосообщение об успехе операции или ее неудаче.

Драйвер-фильтр начнет свою работу после того, как устройство, накоторое он был установлен, будет перезапущено. Перезапуск можно осуществить путемвыделения нужного устройства в списке и нажатия кнопки «Перезапуститьустройство». Того же результата можно добиться, перезапустив устройство типа«Хост-контроллер» или «Корневой концентратор», к которому подключен рассматриваемыйUSB‑накопитель.Возможен также перезапуск устройства путем отсоединения от порта концентратораи последующего подключения к нему.

Удаление драйвера-фильтра из системы должно производиться вобратном порядке: сначала удаляется драйвер с устройства, а затем ключдрайвера. Это связано с тем, что в случае, если будет удален ключ драйвера, асамо устройство не будет освобождено от фильтра, то работа устройства будетблокирована. Но после полного удаления фильтра из системы и перезапускаустройства, его работа будет происходить в обычном режиме.

3.3 Тестирование драйвера-фильтра

Драйвер был протестирован с использованием стандартной тестирующейутилиты DriverVerifier, поставляемой в составе пакета DDK. С помощью этой утилитыбыли проведены следующие тесты:

·    Операции с пулами памяти;

·    Корректность уровней IRQL, на которых выполняется код драйвера;

·    Нехватка ресурсов;

·    Нетипичные запросы к драйверу.

Все тесты прошли успешно. Память в системе распределяласьправильно, ошибок с ней не возникало. На нехватку ресурсов драйвер реагировалкорректно. Нетипичные запросы к драйверу не обрабатывались им.

Для отладки драйвера использовалась программа DebugView. Эта утилита позволяетосуществлять перехват отладочных сообщений, выдаваемых драйвером.


Заключение

В данной работе рассмотрен вопрос, связанный с разработкойдрайверов устройств в системе Windows, и реализован драйвер-фильтр USB‑накопителя.

Разработанный драйвер предоставляет следующие возможности:

·    возможность установки на любой USB‑накопитель,присутствующий в системе;

·    перехват информации ввода / вывода USB‑накопителя;

·    запись перехваченной информации в файл на диске.

Драйвер-фильтр был протестирован с помощью тестовых утилит изсостава пакета DDK и отвечает всем современным требованиям, накладываемым ОС Windows на характеристики драйверов.

Тем не менее, существуют пути по усовершенствованию разработанногопрограммного комплекса. Например, существует возможность по созданию связки «драйвер уровня ядра – управляющее приложение пользовательского уровня», которая при наличии развитых механизмов синхронизациипозволила бы получать информацию о вводе / выводе устройства винтерактивном режиме. Но это достаточно трудоемкая задача, выходящая за рамкикурсовой работы.


Списоклитературы и интернет-ресурсов

1. Агуров П.В. Интерфейсы USB. Практика использования ипрограммирования. – СПб.:БХВ-Петербург, 2004. – 576 с.

2. Солдатов В.П. Программирование драйверов Windows. Изд. 2-е, перераб. и доп. – М.: ООО «Бином-Пресс»,2004. – 480 с.

3. Материалы проекта «Windows Assembly Site» – www.wasm.ru.

4. Материалы сайта www.usb.org.

5. MSDN Library, Copyright 1987–2005 Microsoft Corporation.

еще рефераты
Еще работы по информатике, программированию