Перевизначення призначень клавіш на клавіатурі в операційній системі Windows

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Факультет: Інформатика та системи управління
Кафедра: Програмне забезпечення ЕОМ та інформаційні технології
РОЗРАХУНКОВО-ПОЯСНЮВАЛЬНА ЗАПИСКА
до курсового проекту на тему:
"Перевизначення призначень клавіш на клавіатурі
в операційній системі Windows "
2009

Зміст
Введення. 4
1. Аналітичний розділ. 5
1.1 Постановка завдання. 5
1.2 Архітектура Windows XP. 5
1.3 Модель WDM .. 8
1.4 Стек клавіатури .. 9
1.5 Структура драйвера. 12
DiverEntry. 12
AddDevice. 12
DriverUnload. 13
Процедури обробки пакетів IRP. 13
Функція обробки пакетів IRP_MJ_DEVICE_CONTROL. 15
Функція обробки пакетів IRP_MJ_READ .. 16
Функція обробки пакетів IRP_MJ_PNP. 16
ISR .. 16
1.6 Аналіз методів рішення задачі. 17
2. Конструкторський розділ. 19
2.1 Точки входу розроблюваного драйвера-фільтра. 19
DiverEntry. 19
AddDevice. 20
DriverUnload. 21
Процедури обробки пакетів IRP. 21
Функція обробки пакетів IRP_MJ_DEVICE_CONTROL. 21
Функція обробки пакетів IRP_MJ_READ .. 22
Функція обробки пакетів IRP_MJ_PNP. 22
Обробка інших пактів IRP. 23
2.2 Взаємодія компонентів системи .. 24
2.3 Розміщення драйвера в пам'яті. 24
2.4 Перевизначення клавіш .. 25
2.5 Установка драйвера в системі. 27
3. Технологічний розділ. 30
3.1 Вибір мови програмування і засобів програмування. 30
Драйвер-фільтр. 30
Програма для встановлення драйвера. 31
Програма для управління драйвером. 31
3.2 Структури даних проекту. 31
Інформація про натиснення і отпусканиях клавіш .. 31
Структура списку замін. 33
Додаткова інформація. 33
3.3 Інтерфейс керуючого додатки. 34
3.4 Тестування драйвера-фільтра клавіатури .. 35
Висновок. 37
Список літератури .. 38


Введення

Дуже часто виникає необхідність у перепризначення клавіш на клавіатурі.
§ Стандартне розташування клавіш незручно при роботі з певним програмним забезпеченням
§ При переході з одного типу клавіатури на інший важко звикнути до нового розташування клавіш.
У багатьох випадках певні клавіші можуть перешкодити роботі. Випадкове натискання на такі клавіші уповільнює роботу користувача. Бажано, щоб натискання цих клавіш не призводило ні до яких дій.
Тому завдання перевизначення і відключення клавіш є на сьогоднішній день актуальною.
Існують програми, вирішальні поставлене завдання. Прикладами таких програм є програма Марка Руссиновича Ctrl 2 і програма MagicKey.
Програма Ctrl2 замінює клавішу CapsLock на клавішу «лівий Ctrl». Вона реалізована у вигляді драйвера.
Програма MagicKey, дозволяє міняти місцями алфавітно-цифрові клавіші. Вона реалізована у вигляді драйвера і користувальницького додатка для управління цим драйвером.

1. Аналітичний розділ

1.1 Постановка завдання
Відповідно до завдання на курсову роботу, необхідно розробити програмне забезпечення, що дозволяє перевизначати призначення клавіш на клавіатурі.
§ Програмне забезпечення повинно дозволяти перевизначати всі клавіші клавіатури
§ Програмне забезпечення повинно дозволяти відключати клавіші.
§ Програмне забезпечення повинно дозволяти встановлювати список здійснюваних замін.
§ Програмне забезпечення не повинно порушувати і сповільнювати роботу системи.

1.2 Архітектура Windows XP

Windows XP є наступною - після Windows 2000 і Windows Millennium - версією операційної системи Microsoft Windows. Найбільш поширені реалізації даної ОС для платформи Intel x86 в одно-або багатопроцесорних конфігураціях, проте існують також версії для DEC Alpha і MIPS. Дана операційна система використовує захищений режим центрального процесора, реалізує механізми віртуальної пам'яті і багатозадачності.
Windows XP використовує два рівні привілеїв: рівень привілеїв 0, відповідний коду режиму ядра і рівень привілеїв 3, відповідний кодом прикладних завдань (всього існує чотири рівні привілеїв). Рівень привілеїв накладає певні обмеження: у режимі користувача не можуть виконуватися привілейовані інструкції процесора і не дозволено звернення до захищених сторінок в пам'яті. Ці обмеження накладаються для забезпечення безпеки роботи системи. Для користувача додаток не повинно мати можливість - в результаті помилки або навмисно - вносити зміни в системні таблиці або в пам'ять інших додатків. Зокрема, такі обмеження забороняють користувача додатком безпосередньо керувати зовнішніми пристроями.
У Windows XP забезпечення обміну даними і управління доступом до зовнішнього пристрою покладається на його драйвер. Введення і виведення в драйверах здійснюється пакетами - IRP (Input / Output Request Packet). Запити на введення / висновок, що їх посилають додатками або іншими драйверами, обробляються драйвером, після чого запитуючої програмою в тому ж пакеті надсилається статус завершення операції.
Архітектура введення / виводу в Windows XP має ієрархічну структуру. Для здійснення операції введення / виводу користувальницький додаток повинно викликати одну з функцій API. Ця функція створює необхідний IRP пакет і направляє його підсистемі введення / виводу. Підсистема вводу / виводу направляє IRP пакет необхідного драйвера. Драйвер здійснює обіг до пристроїв, використовуючи функції HAL.
HAL (Hardware Abstraction Layer) - це шар програмного забезпечення, який приховує специфіку апаратної платформи від інших компонентів системи. Він забезпечує малі витрати при перенесенні системи або елементів програмного забезпечення. На Рис. 1. показана архітектура введення / виводу Windows XP.


Рис. SEQ Рис. \ * ARABIC 1. Архітектура введення / виводу Windows XP
Управління зовнішнім пристроєм в загальному випадку зводиться до заповнення регістрів контролера необхідними даними. Монопольний доступ драйвера до цих регістрів гарантується операційною системою. Очевидно, що за даних обставин потрібно, щоб драйвер пристрою виконується в режимі ядра. В архітектурі Windows XP існують так звані драйвери віртуальних пристроїв для підтримки DOS-додатків, яка крутиться в реальному режимі.
Класифікація драйверів Windows XP
§ Драйвери режиму ядра
· Драйвери файлових систем
· Успадковані
· Драйвери Plug and Play
· Відеодрайвери
§ Драйвери користувальницького режиму
· Драйвери віртуальних пристроїв

1.3 Модель WDM
Windows Driver Model (WDM) - це стандартна специфікація Microsoft для розробників драйверів пристроїв. Вона підтримується в операційних системах Windows 98/Me/2000/XP. Компанія Microsoft вимагає, щоб всі нові драйвери під ці операційні системи створювалися з цієї специфікації. Для цього від них вимагається чітке дотримання структурі WDM, підтримка Plug and Play і управління електроживленням.
Драйверне модель WDM побудована на організації і маніпулюванні шарами «Об'єктів фізичних пристроїв» і «Об'єктів функціональних пристроїв». Об'єкт-пристрій - це особлива структура даних, створювана системою для взаємодії програмного і апаратного забезпечення. Об'єкт PDO створюється для кожного знайденого елемента апаратури, підключеного до шини даних. Об'єкт FDO пропонує «уособлення» кожної логічної функції, яку бачить у пристрої програмне забезпечення верхніх рівнів.

Функціональним Об'єктам пристроїв дозволяється оточувати себе Об'єктами Фільтрами (Filter Device objects). Відповідно, кожному FiDO об'єкту сопоставлен драйвер, який виконує певну роботу. Об'укти фільтри підрозділяються на фільтри нижнього рівня та фільтри верхнього рівня. І тих і інших може існувати довільна кількість. Вони модифікують процес обробки запитів вводу / виводу. Об'єкти FDO і FiDO відрізняються тільки в смисловому плані. FDO об'єкт і його драйвер вважаються головними. Вони звичайно забезпечують керування пристроєм, а об'єкти FiDO є допоміжними.
Всі об'єкти FDO і FiDO позиціонують себе в стеку пристроїв. Порядок об'єктів в стеку визначає порядок обробки запитів вводу-виводу. Якщо необхідно перехопити і обробити запит, безпосередньо йде від користувача, то потрібно встановлювати верхній фільтр. Якщо ж потрібно відслідковувати звернення до портів вводу виводу, обробляти переривання, то потрібен нижній фільтр. Дана модель дозволяє драйверу встановлювати callback процедури. Коли запит починає оброблятися, то він обробляється послідовно усіма драйверами стека пристрої (виключаючи ситуацію, коли який-небудь драйвер сам завершить обробку запиту). Після цього диспетчер вводу-виводу передає запит callback процедурі кожного драйвера стека. Спочатку запит передається callback процедурі останнього драйвера який у стеку, потім процедурі передостаннього драйвера и.т. д. Callback процедури потрібні для того, щоб обробити прочитану з пристрою інформацію. Якщо фільтр обробляє запити на читання, то коли цей запит надійде в драйвер інформація ще не буде лічена. Тому драйверу необхідно встановити callback функцію. При її виклику запит вже буде містити лічені дані.
1.4 Стек клавіатури
Фізичну зв'язок клавіатури з шиною здійснює мікроконтроллер клавіатури Intel 8042. На сучасних комп'ютерах він інтегрований в чіпсет материнської плати. Цей контролер може працювати в двох режимах: AT-сумісному і PS/2-совместімом. Майже всі клавіатури вже давно є PS/2-совместімимі. У PS/2-совместімом режимі мікроконтроллер клавіатури також пов'язує з шиною і PS/2-совместімую миша. Даним мікроконтролером управляє функціональний драйвер i8042prt. Драйвер i8042prt створює два безіменних об'єкта «пристрій» і підключає один до стеку клавіатури, а інший до стека миші. Поверх драйвера i8042prt, точніше, поверх його пристроїв, розташовуються іменовані об'єкти «пристрій» драйверів Kbdclass і Mouclass. Драйвери Kbdclass і Mouclass є так званими драйверами класу і реалізують загальну функціональність для всіх типів клавіатур і мишей, тобто для всього класу цих пристроїв. Обидва ці драйвера встановлюються як високорівневі драйвери.
Стек клавіатури обробляє кілька типів. У цій роботі необхідно розглянути тільки IRP типу IRP_MJ_READ, які несуть з собою коди клавіш. Генератором цих IRP є потік необробленого введення RawInputThread системного процесу csrcc.exe. Цей потік відкриває об'єкт «пристрій» драйвера класу клавіатури для ексклюзивного використання і надсилає йому IRP типу IRP_MJ_READ. Отримавши IRP, драйвер Kbdclass відзначає його як очікує завершення (pending), ставить в чергу і повертає STATUS_PENDING. Потоку необробленого введення доведеться чекати завершення IRP. Підключаючись до стека, драйвер Kbdclass реєструє у драйвера i8042prt процедуру зворотного виклику KeyboardClassServiceCallback, направляючи йому IRP IOCTL_INTERNAL_KEYBOARD_CONNECT. Драйвер i8042prt теж реєструє у системи свою процедуру обробки переривання (ISR) I8042KeyboardInterruptService, викликом функції IoConnectInterrupt. Коли буде натиснута або відпущена клавіша, контролер клавіатури виробить апаратне переривання. Його обробник викличе I8042KeyboardInterruptService, яка прочитає з внутрішньої черги контролера клавіатури необхідні дані. Оскільки обробка апаратного переривання відбувається на підвищеному IRQL, ISR робить тільки саму невідкладну роботу і ставить в чергу виклик відкладеної процедури (DPC). DPC працює при IRQL = DISPATCH_LEVEL. Коли IRQL знизиться до DISPATCH_LEVEL, система викличе процедуру I8042KeyboardIsrDpc, яка викличе зареєстровану драйвером Kbdclass процедуру зворотного виклику KeyboardClassServiceCallback (також виконується на IRQL = DISPATCH_LEVEL). KeyboardClassServiceCallback витягне зі своєї черги чекає завершення IRP, заповнить структуру KEYBOARD_INPUT_DATA, несучу всю необхідну інформацію про натиснення / отпусканиях клавіш, і завершить IRP. Потік необробленого введення пробуджується, обробляє отриману інформацію і знову посилає IRP типу IRP_MJ_READ драйверу класу, який знову ставиться в чергу до наступного натискання / відпускання клавіші. Таким чином, у стека клавіатури завжди є, принаймні, один, що очікує завершення IRP і знаходиться він в черзі драйвера Kbdclass.
Розроблюваний драйвер-фільтр встановлюється над фільтром Kbdclass. Так як IRP типу IRP_MJ_READ є фактично запитом на читання даних, то коли він йде вниз по стеку його буфер, природно порожній. Прочитаний дані буфер буде містити тільки після завершення IRP. Для того, щоб ці дані побачити, фільтр повинен встановити в кожний IRP (точніше в свій блок стека) процедуру завершення. У цій процедурі як раз і будуть здійснюватися операції по перетворенню скенкодов.


1.5 Структура драйвера
Драйвер має такі точки входу:
§ DriverEntry
§ DriverUnload
§ AddDevice
§ Функції для обробки пакетів IRP
§ ISR
DiverEntry
Процедура DiverEntry має бути присутня у будь-якому драйвері. На дану процедуру покладено функцію початкової ініціалізації та визначення інших точок входу в драйвер. Вона виконується у момент завантаження драйвера. У драйверах WDM значення цієї функції значно зменшилася, більша частина роботи покладається на функцію AddDevice. Для реєстрації точок входу у драйвер DriverEntry повинна заповнити відповідні поля в структурі об'єкта драйвера. Покажчик на цю структуру передається у функцію.
Поле DriverUnload необхідно заповнити адресою процедури, викликається при вивантаженні драйвера.
Поле DriverExtension-> AddDevice необхідно заповнити адресою процедури AddDevice.
Масив MajorFunctions заповнюється адресами процедур обробки IRP пакетів. Процедура, зареєстрована під номером N, обробляє IRP пакет з кодом N. Зазвичай драйвери використовують не всі ці процедури, а реєструють тільки потрібні. Інші ж елементи масиву заповнюються адресою процедури, що виконує передачу пакета нижче по стеку драйверів.
AddDevice
Ця функція реєструється, якщо драйвер підтримує PnP. Одна з головних обов'язків AddDevice - це створення об'єкта пристрої FDO і якщо необхідно підключення його до стека драйверів пристрою. Дана функція може створити кілька об'єктів пристроїв і підключити їх до різних стекам. Більш того, деякі пристрої FDO можуть існувати, не будучи в зв'язці з PDO. Вони часто сода для управління драйвером.
DriverUnload
Процедура DriverUnload необхідна для того, щоб зробити драйвер вивантажуємо. У драйверах «в стилі NT» на цю процедуру покладено весь процес вивантаження. Вона зобов'язана видалити всі символьні посилання, всі об'єкти пристроїв, відключити (якщо потрібно) переривання від об'єктів, очистити пам'ять за собою. У PnP драйверах всі ці дії покладені на обробник пакетів IRP_MJ_PNP.
Процедури обробки пакетів IRP
Функції, адреси яких записані в масиві MajorFunctions, викликаються диспетчером вводу / виводу для обробки відповідних запитів від клієнтського драйвера (призначених для користувача додатків або модулів рівня ядра). Ці запити оформляються у вигляді спеціальних структур - IRP пакетів.
При будь-якому запиті Диспетчер формує IRP. пам'ять для структури IRP виділяється в нестранічной пам'яті. У IRP записується код операції вводу виводу. Пакет IRP складається з заголовка, який має постійний розмір і стека IRP. Стек має змінну довжину.
Тема IRP пакету:
§ Поле IoStatus типу IO _ STATUS _ BLOCK містить два підполя
§ Status містить значення, яке встановлює драйвер після обробки пакета.
§ У Information найчастіше міститься число переданих або отриманих байт.
§ Поле AssociatedIrp. SystemBuffer типу void * містить покажчик на системний буфер для випадку якщо пристрій підтримує буферизованная введення / висновок.
§ Поле MdlAddress типу PMDL містить покажчик на MDL список, якщо пристрій підтримує пряме введення висновок.
§ Поле UserBuffer типу void * містить адресу користувацького буферу для введення / виводу.
§ Типу Cancel типу BOOLEAN - це індикатор того, що пакет IRP повинен бути анульований.

Стек IRP пакету
Основне значення осередків стека IRP пакету полягає в тому, щоб зберігати функціональний код і параметри запиту на ввід / вивід. Для запиту, який адресований драйверу самого нижнього рівня, що відповідає IRP пакет має тільки одну клітинку стека. Для запиту, який посланий драйверу верхнього рівня, Диспетчер введення / виведення створює пакет IRP з кількома стековими осередками - по одній для кожного FDO.
Кожна клітинка стека IRP містить:
§ MajorFunction типу UCHAR - це код, що описує призначення операції
§ MinorFunction типу UCHAR - це код, що описує суб-код операції
§ DeviceObject типу PDEVICE _ OBJECT - це покажчик на об'єкт пристрою, якому був адресований даний запит IRP
§ FileObject типу PFILE _ OBJECT - файловий об'єкт для даного запиту
Диспетчер введення / виводу використовує поле MajorFunction для того, щоб витягти з масиву MajorFunction потрібну для обробки запиту процедуру.
Кожна процедура обробки IRP пакетів повинна в якості параметрів мати:
§ Покажчик на об'єкт пристрою, для якого призначений IRP запит
§ Покажчик на пакет IRP, що описує цей запит
Повертає така функція значення типу NTSTATUS, що містить результат обробки.

Функція обробки пакетів IRP _ MJ _ DEVICE _ CONTROL
Ці функції дозволяють обробляти розширені запити від клієнтів користувацького режиму. Такий запит може бути сформований за допомогою виклику функції DeviceIoControl. Кожен IOCTL запит має свій код. Цей код передається як параметр функції DeviceIoControl. Код IOCTL - це 32-бітове число.
Запити IOCTL служать найчастіше для обміну даними між драйвером та програмою. Для передачі даних в Windows передбачені 4 способи
§ METHOD_BUFFERED
Вхідний користувальницький буфер копіюється в системний, а після закінчення обробки системний копіюється в у вихідний користувальницький буфер.
§ METHOD_IN_DIRECT і METHOD_OUT_DIRECT
Необхідні сторінки користувацького буферу завантажуються з диска в оперативну пам'ять і блокуються. І за допомогою DMA здійснюється передача даних між пристроєм і користувачем.
§ METHOD_NEITHER
При цьому методі передачі не проводиться перевірка доступності пам'яті, не виділяються проміжні буфера і не створюються MDL. У пакеті IRP передаються віртуальні адреси буферів у просторі пам'яті ініціатора запиту вводу / виводу.
Функція обробки пакетів IRP MJ READ
Ця функція повинна обробляти запити на читання інформації з пристрою.
Функція обробки пакетів IRP MJ PNP
Ця функція повинна обробляти запити від менеджера PnP.
ISR
Дана точка входу викличеться прі, коли відбудеться переривання, на яке зареєстрована ця ISR функція. Виклик може відбутися в будь-якому контексті: як ядра, так і для користувача процесу. Тут драйвер може або чекати наступного переривання (з будь-якою метою), або запросити відкладений виклик процедури (Deferred Procedure Call), DPC

1.6 Аналіз методів рішення задачі
Відповідно до завдання на курсову роботу, необхідно розробити програмне забезпечення, що дозволяє перевизначати призначення клавіш на клавіатурі. З аналізу архітектури Windows XP слід, що для доступу до інформації, яка містить скенкоди натиснутих або відпущених клавішею необхідно написати драйвер. Драйвер може отримати доступ до скенкодам натиснутих або відпущених клавіш двома способами. Або перехоплюючи IRP пакети від інших драйверів, або самостійно обробляючи переривання від клавіатури. Оптимальним є написання драйвера, який перехоплював би IRP пакети від драйвера клавіатури, тобто написання драйвера-фільтра. У цьому випадку немає необхідності переписувати вже зроблений драйвер клавіатури, потрібно написати драйвер, що змінює інформацію в приходять IRP пакетах.
Існує два типи драйверів фільтрів: драйвер-фільтр верхнього та нижнього рівня. У рамкою даного завдання не має значення на якому етапі буде проводиться перевизначення. Але краще вибрати драйвер-фільтр верхнього рівня, оскільки інформація повертається драйвером клавіатури добре документована і описана в літературі.
З огляду на те, що всі сучасні драйвери, рекомендується писати відповідно до стандарту PnP, оскільки вони володіють більшою функціональністю, то розробляється драйвер повинен бути драйвером PnP.
Формалізація постановки задачі:
§ Необхідно написати драйвер-фільтр верхнього рівня для драйвера клавіатури.
§ Драйвер-фільтр повинен перехоплювати IRP пакети, що містять скенкоди натиснутих і відпущених клавіш, перевизначати, якщо необхідно, скенкоди на скенкоди інших клавіш. Він повинен видаляти записи, що відповідають відключеним клавішах.
§ Рішення про те, які клавіші повинні бути перевизначені або відключені, приймається відповідно до списку замін, який зберігається в пам'яті ядра.
§ Для установки списку замін використовується користувальницький додаток, яке пересилає в драйвер список замін.
§ Драйвер повинен бути драйвером PnP.
§ Драйвер-фільтр не повинен гальмувати введення з клавіатури і роботу всієї системи в цілому. Драйвер-фільтр повинен забезпечити надійну роботу системи.

2. Конструкторський розділ
2.1 Точки входу розроблюваного драйвера-фільтра
Оскільки розробляється драйвер-фільтр є драйвером PnP, то повинен мати такі точки входу:
§ DriverEntry
§ DriverUnload
§ AddDevice
§ Функції для обробки пакетів IRP
Функції для обробки переривань в даній роботі не реєструються, оскільки драйвер не працює з перериваннями.
DiverEntry
У даній роботі процедура DriverEntry виконує наступні дії:
· Заповнення масиву MajorFunctions. Реєструється процедура обробки пакета на читання, процедура обробки IOCTL запитів, процедури обробки запитів від менеджера PnP і менеджера харчування. Інші елементи масиву заповнюються адресою функції MyPassNext, яка пропускає пакети нижче по стеку.
· Реєстрація процедури AddDevice. У даній роботі вона називається MyAddDevice.
· Реєстрація процедури DriverUnload, що називається MyUnload.
· Виділення пам'яті для зберігання масиву замін клавіш. Один запис масиву займає 4 байти, а максимум може бути тільки 103 заміни (клавіша Pause / Break не в рахунок). Значить максимальний обсяг масиву дорівнює 412 байт. DriverEntry відразу виділяє при завантаженні ці 412 байт. Не має сенсу економити і виділяти пам'ять динамічно при кожній ініціалізації масиву, оскільки 412 - це дуже мало, і система не буде витрачати час на звільнення і виділення пам'яті при кожній ініціалізації.
· Ініціалізація деяких глобальних змінних: AltPressed, CtrlPressed, KeyPause.
DriverEntry реєструє тільки необхідні процедури. Оскільки проект являє собою драйвер-фільтр верхнього рівня, і в ньому немає необхідності обробляти переривання, то не проводиться реєстрація DriverStartIo, процедур ISR і DPC.
AddDevice
У даній роботі функція MyAddDevice створює одне функціональний пристрій з назвою \ \ Device \ \ MyFilter. При створенні пристрою відбувається резервування місця для зберігання адреси пристрою, розташованого нижче в стеку драйверів. Це зроблено для того, щоб при руйнуванні стека драйверів передати запит PnP на демонтаж нижчестоящому драйверу. Створене пристрій підключається до стека драйверів клавіатури. Це робиться за допомогою функції IoAttachDeviceToDeviceStack. Це стандартна функція Windows, вона приймає PDO і покажчик на структуру підключається FDO. FDO займає місце в стеку драйверів відразу після об'єкту, що знаходиться у вершині стека. Тепер підключається FDO стає вершиною стека. Не можна підключиться до стека коли він уже сформований, тому необхідно підключиться до нього в певний момент. Черговість завантаження драйверів описана в реєстрі Windows. Програма установки виробляє необхідну реєстрацію. Структура цієї програми описана нижче.
Для того щоб користувальницький додаток змогло звернутися до драйвера (для завантаження в драйвер списку замін або для отримання списку замін, які драйвер здійснює в даний момент) для FDO повинно бути зареєстровано DOS ім'я. Використовуючи це ім'я додаток зможе послати драйверу IOCTL запит. Для реєстрації такого імені створюється рядок юнікод зі значенням \ \ DosDevices \ \ MyFilter і застосовується функція IoCreateSymbolicLink. Її параметрами є тільки що створена рядок і ім'я FDO, яке обслуговує наш драйвер. Тепер \ \ DosDevices \ \ MyFilter - це DOS ім'я створеного FDO пристрою.
DriverUnload
Оскільки даний фільтр є PnP драйвером, то на процедуру DriverUnload нічого не покладено.
Процедури обробки пакетів IRP
Розроблюваний драйвер-фільтр здійснює обробку наступних пакетів IRP:
§ IRP _ MJ _ DEVICE _ CONTROL
§ IRP _ MJ _ READ
§ IRP _ MJ _ PNP
Решта IRP пакети пропускаються нижче по стеку драйверів.
Функція обробки пакетів IRP _ MJ _ DEVICE _ CONTROL
У даній роботі для користувача додаток повинен мати можливість посилати IOCTL запити драйверу. Додаток повинен мати можливість одержати список поточних замін здійснюваних драйвером і передати драйверу новий список замін.
Для цього в тілі драйвера визначені дві 32-бітові константи.
§ GetKeys
CTL_CODE (FILE_DEVICE_KEYBOARD, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS)
§ SetKeys
CTL_CODE (FILE_DEVICE_KEYBOARD, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS)
Це коди IOCTL запитів не використовуються драйверами стека клавіатури. Тому в даному проекті вони можуть бути використані без жодних побоювань. Запити з першим кодом використовується для отримання списку поточних замін, з другим для його установки.
Оскільки в першому випадку драйверу необхідно отримати буфер з даними, а в другому передати його, то необхідно використовувати один з чотирьох способів передачі даних. У проекті застосовується спосіб METHOD_BUFFERED. Оскільки список замін займає всього 500 байт, то його розмір не зашкодить системного пулу, і копіюватися користувальницький буфер в системний буде дуже швидко. Немає необхідності застосовувати більш складні методи METHOD_IN_DIRECT або METHOD_NEITHER використовуються при передачі великих обсягів даних.
При обробці запиту на отримання списку замін процедура копіює дані з буфера драйвера в системний буфер. Після завершення обробки запиту менеджер вводу / виводу скопіює системний буфер у вихідний для користувача. Таким чином додаток зможе отримати список замін. При установці списку замін менеджер скопіює користувальницький буфер в системний, а функція обробки IOCTL скопіює системний буфер в буфер драйвера. Після цього драйвер починає робити заміну сканкодов, орієнтуючись на нові дані.
Функція обробки пакетів IRP _ MJ _ READ
Дана функція здійснює обробку пакетів на читання. IRP пакет спочатку буде потрапляти в розроблювальний драйвер. Викличеться зареєстрована в DriverEntry функція MyRead. До моменту виклику MyRead, буфер не містить кодів лічених клавіш. Для того щоб отримати доступ до них. MyRead повинна встановити CallBack процедуру. Вона отримає управління коли буфер IRP пакету буде містити інформацію про натиснутих клавішах і буде підніматися вгору по стеку драйверів і буде викликати CallBack функції на кожному рівні стека. CallBack процедура встановлюється за допомогою функції IoSetCompletionRoutine. Далі в MyRead відбувається копіювання поточної комірки IRP пакету в наступну клітинку, таким чином. Таким чином відбувається передача незмінених параметрів у Kbdclass.
Функція обробки пакетів IRP _ MJ _ PNP
Драйвер-фільтр повинен обробляти тільки запит IRP_MN_REMOVE_DEVICE. При цьому функція посилає даний пакет менеджера PnP нижчестоящому в стеку пристрою. Потім вона виробляє необхідні завершальні дії:
§ відключає пристрій від стека драйверів викликом функції IoDetachDevice
§ видаляє пристрій FDO викликом функції IoDeleteDevice
§ видаляє символьну посилання викликом IoDeleteSymbolicLink
Решта пакетів пропускаються нижче по стеку.
Обробка інших пактів IRP
Решта пакету IRP, які за непотрібністю не обробляються в даному фільтрі, пропускаються нижче по стеку. Процедури даного фільтра не в праві самостійно обробляти ці запити, тому що це можуть запити, адресовані нижчестоящим драйверам. Прикладом одного з таких запитів є IOCTL запит, адресований драйверу i8042prt і призначений для перепрограмування котроллер клавіатури і для запалювання лампочок на клавіатурі. Такі запити посилає Windows при виявленні натискання CapsLock, NumLock або ScrollLock.
У даній роботі за пропущення пакетів вниз відповідає процедура MyPassNext. Вона передає IRP пакет нижчестоящому драйверу за допомогою функції IoCallDriver. При цьому нижчий драйвер повинен зчитувати поточну клітинку IRP пакета. Це досягається за рахунок використання функції IoSkipCurrentIrpStackLocation

2.2 Взаємодія компонентів системи

2.3 Розміщення драйвера в пам'яті
Деякі процедури драйвера, ті які виконують ініціалізацію, вигідно виконати і звільнити пам'ять після виконання. Оскільки процедури ініціалізації виконуються лише один раз при завантаженні системи, а після цього перебувають у пам'яті, займаючи цінне місце. У мові C є спеціальна директива, що дозволяє розмістити ініціалізація код у спеціальній секції. Пам'ять з-під цієї секції буде повернена системі після виконання. Це директива # pragma alloc_text («INIT», ім'я). Параметром директиви є ім'я функції.
У даному фільтрі функцією, яка виконує ініціалізацію, є тільки DriverEntry. Її ім'я і є параметром директиви.
За замовчуванням функції драйвера розміщуються в нестранічной пам'яті. Ця пам'ять є дуже цінною, оскільки вона не може бути вивантажено на жорсткий диск. Економніше було б розмістити код драйвера в сторінково організованою пам'яті. Для цього в C передбачена директива # pragma alloc_text («PAGE», ім'я). Параметром директиви є ім'я функції, яка повинна бути розміщена в сторінково організованою пам'яті. У даному драйвері-фільтрі всі процедури крім DriverEntry розміщуються там.
2.4 Перевизначення клавіш
Оскільки функція MyRead, яка обробляє пакети IRP _ MJ _ READ, отримує пакет IRP без прочитаних даних, то вона встановлює CallBack процедуру. Ця процедура викликається, коли буфер отримує дані.
Реалізація процедури MyReadBack

N - це кількість записів в буфері.
K - кількість записів у масиві замін.
S [i] - скенкод клавіші, відповідної i-ої запису буфера.
F1 [j] - скенкод замінної клавіші (j-а запис масиву замін).
F2 [j] - скенкод клавіші, на яку відбувається заміна (j-а запис масиву замін).
Клавіша Pause
Драйвер не дозволяє замінити клавішу Pause на яку або іншу клавішу, поскільки вона сигналізує тільки при натисканні. Але ця клавіша може видавати різні записи в буфері, в залежності від того, натиснуто Ctrl чи ні.
Припустимо, користувач поміняв правий Ctrl і «a» місцями. У цьому випадку при натисканні на «a» + Pause, клавіша Pause повинна видати код, як ніби то була натиснута клавіша Ctrl. І навпаки видати звичайний код Pause при натисканні Ctrl + Pause.
Для вирішення цього завдання необхідно завести змінну, яка буде зберігати інформацію, про те, чи натиснута клавіша, що відповідає на даний момент за Ctrl. Ця змінна називається CtrlPressed. Якщо клавіша натиснута, то змінна дорівнює 1, інакше 0.
Алгоритм роботи з клавішею Pause
§ зустрінута послідовність записів Ctrl + Pause
· Якщо CtrlPressed = 1, то
послідовність пропускається в незміненому стані
· Якщо CtrlPressed = 0, то
послідовність, замінюється на послідовність, відповідну звичайної Pause
§ зустрінута послідовність записів Pause
· Якщо CtrlPressed = 1, то
послідовність, замінюється на послідовність, відповідну Ctrl + Pause
· Якщо CtrlPressed = 0, то
послідовність пропускається в незміненому стані
Клавіша PrintScreen
Оскільки PrintScreen видає різні записи, в залежності від того, чи натиснута клавіша Alt. Клавіша PrintScreen, на відміну від Pause може бути замінена на іншу клавішу. І вона завжди видає по одному запису при натисканні та тпусканіі.
Як і у випадку з Pause вводиться мінлива AltPressed, яка дорівнює 1, якщо натиснута клавіша, що відповідає за Alt.
Зробимо уніфікацію. При зустрічі запису, відповідної PrintScreen або Alt + PrintScreen будемо замінювати її на запис, відповідну PrintScreen.
Тепер необхідно перевірити, чи є PrintScreen в списку замін, і якщо потрібно, замінити його на іншу клавішу або взагалі видалити з буфера (якщо клавіша відключена).
§ Якщо PrintScreen був замінений на іншу клавішу, то
ніякі дії над ним не виробляються
§ Якщо PrintScreen не був замінений, то
· Якщо AltPressed = 1, то
запис замінюється на запис, відповідну Alt + PrintScreen
· Якщо AltPressed = 1, то
запис замінюється на запис, відповідну Alt + PrintScreen
2.5 Установка драйвера в системі
Для установки драйвера необхідно викликати функції драйвера в певний момент завантаження системи. Це необхідно для того, щоб драйвер зайняв потрібне місце в стеку драйверів. Операційна система Windows здійснює завантаження драйверів в порядку, прописаному в системному реєстрі.
Кожен пристрій має свій розділ в реєстрі. Всі ці розділи знаходяться в HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControleSet \ Control \ Class. Клавіатурі відповідає розділ {4 D 36 E 96 B - E 325-11 CE - BFC 1-08002 BE 10318}. У кожного пристрою в його розділі є ключі UpperFilters і LowerFilters. Це ключі типу MultiString. Вони містять імена верхніх і нижніх драйверів-фільтрів даного пристрою. Драйвери-фільтри завантажуються в систему в тому порядку, в якому вони записані в цих ключах.
Для реєстрації разрабативавемого драйвера як фільтру необхідно помістити його ім'я в перший в ключі UpperFilters.
Для реєстрації нового драйвера необхідно створити розділ з ім'ям цього драйвера в системному реєстрі за адресою HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services. Цей розділ повинен містити наступні ключі.
§ Type типу подвійне слово
Визначає тип модуля. Для драйверів режиму ядра значення завжди дорівнює одиниці.
§ Start типу подвійне слово
Визначає спосіб завантаження драйвера. Може приймати одне з наступних значень:
· SERVICE _ BOOT _ START (0) - під час початкового завантаження ОС. Дане значення застосовується, коли драйвер використовується завантажувачем системи;
· SERVICE _ SYSTEM _ START (1) - після початкового завантаження ОС. Застосовується для драйверів, які самостійно здійснюють пошук обладнання, але не використовуються завантажувачем системи (нумератори).
· SERVICE _ AUTO _ START (2) - автоматичне завантаження з допомогою диспетчера управління сервісами (Service Control Manager). Застосовується для драйверів, що не підтримують Plug and Play.
· SERVICE _ DEMAND _ START (3) - завантаження «на вимогу» або диспетчера Plug and Play при виявленні пристрою, або диспетчера управління сервісами при надходженні від користувача команди на завантаження.
· SERVICE _ DISABLED (4) - драйвер не завантажується.
§ ErrorControl типу подвійне слово
Визначає рівень контролю помилок. Може приймати одне з наступних значень:
· SERVICE_ERROR_IGNORE (0). У разі збою при завантаженні драйвера ігнорувати його і продовжити роботу.
· SERVICE_ERROR_NORMAL (1). У разі збою при завантаженні драйвера продовжити роботу, але видати при цьому відповідне попередження.
· SERVICE_ERROR_SEVERE (2). У разі збою при завантаженні драйвера перемкнутися на останню конфігурацію, при якій робота системи відбувалася без помилок.
· SERVICE_ERROR_CRITICAL (3). Аналогічно (2), але в разі повторного збою видати «синій екран».
§ DisplayName типу рядок ASCII
Назва драйвера або пристрою в тому вигляді, в якому воно буде відображатися для користувача.
§ ImagePath типу рядок Unicode
Повний шлях до файлу з драйвером на диску. Зазвичай це поле встановлюється в значення% windir% \ ‌‌ system32 \ ‌‌ Drivers \ ‌‍‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ D riverName.sys, де% windir% - папка, в яку встановлена ​​Windows, а Dr iverName - ім'я файлу.

3. Технологічний розділ
3.1 Вибір мови програмування і засобів програмування
Даний проект складається з трьох програм:
§ Драйвер-фільтр
§ Програма для установки драйвера
§ Програма для управління драйвером
Кожна з програм, здійснює спілкування з операційною системою на різному рівні. Відповідно необхідний різний підхід до цих завдань і спеціальний підбір засобів розробки.
Драйвер-фільтр
Від розроблюваного драйвера-фільтра потрібно висока швидкість роботи та надійність. При написанні такого завдання здійснюється безліч маніпуляцій з пам'яттю, операцій з покажчиками, перетворень типів. Програмісту важливо уявляти структуру скомпільованого продукту, щоб правильно уявити собі логіку його роботи. Серед мов програмування, що задовольняють цим вимогам, відомі С і асемблер. Для написання драйвера перевагу було віддано мови C. Вибір зроблений, грунтуючись на наступних причинах:
§ Існує спеціальний компілятор C, що поставляється разом з пакетом DDK, призначений спеціально для компіляції драйверів. Він містить безліч макроозначень і бібліотек, що дозволяють зробити процес написання драйвера більш легким. Microsoft рекомендує його як основну середовище для розробки драйверів для Windows. Компілятор містить спеціальні функції, що дозволяють зменшити розмір вихідного коду. Спеціального компілятора асемблера Microsoft не випускає.
§ Програми на асемблері працюють, звичайно, швидше, ніж програми на C. Але різниця в швидкості між цими мовами не дуже велика. Зате продуктивність праці при використанні C набагато вище, ніж при використанні асемблера.
Програма для установки драйвера
Програма для установки являє собою консольне пропозицію. На цей додаток не накладається особливих вимог щодо швидкості і за розміром. Тому і була вибрана середовище C + + Builder. Вона дозволяє легко створювати консольні пропозиції. Програми, написані в цьому середовищі, займають мало місця, і мають компактний текст.
При написанні програми також була використана технологія структурного програмування, хоча для таких маленьких проектів використовувати її невигідно. Буде тільки падіння швидкодії.
Програма для управління драйвером
Програма для управління драйвером представляє собою віконне додаток. Написана вона була в середовищі C + + Builder. Оскільки додаток призначений для користувача., То воно повинно мати красивий і зрозумілий інтерфейс. Дане середовище містить безліч стандартних візуальних компонент. Дозволяють здійснити поставлену задачу. Для програми швидкість і обсяг не є критичним параметром. Тому вибір C + + Builder можна вважати оптимальним.
У додатку використовується технологія об'єктно-орієнтованого програмування. Без її використання організація віконного інтерфейсу виглядала б дуже заплутаною.
3.2 Структури даних проекту
Інформація про натиснення і опускання клавіш
Скенкоди натиснутих або відпущених клавіш зберігаються в системному буфері. Доступ до цього буферу можна отримати, якщо прочитати дані за адресою, що зберігається в IRP пакеті. Адреса зберігається в полі AssociatedIrp. SystemBuffer. Буфер представляє собою масив структур типу KEYBOARD_INPUT_DATA. Вона складається з наступних полів:
§ UnitId типу USHORT. У ньому зберігається номер пристрою, на якому натиснули або відпустили клавішу.
§ MakeCode типу USHORT. У цьому полі зберігається скенкод натиснутою або відпущеної клавіші. Скенкод, переданий в цьому полі, не визначає клавішу однозначно. Для повної ідентифікації клавіші необхідно значення поля Flags.
§ Flags типу USHORT. Це поле несе додаткову інформацію про клавіші, а так само визначає, натиснули клавішу або відпустили. Якщо нульовий біт дорівнює 0, то значить клавіша натиснута, якщо ж він дорівнює 1, то вона відпущена. Біти 1 і 2 використовуються для ідентифікації клавіші.
§ Reserved типу USHORT. Поля є зарезервованим.
§ ExtraInformation типу ULONG. Це поле містить додаткову інформацію про пристрій.
Всі клавіші, окрім клавіші Pause, виробляють одну запис при натисканні та одну при відпусканні.
§ Клавіша Pause виробляє 4 записи, якщо вона була натиснута без Ctrl:
· Скан код дорівнює 29, прапори рівні 4
· Скан код дорівнює 69, прапори рівні 0
· Скан код дорівнює 29, прапори рівні 5
· Скан код дорівнює 69, прапори рівні 1
Якщо клавіша Pause була натиснута разом з Ctrl, то вона видає 2 записи:
· Скан код дорівнює 70, прапори дорівнюють 2
· Скан код дорівнює 70, прапори дорівнюють 3
§ Біт 2 дорівнює 0, а біт 1 дорівнює 1 у полі Flags у наступних клавіш: Insert, Delete, PageUp, PageDown, Home, End, PrintScreen, права Ctrl, правий Alt, Enter на додатковій клавіатурі, зворотний слеш на додатковому, стрілки, клавіші Windows, клавіша спливаючого меню.
§ У всіх інших клавіш біти 1 і 2 поля Flags рівні 0.
Клавіша PrintScreen - це єдина клавіша, яка змінює видається скенкод в залежності від того, чи натиснута інша. PrintScreen змінює скенкод в залежності від Alt.
Разом з Alt PrintScreen видає:
§ Скан код дорівнює 84, прапори рівні 0 (при натисканні)
§ Скан код дорівнює 84, прапори рівні 1 (при відпусканні)
Без Alt PrintScreen видає:
§ Скан код дорівнює 55, прапори рівні 2 (при натисканні)
§ Скан код дорівнює 55, прапори рівні 3 (при відпуску)
Структура списку замін
Список замін замін - це масив структур ChangeStruct. Вона складається з наступних полів:
§ f1 типу UCHAR. Поле містить додаткову, що ідентифікує заміняють клавіші.
§ Scan1 типу UCHAR. Поле містить скенкод замінної клавіші
§ f2 типу UCHAR. Поле містить інформацію про клавіші, на яку замінюють.
§ Scan2 типу UCHAR. Поле містить скенкод клавіші, на яку замінюють.
Фактично поля f1 і f2 містять 1 і 2 біт поля Flags структури KEYBOARD_INPUT_DATA. Вони допомагають ідентифікувати клавішу, яка замінюється, і на яку відбувається заміна.
Додаткова інформація
При створенні FDO виділяється пам'ять під структуру DEVICE_EXTENSION, в ця структура складається всього з одного поля. Це поле TopOfStack типу PDEVICE_OBJECT. Воно містить покажчик на FDO, розташоване нижче в стеку клавіатури, і використовується для передачі IRP пакетів нижче по стеку. Адреса цієї структури знаходиться в полі D eviceExtension нашого FDO.
3.3 Інтерфейс керуючого програми
Інтерфейс керуючого програми складається з двох вікон. Перше вікно є модель клавіатури, вона є головним у програмі. Друге вікно призначено для виведення інформації і називається інформаційним.

При натисканні на цікаву кнопку на головному вікні вона вдавлюється, і червоним кольором підсвічується кнопка, на яку замінюється вибрана кнопка. При цьому з'являється інформаційне вікно, що містить наступні параметри:
§ Назва обраної кнопки
§ Назва кнопки, на яку відбувається заміна
§ Стан кнопки (включена або вимкнена)
§


Якщо необхідно перевизначити кнопку, то потрібно клацнути по цій кнопці. В інформаційному вікні з'явиться інформація про активізованою кнопці. Далі необхідно натиснути на кнопку «Замінити», вона розташована в інформаційному вікні. І потім клацнути по кнопці, на яку необхідно зробити заміну.
Після того як бажана конфігурація визначена, потрібно натиснути кнопку «Встановити». Після цього інформація буде надіслана драйверу, і зміни набудуть чинності. Якщо необхідно дізнатися, які заміни виробляє драйвер на даний момент, то потрібно клацнути по кнопці «Прийняти».
Для швидкого відновлення стандартних настройок клавіатури передбачена кнопка «За замовчуванням». Вона завантажує стандартну конфігурацію. Щоб вона набула чинності, необхідно натиснути на кнопку «Встановити».
3.4 Тестування драйвера-фільтра клавіатури
Драйвер був протестований з використанням стандартної тестуючої утиліти DriverVerifier пакету DDK. З його допомогою були проведені наступні тести:
§ Операції з пулами пам'яті
§ Коректність рівнів IRQL, на яких виконується код драйвера
§ Виявлення взаімоблокіровок
§ Брак ресурсів
§ Нетипові запити до драйвера
Всі тести пройшли успішно. Пам'ять в системі розподілялася правильно, помилок з нею не виникало. На брак ресурсів драйвер реагував коректно. Нетипові запити до драйвера не оброблялися ім.
Для налагодження драйвера використовувалася програма DebugView. За допомогою цієї програми будь-який драйвер може виводити на екран налагоджувальну інформацію. При налагодженні ця програма дозволила відстежити процес перевизначення клавіш.
Драйвер використовували троє осіб протягом місяця, і помилок за цей період ними виявлено не було.

Висновок
У даній роботі розглянуто питання, пов'язане з розробкою драйверів пристроїв у системі Windows, і реалізований драйвер-фільтр клавіатури.
Розроблюваний драйвер дозволяє
§ перевизначати значення будь-яких клавіш клавіатури
§ відключати клавіші клавіатури
Драйвер-фільтр відповідає всім сучасним вимогам, що накладаються Windows на драйвери.
Драйвер був протестований з допомогою тестуючих утиліт Microsoft і успішно витримав всі тести. Тестування показало коректну роботу.

Список літератури
1. Кузьмін І. Драйвери рівня ядра системи Windows XP / / Програміст, - М.: ТОВ «Вікфілд». - № 11, 2003
2. Солдатов В.П. Програмування драйверів Windows. Вид. 2-е, перероб. і доп. М.: ТОВ «Біном-Пресс», 2004 р.
3. MSDN Library, Copyright 1987-2004 Microsoft Corporation
4. Форум і публікації проекту «Перші кроки» - www.firststeps.ru.
Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Курсова
95.9кб. | скачати


Схожі роботи:
Основи роботи в операційній системі Windows 2
Робота з гарячими клавішами в ОС Windows Призначення гарячих клавіш в ОС WINDOWS -функції
Драйвер клавіатури реалізує функції музичного синтезатора на клавіатурі для Windows NT 5
Мережевий друк в операційній системі FreeBSD
Безпека в мережевій операційній системі FreeBSD
Складання сценаріїв в операційній системі LINUX
Реалізація мережі в операційній системі Linux
Розсилання пошти в мережевій операційній системі FreeBSD
Бізнес план розробки навчального курсу по операційній системі OS 2 Warp Connect 4
© Усі права захищені
написати до нас