| RSS



Меню

Bookmark and Share


Статистика
Ваш IP: 18.191.84.33
Вы используете: v





Сейчас на сайте:

Тех поддержка ->

Облако тэгов
ОС видио Tor Обратная сторона антенна 4.6 PHP Эксплоит Windows Server 2008 qip Virtual chroot kernel proc sysctl tune FreeBSD bridge Boot Disk Bluetooth GEO game directx Emulator Python Shell DDoS червь Conficker вирус троян Лаборатория Касперского пиратство apple iPhone ИТ-отрасль Щеголев Microsoft экономический кризис Twitter социальная сеть анонимность Лицензия Open Source ASP.NET MVC уязвимость MySQL база данных файлообмен закон франция пират Skype мобильный Deutsche Telekom Хакер киберпреступник Trend Micro кибератака Германия робот утечка данных персональные данные ноутбук интернет Китай цензура ядро Linux Торвальдс Windows Vista Acer Linux патент браузер Firefox Internet Explorer Opera Net Applications Safari Intel Linux Foundation Moblin Oracle патч банкомат кардер HSM IBM X-Force Cofee сша кибервойна Эстония Dell ИТ-специалист хакерские атаки Pirate Bay контроль кибербезопасность язык программирования The Pirate Bay Пиратская партия утечка информации приговор Mozilla Chrome безопасность Госдума СМИ Windows 8 Баллмер взлом Пентагон ботнет Украина Facebook Cisco cloud Windows XP нетбук торрент музыка биометрический nokia ФБР IP-адрес CIPAV Comcast sms RSA java Google CAPTCHA Symantec спам конфиденциальная информация инсайдер Perimetrix антивирус тест Anti-Malware Windows 7 операционная система Windows провайдер авторское право RapidShare UNIX свиной грипп шантаж дети EFF BluWiki копирайт экстремизм Panda Security cloud computing McAfee Cybercrime Response Unit Bottle Domains HTTPS ICANN студент шпионское ПО Норвегия школьник New York Times XSS YouTube Warner Music кибершпионаж КНДР Ubuntu свободное ПО AMD ATI касперский Россия РФ сервер хостинг фальшивый антивирус Comodo CA Wi-Fi D-Link суд пароль блог фишинг Одноклассники медведев контрафакт мошенник штраф Sony GPS по Gumblar JAVASCRIPT хакеры вредоносное ПО Yahoo ФАС компьютер Софт MPAA кибероружие PandaLabs Red Hat Минкомсвязи сбой ASUSTeK Computer мошенничество Доктор Веб ВКонтакте Cyber-Arc исходный код PCI DSS МВД фильтр порнография BREIN свобода слова Казахстан GEMA Autodesk сисадмин Gmail кредитная карта кибермошенник LiveJournal шифрование криптография Deep Purple банк нанотехнологии Wikipedia zero-day ColdFusion выборы кража данных DNS BIND Android BASIC атака Black Hat Mac OS X Click Forensics Clampi домен фсб Прокуратура Уголовное дело icq Barrelfish киберпреступность Sophos AT&T ошибка Electa Gamma Knife OpenBSD DARPA военные Сайт Visual Studio 2010 .NET Framework 4 Chrome OS электронная почта турция конференция спамер FTC полиция российская ОС Koobface Великобритания БЕЛОРУССИЯ грузия BSA Bittorrent облачные вычисления Azure Европа Dr.Web Билл Гейтс спецслужбы Cryzip Живой Журнал Royal Bank of Scotland смартфон Canonical Pwn2Own F-Secure Symbian Hotmail фильм

Главная » Статьи » Общие Статьи

Написание драйвера в подробностях №3
Вот и пришло время третьей статьи в цикле о написании драйверов режима ядра под Windows (и не последней - решено включить в цикл ещё одну, четвёртую, статью). Мы разобрали особенности архитектуры Windows NT, поговорили об особенностях драйвера, как понятия, и об его структуре и познакомились с некоторыми приёмами программирования в режиме ядра. А теперь мы, наконец, вплотную подошли к, собственно, написанию своего первого (или тридцать первого) драйвера. В данной статье мы это и осуществим. Мы напишем простейший legacy - драйвер ("драйвер в стиле NT"), скомпилируем и установим его. И в результате, в виндошном диспетчере устройств наконец - то появится "устройство", драйвер к которому будет написан тобой. Приступим к воплощению этой мечты в реальность! 

Пишем код драйвера

Процесс работы над нашим драйвером, мы начнем, естественно, с написания кода (писать будем, как я уже говорила, на сях). Весь код нашего драйвера (который мы назовём "Primer") будет находиться в двух файлах: Driver.h и main.cpp. Я буду по порядку объяснять куски кода, поэтому, если тебе захочется скомпилировать этот драйвер, достаточно будет просто скопировать их (куски кода) в один файл. Начнём с Driver.h.

#ifndef _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_ // эти строки запрещают повторный проход по тексту заголовочных 
#define _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_ //
(*.h) файлов, что особенно актуально для больших проектов 
//
и повышает скорость компиляции
#ifdef __cplusplus
extern "C"
{
#endif

#include "ntddk.h" //
если заменить эту строку на #include "wdm.h", то компиляция драйвера (с использованием Build из DDK)
//
пройдёт успешно, но WDM он всё равно не станет 

#ifdef __cplusplus
}
#endif

//
Далее - структура расширения устройства 

typedef struct _PRIMER_DEVICE_EXTENSION
{
PDEVICE_OBJECT fdo; //
указатель на FDO.
UNICODE_STRING ustrSymLinkName; //
L"\\DosDevices\\Primer" - имя символьной ссылки
} PRIMER_DEVICE_EXTENSION, *PPRIMER_DEVICE_EXTENSION;


//
С помощью этих, определённых нами, кодов IOCTL, в будущем можно будет обращаться к драйверу через DeviceIoControl

#define IOCTL_PRINT_DEBUG_MESS CTL_CODE(\
FILE_DEVICE_UNKNOWN, 0x701, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_CHANGE_IRQL CTL_CODE(\
FILE_DEVICE_UNKNOWN, 0x702, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_MAKE_SYSTEM_CRASH CTL_CODE(\
FILE_DEVICE_UNKNOWN, 0x703, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_TOUCH_PORT_378H CTL_CODE(\
FILE_DEVICE_UNKNOWN, 0x704, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_SEND_BYTE_TO_USER CTL_CODE(\
FILE_DEVICE_UNKNOWN, 0x705, METHOD_BUFFERED, FILE_ANY_ACCESS)

#endif


Подробное описание макроса CTL_CODE можно найти в заголовочном DDK файле Winioctl.h. А мы перейдём к main.cpp. В прошлой статье я уже говорила о главных процедурах драйвера. В нашем драйвере это будут DriverEntry - главная точка входа драйвера, UnloadRoutine - процедура выгрузки драйвера и DeviceControlRoutine - обработчик DeviceIoControl IRP пакетов. Но перед тем, как разобраться с реализацией этих процедур, необходимо сделать некоторые предварительные объявления, с которых и начнётся наш файл main.cpp.

#include "Driver.h"

//
Предварительные объявления функций:
NTSTATUS DeviceControlRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp);

VOID UnloadRoutine(IN PDRIVER_OBJECT DriverObject);

NTSTATUS
ReadWrite_IRPhandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp);

NTSTATUS
Create_File_IRPprocessing(IN PDEVICE_OBJECT fdo, IN PIRP Irp);

NTSTATUS
Close_HandleIRPprocessing(IN PDEVICE_OBJECT fdo, IN PIRP Irp);

KSPIN_LOCK SpinLock;
#pragma code_seg("INIT") //
положим начало секции INIT

Итак, мы подключили заголовочный файл Driver.h, сделали несколько предварительных объявлений важных функций, объявили глобальную переменную и определили начало секции INIT. А теперь - реализация функции загрузки драйвера.

extern "C"
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) 

{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT fdo; //
указатель на объект драйвера
UNICODE_STRING devName; //
указатель на раздел реестра
//
Так как функция - NTSTATUS, то и возвращает она - STATUS_XXX.

//
Все строки, обрамлённые if`ами DBG - будут исполняться только в отладочной версии драйвера.
#if DBG
DbgPrint("=Primer= DriverEntry.");
DbgPrint("=Primer= RegistryPath = %ws.", RegistryPath->Buffer);
#endif

//
Экспортируем точки входа в драйвер. Поскольку наш драйвер - legacy, процедуру AddDevice мы не экспортируем.
DriverObject->DriverUnload = UnloadRoutine;
DriverObject->MajorFunction[IRP_MJ_CREATE]= Create_File_IRPprocessing;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Close_HandleIRPprocessing;
DriverObject->MajorFunction[IRP_MJ_READ] = ReadWrite_IRPhandler;
DriverObject->MajorFunction[IRP_MJ_WRITE] = ReadWrite_IRPhandler;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DeviceControlRoutine;

//
Начнём создавать символьную ссылку
RtlInitUnicodeString(&devName, L"\\Device\\PRIMER"); // данная процедура тоже должна бы располагаться в AddDevice.

//
Создаём свой FDO и получаем указатель на него в fdo. Размер структуры PRIMER_DEVICE_EXTENSION передаётся для // того, чтобы при создании FDO выделить под неё память.
status = IoCreateDevice(DriverObject,
sizeof(PRIMER_DEVICE_EXTENSION),
&devName, FILE_DEVICE_UNKNOWN,0,FALSE, &fdo);
if(!NT_SUCCESS(status)) return status; //
данная процедура также должна бы располагаться в AddDevice.

//
Получаем указатель на область, предназначенную для PRIMER_DEVICE_EXTENSION. 
PPRIMER_DEVICE_EXTENSION dx = (PPRIMER_DEVICE_EXTENSION)fdo->DeviceExtension;

dx->fdo = fdo; //
сохраняем обратный указатель

#if DBG
DbgPrint("=PRIMER= FDO %X, DevExt=%X.",fdo,dx);
#endif

//
Продолжаем работу по созданию символьной ссылки (примечания такие же, что и в предыдущей части работы).

UNICODE_STRING symLinkName; 

#define SYM_LINK_NAME L"\\DosDevices\\Primer" //
именно ТАКОЙ код предназначен для того, чтобы символьная ссылка // работала и в Windows 9x, и в NT.
RtlInitUnicodeString(&symLinkName, SYM_LINK_NAME);
dx->ustrSymLinkName = symLinkName;

//
И, наконец, создаем собственно символьную ссылку.
status = IoCreateSymbolicLink(&symLinkName, &devName);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(fdo);
return status;


//
Инициализируем объект спин - блокировки, который мы будем использовать для обрушения системы во время // выполнения кода обработчика IOCTL - запросов.
KeInitializeSpinLock(&SpinLock);

#if DBG
DbgPrint("=PRIMER= DriverEntry successfully completed.");
#endif
return status;
}
#pragma code_seg() //
конец секции INIT

Процедура CompleteIrp, первый аргумент которой - указатель на объект нашего FDO, предназначена для завершения обработки IRP пакетов с кодом завершения status. Эту функцию не нужно нигде регистрировать, так как она предназначена для внутренних потребностей драйвера. 

NTSTATUS CompleteIrp(PIRP Irp, NTSTATUS status, ULONG info)
{
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info; //
если этот параметр не равен нулю, то он обычно содержит количество байт, // переданных клиенту.
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}


Функция ReadWrite_IRPhandler - это рабочая процедура обработки read/write запросов. Если подробнее - она выполняет обработку запросов Диспетчера ввода/вывода, сформированных им в виде IRP пакетов (с кодами IRP_MJ_READ/WRITE) в результате обращений к драйверу из пользовательских приложений с вызовами read/write (или же из кода режима ядра с вызовами ZwRead/WriteFile). В нашем случае функция ReadWrite_IRPhandler ничего особенного не делает, поэтому она реализована в виде заглушки. Определила же я эту процедуру для демонстрации её использования (что позднее ты сможешь применить в разработке своих, уже намного более продвинутых драйверов).

NTSTATUS ReadWrite_IRPhandler(IN PDEVICE_OBJECT fdo, // указатель на объект нашего FDO
IN PIRP Irp) //
указатель на структуру принятого от Диспетчера ввода/вывода IRP
{
ULONG BytesTxd = 0;
NTSTATUS status = STATUS_SUCCESS;

#if DBG
DbgPrint("-Primer- in ReadWrite_IRPhandler.");
#endif
return CompleteIrp(Irp,status,BytesTxd); //
CompleteIrp завершает обработку IRP. BytesTxd (число переданных или // полученных байт) - равно нулю. 
}


Теперь - две связанных функции: Create_File_IRPprocessing и Close_File_IRPprocessing, предназначенные для обработки запросов открытия/закрытия драйвера (CreateFile/CloseHandle, ZwCreateFile/ZwClose). Create_File_IRPprocessing обрабатывает IRP_MJ_CREATE, а Close_File_IRPprocessing - IRP_MJ_CLOSE.

NTSTATUS Create_File_IRPprocessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp) // параметры такие же, что и у ReadWrite_IRPhandler
{
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);

#if DBG
DbgPrint("-Primer- Create File is %ws",
&(IrpStack->FileObject->FileName.Buffer));
#endif

return CompleteIrp(Irp,STATUS_SUCCESS,0);
}

NTSTATUS Close_HandleIRPprocessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp) //
параметры те же, что и у ReadWrite_IRPhandler и // Create_File_IRPprocessing 
{
#if DBG
DbgPrint("-Primer- In Close handler."); 
#endif
return CompleteIrp(Irp,STATUS_SUCCESS,0);
}


Теперь - огромная рабочая процедура DeviceControlRoutine, предназначенная для обработки IOCTL - запросов (точнее - для обработки IRP_MJ_DEVICE_CONTROL - запросов, возникающих в результате обращения пользовательских приложений к драйверу с вызовом DeviceIoControl). В нашем драйвере эта функция реализует обработку нескольких IOCTL запросов. Все необходимые комментарии я буду давать в коде (определения возможно незнакомых тебе типов данных (UCHAR, PUCHAR etc) можно посмотреть в Windef.h). 

NTSTATUS DeviceControlRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp) // параметры - смотри в предыдущих трёх функциях.
{
NTSTATUS status = STATUS_SUCCESS;
ULONG BytesTxd =0; //
Число переданных/полученных байт
PIO_STACK_LOCATION IrpStack=IoGetCurrentIrpStackLocation(Irp);

//
Получаем указатель на расширение устройства
PPRIMER_DEVICE_EXTENSION dx = (PPRIMER_DEVICE_EXTENSION)fdo->DeviceExtension;

ULONG ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
ULONG method = ControlCode & 0x03;

//
Получаем текущее значение уровня IRQL – приоритета,
//
на котором выполняется поток:
KIRQL irql, 
currentIrql = KeGetCurrentIrql();

#if DBG
DbgPrint("-Primer- In DeviceControlRoutine (fdo= %X)\n",fdo);
DbgPrint("-Primer- DeviceIoControl: IOCTL %x.", ControlCode);
if(currentIrql==PASSIVE_LEVEL)
DbgPrint("-Primer- PASSIVE_LEVEL (val=%d)",currentIrql);
#endif

KeAcquireSpinLock(&SpinLock,&irql);

//
Диспетчеризация по IOCTL кодам:
switch(ControlCode) {

#ifndef SMALL_VERSION
case IOCTL_PRINT_DEBUG_MESS: //
выводит мессагу в дебаговую консоль

#if DBG
DbgPrint("-Primer- IOCTL_PRINT_DEBUG_MESS.");
#endif
break;
}
case IOCTL_CHANGE_IRQL: //
играемся с уровнями IRQL 
{
#if DBG
DbgPrint("-Primer- IOCTL_CHANGE_IRQL.");
KIRQL dl = DISPATCH_LEVEL, 
oldIrql,
newIrql=25; 

KeRaiseIrql(newIrql,&oldIrql);
newIrql=KeGetCurrentIrql(); 

DbgPrint("-Primer- DISPATCH_LEVEL value =%d",dl);
DbgPrint("-Primer- IRQLs are old=%d new=%d", oldIrql,newIrql);
KeLowerIrql(oldIrql); 
#endif
break;
}
#endif 


case IOCTL_MAKE_SYSTEM_CRASH: //
"роняем" систему (падает только NT)
{
int errDetected=0;
char x = (char)0xFF;

#if DBG :
DbgPrint("-Primer- IOCTL_MAKE_SYSTEM_CRASH.");
#endif
__try { 
x = *(char*)0x0L;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{ //
Перехват исключения не срабатывает

errDetected=1;
};
#if DBG
DbgPrint("-Primer- Value of x is %X.",x);
if(errDetected)
DbgPrint("-Primer- Except detected in Primer driver.");
#endif
break;
}

#ifndef SMALL_VERSION
case IOCTL_TOUCH_PORT_378H: //
пробуем поработать с аппаратными ресурсами системы

unsigned short ECRegister = 0x378+0x402;
#if DBG
DbgPrint("-Primer- IOCTL_TOUCH_PORT_378H.");
#endif
_asm {
mov dx,ECRegister ;
xor al,al ;
out dx,al ; Установить EPP mode 000
mov al,095h ; Биты 7:5 = 100
out dx,al ; Установить EPP mode 100
}
break;
}

case IOCTL_SEND_BYTE_TO_USER: //
шлём байтик юзерскому приложению 

//
Размер данных, поступивших от пользователя:
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputLength = 
IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
#if DBG
DbgPrint("-Primer- Buffer outlength %d",OutputLength);
#endif

if(OutputLength<1)
{
status = STATUS_INVALID_PARAMETER;
break;
}
UCHAR *buff; // 
if(method==METHOD_BUFFERED)
{
buff = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
#if DBG
DbgPrint("-Primer- Method : BUFFERED.");
#endif
}
else
if (method==METHOD_NEITHER)
{
buff=(unsigned char*)Irp->UserBuffer;
#if DBG
DbgPrint("-Primer- Method : NEITHER.");
#endif
}
else 
{
#if DBG
DbgPrint("-Primer- Method : unsupported.");
#endif
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
#if DBG
DbgPrint("-Primer- Buffer address is %08X",buff);
#endif
*buff=33; 
BytesTxd = 1; 
break;
}
#endif 

default: status = STATUS_INVALID_DEVICE_REQUEST;
}

KeReleaseSpinLock(&SpinLock,irql);

#if DBG
DbgPrint("-Primer- DeviceIoControl: %d bytes written.", (int)BytesTxd);
#endif

return CompleteIrp(Irp,status,BytesTxd); 
}


Небольшая Эрих Мария Ремарка: почему в обработке IOCTL_MAKE_SYSTEM_CRASH не происходит перехвата исключения? Да потому, что вызов KeAcquireSpinLock меняет уровень IRQL на 2, а ведь данный обработчик IOCTL был вызван драйвером с уровня IRQL == 0 (PASSIVE_LEVEL)! Таким образом, конструкция try/exception, корректно работающая на нулевом IRQL уровне, на IRQL == 2 исключение не перехватывает, и, следовательно, не обрабатывает. Так что во всём виноваты спин - блокировки! Также стоит обратить пристальное внимание на процедуру обработки IOCTL_TOUCH_PORT_378H, так как в момент нашего обращения к порту может случиться так, что с ним уже будут работать другие драйвера или устройства. 

Ну а теперь, наконец, процедура UnloadRoutine, выполняющая выгрузку драйвера, высвобождающая занятые драйвером объекты, и принимающая единственный параметр - указатель на объект драйвера. 

#pragma code_seg("PAGE") // начинает секцию PAGE

VOID UnloadRoutine(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextDevObj;
int i;

#if DBG
DbgPrint("-Primer- In Unload Routine.");
#endif
//
Нижеприведённые операции в полноценном WDM драйвере следут поместить в обработчик IRP_MJ_PNP - запросов (с // субкодом IRP_MN_REMOVE_DEVICE, естественно).

pNextDevObj = pDriverObject->DeviceObject;

for(i=0; pNextDevObj!=NULL; i++)
{
PPRIMER_DEVICE_EXTENSION dx = 
(PPRIMER_DEVICE_EXTENSION)pNextDevObj->DeviceExtension;
//
Удаляем символьную ссылку и уничтожаем FDO:
UNICODE_STRING *pLinkName = & (dx->ustrSymLinkName);
//
сохраняем указатель:
pNextDevObj = pNextDevObj->NextDevice;

#if DBG
DbgPrint("-Primer- Deleted device (%d) : pointer to FDO = %X.",
i,dx->fdo);
DbgPrint("-Primer- Deleted symlink = %ws.", pLinkName->Buffer);
#endif

IoDeleteSymbolicLink(pLinkName);
IoDeleteDevice(dx->fdo);
}
}
#pragma code_seg() //
завершаем секцию PAGE

Вот и всё! (правда, несложно?) Драйвер готов! Точнее, готов только его исходный код: его ещё нужно откомпилировать, установить в систему и запустить. Вот об этом и поговорим.

Компиляция драйвера

Скомпилировать драйвер можно двумя способами: в Visual Studio и в DDK. Первый способ хорош тем, что в Visual Studio можно набрать (при этом, как обычно, будет производиться автоматическая проверка синтаксиса кода) и скомпилировать там же код. Но для того, что бы происходила проверка и корректная компиляция кода необходимо, как я уже говорила, исправить солюшены (.sln - файлы проекта), что достаточно лениво (тем не менее, такой способ мы рассмотрим в следующей статье цикла). Способ же с использованием DDK более прост и надёжен, поэтому на данный момент разберём второй вариант. Для компиляции и сборки драйвера в DDK (с использованием Build) необходимо создать два файла: Makefile и source. Первый управляет работой Build и в нашем случае имеет следующий стандартный вид :

# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
!INCLUDE $ (NTMAKEENV) \ makefile.def
#


Файл source содержит в себе индивидуальные настройки процесса компиляции и сборки драйвера. В нашем случае он будет выглядит так:

TARGETNAME=PRIMER // имя компилируемого драйвера
TARGETTYPE=DRIVER // тип компилируемого проекта
#DRIVERTYPE=WDM // При компиляции WDM драйвера эту строку нужно раскомментировать, а в заголовочном файле Driver.h вместо // ntddk.h подключить wdm.h
TARGETPATH=obj // директория, в которой будут размещены промежуточные файлы
SOURCES=main.cpp // главный файл сорцов

Теперь все необходимые для компиляции файлы (в нашем случае - main.cpp, Makefile,sources) осталось только поместить в один каталог и запустить компиляцию отладочной (checked) версии драйвера с помощью утилиты Build. Всё, компиляция и сборка драйвера завершены. Перейдём к инсталляции.

Инсталляция драйвера

Инсталлировать драйвер можно несколькими способами: с внесением записей в реестр, с использованием программы Monitor из пакета Driver Studio, с использованием INF - файла и с использованием SCM - менеджера (программно) (к слову сказать, не всегда есть такое богатство выбора - WDM - драйвера, например, рекомендуется инсталлить только с помощью INF - файла и Мастера установки оборудования). Последние два способа мы рассмотрим в следующей статье цикла, а первые два - сейчас.

Наш драйвер без проблем инсталлируется и работает как под Windows 9x, так и под NT (секрет этого заключается в Windows 9x драйвере ntkern.vxd, который помогает NT - драйверам "почувствовать себя, как дома"; но, естественно, возможности его не безграничны), но процесс записи в реестр (и записываемые значения) немного отличаются. Разберём оба варианта.

Открывай нотпэд, набивай в нём следующие строки и сохраняй документ под любым именем в виде .reg файла:

# содержимое файла реестра, необходимого для инсталляции драйвера, под Windows 9x:

REGEDIT4
[HKEY_LOCAL_MACHINE\System\ CurrentControlSet\Services\Primer]
"ErrorControl"=dword:00000001
"Type" =dword:00000001
"Start" =dword:00000002
"ImagePath" ="\\SystemRoot\\System32\\Drivers\Primer.sys"

Название параметров говорят сами за себя, так что, думаю, дополнительных пояснений не требуется. Для инсталляции драйвера в Windows NT необходимо практически то же самое. Топаешь по тому же пути, который был указан в вышеприведённом .reg файле (не важно, вручную, или же создавая .reg - файл), создаёшь тот же раздел и те же параметры со значениями 1,1 и 2 соответственно. Понятно, что перед внесением изменений в реестр готовый драйвер нужно положить в директорию, указанную в параметре ImagePath.

Программа Monitor из пакета DriverStudio позволяет загрузить, запустить, остановить и удалить драйвер и имеет интуитивно понятный графический фейс, работе с которым, я думаю, обучать не нужно. Перед запуском драйвера из Monitor`а можно предварительно запустить прогу DebugView - тогда все отладочные сообщения драйвера будут выдаваться в её окно.

Вот и всё. Ребуться и наслаждайся результатом! (Проверить корректность установки и интеграции в ОС нового драйвера можно с помощью DeviceTree, например).

Заключение

Наконец настал тот торжественный момент, когда ты можешь с достаточным основанием назвать себя разработчиком драйверов! Но это только начало пути: написание драйверов для видеокарт, например - намного более сложное занятие. Но охватить всё не может ни один, даже самый большой и подробный цикл статей. Главное - начать, а уж потом, если это дело тебе приглянётся, будет намного легче (или, временами, трудней - но и в триста раз интересней). Тем не менее, этот цикл ещё не закончен: в следующей статье я помогу тебе исправить солюшены проекта визуальной студии для корректной компиляции в ней драйвера, заинсталлить драйвер в систему с использованием INF - файла, а также покажу использование возможностей SCM - менеджера в программе, предназначенной для тестирования только что созданного нами драйвера (хочется же потестить творение рук своих !). А пока что изучай, изменяй и тестируй любыми своими способами наш свежесозданный драйвер в "стиле NT"! Да не облысеют твои пятки!

Категория: Общие Статьи | Добавил: aka_kludge (12.09.2008)
Просмотров: 2301 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
    Главная      
...
На службе : дней

16:04
Обновить


Пользователи
aka_kludge
qwerty
LeadyTOR
aka_Atlantis
AdHErENt
mAss
Sissutr
hiss
DrBio
tHick

Поиск


Copyright tHR - TeAM 2024 г. admin: aka_kludge (ICQ:334449009) Moderator's: LeadyTOR, ... Яндекс.Метрика