1332 lines
32 KiB
NASM
1332 lines
32 KiB
NASM
title DOSINIT - Initialize dos specific static data.
|
|
|
|
.xlist
|
|
include kernel.inc
|
|
include pdb.inc
|
|
.list
|
|
|
|
externFP GetModuleHandle
|
|
externFP GetProcAddress
|
|
externFP Int21Handler
|
|
externFP GlobalDOSAlloc
|
|
externFP GetFreeSpace
|
|
ifdef FE_SB
|
|
externFP GetSystemDefaultLangID
|
|
endif ;FE_SB
|
|
ifdef WOW
|
|
externNP ExitKernel
|
|
endif
|
|
|
|
DataBegin
|
|
|
|
externB graphics
|
|
externB Kernel_flags
|
|
externB DOS_version
|
|
externB DOS_revision
|
|
externB KeyInfo
|
|
externB fFarEast
|
|
ifdef FE_SB
|
|
externB fDBCSLeadTable
|
|
externB DBCSVectorTable
|
|
endif ;FE_SB
|
|
externB fBreak
|
|
externB fNovell
|
|
externB CurDOSDrive
|
|
externB DOSDrives
|
|
externW cur_dos_PDB
|
|
externW Win_PDB
|
|
externW f8087
|
|
externW FileEntrySize
|
|
externW topPDB
|
|
externW headPDB
|
|
externW hExeHead
|
|
externW MyCSDS
|
|
externW hGDI
|
|
externW hUser
|
|
externD pTimerProc
|
|
externD pSftLink
|
|
externD pFileTable
|
|
externD myInt2F
|
|
externD pMBoxProc
|
|
externD pSysProc
|
|
externD pGetFreeSystemResources
|
|
externD plstrcmp
|
|
ifdef JAPAN
|
|
externD pJpnSysProc
|
|
endif
|
|
externD pKeyProc
|
|
externD pKeyProc1
|
|
externD pSErrProc
|
|
externD pDisableProc
|
|
externD pExitProc
|
|
|
|
externD pMouseTermProc
|
|
externD pKeyboardTermProc
|
|
externD pKeyboardSysReq
|
|
externD pSystemTermProc
|
|
externD pDisplayCritSec
|
|
externD pUserInitDone
|
|
externD pPostMessage
|
|
externD pSignalProc
|
|
externD pIsUserIdle
|
|
externD pUserGetFocus
|
|
externD pUserGetWinTask
|
|
externD pUserIsWindow
|
|
externD curDTA
|
|
externD InDOS
|
|
|
|
if ROM
|
|
externD pYieldProc
|
|
externD pStringFunc
|
|
externD prevInt21Proc
|
|
externD prevInt00proc
|
|
externD prevInt24Proc
|
|
externD prevInt2FProc
|
|
externD prevInt02proc
|
|
externD prevInt04proc
|
|
externD prevInt06proc
|
|
externD prevInt07proc
|
|
externD prevInt3Eproc
|
|
externD prevInt75proc
|
|
endif
|
|
|
|
ifdef JAPAN
|
|
; Need this variable in order to make Kernel to hardware independent
|
|
externW WinFlags
|
|
endif
|
|
|
|
DataEnd
|
|
|
|
DataBegin INIT
|
|
|
|
; Win.com does version check, so this does not need to be internationalized.
|
|
|
|
externB szDosVer
|
|
;msg0 DB 'Incorrect DOS version: DOS 3.1 or greater required.',13,10,'$'
|
|
|
|
handles dw 10 dup(0)
|
|
|
|
find_string db 'CON '
|
|
name_string db 'CON',0
|
|
|
|
DataEnd INIT
|
|
|
|
|
|
sBegin CODE
|
|
assumes cs,CODE
|
|
|
|
ife ROM
|
|
externD pYieldProc
|
|
externD pStringFunc
|
|
externD prevInt21Proc
|
|
externD prevInt00proc
|
|
externD prevInt24Proc
|
|
externD prevInt2FProc
|
|
externD prevInt02proc
|
|
externD prevInt04proc
|
|
externD prevInt06proc
|
|
externD prevInt07proc
|
|
externD prevInt3Eproc
|
|
externD prevInt75proc
|
|
ifdef WOW
|
|
externD prevInt31proc
|
|
endif
|
|
endif
|
|
|
|
sEnd CODE
|
|
|
|
externNP DebugSysReq
|
|
externNP SetOwner
|
|
|
|
;----------------------------------------------------------------------------;
|
|
; define any constans used in the file. ;
|
|
;----------------------------------------------------------------------------;
|
|
|
|
SFT_GROW_LIM_IN_64K equ 8 ;if memory < 8*64k, grow to 100 handles
|
|
;else grow upto 127 handles
|
|
SFT_HIGH_LIM equ 127 ;grow upto 127 when enough memory
|
|
SFT_LOW_LIM equ 100 ;grow upto 100 when low in memory
|
|
|
|
|
|
;----------------------------------------------------------------------------;
|
|
; define any macros used in the file. ;
|
|
;----------------------------------------------------------------------------;
|
|
|
|
SaveVec MACRO vec
|
|
mov ax,35&vec&h
|
|
pushf
|
|
call prevInt21proc
|
|
if ROM
|
|
mov prevInt&vec&proc.off,bx
|
|
mov prevInt&vec&proc.sel,es
|
|
else
|
|
mov ax,codeOffset prevInt&vec&proc
|
|
SetKernelCSDword ax,es,bx
|
|
endif
|
|
ENDM
|
|
|
|
;----------------------------------------------------------------------------;
|
|
|
|
DataBegin INIT
|
|
|
|
sysmodstr DB 'SYSTEM',0
|
|
keymodstr DB 'KEYBOARD',0
|
|
displaymodstr DB 'DISPLAY',0
|
|
mousemodstr DB 'MOUSE',0
|
|
gdimodstr DB 'GDI',0
|
|
usermodstr DB 'USER',0
|
|
|
|
inqprocstr label byte
|
|
msgprocstr label byte ; MessageBox in USER
|
|
sysprocstr DB '#1',0 ; sysprocstr = InquireSystem
|
|
timerprocstr DB '#2',0 ; timerprocstr = CreateSystemTimer
|
|
keydisstr label byte ; keydisstr = DisableKeyboard
|
|
mousedisstr DB '#3',0 ; mouseprocstr = DisableMouse
|
|
disprocstr DB '#4',0 ; DisableOEMLayer in USER
|
|
extprocstr label byte ; ExitWindows in USER
|
|
coprocessor DB '#7',0 ; Get80x87SaveSize in system
|
|
kbdfocus DB '#23',0 ; GetFocus in USER
|
|
wintask DB '#224',0 ; GetWindowTask in USER
|
|
iswindow DB '#47',0 ; IsWindow in USER
|
|
signalproc DB '#314',0 ; SignalProc in user
|
|
isuseridle DB '#333',0 ; IsUserIdle in user
|
|
getfreesysrsc DB '#284',0 ; GetFreeSystemResources in user
|
|
userlstrcmp DB '#430',0 ; lstrcmp in user
|
|
stringfunc DB '#470',0 ; StringFunc in User.
|
|
|
|
sysdisstr DB '#5',0 ; sysdisstr = DisableSystemTimers
|
|
pmprocstr DB '#110',0 ; pmprocstr = PostMessage
|
|
keysysreq DB '#136',0 ; keysysreq = EnableKBSysReq
|
|
syserrorstr DB '#320',0 ; syserrorstr = SysErrorBox in USER
|
|
yldprocstr DB '#332',0 ; yldprocstr = UserYield in USER
|
|
udnprocstr DB '#400',0 ; tell user that initialization done
|
|
displaycrit DB '#500',0 ; win386 interaction craziness
|
|
ifdef JAPAN
|
|
jpnsysprocstr db 'JapanInquireSystem',0 ; Kernel.JapanInquireSystem entry
|
|
endif
|
|
|
|
DataEnd INIT
|
|
|
|
sBegin INITCODE
|
|
assumes CS,CODE
|
|
;-----------------------------------------------------------------------;
|
|
; InitFwdRef ;
|
|
; ;
|
|
; Initializes the far call pointers to SYSTEM, USER, KEYBOARD. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Tue Jan 06, 1987 04:21:13p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc InitFwdRef,<PUBLIC,NEAR>,<si,di>
|
|
cBegin
|
|
SetKernelDS
|
|
|
|
mov ax,352Fh
|
|
pushf
|
|
call prevInt21proc
|
|
mov myInt2F.sel,es
|
|
mov myInt2F.off,bx
|
|
|
|
; Save current Int 00h, 21h, 24h, and 2Fh.
|
|
|
|
SaveVec 00
|
|
;;; SaveVec 21
|
|
SaveVec 24
|
|
|
|
; Get address of procedures in USER and SYSTEM modules that we will need.
|
|
|
|
regptr pStr,ds,bx
|
|
|
|
mov bx,dataOffset sysmodstr
|
|
cCall GetModuleHandle,<pStr>
|
|
mov si,ax
|
|
|
|
mov bx,dataOffset sysprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov pSysProc.off,ax
|
|
mov pSysProc.sel,dx
|
|
|
|
ifdef JAPAN
|
|
mov bx,dataOffset jpnsysprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov pJpnSysProc.off,ax
|
|
mov pJpnSysProc.sel,dx
|
|
endif
|
|
|
|
mov bx,codeOffset ifr4
|
|
push cs ; push return address
|
|
push bx
|
|
mov bx,dataOffset coprocessor
|
|
cCall GetProcAddress,<si,pStr>
|
|
push dx
|
|
push ax ; push address to call
|
|
ret_far ; call 8087 info
|
|
ifr4:
|
|
mov f8087,ax
|
|
ifdef JAPAN
|
|
;;; int 1 ; debugging purpose only
|
|
; Since Japanese OEMs have non-IBM clone machines, Windows
|
|
; cannot use standard Bios interrupt to get system informations.
|
|
; In BootStrap (see LDBOOT.ASM), it uses Int 11h to obtain MCP's
|
|
; availability. However, Windows cannot use Int 11h (becase of
|
|
; IBM-dependant), MSKK has removed Int 11h from BootStrap.
|
|
;
|
|
; At this point, AX register contains MCP's availability, i.e.
|
|
; if AX has value zero, no MCP is installd. if AX has value except
|
|
; zero, MCP is installed. The following codes will update WinFlags
|
|
; and its exported variables by using AX register.
|
|
|
|
test ax,ax ; MCP is installed?
|
|
jz @F ; jump if not
|
|
mov ax,WF1_80x87 shl 8 ; set MCP present bit
|
|
@@:
|
|
or WinFlags,ax ; update internal variable
|
|
xor ax,ax
|
|
mov dx,178 ; #178 is __WinFlags location for public use
|
|
cCall GetProcAddress,<hExeHead,ax,dx>
|
|
mov ax,WinFlags
|
|
mov es:[bx],ax
|
|
endif
|
|
|
|
mov bx,dataOffset timerprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov pTimerProc.off,ax
|
|
mov pTimerProc.sel,dx
|
|
|
|
mov bx,dataOffset sysdisstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov pSystemTermProc.off,ax
|
|
mov pSystemTermProc.sel,dx
|
|
|
|
cmp graphics,0 ; Graphics?
|
|
jne grp
|
|
jmp nographics
|
|
|
|
grp:
|
|
ifndef WOW
|
|
mov bx,dataOffset displaymodstr ; display stuff
|
|
cCall GetModuleHandle,<pStr>
|
|
mov bx,dataOffset displaycrit
|
|
|
|
cCall GetProcAddress,<ax,pStr>
|
|
mov pDisplayCritSec.off,ax
|
|
mov pDisplayCritSec.sel,dx
|
|
|
|
mov bx,dataOffset mousemodstr ; mouse stuff
|
|
cCall GetModuleHandle,<pStr>
|
|
mov si,ax
|
|
|
|
mov bx,dataOffset mousedisstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov pMouseTermProc.off,ax
|
|
mov pMouseTermProc.sel,dx
|
|
endif
|
|
mov bx,dataOffset gdimodstr
|
|
cCall GetModuleHandle,<pStr>
|
|
mov hGDI,ax
|
|
|
|
mov bx,dataOffset usermodstr ; user stuff
|
|
cCall GetModuleHandle,<pStr>
|
|
mov hUser,ax
|
|
mov si,ax
|
|
|
|
mov bx,dataOffset msgprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov pMBoxProc.off,ax
|
|
mov pMBoxProc.sel,dx
|
|
|
|
mov bx,dataOffset syserrorstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pSErrProc[0],ax
|
|
mov word ptr pSErrProc[2],dx
|
|
|
|
mov bx,dataOffset extprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pExitProc[0],ax
|
|
mov word ptr pExitProc[2],dx
|
|
|
|
mov bx,dataOffset disprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pDisableProc[0],ax
|
|
mov word ptr pDisableProc[2],dx
|
|
|
|
mov bx,dataOffset yldprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
ife ROM
|
|
mov bx, codeOFFSET pYieldProc
|
|
SetKernelCSDword bx,dx,ax
|
|
else
|
|
mov pYieldProc.off,ax
|
|
mov pYieldProc.sel,dx
|
|
endif
|
|
|
|
mov bx,dataOffset udnprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pUserInitDone[0],ax
|
|
mov word ptr pUserInitDone[2],dx
|
|
|
|
mov bx,dataOffset pmprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pPostMessage[0],ax
|
|
mov word ptr pPostMessage[2],dx
|
|
|
|
mov bx,dataOffset signalproc
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pSignalProc[0],ax
|
|
mov word ptr pSignalProc[2],dx
|
|
|
|
; These are never called in WOW
|
|
|
|
ifndef WOW
|
|
mov bx,dataOffset isuseridle
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pIsUserIdle[0],ax
|
|
mov word ptr pIsUserIdle[2],dx
|
|
|
|
mov bx,dataOffset getfreesysrsc
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pGetFreeSystemResources[0],ax
|
|
mov word ptr pGetFreeSystemResources[2],dx
|
|
endif
|
|
|
|
mov bx,dataOffset userlstrcmp
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr plstrcmp[0],ax
|
|
mov word ptr plstrcmp[2],dx
|
|
|
|
mov bx,dataOffset stringfunc
|
|
cCall GetProcAddress,<si,pStr>
|
|
if ROM
|
|
mov pStringFunc.off,ax
|
|
mov pStringFunc.sel,dx
|
|
else
|
|
mov bx, codeOFFSET pStringFunc
|
|
SetKernelCSDword bx,dx,ax
|
|
endif
|
|
|
|
mov bx,dataOffset kbdfocus
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pUserGetFocus[0],ax
|
|
mov word ptr pUserGetFocus[2],dx
|
|
|
|
mov bx,dataOffset wintask
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pUserGetWinTask[0],ax
|
|
mov word ptr pUserGetWinTask[2],dx
|
|
|
|
mov bx,dataOffset iswindow
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr pUserIsWindow[0],ax
|
|
mov word ptr pUserISWindow[2],dx
|
|
|
|
mov bx,dataOffset keymodstr
|
|
cCall GetModuleHandle,<pStr>
|
|
mov si,ax
|
|
|
|
mov bx,dataOffset keydisstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov word ptr [pKeyboardTermProc],ax
|
|
mov word ptr [pKeyboardTermProc+2],dx
|
|
|
|
mov bx,dataOffset keysysreq
|
|
cCall GetProcAddress,<si,pStr>
|
|
mov pKeyboardSysReq.off,ax
|
|
mov pKeyboardSysReq.sel,dx
|
|
|
|
mov ax,4
|
|
cCall pKeyboardSysReq,<ax> ; tell kbd to pass SysReq to CVWBreak
|
|
|
|
mov bx,dataOffset KeyInfo
|
|
push ds
|
|
push bx ; push argument to keyboard.inquire
|
|
mov bx,codeOffset ifr1
|
|
push cs ; push return address
|
|
push bx
|
|
mov bx,dataOffset inqprocstr
|
|
cCall GetProcAddress,<si,pStr>
|
|
push dx
|
|
push ax ; push address to call
|
|
ret_far ; call keyboard inquire
|
|
ifr1:
|
|
ifndef JAPAN
|
|
; This is DBCS kernel. So do not get information from keyboard
|
|
; driver. This K/B spec is old one and should be ignored.
|
|
; We use DOS DBCS vector instead of K/B table.
|
|
; 071191 Yukini
|
|
;
|
|
;ifndef KOREA ;Korea might want to remove this too.
|
|
|
|
;!!!! Note to Taiwan developers !!!
|
|
; The following code fragment is necessary for those countries
|
|
; who want to run DBCS Windows on top of SBCS MS-DOS.
|
|
; For example, Taiwan might need this feature.
|
|
; Japan and Korea are safe to remove this fragment as Japanese
|
|
; and Hangeul Windows all assume DBCS MS-DOS.
|
|
|
|
mov si,dataOffset KeyInfo+KbRanges
|
|
lodsw
|
|
cmp al,ah
|
|
jbe ifr2
|
|
lodsw
|
|
cmp al,ah
|
|
ja ifr3
|
|
ifr2: inc fFarEast
|
|
ifdef FE_SB
|
|
;
|
|
; setup DBCS lead byte flag table after keyboard driver is loaded
|
|
;
|
|
mov di, dataOffset fDBCSLeadTable ; clear table before begin...
|
|
mov cx, 128
|
|
xor ax, ax
|
|
push es
|
|
push ds
|
|
pop es
|
|
cld
|
|
rep stosw
|
|
pop es
|
|
mov si, dataOffset KeyInfo+KbRanges
|
|
mov cx, 2
|
|
idr1:
|
|
lodsw ; fetch a DBCS lead byte range
|
|
cmp al, ah ; end of range info?
|
|
ja idr3 ; jump if so.
|
|
call SetDBCSVector
|
|
loop idr1 ; try another range
|
|
idr3:
|
|
endif ;FE_SB
|
|
endif ;NOT JAPAN
|
|
jmps ifr3
|
|
|
|
;
|
|
; Substitute dummy procs if user/gdi/keyboard/display not present
|
|
;
|
|
if 0
|
|
externFP <DummyKeyboardOEMToAnsi>
|
|
endif
|
|
externFP <OldYield>
|
|
nographics:
|
|
ife ROM
|
|
push di
|
|
push bx
|
|
if 0
|
|
mov bx, codeOffset pKeyProc
|
|
mov di, codeOffset DummyKeyboardOEMToAnsi
|
|
; SetKernelCSDword bx,cs,di
|
|
endif
|
|
mov bx, codeOffset pYieldProc
|
|
mov di, codeOffset OldYield
|
|
SetKernelCSDword bx,cs,di
|
|
pop bx
|
|
pop di
|
|
else
|
|
mov pYieldProc.off,codeOffset OldYield
|
|
mov pYieldProc.sel,cs
|
|
endif
|
|
ifr3:
|
|
call DebugSysReq
|
|
cEnd
|
|
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; InitDosVarP ;
|
|
; ;
|
|
; Records for future use various DOS variables. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; ES = PDB of Kernel ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX != 0 if successful ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; DI,SI,DS,ES ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; BX,CX,DX ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Mon 07-Aug-1989 23:50:20 -by- David N. Weise [davidw] ;
|
|
; Removed more dicking around by removing WinOldApp support. ;
|
|
; ;
|
|
; Tue Feb 03, 1987 10:45:31p -by- David N. Weise [davidw] ;
|
|
; Removed most of the dicking around the inside of DOS for variable ;
|
|
; locations. Variables are now got and set the right way: through DOS ;
|
|
; calls. This should allow Windows to run in the DOS 5 compatibility ;
|
|
; box as well as under future versions of real mode DOS. ;
|
|
; ;
|
|
; Tue Jan 06, 1987 04:33:16p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc InitDosVarP,<PUBLIC,NEAR>,<bx,cx,dx,si,di,es>
|
|
cBegin
|
|
|
|
ReSetKernelDS
|
|
|
|
; Save our PDB pointer in the code segment
|
|
|
|
mov ax,es
|
|
mov topPDB,ax
|
|
mov headPDB,ax
|
|
mov es:[PDB_Chain],0 ; the buck stops here
|
|
|
|
; record current PDB
|
|
|
|
mov cur_dos_PDB,ax
|
|
mov Win_PDB,ax
|
|
|
|
; record current DTA
|
|
|
|
mov curDTA.sel,ax
|
|
mov curDTA.off,80h
|
|
|
|
; disable ^C checking as fast as possible
|
|
|
|
mov ax,3300h ; remember ^C state
|
|
int 21h
|
|
mov fBreak,dl
|
|
|
|
mov ax,3301h ; disable ^C checking
|
|
mov dl,0
|
|
int 21h
|
|
|
|
; record in_dos pointer
|
|
|
|
mov ah,34h
|
|
int 21h
|
|
mov InDOS.sel,es
|
|
mov InDOS.off,bx
|
|
|
|
mov ah, 19h
|
|
int 21h
|
|
mov CurDOSDrive, al ; Initialize current drive tracking
|
|
mov dl, al
|
|
mov ah, 0Eh
|
|
int 21h
|
|
mov DOSDrives, al ; For returning from Select Disk calls
|
|
|
|
; To avoid beaucoup thought, let's init prevInt21Proc right now!
|
|
;
|
|
; This was done as a last minute hack to 2.10. I forget the
|
|
; motivation for it, other than it fixed a couple of bugs
|
|
; having to do with error recovery. It did introduce one
|
|
; bug with one error path having to do with Iris, but I don't
|
|
; remember that either. Interested parties can grep for
|
|
; prevInt21Proc and think hard and long.
|
|
;
|
|
; Since we now call through prevInt21Proc in many places rather
|
|
; than use int 21h (saves ring transitions), this had better stay here!
|
|
; See the DOSCALL macro.
|
|
;
|
|
|
|
mov ax, 3521h
|
|
int 21h
|
|
if ROM
|
|
mov prevInt21Proc.off,bx
|
|
mov prevInt21Proc.sel,es
|
|
else
|
|
mov ax,codeOffset prevInt21Proc
|
|
SetKernelCSDword ax,es,bx
|
|
endif
|
|
|
|
ifdef WOW
|
|
;
|
|
; We save the int 31 vector here to avoid emulation of int 31 instructions.
|
|
; THIS WILL BREAK INT 31 HOOKERS. Currently we don't beleive that any
|
|
; windows apps hook int 31.
|
|
mov ax, 3531h
|
|
int 21h
|
|
|
|
mov ax,codeOffset prevInt31Proc
|
|
SetKernelCSDword ax,es,bx
|
|
endif
|
|
|
|
; moved here 8 feb 1990 from InitFwdRef, no good reason for
|
|
; leaving 0 behind, except that's the way we did it in 2.x.
|
|
|
|
; Save current Int 02h, 04h, 06h, 07h, 3Eh, and 75h.
|
|
|
|
SaveVec 02
|
|
SaveVec 04
|
|
SaveVec 06
|
|
SaveVec 07
|
|
SaveVec 3E
|
|
SaveVec 75
|
|
|
|
; get the 2F
|
|
; this slime is an old novell hack
|
|
SaveVec 2F ; and can probably be removed!
|
|
|
|
; See if we are under NOVELL
|
|
|
|
mov ah, 0DCh
|
|
int 21h
|
|
mov fNovell, al
|
|
|
|
; Get MSDOS version number
|
|
|
|
mov ah,30h
|
|
int 21h
|
|
ifdef TAKEN_OUT_FOR_NT
|
|
cmp al,10 ; is it the DOS 5 compatibility box?
|
|
jae got_ver
|
|
cmp al,4 ; > 4.xx?
|
|
jae got_ver
|
|
cmp al,3 ; < 3.0 ?
|
|
jb dos_version_bad
|
|
cmp ah,10
|
|
jae got_ver ; < 3.1 ?
|
|
dos_version_bad:
|
|
jmps fail
|
|
endif
|
|
|
|
got_ver:
|
|
|
|
mov DOS_version,al
|
|
mov DOS_revision,ah
|
|
|
|
; Remember where the end of the SFT table is, so if we decide to
|
|
; add file handles we can remove them on exit
|
|
;
|
|
; DOS 3.10 =< version =< DOS 3.21 => FileEntrySize = 53
|
|
; DOS 3.21 < version < DOS 4.00 => unknown
|
|
; DOS 4.00 =< version =< DOS 4.10 => FileEntrySize = 58
|
|
; DOS 4.10 < version => unknown
|
|
; version = DOS 10 => FileEntrySize = 00
|
|
|
|
; OS|2
|
|
xor bx,bx
|
|
ifdef TAKEN_OUT_FOR_NT
|
|
cmp al,10 ; OS|2 can't mess with SFTs
|
|
jae have_file_size
|
|
|
|
; DOS 3
|
|
cmp al,3
|
|
ja DOS_4
|
|
|
|
mov bx,56
|
|
cmp ah,0
|
|
jz have_file_size
|
|
mov bx,53
|
|
cmp ah,31
|
|
jbe have_file_size
|
|
jmps unknown_DOS
|
|
|
|
DOS_4: ; REMOVED FOLLOWING! DOS 3.4 will be
|
|
; called 4.0 so we don't know the size!
|
|
;;; mov bx,58
|
|
;;; cmp ah,1 ; DOS 4
|
|
;;; jbe have_file_size
|
|
|
|
unknown_DOS:
|
|
push ax
|
|
call GetFileSize
|
|
mov bx,ax
|
|
pop ax
|
|
cmp bx,-1
|
|
jz fail
|
|
endif
|
|
|
|
have_file_size:
|
|
mov FileEntrySize,bx
|
|
|
|
mov al,10 ; don't want to mess with SFT's!
|
|
ifdef FE_SB
|
|
;During boot,
|
|
;Use thunked API GetSystemDefaultLangID() to set DBCS leadbyte table
|
|
cCall GetSystemDefaultLangID
|
|
xor bx,bx
|
|
|
|
Search_LangID:
|
|
mov dx,word ptr DBCSVectorTable[bx] ;get language ID
|
|
test dx,dx ;if end of table,
|
|
jz DBCS_Vector_X ;exit
|
|
cmp ax,dx ;match LangID?
|
|
jz LangID_Find ;yes
|
|
add bl, DBCSVectorTable[bx+2] ;point to next DBCS vector
|
|
add bl, 3 ;point to DBCS leadbyte range
|
|
jmps Search_LangID ;continue search
|
|
|
|
LangID_Find:
|
|
mov cl, DBCSVectorTable[bx+2] ;get DBCS vector size
|
|
Set_DBCS_Vector:
|
|
sub cl, 2
|
|
jc DBCS_Vector_X
|
|
mov ax, word ptr DBCSVectorTable[bx+3] ;set DBCS vector
|
|
push bx
|
|
call SetDBCSVector
|
|
pop bx
|
|
add bl, 2
|
|
jmps Set_DBCS_Vector
|
|
|
|
DBCS_Vector_X:
|
|
endif ;FE_SB
|
|
|
|
mov ax,-1
|
|
jmps initdone
|
|
fail:
|
|
mov dx,dataOffset szDosVer ;msg0
|
|
mov ah,09
|
|
int 21h
|
|
xor ax,ax
|
|
initdone:
|
|
cEnd
|
|
|
|
ifdef FE_SB
|
|
;-----------------------------------------------------------------------;
|
|
; SetDBCSVector ;
|
|
; ;
|
|
; Setup fDBCSLeadTable ;
|
|
; ;
|
|
; Arguments: ;
|
|
; AL = First DBCS lead byte ;
|
|
; AH = Final DBCS lead byte ;
|
|
; ;
|
|
; Returns: ;
|
|
; NONE ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; BX ;
|
|
; Calls: ;
|
|
; NONE ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc SetDBCSVector,<PUBLIC,NEAR>
|
|
|
|
cBegin nogen
|
|
|
|
mov bl, al ;
|
|
xor bh, bh ;
|
|
idr2:
|
|
mov byte ptr fDBCSLeadTable[bx], 1 ; set "DBCS lead byte"
|
|
inc bl
|
|
cmp bl, ah ; end of range?
|
|
jle idr2 ; jump if not
|
|
mov fFarEast,1 ; I am in DBCS world. 071191 Yukini.
|
|
|
|
ret
|
|
|
|
cEnd nogen
|
|
|
|
endif
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GetFileSize ;
|
|
; ;
|
|
; Measures the SFT entry size for DOS versions we don't know about. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; none ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = SFT size ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; AX = -1 ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Mon Aug 03, 1987 02:42:15p -by- David N. Weise [davidw] ;
|
|
; Rickz wrote it. ;
|
|
; ;
|
|
; Modifications: ;
|
|
; -by- Amit Chatterjee. ;
|
|
; ;
|
|
; The original method of opening 5 files and looking for 3 consecutive ;
|
|
; ones would not succeed always. IRMALAN when run as a TSR from standar-;
|
|
; -d mode Windows would leave a file open (it probably opens 3 files ;
|
|
; when pooped into the host and leaves the third one open). Next time ;
|
|
; on starting windows, the index of the above 5 files that this routine ;
|
|
; would open would be 3,4,5,6 & 8 (SFT entry no). Of these the first ;
|
|
; 2 would be in one node so this woutine would not find 3 consecutive ;
|
|
; entries and Windows would not start up. ;
|
|
; ;
|
|
; To work around this, we try to open 5 at first. If we fail, then we ;
|
|
; leave the 5 open and open another 5. ;
|
|
; ;
|
|
; !!! At some point we should try to figure out why IRMALAN leaves a ;
|
|
; file open. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GetFileSize,<PUBLIC,NEAR>
|
|
|
|
cBegin nogen
|
|
|
|
CheckKernelDS
|
|
ReSetKernelDS
|
|
|
|
mov si,dataOffset handles
|
|
cCall GetFileSize1
|
|
cmp ax,-1 ;did it succeed ?
|
|
jnz @f ;yes.
|
|
mov si,dataOffset handles+10;place for another five
|
|
cCall GetFileSize1 ;try to get it
|
|
@@:
|
|
push ax ;save return value
|
|
|
|
; close files that were opened
|
|
|
|
mov si,dataOffset handles
|
|
mov cx,10
|
|
|
|
close_file_loop: ; close the file for each handle
|
|
|
|
mov ax,3E00h
|
|
mov bx,[si]
|
|
or bx,bx ; no more open ?
|
|
jz close_file_done
|
|
int 21h
|
|
add si,2
|
|
loop close_file_loop
|
|
|
|
close_file_done:
|
|
|
|
pop ax ;get back return value
|
|
ret
|
|
|
|
cEnd nogen
|
|
|
|
|
|
|
|
cProc GetFileSize1,<PUBLIC,NEAR>
|
|
|
|
cBegin nogen
|
|
|
|
mov dx,dataOffset name_string
|
|
mov cx,5
|
|
open_file_loop: ; open the console four times
|
|
mov ax,3D00H
|
|
int 21h
|
|
mov [si],ax ; save the handle
|
|
add si,2
|
|
loop open_file_loop
|
|
|
|
xor di,di ; start searching from 0:0
|
|
|
|
|
|
; get a selector for searching from 0:0
|
|
|
|
mov ax,0 ;get a free slector
|
|
mov cx,1 ;only 1 selector to allocate
|
|
int 31h ;ax has selector
|
|
xor cx,cx ;hiword of initial base
|
|
push dx
|
|
xor dx,dx ;loword of initial base
|
|
mov bx,ax ;get the selector
|
|
call SetSelectorBaseLim64k ;base is at 0:0
|
|
pop dx
|
|
mov es,bx
|
|
|
|
get_first:
|
|
call find_con ; find first 'CON\0'
|
|
cmp ax,-1
|
|
jz no_table
|
|
|
|
cmp ax,-2
|
|
jnz get_second
|
|
search_again:
|
|
|
|
push bx
|
|
mov bx,es ;get the slector
|
|
|
|
; add FFD paragraphs to the base to get to next segment
|
|
|
|
mov ax,0FFDh ;paragraphs to offset base by
|
|
push dx
|
|
call AddParaToBase ;update base
|
|
pop dx
|
|
mov es,bx ;have the updated selector
|
|
pop bx
|
|
xor di,di
|
|
jmp get_first
|
|
|
|
get_second:
|
|
|
|
mov bx,ax ; bx is location of first 'CON\0'
|
|
and bx,000Fh
|
|
shr ax,1
|
|
shr ax,1
|
|
shr ax,1
|
|
shr ax,1
|
|
push bx ;save
|
|
mov bx,es ;get the base
|
|
push dx
|
|
call AddParaToBase ;add AX paras to base
|
|
pop dx
|
|
mov es,bx ;have the updated base
|
|
pop bx ;restore
|
|
mov di,bx
|
|
add di, 3 ; kludge for the size of desired string
|
|
call find_con ; find second 'CON\0'
|
|
cmp ax,-1
|
|
jz no_table
|
|
cmp ax,-2
|
|
jz search_again
|
|
|
|
mov dx,ax ; dx is location of second 'CON\0'
|
|
sub dx,bx
|
|
cmp dx,100h ; file entries are within 100h bytes of another
|
|
ja get_second
|
|
mov bx,dx ; bx is distance between the first two
|
|
mov dx,ax ; dx is location of second 'CON\0'
|
|
get_third:
|
|
call find_con
|
|
cmp ax,-1
|
|
jz no_table
|
|
cmp ax,-2
|
|
jz search_again
|
|
mov cx,ax ; ax & cx = location of third 'CON\0'
|
|
sub cx,dx ; cx is distance between the 2nd & 3rd
|
|
sub bx,cx ; bx = the difference in distances
|
|
jz found
|
|
cmp cx,100h ; file entries are within 100h bytes of another
|
|
ja get_second
|
|
mov bx,cx ; bx is distance between the two
|
|
mov dx,ax ; dx is location of the last 'CON\0'
|
|
jmp get_third
|
|
|
|
found:
|
|
mov ax,cx ; store file table entry size in ax
|
|
|
|
no_table:
|
|
|
|
; if the temp selector had been allocated free it.
|
|
|
|
push bx
|
|
push ax
|
|
mov bx,es
|
|
xor ax,ax
|
|
mov es,ax
|
|
or bx,bx ;allocated ?
|
|
jz @f ;no.
|
|
mov ax,1 ;free selector
|
|
int 31h ;free it
|
|
@@:
|
|
pop ax
|
|
pop bx ;restore
|
|
ret
|
|
|
|
find_con:
|
|
mov ax,es
|
|
push dx ;save
|
|
push bx
|
|
mov bx,ax ;get the slector
|
|
call GetSelectorSegment ;DX returns segment value
|
|
mov ax,dx ;get the segment value
|
|
pop bx
|
|
pop dx ;restore
|
|
cmp ax,8000h
|
|
ja not_found
|
|
xor ax,ax
|
|
mov al, byte ptr [find_string]
|
|
try_again:
|
|
mov cx,0FFF0h
|
|
sub cx,di
|
|
repnz scasb ; search for the first letter ('C')
|
|
jz continue
|
|
mov ax,-2
|
|
jmps temp_ret
|
|
; ret
|
|
continue:
|
|
mov cx,3
|
|
mov si, dataOffset find_string+1
|
|
repz cmpsb ; search for the next three letters
|
|
jnz find_con
|
|
lea ax,[di-4] ; return the string's location in ax
|
|
temp_ret:
|
|
ret
|
|
|
|
not_found:
|
|
|
|
mov ax,-1
|
|
ret
|
|
|
|
cEnd nogen
|
|
;----------------------------------------------------------------------------;
|
|
; AddParaToBase: ;
|
|
; ;
|
|
; Given a selector in BX and a para value in AX, it updates the base of the ;
|
|
; selector by AX paras. In real mode, it just adds AX to BX. The modified ;
|
|
; selector/segment is returned in BX. ;
|
|
;----------------------------------------------------------------------------;
|
|
|
|
AddParaToBase proc near
|
|
push ax ;save
|
|
mov ax,6 ;get base address code
|
|
int 31h ;cx:dx has current base address
|
|
pop ax ;get back the offset in para
|
|
push bx ;use as work register
|
|
xor bx,bx ;zero out
|
|
shl ax,1 ;shift out a bit
|
|
rcl bx,1 ;gather into bx
|
|
shl ax,1 ;shift out a bit
|
|
rcl bx,1 ;gather into bx
|
|
shl ax,1 ;shift out a bit
|
|
rcl bx,1 ;gather into bx
|
|
shl ax,1 ;shift out a bit
|
|
rcl bx,1 ;gather into bx
|
|
add dx,ax ;add low word of offset
|
|
adc cx,0 ;update hiword
|
|
add cx,bx ;update hiword of offset
|
|
pop bx ;get back selector
|
|
mov ax,7 ;set selector base code
|
|
int 31h ;the base of the selector has been set
|
|
inc ax ;set selector limit code
|
|
mov dx,-1 ;64-1k limit
|
|
xor cx,cx ;cx:dx=64-1k
|
|
int 31h ;limit set to 64-1k
|
|
ret
|
|
|
|
AddParaToBase endp
|
|
;----------------------------------------------------------------------------;
|
|
|
|
;----------------------------------------------------------------------------;
|
|
; GrowSFTToMax: ;
|
|
; ;
|
|
; This routine is invoked only in protected mode and grows the SFT to its max;
|
|
; size by linking in one more tanle entry. ;
|
|
;----------------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GrowSFTToMax,<NEAR,PUBLIC,PASCAL>,<es,ax,di>
|
|
|
|
localW NewHandles ;# of extra handles being allocated
|
|
localW NewTableSize ;size of newtable
|
|
localB GrowLimit ;size to grow sft to
|
|
|
|
cBegin
|
|
ReSetKernelDS
|
|
|
|
; get the amount of free space and decide on the number of handle entries that
|
|
; we want to add. If the memory space is more than 8*64K, make the total number
|
|
; of handle entries 256 else make it 100.
|
|
|
|
mov GrowLimit,SFT_HIGH_LIM ;assume we will grow upto 255
|
|
xor bx,bx ;dummy parameter
|
|
cCall GetFreeSpace,<bx> ;dx:ax returns free area size
|
|
cmp dx,SFT_GROW_LIM_IN_64K ;is it more than or equal (in 64k incs)
|
|
jae @f ;yes
|
|
mov GrowLimit,SFT_LOW_LIM ;low on memory, grow till 100
|
|
@@:
|
|
|
|
; allocate a free selector.
|
|
|
|
xor ax,ax ;allocate selector function code
|
|
mov cx,1 ;need to get 1 selector
|
|
int 31h ;ax has the selector
|
|
|
|
; get the address of the first in the SFT chain.
|
|
|
|
push ax ;save the slector
|
|
mov ah,52h ;get SYSVARS call
|
|
int 21h ;es:bx points to DOS SYSVAR structure
|
|
lea bx,[bx+sftHead] ;es:bx points to the start of the sft
|
|
mov cx,es:[bx][2] ;get the segment
|
|
mov dx,es:[bx] ;get the offset
|
|
pop ax ;get back the free selector
|
|
|
|
; modify the base of the free selector to point to the first link in the system
|
|
; file table list.
|
|
|
|
mov bx,ax ;get the selector here
|
|
call SetSelectorBaseLim64k ;set selector base and limit.
|
|
|
|
; now get into a loop, to find out the number of file handles that the system
|
|
; currently.
|
|
|
|
xor ah,ah ;will count handles here.
|
|
mov es,bx ;es points to the first entry
|
|
|
|
CountNumHandles:
|
|
|
|
xor bx,bx ;es:bx points to first table
|
|
mov cx,es:[bx].sftCount ;get the number of handles
|
|
add ah,cl ;accumulate no of handles here
|
|
cmp word ptr es:[bx],-1 ;end of chain ?
|
|
jz AddOneMoreSFTLink ;end of current list reached
|
|
mov cx,word ptr es:[bx].sftLink[2];get the segment of next node
|
|
mov dx,word ptr es:[bx].sftLink[0];get the offset of the next node
|
|
mov bx,es ;get the selector
|
|
call SetSelectorBaseLim64k ;modify sel to point to next node
|
|
jmp short CountNumHandles ;continue
|
|
|
|
AddOneMoreSFTLink:
|
|
|
|
; find out the number of extra handles for which we will allocate space
|
|
|
|
mov al,GrowLimit ;max number of handles
|
|
cmp ah,al ;is it already more than limit ?
|
|
jae GrowSFTToMaxRet ;no need to grow any more.
|
|
|
|
ifdef WOW
|
|
xchg ah,al
|
|
xor ah,ah
|
|
Debug_Out "GrowSFTToMax: At least 128 files handles required in CONFIG.SYS only specified #AX"
|
|
jmp ExitKernel
|
|
else
|
|
sub al,ah ;al has the no of extra handles
|
|
xor ah,ah ;ax has no of extra handles
|
|
mov NewHandles,ax ;save it.
|
|
mul FileEntrySize ;dx:ax has size of table
|
|
add ax,(SIZE SFT) - 1 ;size of the initial header
|
|
mov NewTableSize,ax ;save size
|
|
regptr dxax,dx,ax
|
|
|
|
save <es,bx>
|
|
cCall GlobalDOSAlloc,<dxax> ;allocate the block
|
|
jcxz GrowSFTToMaxRet ;no memory to allocate
|
|
|
|
cCall SetOwner,<ax,hExeHead>
|
|
|
|
; store the pointer to the new link in the current link.
|
|
|
|
push bx ;save
|
|
mov bx,ax ;get the new selector
|
|
call GetSelectorSegment ;returns segment of sel in ax, in dx
|
|
pop bx ;restore
|
|
mov word ptr es:[bx].sftLink[2],dx
|
|
mov word ptr es:[bx].sftLink[0],0
|
|
|
|
; we have to save the address of this last original link so that it can be
|
|
; restored to be the last at DisableKernel time. We will save the current
|
|
; selector and delete it at disable time
|
|
|
|
mov word ptr [pSftLink],bx ;save
|
|
mov word ptr [pSftLink+2],es
|
|
|
|
mov bx,es ;get the selector
|
|
mov es,ax ;es points to new link
|
|
|
|
; initialize memory tp all zeros
|
|
|
|
xor di,di ;es:di points to new buffer
|
|
mov cx,NewTableSize ;size of buffer
|
|
xor al,al ;want to initialize to 0's
|
|
rep stosb ;initialized
|
|
|
|
; prepare the header for the new table.
|
|
|
|
xor bx,bx ;es:bx points to the new table
|
|
mov cx,-1 ;link terminator code
|
|
mov word ptr es:[bx].sftLink[2],cx
|
|
mov word ptr es:[bx].sftLink[0],cx
|
|
mov cx,NewHandles ;# of handles in this node
|
|
mov es:[bx].sftCount,cx
|
|
endif; WOW
|
|
|
|
GrowSFTToMaxRet:
|
|
|
|
cEnd
|
|
;----------------------------------------------------------------------------;
|
|
; SetSelectorBaseLim64k: ;
|
|
; ;
|
|
; Given a selector value in bx and a real mode lptr in cx:dx, it sets the ba-;
|
|
; -se of the selector to that value and sets it to be a 64k data segment. AX ;
|
|
; is preserved. ;
|
|
; ;
|
|
;----------------------------------------------------------------------------;
|
|
|
|
SetSelectorBaseLim64k proc near
|
|
|
|
push ax ;save
|
|
|
|
; calculate the linear base address.
|
|
|
|
xor ax,ax ;will have high nibble of shift
|
|
shl cx,1 ;shift by 1
|
|
rcl ax,1 ;gather in
|
|
shl cx,1 ;shift by 1
|
|
rcl ax,1 ;gather in
|
|
shl cx,1 ;shift by 1
|
|
rcl ax,1 ;gather in
|
|
shl cx,1 ;shift by 1
|
|
rcl ax,1 ;gather in
|
|
add cx,dx ;add in the offset
|
|
adc ax,0 ;ax:cx has the base
|
|
mov dx,cx ;get into proper registers
|
|
mov cx,ax ;cx:dx has the base
|
|
mov ax,7 ;set selector base code
|
|
int 31h ;the base of the selector has been set
|
|
inc ax ;set selector limit code
|
|
mov dx,-1 ;64-1k limit
|
|
xor cx,cx ;cx:dx=64-1k
|
|
int 31h ;limit set to 64-1k
|
|
|
|
pop ax ;restore ax
|
|
ret
|
|
|
|
SetSelectorBaseLim64k endp
|
|
;----------------------------------------------------------------------------;
|
|
; GetSelectorSegment: ;
|
|
; ;
|
|
; Given a slector in bx pointing to DOS memory, this function returns the ;
|
|
; real mode segment value in DX. AX,BX is preserved. ;
|
|
;----------------------------------------------------------------------------;
|
|
|
|
GetSelectorSegment proc near
|
|
|
|
push ax ;save
|
|
push bx ;save
|
|
mov ax,6 ;get selector base
|
|
int 31h ;cx:dx has base
|
|
shr cx,1 ;shift by 1
|
|
rcr dx,1 ;gather into dx
|
|
shr cx,1 ;shift by 1
|
|
rcr dx,1 ;gather into dx
|
|
shr cx,1 ;shift by 1
|
|
rcr dx,1 ;gather into dx
|
|
shr cx,1 ;shift by 1
|
|
rcr dx,1 ;gather into dx
|
|
pop bx ;restore
|
|
pop ax ;dx has segment value
|
|
ret
|
|
|
|
GetSelectorSegment endp
|
|
;----------------------------------------------------------------------------;
|
|
|
|
|
|
sEnd INITCODE
|
|
|
|
end
|