Сервис, предоставляемый виртуальным драйвером
Приложения Windows, работающие в системной виртуальной машине, а также программы MS-DOS, запущенные в среде виртуальной машины MS-DOS, могут вызывать виртуальные драйверы для выполнения тех или иных операций.
Однако, прежде всего, необходимо получить адрес точки входа для вызова драйвера. Способ получения этого адреса одинаков как для приложений Windows, работающих в защищенном режиме, так и для программ MS-DOS, работающих на виртуальных машинах MS-DOS в виртуальном режиме процессора V86.
Приведем пример функции, возвращающей адрес точки входа для виртуального драйвера, идентификатор которого задан через параметр vxd_id:
VXDAPI vxdGetDeviceAPI(unsigned short vxd_id) { unsigned axreg, dxreg; asm push di asm push es asm mov ax, 0x1684 asm mov bx, vxd_id asm xor di, di asm mov es, di asm int 0x2f asm mov ax, di asm mov dx, es asm pop es asm pop di asm mov axreg, ax asm mov dxreg, dx return((VXDAPI)MAKELP(dxreg, axreg)); }
Как видно из примера, получение адреса точки входа сводится к вызову функции 1684h прерывания INT2Fh. Искомый адрес возвращается в регистрах ES:DI. Если драйвер с указанным идентификатором отсутствует в системе, возвращается нулевой адрес.
Учтите, что если адрес точки входа определяется из приложения Windows, когда процессор находится в защищенном режиме, адрес возвращается в формате <селектор:смещение>. Если же этот адрес определяется в виртуальной машине MS-DOS, он будет получен в формате <сегмент:смещение>.
После того как адрес точки входа определен, вызов виртуального драйвера выполняется следующим образом:
asm mov dx, sel asm mov cx, off asm mov si, bsel asm mov di, boff asm mov ax, vxdapiRegisterWnd (*vxdApi)();
Перед вызовом необходимо загрузить все нужные для выполнения данной функции регистры. Номер выполняемой функции следует указать в регистре AX.
Что происходит в виртуальном драйвере, когда его вызывают подобным образом?
Если вы помните, в седьмом и восьмом параметрах макрокоманды определения драйвера Declare_Virtual_Device указываются адреса процедур, соответственно, для виртуального и защищенного режима, которые вызываются при обращении к драйверу. Именно эти процедуры и будут вызваны в нашем случае. Они могут проверить содержимое регистра AX на момент вызова виртуального драйвера и в соответствии с ним сделать, например, переход по таблице адресов функций, определенных внутри виртуального драйвера.
Однако не следует думать, что соответствующая функция просто проверяет текущее содержимое регистра AX. Дело в том, что в мультизадачной среде одновременно работают несколько виртуальных машин, каждая из которых имеет свой виртуальный процессор и свой набор регистров. При вызове виртуального драйвера из виртуальной машины регистры процессора не соответствуют состоянию виртуальной машины на момент вызова. Тем не менее, виртуальный драйвер может легко получить доступ к области памяти, в которую автоматически переписывается содержимое всех регистров при переключении виртуальных машин (а также при вызове виртуального драйвера).
Расскажем об этом подробнее.