IMPLEMENTATION OF CODE FOR HOOKING THE XMS DRIVER
In order to support the hooking of the XMS driver by multiple pieces of
code, the following code sample should be followed. Use of other methods
for hooking the XMS driver will not work in many cases. This method is
the official supported one.
The basic strategy is:
Find the XMS driver header which has the "near jump" dispatch.
Patch the near jump to a FAR jump which jumps to my HOOK XMS driver
header.
NOTES:
This architecture allows the most recent HOOKer to undo his XMS
driver hook at any time without having to worry about damaging a
"hook chain".
This architecture allows the complete XMS hook chain to be
enumerated at any time. There are no "hidden hooks".
This architecture allows the HOOKer to not have to worry about
installing an "INT 2F hook" to hook the AH=43h INT 2Fs handled by
the XMS driver. The base XMS driver continues to be the only one
installed on INT 2Fh AH=43h.
This avoids all of the problems of undoing a software interrupt
hook.
;
; When I wish to CHAIN to the previous XMS driver, I execute a FAR JMP
; to the address stored in this DWORD.
;
PrevXMSControlAddr dd ?
;
; The next two data items are needed ONLY if I desire to be able to undo
; my XMS hook.
; PrevXMSControlJmpVal stores the previos XMS dispatch near jump offset
; value that is used to unhook my XMS hook
; PrevXMSControlBase stores the address of the XMS header that I hooked
;
PrevXMSControlBase dd ?
PrevXMSControlJmpVal db ?
;
; This is MY XMS control header.
;
MyXMSControlFunc proc FAR
jmp short XMSControlEntry
nop
nop
nop
XMSControlEntry:
......
Chain:
jmp cs:[PrevXMSControlAddr]
MyXMSControlFunc endp
.......
;
; This is the code which installs my hook into the XMS driver.
;
;
; See if there is an XMS driver to hook
;
mov ax,4300h
int 2Fh
cmp al,80h
jne NoXMSDrvrToHookError
;
; Get the current XMS driver Control address
;
mov ax,4310h
int 2Fh
NextXMSHeader:
mov word ptr [PrevXMSControlAddr+2],es
mov word ptr [PrevXMSControlBase+2],es
mov word ptr [PrevXMSControlBase],bx
mov cx,word ptr es:[bx]
cmp cl,0EBh ; Near JUMP
je ComputeNearJmp
cmp cl,0EAh ; Far JUMP
jne XMSDrvrChainMessedUpError
ComputeFarJmp:
mov si,word ptr es:[bx+1] ; Offset of jump
mov es,word ptr es:[bx+1+2] ; Seg of jump
mov bx,si
jmp short NextXMSHeader
ComputeNearJmp:
cmp word ptr es:[bx+2],9090h ; Two NOPs?
jne XMSDrvrChainMessedUpError ; No
cmp byte ptr es:[bx+4],90h ; Total of 3 NOPs?
jne XMSDrvrChainMessedUpError ; No
mov di,bx ; Save pointer to header
xor ax,ax
mov al,ch ; jmp addr of near jump
mov [PrevXMSControlJmpVal],al
add ax,2 ; NEAR JMP is 2 byte instruction
add bx,ax ; Target of jump
mov word ptr [PrevXMSControlAddr],bx
;
; Now INSTALL my XMS HOOK
;
cli ; Disable INTs in case someone calls
; XMS at interrupt time
mov byte ptr es:[di],0EAh ; Far Immed. JUMP instruction
mov word ptr es:[di+1],offset MyXMSControlFunc
mov word ptr es:[di+3],cs
sti
.....
;
; Deinstall my XMS hook. This can be done IF AND ONLY IF my XMS header
; still contains the near jump dispatch
;
cmp byte ptr [MyXMSControlFunc],0EBh
jne CantDeinstallError
mov al,0EBh
mov ah,[PrevXMSControlJmpVal]
les bx,[PrevXMSControlBase]
cli ; Disable INTs in case someone calls
; XMS at interrupt time
mov word ptr es:[bx],ax
mov word ptr es:[bx+2],9090h
mov byte ptr es:[bx+4],90h
sti
....