Главная ]
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

 

<< Назад ] Содержание ] Далее >> ]

Дизайн: Piton Alien
Rambler's Top100 Рейтинг@Mail.ru
Сайт создан в системе uCoz