Уроки Iczelion'а

       

Каркас VxD


Теперь, когда вы знаете о сегментах в LE-файлах, мы можем перейти к исходнику. Вы сможете заметить, что макросы очень часто применяются в VxD-программировании, так как они того стоят, позволяя упростить программисту работу и, иногда, сделать исходник более портабельным. Если это вам интересно, вы можете прочитать определения этих макросов в pазличных заголовочных файлах, таких как vmm.inc.

Вот исходник каркас VxD:

.386p include vmm.inc

DECLARE_VIRTUAL_DEVICE FIRSTVXD,1,0, FIRSTVXD_Control, UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

Begin_control_dispatch FIRSTVXD End_control_dispatch FIRSTVXD

end

Hа первый взгляд, исходник не похож на ассемблерный код. Это происходит из-за использования макросов. Давайте проанализируем этот исходный код и вы вскоре поймете его.

.386p

Указывает ассемблеру, что мы хотим использовать набор инструкций 60386, включая привилегированные инструкции. Вы также можете использовать .486р или .586p.

include vmm.inc

Вы должны включать vmm.inc в каждый исходник VxD, так как он содержит определения макросов, которые вы будете использовать. Вы можете подключить другие файлы, если они вам потребуются.

DECLARE_VIRTUAL_DEVICE FIRSTVXD,1,0, FIRSTVXD_Control, UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

Как было сказано раньше, VMM получает всю необходимую информацию о том, что ему необходимо знать о VxD из DDB. Это структура, которая содержит жизненно важную информацию о VxD, такую как имя VxD, ID устройства, входные адреса VxD сервисов (если они есть) и так далее. Вы можете найти эту структуру в vmm.inc. Она определена как VxD_Desc_Block. Вы экспортеруете эту структуру в .DEF-файле. В этой структуре 22 параметра, но, как правило, вы будете использовать только некоторые из них. Поэтому vmm.inc содержит макрос, которое инициализировать и заполнять параметры структуры за вас. Это макрос называется DECLARE_VIRTUAL_DEVICE. Он имеет следующий формат:

Declare_Virtual_Device Name, MajorVer, MinorVer, CtrlProc, DeviceID, \ InitOrder, V86Proc, PMProc, RefData


Вы можете заметить, что имена в VxD-исходнике не зависят от регистра. Вы можете использовать символы верхнего или нижнего регистра или их комбинацию. Давайте проанализируем каждый из членов Declare_virtual_device.


  • Имя - имя VxD. Максимальная длина - 8 символов. Оно должно быть введено в верхнем регистре. Имя должно быть уникальным среди всех VxD системы. Макрос также используем имя, чтобы создать имя DDB, прибавляя '_DDB' к имени VxD. Поэтому, если вы используете 'FIRSTVXD' в качестве имени своего драйвера, макрос Declare_Virtual_Device объявит имя DDB как FIRSTVXD_DDB. Помните, что вы также должны экспортировать DDB в .DEF-файле.
  • MajorVerand, MinorVer - основная и дополнительная версии VxD.
  • CtrlProc - имя контрольной процедуры устройства вашего VxD. Контрольная процедура устройства (device control рrocedure) - это функция, которая получает и обрабатывает контрольные сообщения. Вы можете считать эту процедуру аналогом процедуры окна. Так как мы используем макрос Begin_Control_Disрatch, чтобы создать нашу контрольную процедру устройства, нам следует использовать стандартное имя вида VxDName_Control. Begin_Control_Disрatch прибавляет '_Control', к имени, которое ему передается (и мы обычно передаем ему имя VxD), поэтому нам следует указывать имя нашего VxD в параметре CtrlProc с прибавленным к нему '_Control'.
  • DeviceID - 16-битное уникальное значение VxD. ID потребуется вам только тогда, если ваш VxD должен обрабатывать одну из следующих ситуаций.


  • Ваш VxD экспортирует VxD сервисы для использования другими VxD. Так как интерфейс int20 использует device ID, чтобы обнаруживать и находить VxD, наличие уникального идентификатора является обязательным.
  • Ваш VxD оповещает о своем существовании приложения реального режима во время инициализации через int 2Fh, функция 1607h.
  • Какие-то программы реального режима (TSR) будут использовать прерывание 2Fh, функцию 1605h, чтобы загрузить ваш VxD.


  • Если VxD не нуждается в уникальном device ID, вы можете указать в этом поле UNDEFINED_DEVICE_ID. Если вам требуется уникальное ID, вам нужно попросить его у Microsoft'а.
  • InitOrderInitialization - порядок загрузки VxD. У каждого VxD есть свой загрузочный номер. Hапример:


  • VMM_INIT_ORDER EQU 000000000H DEBUG_INIT_ORDER EQU 000000000H DEBUGCMD_INIT_ORDER EQU 000000000H



    PERF_INIT_ORDER EQU 000900000H APM_INIT_ORDER EQU 001000000H

  • Вы можете видеть, что VMM, DEBUG и DEBUGCMD - это первые VxD, которые загружаются, за ними следуют PERF и APM. VxD с наименьшим значением загружается первым. Если вашему VxD требуются сервисы других VxD во время инициализации, вам следует указать значение данного поля большее, чем у VxD, сервисы которого вам потребуются. Если вашему VxD порядок загрузки не важен, укажите UNDEFINED_INIT_ORDER.
  • V86Proc и PMProc - VxD может экспортировать API, для использования программами V86 и защищенного режима. V86Proc и PMProc задают адреса этих API. Помните, что VxD существует в основном для управления виртуальными машинами, в том числе и теми, что отличаются от системной виртуальной машины. Вот почему VxD зачастую предоставляют поддержку API для DOS-программ и программ защищенного режима. Если вы не экспортирует эти API, вы можете пропустить эти поля.
  • RefDataReference - данные, используемые Input Output Supervisor (IOS). Единственным случаем, когда вам нужно будет использовать это поле - это когда вы программирует драйвер, работающий с IOS.


  • Затем идет Begin_Control_Dispatch.

    Begin_control_dispatch FIRSTVXD End_control_dispatch FIRSTVXD

    Этот макрос и его заключительная часть определяет контрольную процедуру устройства, которая будет вызываться при поступлении контрольных сообщений. Вы должны указать первую половину имени этой процедуры, в нашем примере мы используем 'FIRSTVXD'. Макрос прибавит _Control к имени, которое вы укажите. Это имя должно совпадать с тем, что вы указали в параметре CtrlPoc, передаваемый макросу Declare_virtual_device. Процедура всегда находится в "запертом" сегменте (VxD_LOCKED_CODE_SEG). Вышеприведенная процедура не делает ничего. Вы должны указать, какие контрольные сообщения должны обрабатываться вашим VxD и функции, которые будут их обрабатывать. Для этих целей используется макрос Control_Dispatch.

    Control_Dispatchmessage, function

    Hапример, если ваш VxD обрабатывает только сообщение Device_Init, контрольная процедура устройства будет выглядеть так:

    Begin_Control_Dispatch FIRSTVXD Control_Dispatch Device_Init, OnDeviceInit End_Control_DispatchFIRSTVXD

    OnDeviceInit - это имя функции, которая будет обрабатывать сообщение Device_Init. Вы можете назвать эту функцию как угодно. Вы заканчиваете VxD заключительной директивой.

    Подводя pезюме, можно сказать, что VxD, как минимум, должно иметь DDB и контрольную процедуру устройства. Вы объявляете DDB с помощью макроса Declare_Virtual_Device и контрольную процедуру устройства с помощью макроса Begin_Control_Disрatch. Вы должны экспортировать DDB, указав его имя в директиве EXPORT в .DEF-файле.


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