windows-nt/Source/XPSP1/NT/base/mvdm/wow16/kernel31/ldboot.asm
2020-09-26 16:20:57 +08:00

3449 lines
76 KiB
NASM

PAGE ,132
TITLE LDBOOT - BootStrap procedure
?DFSTACK = 1
.xlist
include kernel.inc
include newexe.inc
include tdb.inc
include pdb.inc
include eems.inc
include protect.inc
include gpcont.inc
ifdef WOW
include vint.inc
include doswow.inc
endif
.list
if 0; KDEBUG
ifdef WOW
BootTraceOn = 1
BootTrace macro char
push ax
mov ax,char
int 3
pop ax
endm
else
BootTraceOn = 1
BootTrace macro char
push char
call BootTraceChar
endm
endif
else
BootTrace macro char
endm
BootTraceOn = 0
endif
; Note that the following public constants require special handling
; for ROM Windows. If you add, delete, or change this list of constants,
; you must also check the ROM Image Builder.
public __ahshift
public __ahincr
public __0000h
public __0040h
public __A000h
public __B000h
public __B800h
public __C000h
public __D000h
public __E000h
public __F000h
public __ROMBIOS
public __WinFlags
public __flatcs
public __flatds
public __MOD_KERNEL
public __MOD_DKERNEL
public __MOD_USER
public __MOD_DUSER
public __MOD_GDI
public __MOD_DGDI
public __MOD_KEYBOARD
public __MOD_SOUND
public __MOD_SHELL
public __MOD_WINSOCK
public __MOD_TOOLHELP
public __MOD_MMEDIA
public __MOD_COMMDLG
ifdef FE_SB
public __MOD_WINNLS
public __MOD_WIFEMAN
endif ; FE_SB
__ahshift = 3
__ahincr = 1 shl __ahshift
__0000h = 00000h
__0040h = 00040h
__A000h = 0A000h
__B000h = 0B000h
__B800h = 0B800h
__C000h = 0C000h
__D000h = 0D000h
__E000h = 0E000h
__F000h = 0F000h
__ROMBIOS = 0F000h
__WinFlags = 1
__flatcs = 1Bh
__flatds = 23h
__MOD_KERNEL = 0h
__MOD_DKERNEL = 0h
__MOD_USER = 0h
__MOD_DUSER = 0h
__MOD_GDI = 0h
__MOD_DGDI = 0h
__MOD_KEYBOARD = 0h
__MOD_SOUND = 0h
__MOD_SHELL = 0h
__MOD_WINSOCK = 0h
__MOD_TOOLHELP = 0h
__MOD_MMEDIA = 0h
__MOD_COMMDLG = 0h
ifdef FE_SB
__MOD_WINNLS = 0h ; for IME
__MOD_WIFEMAN = 0h ; for WIFEMAN
endif ; FE_SB
BOOTSTACKSIZE = 512
EXTRASTACKSIZE = (4096-BOOTSTACKSIZE)
MultWIN386 EQU 16h ; Reserved to Win386
MW3_ReqInstall EQU 00h ; Installation check
MW3_ReqInstall_Ret_1 EQU 0FFh ; Return number 1
MW3_ReqInstall_Ret_2 EQU 01h ; Return number 2
MW3_ReqInstall_Ret_3 EQU 02h ; Return number 3
MW3_ReqInstall_Ret_4 EQU 03h ; Return number 4
externFP lstrlen
externFP lstrcat
externFP lstrcpy
externFP IGlobalAlloc
externFP IGlobalFree
externFP IGlobalRealloc
externFP LoadModule
externFP IOpenFile
externFP lrusweep
externFP GetExePtr
externFP GetProfileInt
externFP GetPrivateProfileString
externFP GetPrivateProfileInt
externFP GetProcAddress
externFP GetTempDrive
externFP ExitKernel
externFP InternalEnableDOS
externFP FlushCachedFileHandle
externFP SetHandleCount
externFP IPrestoChangoSelector
externFP GPFault
externFP StackFault
externFP invalid_op_code_exception
externFP page_fault
ifdef WOW
externFP divide_overflow
externFP single_step
externFP breakpoint
endif
externFP DiagInit
ifdef WOW
externFP StartWOWTask
externFP AllocSelector_0x47
externW MOD_KERNEL
externW ModCount
externFP WOWGetTableOffsets
externFP WOWDosWowInit
externFP GetShortPathName
endif
if KDEBUG
externFP ValidateCodeSegments
endif
ifdef FE_SB
externFP GetSystemDefaultLangID
endif
externFP TermsrvGetWindowsDir
externW pStackBot
externW pStackMin
externW pStackTop
sBegin CODE
externFP Int21Handler
externFP Int10Handler
externD prevInt10proc
sEnd CODE
;------------------------------------------------------------------------
; Data Segment Variables
;------------------------------------------------------------------------
DataBegin
if SHERLOCK
externW gpEnable
endif
externB graphics
externB fBooting
externB Kernel_flags
externB fChkSum
externB fCheckFree
externB WOAName
externB grab_name
ifndef WOW
externB szUserPro
endif
externB szBootLoad
externB szCRLF
externB szMissingMod
externB szPleaseDoIt
externB fPadCode
;externW EMScurPID
;externW PID_for_fake
externW cBytesWinDir
externW cBytesSysDir
externW pGlobalHeap
externW hExeHead
externW MaxCodeSwapArea
externW curTDB
externW f8087
externB fastFP
externW topPDB
externW headTDB
externW winVer
ifndef WOW
externB WinIniInfo
externB PrivateProInfo
endif
externW gmove_stack
externW prev_gmove_SS
externW BaseDsc
externW WinFlags
externW hUser
externW hShell
externW MyCSSeg
externW MyDSSeg
externW MyCSAlias
externB fhCache
externW fhCacheEnd
externW fhCacheLen
externB fPokeAtSegments
externB fExitOnLastApp
externW segLoadBlock
externD pKeyProc
externD pKeyProc1
externW wDefRIP
ife ROM
externW cpShrunk
externW cpShrink
externW hLoadBlock
endif
if ROM
externW selROMTOC
externW selROMLDT
externW sel1stAvail
endif
externD pTimerProc
externD pExitProc
externD pDisableProc
externD lpWindowsDir
externD lpSystemDir
if ROM
externD prevIntx6proc
externD prevInt0Cproc
externD prevInt0Dproc
externD prevInt0Eproc
externD prevInt21proc
externD prevInt3Fproc
endif
;if KDEBUG and SWAPPRO
;externD prevIntF0proc
;endif
externD lpInt21 ; support for NOVELL stealing int 21h
ifdef WOW
externD pFileTable
externW cBytesSys16Dir
externD lpSystem16Dir
externB Sys16Suffix
externW cBytesSys16Suffix
externW cBytesSysWx86Dir
externD lpSystemWx86Dir
externB SysWx86Suffix
externW cBytesSysWx86Suffix
externD pPMDosCURDRV
externD pPMDosCDSCNT
externD pPMDosPDB
externD pPMDosExterr
externD pPMDosExterrLocus
externD pPMDosExterrActionClass
externD pDosWowData
globalW cbRealWindowsDir,0
WINDIR_BUFSIZE equ 121
achWindowsDir DB WINDIR_BUFSIZE DUP(?)
achRealWindowsDir DB WINDIR_BUFSIZE DUP(?)
achSystem16Dir DB 128 DUP(?)
achSystemWx86Dir DB 128 DUP(?)
public cbRealWindowsDir, achRealWindowsDir, achWindowsDir, achSystem16Dir
externB achTermSrvWindowsDir ; windows directory path (for win.ini)
endif
DataEnd
;------------------------------------------------------------------------
; INITDATA Variables
;------------------------------------------------------------------------
DataBegin INIT
ifndef WOW
; WOW doesn't muck with the WOAName buffer -- we just leave it
; as WINOLDAP.MOD
externB woa_286
externB woa_386
endif
externB bootExecBlock
externW oNRSeg
externW oMSeg
externW win_show
externD lpBootApp
if ROM
externD lmaROMTOC
staticD MyLmaROMTOC,lmaROMTOC
.errnz opLen
.errnz 8 - opFile
ROMKRNL db 19 ; mocked up open file structure
db 7 dup (0) ; for ROM Kernel
db 'ROMKRNL.EXE',0
endif
staticW initTDBbias,0
staticW initSP,0
staticW initSSbias,0
staticW segNewCS,0
app_name db 68 dup(0)
DataEnd INIT
;------------------------------------------------------------------------
; EMSDATA Variables
;------------------------------------------------------------------------
;------------------------------------------------------------------------
externNP LoadSegment
externNP genter
externNP gleave
externNP GlobalInit
externNP DeleteTask
externNP BootSchedule
externNP InitFwdRef
externNP SaveState
externNP LKExeHeader
externNP GetPureName
externNP SegmentNotPresentFault
externNP LDT_Init
externNP alloc_data_sel
externNP get_physical_address
externNP set_physical_address
externNP set_sel_limit
externNP free_sel
externFP set_discarded_sel_owner
externNP SelToSeg
externNP DebugDefineSegment
externNP DebugFreeSegment
ife ROM
externNP SwitchToPMODE
externNP LKAllocSegs
endif
if ROM and PMODE32
externFP HocusROMBase
endif
ifdef WOW
externFP WOWFastBopInit
endif
if KDEBUG
ife PMODE32
externNP init_free_to_CCCC
endif
if SWAPPRO
externB fSwapPro
externW hSwapPro
externW cur_dos_pdb
endif
endif
ifdef FE_SB
externFP FarMyIsDBCSTrailByte
endif
;------------------------------------------------------------------------
sBegin INITCODE
assumes cs,CODE
ife ROM
externD prevIntx6proc
externD prevInt0Cproc
externD prevInt0Dproc
externD prevInt0Eproc
externD prevInt21proc
externD prevInt3Fproc
ifdef WOW
externD prevInt01proc
externD prevInt03proc
externD oldInt00proc
externFP GlobalDosAlloc
externFP GlobalDosFree
endif
endif
externNP TextMode
externNP InitDosVarP
externNP GrowSFTToMax
ifndef WOW
externNP SetUserPro
endif
externNP MyLock
externNP Shrink
externNP DebugDebug
externNP NoOpenFile
externNP NoLoadHeader
if SDEBUG
externNP DebugInit
endif
;if SWAPPRO
;externNP INTF0Handler
;endif
if SDEBUG
szModName db 'KERNEL',0
endif
if ROM
externNP ROMInit
externNP SetOwner
externNP SetROMOwner
externNP alloc_data_sel16
if KDEBUG
externNP CheckGlobalHeap
endif
endif
ifdef WOW
externNP SetOwner
endif
;-----------------------------------------------------------------------;
; Bootstrap ;
; ;
; Determines whether we should initialize in a smaller amount of ;
; memory, leaving room for an EEMS swap area. If so, we rep-move the ;
; code to a lower address, and tell the PSP to report less memory ;
; available. It then does lots more of stuff. ;
; ;
; Arguments: ;
; DS:0 = new EXE header ;
; ES:0 = Program Segment Prefix block (PSP) ;
; SS:SP = new EXE header ;
; CX = file offset of new EXE header (set by KernStub) ;
; DS = automatic data segment if there is one ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Sat Jun 20, 1987 06:00:00p -by- David N. Weise [davidw] ;
; Made fast booting work with real EMS. ;
; ;
; Tue Apr 21, 1987 06:31:42p -by- David N. Weise [davidw] ;
; Added some more EMS support. ;
; ;
; Thu Apr 09, 1987 02:52:37p -by- David N. Weise [davidw] ;
; Put back in the movement down if EMS. ;
; ;
; Sat Mar 14, 1987 05:55:29p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds,DATA
assumes es,nothing
assumes ss,nothing
cProc BootStrap,<PUBLIC,NEAR>
cBegin nogen
ifndef NEC_98
if KDEBUG
jmp short Hello_WDEB_End
Hello_WDEB:
db 'Windows Kernel Entry',13,10,0
Hello_WDEB_End:
push ax
push es
push si
xor ax, ax
mov es, ax
mov ax, es:[68h*4]
or ax, es:[68h*4+2]
jz @F
mov ax,cs
mov es,ax
lea si,Hello_WDEB
mov ah,47h
int 68h
@@:
pop si
pop es
pop ax
endif
endif ; NEC_98
BootTrace 'a'
if ROM
call ROMInit ; BX -> LDT, DS -> RAM DGROUP, SI -> start mem
else
cmp ax, "KO" ; OK to boot; set by kernstub.asm
je @F
xor ax, ax
retf
@@:
; Set up addressibility to our code & data segments
mov MyCSSeg, cs
mov MyDSSeg, ds
endif ;ROM
ifdef WOW
; Get pointer to sft so that I can find do direct protect mode
; file IO operations
mov CS:MyCSDS, ds
push es
mov ah,52h ; get pointer to internal vars
int 21h
;
; Retrieve some pointers from the DosWowData structure in DOS.
;
push di
push dx
mov di, es:[bx+6ah] ;kernel data pointer
mov pDosWowData.off, di
mov pDosWowData.sel, es
mov ax, word ptr es:[di].DWD_lpCurPDB
; mov dx, word ptr es:[di].DWD_lpCurPDB+2
mov pPMDosPDB.off,ax
mov pPMDosPDB.sel,0 ;to force gpfault if not ready
mov ax, word ptr es:[di].DWD_lpCurDrv
; mov dx, word ptr es:[di].DWD_lpCurDrv+2
mov pPMDosCURDRV.off,ax
mov pPMDosCURDRV.sel,0 ;to force gpfault if not ready
mov ax, word ptr es:[di].DWD_lpCDSCount
; mov dx, word ptr es:[di].DWD_lpCDSCount+2
mov pPMDosCDSCNT.off,ax
mov pPMDosCDSCNT.sel,0 ;to force gpfault if not ready
mov ax, word ptr es:[di].DWD_lpExterr
mov pPMDosExterr.off, ax
mov pPMDosExtErr.sel, 0
mov ax, word ptr es:[di].DWD_lpExterrLocus
mov pPMDosExterrLocus.off, ax
mov pPMDosExtErrLocus.sel, 0
mov ax, word ptr es:[di].DWD_lpExterrActionClass
mov pPMDosExterrActionClass.off, ax
mov pPMDosExtErrActionClass.sel, 0
pop dx
pop di
lea bx,[bx+sftHead]
mov pFileTable.off,bx
mov pFileTable.sel,es
pop es
endif ; WOW
ife ROM
BootTrace 'b'
call SwitchToPMODE ; BX -> LDT, DS -> CS(DS), SI start of memory
BootTrace 'c'
endif
ReSetKernelDS
mov BaseDsc,si
call LDT_Init
BootTrace 'd'
ifdef WOW
call AllocSelector_0x47
call WOWFastBopInit
endif
if SDEBUG
; In protected mode, initialize the debugger interface NOW. Only real mode
; needs to wait until the global heap is initialized.
cCall DebugInit
; In protected mode, define where our temp Code & Data segments are
mov ax,codeOffset szModName
cCall DebugDefineSegment,<cs,ax,0,cs,0,0>
mov ax,codeOffset szModName
cCall DebugDefineSegment,<cs,ax,3,ds,0,1>
endif
BootTrace 'e'
if ROM
; In the ROM version, the DS selector doesn't change from now on, so we
; can tell the debugger where the special kernel data is now.
cCall DebugDebug
endif
BootTrace 'f'
ifdef WOW
push ax
push bx
mov bx, pDosWowData.sel ;use this segment
mov ax, 2
int 31h
mov pPMDosPDB.sel,ax ;make this a PM pointer
mov pPMDosCURDRV.sel,ax ;make this a PM pointer
mov pPMDosCDSCNT.sel,ax ;make this a PM pointer
mov pPMDosExterr.sel,ax
mov pPMDosExterrLocus.sel,ax
mov pPMDosExterrActionClass.sel,ax
pop bx
pop ax
push pDosWowData.sel
push pDosWowData.off
call WOWDosWowInit
endif
; InitDosVarP just records a few variables, it does no hooking.
; It does dos version checking and other fun stuff that
; must be done as soon as possible.
call InitDosVarP
or ax,ax
jnz inited_ok
Debug_Out "KERNEL: InitDosVarP failed"
mov ax,4CFFh ; Goodbye!
INT21
inited_ok:
BootTrace 'g'
push bx
mov bx, WinFlags
ifndef JAPAN ; should be removed because of IBM dependent code.
ifndef NEC_98
; InitFwdRef routine will set 80x87 status bit in WinFlags
; and exported location #178.
; Determine if there is a co-processor present.
int 11h ; get equipment word
test al,2 ; this is the IBM approved method
jz no_80x87 ; to check for an 8087
or bh,WF1_80x87
no_80x87:
endif ; NEC_98
endif ;NOT JAPAN
ifdef WOW
or bh,WF1_WINNT ; Set NT flag ON
endif
mov WinFlags,bx
pop bx
; Determine if running under Windows/386 or the 286 DOS Extender
push bx
mov ax,(MultWin386 SHL 8) OR MW3_ReqInstall ; Win/386 install check
int 2Fh
BootTrace 'h'
cmp al,MW3_ReqInstall_Ret_4 ; Under WIN386 in pmode?
ifdef WOW ; For WOW Enhanced Mode on 386
ife PMODE32
jnz NotUnderWin386
endif
endif
or Kernel_flags[1],kf1_Win386
or byte ptr WinFlags,WF_PMODE or WF_ENHANCED
jmps InstallChkDone
NotUnderWin386:
or Kernel_flags[2],KF2_DOSX
or byte ptr WinFlags,WF_PMODE or WF_STANDARD
InstallChkDone:
BootTrace 'i'
pop bx
ifndef WOW
; WOW doesn't muck with the WOAName buffer -- we just leave it
; as WINOLDAP.MOD
push cx
push di
push si
cld
mov cx,8
smov es,ds
mov di,dataOffset WOAName
mov si,dataOffset woa_286
test Kernel_flags[2],KF2_DOSX
jnz @F
mov si,dataOffset woa_386
@@: rep movsb
pop si
pop di
pop cx
endif
BootTrace 'j'
ife ROM ;--------------------------------------------------------
mov ax,cx
mov cl,4
shr ax,cl
mov cpShrunk,ax
; Compute paragraph address of new EXE header from SS:SP
mov bx,sp ; SS:SP -> new EXE header
cCall get_physical_address,<ss>
add ax,bx
adc dx,0
BootTrace 'k'
if PMODE32
cCall alloc_data_sel,<dx,ax,0,0FFFFh>
else
cCall alloc_data_sel,<dx,ax,1000h>
endif
BootTrace 'l'
else ; ROM ---------------------------------------------------------
; Setup selector to ROM Table of Contents
mov ax,word ptr [MyLmaROMTOC]
mov dx,word ptr [MyLmaROMTOC+2]
cCall alloc_data_sel16,<dx,ax,1000h>
if PMODE32
cCall HocusROMBase, <ax>
endif
mov selROMTOC,ax
; Setup another selector to the ROM prototype LDT
mov es,ax
assumes es,nothing
mov ax,word ptr es:[lmaROMLDT]
mov dx,word ptr es:[lmaROMLDT+2]
cCall alloc_data_sel16,<dx,ax,1000h>
if PMODE32
cCall HocusROMBase, <ax>
endif
mov selROMLDT,ax
mov ax,es:[FirstROMsel]
shr ax,3
add ax,es:[cROMsels]
shl ax,3 ; ax = 1st non-ROM selector
mov sel1stAvail,ax
; Setup selector to KERNEL EXE header in ROM. **ASSUMES KERNEL is 1st
; module in ROM TOC**
mov ax,word ptr es:[ModEntries+lmaExeHdr]
mov dx,word ptr es:[ModEntries+lmaExeHdr+2]
cCall alloc_data_sel16,<dx,ax,1000h>
if PMODE32
cCall HocusROMBase, <ax>
endif
endif ; ROM ---------------------------------------------------------
mov segLoadBlock,ax ; hinitexe:0 -> new EXE header
; calculate the TDB bias
mov bx,dataOffset boottdb
mov initTDBbias,bx
; calculate the SS bias
mov bx,dataOffset stackbottom
mov initSSbias,bx
; calculate the initial SP
mov si,dataOffset stacktop
sub si,dataOffset stackbottom
mov initSP,si
cCall get_physical_address,<ds>
add ax,bx
adc dx,0
BootTrace 'm'
if ROM
cCall alloc_data_sel16,<dx,ax,1000h>
FCLI
else
FCLI
mov prev_gmove_SS, ss ; Switch stack while we set up new SS
smov ss, ds
mov sp, dataOFFSET gmove_stack
cCall set_physical_address,<prev_gmove_SS>
xor ax, ax
xchg ax, prev_gmove_SS
endif
BootTrace 'n'
mov ss,ax ; switch to new stack
mov sp,si
FSTI
xor bp,bp ; zero terminate BP chain.
sub si,BOOTSTACKSIZE
mov ss:[pStackBot],sp
mov ss:[pStackMin],sp
mov ss:[pStackTop],si
cld
mov es,topPDB
externB szNoGlobalInit
if ROM ;----------------------------------------------------------------
; In the ROM Windows version, the "allocated" block in the global heap is
; the kernel data segment, not the code segments
mov bx,ds ; kernel DS is first busy block
lsl bx,bx ; pass its size to GlobalInit
inc bx
cCall GlobalInit,<MASTER_OBJECT_SIZE,bx,BaseDsc,es:[PDB_block_len]>
jnc mem_init_ok
if KDEBUG
Debug_Out "GlobalInit failed!"
else
mov dx, codeoffset szNoGlobalInit
smov ds, cs
mov ah, 9
int 21h ; Whine
mov ax, 4CFFh
int 21h ; And exit
;NoGlobalInit db "KERNEL: Unable to initialise heap",13,10,'$'
endif
mem_init_ok:
if KDEBUG
cCall CheckGlobalHeap
endif
else ;ROM ---------------------------------------------------------
BootTrace 'o'
mov ax, BaseDsc ; Free memory starts after this
mov bx,segLoadBlock ; Make boot image be first busy block
mov cx,es:[PDB_block_len] ; cx is end of memory
mov dx,MASTER_OBJECT_SIZE
cCall GlobalInit,<dx,bx,ax,cx>
jc @F ; passed through from ginit
or ax,ax
jnz mem_init_ok
@@:
mov dx, codeoffset szNoGlobalInit
smov ds, cs
mov ah, 9
int 21h ; Whine
mov ax, 4CFFh
int 21h ; And exit
;NoGlobalInit db "KERNEL: Unable to initialise heap",13,10,'$'
mem_init_ok:
mov hLoadBlock,ax ; Save handle to first busy block
endif ;ROM ---------------------------------------------------------
BootTrace 'p'
mov pExitProc.sel,cs
mov pExitProc.off,codeOffset ExitKernel
; Find out where we live, and where win.com lives.
mov ds,topPDB
UnSetKernelDS
mov bx,ds
mov ds,ds:[PDB_environ]
xor si,si
cld
envloop1:
lodsb
or al,al ; end of item?
jnz envloop1
lodsb
or al,al ; end of environment?
jnz envloop1
lodsw ; ignore argc, DS:SI -> kernel path
ifdef WOW
smov es, ds ; now ES:SI -> kernel path
else
call get_windir ; on return, DS:DI -> windir= value
smov es,ds
; Record where to find the 'windows' directory.
BootTrace 'q'
SetKernelDS
or di,di
jz no_win_dir_yet
mov lpWindowsDir.sel,es
mov lpWindowsDir.off,di
mov cBytesWinDir,cx
; Now set pointer to WIN.INI to be
; in the Windows directory
push si
push es
smov es, ds
mov si, dataoffset szUserPro+6
mov di, si
inc cx
add di, cx ; Move up the string WIN.INI
std
mov cx, 4
rep movsw
; Now copy Windows directory
cld
mov cx, cBytesWinDir
mov di, dataoffset szUserPro
lds si, lpWindowsDir
UnSetKernelDS
rep movsb
mov byte ptr es:[di], '\'
pop es
pop si
endif
SetKernelDS
BootTrace 'r'
no_win_dir_yet:
if ROM ;----------------------------------------------------------------
; 'Load' the kernel exe header from ROM.
mov si,dataOffset ROMKRNL
cCall LKExeHeader,<segLoadBlock,ds,si>
or ax,ax
jnz hdr_ok
jmp bootfail
hdr_ok:
else ;ROM ---------------------------------------------------------
sub sp,SIZE OPENSTRUC + 127
mov di,sp
regptr ssdi,ss,di
mov bx,OF_EXIST
cCall IOpenFile,<essi,ssdi,bx>
BootTrace 's'
inc ax ; Test for -1
jnz opn1 ; Continue if success
mov dx, codeoffset NoOpenFile
fail1:
push dx ; Save string pointer
call textmode ; Switch to text mode
pop dx
smov ds, cs
mov ah, 9
int 21h ; Tell user why we're bailing out
mov ax,4CFFh ; Goodbye!
INT21
opn1:
; Now simulate loading ourselves from memory
; Load new EXE header for KERNEL.EXE from memory
cCall LKExeHeader,<segLoadBlock,ssdi>
BootTrace 't'
add sp,SIZE OPENSTRUC + 127
or ax,ax
jnz @F
mov dx, codeoffset NoLoadHeader
jmp SHORT fail1
@@:
endif ;ROM ---------------------------------------------------------
mov hExeHead,ax
mov es,ax
ifndef WOW
; Record where to find the 'system' directory.
if ROM ;----------------------------------------------------------------
push es
mov es,selROMTOC ; ROM system dir @ selROMTOC:offSysDir
mov di,es:offSysDir
mov lpSystemDir.sel,es
mov lpSystemDir.off,di
xor ax,ax
mov cx,-1
cld
repne scasb
not cx
dec cx
mov cBytesSysDir,cx
pop es
else ;ROM ---------------------------------------------------------
mov di,es:[ne_pfileinfo]
lea di,es:[di].opFile
mov lpSystemDir.sel,es
mov lpSystemDir.off,di
mov dx,di
call GetPureName
sub di,dx
dec di
mov cBytesSysDir,di
endif ;ROM ---------------------------------------------------------
BootTrace 'u'
endif
; ndef WOW
; Make room at end of kernel data segment for stack--NOTE: DGROUP is
; assumed to be segment 4!
mov bx,es:[ne_segtab]
ife ROM
add es:[bx+(3*size NEW_SEG1)].ns_minalloc,EXTRASTACKSIZE
endif
; Determine size of kernel's largest discardable code segment
; don't bother with swap area's anymore. Its fixed 192k (3segs)
; picked this up from Win95
xor ax,ax ; No max
mov es:[ne_swaparea],ax
BootTrace 'v'
ife ROM ;----------------------------------------------------------------
; Allocate memory for kernel segments
cCall LKAllocSegs,<es>
mov oNRSeg,ax
mov oMSeg, bx ; Misc segment
mov es,hExeHead
; If this is a pMode debug version, the code and data segments have already
; been defined to the debugger once. We're about to LoadSegment and define
; these segments again in their final location. Use a special form of
; DebugFreeSegment to force the debugger to pull out any breakpoints in these
; segments. If we don't do this, any existing breakpoints become INT 3's
; in the new copy of the segment and the code has to be patched by hand.
; If only the debugger was smart enough to 'move' the breakpoints when it
; saw a second define for an already loaded segment...
if SDEBUG
cCall DebugFreeSegment,<cs,-1>
cCall DebugFreeSegment,<MyCSDS,-1>
endif
; Load kernel code segment 1 (resident code)
mov si,1
mov ax,-1 ; Indicate loading from memory
cCall LoadSegment,<es,si,cs,ax>
or ax,ax
jnz ll1
fail2: jmp bootfail
ll1:
mov segNewCS,ax ; Save new CS value
; Load kernel data segment (segment 4)
mov si,4
mov ax,-1
cCall LoadSegment,<hExeHead,si,ds,ax>
or ax,ax
jz fail2
BootTrace 'w'
; locate the stack in the new segment
mov bx,ax
mov si,initSP
add si,EXTRASTACKSIZE
else ;ROM ---------------------------------------------------------
cCall SetOwner,<ds,hExeHead> ;Who owns ya baby?
cCall SetROMOwner,<cs,hExeHead> ;IGROUP isn't loaded, but needs owner
; locate the stack at the end of the data segment
mov ax, ds
mov bx, ax
mov si, initSP
add si, ROMEXTRASTACKSZ
endif ;ROM ---------------------------------------------------------
cCall get_physical_address,<ax>
add ax,initSSbias
adc dx,0
sub ax,10h
sbb dx,0
or ax,10h
FCLI
mov prev_gmove_SS, ss ; Switch stack while we set up new SS
smov ss, ds
mov sp, OFFSET gmove_stack
cCall set_physical_address,<prev_gmove_SS>
push bx
mov bx, si
xor cx, cx ; cx:bx=stack len (for set_sel_limit)
cCall set_sel_limit,<prev_gmove_SS>
pop bx
xor ax, ax
xchg ax, prev_gmove_SS
mov ss,ax ; Switch to new stack location
mov sp,si
FSTI
mov ax,bx
; zero the new TDB
push ax
cCall get_physical_address,<ax>
add ax,initTDBbias
adc dx,0
if PMODE32
YAH_WELL = (SIZE TDB+15) and NOT 15
cCall alloc_data_sel,<dx,ax,0,YAH_WELL>
else
YAH_WELL = (SIZE TDB+15)/16
cCall alloc_data_sel,<dx,ax,YAH_WELL>
endif
mov es,ax
xor ax,ax
mov di,ax
mov cx,SIZE TDB
cld
rep stosb
pop ax
; put the limits in the stack
xor bp,bp ; zero terminate BP chain.
mov ss:[pStackBot],sp
mov ss:[pStackMin],sp
mov ss:[pStackTop],10h
mov ss:[0],bp ; To mark this stack as NOT linked
mov ss:[2],bp ; to another, see PatchStack.
mov ss:[4],bp
; initialize the new TDB
sub sp,SIZE TASK_REGS
mov es:[TDB_taskSS],ss
mov es:[TDB_taskSP],sp
mov cx,topPDB
mov es:[TDB_PDB],cx ; save new PDB
mov es:[TDB_DTA].off,80h ; set initial DTA
mov es:[TDB_DTA].sel,cx
mov bx,1 ; BX = 1
mov es:[TDB_nEvents],bx ; Start this guy up!
mov es:[TDB_pModule],-1 ; EMS requires -1
mov bx,winVer
mov es:[TDB_ExpWinVer],bx ; Windows Version #
mov es:[TDB_sig],TDB_SIGNATURE ; Set signature word.
; initialize the task BP and DS
push es
les bx,dword ptr es:[TDB_taskSP]
mov es:[bx].TASK_BP,bp ; initial BP = 0
mov es:[bx].TASK_DS,bp ; initial DS = 0
pop es
ife ROM ;---------------------------------------------------------------
mov ds,ax ; switch to new DS segment
mov ax,segNewCS ; recover new CS value
push cs ; to free the selector
; do a far return to the new code segment
push ax
mov ax,codeOffset new_code
push ax
ret_far ; FAR return to new code segment
public new_code
new_code:
pop ax
push es
cCall free_sel,<ax> ; Free old CS selector
cCall IPrestoChangoSelector,<cs,MyCSAlias> ; Change our CS Alias
mov es,MyCSAlias ; Change MyCSDS to new DS
assumes es,CODE
mov ax,ds
xchg ax,es:MyCSDS
assumes es,nothing
cCall free_sel,<ax> ; Free old DS selector
call DebugDebug ; do after MyCSDS changes
mov pExitProc.sel,cs ; reset this!!
;;; pusha
;;; cCall get_physical_address,<cs>
;;; add ax, codeOffset end_page_locked
;;; adc dx, 0
;;; mov bx, dx
;;; mov cx, ax
;;; mov di, cs
;;; lsl di, di
;;; sub di, codeOffset end_page_locked
;;; xor si, si
;;; mov ax, 0601h
;;; int 31h ; Unlock some of Kernel!
;;; popa
cCall SelToSeg,<ds> ; Save DS segment value
mov MyDSSeg,ax
cCall SelToSeg,<cs> ; Set segment equivalent
mov MyCSSeg, ax
; calculate the maximum amount that we will allow SetSwapAreaSize to set
mov ax,-1 ; They can only harm themselves.
else ;ROM ---------------------------------------------------------
push es ; code below expects this on stack
mov ax,-1 ; They can only harm themselves.
endif ;ROM ---------------------------------------------------------
mov MaxCodeSwapArea,ax
ifndef WOW ; WOW uses 32 bit profile api's
; Allocate a handle for WIN.INI
xor ax,ax
mov bx,GA_SHAREABLE shl 8 OR GA_MOVEABLE
cCall IGlobalAlloc,<bx,ax,ax>
mov [WinIniInfo.hBuffer], ax
or ax,ax
jz nowinini
mov bx,ax ; put handle into base register
mov ax,hExeHead
mov es,ax
call set_discarded_sel_owner
; Set up the filename
mov word ptr [WinIniInfo.lpProFile], dataoffset szUserPro
mov word ptr [WinIniInfo.lpProFile][2], ds
nowinini:
; Allocate a handle for Private Profiles
xor ax,ax
mov bx,GA_SHAREABLE shl 8 OR GA_MOVEABLE
cCall IGlobalAlloc,<bx,ax,ax>
mov [PrivateProInfo.hBuffer],ax
or ax,ax
jz noprivate
mov bx,ax ; put handle into base register
mov ax,hExeHead
mov es,ax
call set_discarded_sel_owner
noprivate:
endif; WOW
ifdef WOW
; Allocate a ~128K discardable code selector to hide the
; GrowHeap - heap not sorted bugs, also present in Win 3.1.
;
; Since our system DLLs (like krnl386, user, gdi etc) contain a few
; discardable codesgements (of approx 40K), we need not be precise
;
push es
mov ax, 0C000H ; hiword is 01h , totalsize 0x1c000 bytes
mov bx, GA_MOVEABLE OR GA_DISCCODE
cCall IGlobalAlloc,<bx,01h,ax>
or ax,ax
jz short nogrowheap
cCall SetOwner, <ax, hExeHead>
nogrowheap:
pop es
endif; WOW
ife ROM ;----------------------------------------------------------------
; Now shrink off exe header and segment 1 of KERNEL.EXE
mov si,2 ; Segment number
xor ax,ax
xchg oNRSeg,ax
nofastboot:
sub ax,cpShrunk
mov cpShrink,ax ; Amount to shrink by
cCall MyLock,<hLoadBlock>
mov bx,ax
xchg segLoadBlock,ax
cCall get_physical_address,<ax>
mov cx,dx
xchg bx,ax
cCall get_physical_address,<ax>
sub bx,ax
sbb cx,dx
REPT 4
shr cx,1
rcr bx,1
ENDM
mov ax,bx
add cpShrink,ax
push ax
cCall Shrink
pop ax
sub cpShrunk,ax
; Load kernel code segment 2 (non-resident code)
cCall MyLock,<hLoadBlock>
mov bx,-1 ; Indicate loading from memory
cCall LoadSegment,<hExeHead,si,ax,bx>
or ax,ax
jnz ll2
pop es
jmp bootfail
ll2:
inc si ; On to segment 3
xor ax, ax
xchg ax, oMSeg ; Once back only!
or ax, ax
jnz nofastboot
else ;ROM ---------------------------------------------------------
; The ROM kernel 'loads' the other two kernel segments now. Currently
; LoadSegment does little more than define the segment to the debugger
; which has already been done for the primary code & data segments.
cCall LoadSegment,<hExeHead,2,0,-1>
cCall SetROMOwner,<ax,hExeHead>
cCall LoadSegment,<hExeHead,3,0,-1>
cCall SetROMOwner,<ax,hExeHead>
endif ;ROM ---------------------------------------------------------
pop es
call genter
smov ds, es
UnSetKernelDS
SetKernelDS es
;;;mov ax,EMScurPID ; In case an EMS fast boot is going down.
;;;mov ds:[TDB_EMSPID],ax
;;;mov ax,ds:[TDB_EMSPID]
;;;mov PID_for_fake,ax
;;;mov EMScurPID,ax
mov curTDB,ds
mov headTDB,ds
push es
; vectors
SaveVec MACRO vec
mov ax, 35&vec
DOSCALL
mov [di.off], bx
mov [di.sel], es
add di, 4
ENDM
push di
mov di, TDB_INTVECS
SaveVec 00h
SaveVec 02h
SaveVec 04h
SaveVec 06h
SaveVec 07h
SaveVec 3Eh
SaveVec 75h
ifdef WOW
;; Hook Int10 so we can filter calls in WOW (see intnn.asm)
push es
push ds
mov ax,3510h
INT21
mov ax,codeOffset prevInt10proc
SetKernelCSDword ax,es,bx
mov ax,2510h
smov ds,cs
mov dx,codeOFFSET Int10Handler
INT21
pop ds
pop es
endif
pop di
cCall SaveState,<ds>
pop es
mov ds,pGlobalHeap
call gleave
UnSetKernelDS es
mov ax, 32 ; Kernel wants a big handle table
cCall SetHandleCount,<ax>
SetKernelDS
;
; The following variable initialization is done here to avoid having
; relocations in Kernel's data segment.
;
mov lpInt21.off,codeOFFSET Int21Handler
mov lpInt21.sel,cs
;
; Before we hook exception handlers, make sure the DPMI exception
; handler stack is set up the way Windows likes it.
;
mov bl,6
mov ax,0202h ; DPMI get exception handler vector
int 31h
push cx
push dx
mov cx,cs
lea dx,fixing_stack
mov bl,6
mov ax,0203h ; DPMI set exception handler vector
int 31h
pop dx
pop cx
;
; Generate an invalid opcode exception fault. This causes DPMI to call
; our "exception handler."
;
db 0fh,0ffh
fixing_stack:
push bp
mov bp,sp ; BP -> BP RETIP RETCS EC IP CS FL SP SS
;
; Restore the previous invalid exception handler vector.
;
mov bl,6
mov ax,0203h
int 31h
;
; Replace the return address on the DPMI fault handler routine with
; our exit code.
;
lea ax,done_fixing_stack
mov [bp+8],ax
mov [bp+10],cs
lea ax,[bp+16]
mov ss:[pStackBot],ax
mov ss:[pStackMin],sp
mov ss:[pStackTop],offset pStackBot + 150
mov sp,bp
pop bp
retf
done_fixing_stack:
ife ROM
mov es, MyCSAlias
assumes es, CODE
endif
; Hook not present fault for segment reloader.
mov ax,0202h ; Record old not present fault.
mov bl,0Bh
int 31h
mov prevInt3Fproc.off,dx
mov prevInt3Fproc.sel,cx
mov ax,0203h ; Hook not present fault.
mov cx,cs
mov dx,codeOffset SegmentNotPresentFault
int 31h
; Hook GP fault in order to terminate app.
mov bl, 0Dh ; GP Fault
mov ax, 0202h
int 31h
mov prevInt0Dproc.off, dx
mov prevInt0Dproc.sel, cx
mov ax, 0203h
mov cx, cs
mov dx, codeOffset GPFault
int 31h
; Hook invalid op-code in order to terminate app.
mov bl, 06h ; invalid op-code
mov ax, 0202h
int 31h
mov prevIntx6proc.off, dx
mov prevIntx6proc.sel, cx
mov ax, 0203h
mov cx, cs
mov dx, codeOffset invalid_op_code_exception
int 31h
; Hook stack fault in order to terminate app.
mov bl, 0Ch ; stack fault
mov ax, 0202h
int 31h
mov prevInt0Cproc.off, dx
mov prevInt0Cproc.sel, cx
mov ax, 0203h
mov cx, cs
mov dx, codeOffset StackFault
int 31h
; Hook bad page fault in order to terminate app.
mov bl, 0Eh ; page fault
mov ax, 0202h
int 31h
mov prevInt0Eproc.off, dx
mov prevInt0Eproc.sel, cx
mov ax, 0203h
mov cx, cs
mov dx, codeOffset page_fault
int 31h
ifdef WOW
; Hook divide overflow trap in order to get better WOW debugging.
mov bl, 00h ; divide overflow
mov ax, 0202h
int 31h
mov oldInt00proc.off, dx
mov oldInt00proc.sel, cx
mov ax, 0203h
mov cx, cs
mov dx, codeOffset divide_overflow
int 31h
; Hook single step trap in order to get better WOW debugging.
mov bl, 01h ; single step
mov ax, 0202h
int 31h
mov prevInt01proc.off, dx
mov prevInt01proc.sel, cx
mov ax, 0203h
mov cx, cs
mov dx, codeOffset single_step
int 31h
; Hook breakpoint trap in order to get better WOW debugging.
mov bl, 03h ; page fault
mov ax, 0202h
int 31h
mov prevInt03proc.off, dx
mov prevInt03proc.sel, cx
mov ax, 0203h
mov cx, cs
mov dx, codeOffset breakpoint
int 31h
endif
assumes es, nothing
; Do a slimy fix-up of __WinFlags containing processor and protect mode flags
xor ax,ax
mov dx,178
cCall GetProcAddress,<hExeHead,ax,dx>
mov ax,WinFlags
mov es:[bx],ax
ifdef WOW
; get WOW32 thunk table offsets and do fixups
; WARNING: WOW32 has a dependency on this being called after
; kernel is done booting and addresses are fixed
push ds
push dataoffset MOD_KERNEL
call far ptr WOWGetTableOffsets
mov si, dataoffset MOD_KERNEL
mov cx, ModCount ; # fixups to do
mov di, 570 ; first ordinal of the group (DANGER hardcoded from kernel.def)
Mexico:
push si
push di
push cx
push hExeHead
push 0
push di
call GetProcAddress
pop cx
pop di
pop si
mov ax,[si]
mov es:[bx],ax
inc si ; point to next word
inc si
inc di ; get next ordinal
loop Mexico
endif
ife ROM ;--------------------------------
; Can't do slimy fix-ups in ROM--already done by ROM Image Builder
; Do a very slimy fix-up of the runtime constant __0000h
cCall GetProcAddress,<hExeHead,0,183>
mov si,bx
mov bx,00000h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __0040h
cCall GetProcAddress,<hExeHead,0,193>
mov si,bx
mov bx,00040h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __ROMBIOS
cCall GetProcAddress,<hExeHead,0,173>
mov si,bx
mov bx,0F000h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __F000h
cCall GetProcAddress,<hExeHead,0,194>
mov si,bx
mov bx,0F000h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __A000h
cCall GetProcAddress,<hExeHead,0,174>
mov si,bx
mov bx,0A000h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __B000h
cCall GetProcAddress,<hExeHead,0,181>
mov si,bx
mov bx,0B000h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __B800h
cCall GetProcAddress,<hExeHead,0,182>
mov si,bx
mov bx,0B800h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __C000h
cCall GetProcAddress,<hExeHead,0,195>
mov si,bx
mov bx,0C000h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __D000h
cCall GetProcAddress,<hExeHead,0,179>
mov si,bx
mov bx,0D000h
mov ax,2
int 31h
mov es:[si],ax
; Do a very slimy fix-up of the runtime constant __E000h
cCall GetProcAddress,<hExeHead,0,190>
mov si,bx
mov bx,0E000h
mov ax,2
int 31h
mov es:[si],ax
endif ;ROM -------------------------
ifndef WOW
cCall SetUserPro ; Get WIN.INI filename from environment
endif
CheckKernelDS
; Free high memory copy of KERNEL.EXE
ife ROM
cCall IGlobalFree,<hLoadBlock>
mov hLoadBlock,ax
else
xor ax, ax
endif
if PMODE32
.386
mov fs, ax
mov gs, ax
.286p
endif
ifndef WOW
cmp lpWindowsDir.sel,ax
jnz got_win_dir
mov si,dataOffset szUserPro
mov di,dataOffset [WinIniInfo.ProBuf]
cCall IOpenFile,<dssi,dsdi,OF_PARSE>
lea di,[di].opfile
mov lpWindowsDir.sel,ds
mov lpWindowsDir.off,di
mov dx,di
call GetPureName
sub di,dx
dec di
mov cBytesWinDir,di
got_win_dir:
endif
ifdef WOW
; Regular Windows kernel sets up the Windows directory very early in
; boot, before WOW kernel loads WOW32.DLL.
;
; It turns out we can delay setting up the 16-bit copy of the
; windows directory (referred by lpWindowsDir) until here, where
; we're in protected mode and about to set up the system directories
; as well. This allows us to call a GetShortPathName thunk in
; WOW32.
;
mov ds,topPDB
UnSetKernelDS
mov ds,ds:[PDB_environ]
call get_windir ; on return, DS:DI -> windows dir
smov es,ds
SetKernelDS
; Record where to find the 'windows' directory.
BootTrace 'q'
mov lpWindowsDir.sel,es
mov lpWindowsDir.off,di
mov cBytesWinDir,cx
; Record where to find the 'system32' directory.
mov ax,hExeHead
mov es,ax
mov di,es:[ne_pfileinfo]
lea di,es:[di].opFile
mov lpSystemDir.sel,es
mov lpSystemDir.off,di
mov dx,di
call GetPureName
sub di,dx
dec di
mov cBytesSysDir,di
BootTrace 'u'
;
; Under WOW there are two system directories: \nt\system and \nt\system32.
; lpSystemDir points to \nt\system32, while lpSystem16Dir points to
; \nt\system. We return the latter from GetSystemDirectory, since we want
; applications to install their shared stuff in \nt\system, but we want
; to search \nt\system32 before \nt\system when loading modules.
; Set up lpSystem16Dir using the Windows dir + \system.
; Note that the string pointed to by lpSystem16Dir is not null terminated!
mov lpSystem16Dir.sel,ds
mov lpSystem16Dir.off,dataoffset achSystem16Dir
cld
mov si,dataoffset achRealWindowsDir
mov es,lpSystem16Dir.sel
mov di,lpSystem16Dir.off
mov cx,cbRealWindowsDir
rep movsb ; copy Windows dir
mov si,dataoffset Sys16Suffix
mov cx,cBytesSys16Suffix
rep movsb ; tack on "\system"
mov cx,cbRealWindowsDir
add cx,cBytesSys16Suffix
mov cBytesSys16Dir,cx
;
; build the Wx86 system directory "Windir\Sys32x86"
;
mov lpSystemWx86Dir.sel,ds
mov lpSystemWx86Dir.off,dataoffset achSystemWx86Dir
mov es,lpSystemWx86Dir.sel
mov di,lpSystemWx86Dir.off
mov cx,cbRealWindowsDir
mov si,dataoffset achRealWindowsDir
rep movsb ; copy System dir (Windows\System32)
mov si,dataoffset SysWx86Suffix
mov cx,cBytesSysWx86Suffix
rep movsb ; tack on "\Wx86"
mov cx,cbRealWindowsDir
add cx,cBytesSysWx86Suffix
mov cBytesSysWx86Dir,cx
@@:
; WOW DPMI Supports wants to call GlobalDosAlloc and GlobalDosFree so that
; We don't have to write the same code for DPMI support. So we call DPMI
; Here with the addresses of those routines so he can call us back.
mov bx,cs
mov si,bx
mov dx,codeOffset GlobalDosAlloc
mov di,codeOffset GlobalDosFree
mov ax,4f3h
int 31h
; Now that we've built up the system dir from the windows dir, set
; the windows dir to where it should be for this user.
push es
cld
mov di,offset achTermsrvWindowsDir
cCall TermsrvGetWindowsDir,<ds, di, MaxFileLen>
or ax, ax
jz @F ; ax = 0 -> error, just leave windows dir
smov es,ds
mov cx,-1
xor ax,ax
repnz scasb
not cx
dec cx ; length of windows directory
mov lpWindowsDir.sel,ds
mov lpWindowsDir.off,offset achTermsrvWindowsDir
mov cBytesWinDir,cx
@@:
pop es
endif
; Under win 2.11 we allowed the ":" syntax to replace the shell.
; We no longer allow this, however to avoid messing up people
; with batch files that have ":" in them we will strip the
; ":" out of the command line. But we retain the :: syntax
; for the OS/2 VM!!
; We also do the check for the /b switch here. This puts us in "diagnostic
; mode and we set a flag to say this. Later, we will call the DiagInit()
; function to open the log file, etc.
push ds
cld
mov ds,topPDB
UnSetKernelDS
push ds
pop es
mov si,80h
xor ax,ax
lodsb
or al,al
jz no_colon
mov cx,ax
@@: lodsb
cmp al,' '
loopz @B
cmp al,':'
jnz no_colon
cmp byte ptr [si],':'
jz no_colon
mov byte ptr [si][-1],' '
no_colon:
cmp al,'/' ;Switch character?
je CheckSwitch ;Yes
cmp al,'-' ;Other switch character?
jne NoSwitch ;Nope.
CheckSwitch:
lodsb ;Get next char
or al,32 ;Convert to lowercase if necessary
cmp al,'b' ;Diagnostic mode?
jnz NoSwitch ;Nope
cCall DiagInit ;Initialize diagnostic mode
mov WORD PTR [si-2],2020h ;Blank out the switch
NoSwitch:
pop ds
ReSetKernelDS
;** Reset secret flag for memory manager. Fixed segments will go
;** >1MB after this
and fBooting, NOT 2
;** We want to grow the SFT *before* loading the modules,
;** not after, like was the case previous to win3.1
call GrowSFTToMax ;add to SFT chain in p mode
if 1
; old ldinit.c
cld
push ds
smov es,ds
xor ax,ax
xor cx,cx
mov ds,topPDB
UnSetKernelDS
mov si,80h
lodsb
or al,al
jz gwaphics_done
mov cl,al
lodsb
cmp al,' '
mov al,ah
jnz gwaphics_done
lodsb
cmp al,':'
mov al,ah
jnz gwaphics_done
lodsb
cmp al,':'
mov al,ah
jnz gwaphics_done
mov di,dataOffset app_name
find_delineator:
lodsb
stosb
cmp al,' '
ja find_delineator
mov es:[di][-1],ah
mov ds:[80h],ah ; assume no arguments
jnz gwaphics_done
add cx,82h
sub cx,si
smov es,ds
mov di,80h
mov al,cl
stosb
rep movsb
gwaphics_done:
pop ds
ReSetKernelDS
or ax,ax
jz @F
mov graphics,0
@@:
else
cld
xor ax,ax
xor bx,bx
endif
jmps SlowBoot
bootfail:
mov al,1
cCall ExitKernel,<ax>
cEnd nogen
sEnd INITCODE
;-----------------------------------------------------------------------;
; SlowBoot ;
; ;
; ;
; Arguments: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Sat Mar 14, 1987 05:52:22p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
DataBegin INIT
BootSect db 'BOOT',0
BootFile db 'SYSTEM.INI',0
FilesCached db 'CACHEDFILEHANDLES',0
IdleSegLoad db 'LOADSEGMENTSATIDLE',0
ifdef WOW
ExitLastApp db 'CLOSEONLASTAPPEXIT',0
endif
if SHERLOCK
szGPC db 'GPCONTINUE',0
endif
szDebugSect db 'DEBUG',0
szOutputTo db 'OUTPUTTO', 0
szAux db 0 ;'AUX', 0 ; don't return a default
if KDEBUG
szKRInfo db 'KERNELINFO', 0
szKRBreak db 'KERNELBREAK', 0
szWin3Info db 'WIN3INFO', 0
szWin3Break db 'WIN3BREAK', 0
endif
ife PMODE32
Standard db 'STANDARD',0
PadCodeStr db 'PADCODESEGMENTS',0
endif
BootBufLen equ 80
BootBuf db BootBufLen dup (?)
bootmods label byte
DB 'SYSTEM.DRV',0
winmods label byte
ifdef WOW
DB 'KEYBOARD.DRV',0
szAfterKeyboardDriver label byte ;Used so we can tell key driver loaded
DB 'MOUSE.DRV',0
ifdef FE_SB
szBeforeWifeMan label byte ;Used so we can tell key driver loaded
DB 'WIFEMAN.DLL', 0 ;WIFE manager has to be loaded before display driver
endif
DB 'VGA.DRV',0
DB 'SOUND.DRV',0
DB 'COMM.DRV',0
DB 'USER.EXE',0
DB 'GDI.EXE',0
ifdef FE_SB
szBeforeWinNls label byte ;Used so we can tell key driver loaded
DB 'WINNLS.DLL', 0 ;bug #112335
endif
else
DB 'KEYBOARD.DRV',0
szAfterKeyboardDriver label byte ;Used so we can tell key driver loaded
DB 'MOUSE.DRV',0
ifdef FE_SB
szBeforeWifeMan label byte ;Used so we can tell key driver loaded
DB 'WIFEMAN.DLL', 0 ;WIFE manager has to be loaded before
;display driver
endif
DB 'DISPLAY.DRV',0
DB 'SOUND.DRV',0
DB 'COMM.DRV',0
DB 'FONTS.FON',0
DB 'OEMFONTS.FON',0 ; For Internationals use.
DB 'GDI.EXE',0
DB 'USER.EXE',0
ifdef FE_SB
szBeforeWinNls label byte ;Used so we can tell key driver loaded
DB 'WINNLS.DLL', 0
endif
endif
ifdef WOW
defapp label byte
DB 'WOWEXEC.EXE',0
else
defapp label byte
DB 'PROGMAN.EXE',0
endif
Shell label byte
DB 'WOWSHELL',0
;** Ordinal strings for two of the Keyboard driver exports
keymodstr DB 'KEYBOARD',0
keyprocstr DB '#5',0 ; keyprocstr = AnsiToOem
keyprocstr1 DB '#6',0 ; keyprocstr = OemToAnsi
DataEnd INIT
sBegin INITCODE
assumes cs,CODE
assumes ds,nothing
assumes es,nothing
if BootTraceOn
cProc BootTraceChar,<PUBLIC,NEAR,NODATA>, <ax, dx>
parmW char
cBegin
mov dx, 3fdh
@@: in al, dx
test al, 20h
jz @B
mov ax, char
mov dx, 3f8h
out dx, al
cEnd
endif ; BootTraceOn
cProc ttywrite,<PUBLIC,NEAR,NODATA>, <ds, si>
parmD s
cBegin
; cCall lstrlen,<s>
; mov cx, ax
; lds bx, s
; mov bx,1
; mov ah,40h
; int 21h
lds si, s
cld
mov ah, 2
tty1:
lodsb
mov dl, al
or dl, dl
jz tty2
int 21h
jmps tty1
tty2:
cEnd
ifdef WOW
cProc LoadFail,<PUBLIC,NEAR,NODATA>, <ds,si,di,cx>
parmD s
cBegin
;** Put Up a Dialog Box If we can't load a module
; since szPleaseDoIt resides in protected cs we can't concat the module
; name to it -- so we need to copy it to the stack
;szPleaseDoIt db "Please re-install the following module to your system32
; directory: ",13,10,9,9,0
mov di,sp ; save current stack pointer
sub sp,100h ; allocate for new concat'd string on the stack
mov si,sp ; save the start of the stack string
push ss ; copy szPleaseDoIt to the stack buffer
push si
push cs
push codeOFFSET szPleaseDoIt
call lstrcpy
push ss ; concat module name to string on stack
push si
lds cx, s ; get the module name
push ds
push cx
call lstrcat
push ss ;push finished stack string now
push si
push cs ;szMissingMod db "KERNEL: Missing 16-bit module:",0
push codeOFFSET szMissingMod ; Set Caption
push 0 ;No left button
push SEB_CLOSE + SEB_DEFBUTTON ;Button 1 style
push 0 ;No right button
externFP kSYSERRORBOX
call kSYSERRORBOX ;Put up the system message
mov sp,di ; restore sp
cEnd
else // non-WOW
cProc LoadFail,<PUBLIC,NEAR,NODATA>, <ds>
parmD s
cBegin
SetKernelDS
cCall TextMode
mov bx, dataoffset szCRLF
cCall ttywrite, dsbx
mov bx, dataoffset szCRLF
cCall ttywrite, dsbx
mov bx, dataoffset szBootLoad
cCall ttywrite, dsbx
cCall ttywrite, s
mov bx, dataoffset szCRLF
cCall ttywrite, dsbx
cEnd
endif
cProc SlowBoot,<PUBLIC,NEAR>
cBegin nogen
CheckKernelDS
ReSetKernelDS
GPPI macro sect, key, defval, file, storeit
push ds
push dataoffset sect
push ds
push dataoffset key
push defval
push ds
push dataoffset file
call GetPrivateProfileInt
ifb <storeit>
mov defval, ax
endif
endm
GPPS macro sect, key, defval, here, hereLen, file
push ds
push dataoffset sect
push ds
push dataoffset key
push ds
push dataoffset defval
push ds
push dataoffset here
push hereLen
push ds
push dataoffset file
call GetPrivateProfileString
endm
GPPS1 macro sect, key, defval, here, hereLen, file
push ds
push dataoffset sect
push ds
push key
push ds
push defval
push ds
push dataoffset here
push hereLen
push ds
push dataoffset file
call GetPrivateProfileString
endm
GPI macro sect, key, defval, storeit
push ds
push dataoffset sect
push ds
push dataoffset key
push defval
call GetProfileInt
ifb <storeit>
mov defval, ax
endif
endm
ife PMODE32
xor ax,ax
mov al,fPadCode
GPPI Standard, PadCodeStr, ax, BootFile, nostore
or al,ah
mov fPadCode,al
endif
if SHERLOCK
GPI szKernel, szGPC, gpEnable
endif
if KDEBUG
ifdef DISABLE
GPPI szDebugSect, szKRInfo, _krInfoLevel, BootFile
GPPI szDebugSect, szKRBreak, _krBreakLevel, BootFile
GPPI szDebugSect, szWin3Info, _Win3InfoLevel, Bootfile
GPPI szDebugSect, szWin3Break, _Win3BreakLevel, Bootfile
endif
endif ;KDEBUG
GPPS szDebugSect, szOutputTo, szAux, BootBuf, BootBufLen, BootFile
or ax, ax
jz @F
cmp ax, BootBufLen-2
jz @F
mov ah, 3ch ; creat file (zero length)
xor cx, cx
mov dx, dataOffset BootBuf
DOSCALL
jc @F
mov bx, ax
mov ah, 3eh ; now close it
DOSCALL
jc @F
mov ax, 3d42h ; open inherit, deny none, read/write
DOSCALL
jc @F
mov bx, ax ; dup handle
mov cx, 3 ; force AUX to be this file
mov ah, 46h
DOSCALL
mov ah, 3eh ; close temp file
DOSCALL
mov wDefRIP, 'i' ; since AUX is redirected, assume Ignore RIP
@@:
GPPI BootSect, FilesCached, MAXFHCACHELEN, BootFile, nostore
cmp ax, MINFHCACHELEN ; Validate length
jae @F
mov ax, MINFHCACHELEN
@@: cmp ax, MAXFHCACHELEN
jbe @F
mov ax, MAXFHCACHELEN
@@: mov fhCacheLen, ax ; Adjust # of cached file handles
shl ax, 1
shl ax, 1
add ax, dataoffset fhCache
mov fhCacheEnd, ax
GPPI BootSect, IdleSegLoad, 1, BootFile, nostore
mov fPokeAtSegments, al
ifdef WOW
GPPI BootSect, ExitLastApp, 0, BootFile, nostore
mov fExitOnLastApp, al
endif
mov bootExecBlock.lpfcb1.off,dataOffset win_show
mov bootExecBlock.lpfcb1.sel,ds
mov es,topPDB
mov bootExecBlock.lpcmdline.off,80h
mov bootExecBlock.lpcmdline.sel,es
mov lpBootApp.off,dataOffset app_name
mov lpBootApp.sel,ds
cmp graphics,1
jnz sb1
mov lpBootApp.off,dataOffset defapp
mov lpBootApp.sel,ds
sb1: mov di,dataOffset bootMods
sbloop1:
cCall LoadNewExe,<di>
SetKernelDS es
mov cx,-1
xor ax,ax
cld
repnz scasb
cmp di,dataOffset winmods
jb sbloop1
cmp graphics,1
jz sbloop2
; cCall InitFwdRef
jmps sb4
UnSetKernelDS es
sbloop2: ; load USER.EXE, GDI.EXE
ifdef FE_SB
;** If we just load the fae east modules, we want to
;** checks the system locale vale which is far east
;** locale.
;** If system locale is not far east, then we skip
;** to load far east module.
cmp di,dataOffset szBeforeWifeMan
je SB_DoFarEastModule
cmp di,dataOffset szBeforeWinNls
jne SB_DoLoadModule
SB_DoFarEastModule:
cCall GetSystemDefaultLangID
; return: ax is system locale value
cmp ax,411h
je SB_DoLoadModule
cmp ax,412h
je SB_DoLoadModule
cmp ax,404h
je SB_DoLoadModule
cmp ax,804h
je SB_DoLoadModule
cmp ax,0c04h
je SB_DoLoadModule
; skip to next module
mov cx,-1
xor ax,ax
cld
repnz scasb
jmp SB_NotKeyboardDriver
SB_DoLoadModule:
endif
cCall LoadNewExe,<di>
push ax ; Save hInst return value
SetKernelDS es
mov cx,-1
xor ax,ax
cld
repnz scasb
pop si ; Get hInst of latest module in SI
;** If we just loaded the keyboard driver, we want to
;** point our explicit link variables to the AnsiToOem and
;** OemToAnsi functions so OpenFile can use them for the
;** remaining boot modules
cmp di,dataOffset szAfterKeyboardDriver
jne SB_NotKeyboardDriver
push ds ; Save regs we care about
push di
regptr pStr,ds,bx
mov bx,dataOffset keyprocstr
cCall GetProcAddress,<si,pStr>
mov pKeyProc.off,ax
mov pKeyProc.sel,dx
mov bx,dataOffset keyprocstr1
cCall GetProcAddress,<si,pStr>
mov pKeyProc1.off,ax
mov pKeyProc1.sel,dx
pop di
pop ds
SB_NotKeyboardDriver:
cmp di,dataOffset defapp
jb sbloop2
; OPTIMIZE BEGIN
; OPTIMIZE END
sb4:
cCall InitFwdRef ; Gets stuff we can't dynalink to
cCall InternalEnableDOS ; Enable int21 hooks
;sb4:
call check_TEMP
; Get the shell name from SYSTEM.INI
mov ax,dataoffset Shell
GPPS1 BootSect, ax, lpBootApp.off, BootBuf, BootBufLen, BootFile
;** Here we need to convert the command line to ANSI
cmp WORD PTR pKeyProc1[2],0 ; Paranoia...
jz @F
;** Zero terminate the string before passing to OemToAnsi
mov es,bootExecBlock.lpcmdline.sel
mov bl,es:[80h] ; Get length byte
xor bh,bh
xchg BYTE PTR es:[bx+81h],bh ; Replace terminator char with zero
;** Call the keyboard driver
push es ; Save the seg reg
push bx ; Save offset and char saved
push es
push 81h ; Always starts here (fixed offset)
push es
push 81h
cCall [pKeyProc1] ; Call OemToAnsi in keyboard driver
pop bx ; Get saved info
pop es
mov al,bh ; Saved char from string
xor bh,bh
mov BYTE PTR es:[bx+81h],al ; Replace the character
@@:
mov ax,dataOffset bootExecBlock
regptr dsax,ds,ax
cmp graphics,1
jz @F
cCall LoadModule,<lpBootApp,dsax>
jmps asdf
@@: cCall FlushCachedFileHandle,<hUser> ; in case 100 fonts are loaded
farptr lpBootBuf,ds,di
mov di, dataoffset BootBuf
cCall LoadModule,<lpBootBuf,dsax>
asdf:
cmp ax,32
jbe sb6
cCall GetExePtr,<ax>
mov hShell, ax
jmp bootdone
sb6:
ReSetKernelDS
les bx, lpBootApp
krDebugOut DEB_ERROR, "BOOT: unable to load @ES:BX"
cCall LoadFail,<lpBootApp>
; cmp pDisableProc.sel,0 ; Is there a USER around yet?
; jz @F
; cCall pDisableProc
;@@:
jmp bootfail
UnSetKernelDS
cEnd nogen
;------------------------------------------------------------------------
assumes ds,nothing
assumes es,nothing
cProc LoadNewExe,<PUBLIC,NEAR>,<si,di>
parmW pname
cBegin
farptr lpparm,ax,ax
farptr lpBootBuf,ds,di
mov di, dataoffset BootBuf
CheckKernelDS
ReSetKernelDS
ifdef WOW
; ATM Alters system.ini registry boot section to load its own SYSTEM.DRV
; However on WOW this causes us to fail to load correctly. Also we
; would be hard pushed to support the current 16 bit ATM since it relies
; on internals of 16 bit GDI which are not present in WOW.
; For this Beta I'm going to ignore the bootsection of the registry
; when loading drivers and thus ATM will not get installed.
; At least the user will be protected from not being able to boot WOW
; BUGBUG - Consider
; MattFe Oct9 92
mov di,pname
else
GPPS1 BootSect, pname, pname, BootBuf, BootBufLen, BootFile
endif
xor ax,ax
cCall LoadModule,<lpBootBuf,lpparm>
cmp ax,2
jne lne1
krDebugOut DEB_ERROR, "Can't find @DS:DI"
; kerror ERR_LDBOOT,<BOOT: Unable to find file - >,ds,di
jmps lne4
lne1:
cmp ax,11
jne lne2
krDebugOut DEB_ERROR, "Invalid EXE file @DS:DI"
; kerror ERR_LDBOOT,<BOOT: Invalid .EXE file - >,ds,di
jmps lne4
lne2:
cmp ax,15
jnz lne3
krDebugOut DEB_ERROR, "Invalid protect mode EXE file @DS:DI"
; kerror ERR_LDBOOT,<BOOT: Invalid protect mode .EXE file - >,ds,di
jmps lne4
lne3:
cmp ax, 4
jne lne3a
krDebugOut DEB_ERROR, "Out of files (set FILES=30 in CONFIG.SYS) @DS:DI"
; kerror ERR_LDFILES,<BOOT: Out of files, (set FILES=30 in CONFIG.SYS) loading - >,ds,di
jmps lne4
lne3a:
cmp ax, 32
jae lnex
NoLoadIt:
; kerror ERR_LDBOOT,<BOOT: Unable to load - >,ds,pname
krDebugOut DEB_ERROR, "Unable to load @DS:DI (#ax)"
lne4:
cCall LoadFail,dsdi
mov ax,1
cCall ExitKernel,<ax>
lnex:
UnSetKernelDS
cEnd
sEnd INITCODE
;-----------------------------------------------------------------------;
; BootDone ;
; ;
; Boot is done when all of modules are loaded. Here we do a bit of ;
; clean up, such as validating code segments, initing free memory to ;
; CCCC, freeing up the fake TDB, and finally reallocating the init ;
; code away. ;
; ;
; Arguments: ;
; none ;
; ;
; Returns: ;
; nothing ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; all ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Wed Apr 15, 1987 08:53:23p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
DataBegin INIT
externB beg_initdata
szKernel DB 'KERNEL',0
szWindows DB 'WINDOWS',0
if KDEBUG
szDebugOptions DB 'DebugOptions',0
szDebugFilter DB 'DebugFilter',0
szChecksum DB 'EnableSegmentChecksum',0
szSweepFreak DB 'LRUSweepFrequency',0
sz80x87 DB 'NoUse80x87',0
szFastFP DB 'FastFP', 0
externW DebugOptions
externW DebugFilter
ifdef DISABLE
externB fLoadTrace
endif
endif ; KDEBUG
ifdef SDEBUG
szEMSDebug DB 'EnableEMSDebug',0
endif
szgrab_386 DB '386GRABBER',0
if SWAPPRO
szSwapPro DB 'SwapProfile',0
szSwapFile DB 'SWAPPRO.DAT',0
endif
DataEnd INIT
sBegin INITCODE
assumes cs,CODE
assumes ds,nothing
assumes es,nothing
externB beg_initcode
cProc BootDone,<PUBLIC,NEAR>
cBegin nogen
SetKernelDS
if KDEBUG
; Get win.ini [Windows] DebugOptions
GPI szWindows, szDebugOptions, DebugOptions
; Get win.ini [Windows] DebugFilter
GPI szWindows, szDebugFilter, DebugFilter
; Now set various internal flags based on DebugOptions
xor ax,ax
test DebugOptions,DBO_CHECKHEAP
jz @F
inc ax
@@:
mov es,pGlobalHeap
mov es:[hi_check],ax
test DebugOptions,DBO_CHECKFREE
jz @F
or Kernel_flags,kf_check_free
@@:
ifdef DISABLE
xor ax,ax
test DebugOptions,DBO_LOADTRACE
jz @F
mov fLoadTrace, al
@@:
endif ; DISABLE
test DebugOptions,DBO_DISABLEGPTRAPPING
jz wants_trapping
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
wants_trapping:
if SWAPPRO
GPI szKernel, szSwapPro, 1, nostore
mov fSwapPro, al
mov bx,TopPDB
mov ah,50h
pushf
FCLI
call prevInt21Proc
lea dx,szSwapFile
xor cx,cx
mov ah,3Ch
pushf
FCLI
call prevInt21Proc
mov hSwapPro,ax
mov bx,cur_dos_pdb
mov ah,50h
pushf
FCLI
call prevInt21Proc
endif
GPI szKernel, szChecksum, 1, nostore
mov fChkSum,al
GPI szKernel, sz80x87, 0, nostore
or ax,ax
jz wants_8087
mov f8087,0
and WinFlags,NOT WF1_80x87 ;Turn off corresponding WinFlags bit
wants_8087:
GPI szKernel, szFastFP, 1, nostore
mov fastFP, al
GPI szKernel, szSweepFreak, 500, nostore
else
mov ax, 500
endif ; KDEBUG
ifdef WOW
xor ax,ax
endif
or ax,ax
jz nolrusweep
test WinFlags[1], WF1_PAGING
jnz short nolrusweep
mov bx,codeOffset lrusweep
regptr csbx,cs,bx
xor dx,dx
cCall pTimerProc,<dx,ax,csbx>
nolrusweep:
if SDEBUG
GPI szKernel, szEMSDebug, 0, nostore
or ax,ax
jz no_EMS_debug_wanted
or Kernel_flags,kf_EMS_debug
no_EMS_debug_wanted:
endif
if LDCHKSUM
cCall ValidateCodeSegments
endif
if KDEBUG
mov fCheckFree,0
ife PMODE32
call init_free_to_CCCC
endif
endif
; Get the shell name from SYSTEM.INI
GPPS BootSect, szgrab_386, szgrab_386, grab_name, 128, BootFile
mov es,curTDB ; ES = TDB of fake task
push es
cCall DeleteTask,<es> ; Flush bogus task
pop es
xor dx,dx
mov es:[TDB_sig],dx ; Clear signature word.
mov curTDB,dx ; Let someone else be current task
; switch to the temp stack since we're about to Realloc the present one away
mov ax, ss
FCLI
SetKernelDS ss
mov sp,dataOffset gmove_stack
FSTI
cCall free_sel,<ax>
; Shrink DGROUP down to its post initialization size
mov cx,dataOFFSET beg_initdata ; don't need init data
; dx doubles as high word and specifies fixed
; reallocation
xor dx,dx
cCall IGlobalReAlloc,<ds,dx,cx,dx> ; Realloc DGROUP
xor dx,dx
; Now shrink the resident CODE segment
ife ROM
mov cx,codeOFFSET beg_initcode ; dont need init code
; cCall IGlobalReAlloc,<cs,dxcx,dx>
; jmps BootSchedule ; Jump to schedule first app
push cs ; Arguments to GlobalReAlloc
push dx
push cx
push dx
push cs ; Where GlobalReAlloc will eventually return
mov ax,codeOFFSET BootSchedule
push ax
jmp near ptr IGlobalReAlloc ; Jump to GlobalReAlloc
else ;ROM
jmp BootSchedule
endif
UnSetKernelDS ss
UnSetKernelDS
cEnd nogen
;-----------------------------------------------------------------------;
; check_TEMP
;
; If the environment variable TEMP points to garbage then GetTempFile
; screws up. We fix it by wiping out the TEMP string if it points
; to garbage.
;
; Entry:
; none
;
; Returns:
;
; Registers Preserved:
; all
;
; History:
; Thu 11-May-1989 16:39:34 -by- David N. Weise [davidw]
; Wrote it.
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc check_TEMP,<PUBLIC,NEAR>,<ds,es>
ifdef FE_SB
localW pMyBuf
endif
cBegin
pusha
SetKernelDS
sub sp,130
mov di,sp
CheckKernelDS
mov ds,TopPDB
UnSetKernelDS
mov ds,ds:[PDB_environ]
xor si, si ; assume DS:SI points to environment
cCall GetTempDrive,<si>
smov es,ss
cld
stosw
ifdef FE_SB
mov pMyBuf,di ; save string offset(exclude D:)
endif
stmp2:
lodsw
or al,al ; no more enviroment
ifdef FE_SB
jnz @F ; I hate this
jmp stmpNo1
@@:
else
jz stmpNo1
endif
cmp ax,'ET' ; Look for TEMP=
jne stmp3
lodsw
cmp ax,'PM'
jne stmp3
lodsb
cmp al,'='
je stmpYes
stmp3: lodsb
or al,al
jnz stmp3
jmp stmp2
stmpYes:
push si ; save pointer to TEMP
push ds
push si ; spaces are legal, but they
lookForSpace: ; confuse too many apps, so
lodsb ; we treat them as illegal
cmp al, ' '
jz stmpFoundSpace
or al, al
jnz lookForSpace
pop si
cmp byte ptr [si+1],':'
jne stmpnodrive
and byte ptr [si],NOT 20h ; springboard needs this!
dec di
dec di
stmpnodrive:
lodsb
or al,al
jz stmpNo
stosb
jmp stmpnodrive
stmpNo:
mov ax,'~\'
cmp es:[di-1],al ; does it already end in \
jnz stmpNoF ; no, just store it
dec di ; override it
ifdef FE_SB
push si
mov si,pMyBuf
call FarMyIsDBCSTrailByte ;is that '\' a DBCS trailing byte?
cmc
adc di,0 ;skip it if yes.
pop si
endif
stmpNoF:
stosw
xor ax,ax
stosb ; zero terminate it
pop es ; recover pointer to TEMP
pop di
smov ds,ss
mov dx,sp
mov ax,5B00h
xor cx,cx
DOSCALL
jnc stmpClose
cmp al,80 ; Did we fail because the file
jz stmpNo1 ; already exists?
stmpNukeIt:
sub di,5 ; Get the TEMP= part.
@@: mov al,'x'
xchg al,es:[di]
inc di
or al,al
jnz @B
mov byte ptr es:[di-1],0
jmps stmpNo1
stmpClose:
mov bx,ax
mov ah,3Eh
DOSCALL
mov ah,41h
DOSCALL
stmpNo1:
add sp,130
popa
cEnd
stmpFoundSpace:
pop si
pop es
pop di
jmps stmpNukeIt
;-----------------------------------------------------------------------;
; get_windir
;
; Get a pointer to the 'windows' directory.
;
; Entry:
; DS => environment string
;
; Returns:
; CX = length of string
; DI => WFP of 'windows' directory
;
; Registers Preserved:
; all
;
; History:
; Mon 16-Oct-1989 23:17:23 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
ifdef WOW
;-----------------------------------------------------------------------;
; original get_windir looks for the environment variable 'windir' (all
; lowercase) to set the 'windows' directory.
;
; On NT the equivalent environment variable is 'SystemRoot' (all
; uppercase). Hence the code is different.
;
; - nanduri
;
; There are some customers that used the undocumented trick on win31
; of moving windir to some network location by putting win.com there.
; The result would be that the "Windows Directory" would point
; to the network location, and the system directory would be local.
; Currently, the way WINDIR is supported involves hacks in a couple
; of different places. What would be best is if you could do a
; "set windir=xxxx" in your autoexec.nt and we would look for windir
; here and we would code it to emulate win31 behavior. However, that's
; broken right now, and windir is only regenerated after krnlx86.exe
; has finished booting. So the approach taken here is to look for
; a new environment variable called win16dir, and if it exists, make
; the windows directory point to it. Systemroot is still used to
; generate the system directory.
;
; We want to allow NT to be installed into a directory with a long
; name, so we use GetShortPathName on the directory we get from
; either SystemRoot or Win16Dir variables.
; -- DaveHart 9-Feb-96
;-----------------------------------------------------------------------;
szSystemRoot DB 'SYSTEMROOT=',0
szWin16Dir DB 'WIN16DIR=',0
cProc get_windir,<PUBLIC,NEAR>
cBegin nogen
push es
mov ax, cs ; the string is in 'cs', see above
mov es, ax
mov di, codeoffset szSystemRoot
call get_env_var_ptr
push dx
mov dx, ds
mov es, dx
SetKernelDS
mov si, dataoffset achRealWindowsDir
regptr esdi,es,di
regptr dssi,ds,si
mov cx, WINDIR_BUFSIZE
push dx
cCall GetShortPathName, <esdi, dssi, cx>
pop dx
mov cbRealWindowsDir,ax
mov ds, dx ;restore ds
pop dx
assumes ds,nothing
push cx
push di
mov ax, cs ; the string is in 'cs', see above
mov es, ax
mov di, codeoffset szWin16Dir
call get_env_var_ptr
or di, di ;does win16dir exist?
jz gw_not
add sp, 4 ;throw away systemroot
jmp short gw_cont
gw_not:
pop di
pop cx
gw_cont:
; Now ds:di points to the Windows directory string in
; the environment block. It may be a long pathname,
; so fix it up.
smov es, ds
SetKernelDS
mov si, dataoffset achWindowsDir
regptr esdi,es,di
regptr dssi,ds,si
mov cx, WINDIR_BUFSIZE
cCall GetShortPathName, <esdi, dssi, cx>
mov cx, ax
smov ds, es
assumes ds,nothing
pop es
ret
cEnd nogen
cProc get_env_var_ptr,<PUBLIC,NEAR>
cBegin nogen
cld
push si
xor si,si
push di
mov cx,-1
xor ax,ax
repnz scasb
not cx
dec cx ; length of szSystemRoot
pop di
gw_cmp:
mov al, [si]
or al, al
jz gw_exit
push di
push cx
repz cmpsb ; compare the inputstring with szSystemRoot
pop cx
pop di
jnz gw_next ; not szSystemRoot
xor cx,cx ; yes szSystemRoot, cx=0 indicates so
mov di,si
gw_next:
lodsb
or al,al
jnz gw_next ; skip to the terminating NULL.
or cx,cx ; cx==0 implies... found szSystemRoot
jnz gw_cmp ; compare with the next environment string
mov cx,si ; here if found szSystemRoot.
sub cx,di
mov ax,di
dec cx
gw_exit:
mov di,ax
pop si
ret
cEnd nogen
;-----------------------------------------------------------------------;
; original get_windir is within the 'else' 'endif' block
;
;-----------------------------------------------------------------------;
else
cProc get_windir,<PUBLIC,NEAR>
cBegin nogen
cld
push si
xor di,di
xor si,si
gw: lodsw
or al,al ; no more enviroment
jz gw_exit
if ROM
if1
%out Take this out!
endif
;;;!!!only until loader builds proper environment block
or ax,2020h ; ignore case of ENV string
endif
cmp ax,'iw' ; Look for windir=
jne @F
lodsw
if ROM
;;;!!!only until loader builds proper environment block
or ax,2020h ; ignore case of ENV string
endif
cmp ax,'dn'
jne @F
lodsw
if ROM
;;;!!!only until loader builds proper environment block
or ax,2020h ; ignore case of ENV string
endif
cmp ax,'ri'
jne @F
lodsb
cmp al,'='
je gw_got_it
@@: lodsb
or al,al
jnz @B
jmp gw
gw_got_it:
mov di,si
@@: lodsb
or al,al
jnz @B
mov cx,si
sub cx,di
dec cx
gw_exit:
pop si
ret
cEnd nogen
endif
sEnd INITCODE
;------------------------------------------------------------------------
sBegin STACK
; Boot TDB
boottdb equ this byte
DB SIZE TDB dup (0)
if 0
;0123456789012345
; Boot EEMS context save area
NUMBER_OF_BANKS = 4 * (0FFFFh - (LOWEST_SWAP_AREA * 64) + 1)/400h
boottdb_EEMSsave equ this byte
DB NUMBER_OF_BANKS + 100h DUP (0)
endif
; do a clumsy paragraph alignment
rept 16
if ($ - boottdb) and 0Fh
db 0
endif
endm
; Dummy arena entry so boot SS looks like a valid object
DB 'M'
DW -1
DW (BOOTSTACKSIZE + 31)/16
DB 0
DW 5 DUP (0)
; Another in case we have to tweek the low order bit of SS
DB 'M'
DW -1
DW (BOOTSTACKSIZE + 15)/16
DB 0
DW 5 DUP (0)
; Boot stack
stackbottom equ this word
DB BOOTSTACKSIZE DUP (0)
stacktop equ this word
DW -1
sEnd STACK
end BootStrap