Страница 9 из 13 Общая схема драйвера VxDМинимальный виртуальный драйвер должен содержать секцию резидентного кода, в которой расположены блок описателя устройства, диспетчер системных сообщений и обработчики сервисных функций.Обработчик системных сообщений анализирует код сообщения, переданный в EAX, выделяет интересующие его сообщения, обрабатывает их и возвращает сброшенный флаг CF в случае успеха, и установленный — в случае неудачи. Для всех необрабатываемых сообщений должен возвращаться сброшенный флаг CF.Обработчики сервисных функций вызываются по таблице, так что каждой функции соответствует собственный обработчик. Способ передачи параметров и возврата результатов определяется разработчиком.При необходимости драйвер может содержать обработчики запросов V86 и PM API. Для доступа к данным виртуальных машин DOS, указатели на которые могут передаваться в регистрах при запросе, достаточно преобразовать их в линейные 32-разрядные адреса, ибо первый мегабайт адресного пространства текущей виртуальной машины непосредственно «виден» из VxD. Для доступа к данным приложений Win16 потребуется выполнить отображение адресов посредством функции VMM _SelectorMapFlat. Программирование VxD Средства разработки, включаемые файлы и библиотекиМинимально необходимый набор включаемых файлов и библиотек содержится в Windows 95 DDK (подкаталоги Inc32 и Lib). Обычно требуется включение хотя бы файлов BASEDEF.H и VMM.H.Файлы VXDWRAPS.H, CONFIGMG.H и некоторые другие оформлены в стиле обычного языка C, поэтому при включении их в файлы типа CPP директивы #include необходимо помещать внутрь квалификатора extern "C": extern "C" { #include <vxdwraps.h> } Файлы из DDK можно включать и в тексты модулей обычных приложений, определив перед этим символическое имя Not_VxD. При этом определяются только полезные константы и типы, а определение специфических для VxD конструкций отключается. Структуры, обычно используемые в VxDVxD_Desc_Block - блок описателя устройстваОписывает структуру DDB. Заполняется статически, чтобы к моменту загрузки драйвера все поля имели нужные значения. ULONG DDB_Next; USHORT DDB_SDK_Version; USHORT DDB_Req_Device_Number; UCHAR DDB_Dev_Major_Version; UCHAR DDB_Dev_Minor_Version; USHORT DDB_Flags; UCHAR DDB_Name [8]; ULONG DDB_Init_Order; ULONG DDB_Control_Proc; ULONG DDB_V86_API_Proc; ULONG DDB_PM_API_Proc; ULONG DDB_V86_API_CSIP; ULONG DDB_PM_API_CSIP; ULONG DDB_Reference_Data; ULONG DDB_Service_Table_Ptr; ULONG DDB_Service_Table_Size; ULONG DDB_Win32_Service_Table; ULONG DDB_Prev; ULONG DDB_Size; ULONG DDB_Reserved1; ULONG DDB_Reserved2; ULONG DDB_Reserved3; - DDB_Next — поле для адреса следующего DDB в списке VMM. Инициализируется нулем.
- DDB_SDK_Version — версия DDK, с которой построен драйвер. Инициализируется константой DDK_VERSION.
- DDB_Req_Device_Number — идентификатор устройства. При отсутствии назначенного идентификатора задается нулевое значение.
- DDB_Dev_Major_Version — старшая часть номера версии драйвера.
- DDB_Dev_Minor_Version — младшая часть номера версии драйвера.
- DDB_Flags — для служебных флагов VMM. Инициализируется нулем.
- DDB_Name — имя устройства, дополненное пробелами до восьми символов.
- DDB_Init_Order — позиция драйвера в списке загрузки. Если порядок загрузки не важен, используется константа UNDEFINED_INIT_ORDER (нуль).
- DDB_Control_Proc — адрес функции диспетчера системных сообщений.
- DDB_V86_API_Proc — адрес функции диспетчера V86 API.
- DDB_PM_API_Proc — адрес функции диспетчера PM API.
- DDB_V86_API_CSIP — служебное поле, инициализируется нулем.
- DDB_PM_API_CSIP — служебное поле, инициализируется нулем.
- DDB_Reference_Data — служебное поле, инициализируется нулем.
- DDB_Service_Table_Ptr — указатель таблицы адресов процедур—обработчиков сервисных функций.
- DDB_Service_Table_Size — количество сервисных функций, реализованных в драйвере.
- DDB_Win32_Service_Table — служебный указатель таблицы функций Win32, инициализируется нулем.
- DDB_Prev — поле для адреса предыдущего DDB в списке VMM, инициализируется константой 'Prev'.
- DDB_Size — размер структуры описателя.
- DDB_Reserved1 — служебное поле. Инициализируется константой 'Rsv1'.
- DDB_Reserved2 — служебное поле. Инициализируется константой 'Rsv2'.
- DDB_Reserved3 — служебное поле. Инициализируется константой 'Rsv3'.
Client_Reg_Struc - структура пакета регистров клиентаОписывает состояние регистров процессора в вызвавшей виртуальной машине/приложении (клиенте). ULONG Client_EDI; ULONG Client_ESI; ULONG Client_EBP; ULONG Client_res0; ULONG Client_EBX; ULONG Client_EDX; ULONG Client_ECX; ULONG Client_EAX; ULONG Client_Error; ULONG Client_EIP; USHORT Client_CS; USHORT Client_res1; ULONG Client_EFlags; ULONG Client_ESP; USHORT Client_SS; USHORT Client_res2; USHORT Client_ES; USHORT Client_res3; USHORT Client_DS; USHORT Client_res4; USHORT Client_FS; USHORT Client_res5; USHORT Client_GS; USHORT Client_res6; ULONG Client_Alt_EIP; USHORT Client_Alt_CS; USHORT Client_res7; ULONG Client_Alt_EFlags; ULONG Client_Alt_ESP; USHORT Client_Alt_SS; USHORT Client_res8; USHORT Client_Alt_ES; USHORT Client_res9; USHORT Client_Alt_DS; USHORT Client_res10; USHORT Client_Alt_FS; USHORT Client_res11; USHORT Client_Alt_GS; USHORT Client_res12; Поля с именами Client_xxx содержат значения соответствующих регистров на момент обращения виртуальной машины или приложения к системной функции. В поле Client_Error может быть занесен код ошибки.Для структуры введен синоним типа (typedef) с именем CRS. В файле VMM.H определены также вспомогательные структуры Client_Word_Reg_Struc и Client_Byte_Reg_Struc и объединение всех трех структур CLIENT_STRUCT. DIOCParams - параметры запроса DeviceIoControlDWORD Internal1; DWORD VMHandle; DWORD Internal2; DWORD dwIoControlCode; DWORD lpvInBuffer; DWORD cbInBuffer; DWORD lpvOutBuffer; DWORD cbOutBuffer; DWORD lpcbBytesReturned; DWORD lpoOverlapped; DWORD hDevice; DWORD tagProcess; - VMHandle — идентификатор виртуальной машины, сделавшей запрос.
- dwIoControlCode — код функции. Константы для определенных в системе кодов функций имеют префикс DIOC_, остальные функции определяются разработчиком.
GETVERSION (0) | Открывание и опрос интерфейса. Если драйвер не поддерживает Win32 API, он должен вернуть в EAX ненулевое значение. В противном случае в EAX возвращается нуль, а если задан буфер результата, то в него заносится номер версии драйвера. | CLOSEHANDLE (-1) | Закрывание интерфейса. Драйвер должен прервать обработку всех асинхронных запросов по этому устройству и освободить относящиеся к нему ресурсы. | - lpvInBuffer — указатель исходного буфера.
- cbInBuffer — размер исходного буфера в байтах.
- lpvOutBuffer — указатель буфера результата.
- cbOutBuffer — размер буфера результата в байтах.
- lpcbBytesReturned — поле для объема в байтах данных, занесенных драйвером в буфер результата.
- lpoOverlapped — указатель структуры типа OVERLAPPED (описатель адреса внутри файла и/или данных для асинхронной операции).
- hDevice — идентификатор устройства.
- tagProcess — идентификатор запроса. Вместе с полем hDevice образует уникальный внутри системы идентификатор запроса, по которому запрос может быть найден и аварийно прерван при получении запроса CLOSEHANDLE.
|