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,, 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, mov si,ax mov bx,dataOffset sysprocstr cCall GetProcAddress, mov pSysProc.off,ax mov pSysProc.sel,dx ifdef JAPAN mov bx,dataOffset jpnsysprocstr cCall GetProcAddress, 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, 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, mov ax,WinFlags mov es:[bx],ax endif mov bx,dataOffset timerprocstr cCall GetProcAddress, mov pTimerProc.off,ax mov pTimerProc.sel,dx mov bx,dataOffset sysdisstr cCall GetProcAddress, 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, mov bx,dataOffset displaycrit cCall GetProcAddress, mov pDisplayCritSec.off,ax mov pDisplayCritSec.sel,dx mov bx,dataOffset mousemodstr ; mouse stuff cCall GetModuleHandle, mov si,ax mov bx,dataOffset mousedisstr cCall GetProcAddress, mov pMouseTermProc.off,ax mov pMouseTermProc.sel,dx endif mov bx,dataOffset gdimodstr cCall GetModuleHandle, mov hGDI,ax mov bx,dataOffset usermodstr ; user stuff cCall GetModuleHandle, mov hUser,ax mov si,ax mov bx,dataOffset msgprocstr cCall GetProcAddress, mov pMBoxProc.off,ax mov pMBoxProc.sel,dx mov bx,dataOffset syserrorstr cCall GetProcAddress, mov word ptr pSErrProc[0],ax mov word ptr pSErrProc[2],dx mov bx,dataOffset extprocstr cCall GetProcAddress, mov word ptr pExitProc[0],ax mov word ptr pExitProc[2],dx mov bx,dataOffset disprocstr cCall GetProcAddress, mov word ptr pDisableProc[0],ax mov word ptr pDisableProc[2],dx mov bx,dataOffset yldprocstr cCall GetProcAddress, 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, mov word ptr pUserInitDone[0],ax mov word ptr pUserInitDone[2],dx mov bx,dataOffset pmprocstr cCall GetProcAddress, mov word ptr pPostMessage[0],ax mov word ptr pPostMessage[2],dx mov bx,dataOffset signalproc cCall GetProcAddress, 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, mov word ptr pIsUserIdle[0],ax mov word ptr pIsUserIdle[2],dx mov bx,dataOffset getfreesysrsc cCall GetProcAddress, mov word ptr pGetFreeSystemResources[0],ax mov word ptr pGetFreeSystemResources[2],dx endif mov bx,dataOffset userlstrcmp cCall GetProcAddress, mov word ptr plstrcmp[0],ax mov word ptr plstrcmp[2],dx mov bx,dataOffset stringfunc cCall GetProcAddress, 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, mov word ptr pUserGetFocus[0],ax mov word ptr pUserGetFocus[2],dx mov bx,dataOffset wintask cCall GetProcAddress, mov word ptr pUserGetWinTask[0],ax mov word ptr pUserGetWinTask[2],dx mov bx,dataOffset iswindow cCall GetProcAddress, mov word ptr pUserIsWindow[0],ax mov word ptr pUserISWindow[2],dx mov bx,dataOffset keymodstr cCall GetModuleHandle, mov si,ax mov bx,dataOffset keydisstr cCall GetProcAddress, mov word ptr [pKeyboardTermProc],ax mov word ptr [pKeyboardTermProc+2],dx mov bx,dataOffset keysysreq cCall GetProcAddress, mov pKeyboardSysReq.off,ax mov pKeyboardSysReq.sel,dx mov ax,4 cCall pKeyboardSysReq, ; 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, 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 endif externFP 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,, 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, 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, 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, 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,, 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, ;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 cCall GlobalDOSAlloc, ;allocate the block jcxz GrowSFTToMaxRet ;no memory to allocate cCall SetOwner, ; 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