680 lines
20 KiB
NASM
680 lines
20 KiB
NASM
|
|
|
|
.xlist
|
|
include kernel.inc
|
|
include pdb.inc
|
|
include tdb.inc
|
|
include newexe.inc
|
|
include eems.inc
|
|
ifdef WOW
|
|
include vint.inc
|
|
endif
|
|
.list
|
|
|
|
externFP KillLibraries
|
|
ifndef WOW
|
|
externFP WriteOutProfiles
|
|
endif
|
|
|
|
DataBegin
|
|
|
|
externB PhantArray
|
|
externB kernel_flags
|
|
externB fBreak
|
|
externB fInt21
|
|
ifndef WOW
|
|
externB fProfileMaybeStale
|
|
endif
|
|
externW curTDB
|
|
externW headPDB
|
|
externW topPDB
|
|
ife PMODE32
|
|
externW hXMMHeap
|
|
endif
|
|
externD lpInt21
|
|
externD pSftLink
|
|
externD lpWinSftLink
|
|
externD pSysProc
|
|
externD pMouseTermProc
|
|
externD pKeyboardTermProc
|
|
externD pSystemTermProc
|
|
externW MyCSAlias
|
|
|
|
externD myInt2F
|
|
|
|
if ROM
|
|
externD prevInt00Proc
|
|
externD prevInt21Proc
|
|
externD prevInt24Proc
|
|
externD prevInt2FProc
|
|
externD prevInt3FProc
|
|
externD prevInt67Proc
|
|
externD prevInt02Proc
|
|
externD prevInt04Proc
|
|
externD prevInt06Proc
|
|
externD prevInt07Proc
|
|
externD prevInt3EProc
|
|
externD prevInt75Proc
|
|
externD prevInt0CProc
|
|
externD prevInt0DProc
|
|
externD prevIntx6Proc
|
|
externD prevInt0EProc
|
|
endif
|
|
|
|
DataEnd
|
|
|
|
sBegin CODE
|
|
assumes CS,CODE
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
ife ROM
|
|
externD prevInt00Proc
|
|
externD prevInt21Proc
|
|
externD prevInt24Proc
|
|
externD prevInt2FProc
|
|
externD prevInt3FProc
|
|
externD prevInt67Proc
|
|
externD prevInt02Proc
|
|
externD prevInt04Proc
|
|
externD prevInt06Proc
|
|
externD prevInt07Proc
|
|
externD prevInt3EProc
|
|
externD prevInt75Proc
|
|
externD prevInt0CProc
|
|
externD prevInt0DProc
|
|
externD prevIntx6Proc
|
|
externD prevInt0EProc
|
|
ifdef WOW
|
|
externD prevInt01proc
|
|
externD prevInt03proc
|
|
externD oldInt00proc
|
|
endif
|
|
endif
|
|
|
|
|
|
if ROM
|
|
externFP PrevROMInt21Proc
|
|
endif
|
|
|
|
externNP real_DOS
|
|
externNP Enter_gmove_stack
|
|
externNP TerminatePDB
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; InternalEnableDOS
|
|
;
|
|
;
|
|
; Entry:
|
|
; none
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Thu 21-Sep-1989 20:44:48 -by- David N. Weise [davidw]
|
|
; Added this nifty comment block.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
SetWinVec MACRO vec
|
|
externFP Int&vec&Handler
|
|
mov dx, codeoffset Int&vec&Handler
|
|
mov ax, 25&vec&h
|
|
pushf
|
|
if ROM
|
|
call PrevROMInt21Proc
|
|
else
|
|
call prevInt21Proc
|
|
endif
|
|
endm
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc InternalEnableDOS,<PUBLIC,FAR>
|
|
cBegin nogen
|
|
|
|
push si
|
|
push ds
|
|
SetKernelDS
|
|
|
|
mov al,1
|
|
xchg al,fInt21 ; set hook count to 1
|
|
or al,al ; was it zero?
|
|
jz @f
|
|
jmp ena21 ; no, just leave
|
|
@@:
|
|
|
|
; now link back nodes to SFT if kernel had done it before. InternalDisableDOS
|
|
; saves the link in the DWORD variable lpWinSftLink. If this variable is NULL
|
|
; then either this is the first time InternalEnableDOS is being called or
|
|
; else the SFT had not been grown.
|
|
|
|
cmp lpWinSftLink.sel,0 ;was it allocated ?
|
|
jz @f ;no.
|
|
push ds ;save
|
|
mov cx,lpWinSftLink.sel ;get the selector
|
|
mov dx,lpWinSftLink.off ;get the offset
|
|
lds bx,[pSftLink] ;place where we hooked new entry
|
|
mov word ptr ds:[bx][0],dx ;restore offset
|
|
mov word ptr ds:[bx][2],cx ;restore segment
|
|
pop ds ;restore data segment
|
|
@@:
|
|
|
|
|
|
; WARNING!! The ^C setting diddle MUST BE FIRST IN HERE......
|
|
; If you do some other INT 21 call before this you will have
|
|
; a "^C window", so don't do it....
|
|
|
|
mov ax,3301h ; disable ^C checking
|
|
mov dl,0
|
|
call real_DOS
|
|
|
|
mov bx,TopPDB
|
|
mov ah,50h
|
|
call real_DOS ; This way, or TDB_PDB gets set wrong
|
|
|
|
ifndef WOW
|
|
ends1: mov ah,6 ; clean out any pending keys
|
|
mov dl,0FFh
|
|
call real_DOS
|
|
jnz ends1
|
|
endif
|
|
|
|
mov es,curTDB
|
|
mov bx,es:[TDB_PDB]
|
|
mov ah,50h
|
|
int 21h
|
|
|
|
push ds
|
|
lds dx,myInt2F
|
|
mov ax,252Fh
|
|
int 21h
|
|
|
|
smov ds,cs ; Pick up executable sel/seg
|
|
UnSetKernelDS
|
|
SetWinVec 24
|
|
SetWinVec 00
|
|
SetWinVec 02
|
|
SetWinVec 04
|
|
SetWinVec 06
|
|
SetWinVec 07
|
|
SetWinVec 3E
|
|
SetWinVec 75
|
|
pop ds
|
|
ReSetKernelDS
|
|
|
|
mov bx,2 ; 2 = Enable/Disable one drive logic
|
|
xor ax,ax ; FALSE = Disable
|
|
cCall [pSysProc],<bx,ax> ; NOTE: destroys ES if DOS < 3.20
|
|
|
|
; Set up the PhantArray by calling inquire system for each drive letter
|
|
|
|
mov bx,dataOffset PhantArray + 25 ; Array index
|
|
mov cx,26 ; Drive #
|
|
SetPhant:
|
|
dec cx
|
|
push cx
|
|
push bx
|
|
mov dx,1 ; InquireSystem
|
|
cCall [pSysProc],<dx,cx>
|
|
pop bx
|
|
pop cx
|
|
mov byte ptr [bx],0 ; Assume not Phantom
|
|
cmp ax,2
|
|
jae NotPhant ; Assumption correct
|
|
; or dx,dx ; Drive just invalid?
|
|
; jz NotPhant ; Yes, assumption correct
|
|
mov byte ptr [bx],dl ; Drive is phantom
|
|
NotPhant:
|
|
dec bx ; Next array element
|
|
jcxz phant_done
|
|
jmp SetPhant
|
|
phant_done:
|
|
|
|
lds dx,lpInt21
|
|
UnSetKernelDS
|
|
mov ax,2521h
|
|
int 21h
|
|
ena21:
|
|
pop ds
|
|
pop si
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; InternalDisableDOS ;
|
|
; ;
|
|
; ;
|
|
; Arguments: ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Mon Oct 16, 1989 11:04:50 -by- Amit Chatterjee [amitc] ;
|
|
; InternalDisableDOS now takes away any nodes that kernel would have ;
|
|
; added to the SFT. InternalEnableDOS puts the nodes backs. Previously ;
|
|
; the delinking was done by DisableKernel, but no one linked it back! ;
|
|
; ;
|
|
; Sat May 09, 1987 02:00:52p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
; ;
|
|
; Thu Apr 16, 1987 11:32:00p -by- Raymond E. Ozzie [-iris-] ;
|
|
; Changed InternalDisableDOS to use real dos for 52h function, since ;
|
|
; DosTrap3 doesn't have 52h defined and PassOnThrough will croak if the ;
|
|
; current TDB's signature is 0, as it is during exit after the last ;
|
|
; task has been deleted. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
ReSetDOSVec MACRO vec
|
|
lds dx,PrevInt&vec&proc
|
|
mov ax,25&vec&h
|
|
int 21h
|
|
endm
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc InternalDisableDOS,<PUBLIC,FAR>
|
|
cBegin
|
|
SetKernelDS es
|
|
xor ax,ax
|
|
xchg al,fInt21 ; set hook count to zero
|
|
or al,al ; was it non zero?
|
|
jnz @F
|
|
jmp dis21 ; no, just leave
|
|
@@:
|
|
mov bx,2 ; 2 = Enable/Disable one drive logic
|
|
mov ax,1 ; TRUE = Enable
|
|
push es
|
|
cCall pSysProc,<bx,ax>
|
|
pop es
|
|
|
|
mov ax,3301h ; disable ^C checking
|
|
mov dl,0
|
|
pushf
|
|
ife PMODE32
|
|
FCLI
|
|
endif
|
|
call [prevInt21Proc]
|
|
|
|
mov ax,2521h
|
|
lds dx,prevInt21Proc
|
|
pushf
|
|
ife PMODE32
|
|
FCLI
|
|
endif
|
|
call [prevInt21Proc]
|
|
|
|
push es
|
|
mov ax,352Fh
|
|
int 21h
|
|
mov ax,es
|
|
pop es
|
|
mov myInt2F.sel,ax
|
|
mov myInt2F.off,bx
|
|
|
|
ReSetDOSVec 00 ; as a favor in win2 we restored this
|
|
ReSetDOSVec 24
|
|
ReSetDOSVec 2F
|
|
ReSetDOSVec 02
|
|
ReSetDOSVec 04
|
|
ReSetDOSVec 06
|
|
ReSetDOSVec 07
|
|
ReSetDOSVec 3E
|
|
ReSetDOSVec 75
|
|
|
|
mov dl,fBreak ; return state of ^C checking
|
|
mov ax,3301h
|
|
int 21h
|
|
|
|
dis21:
|
|
cEnd
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; Ancient WinOldAp hook.
|
|
;
|
|
;------------------------------------------------------------------
|
|
public EnableDOS
|
|
|
|
EnableDOS Label Byte
|
|
if kdebug
|
|
krDebugOut DEB_WARN, "Don't call EnableDOS"
|
|
endif
|
|
retf
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; Ancient WinOldAp hook.
|
|
;
|
|
;------------------------------------------------------------------
|
|
public DisableDOS
|
|
|
|
DisableDOS Label Byte
|
|
if kdebug
|
|
krDebugOut DEB_WARN, "Don't call DisableDOS"
|
|
endif
|
|
retf
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; Ancient WinOldAp hook.
|
|
;
|
|
;------------------------------------------------------------------
|
|
public EnableKernel
|
|
|
|
EnableKernel Label Byte
|
|
if kdebug
|
|
krDebugOut DEB_WARN, "Don't call EnableKernel"
|
|
endif
|
|
retf
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; DisableKernel ;
|
|
; ;
|
|
; This call is provided as a Kernel service to applications that ;
|
|
; wish to totally unhook Windows in order to do something radical ;
|
|
; such as save the state of the world and restore it at a later ;
|
|
; time. This is similar in many ways to the way OLDAPP support ;
|
|
; works, with the addition that it also unhooks the kernel. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; DI,SI,DS ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Sat May 09, 1987 02:34:35p -by- David N. Weise [davidw] ;
|
|
; Merged changes in. Most of this came from ExitKernel. ;
|
|
; ;
|
|
; Tue Apr 28, 1987 11:12:00a -by- R.E.O. SpeedWagon [-????-] ;
|
|
; Changed to indirect thru PDB to get JFN under DOS 3.x. ;
|
|
; ;
|
|
; Mon Apr 20, 1987 11:34:00p -by- R.E.O. SpeedWagon [-????-] ;
|
|
; Set PDB to topPDB before final int 21/4C; we were sometimes exiting ;
|
|
; with a task's PDB, and thus we came back to ExitCall2 instead of ;
|
|
; going back to DOS! ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc DisableKernel,<PUBLIC,FAR>,<si,di>
|
|
cBegin
|
|
|
|
SetKernelDS
|
|
or Kernel_flags[2],KF2_WIN_EXIT ; prevent int 24h dialogs
|
|
cmp prevInt21Proc.sel,0
|
|
je nodisable
|
|
call InternalDisableDOS
|
|
nodisable:
|
|
|
|
SetKernelDS
|
|
mov ax,0203h ; Reset not present fault.
|
|
mov bl,0Bh
|
|
mov cx,prevInt3Fproc.sel
|
|
mov dx,prevInt3Fproc.off
|
|
int 31h
|
|
|
|
mov ax,0203h ; Reset stack fault.
|
|
mov bl,0Ch
|
|
mov cx,prevInt0Cproc.sel
|
|
mov dx,prevInt0Cproc.off
|
|
int 31h
|
|
|
|
mov ax,0203h ; Reset GP fault.
|
|
mov bl,0Dh
|
|
mov cx,prevInt0Dproc.sel
|
|
mov dx,prevInt0Dproc.off
|
|
int 31h
|
|
|
|
mov ax,0203h ; Reset invalid op-code exception.
|
|
mov bl,06h
|
|
mov cx,prevIntx6proc.sel
|
|
mov dx,prevIntx6proc.off
|
|
int 31h
|
|
|
|
mov ax,0203h ; Reset page fault.
|
|
mov bl,0Eh
|
|
mov cx,prevInt0Eproc.sel
|
|
mov dx,prevInt0Eproc.off
|
|
int 31h
|
|
|
|
ifdef WOW
|
|
mov ax,0203h ; Reset divide overflow traps
|
|
mov bl,00h
|
|
mov cx,oldInt00proc.sel
|
|
mov dx,oldInt00proc.off
|
|
int 31h
|
|
|
|
mov ax,0203h ; Reset single step traps
|
|
mov bl,01h
|
|
mov cx,prevInt01proc.sel
|
|
mov dx,prevInt01proc.off
|
|
int 31h
|
|
|
|
mov ax,0203h ; Reset breakpoint traps
|
|
mov bl,03h
|
|
mov cx,prevInt03proc.sel
|
|
mov dx,prevInt03proc.off
|
|
int 31h
|
|
endif
|
|
|
|
mov dx, [HeadPDB]
|
|
SetKernelDS es
|
|
UnSetKernelDS
|
|
exk1:
|
|
mov ds,dx
|
|
cmp dx, [topPDB] ; Skip KERNEL, he is about to get
|
|
je exk3 ; a 4C stuffed down his throat
|
|
|
|
push ds
|
|
call TerminatePDB
|
|
pop ds
|
|
|
|
exk3:
|
|
mov dx,ds:[PDB_Chain] ; move to next PDB in chain
|
|
or dx,dx
|
|
jnz exk1
|
|
|
|
mov bx,[topPDB] ; set to initial DOS task PDB
|
|
mov ah,50h ; set PDB function
|
|
int 21h
|
|
and Kernel_flags[2],NOT KF2_WIN_EXIT ; prevent int 24h dialogs
|
|
;
|
|
; Close all files on Kernel's PSP, 'cause we're gonna shrink the SFT and
|
|
; quit ourselves afterwards.
|
|
;
|
|
mov ds,[topPDB]
|
|
mov cx,ds:[PDB_JFN_Length]
|
|
exk4: mov bx,cx ; close all file handles
|
|
dec bx
|
|
cmp bx,5 ; console-related handle?
|
|
jb exk5 ; yup, don't close it (AUX, etc.)
|
|
mov ah,3eh
|
|
int 21h
|
|
exk5: loop exk4
|
|
|
|
; kernel could have added some nodes to the SFT. Delink them by removing
|
|
; the link from the last DOS link in the chain. We need to remember the
|
|
; current pointer there so that InternalEnableDOS can put it back.
|
|
|
|
lds bx,[pSftLink] ;place where we hooked new entry
|
|
assumes ds,nothing
|
|
mov cx,ds ;this could have been unitialized too
|
|
jcxz exk6 ;if unitialized, nothing to do
|
|
mov dx,ds:[bx].off ;get the current offset
|
|
mov cx,ds:[bx].sel ;get the current segment
|
|
mov ds:[bx].off,-1 ;remove windows SFT link
|
|
mov ds:[bx].sel, 0 ;remove windows SFT link
|
|
mov lpWinSftLink.off,dx ;save the offset
|
|
mov lpWinSftLink.sel,cx ;save the segment
|
|
exk6:
|
|
|
|
UnSetKernelDS es
|
|
cEnd
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; ExitKernel -- Bye, bye.
|
|
;
|
|
;------------------------------------------------------------------
|
|
ifndef WOW ; If we are closing down WOW then we don't want to go back to the DOS Prompt
|
|
; We want to kill the NTVDM WOW Process - so we don't need/want this code.
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc ExitKernel,<PUBLIC,FAR>
|
|
; parmW exitcode
|
|
cBegin nogen
|
|
SetKernelDS
|
|
or Kernel_flags[2],KF2_WIN_EXIT ; prevent int 24h dialogs
|
|
call KillLibraries ; Tell DLLs that the system is exiting
|
|
|
|
mov si,sp
|
|
mov si,ss:[si+4] ; get exit code
|
|
|
|
; Call driver termination procs, just to make sure that they have removed
|
|
; their interrupt vectors.
|
|
|
|
push si
|
|
mov ax,word ptr [pMouseTermProc]
|
|
or ax,word ptr [pMouseTermProc+2]
|
|
jz trm0
|
|
call [pMouseTermProc]
|
|
CheckKernelDS
|
|
trm0: mov ax,word ptr [pKeyboardTermProc]
|
|
or ax,word ptr [pKeyboardTermProc+2]
|
|
jz trm1
|
|
call [pKeyboardTermProc]
|
|
CheckKernelDS
|
|
trm1: mov ax,word ptr [pSystemTermProc]
|
|
or ax,word ptr [pSystemTermProc+2]
|
|
jz trm2
|
|
call [pSystemTermProc]
|
|
CheckKernelDS
|
|
trm2: pop si
|
|
|
|
call WriteOutProfiles
|
|
mov fProfileMaybeStale,1 ; Make sure we check the
|
|
; INI file next time around
|
|
;;; cCall CloseCachedFiles,<topPDB>
|
|
|
|
; Close open files and unhook kernel hooks
|
|
|
|
; get on a stack that's not in EMS land
|
|
|
|
call Enter_gmove_stack
|
|
|
|
cCall DisableKernel
|
|
CheckKernelDS
|
|
|
|
cmp si,EW_REBOOTSYSTEM ; Reboot windows?
|
|
jnz exitToDos
|
|
|
|
ifndef WOW
|
|
if PMODE32
|
|
mov ax,1600h
|
|
int 2Fh
|
|
test al,7Fh
|
|
jz NotRunningEnhancedMode
|
|
cmp al,1
|
|
je exitToDos ;RunningWindows3862x
|
|
cmp al,-1
|
|
je exitToDos ;RunningWindows3862x
|
|
xor di,di ; Zero return regs
|
|
mov es,di
|
|
mov bx,0009h ; Reboot device ID
|
|
mov ax,1684h ; Get device API entry point
|
|
int 2Fh
|
|
mov ax,es
|
|
or ax,di
|
|
jz exitToDos ; Reboot vxd not loaded. Exit to dos
|
|
|
|
; Call the reboot function
|
|
mov ax,0100h
|
|
push es
|
|
push di
|
|
mov bx,sp
|
|
call DWORD PTR ss:[bx]
|
|
|
|
jmp short exitToDos ; Reboot didn't work just exit to dos
|
|
|
|
NotRunningEnhancedMode:
|
|
endif
|
|
endif ; WOW
|
|
|
|
mov ah, 0Dh ; Disk Reset so that Smartdrv etc buffers
|
|
int 21h ; are written to disk
|
|
|
|
mov ax, 0FE03h ; Flush Norton NCache
|
|
mov si, "CF"
|
|
mov di, "NU"
|
|
stc ; Yes! Really set carry too!
|
|
int 2Fh
|
|
|
|
ifdef NEC_98
|
|
mov al,92h
|
|
out 37h,al
|
|
mov al,07h
|
|
out 37h,al
|
|
mov al,0bh
|
|
out 37h,al
|
|
mov al,0fh
|
|
out 37h,al
|
|
mov al,08h
|
|
out 37h,al
|
|
out 50h,al
|
|
|
|
mov al,05h
|
|
out 0a2h,al ; graph off
|
|
out 62h,al ; text off
|
|
|
|
xor cx, cx
|
|
loop $
|
|
loop $
|
|
loop $
|
|
loop $
|
|
mov al, 00h
|
|
out 0f0h, al ; CPU Reset
|
|
jmp $
|
|
else ; NEC_98
|
|
int 19h ; Reboot via int 19h
|
|
endif ; NEC_98
|
|
|
|
|
|
exitToDos:
|
|
mov ax,si
|
|
mov ah,4Ch ; Leave Windows.
|
|
int 21h
|
|
cEnd nogen
|
|
|
|
endif ; NOT WOW
|
|
|
|
sEnd CODE
|
|
|
|
end
|