📄 hooks.asm
字号:
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;
;OVERVIEW
;
; This module contains the interrupt hooks for
;int 8 (timer interrupt), int 10 (video BIOS), int13 (disk BIOS)
;int 19 (reboot vector), int 15 (keyboard intercept),int 9 (keyboard)
;and int 28 (idle interrupt)
; Also, it contains the main entry point for write behind.
; See hooksini.asm for the code which inserts these hooks into
;the interrupt chains.
;
; Int 8 is hooked so write behind can occur. Every timer tick
;the handler determines if it is appropriate to attempt write behind, and
;if so call the write behind entry point. Note that previous int 8
;handlers are allowed to process before write behind since the EOI must
;be done quickly.
;
; Int 10 is hooked to prevent write behind from occuring during
;video BIOS interaction. Write behind could mess with video timing and
;cause video problems.
;
; Int 13 is hooked to keep external int 13 callers from
;breaking cache consistency,and to keep those cases from allowing a
;re-entrancy to occur on the int 13 vector.
;
; Int 19 is hooked to catch those programs which use int 19
;to soft-reboot the machine. This is done so the cache can be commited
;to disk if necessary.
;
; Int 15 is hooked so that on those machines which support the
;keyboard intercept we can catch the ctrl+alt+delete sequence. Since
;this does not work on all machines, we also hook int 9. However, this
;hook is not redunant because some programs use the int 15 intercept to
;reboot the machine.
;
; Int 9 is hooked to catch ctrl+alt+delete and allow the cache
;to commit dirty buffers before reboot occures. Also, we prevent
;write behind during int 9 processing since this is a timing dependant
;interrupt on some machines.
;
; Int 28 is hooked to allow the cache to write behind during idle
;cycles at an accelerated pace (compared to int 8).
;
; Note that int 16 is no longer hooked for write behind acceleration
;because the hook encounters problems with windows (esp idle detection)
;the hook was redundant for the most part since most software uses int 28
;for idle. Those software that do not do int 28s will have a slower
;write-behind since write behind will only occur on timer ticks.
;
;
; Write_behind_cache is the main entry point for the write behind.
;The code determines if it is OK to access the disk, and if so will
;commit one cache element to disk. Also, if the reboot hooks have been
;triggered, it will commit all uncommited data and reboot the machine.
public commit_all_when_ok
public invalidate_when_ok
public reboot_when_ok
public write_behind_cache
public safety_flush
public int08hook ;vector for timer interrupt
public int09hook ;vector for keyboard interrupt
public int10hook ;vector for video bios
public int13hook ;vector for disk bios
public int19hook ;vector for reboot
public int15hook ;vector for reboot keys
;public int16hook ;vector for keyboard bios
public int28hook ;vector for software idle
public int21hook
public int25hook
public int26hook
;
; data from rdata.asm
;
extrn indosaddr :dword
extrn in_win :byte ; in windows flag
extrn in_08 :byte ;re-entry count for int 08
extrn in_09 :byte ;re-entry count for int 09
extrn in_10 :byte ;re-entry flag(?) for int 10
extrn in_13 :byte ;re-entry flag(?) for int 13
extrn in_16 :byte ;re-entry flag(?) for int 16
extrn in_bambi :byte ;re-entry count for bambi
extrn int08chain :dword
extrn int09chain :dword
extrn int10chain :dword
extrn int13chain :dword
extrn int15chain :dword
extrn int16chain :dword
extrn int19chain :dword
extrn int28chain :dword
extrn int21chain :dword
extrn int2fchain :dword
extrn int25chain :dword
extrn int26chain :dword
extrn processor_type :byte
extrn number_of_dirty_elements:word
;
; routines from queueman.asm
;
extrn commit_lru_dirty_element:near
extrn commit_all_dirty:near
;
; routines from reboot.asm
;
extrn rebootsystem :near
;
; routines from queueman.asm
;
extrn flush_queue :near
;
; routines from popup.asm
;
extrn shut_down_pop_up :near
;
; data from bambi.asm
;
extrn num_valid_buffers :word
extrn next_bad_entry_ptr :word ; first entry will be 0
extrn num_bad_blocks :word
extrn accessing_swap_file_ptr :dword
extrn commitflag :byte
; align to word for stack save variables
zseg segment word public 'CODE'
assume cs:zseg
assume ds:nothing
include bambi.inc
;
; local data
;
save_stack_ss dw ? ;tempory stack pointer saves
save_stack_sp dw ?
public save_stack_ss
public save_stack_sp
num_ticks_to_timeout db 18 ;1 sec, WARNING must be non-zero!
commit_all_when_ok db 0 ;non zero means commit all dirty
invalidate_when_ok db 0 ;non zero means invalidate after commit
reboot_when_ok db 0 ;non zero means reboot after commit
num_ticks_to_int28 db 0
ignore_intenter_checks db 0 ;somebody else is doing bad things,
;lets hope they know what they're doing
;=============================================================================
;== Scan Code
;=============================================================================
SC_DEL equ 0053h ; Delete
SC_INS equ 0052h ; Insert
;=============================================================================
;== Keyboard Control Byte Bit Positions (ROM Data Area)
;=============================================================================
KP_ALT equ 00001000b
KP_CTRL equ 00000100b
KP_LSHIFT equ 00000010b
KP_RSHIFT equ 00000001b
interrupt_status_ok proc near
push ax
mov ax,00001011b
out 20h,al
jmp short sometime
sometime:
in al,20h
cmp ah,al
pop ax
ret
interrupt_status_ok endp
;int28hook
;FUNCTION
; idle interrupt handler--write behind on idle
;USES
; none
;
int28hook proc far
pushf ;setup iret fraim
cli ;safety first
call DWORD PTR cs:int28chain ;call down idle chain
cmp cs:num_ticks_to_int28,5 ;bug bug hard coded
jae write_behind_on_int28
push es
push di
les di,cs:accessing_swap_file_ptr
test byte ptr es:[di].enhanced_mode_flags,ENHANCED_MODE_WIN
pop di
pop es
jnz no_write_behind_on_int28
write_behind_on_int28:
mov cs:num_ticks_to_int28,0
call write_behind_cache ;write behind a block
no_write_behind_on_int28:
iret
int28hook endp
;
;safety flush is consolidate code from i21 and i13 handlers
;for flushing the cache.
;set commit_all_when_ok and/or invalidate_when ok and
;call this function to properly flush the cache
;
safety_flush proc near
jmp short be_sure_to_invalidate ;invalidate even if no dirty
continue_write_reset:
cmp cs:invalidate_when_ok,0
jne be_sure_to_invalidate
cmp cs:number_of_dirty_elements,0
je done_reset
be_sure_to_invalidate:
sti ;enable interrupts so
;concurrent entry to
;write behind can complete
;if we get here, we must allow writes to go through
;even if we are "in" int 10, 9, or int 13.
;This will only happen is some other app (not smartdrv)
;is already breaking one of the re-entrancy rules.
;this should be dangerous, but heck, we just have to
;hope they know what they're doing
inc cs:ignore_intenter_checks
call write_behind_cache ;write behind a block
dec cs:ignore_intenter_checks
jmp short continue_write_reset
done_reset:
ret
safety_flush endp
;int21hook
;FUNCTION
;USES
int21hook proc far
cmp ah,3fh ; file read?
je handle_file_read ; check for read of STDIN
cmp ah,0dh ;disk reset?
je handle_reset
cmp ax,2513h ;see below
je flush_for_pctools
cmp ah,68h ;commit_file?
je handle_reset_flag
chainondown21:
jmp DWORD PTR cs:int21chain
handle_file_read:
or bx,bx
jnz chainondown21 ; only commit if handle == STDIN
cmp cs:in_win,1 ; and not in windows
jz chainondown21
mov cs:commit_all_when_ok,1
call safety_flush ; commit before blocking read
jmp chainondown21 ; of console makes it
; ; impossible.
handle_reset:
pushf ;setup iret fraim
cli ;safety first
call DWORD PTR cs:int21chain ;call down idle chain
;;;Set carry flag appropriately in iret frame
push ax
push bp
mov bp,sp
lahf
mov byte ptr ss:[bp+8],ah
pop bp
pop ax
mov cs:commit_all_when_ok,1
cmp ah,0dh
jne commit_no_invalidate
mov cs:invalidate_when_ok,1
commit_no_invalidate:
call safety_flush
iret
handle_reset_flag:
cmp cs:commitflag,1
je handle_reset
jmp short chainondown21
;
;PCtools hooks int13 and succeeds the call with carry clear, but does
;not reflect down the int 13 chain for the actual read. They do this
;on int 25s for disk detection. Here, we detect that someone is hooking
;int 13h and flush the cache so when the int 25 happens,
;the commit will have nothing to do. It cannot, since the next int13
;will not go through!
flush_for_pctools:
cmp cs:in_bambi,0 ;if we get call while in_bambi
jne chainondown21 ;we arent in pctools--safetyflush
mov cs:commit_all_when_ok,1 ;will hang if in_bambi is set
call safety_flush
jmp short chainondown21
int21hook endp
IF 0
messes with windows idle detection
;int16hook
;FUNCTION
; software keyboard handler
; write behind on keyboard poll
;
int16hook proc far
pushf
inc cs:in_16
cmp cs:in_16,1
jne dont_reenter16
call write_behind_cache
dont_reenter16:
dec cs:in_16
popf
jmp DWORD PTR cs:int16chain ;call down int 16 chain
int16hook endp
endif
;
;quick out exit for short jmps in write_behind_cache
;
quick_out_writebehind:
dec cs:in_bambi
push ds ;set the indos flag
push di ;so TSRS wont try to
lds di,cs:indosaddr ;pop up while we are
dec byte ptr ds:[di] ;doing write behind
pop di ;re-enter us via int 21
pop ds
ret
;
;write_behind_cache
;FUNCTION
; Determine that it is safe to access the disk (via the device drivers)
;to write behind cached data. If it is, commit the "least recently used"
;block to disk.
; This function is called at (asynchronous) interrupt time.
;In particular, interrupt 08 (the timer tick).
;
;USES
; none
;EFFECTS
; stack change
; critical section entered
;
write_behind_cache proc near
write_behind_on_idle:
push ds ;set the indos flag
push di ;so TSRS wont try to
lds di,cs:indosaddr ;pop up while we are
inc byte ptr ds:[di] ;doing write behind
pop di ;re-enter us via int 21
pop ds
inc cs:in_bambi
cmp cs:in_bambi,1 ;do not re-enter any part
jne quick_out_writebehind ;of the caching mechanism
cmp cs:invalidate_when_ok,0 ;invalidate even if no dirty
jne dont_check_dirty_count
cmp cs:number_of_dirty_elements,0 ;if there are no dirty blocks
je quick_out_writebehind ;don't do anything
dont_check_dirty_count:
cmp cs:ignore_intenter_checks,0 ;see safety_flush above
jne dont_do_int_checks
cmp cs:in_10,0 ;do not re-enter the ROM
jne short_jne_exit_08_no_crit ;BIOS if already in video
;functions--could lead to
;crash and odd video (timing,
;snow) problems. Device drivers
;called by cache call the
;ROM BIOS
cmp cs:in_09,0 ;do no process during
jne short_jne_exit_08_no_crit ;keyboard interrupt--timing
;dependent on some machines
cmp cs:in_13,0 ;do not process (reenter)
je noexit
;during ROM BIOS disk
;functions non-dos programs can
;use int13 directly without
;going through DOS
short_jne_exit_08_no_crit:
jmp exit_08_no_crit
noexit:
dont_do_int_checks:
push ax ;At this point, we need to
mov ax,8001h ;enter a critical disk
int 2ah ;section so a context
pop ax ;switch will not interrupt
;(therefore re-enter) the
;disk drivers (and our own
;code!)
cmp cs:in_bambi,1 ;we need to re-check this
jne critical_section_out ;within the critical section
;to verify that window's
;hasn't swapped to another
;task since our first check
;we do it this way to
;prevent critical sections
;on every timer tick
mov cs:save_stack_ss,ss ;save the current stack
mov cs:save_stack_sp,sp ;contexed
push cs ;and switch to our own
pop ss ;internal stack
mov sp,offset cs:resident_stack
cmp cs:processor_type,CPU386
jae save386regs
push ds ;we cannot corrupt any
push ax ;registers on a timer tick!
push bx
push cx ;finish saving all the
push dx ;registers for write-behind
push es
push bp
push si
push di
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -