необхідно приєднатися до стеку файлової системи, то буде викликана функція AttachToFsDO (опис даної функції див. далі), якщо необхідно відчепитися - буде викликана функція DetachFromFsDO (її опис див. далі).
AttachToFsDO
void AttachToFsDO(PDEVICE_OBJECT pFsDeviceObject);
pFsDeviceObject - покажчик на об'єкт пристрою файлової системи, до якого потрібно приєднатися.
Першою справою дана функція створює об'єкт пристрою (FiDO). Потім намагається приєднати його до зазначеного об'єкта пристрою файлової системи. Дана функція використається не тільки під час ініціалізації драйверу.
DetachFromFsDO
void DetachFromFsDO (PDEVICE_OBJECT pFsDeviceObject);
pFsDeviceObject - покажчик на об'єкт пристрою файлової системи, від якого потрібно від’єднатися.
Функція від'єднує наш об'єкт пристрою від об'єкта пристрою файлової системи й видаляє його. Дана функція використається не тільки під час ініціалізації драйверу.
3.4.2 Опис класу «Асоціативний список»
Реалізація класу “Асоціативний список” (Association List) представляє собою хеш таблицю, у якій можна зберігати дані й при правильно підібраному розмірі швидко знаходити необхідну інформацію. Величезним достоїнством цього класу є відсутність обмежень на структуру даних. Тобто формат даних, що зберігаються в хеш таблиці, може бути довільним. Розглянемо члени даного класу:
m_HashTableSize – розмір хеш таблиці;
m_cbValueServicePart – кількість байт для зберігання службової інформації (це значення ключа й покажчик на наступний елемент, що має таке ж хеш-значення);
m_cbValueInfoPart – кількість байт для зберігання асоційованих із ключем даних (яка-небудь структура);
m_pHashTable – хеш таблиця (масив покажчиків на списки).
Розглянемо методи класу “Асоціативний список”:
Init – метод, у параметрах якого потрібно вказати розмір хеш таблиці (HashTableSize) і кількість байт для зберігання власної інформації (cbValueInfoPart). По-перше, будуть проініціалізовані члени класу. По-друге буде виділена пам'ять (з пула) для масиву покажчиків (m_pHashTable). Тобто для кожного хеш-значення, якщо буде потреба, буде створено список;
DeInit – даний метод видаляє всі створені списки й звільняє пам'ять для масиву покажчиків на списки;
Add – даному методу необхідно передати як параметри значення ключа (Key) і покажчик на структуру (pInfo), яку потрібно зберегти в хеш таблиці. Розмір даної структури повинен дорівнювати значенню члена класу m_cbValueInfoPart. Цей метод додає значення в таблицю, при цьому, створюючи елемент списку, що складається із двох частин (службова частина ListItemServicePart і інформаційна - структура, розмір якої буде зазначений при виклику методу Init). При створенні елемента списку буде виділена пам'ять для службової й інформаційної частин. Інформаційна частина буде розміщена відразу ж за службовою. Ідеальним є випадок, коли кожному ключу відповідає своє хеш значення, тобто в списку перебуває всього по одному елементу. Але, якщо відбудеться колізія, то для даного хеш значення буде створений “дійсний” список, тобто даний список буде складатися більш ніж з одного елемента;
Delete – тут єдиним параметром є ключ (Key). Елемент списку, відповідному даному ключу буде вилучений з хеш таблиці;
Get – для даного методу параметром є ключ (Key). У результаті успішного пошуку буде повернутий покажчик на хеш-значення, інакше значення NULL;
Даний клас використається у фільтрі-драйвері для зберігання:
Відповідності між покажчиком на фізичний або логічний об'єкт пристрою й його серійним номером, структурою VOLUME, що відповідає даному тому. Такі відповідності зберігається в глобальної змінної g_MountedVolumes;
Відповідності між покажчиком на об'єкт файлу й покажчиком на його унікальний ідентифікатор. Відповідності такого роду зберігається в глобальної змінної g_FileObjects.
3.4.3 Опис функцій для обробки пакетів, адресованих керуючому об'єкту пристрою
Перелічимо ці функції:
CfShutDown;
TestRegister;
CfDeviceIoControl;
GetStandardizedPath;
GetPdoPointer.
CfCreate
NTSTATUS
CfCreate(
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp);
pDeviceObject - покажчик на об'єкт пристрою (CDO).
pIrp - покажчик на пакет запиту на ввід-вивід.
Дана функція обробляє запити зі старшим кодом IRP_MJ_CREATE.
CfCreate повертає STATUS_SUCCESS і завершує обробку даного запиту.
CfShutDown
NTSTATUS
CfShutDown (
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp);
pDeviceObject - покажчик на об'єкт пристрою (CDO).
pIrp - Покажчик на пакет запиту на ввід-вивід.
Дана функція обробляє запити зі старшим кодом IRP_MJ_SHUTDOWN. Вона викликає функцію TestRegister і завершує обробку даного запиту з кодом, що повернула функція TestRegister. Алгоритм роботи даної функції показано на мал. 3.4.1.
Мал. 3.4.1 Алгоритм роботи функції CfShutDown
TestRegister
NTSTATUS TestRegister();
Функція перевіряє ключ реєстру HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\CRIOFILE чи перебуває там строковий параметр ImagePath, якому привласнене ім'я файлу ядра безпеки із вказівкою повного шляху до нього. Якщо цей параметр відсутній, то він створюється знову. Якщо йому привласнене неправильне значення, то йому привласнюється правильне значення. Однак якщо відсутній вищевказаний розділ реєстру й при цьому на диску відсутній файл ядра безпеки, то інформація в реєстрі не відновлюється.
CfDeviceIoControl
NTSTATUS CfDeviceIoControl(PDEVICE_OBJECT pDeviceObject,
PIRP pIrp);
pDeviceObject - покажчик на об'єкт пристрою (CDO).
pIrp - Покажчик на пакет запиту на ввід-вивід.
Дана функція обробляє запити зі старшим кодом IRP_MJ_DEVICE_CONTROL. Докладний опис дій, які виконує функція залежно від значення керуючого коду (CTL_CODE), наведене в Додатку А. Алгоритм роботи даної функції показано на мал. 3.4.2.
Мал. 3.4.2 Алгоритм роботи функції CfDeviceIoControl
Функція повертає код помилки або STATUS_SUCCESS код.
GetPdoPointer
unsigned GetPdoPointer(WCHAR VolumeLetter);
VolumeLetter - літера диску.
Літера диску буде використана для створення символічного посилання. Потім ми відкриваємо це символічне посилання, одержуємо ім'я пристрою, якому вона відповідає. По імені об'єкта пристрою одержуємо покажчик на об'єкт пристрою і його повертаємо. Дана функція використовується при обробці DIOC_GETSECURITYATTR і DIOC_GETSECURITYATTR керуючих кодів.
GetStandardizedPath
bool GetStandardizedPath(UNICODE_STRING
*pusStandardizedPath);
pusStandardizedPath - покажчик на структуру, у якій утримується шлях. Даний шлях потрібно перетворити в стандартизований шлях. У випадку помилки дана функція повертає FALSE, інакше - TRUE.
3.4.4 Опис функцій для обробки пакетів, адресованих фільтруючому об'єкту пристрою
До вищезгаданих функцій відносяться наступні:
CfFiDOCreate;
CfFiDORead;
CfFiDOWrite;
CfFiDOCreate
NTSTATUS CfFiDOCreate(PDEVICE_OBJECT pDeviceObject, PIRP
pIrp);
pDeviceObject - покажчик на об'єкт пристрою, якому адресований пакет запиту на уведення-вивід.
pIrp - покажчик на пакет запиту на ввід-вивід.
Дана функція виконує наступні дії:
1 Перевіряє покажчик на об'єкт файлу (file object), якщо він дорівнює NULL, те передає запит драйверу, що лежить нижче.
2 Перевіряє поле FileName