власний метод налагодження. Фільтр-драйвер передбачалося тестувати на віртуальних машинах, які мають серед іншого віртуального встаткування паралельний порт, якому можна зіставити який-небудь файл реальної машини. Ця можливість і була використана. Був написаний код дебагу, головним обов'язком якого було записувати інформацію в паралельний порт. Код дебагу дає можливість викликати в будь-якому місці фільтра-драйвера функцію TRACE, що приймає такі ж аргументи, що й функція Win32 printf. Можна відстежити які функції фільтра драйвера були викликані в процесі роботи, які значення мали певні змінні й т.д. Величезним плюсом даного методу налагодження є те, що ми маємо можливість стежити за роботою драйвера до останнього моменту (так званого блакитного екрана смерті). Це дуже полегшує налагодження драйверу. Адже найменша помилка в коді (наприклад, обіг по нульовій адресі) приводить до повної зупинки операційної системи.
3.4 Реалізація драйверу
3.4.1 Опис функції DriverEntry і функцій використовуваних нею
DriverEntry у процесі своєї роботи використовує наступні функції:
CreateNamedDeviceObject,
FindDriverLocation,
LoadFSESA,
FindFileSystems,
FilesDispatch
DetachFromFsDO
AttachToFsDO
FilesFSNotification
CreateNamedDeviceObject
NTSTATUS
CreateNamedDeviceObject (
PDRIVER_OBJECT pDriverObject );
pDriverObject - покажчик на об'єкт драйвера.
Функція створює іменований об'єкт пристрою (control device object або CDO). Даний об'єкт використовується додатками рівня користувача для того щоб управляти драйвером. Як відомо додатки Win32 не мають доступу до всьому простору імен менеджера об'єктів (Object Manager) і не зможуть прямо звертатися до даного об'єкта пристрою, тому для даного керуючого об'єкта пристрою необхідно створити символічне посилання в директорії “\??” або “\GLOBAL”, що дана функція й виконує. У випадку помилки буде повернутий код помилки. Функція повертає код помилки або код STATUS_SUCCESS.
FindDriverLocation
NTSTATUS FindDriverLocation();
Дана функція, використовуючи покажчик на шлях у реєстрі (переданий менеджером вводу-виводу як параметр у функцію DriverEntry), шукає в реєстрі повне ім'я даного драйвера й зберігає дане значення до глобальної змінної g_usDriverLocation. Функція повертає код помилки або код STATUS_SUCCESS.
LoadFSESA
NTSTATUS LoadFSESA(PUNICODE_STRING pusFsesaLocation);
pusFsesaLocation - покажчик на структуру, у якій перебуває повне ім'я файлу FSESA. Даний файл повинен перебуває в тій же директорії, що й файл фільтра-драйвера. Функція виконує наступні дії:
Відкриває файл FSESA;
Визначає розмір файлу FSESA;
Читає заголовок файлу й зберігає його в глобальної змінної g_FsesaHeader, перевіряє правильність сигнатури файлу FSESA;
Виділяє з несторінкового пула пам'ять для купи файлів, що треба заблокувати й зчитує в цей буфер список файлів що треба заблокувати;
Виділяє зі сторінкового пула пам'ять для купи томів і зчитує в цей буфер уміст купи томів у файлі FSESA; ініціалізує глобальні змінні, стосовні до купи томів;
Виділяє зі сторінкового пула пам'ять для купи елементів каталогу й зчитує в цей буфер уміст купи елементів каталогу у файлі FSESA;
Ініціалізує глобальні змінні, стосовні до купи елементів каталогу; привласнює полям cFileOpenings всіх структур у даній купі значення 0 і опускає прапор SAFLAG_SIZECHANGED;
Якщо на якому-небудь із перерахованих етапів відбудеться помилка, то буде повернуто код даної помилки й ініціалізація драйвера завершиться з помилкою. Функція повертає код помилки або код STATUS_SUCCESS.
FindFileSystems
NTSTATUS FindFileSystems(WCHAR *puPath);
puPath - покажчик на рядок у кодуванні Unicode, завершену нульовим символом. Дана функція використається DriverEntry при пошуку активних файлових систем для Windows 2000 (в Windows XP необхідності в цій функції немає). Для того щоб не пропустити ні однієї файлової системи, функція перебирає вміст директорії “\FileSystems” глобального простору імен менеджера об'єктів. При цьому для кожного драйвера файлової системи потрібно одержати покажчик на об'єкт драйвера, за допомогою якого потрібно одержати покажчики на об'єкти пристроїв, що належать даній файловій системі. Тепер, одержавши покажчик на об'єкт пристрою локальної файлової системи, можливо прикріпитися зверху до стеку драйверів даної файлової системи й одержувати запити (IRPs), адресовані файлової системи. Для того щоб прикріпити наш об'єкт фільтр-пристрою (Filter Device Object - FiDO) до об'єкта пристрою файлової системи використовується функція AttachToFsDO (її опис див. далі). Функція повертає код помилки або код STATUS_SUCCESS.
FilesDispatch
NTSTATUS FilesDispatch(PDEVICE_OBJECT pDeviceObject,
PIRP pIrp);
pDeviceObject - покажчик на об'єкт пристрою, якому адресований IRP.
pIrp - покажчик на пакет запиту на ввід-вивід.
Дана функція визначає, якому з об'єктів пристроїв (керуючому об'єкту пристрою або фільтруючому об'єкту пристрою) адресований даний пакет і викликає відповідну робочу процедуру. Функція повертає код помилки або код STATUS_SUCCESS.
DriverEntry
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pusRegistryPath);
pDriverObject - покажчик на об'єкт драйвера.
pusRegistryPath - покажчик на ключ у реєстрі, створений для фільтра-драйвера.
Крім виклику перерахованих вище функцій, при виклику DriverEntry виконуються наступні дії:
Створюється та ініціалізується м’ютекс g_pFsesaMutex для синхронізації доступу до даних;
Виклик функції IoRegisterFsRegistrationChange для реєстрації бажання даного драйвера одержувати повідомлення про реєстрацію файлової системи в якості активної файлової системи;
Створення асоціативного списку g_MountedVolumes для зберігання зв'язку між змонтованим томом і нашими внутрішніми структурами;
Створення асоціативного списку g_EncryptedFileObjects для зберігання зв'язку між файловим об'єктом і нашими внутрішніми структурами;
Реєстрація робочих процедур фільтра-драйвера;
Реєстрація функцій для обробки запитів на швидкий ввід-вивід (Fast I/O);
Реєстрація функції DeallocateResources, що викличе менеджер вводу-виводу при динамічному вивантаженні драйвера. Динамічна вивантаження й завантаження фільтра-драйвера використається під час налагодження даного драйвера.
Функція повертає код помилки або код STATUS_SUCCESS.
DeallocateResources
void DeallocateResources(PDRIVER_OBJECT pDriverObject);
pDriverObject - покажчик на об'єкт драйвера.
У даній функції відбувається звільнення всіх ресурсів, виділених драйвером.
FilesFSNotification
void CrioFilesFSNotification (PDEVICE_OBJECT
pDeviceObject, BOOLEAN bFsActive);
pDeviceObject - покажчик на керуючий (іменований) об'єкт пристрою файлової системи.
bFsActive - прапор, показує зареєструвала файлова система об'єкт пристрою або немає.
Менеджер вводу-виводу викличе дану функцію, щоб сповістити фільтр-драйвер про те, що певна файлова система реєструє себе в якості активної файлової системи. Дана функція визначає чи потрібно причіплятися до даного об'єкта, якщо прапор bFsActive дорівнює TRUE, або визначає потрібно чи відчепитися від даного об'єкта, якщо файлова система разрегеструє себе. Якщо