оящим драйвером
При відстеженні обміну даними драйвер-фільтр може отримувати повідомлення про те, що деякий переданий запит був завершений нижчестоящим драйвером. Механізм повідомлення полягає в тому, що викликом спеціальної функції IoSetCompletionRoutine фільтр звертається до стека в пакеті IRP. У позиції стека, наступної за поточною позицією, він встановлює в спеціальному полі адреса функції завершення (completion routine). Потім при передачі пакета по ланцюжку позиція стека збільшується.
Колиа нижчий драйвер відправляє пакет запиту на завершення (викликом IoCompleteRequest), підсистема вводу/виводу починає переглядати стек всередині цього пакета від кінця до початку. Якщо в якійсь позиції стека визначена функція завершення, управління передається їй. Відпрацювавши, функція повертає результат, що сигналізує про успіх, помилково або необхідності подальшої обробки запиту.
При перших двох варіантах підсистема вводу/виводу переходить до наступної позиції стека і продовжує перегляд, поки не буде досягнуто його початок. Після цього запит завершується нормальним чином.
При третьому ж варіанті перегляд стека негайно припиняється і клопотання не буде завершений. Ця можливість реалізована для того, щоб драйвер-фільтр міг виконати будь-які дії над пакетом запиту після того, як той буде оброблений в нижестоящем драйвері. Після такої «додаткової обробки» пакет знову повинен бути відправлений на завершення.
2.Технічні частина
2.1 Точки входу розроблювального драйвера
Розроблюваний драйвер є драйвером нижнього рівня. У стеці драйверів USB-накопичувача він знаходиться безпосередньо під драйвером пристрою, якщо після його завантаження не відбудеться установки якого-небудь іншого драйвера-фільтра нижнього рівня.
Розроблюваний драйвер включає в себе наступні точки входу:
· DriverEntry; У цій функції відбувається реєстрація всіх стандартних точок входу драйвера і обробників IRP-пакетів.
· AddDevice; Управління цієї функції передається диспетчером вводу/виводу після того, як завершує свою роботу DriverEntry. AddDevice створює функціональний об'єкт пристрою за допомогою виклику IoCreateDevice і підключає його до стека драйверів вибраного пристрою (викликом IoAttachDeviceToDeviceStack). Крім того, в цій функції здійснюються дії з підготовки до протоколювання: зчитуються налаштування з системного реєстру, виділяється буфер для збору протоколюються інформації, створюється лог-файл.
· DriverUnload; Функція DriverUnload необхідна для того, щоб зробити драйвер вивантажується. У успадкованих драйверах на цю функцію покладено весь процес вивантаження драйвера: видалення символьних посилань, об'єктів пристроїв драйвера, відключення переривань від об'єктів, звільнення виділеної пам'яті. У WDM-драйверах всі ці дії покладені на функцію-обробник пакетів з кодом IRP_MJ_PNP.
Функції обробки IRP-пакетів:
· FilterDispatchPnp; На цю функцію покладено обов'язки з обробки IRP-пакетів з різними кодами, хоча в розробляється драйвері існує необхідність в обробці тільки двох типів запитів. Всі запити з кодом, відмінним від IRP_MJ_PNP передаються вниз по стеку драйверів без змін. Запити ж IRP_MJ_PNP диспетчеризующая по суб-кодами у функції PnP_Dispatch. Необхідність диспетчеризації після суб-кодами запитів IRP_MJ_PNP викликана тим, що драйвер не повинен порушувати порядку роботи операційної системи і зобов'язаний підкорятися PnP-менеджеру, тобто в драйвері повинні коректно оброблятися події старту і видалення пристрою.
· FilterDispatchIoVista; Запити вводу/виводу до USB-накопичувача передаються у складі IRP-пакетів з кодом IRP_MN_INTERNAL_DEVICE_CONTROL. Цей пакет містить повну інформацію про повернення і характері переданих даних. Тобто для протоколювання обміну інформацією з USB-пристроєм слід перехоплювати пакети саме цього типу.
Для того щоб перехоплювати інформацію, передану в обох напрямках, слід встановити функцію зворотного виклику диспетчера введення/виводу. При наявності цієї функції розроблюваний драйвер-фільтр отримає можливість перехоплення даних, переданих від пристрою до хосту.
Така методика обрана через те, що функція FilterDispatchIoVista працює на рівні запиту переривань, рівному DISPATCH_LEVEL, що сильно ускладнює використання механізмів синхронізації, які могли б дозволити перейти на рівень запиту переривань, рівний PASSIVE_LEVEL, де стають доступними функції роботи з файлами. Якби це було досягнуто в розробляється драйвері, то відпала б необхідність виділення великих обсягів нестранічной пам'яті для зберігання протоколу.
Запис файлу на диск у момент видалення пристро...