559 lines
12 KiB
NASM
559 lines
12 KiB
NASM
|
|
;-----------------------------------------------------------------------;
|
|
; ;
|
|
; Windows Critical Error Handler ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.xlist
|
|
include kernel.inc
|
|
include tdb.inc
|
|
ifdef WOW
|
|
include vint.inc
|
|
endif
|
|
.list
|
|
|
|
DEVSTRC struc
|
|
devLink dd ?
|
|
devAttr dw ?
|
|
devPtr1 dw ?
|
|
devPtr2 dw ?
|
|
devName db 8 dup (?)
|
|
DEVSTRC ends
|
|
|
|
IDABORT = 3
|
|
IDRETRY = 4
|
|
IDIGNORE = 5
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; ;
|
|
; XENIX calls all return error codes through AX. If an error occurred ;
|
|
; then the carry bit will be set and the error code is in AX. ;
|
|
; If no error occurred then the carry bit is reset and AX contains ;
|
|
; returned info. ;
|
|
; ;
|
|
; Since the set of error codes is being extended as we extend the ;
|
|
; operating system, we have provided a means for applications to ask ;
|
|
; the system for a recommended course of action when they receive an ;
|
|
; error. ;
|
|
; ;
|
|
; The GetExtendedError system call returns a universal error, an error ;
|
|
; location and a recommended course of action. The universal error ;
|
|
; code is a symptom of the error REGARDLESS of the context in which ;
|
|
; GetExtendedError is issued. ;
|
|
; ;
|
|
; These are the universal int 24h mappings for the old INT 24 set of ;
|
|
; errors. ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
error_write_protect EQU 19
|
|
error_bad_unit EQU 20
|
|
error_not_ready EQU 21
|
|
error_bad_command EQU 22
|
|
error_CRC EQU 23
|
|
error_bad_length EQU 24
|
|
error_Seek EQU 25
|
|
error_not_DOS_disk EQU 26
|
|
error_sector_not_found EQU 27
|
|
error_out_of_paper EQU 28
|
|
error_write_fault EQU 29
|
|
error_read_fault EQU 30
|
|
error_gen_failure EQU 31
|
|
|
|
; These are the new 3.0 error codes reported through INT 24h
|
|
|
|
error_sharing_violation EQU 32
|
|
error_lock_violation EQU 33
|
|
error_wrong_disk EQU 34
|
|
error_FCB_unavailable EQU 35
|
|
|
|
; New OEM network-related errors are 50-79
|
|
|
|
error_not_supported EQU 50
|
|
|
|
; End of INT 24h reportable errors
|
|
|
|
error_file_exists EQU 80
|
|
error_DUP_FCB EQU 81 ; *****
|
|
error_cannot_make EQU 82
|
|
error_FAIL_I24 EQU 83
|
|
|
|
; New 3.0 network related error codes
|
|
|
|
error_out_of_structures EQU 84
|
|
error_Already_assigned EQU 85
|
|
error_invalid_password EQU 86
|
|
error_invalid_parameter EQU 87
|
|
error_NET_write_fault EQU 88
|
|
|
|
error_I24_write_protect EQU 0
|
|
error_I24_bad_unit EQU 1
|
|
error_I24_not_ready EQU 2
|
|
error_I24_bad_command EQU 3
|
|
error_I24_CRC EQU 4
|
|
error_I24_bad_length EQU 5
|
|
error_I24_Seek EQU 6
|
|
error_I24_not_DOS_disk EQU 7
|
|
error_I24_sector_not_found EQU 8
|
|
error_I24_out_of_paper EQU 9
|
|
error_I24_write_fault EQU 0Ah
|
|
error_I24_read_fault EQU 0Bh
|
|
error_I24_gen_failure EQU 0Ch
|
|
; NOTE: Code 0Dh is used by MT-DOS.
|
|
error_I24_wrong_disk EQU 0Fh
|
|
|
|
; THE FOLLOWING ARE MASKS FOR THE AH REGISTER ON Int 24h
|
|
|
|
Allowed_FAIL EQU 00001000b
|
|
Allowed_RETRY EQU 00010000b
|
|
Allowed_IGNORE EQU 00100000b
|
|
|
|
;NOTE: ABORT is ALWAYS allowed
|
|
|
|
I24_operation EQU 00000001b ;Z if READ,NZ if Write
|
|
I24_area EQU 00000110b ; 00 if DOS
|
|
; 01 if FAT
|
|
; 10 if root DIR
|
|
DataBegin
|
|
|
|
externB SysErr
|
|
externB msgWriteProtect
|
|
externB drvlet1
|
|
externB msgCannotReadDrv
|
|
externB drvlet2
|
|
externB msgCannotWriteDrv
|
|
externB drvlet3
|
|
externB msgShare
|
|
externB drvlet4
|
|
externB msgNetError
|
|
externB drvlet5
|
|
externB msgCannotReadDev
|
|
externB devenam1
|
|
externB msgCannotWriteDev
|
|
externB devenam2
|
|
externB devenam3
|
|
externB msgNetErrorDev
|
|
externB msgNoPrinter
|
|
externB OutBuf
|
|
externB Kernel_Flags
|
|
externB Kernel_InDOS
|
|
externB Kernel_InINT24
|
|
externB InScheduler
|
|
externB cdevat
|
|
externB errcap
|
|
externB fNovell
|
|
externB fDW_Int21h
|
|
externW pGlobalHeap
|
|
externW CurTDB
|
|
;externW MyCSDS
|
|
externW LastExtendedError
|
|
if 0; EarleH
|
|
externW LastCriticalError
|
|
endif ; 0
|
|
externD pSErrProc
|
|
externD InDOS
|
|
|
|
fDialogShown db 0 ; NZ if end user sees dialog box
|
|
|
|
if ROM
|
|
externD prevInt21Proc
|
|
endif
|
|
|
|
DataEnd
|
|
|
|
INT24STACK STRUC
|
|
Int24_IP dw ?
|
|
Int24_CS dw ?
|
|
Int24_FG dw ?
|
|
Int24_AX dw ?
|
|
Int24_BX dw ?
|
|
Int24_CX dw ?
|
|
Int24_DX dw ?
|
|
Int24_SI dw ?
|
|
Int24_DI dw ?
|
|
Int24_BP dw ?
|
|
Int24_DS dw ?
|
|
Int24_ES dw ?
|
|
INT24STACK ENDS
|
|
|
|
|
|
sBegin code
|
|
assumes cs,code
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
ife ROM
|
|
externD prevInt21Proc
|
|
endif
|
|
|
|
externNP AppendFirst
|
|
externNP GetKernelDataSeg
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Int24Handler ;
|
|
; ;
|
|
; This is the default disk error handling code available to all ;
|
|
; users if they do not try to intercept interrupt 24h. ;
|
|
; The two options given the user are RETRY and FAIL. Retry goes back ;
|
|
; to DOS. If FAIL is chosen then for DOS 3.XX we return to DOS, but ;
|
|
; for DOS 2.XX we do the fail ourselves and return to the APP. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Tue Feb 03, 1987 10:10:09p -by- David N. Weise [davidw] ;
|
|
; Removed the poking around in DOS by using Kernel_InDOS. ;
|
|
; ;
|
|
; Tue Jan 27, 1987 07:58:56p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc Int24Handler,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
|
|
push ds
|
|
SetKernelDS
|
|
mov fDialogShown, 0 ; Assume no dialog box
|
|
inc InScheduler ; Prevent recursion
|
|
cmp InScheduler,1 ; Well are we?
|
|
jz NotInSched ; No, then handle this one
|
|
jmp ReturnError ; Yes, return abort
|
|
|
|
NotInSched:
|
|
mov Kernel_InINT24,1
|
|
FSTI
|
|
cld
|
|
push es
|
|
push dx
|
|
push cx
|
|
push bx
|
|
|
|
; Save away the return capabilities mask.
|
|
|
|
mov errcap,ah ; save the capabilities mask
|
|
push di
|
|
mov ds,bp
|
|
UnSetKernelDS
|
|
SetKernelDS es
|
|
mov cx,[si].devAttr
|
|
mov cdevat,ch
|
|
mov di,dataOffset devenam1
|
|
mov cx,8
|
|
add si,devName ; pull up device name (even on block)
|
|
push si
|
|
rep movsb
|
|
pop si
|
|
mov di,dataOffset devenam2
|
|
mov cl,8
|
|
push si
|
|
rep movsb
|
|
pop si
|
|
mov di,dataOffset devenam3
|
|
mov cl,8
|
|
rep movsb
|
|
pop di
|
|
|
|
SetKernelDS
|
|
UnSetKernelDS es
|
|
if 0; EarleH
|
|
mov LastCriticalError, di
|
|
endif
|
|
|
|
add al,'A' ; compute drive letter (even on character)
|
|
mov drvlet1,al
|
|
mov drvlet2,al
|
|
mov drvlet3,al
|
|
mov drvlet4,al
|
|
mov drvlet5,al
|
|
|
|
; At app exit time we will Ignore any critical errors. This is
|
|
; because errors that usually occur at app exit time are generally
|
|
; due to the network beeping death. Trying to put up the dialog
|
|
; hangs Windows because USER doesn't think the task exists any more.
|
|
; THIS IS AN INCREADABLE HACK!! We don'r really know if we can
|
|
; ignore all critical errors, but hey, nobodies complained yet.
|
|
|
|
test Kernel_flags[2],KF2_WIN_EXIT ; prevent int 24h dialogs
|
|
jz SetMsg
|
|
xor ax,ax
|
|
jmp eexit
|
|
|
|
SetMsg: test ah,1
|
|
jz ReadMes
|
|
|
|
WriteMes:
|
|
mov si,dataOffset msgCannotWriteDev
|
|
test cdevat,10000000b
|
|
jnz Gotmes
|
|
mov si,dataOffset msgCannotWriteDrv
|
|
jmps Gotmes
|
|
|
|
ReadMes:
|
|
mov si,dataOffset msgCannotReadDev
|
|
test cdevat,10000000b
|
|
jnz Gotmes
|
|
mov si,dataOffset msgCannotReadDrv
|
|
Gotmes:
|
|
|
|
; reach into DOS to get the extended error code
|
|
|
|
;;; les bx,InDOS
|
|
;;; mov ax,es:[bx].3
|
|
|
|
push es ; DOS may trash these...
|
|
push ds
|
|
push si
|
|
push di
|
|
xor bx, bx
|
|
mov ah, 59h
|
|
pushf
|
|
call prevInt21Proc
|
|
mov LastExtendedError, ax
|
|
mov LastExtendedError[2], bx
|
|
mov LastExtendedError[4], cx
|
|
pop di
|
|
pop si
|
|
pop ds
|
|
pop es
|
|
|
|
mov dx,dataOffset msgWriteProtect
|
|
cmp ax,error_write_protect
|
|
jz prmes ; Yes
|
|
mov dx,dataOffset msgNoPrinter
|
|
cmp al,error_out_of_paper
|
|
jz prmes ; Yes
|
|
mov dx,dataOffset msgShare
|
|
cmp al,error_sharing_violation
|
|
jz prmes ; Yes
|
|
cmp al,error_lock_violation
|
|
jz prmes ; Yes
|
|
mov dx,dataOffset msgNetError
|
|
test cdevat,10000000b
|
|
jz check_net_error
|
|
mov dx,dataOffset msgNetErrorDev
|
|
check_net_error:
|
|
cmp al,50
|
|
jb not_net_error
|
|
cmp al,80
|
|
ja not_net_error
|
|
test Kernel_Flags[2],KF2_APP_EXIT
|
|
jz prmes
|
|
jmps ReturnError
|
|
|
|
not_net_error:
|
|
|
|
mov dx,si ; Message in SI is correct
|
|
|
|
prmes: call AppendFirst ; print error type
|
|
|
|
mov es,curTDB ; Point to current task
|
|
mov ax,es:[TDB_errMode] ; See if wants default error processing
|
|
test al,1 ; Low-order bit = zero means
|
|
jz ask ; ...put up dialog box
|
|
mov al,2
|
|
jmps eexit ; <> 0 means return error from call
|
|
|
|
ask: mov es,pGlobalHeap
|
|
inc es:[hi_freeze] ; freeze global heap
|
|
call ShowDialogBox
|
|
mov fDialogShown, dl ; will be 0 if dialog box NOT shown
|
|
mov es,pGlobalHeap
|
|
dec es:[hi_freeze] ; thaw global heap
|
|
|
|
eexit: pop bx
|
|
pop cx
|
|
pop dx
|
|
pop es
|
|
cmp al,2 ; retry, ignore?
|
|
jb aexit ; yes, return to dos
|
|
|
|
cmp fNovell, 0
|
|
je ReturnError ; Not NOVELL
|
|
test errcap, Allowed_FAIL
|
|
jnz ReturnError ; We CAN fail, so we do.
|
|
push ax
|
|
mov ax, di
|
|
cmp al, 0Ch ; General failure
|
|
pop ax
|
|
jne ReturnError
|
|
cmp word ptr devenam1[0], 'EN'
|
|
jne ReturnError
|
|
cmp word ptr devenam1[2], 'WT'
|
|
jne ReturnError
|
|
cmp word ptr devenam1[4], 'RO'
|
|
jne ReturnError
|
|
cmp word ptr devenam1[6], 'K'
|
|
jne ReturnError
|
|
mov al, 2 ; ABORT because NOVELL doesn't like FAIL
|
|
jmps aexit
|
|
|
|
ReturnError:
|
|
mov al,3 ; change to return error code
|
|
|
|
; If the user canceled an error generated by the Int 21h to AUX: in kernel's
|
|
; DebugWrite routine, set a flag telling DebugWrite not to do that anymore.
|
|
|
|
cmp fDialogShown, 0 ; Did end user see dialog box?
|
|
jz not_krnl
|
|
cmp fDW_Int21h, 0 ; fDW_Int21h will == 0 if caused by
|
|
jnz not_krnl ; Int 21h/Write to AUX: in DebugWrite.
|
|
mov fDW_Int21h, 2 ; Prevent DebugWrite from trying again
|
|
not_krnl: ; (any value >= 2, <= 0FEh works)
|
|
|
|
aexit: mov Kernel_InINT24,0
|
|
dec InScheduler
|
|
pop ds
|
|
UnSetKernelDS ds
|
|
FSTI
|
|
iret
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; ShowDialogBox
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 02-Dec-1989 15:28:51 -by- David N. Weise [davidw]
|
|
; Removed the stack switching because of the new WinOldAp support,
|
|
; and added this nifty comment block.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc ShowDialogBox,<PUBLIC,NEAR>
|
|
|
|
cBegin nogen
|
|
|
|
CheckKernelDS
|
|
ReSetKernelDS
|
|
|
|
mov ax,3 ; assume no USER therefor CANCEL
|
|
xor dx, dx
|
|
cmp pSErrProc.sel,0 ; is there a USER yet?
|
|
jz sdb_exit
|
|
|
|
push bp
|
|
xor bp,bp
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
mov ax,dataOffset OutBuf ; lpText
|
|
push ax
|
|
push ds
|
|
mov ax,dataOffset SysErr ; lpCaption
|
|
push ax
|
|
|
|
; Set up the buttons based on the capabilities mask. Cancel is always
|
|
; availible. Retry and Ignore are not always available.
|
|
|
|
mov ax,SEB_CANCEL+SEB_DEFBUTTON ; cancel is always allowed
|
|
push ax
|
|
xor ax,ax ; assume no second button
|
|
if 0 ; 05 feb 1990, ignoring is not user friendly, win 2.x did not allow it
|
|
test errcap,20h ; is ignore allowed?
|
|
jz button_2
|
|
mov ax,SEB_IGNORE ; ignore is the second button
|
|
endif
|
|
|
|
button_2:
|
|
push ax
|
|
|
|
xor ax,ax ; assume no third button
|
|
test errcap,10h ; is retry allowed?
|
|
jz button_3
|
|
mov ax,SEB_RETRY ; retry is the third button
|
|
button_3:
|
|
push ax
|
|
dobox:
|
|
call [pSErrProc] ; USER.SysErrorBox()
|
|
mov dx, ax
|
|
|
|
; We need to map the return as follows:
|
|
; button 1 (Cancel) => 3 3
|
|
; button 2 (Retry) => 1 0
|
|
; button 3 (Ignore) => 0 1
|
|
|
|
sub al,2
|
|
jnb codeok
|
|
mov al,3
|
|
codeok:
|
|
pop bp
|
|
pop bp
|
|
sdb_exit:
|
|
ret
|
|
|
|
cEnd nogen
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GetLPErrMode ;
|
|
; ;
|
|
; This routine returns a long pointer to the Kernel_InDOS and ;
|
|
; Kernel_InINT24 bytes inside the KERNEL. It is used by 386 WINOLDAP ;
|
|
; to prevent switching while inside INT 24 errors from other VMs. ;
|
|
; ;
|
|
; NOTE: Do not change this call without talking to the WIN/386 group. ;
|
|
; NOTE: USER also uses this call to determine whether PostMessage ;
|
|
; can call FatalExit. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; none ;
|
|
; ;
|
|
; Returns: ;
|
|
; DX:AX = pointer to Kernel_InDOS followed by Kernel_InINT24 ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; all ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Tue Jan 27, 1987 07:13:27p -by- David N. Weise [davidw] ;
|
|
; Rewrote it and added this nifty comment block. ;
|
|
; ;
|
|
; 7/23/87 -by- Arron Reynolds [aaronr], updated comments to desired ;
|
|
; state. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GetLPErrMode,<PUBLIC,FAR>
|
|
cBegin nogen
|
|
call GetKernelDataSeg
|
|
mov dx, ax
|
|
mov ax,dataOffset Kernel_InDOS
|
|
ret
|
|
cEnd nogen
|
|
|
|
sEnd code
|
|
|
|
end
|