Драйверы устройств в системе Windows

       

Драйвер виртуального устройства


     Файл vxd2.asm (листинги  6 и 7)  представляет собой исходный  код драйвера фиктивного устройства. Следует отметить, что для того,  чтобы построить этот драйвер, необходимо иметь комплект драйверов  устройств (Device Driver Kit  - DDK) системы  Windows фирмы Microsoft,  т.к. код написан для 32-битового  ассемблера, предусмотренного в  комплекте DDK (MASM5).  Результирующий   модуль  может   быть  скомпонован    только DDK-компоновщиком  LINK386  и  утилитой  послекомпоновочной  обработки ADDHDR.  Кроме  того,  данный  исходный  код ссылается на определенное количество включаемых файлов (include files), которые входят в  состав только комплекта DDK.

     Как  было  указано,  типичный  драйвер  VxD содержит обязательные включаемые файлы, а кроме того он начинается с вызова макроса  Declare _Virtual_Device, который создает блок данных, описывающий  виртуальный драйвер  для  ядра  системы  Windows.  Этот блок данных, фактически, -единственное  обозначение,   экспортируемое  из   драйвера  VxD.   Все остальные точки  входа являются  производными от  данных, содержащихся внутри. Кроме всего прочего,  данный макрос описывает имя  устройства, порядок  его инициализации и его точки входа.  Виртуальный драйвер VxD может обслуживать запросы приложений как в реальном,  так и в защищенном  режимах.  Точки  входа  для такого обслуживания также описываются данным макросом.

_____________________________________________________________________

PAGE ,132

title VxD2B.ASM - Пример драйвера устройства #2b

;EM VxD2B - Пример драйвера устройства #2b

;

;  Copyright 1992, Cherry Hill Software

;  All rights reserved

;

;  SUMMARY (Резюме)

;      Данный   драйвер   имитирует   прерываемое   устройство.   Порт

;      управления (выход) имеет следующее назначение битов:



;

;      Бит 0 -  Начать (Start)  ввод-вывод. Запись  нуля в данный  бит

;               начинает  пересылку  ввода-вывода.  Пересылка   длится

;               около  1/10  секунды.  Запись  единицы в этот  бит  не




;               дает результата.

;

;      Бит 1 -  Устройству  посылается EOI. Запись  нуля в данный  бит

;               приводит к  посылке признака "Конец прерывания"  (End-

;               of-interrupt - EOI) устройству и удаляет любой  запрос

;               на отложенное прерывание. Запись единицы в этот бит не

;               дает результата.

;      Все остальные биты: Всегда записываются единицы для  дальнейшей

;      совместимости.

;

;      При чтении порта следующие значения возвращаются:

;

;      Бит 0 - Первоначально     присваивается    значение   1,    бит

;              сбрасывается, когда бит 1 выходного порта сбрасывается,

;              и   устанавливается,  когда   добавляется   запрос   на

;              прерывание.  Данный  бит  равен  нулю, когда устройство

;              передает данные и устанавливается  в 1, чтобы  указать,

;              когда передача завершена.

;

;      Бит 1 - Первоначально    присваивается     значение    1,   бит

;              сбрасывается, когда добавляется запрос на прерывание  и

;              устанавливается,  когда  устройство  удаляет  запрос на

;              прерывание.  Значение   данного   бита,  равное   нулю,

;              указывает на отложенное прерывание, бит устанавливается

;              в 1, если нет отложенного прерывания.

;

;      Все  остальные  биты: возвращаемое  значение  игнорируется  для

;      дальнейшей совместимости.

;

; WARNINGS (Предупреждения)

;

;

.386p

.xlist

include vmm.inc

include debug.inc

include v86mmgr.inc

include vpicd.inc

include ..\include\bogus.inc

.list

VM_Not_Executable equ VM_Not_Executeable ; acckk;

subttl  VxD Declaration/Definition

VxD2B_Init_Order equ VNETBIOS_Init_Order+100 ; Данная операция

                        выполняется после запуска виртуальной сети

VxD2B_Device_ID equ Bogus_Device_ID

Declare_Virtual_Device VXD2, 1, 0, Vxd2B_Control, VxD2B_Device_ID, \

               VxD2B_Init_Order



VxD_DATA_SEG

;

; Структура дескриптора виртуального прерывания

;

;  Данная   структура  передается   VPIDC_Virtualize_IRQ.  В    данной

;  структуре  описывается  уровень  прерывания,  процедура  прерывания

;  аппаратных  средств,  и  процедура,  которую  вызывает VPICD, когда

;  прерывание  диспетчируется  в  виртуальной  машине  VM  и  когда VM

;  возвращается из прерывания.

;

IRQD VPICD_IRQ_Descriptor

hIRQ         dd   -1     ; обработчик IRQ

hOwner       dd   -1     ; обработчик, владеющий VM

hTimeout     dd    0     ; обработчик к обратному вызову по тайм-ауту

bFakeData    dd  01111111b ; имитировать данные порта ввода-вывода

VxD_DATA_ENDS

subttl Dispatch VxD Control

VxD_LOCKED_CODE_SEG

BeginProc CheckOwner, NO_LOG

     cmp ebx,hOwner

     jne short col

     ret   ; выйти, если вызывается владелец

col:

     cmp hOwner,-1

     jne short co2  ; пропустить, если вызов не владельца

     mov hOwner,ebx ;установить владельца

     ret

co2:

     mov al,-1

     ret

EndProc CheckOwner

BeginProc TimeoutProc

     mov hTimeout,0 ;почистить обработчик

     cmp edx,hOwner ; все еще тот же владелец?

     jne short tol  ; пропустить, если нет

     test   bFakeData,FAKE_STAT_BUSY  ;отложенный ввод-вывод?

     jnz short tol  ; пропустить, если нет

     cmp hOwner,-1  ; имеется ли владелец?

     je  short tol  ; пропустить, если нет

     mov eax,hIRQ

     mov ebx,hOwner

     VxDcall VPICD_Set_Int_Request ;добавить прерывание

     mov al,bFakeData

     and al,NOT (FAKE_STAT_IRQ) ; указывает также в порте состояния

     or  al,FAKE_STAT_BUSY ; указывает, что больше не занято

     mov bFakeData,al

tol:

     ret

End Proc TimeoutProc

;IP Port_IO_Callback - выполняет доступ к FAKE_PORT

;

; ENTRY (вход)

;    EAX - выходное значение (для выходных операторов)

;    EBX - обработчик к текущему VM

;    ECX - тип операции ввода-вывода

;    DS,ES - FLAT

;

; EXIT (выход)



;    EAX - входное значение (для входных операторов)

;

; WARNINGS (предупреждения)

;

; NOTES (примечания)

;      Следует отметить, что мы даже не смотрим регистровый фрейм

;      клиента.

;

;      Мы просто читаем и увеличиваем.

;

; CALLS (вызовы)

BeginProc Port_IO_Callback, NO_LOG

     Dispatch_Byte_IO Fall_through,Port_Output_Callback

Port_Input_Callback:

     call   CheckOwner

     jc  short ioexit

     mov al,bFakeData

     or  bFakeData,FAKE_STAT_ERROR  ; почистить отложенную ошибку

ioexit:

     ret

Port_Output_Callback:

     call   CheckOwner

     jc  short ioexit    ;игнорировать ввод-вывод, если не владелец

     test   al,FAKE_CTL_START

     jnz short,poc1  ;пропустить, если не начинается ввод-вывод

     test  bFakeData,FAKE_START_BUSY

     jz  short,poc1  ;пропустить, если уже занято

     test  bFakeData,FAKE_START_IRQ

     jz  short,poc1  ;пропустить, если отложенное IRQ

     push  eax

     push  edx

     and bFakeData,NOT (FAKE_STAT_ERROR)  ;  предположить ошибку

     mov eax,100     ; обратный вызов в 1/10 секунды

     mov edx,hOwner  ; передать владельца обратному вызову

     mov esi,OFFSET32 TimeoutProc

     VMMcall Set_VM_Time_Out

     pop edx

     pop eax

     or  esi,esi

     jz  short,poc1  ;пропустить, если ошибка

     and bFakeData,NOT (FAKE_STAT_BUSY)  ;  указать на занятость

     or bFakeData,FAKE_STAT_ERROR  ; в противном случае почистить

                                     индикацию ошибки

     mov hTimeout,esi  ;сохранить обработчик тайм-аута

poc1:

     test   al,FAKE_CTL_EOI

     jnz short poc2  ; пропустить, если не посылается EOI

     test   bFakeData,FAKE_STAT_IRQ ;прерывание отложено?

     jnz short poc2  ; пропустить, если нет

     or   bFakeData,FAKE_STAT_IRQ ;показать, что прерывание уже не-

                                   отложеное

     push eax

     mov eax,hIRQ

     VxDcall VPICD_Clear_Int_Request

     pop eax

poc2:

     ret

EndProc Port_IO_Callback



; ECX == 0 if unmasking (enabling), ECX != 0 if masking (disabling).

BeginProc VxD2_Mask_Change_Proc

     call CheckOwner

     jc  short mcp9  ; игнорировать, если нет владельца

     jcxz   mcp9     ; пропустить, если не маскировано (включено)

;

; Владелец освобождает управление. Разрешается другой VM войти в

; систему.

;

     mov hOwner,-1   ; почистить владельца

mcp9:

     ret

EndProc VxD2_Mask_Change_Proc

; Вызывается, когда выполняется программа ISR

BeginProc VxD2_VInt_Proc

     mov eax,High_Pri_Device_Boost

     VMMCall Adjust_Exec_Priority  ;повышенный приоритет для начальной

                                    обработки

     ret

EndProc VxD2_VInt_Proc

;  вызывается при возврате из программы ISR (IRETs)

BeginProc VxD2_IRET_Proc

     mov eax,-(High_Pri_Device_Boost)

     VMMCall Adjust_Exec_Priority  ;восстановить приоритет

     ret

EndProc VxD2_IRET_Proc

ifdef DEBUG

BeginProc VxD2B_Debug_Query

     Trace_Out  "VxD2 has no debug command support."

     clc

     ret

End Proc VxD2B_Debug_Query

endif

;

; VxD2B_Control

;

CtlDisp macro x

 Control_Dispatch x, VxD2B_&x

 endm

Begin_Control_Dispatch VxD2B

     CtlDisp Device_Init

ifdef DEBUG

     CtlDisp Debug_Query

endif

End_Control_Dispatch VxD2B

VxD_LOCKED_CODE_ENDS

VxD_CODE_SEG

VxD_CODE_ENDS

subttl  VxD Initialization

VxD_ICODE_SEG

; EP VxD2B_Device_Init - Некритическая инициализация устройства

;

;  ENTRY (вход)

;         EBP - фрейм клиента

;         EBX - системный обработчик VM

;         DS,ES - FLAT

;

;  EXIT  (выход)

;  SUCCESS (успешный)

;  Carry clear ("нет переноса")

;  FAILURE  (аварийный)

;  Carry set  ("есть перенос")

;

;

;  WARNINGS (предупреждения)

;

;  NOTES (примечания)

;

;  CALLS (вызовы)

;

BeginProc VxD2B_Device_Init

        Debug_Out "VxD2B_Device_Init"

        mov edi,OFFSET32 IRQD



        VxDcall VPICD_Virtualize_IRQ  ; виртуализировать прерывание

        jc  short vdi1   ;  выход, если ошибка

        mov hIRQ,eax     ; сохранить обработчик

        mov edx,FAKE_PORT

        mov esi,OFFSET32 Port_IO_Callback

        VMMCall Install_IO_Handler

        VMMCall Enable_Global_Trapping   ;

        clc  ; нет ошибки

vdi1:

        ret

EndProc VxD2B_Device_Init

VxD_ICODE_ENDS

VxD_REAL_INIT_SEG

VxD2B_Real_Init LABEL FAR ; вызывается перед тем, как система Windows

                           входит в защищенный режим

        mov ax,Device_Load_OK  ;позволяет VxD загрузиться

        xor bx,bx  ; нет исключенных (Exclude) страниц EMM

        xor si,si  ; нет элементов экземпляров данных

                   ; передать edx немодифицированным

        ret

VxD_REAL_INIT_ENDS

        END VxD2B_Real_Init

_____________________________________________________________________

     Листинг 6. Программа vxd2.asm

_____________________________________________________________________

LIBRARY  VXD2

DESCRIPTION 'Enhanced Windows VXD2(B) Device  (Version 1.0)'

EXETYPE DEV386

SEGMENTS

          _LTEXT PRELOAD NONDISCARDABLE

          _LDATA PRELOAD NONDISCARDABLE

          _ITEXT CLASS 'ICODE' DISCARDABLE

          _IDATA CLASS 'ICODE' DISCARDABLE

          _TEXT  CLASS 'PCODE' NONDISCARDABLE

          _DATA  CLASS 'PCODE' NONDISCARDABLE

EXPORTS

       VXD2_DDB  @1

_____________________________________________________________________

     Листинг 7. Программа vxd2.def


Содержание раздела