на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Переопределение назначений клавиш на клавиатуре в операционной системе Windows
p align="left">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. Клавиатуре соответствует раздел {4D36E96B-E325-11CE-BFC1-08002BE10318}. У каждого устройства в его разделе есть ключи 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\DriverName.sys, где % windir% - папка, в которую установлена Windows, а DriverName - имя файла.

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 пакетов ниже по стеку. Адрес этой структуры находится в поле DeviceExtension нашего 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.

Страницы: 1, 2, 3



© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.