Защищенный режим процессоров Intel 80286/80386/80486© Александр Фролов, Григорий ФроловТом 4, М.: Диалог-МИФИ, 1993, 234 стр. 7.2. Драйверы, резидентные программы и WINDOWSВ этом разделе, как и в следующем, мы не будем ничего говорить о защищённом режиме работы процессора. Мы рассмотрим здесь некоторые особенности, которые необходимо учитывать при разработке резидентных программ и драйверов, работающих совместно с WINDOWS. Очень часто резидентные программы или драйверы перехватывают аппаратное прерывание клавиатуры и отслеживают коды нажимаемых клавиш, выполняя те или иные действия при нажатии заданных комбинаций. Например, драйвер "секретного" диска Norton DISKREET может при нажатии заданной комбинации клавиш блокировать доступ к "секретному" диску, экрану и клавиатуре. Так как WINDOWS в расширенном режиме использует собственную систему клавиатурного ввода/вывода, основанную на очередях сообщений, а также реализует концепцию виртуальных машин, нажатие активизирующих резидентную программу комбинаций клавиш в неподходящий момент может не привести к желаемому результату и даже стать причиной "зависания" системы. Есть два возможных решения этой проблемы. Во-первых, можно запретить запуск WINDOWS, если активна резидентная программа или драйвер, не способные работать совместно с WINDOWS. Во-вторых, на время работы WINDOWS можно запретить выполнение резидентной программой или драйвером специфических функций, несовместимых с WINDOWS (например, запретить активизацию резидентной программы при нажатии комбинации клавиш). Перед запуском WINDOWS и перед её завершением вызываются функции прерывания INT 2Fh 1605h и 1606h соответственно. Ваша резидентная программа или драйвер могут подготовить собственные обработчики для этих прерываний и отслеживать моменты запуска WINDOWS и завершения её работы. Функция 1605h вызывается при запуске WINDOWS: Регистры при вызове прерывания:
AX 1605h
ES:BX 0000h:0000h
DS:SI 0000h:0000h
CX 0000h
DX Флаги:
Бит 0 = 0, если выполняется инициализация WINDOWS в расширенном режиме;
Бит 0 = 1, если выполняется инициализация DOS-экстендера
"Microsoft 286 DOS extender" (используется в
стандартном режиме работы WINDOWS);
Биты 1-15 зарезервированы, их содержимое неопределено.
Регистры перед возвратом из прерывания: CX 0000h, если WINDOWS может продолжать инициализацию; CX <> 0, если запуск WINDOWS недопустим. Функция 1606h вызывается при завершении WINDOWS расширенном или стандартном режиме: Регистры при вызове прерывания:
AX 1606h
DX Флаги:
Бит 0 = 0, если выполняется завершение WINDOWS, работавшей в расширенном режиме;
Бит 0 = 1, если выполняется завершение DOS-экстендера
"Microsoft 286 DOS extender";
Биты 1-15 зарезервированы, их содержимое не определено.
Обработчик функции 1605h может выполнить необходимые действия, связанные с модификацией алгоритма работы резидентной программы или драйвера, а также при помощи соответствующей установки регистра CX может разрешить или запретить запуск WINDOWS. Обработчик функции 1606h получает управление при завершении работы WINDOWS и может восстановить прежний алгоритм работы критичной к WINDOWS резидентной программы или драйвера. Приведённая ниже резидентная программа перехватывает прерывание INT 2Fh и отслеживает фунции 1605h и 1606h, вызавая сообщение и ожидая нажатия на любую клавишу при запуске и завершении работы WINDOWS:
Листинг 22. Контроль запуска WINDOWS
Файл wintsr.asm
-----------------------------------------------------------
.MODEL tiny
.CODE
.STARTUP
jmp begin
old_int2Fh_off dw 0 ; Адрес старого обработчика
old_int2Fh_seg dw 0 ; прерывания 2Fh
; Сообщение, которое будет выдано на экран
; при запуске WINDOWS
msg_win db 'WINDOWS Started. Press any key...$'
msg_win_off dw offset msg_win
; Сообщение, которое будет выдано на экран
; при завершении WINDOWS
msg_win1 db 'WINDOWS Ended. Press any key...$'
msg_winend_off dw offset msg_win1
; Новый обработчик прерывания 2Fh нужен
; для проверки наличия программы в памяти
; при ее запуске для предохранения
; от повторного запуска
new_int2Fh proc far
cmp ax,0FF00h
jz installed
cmp ax,1605h
jz winstart
cmp ax,1606h
jz winend
jmp dword ptr cs:old_int2Fh_off
winstart: ; запуск WINDOWS
push ax
push bx
push cx
push dx
push ds
mov dx,cs:msg_win_off
mov ah,9
push cs
pop ds
int 21h
mov ax,0
int 16h
pop ds
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:old_int2Fh_off
winend: ; завершение WINDOWS
push ax
push bx
push cx
push dx
push ds
mov dx,cs:msg_winend_off
mov ah,9
push cs
pop ds
int 21h
mov ax,0
int 16h
pop ds
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:old_int2Fh_off
; Если код функции 0FF00h, то возвращаем
; в регистре AX значение 00FFh. Это признак
; того, что программа уже загружена в память
installed:
mov ax,00FFh
iret
new_int2Fh endp
;==============================
; Точка входа в программу
; В этом месте начинается выполнение программы
begin proc
; Проверяем, не загружена ли уже программа
; в память
mov ax,0FF00h
int 2Fh
cmp ax,00FFh
jne first_start
mov dx,offset msg_load1
mov ah,9
int 21h
.EXIT
; Первоначальный запуск программы
first_start:
; Запоминаем адрес старого обработчика прерывания 2Fh
mov ax,352Fh
int 21h
mov cs:old_int2Fh_off,bx
mov cs:old_int2Fh_seg,es
push cs
pop ds
; Выводим сообщение
mov dx,offset msg_load
mov ah,9
int 21h
mov dx,OFFSET new_int2Fh
mov ax,252Fh
int 21h
; Завершаем программу и оставляем резидентно
; в памяти часть программы, содержащую новые
; обработчики прерываний
mov dx,OFFSET begin
int 27h
begin endp
msg_load db 'Резидентная программа WINTSR загружена$'
msg_load1 db 'Резидентная программа WINTSR уже загружена$'
end
Следующая резидентная программа работает аналогично, но она запрещает запуск WINDOWS. Попробуйте, запустив предварительно программу NOWINTSR, запустить WINDOWS и посмотрите, что из этого получится.
Листинг 23. Запрет запуска WINDOWS
Файл nowintsr.asm
-----------------------------------------------------------
.MODEL tiny
.CODE
.STARTUP
jmp begin
old_int2Fh_off dw 0 ; Адрес старого обработчика
old_int2Fh_seg dw 0 ; прерывания 2Fh
; Сообщение, которое выдаётся при запуске WINDOWS
msg_win db 'NOWINTSR несовместима с WINDOWS. Нажмите любую клавишу...$'
msg_win_off dw offset msg_win
; Сообщение, которое выдаётся при завершении WINDOWS
msg_win1 db 10,13,'WINDOWS Ended. Press any key...$'
msg_winend_off dw offset msg_win1
; Новый обработчик прерывания 2Fh нужен
; для проверки наличия программы в памяти
; при ее запуске для предохранения
; от повторного запуска
new_int2Fh proc far
cmp ax,0FF00h
jz installed
cmp ax,1605h
jz winstart
cmp ax,1606h
jz winend
jmp dword ptr cs:old_int2Fh_off
winstart:
push ax
push bx
push cx
push dx
push ds
mov dx,cs:msg_win_off
mov ah,9
push cs
pop ds
int 21h
mov ax,0
int 16h
pop ds
pop dx
pop cx
pop bx
pop ax
mov cx,0ffh
jmp dword ptr cs:old_int2Fh_off
winend:
push ax
push bx
push cx
push dx
push ds
mov dx,cs:msg_winend_off
mov ah,9
push cs
pop ds
int 21h
mov ax,0
int 16h
pop ds
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:old_int2Fh_off
; Если код функции 0FF00h, то возвращаем
; в регистре AX значение 00FFh. Это признак
; того, что программа уже загружена в память
installed:
mov ax,00FFh
iret
new_int2Fh endp
;==============================
; Точка входа в программу
begin proc
; Проверяем, не загружена ли уже программа
; в память
mov ax,0FF00h
int 2Fh
cmp ax,00FFh
jne first_start
mov dx,offset msg_load1
mov ah,9
int 21h
.EXIT
; Первоначальный запуск программы
first_start:
; Запоминаем адрес старого обработчика прерывания 2Fh
mov ax,352Fh
int 21h
mov cs:old_int2Fh_off,bx
mov cs:old_int2Fh_seg,es
push cs
pop ds
; Выводим сообщение
mov dx,offset msg_load
mov ah,9
int 21h
mov dx,OFFSET new_int2Fh
mov ax,252Fh
int 21h
; Завершаем программу и оставляем резидентно
; в памяти часть программы, содержащую новые
; обработчики прерываний
mov dx,OFFSET begin
int 27h
begin endp
msg_load db 'Резидентная программа NOWINTSR загружена$'
msg_load1 db 'Резидентная программа NOWINTSR уже загружена$'
end
|

