Каркас 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.
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
Затем идет 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-файле.