Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1560 lines
34 KiB

TITLE LDINT - Loader interrupt procedure
.xlist
include kernel.inc
include newexe.inc
include tdb.inc
include protect.inc
include dbgsvc.inc
include bop.inc
include kdos.inc
include gpcont.inc ; SHERLOCK
ifdef WOW
include vint.inc
include softpc.inc
endif
NOTEXT = 1
NOGDICAPMASKS = 1
NOMB = 1
NOVK = 1
NOWH = 1
NOMST = 1
NORASTOPS = 1
NOMETAFILE = 1
NOMDI = 1
NOWINMESSAGES = 1
NOSYSMETRICS = 1
NOCOLOR = 1
NOCOMM = 1
NOKERNEL = 1
include windows.inc ; YIKES!!!
.list
FAULTSTACKFRAME struc
fsf_BP dw ? ; Saved BP
fsf_msg dw ? ; Near pointer to message describing fault
fsf_prev_IP dw ? ; IP of previous fault handler
fsf_prev_CS dw ? ; CS of previous fault handler
fsf_ret_IP dw ? ; DPMI fault handler frame follows
fsf_ret_CS dw ?
fsf_err_code dw ?
fsf_faulting_IP dw ?
fsf_faulting_CS dw ?
fsf_flags dw ?
fsf_SP dw ?
fsf_SS dw ?
FAULTSTACKFRAME ends
fsf_OFFSET = fsf_ret_IP - fsf_msg
UAE_STRING_LEN equ 192d
MIN_SP equ 256d
externFP ExitKernel
externFP WowDivideOverflowEx
DataBegin
;externB syserr
externB szAbort
externB szAbortCaption
externB szNukeApp
externB szWillClose
externB szBlame
externB szSnoozer
externB szInModule
externB szAt
externB szII
externB szGP
externB szSF
externB szNP
externB szLoad
;externB szDiscard
externB szPF
externB Kernel_Flags
externB fBooting
externW curTDB
;externW pGlobalHeap
externW DemandLoadSel
externD pSErrProc
externD pUserGetFocus
externD pUserGetWinTask
externD pUserIsWindow
externD lpGPChain
if kdebug
globalw wFaultSegNo,0
endif
if KDEBUG
staticW INT3Fcs,0
endif
globalW FaultHandler,<codeOffset HandleFault>
externD pPostMessage
ifdef WOW
externD FastBop
externD prevInt01proc
externD prevInt03proc
externD oldInt00proc
externW DebugWOW
externW gdtdsc
endif
DataEnd
sBegin DATA
externW gmove_stack
externW TraceOff
sEnd DATA
sBegin CODE
assumes CS,CODE
if SHERLOCK
externNP GPContinue
endif
externD prevIntx6proc
externD prevInt0Cproc
externD prevInt0Dproc
externD prevInt0Eproc
externD prevInt3Fproc
externNP LoadSegment
;externNP MyLock
ifndef WOW
externNP htoa
endif
externNP GetOwner
externNP GetPureName
externNP TextMode
externNP Int21Handler
;externNP DebugPostLoadMessage
externFP GlobalLRUNewest
externFP GlobalHandleNorip
externFP HasGPHandler
externFP AllocSelector
externFP IFreeSelector
assumes ds, nothing
assumes es, nothing
ifdef WOW
Entry macro name
public name
align 2
name&:
endm
endif
;-----------------------------------------------------------------------;
; Display_Box_of_Doom -- Display the Unrecoverable Application Error
; box that everyone seems to dislike so much.
;
; Entry:
; Action Reserved, must be zero
; lpText String to display, NULL for default
;
; Returns:
; AX = 1 Cancel
; AX = 2 OK
;
; Registers Destroyed:
; AX, BX, CX, DX, SI, DI
;
; History:
; Thu 16-May-1991 -by- Earle R. Horton
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc Display_Box_of_Doom,<PUBLIC,NEAR>
parmW action
parmD lpText
cBegin
SetKernelDS
if KDEBUG
xor bx,bx
or action,bx
jz @F
kerror 00FFh,<Action not 0 in FatalAppExit>,bx,bx
@@:
endif
push es ; added 10 feb 1990
mov es,curTDB ; did app disable exception
test es:[TDB_ErrMode],02h ; message box?
pop es
jnz nf_dont_ask
cmp pSErrProc.sel, 0 ; Can we put up message box?
jnz short nf_ask ; yes, do it
; no, have debugger?
nf_dont_ask:
mov ax,1
test Kernel_Flags[2],KF2_SYMDEB
jnz nf_ret ; yes, call debugger
inc ax
jmps nf_ret ; no, have to nuke the app
nf_ask:
push es
mov ax,lpText.sel
or ax,ax
jz nf_default_string
push ax
push lpText.off
jmps nf_pushed_string
nf_default_string:
push ds
mov ax,dataOffset szAbort ; lpText
push ax
nf_pushed_string:
push ds ; lpCaption
mov ax, dataOffset szAbortCaption
push ax
xor ax,ax ; Assume no debugger, blank first button
mov cx,ax
test Kernel_Flags[2],KF2_SYMDEB ; Debugger?
jz @F ; No
mov cx,SEB_CANCEL ; Yes, use Cancel button
@@:
push cx
; push SEB_OK+SEB_DEFBUTTON
push SEB_CLOSE + SEB_DEFBUTTON
push ax
call ds:[pSErrProc] ; Put up the system error message
pop es
nf_ret:
cEnd
;-----------------------------------------------------------------------;
; FatalAppExit -- Called by apps. to request an application error
; message box.
;
; Entry:
; Action Reserved, must be zero
; lpText String to display, NULL for default
;
; Returns:
; Returns to caller if Cancel button pressed
;
; Registers Destroyed:
;
; History:
; Sun 22-Oct-1989 15:18:57 -by- David N. Weise [davidw]
; Tonyg wrote it!
; Fri 24-May-1991 EarleH totally rewrote it, so there!
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IFatalAppExit,<PUBLIC,FAR>
parmW action
parmD lpText
cBegin
cmp seg_lpText,0
jne fae_string
mov off_lpText,offset szAbort
mov seg_lpText,seg szAbort
fae_string:
cCall Display_Box_of_Doom,<action,lpText>
cmp ax,1 ; Cancel pressed?
je fae_ret
jmp KillApp
fae_ret:
cEnd
; ------------------------------------------------------------------
;
; FormatFaultString -- Special purpose "sprintf()"
; Only used for the Box of Doom
;
; ------------------------------------------------------------------
cProc FormatFaultString,<PUBLIC,NEAR>,<si,di,ds,es>
parmD lpstr
parmW pStr ; Assumed in Kernel's DS
parmD csip
cBegin
SetKernelDS
cld
les di, lpstr ; Form string in ES:DI
call CurApName
lea si, szSnoozer ; " has caused an error in Windows"
call strcpy
mov si, pStr ; Copy the fault string
call strcpy
lea si, szInModule ; "in Module: <unknown>"
call strcpy
push es
push di
cCall GetOwner,<seg_csip> ; Can we find a module to blame?
or ax, ax
jz NoOwner
mov es, ax
cmp es:[ne_magic], NEMAGIC
jne NoOwner
mov bx, seg_csip ; Have the module, can we get the
and bl, not SEG_RING ; segment number?
mov di,es:[ne_segtab]
mov ax,1
mov cx, es:[ne_cseg]
getsegno:
mov dx, es:[di].ns_handle
and dl, not SEG_RING
cmp dx, bx
jz gotsegno
add di,SIZE NEW_SEG1
inc ax
loop getsegno
jmps nosegno ; No, report the selector instead
gotsegno:
mov seg_csip, ax ; Print Segment #
nosegno:
mov di, es:[ne_pfileinfo] ; Now blame the module
add di, opFile
call GetPureName
mov si, di
smov ds, es
UnSetKernelDS
pop di
pop es
ifdef FE_SB
find_space:
cmp byte ptr es:[di-1],' ' ; prepare space before mod name
jz copy_name
dec di
jmps find_space
copy_name:
else ; !FE_SB
sub di, 9 ; Get rid of <unknown>
endif ; !FE_SB
call strcpy
SetKernelDS
jmps GotOwner
NoOwner:
pop di
pop es
GotOwner:
lea si, szAt
call strcpy
ifdef WOW
cCall <far ptr Far_htoa>,<es,di,seg_csip>
else
cCall htoa,<es,di,seg_csip>
endif
mov di, ax
mov es, dx
mov byte ptr es:[di], ':'
inc di
ifdef WOW
cCall <far ptr Far_htoa>,<es,di,off_csip>
else
cCall htoa,<es,di,off_csip>
endif
mov es, dx
mov di, ax
lea si, szNukeApp
call strcpy
call CurApName
lea si, szWillClose
call strcpy
cEnd
CurApName proc near
SetKernelDS
lea si, szBlame ; Default task to blame
cmp curTDB, 0 ; Have a task to blame?
je DefaultCaption ; nope, use default
mov ds, curTDB
UnSetKernelDS
mov si, TDB_ModName
DefaultCaption:
mov cx, 8
copy_appname:
lodsb
stosb
or al, al ; Null padded in TDB
loopne copy_appname
jne no_null
dec di ; Toss extra space
no_null:
SetKernelDS
ret
CurApName endp
public strcpy
strcpy proc near
lodsb
stosb
or al, al
jnz strcpy
dec di ; Ignore Null
ret
strcpy endp
;-----------------------------------------------------------------------;
;
; KillApp -- Calls USER to tell it that the application is going away,
; then tells DOS to kill it.
;
; ENTRY: None
; EXIT: None, doesn't
;
; Registers modified: Huh?
;
;-----------------------------------------------------------------------;
KillApp proc near
SetKernelDS
test fBooting, 1
jz @F
mov ax, 1
cCall ExitKernel,<ax>
@@: mov ax,4CFFH ; They said OK to Nuke app.
DOSCALL
UnSetKernelDS
KillApp endp
;-----------------------------------------------------------------------;
; FaultFilter -- Called by HandleFault, NestedFault, and routines that
; use the same stack frame. Look at the faulting CS:IP on the exception
; handler frame, and make sure that CS is Ring 3, LDT. If it is not
; pop the near return address from the stack and chain the exception
; to the next handler. This will be the DPMI server, which will crash
; Windows back to DOS. We ought to try to close up a few things first.
;-----------------------------------------------------------------------;
ReSetKernelDS
public FaultFilter
FaultFilter proc near
mov al,byte ptr [bp].fsf_faulting_CS
and al, SEG_RING_MASK ; Check it was Ring 3, LDT
cmp al, SEG_RING
je @F
;
; The faulting CS's ring bits do not match up. We will not handle
; this fault, because we assume it happened in the DPMI provider,
; and is a Real Bad one. Since the default handler is going to
; abort here, it would be nice to let the user down real easy.
; Restoring the display to text mode would be nice, at the very
; minimum.
;
cCall TextMode
ret ; Hypocrite!
@@:
;
; Check for faults on POP FS and POP GS. If found, fix them up. We need to
; fix up faults in the register restoration of both KRNL386 (WOW16Return) and
; MMSYSTEM (MULTI_MEDIA_ISR386). Monty Pythons Complete Waste of Time is an app
; which frees selectors in FS across message boundries.
;
ifdef WOW
push ds
mov ax, word ptr [bp].fsf_faulting_CS
mov ds, ax
mov si, word ptr [bp].fsf_faulting_IP
cmp word ptr [si], 0A10Fh ; pop fs
je HandFSGSflt
cmp word ptr [si], 0A90Fh ; pop gs
je HandFSGSflt
jmp short NoFSGSflt
HandFSGSflt:
if KDEBUG
Trace_Out "POP GS/FS fault fixed up!"
endif
mov ds, [bp].fsf_SS
mov si, [bp].fsf_SP
mov word ptr [si], 0
pop ds ; restore kernel DS
pop ax ; don't do EH_Chain
push codeOffset EH_ret ; use "handled it" return instead
ret
NoFSGSflt:
pop ds
endif
pop ax ; toss chain return
push codeOffset EH_ret ; use "handled it" return
mov si,word ptr FaultHandler ; SI = Handler
push si
mov word ptr FaultHandler,codeOffset NestedFault
if KDEBUG
test byte ptr [bp].fsf_flags+1,2 ; IF set in faulting frame?
jnz @F
Trace_Out "Fault with interrupts disabled!"
@@:
endif
cmp [bp].fsf_SP,128d
jb ff_stack
cCall HasGPHandler, <[bp].fsf_faulting_CS, [bp].fsf_faulting_IP>
or ax, ax
jz ff_real_fault
mov ds, [bp].fsf_SS
mov bx, [bp].fsf_SP
sub [bp].fsf_SP, 4
mov cx, [bp].fsf_err_code ; put error code on stack
mov [bx-2],cx
mov dx, [bp].fsf_faulting_IP
mov [bx-4],dx ; and faulting IP
mov [bp].fsf_faulting_IP, ax ; continue at gp fault handler
jmps ff_ret
ff_real_fault:
ifdef WOW
test DebugWOW,DW_DEBUG
jz ff_no_wdebug
xor ax,ax ; 0 in AX defaults to not handled
push DBG_GPFAULT2
FBOP BOP_DEBUGGER,,FastBop
add sp,+2
or ax, ax
jnz ff_ret ; Alright! they handled the exception!
; Get us back to the app please!
; Otherwise, they chose to continue the exception
ff_no_wdebug:
endif
if SHERLOCK
cCall GPContinue ; We know BP points to
or ax, ax ; the fault frame!
jnz ff_ret
endif
ff_stack:
call si ; call our fault handler
ff_ret:
SetKernelDS
pop FaultHandler
ret
FaultFilter endp
ifdef WOW
;-----------------------------------------------------------------------;
;
; single_step
;
;-----------------------------------------------------------------------;
Entry single_step
push ds
SetKernelDS ds
push ax
; QCWIN traces through code which it has no source code for. This means
; its ends up tracing through the 16-bit to 32-bit transition code and
; when it traces on the call fword instruction, it cause 32-bit trace
; interrupt which breaks into the kd> On a retail build with no
; debugger attached, it might work.
; To work around the problem we turn off the TraceFlag here if wow16cal
; has requested it.
test TraceOff,1h
jnz ss_turn_off_trace_flag
test DebugWOW,DW_DEBUG
jz ss_no_wdebug
xor ax,ax ; 0 in AX defaults to not handled
push DBG_SINGLESTEP
FBOP BOP_DEBUGGER,,FastBop
add sp,+2
or ax, ax
jnz ss_ret ; Alright! they handled the exception!
; Get us back to the app please!
ss_no_wdebug:
; Otherwise, they chose to continue the exception
pop ax
pop ds
jmp cs:[prevInt01proc]
; Tell api code (wow16cal) to turn on trace flag at end of next api
ss_turn_off_trace_flag:
sub sp,2 ; Make it look like "normalized" fault frame
push bp
mov bp,sp
or TraceOff,2h
and [bp].fsf_flags,NOT FLG_TRAP ; turn off the trap flag
pop bp
add sp,2
ss_ret:
pop ax
pop ds
UnSetKernelDS ds
retf
;-----------------------------------------------------------------------;
;
; breakpoint
;
;-----------------------------------------------------------------------;
Entry breakpoint
push ds
SetKernelDS ds
push ax
test DebugWOW,DW_DEBUG
jz br_no_wdebug
xor ax,ax ; 0 in AX defaults to not handled
push DBG_BREAK
FBOP BOP_DEBUGGER,,FastBop
add sp,+2
or ax, ax
jnz bp_ret ; Alright! they handled the exception!
; Get us back to the app please!
br_no_wdebug:
; Otherwise, they chose to continue the exception
pop ax
pop ds
jmp cs:[prevInt03proc]
bp_ret:
pop ax
pop ds
UnSetKernelDS ds
retf
;-----------------------------------------------------------------------;
;
; divide_overflow
;
;-----------------------------------------------------------------------;
Entry divide_overflow
; at this point all of the registers contain the same values as they did
; at the time the faulting instruction was hit
; -- except for: cs:ip and ss:sp
push ds
SetKernelDS ds
push ax
test DebugWOW,DW_DEBUG
jz di_no_wdebug
xor ax,ax ; 0 in AX defaults to not handled
push DBG_DIVOVERFLOW
FBOP BOP_DEBUGGER,,FastBop
.286p
add sp,+2
or ax, ax
jnz do_ret ; Alright! they handled the exception!
; Get us back to the app please!
di_no_wdebug:
; Otherwise, they chose to continue the exception
; check to see if we want to hack this exception for them
push es
mov es, curTDB
mov ax, es:[TDB_WOWCompatFlagsEx2]
pop es
test ax, 2 ; HIWORD(WOWCFEX_DIVIDEOVERFLOWPATCH)
jz di_no_patch1
.386p
pop ax ; get the original ax
; push ax ; restore the stack (don't need to do this since we exit
; via do_ret2 -- we want to preserve our *change* to AX
push ebx ; preserve ebx
mov bx, sp
push eax ; make room for two dword local vars local[1]
push eax ; local[0]
push eax ; push original dividend registers
push edx
push word ptr ss:[bx+14] ;get segment of faulting instruction
push word ptr ss:[bx+12] ;get offset of faulting instruction
mov bx,sp ; push pointer to local[0]
add bx,12 ; point to local[0]
push ss
push bx
;call into wow32 returns with new divisor in al, ax, or dx:ax --
;depending on the instruction
cCall WowDivideOverflowEx
or ax,ax ; if both ax & dx are 0, it was an edx:eax form
jnz di_got_it ; so we have to get eax & edx from local[]
or dx,dx
jnz di_got_it
pop eax ; get eax & edx from local[]
pop edx
pop ebx ; restore original ebx
jmp do_ret2
di_got_it:
pop ebx ; get rid of local[] dwords
pop ebx
pop ebx ; restore original ebx
jmp do_ret2;
.286p
di_no_patch1:
pop ax
pop ds
jmp cs:[oldInt00proc]
do_ret:
pop ax
do_ret2: ; AX already popped -- we want to preserve our change to AX
pop ds
UnSetKernelDS ds
retf
endif
;-----------------------------------------------------------------------;
;
; Set_GO_BP
;
;-----------------------------------------------------------------------;
public Set_GO_BP
Set_GO_BP proc near
mov cx, [bp].fsf_faulting_CS ; Faulting CS
mov bx, [bp].fsf_faulting_IP ; Faulting IP
DebInt 40h
; mov ax, 40h ; 16 bit forced go command
; int 41h ; Call debugger
;ifdef JAPAN
; INT41SIGNATURE
;endif
ret
Set_GO_BP endp
;-----------------------------------------------------------------------;
;
; ExitFault -- Fault at Exit Time!!!
;
; ENTRY: BP points to fault frame described above
;
; EXIT: Returns to DPMI.
;
; Registers Modified: None
;
;-----------------------------------------------------------------------;
ReSetKernelDS
public ExitFault
ExitFault proc near
if KDEBUG
Trace_Out "Fault at Exit Time!!!"
endif
;
; If a kernel debugger is loaded, pop out at the nested fault, and
; take no prisoners.
;
test Kernel_Flags[2],KF2_SYMDEB ; Debugger?
jz @F
jmp Set_GO_BP
@@:
jmps HandleFault
ExitFault endp
public BUNNY_351
BUNNY_351 proc far
push ds
SetKernelDS
mov FaultHandler,codeOffset ExitFault
pop ds
ret
BUNNY_351 endp
;-----------------------------------------------------------------------;
;
; MY_RETF -- Executes a far return.
;
;-----------------------------------------------------------------------;
MY_RETF proc near
retf
MY_RETF endp
;-----------------------------------------------------------------------;
;
; NestedFault -- Called when a fault handler Faults!!!
;
; ENTRY: BP points to fault frame described above
;
; EXIT: Returns to DPMI.
;
; Registers Modified: None
;
;-----------------------------------------------------------------------;
ReSetKernelDS
public NestedFault
NestedFault proc near
if KDEBUG
Trace_Out "Nested Fault!!!"
endif
;
; If a kernel debugger is loaded, pop out at the nested fault, and
; take no prisoners.
;
test Kernel_Flags[2],KF2_SYMDEB ; Debugger?
jz @F
jmp Set_GO_BP
@@:
jmps HandleFault
NestedFault endp
;-----------------------------------------------------------------------;
;
; HandleFault -- Puts up the System Error box for a Fault. Terminates
; the application or enters the debugger.
;
; ENTRY: BP points to fault frame described above
;
; EXIT: Returns to DPMI. If Cancel is pressed, we tell
; WDEB to set a GO breakpoint at the faulting instruction
; first. If OK is pressed, then the CS:IP on the DPMI
; fault frame is modified to point to KillApp, and the
; SS:SP points to a temp. stack owned by Kernel.
;
; Registers Modified: None
;
;-----------------------------------------------------------------------;
ReSetKernelDS
public HandleFault
HandleFault proc near
mov ax, lpGPChain.sel ; Do we have a private GP handler?
mov lpGPChain.sel, 0 ; Prevent re-entrancy
cmp ax, [bp].fsf_SS
jnz We_Can_Handle_It
test Kernel_Flags[2],KF2_SYMDEB ; Debugger?
jz @F
mov lpGPChain.sel,ax
jmp Set_GO_BP
@@:
; If we want to chain back for any
mov bx, lpGPChain.off ; faults, then set up the stack of
mov [bp].fsf_SP, bx ; the handler, and continue execution
mov [bp].fsf_faulting_CS, cs ; at a RETF in Kernel
mov [bp].fsf_faulting_IP, offset MY_RETF
cmp [pPostMessage.sel],0 ; is there a USER around yet?
je @F
pusha
push es
cCall [pPostMessage],<-1,WM_SYSTEMERROR,1,0,0>
pop es
popa
@@:
if kdebug
mov es, ax
mov ax, es:[bx+2]
mov bx, es:[bx]
krDebugOut DEB_ERROR, "Fault detected - handled by %AX2 #AX:#BX"
endif
jmp HandleFault_Exit
We_Can_Handle_It:
sub sp, UAE_STRING_LEN ; Room for string
mov si, sp
cCall FormatFaultString,<ss,si,[bp].fsf_msg,[bp].fsf_faulting_CS,[bp].fsf_faulting_IP>
push bp
xor bp,bp ; Some people are picky...
cCall Display_Box_of_Doom,<0,ss,si>
pop bp
add sp, UAE_STRING_LEN
or ax, ax
jne @F
INT3_DEBUG ; Failed call - no USER
@@:
cmp ax, 1 ; Button 1 (Cancel) pressed?
jne @F
jmp Set_GO_BP
@@:
test fBooting, 1 ; No, they said to Nuke app.
jnz no_signal_proc
mov ds, curTDB
UnSetKernelDS
cmp ds:[TDB_USignalProc].sel,0
jz no_signal_proc
mov bx,0666h
mov di, -1
cCall ds:[TDB_USignalProc],<ds,bx,di,ds:[TDB_Module],ds:[TDB_Queue]>
;
; Since we are on a nice big fat juicy fault handler stack now, we can call
; Windows to clean up after the task.
;
mov bx,SG_EXIT
cCall ds:[TDB_USignalProc],<ds,bx,di,ds:[TDB_Module],ds:[TDB_Queue]>
mov ds:[TDB_USignalProc].sel,0
no_signal_proc:
mov [bp].fsf_SP,dataOffset gmove_stack
mov [bp].fsf_SS,seg gmove_stack
mov [bp].fsf_faulting_CS,cs
lea ax,KillApp
mov [bp].fsf_faulting_IP,ax
HandleFault_Exit:
ret
HandleFault endp
; ------------------------------------------------------------------
;
; ExceptionHandlerProc -- Common entry point for exception handlers
;
; ------------------------------------------------------------------
public ExceptionHandlerProc
ExceptionHandlerProc proc far
push bp
mov bp,sp
pusha
push ds
SetKernelDS
push es
EH_Popup:
call FaultFilter
EH_Chain:
pop es
pop ds
UnsetKernelDS
popa
pop bp
add sp,2 ; remove message from stack
retf ; chain to prev handler
EH_ret:
pop es
pop ds
popa
pop bp
add sp,fsf_OFFSET
retf
ExceptionHandlerProc endp
; ------------------------------------------------------------------
;
; This macro sets up the stack frame for entry to the generic
; exception handler.
;
; ------------------------------------------------------------------
ExceptionHandlerPrologue macro name,msg,chain
public name
name:
push word ptr chain + 2
push word ptr chain
push offset msg
endm
; ------------------------------------------------------------------
;
; This macro sets up the stack frame, then jumps to the generic
; exception handler.
;
; ------------------------------------------------------------------
ExceptionHandler macro name,msg,chain
ExceptionHandlerPrologue name,msg,chain
jmp ExceptionHandlerProc
assumes ds, nothing
assumes es, nothing
endm
; ------------------------------------------------------------------
;
; Four fatal ones.
;
; ------------------------------------------------------------------
ExceptionHandler StackFault,szSF,prevInt0Cproc
ExceptionHandler GPFault,szGP,prevInt0Dproc
ExceptionHandler invalid_op_code_exception,szII,prevIntx6proc
ExceptionHandler page_fault,szPF,prevInt0Eproc
ExceptionHandler LoadSegFailed,szLoad,prevInt3Fproc
; ------------------------------------------------------------------
;
; The not present fault is used to demand-load segments from newexe
; files. If we find out that something bogus has happened, then
; we just jump into the fault handler.
;
; ------------------------------------------------------------------
ExceptionHandlerPrologue SegmentNotPresentFault,szNP,prevInt3Fproc
push bp
mov bp,sp
pusha
push ds
SetKernelDS
push es
mov al,byte ptr [bp].fsf_faulting_CS
and al, SEG_RING_MASK ; Check it was Ring 1, LDT
cmp al, SEG_RING
je @F
jmp EH_Chain
@@:
mov al,byte ptr [bp].fsf_err_code
test al, SEL_LDT ; Check it was LDT
jne @F
jmp EH_Chain
@@:
if KDEBUG
test byte ptr [bp].fsf_flags+1,2 ; IF set in faulting frame?
jnz @F
Trace_Out "Segment not present fault with interrupts disabled!"
@@:
endif
FSTI
;
; Don't discard the segment that we have to return to!!!
;
cCall GlobalHandleNorip,<[bp].fsf_faulting_CS>
test cl,GA_DISCARDABLE
jz @F
cCall GlobalLRUNewest,<ax>
@@:
mov bx,[bp].fsf_err_code
seg_reload:
and bx, NOT 7h ; get the not present selector
or bl, SEG_RING ; Correct RING bits
if KDEBUG
mov INT3Fcs, bx ; Save in case of error
endif
; On WOW we don't copy the owner to the real LDT since it is slow to call
; the NT Kernel, so we read our copy of it directly.
; see set_discarded_sel_owner mattfe mar 23 93
mov es,cs:gdtdsc
mov cx,bx ; save bx
and bl, not 7
mov es,es:[bx].dsc_owner
mov bx,cx ; restore
StoH bl ; Need handle
cmp es:[ne_magic],NEMAGIC ; If owner is not a module
jnz bad_seg_load ; (i.e., an instance or garbage)
; get out of here.
mov di,es:[ne_segtab]
mov ax,1
mov cx, es:[ne_cseg]
jcxz bad_seg_load
dorten:
cmp es:[di].ns_handle,bx
jz got_seg_no
add di,SIZE NEW_SEG1
inc ax
loop dorten
; program has referenced garbage...
bad_seg_load:
jmp EH_Popup
got_seg_no:
;
; If we already are on the exception handler stack, then we want to make
; sure that we don't overwrite the original stack frame. Copy our
; stack frame variables down by the difference between SP and SP before
; we got called.
;
push ax
mov ax,ss
cmp ax,word ptr [bp].fsf_SS
pop ax
jne stack_OK
push ax
push bx
push bp
lea bp,word ptr [bp].fsf_SS
mov ax,sp
dec ax
dec ax
@@:
push word ptr [bp]
dec bp
dec bp
cmp bp,ax
jne @B
pop bp
pop bx
pop ax
;
; Figured out what this was supposed to be by tracing up to here
; in the debugger.
;
sub bp,32h
stack_OK:
push es
mov bx,ax
UnsetKernelDS
mov ax,ss
mov ds,ax
les di,dword ptr [bp].fsf_SP
dec di
dec di
std
;
; Push an IRET frame on the faulting stack.
;
lea si,[bp].fsf_flags
mov cx,3
rep movsw
;
; Push our saved registers on the faulting stack.
;
lea si,[bp]
mov cx,11 ; BP + PUSHA + ES + DS
rep movsw
pop ax
;
; Push arguments to LoadSegment on the faulting stack.
;
stosw ; hExe
mov ax,bx
stosw ; segno
mov ax,-1
stosw
stosw
inc di
inc di
;
; Point the faulting stack at the new location.
;
mov [bp].fsf_SP,di
;
; Tell DPMI to return to us instead of the faulting code.
;
mov [bp].fsf_faulting_CS,cs
mov [bp].fsf_faulting_IP,offset let_them_do_it
lea sp,[bp].fsf_ret_IP
if kdebug
SetKernelDS
mov wFaultSegNo, bx
UnSetKernelDS
endif
retf
let_them_do_it:
SetKernelDS
xor cx, cx ; we try to keep a selector reserved
xchg cx, DemandLoadSel ; for scratch use while demand
jcxz @f ; loading segments--free it to make
cCall IFreeSelector,<cx> ; it available now
@@:
cCall LoadSegment
push ax ; reserve a selector for the next
cCall AllocSelector,<0> ; time we demand load a segment
mov DemandLoadSel, ax
pop cx ; LoadSegment result
jcxz SegLoaderFailure
if kdebug
push bx
mov bx, wFaultSegNo
krDebugOut <DEB_TRACE or DEB_krLoadSeg>, "Demand load %CX2(#bx) on %SS2"
pop bx
endif
pop es
pop ds
UnsetKernelDS
popa
pop bp
;** Check to see if we're about to restart an instruction in
;** a not present segment. This would only occur if the
;** segment was discarded because of the segment load we
;** just did.
IF KDEBUG
push bp ;Make a stack frame
mov bp,sp
push ax
mov bp,[bp + 4] ;Get the CS
lar ax,bp ;See if the CS is valid
test ax,8000h ;Is it present?
jnz @F ;Yes, don't complain
mov ax,bp
Trace_Out <'LDINT: Trying to restart discarded caller (#AX)'>
@@:
pop ax
pop bp
ENDIF
iret
public SegLoaderFailure
SegLoaderFailure proc near
;
; segment loader was unable to load the segment!!!
; Restore all the registers, create a fake DPMI frame, then
; complain about the problem. Lets the user break into the
; debugger, if installed, on Cancel. Creating and destroying
; the fake DPMI frame is inconvenient and messy, but it lets
; us handle the problem in common fault code.
;
pop es
pop ds
UnsetKernelDS
popa
sub sp,4
mov bp,sp ; BP -> xx xx BP IP CS FL
push word ptr [bp+4] ; push app's BP
push ax ; get a temporary register
mov ax,[bp+6] ; IP
mov [bp+2],ax
mov ax,[bp+8] ; CS
mov [bp+4],ax
mov ax,[bp+10] ; Flags
mov [bp+6],ax
mov [bp+10],ss
lea ax,[bp+12]
mov [bp+8],ax
pop ax
pop bp
call far ptr LoadSegFailed ; BP -> RETIP RETCS EC IP CS FL SP SS
push bp
mov bp,sp ; BP -> BP EC IP CS FL SP SS
mov [bp+2],ax
mov ax,[bp+8] ; Flags
mov [bp+12],ax
mov ax,[bp+6] ; CS
mov [bp+10],ax
mov ax,[bp+4] ; IP
mov [bp+8],ax
pop bp
pop ax
add sp,4
iret
SegLoaderFailure endp
;ENDIF
;-----------------------------------------------------------------------;
; default_sig_handler
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Wed 10-Jan-1990 22:32:34 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc default_sig_handler,<PUBLIC,FAR>
cBegin nogen
ret
cEnd nogen
;-----------------------------------------------------------------------;
;
; Panic -- Called by ToolHelp when it gets a bad stack fault or any
; other fault with SP suspiciously low.
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc Panic,<PUBLIC,NEAR>
cBegin
if KDEBUG
Trace_Out "KERNEL: Panic called!!!"
endif
int 1
jmp KillApp
cEnd
;-----------------------------------------------------------------------;
; DoSignal
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Wed 10-Jan-1990 22:52:52 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc DoSignal,<PUBLIC,FAR>,<ax,bx,cx,dx,di,si,es>
cBegin
SetKernelDS
cmp pUserGetFocus.sel,0 ; is there a USER yet?
jz ds_exit
call pUserGetFocus
or ax,ax
jz ds_exit
mov si,ax
cCall pUserIsWindow,<ax>
or ax,ax
jz ds_exit
cCall pUserGetWinTask,<si>
mov ds,ax
TDB_check_DS
cmp ds:[TDB_SigAction],2 ; send it on?
jnz ds_exit
mov ax,1
xor bx,bx
cCall ds:[bx].TDB_ASignalProc,<bx,ax>
ds_exit:
cEnd
sEnd CODE
sBegin MISCCODE
assumes cs, misccode
assumes ds, nothing
assumes es, nothing
externNP MISCMapDStoDATA
ifdef WOW
externFP htoa
assumes ds,nothing
assumes es,nothing
;-----------------------------------------------------------------------;
; allows htoa to be called from _TEXT code segment
cProc Far_htoa,<PUBLIC,FAR>
parmD lpstr
parmW val
cBegin
push [bp+10]
push [bp+8]
push [bp+6]
call far ptr htoa
cEnd
endif ;; WOW
;-----------------------------------------------------------------------;
; SetSigHandler
;
; SetSigHandler notifies Windows of a handler for a signal.
; It may also be used to ignore a signal or install a default
; action for a signal.
;
; Entry:
; parmD lpprocRoutine Signal handler
; parmD lpDPrevAddress Previous handler (returned)
; parmD lpWPrevAction Previous action (returned)
; parmW Action Indicate request type
; parmW SigNumber Signal number of interest
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Mon 25-Dec-1989 00:36:01 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc SetSigHandler,<PUBLIC,FAR>,<di,si,ds>
parmD lpprocRoutine
parmD lpDPrevAddress
parmD lpWPrevAction
parmW Action
parmW SigNumber
cBegin
call MISCMapDStoDATA
ReSetKernelDS
cmp SigNumber,1 ; is it SIGINTR?
jnz dssh_return_success ; ignore if not
cmp Action,4 ; is it reset Signal?
jz @F
push ds
mov ds,curTDB
assumes ds,nothing
mov ax,Action
xchg ax,ds:[TDB_SigAction]
les bx,lpWPrevAction
mov cx,es
or cx,bx
jz @F
mov es:[bx],ax
@@:
mov dx,lpprocRoutine.sel
mov ax,lpprocRoutine.off
cmp Action,0 ; put in default handler?
jnz ssg_stick_it_in
mov dx,SEG default_sig_handler
mov ax,codeOffset default_sig_handler
ssg_stick_it_in:
xchg dx,ds:[TDB_ASignalProc].sel
xchg ax,ds:[TDB_ASignalProc].off
cmp Action,4 ; is it reset Signal?
jz @F
les bx,lpDPrevAddress
mov cx,es
or cx,bx
jz @F
mov es:[bx].sel,dx
mov es:[bx].off,ax
pop ds
@@:
dssh_return_success:
xor ax,ax ; return success
dssh_exit:
cEnd
;----------------------------------------------------------------------------
;
; SwapRecording(Flag)
;
; Flag = 0 => Stop recording
; = 1 => Start recording only Swaps, Discards and Returns
; = 2 => Start recording Calls in addition to Swaps, Discards and
; returns.
; Destroys AL register
;----------------------------------------------------------------------------
; Retail Version
cProc ISwapRecording,<PUBLIC, FAR>
; parmW Flag
cBegin nogen
retf 2
cEnd nogen
sEnd MISCCODE
end