; File : $Workfile$ ; ; Description : ; ; Original Author : ; ; Last Edited By : $Author$ ; ;-----------------------------------------------------------------------; ; Copyright Work of Caldera, Inc. All Rights Reserved. ; ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND ; CIVIL LIABILITY. ;-----------------------------------------------------------------------; ; ; *** Current Edit History *** ; *** End of Current Edit History *** ; ; $Log$ ; INT2F.A86 1.23 94/11/14 10:34:17 ; Fixed the NWDOS.386 stuff. Still point at startupinfo, but take out the ; vxdname and the vxdnameseg entries. ; INT2F.A86 1.22 94/10/07 09:05:11 ; Added patch 005 as source fix. Removed the stuff to load NWDOS.386 as ; the vxd is no longer needed. ; INT2F.A86 1.21 94/03/24 18:40:10 ; Support para-aligned HMA allocations (Stacker 4 bug) ; INT2F.A86 1.20 93/09/28 19:43:12 ; Extra field to export upper memory root on windows startup ; INT2F.A86 1.19 93/09/06 15:37:35 ; Startup Broadcast fills entry ES:BX into SwStartupInfo "next" link field ; INT2F.A86 1.16 93/08/06 16:35:58 ; Change DELWATCH int 2F hook for getnblk to getblk ; INT2F.A86 1.15 93/07/20 22:47:21 ; Pass on Int 2F/12FF to BIOS - (really to CONFIG) ; INT2F.A86 1.11 93/06/11 02:10:01 ; GateA20 disabled on EXEC for EXEPACKED apps ; ENDLOG ; ; DOS INT 2F Support ; include pcmode.equ include i:msdos.equ include i:mserror.equ include i:driver.equ include i:psp.def include i:doshndl.def include i:redir.equ PCM_CODE CSEG BYTE extrn get_dseg:near ; in PCMIF.PCM extrn do_int24:near ; in PCMIF.PCM extrn dos_entry:near extrn strlen:near ; in SUPPORT.PCM extrn toupper:near ; in UTILS.FDO (in BDOS_CODE) extrn ReadTOD:near ; in UTILS.FDO (in BDOS_CODE) extrn share_delay:near ; in UTILS.FDO (in BDOS_CODE) eject PointHMA: ;-------- ; On Entry: ; None ; On Exit: ; DS = DOS data seg ; BX = bytes available (0 if none) ; ES:DI -> start of available area (FFFF:FFFF if none) ; All other regs preserved ; call get_dseg ; DS = DOS data mov di,0FFFFh mov es,di ; ES:DI = FFFF:FFFF mov bx,hmaRoot test bx,bx ; have we an HMA ? jz PointHMA10 mov di,bx ; ES:DI = start of HMA free area mov bx,es:2[bx] ; BX = length sub bx,4 ; forget the header and bl,not 15 ; make it complete para's PointHMA10: ret QueryHMA: ;-------- ; On Entry: ; None ; On Exit: ; BX = bytes available (0 if none) ; ES:DI -> start of available area (FFFF:FFFF if none) ; All other regs preserved ; push ds call PointHMA ; registers ready for return jmps int2F_BIOS ; give CONFIG processing a chance AllocHMA: ;-------- ; On Entry: ; BX = bytes required ; On Exit: ; ES:DI -> start of available area (FFFF:FFFF if none) ; push ds xchg ax,bx ; AX = bytes required add ax,15 and al,not 15 ; round up to para's call PointHMA xchg ax,bx cmp ax,bx ; enough room up there ? jae AllocHMA10 mov di,es ; ES:DI = FFFF:FFFF jmps AllocHMA20 AllocHMA10: add hmaRoot,bx ; set new start mov ax,es:2[di] ; get length sub ax,bx ; subtract what we just allocated mov es:2[di+bx],ax ; set new length cmp ax,4 ; have we shrunk to zero spare ? mov ax,es:[di] ; move link field to mov es:[di+bx],ax ; new head ja AllocHMA20 mov hmaRoot,ax ; set new hmaRoot AllocHMA20: mov ax,4A02h ; "restore" AX pop ds iret eject ; ++++++++++++++++++++++++++++ ; Int 2F - Multiplex Interrupt ; ++++++++++++++++++++++++++++ ; ; This interrupt is used by DBASE III Plus ; ; On Entry:- AH - Multi-Plex Number ; 01 - Print Spooler ; 02 - Assign Command (Documented) ; 05 - Critical Error Msg ; 06 - Assign Command (By Inspection) ; 08 - DRIVER.SYS Interface for MS-DOS 3.xx ; 10 - Share Command ; 11 - Internal DOS - Network Hooks ; 12 - Internal DOS - Support Services ; 13 - Original INT 13 ROS ISR Address (BIOS) ; 14 - NLSFUNC utility ; AD - IBM CodePage Screen Driver ; B7 - Append Command ; B8 - Network Command ; ; AL - Function Code ; 00 - Get Installed State (All) ; 01 - Submit File (PRINT) ; 02 - Cancel File (PRINT) ; 03 - Cancel All Files (PRINT) ; 04 - Spooler Status (PRINT) ; 05 - End of Status (PRINT) ; ; The Network Test returns the current Network configuration in ; BX when the Get Installed State is requested. ; ; BX = 0008h Redirector | Increasing ; BX = 0080h Receiver | Network ; BX = 0004h Messenger | Functionality ; BX = 0040h Server V ; Public int2F_entry int2F_entry: sti cld cmp ah,012h ! je i2f_12 ; intercept the AH=12 subfunctions cmp ah,011h ! je i2f_11 ; intercept the AH=11 subfunctions cmp ah,010h ! je i2f_10 ; intercept the AH=10 subfunctions cmp ah,005h ! je i2f_05 ; intercept the AH=05 subfunctions cmp ax,4A01h! je QueryHMA ; intercept Query Free HMA Space cmp ax,4A02h! je AllocHMA ; intercept Allocate HMA space cmp ah,016h ! jne int2F_exit ; intercept the AH=16 subfucntions jmp WindowsHooks ; go do windows things... int2F_exit: push ds ; pass onto BIOS now call get_dseg ; trying to remain ROMMABLE int2F_BIOS: jmpf ds:int2FNext ; hence this complication eject i2f_05: ;------ ; CRITICAL ERROR MSG ; This is the critical error message interceptor. ; On Entry: AL = extended error code. ; On Exit: if CY clear then ES:DI -> ASCIIZ string to be used in place ; of the default error message stc ; please use the default message retf 2 ; IRET, but keep flags eject i2f_10: ;------ ; SHARE cmp al,i2f_10size ; do we do this one ? jae int2F_exit ; no, skip it shl al,1 ; we need a word offset jz int2F_exit ; exit if share installation check cbw ; zero AH xchg ax,bx ; we will index with it push ds call get_dseg ; get PCMode data seg push ds ! pop es call i2f_10tbl[bx] ; execute the function pop ds retf 2 ; and return eject i2f_11: ;------ ; MSNET redirector test al,al ; is it installation check ? jz i2f_11_10 mov ax,1 ; no, return ED_FUNCTION error stc ; indicate an error i2f_11_10: retf 2 ; return eject i2f_12: ;------ ; DOS Internal ; Support DOS internal functions here cmp al,0FFh ; should we pass it on to the BIOS ? je int2F_exit ; yes, do so cmp al,i2f_12size ; do we do this one ? jae i2f_12_bad ; no, skip it push bp xor ah,ah add ax,ax ; make sub-func a word mov bp,ax ; we need offset in pointer register mov ax,i2f_12tbl[bp] ; get address of service routine mov bp,sp ; BP points to stack frame call ax ; call the service routine pop bp i2f_12_exit: retf 2 ; IRET, but returning flags i2f_12_bad: mov ax,-ED_FUNCTION stc retf 2 i2f_12tbl dw i2f_1200 dw i2f_1201 dw i2f_1202 dw i2f_1203 dw i2f_1204 dw i2f_1205 dw i2f_1206 dw i2f_12nyi ; Move disk buffer dw i2f_1208 dw i2f_12nyi ; DS:DI -> Disk Buffer ?? dw i2f_120A dw i2f_120B dw i2f_120C dw i2f_120D if DOS5 dw share_delay ; delay else dw i2f_120E ; get buffers endif dw i2f_12nyi ; relink buffer ES:DI ([DI+5].20 <- 0) - Trout dw i2f_1210 dw i2f_1211 dw i2f_1212 dw i2f_1213 dw i2f_1214 dw i2f_12nyi ; Disk buffer DS:SI ??? (Write - Trout) dw i2f_1216 dw i2f_1217 dw i2f_1218 dw i2f_1219 dw i2f_121A dw i2f_121B dw i2f_121C dw i2f_121D dw i2f_121E dw i2f_121F dw i2f_1220 dw i2f_1221 dw i2f_1222 dw i2f_1223 dw share_delay dw i2f_1225 dw i2f_1226 dw i2f_1227 dw i2f_1228 dw i2f_1229 dw i2f_122A dw i2f_122B dw i2f_122C dw i2f_122D i2f_12size equ ((offset $) - (offset i2f_12tbl))/2 i2f_12nyi: ; Sets CY the falls through to installation check - so returns ax = 00FF ; Who knows what to do ? stc ; indicate problem ? i2f_1200: mov ax,00FFh ret i2f_1201: ; Close file ??? (at current_dhndl) les di,current_dhndl mov bx,es:DHNDL_WATTR[di] test bh,DHAT_REMOTE/100h jz i2f_1201_10 ; is it networked ? mov ax,I2F_CLOSE int 2fh ; then close using int 2f call i2f_1201_10: ; else do nothing for now ret i2f_1202: ; Get Interrupt Vector pointer xor bx,bx mov es,bx ; point at the vectors mov bl,8[bp] ; pick up which vector add bx,bx add bx,bx ; make it a DWORD offset ret i2f_1203: ; Get DOS Data segment jmp get_dseg ; return DS = DOS data seg i2f_1204: ; Normalise path character mov ax,8[bp] ; the char is on the stack tobslash: cmp al,'/' ; if it's a fslash jne i2f_1204_10 mov al,'\' ; make it a bslash i2f_1204_10: cmp al,'\' ; set ZF if bslash ret i2f_1205: ; Output Character on the stack push dx mov ah,MS_C_WRITE mov dx,8[bp] ; get char from the stack call dos_entry ; and output it pop dx ret i2f_1206: ; Invoke critical error INT 24 push ds mov ax,8[bp] ; action/drive on stack mov es,0[bp] ; seg was in BP call get_dseg ; get the segment right call do_int24 ; invoke the critical error handler push ax les ax,int24_esbp mov [bp],ax ; really return new BP pop ax pop ds ret i2f_1208: ; Decrement word at ES:DI, skipping zero mov ax,es:word ptr [di] ; return the word in AX i2f_1208_10: dec es:word ptr [di] ; dec it jz i2f_1208_10 ; dec again if it's zero ret i2f_120A: push ds lds si,current_ddsc ; point at current driver lodsb ; get the drive cbw ; pretend dos area read pop ds mov err_drv,al mov rwmode,ah ; set error drive for Int 24h mov ax,3 ; return a Fail ? stc ; return as error ret i2f_120B: ; ES:DI -> system file table entry mov ax,20h ; sharing violation stc ; return as error ret i2f_120C: ; Open file ??? (at current_dhndl) les di,current_dhndl ; would need to call the device driver, but as we don't support this for ; block devices and as it is generally not supported for remote files (but ; only known to be called from redirectors) we leave this out for later test es:byte ptr DHNDL_MODE+1[di],DHM_FCB/100h jz i2f_120C_10 ; is it an FCB open ? mov ax,current_psp mov es:DHNDL_PSP[di],ax ; update owning PSP field i2f_120C_10: ; else do nothing for now ret i2f_120D: ; Get Date/Time push ds push es push cx push bx push si push di push ss pop ds call ReadTOD pop di pop si pop bx pop cx pop es pop ds ret if DOS5 eq 0 i2f_120E: ; Disk Buffers ; On Return ES:DI -> first disk buffer ; les di,ss:bcb_root ; get head of buffer chain ret endif i2f_1210: ; Find Dirty Buffer Entry DS:SI -> 1st buffer, On exit DS:SI-> 1st dirty buffer ; ZF set if none found xor ax,ax ; never find dirty buffers ret i2f_1211: ; Normalise ASCIIZ filename DS:SI -> source buffer, ES:DI -> dest buffer ; make uppercase, fslash becomes bslash ; (Stops at slash - Trout) lodsb ; get a character call toupper ; upper case it call tobslash ; convert '/' to '\' stosb ; plant it test al,al ; terminating zero ? jnz i2f_1211 mov ax,8[bp] ; AX from stack ret i2f_1212: ; Get length of ASCIIZ string ES:DI push ds ! push si push es ! pop ds mov si,di ; make DS:SI -> ASCIIZ call i2f_1225 ; then use our other primitive pop si ! pop ds ret i2f_1213: ; Upperase character on stack mov ax,8[bp] ; get the character jmp toupper ; use BDOS Intl routine i2f_1214: ; Compare far pointers DS:SI with ES:DI cmp di,si jne i2f_1214_10 push ax ! push bx mov ax,ds mov bx,es cmp ax,bx pop bx ! pop ax i2f_1214_10: ret i2f_1216: ; Get address in ES:DI of DOSHNDL for file BX push ds call get_dseg ; we work with the PCMODE data les di,file_ptr ; get the address of the first entry pop ds push bx ; handle # in BX i2f_1216_10: cmp bx,es:DCNTRL_COUNT[di] ; handle in this block? jb i2f_1216_20 ; skip if yes sub bx,es:DCNTRL_COUNT[di] ; update the internal file number les di,es:DCNTRL_DSADD[di] ; get the next entry and check cmp di,0FFFFh ; for the end of the list jnz i2f_1216_10 pop ax ; handle # back in AX stc ; invalid file handle number ret i2f_1216_20: push dx ; save DX and calculate the offset mov ax,DHNDL_LEN ; of the DOS Handle mul bx add di,ax ; add structure offset (should be 0) add di,DCNTRL_LEN ; and then skip the header pop dx pop ax ; handle # back in AX ; clc ret ; valid file handle number i2f_1217: ; Default Drive ??? ; On Exit: ; AL = drive we have set to, DS:SI -> LDT structure call get_dseg ; DS -> PCMODE data mov ax,8[bp] ; get the drive cmp al,last_drv ; do we have an LDT for it ? jae i2f_1217_10 ; if not do no more cmp word ptr ldt_ptr+2,0 ; valid LDT ? je i2f_1217_10 push ax mov ah,LDT_LEN mul ah lds si,ldt_ptr add si,ax ; DS:SI -> requested LDT, current_LDT mov ss:word ptr current_ldt,si mov ss:word ptr current_ldt+2,ds pop ax stc ; indicate NO error (CY inverted) i2f_1217_10: cmc ret ; CY set if invalid i2f_1218: ; DS:SI -> User register on DOS Call call get_dseg ; we save SS:SP after PUSH$DOS lds si,int21regs_ptr ; in this location ret i2f_1219: ; Stack = drive (0=default, 1 = A: etc) push ds ! push si ! push word ptr 8[bp] dec byte ptr 8[bp] ; make drive zero based cmp byte ptr 8[bp],0ffh ; do we want the default ? jne i2f_1219_10 call get_dseg mov al,current_dsk mov byte ptr 8[bp],al ; use the default drive i2f_1219_10: call i2f_1217 ; set's up current_ldt jc i2f_1219_20 test ds:byte ptr 44h[si],40h ; is it valid LDT ? jnz i2f_1219_20 stc ; indicate an error i2f_1219_20: pop word ptr 8[bp] ! pop si ! pop ds ret i2f_121A: ; Get files drive DS:SI -> drives, AL = drive xor ax,ax ; assume default drive cmp ds:byte ptr 1[si],':' jne i2f_121A_10 ; if no drive letter, then default mov al,ds:byte ptr [si] test al,al ; null string ? jz i2f_121A_10 ; then it's the default drive call toupper sub al,'A'-1 ; make one based jbe i2f_121A_20 ; it's invalid.. push ds call get_dseg cmp al,last_drv ; is it a valid drive ? pop ds ja i2f_121A_20 ; yes, return it i2f_121A_10: clc ret i2f_121A_20: mov al,0FFh ; invalid drive stc ret i2f_121B: ; On Entry CX = year-1980 ; On Exit AL = days in February push bx mov bx,offset days_in_month+1 mov ds:byte ptr [bx],28 ; assume 28 days in Feb test cl,3 ; is it a leap year ? jnz i2f_121B_10 inc ds:byte ptr [bx] ; yes, we have 29 i2f_121B_10: mov yearsSince1980,cl ; save the year mov al,ds:byte ptr [bx] ; return the days in Feb pop bx ret i2f_121C: ; Checksum Memory CX bytes at DS:SI, DX = initial checksum ; DX = final checksum ; I've seen this used to total days in N months. ; On Entry: ; CX = current month ; DX = total days in prior years ; DS:SI -> days-per-month table ; On Exit: ; DX = Total days to start of current month ; xor ax,ax ; clear AX jcxz i2f_121C_20 ; check for zero bytes i2f_121C_10: lodsb ; get a byte add dx,ax ; add to the checksum loop i2f_121C_10 ; until we run out i2f_121C_20: ret i2f_121D: ; Calculate Date ; On Entry: ; CX = 0 ; DX = total day count this year ; DS:SI -> days-per-month table ; On Exit: ; CX = Month ; DX = Day ; xor ax,ax i2f_121D_10: lodsb inc cx sub dx,ax jnb i2f_121D_10 dec cx ; undo the last count add dx,ax ; undo the sub cmp dx,ax ; get the flags right ret i2f_121E: ; Compare Filenames at DS:SI and ES:DI push si ! push di ! push cx call i2f_1225 ; find length of DS:SI filename push cx call i2f_1212 ; find length of ES:DI filename pop ax cmp ax,cx ; if lengths not the same jne i2f_121E_20 ; don't even bother i2f_121E_10: push cx lodsb call toupper call tobslash ; normalise slash characters push ax ; save it mov al,es:byte ptr [di] inc di call toupper call tobslash ; normalise slash again pop cx ; recover the character cmp al,cl ; are they the same? pop cx loope i2f_121E_10 ; yes, try again if we have any left i2f_121E_20: pop cx ! pop di ! pop si mov ax,8[bp] ; return stack value in AX ret i2f_121F: ; Build drive info into block ; Stack = Drive (1=A: etc) push ds ! push si ! push dx call get_dseg les di,current_ldt push di mov ax,8[bp] ; get the drive we want to do stosb ; plant the ASCII xchg ax,dx ; save drive in DX mov ax,'\:' stosw ; we have d:\ xor ax,ax mov cx,LDT_FLAGS-3 rep stosb ; zero rest of name and flags ; lea di,LDT_FLAGS and dl,1fh ; convert from ASCII dec dx ; into zero based drive number cmp dl,phys_drv ; valid physical drive ? jae i2f_121F_10 ; mark it as such mov ax,LFLG_PHYSICAL i2f_121F_10: stosw ; set flags ; lea di,LDT_PDT lea si,ddsc_ptr-18h i2f_121F_20: lds si,18h[si] cmp si,-1 je i2f_121F_30 cmp dl,[si] ; is this the DDSC for the drive jne i2f_121F_20 ; if so save it away i2f_121F_30: xchg ax,si ; AX = DDSC offset stosw mov ax,ds ; AX = DDSC seg stosw ; lea di,LDT_BLK mov ax,0FFFFh ; AX = FFFF stosw ! stosw ! stosw ; fill in block info ; lea di,LDT_ROOTLEN mov ax,2 stosw ; set root length pop di pop dx ! pop si ! pop ds ret i2f_1220: ; Get pointer to system file table number for handle BX into ES:DI push ds call get_dseg mov es,current_psp mov ax,6 ; assume illegal cmp bx,PSP_XFNMAX ; is it a legal handle cmc ; invert CY for error return jc i2f_1220_10 ; no, forget it les di,PSP_XFTPTR ; get XFT from PSP add di,bx ; add in the offset ; clc i2f_1220_10: pop ds ret i2f_1221: mov ah,MS_X_EXPAND ; let the FDOS do the walking... call DOS ; and call our internal entry point jnc i2f_1221_10 neg ax ; get error code correct stc ; before returning error i2f_1221_10: ret i2f_1222: ; Store error class, locus, action from DS:SI i2f_1222_10: lodsw cmp al,byte ptr error_code ; have we found the error ? je i2f_1222_20 inc al ; or hit the end of the list ? jz i2f_1222_20 lodsw ; skip this one jmp i2f_1222_10 ; and try the next i2f_1222_20: cmp ah,0ffh ; valid error class ? je i2f_1222_30 mov error_class,ah i2f_1222_30: lodsw cmp al,0ffh je i2f_1222_40 mov error_action,al i2f_1222_40: cmp ah,0ffh je i2f_1222_50 mov error_locus,ah i2f_1222_50: ret i2f_1223: ; On Entry buffer at 4E6 filled with Device name - eg. "NAME1 " ; Preserve word ptr [4E6] ; if byte ptr [4E6] = 5 then byte ptr [4E6] = E5 ; if byte ptr [506] & 8 then exit now with STC ; otherwise work down device chain ; Find device driver for device NAME1 ; Check if character device push ds call get_dseg if FALSE push word ptr name_buf ; save 1st char of name test magic_byte,8 ; magic location and number ?? jnz i2f_1223_40 ; can we do the check ? cmp name_buf,5 jne i2f_1223_10 ; if 1st char is 5, make it mov name_buf,0e5h ; an E5 i2f_1223_10: endif mov si,offset nul_device ; start from NUL i2f_1223_20: test ds:DH_ATTRIB[si],DA_CHARDEV jz i2f_1223_30 ; skip unless character device mov cx,8 lea di,name_buf ; point at name we are looking for push si lea si,ds:DH_NAME[si] ; point a device name repe cmpsb ; compare the names pop si jne i2f_1223_30 ; if we found it, save info mov es:word ptr current_device,si mov es:word ptr current_device+2,ds mov bh,ds:byte ptr DH_ATTRIB[si] or bh,0e0h xor bh,20h ; clear this bit clc ; we found it jmps i2f_1223_50 i2f_1223_30: lds si,ds:DH_NEXT[si] cmp si,0ffffh ; any more entries ? jne i2f_1223_20 ; yes, do them i2f_1223_40: stc i2f_1223_50: if FALSE pushf call get_dseg ; we may have scambled DS popf pop word ptr name_buf ; restore 1st character endif pop ds ret i2f_1225: ; Get length of ASCIIZ string DS:SI call strlen inc cx ; include the terminating zero mov ax,8[bp] ; restore AX from stack ret ; The following are NOT required for MSNET - they are used by NLSFUNC i2f_1226: ; Open the file at DS:DX mov al,cl ; open mode in CL on entry mov ah,MS_X_OPEN ; open the file DOS: push ds ! push es ! pop ds ! pop es call dos_entry ; reverse DS/ES before for dos_entry push ds ! push es ! pop ds ! pop es ret i2f_1227: ; Close file BX mov ah,MS_X_CLOSE ; close the file jmps DOS i2f_1228: ; LSEEK on file BX mov ax,[bp] ; seek mode in BP on entry mov ah,MS_X_LSEEK ; do the seek jmps DOS i2f_1229: ; Read from file BX mov ah,MS_X_READ jmps DOS i2f_122A: ; Set fastopen entry point to DS:SI ; SI = FFFF, sdont't set - just check if installed mov ax,si ; AX = offset inc ax ; AX = 0 if it's an installation check stc ; assume it is, and say not installed jne i2f_122A_10 clc ; fail new installation i2f_122A_10: ret i2f_122B: ; IOCTL mov al,[bp] ; get IOCTL minor mov ah,MS_X_IOCTL jmps DOS i2f_122C: ; Get 2nd device driver header address push ds call get_dseg lds ax,ds:dword ptr nul_device mov bx,ds ; BX:AX -> 2nd device header pop ds ret i2f_122D: ; Get extended error code mov ax,error_code ret ; ; Our FDOS extentions live here ; if DELWATCH extrn locate_buffer:near extrn flush_drive:near extrn delfat:near extrn allocate_cluster:near extrn getblk:near extrn change_fat_entry:near extrn fixup_hashing:near ; for speed/code size we just call directly in BLACK.A86 endif i2f_10tbl dw i2f_10nyi ; never gets here... dw i2f_1001 ; install fdos hook if DELWATCH if FALSE dw i2f_1002 ; read buffer dw i2f_1003 ; flush buffers dw i2f_1004 ; free fat chain dw i2f_1005 ; allocate cluster dw i2f_1006 ; next cluster dw i2f_1007 ; update fat entry dw i2f_1008 ; fixup checksums else dw locate_buffer ; ask BLACK to find that buffer dw flush_drive ; ask BLACK to flush buffers dw delfat ; ask BLACK to release FAT chain dw allocate_cluster; ask DEBLOCK to allocate space dw getblk ; ask DEBLOCK to return next block dw change_fat_entry; ask DEBLOCK to update fat entry dw fixup_hashing ; ask BLACK to fixup hashing/checksums endif dw i2f_1009 ; directory buffer info endif i2f_10size equ (offset $ - offset i2f_10tbl)/2 i2f_1001: ;-------- ; install fdos stub ; ; On Entry: ; DX:AX -> new fdos_stub entry address ; On Exit: ; None ; call get_dseg ; get PCMode data seg mov word ptr fdos_stub,ax ; fixup our share stubs mov word ptr fdos_stub+WORD,dx i2f_10nyi: ret if DELWATCH if FALSE i2f_1002: ;-------- ; read buffer ; On Entry: ; CH = 0FFh (pre-read required) ; CL = BF_ISFAT/BF_ISDIR/BF_ISDATA ; AH:DX = 24 bit sector number ; On Exit: ; ES:SI -> Buffer control block ; jmp locate_buffer i2f_1003: ;-------- ; flush buffers ; On Entry: ; AL = drive ; AH = buffer type to flush (BF_ISFAT+BF_ISDIR+BF_ISDATA) ; On Exit: ; None ; jmp flush_drive i2f_1004: ;-------- ; free fat chain ; On Entry: ; AX = 1st block to release on current drive ; On Exit: ; None jmp delfat i2f_1005: ;-------- ; allocate cluster ; On Entry: ; AX = block to start search from (eg. current end of file) ; 0000 = start of disk ; On Exit: ; AX = 0000 if none available ; else allocated block (marked as End Of Chain) ; jmp allocate_cluster ; ask DEBLOCK.A86 to allocate some space i2f_1006: ;-------- ; get next cluster ; On Entry: ; AX = current block ; On Exit: ; AX = next block in chain ; jmp getblk ; ask DEBLOCK.A86 to return next block i2f_1007: ;-------- ; change fat entry ; On Entry: ; AX = fat entry to change ; DX = new value ; On Exit: ; None ; jmp change_fat_entry ; ask DEBLOCK.A86 to modify FAT entry i2f_1008: ;-------- ; update hash code for directory entry on current drive ; On Entry: ; AX = segment of dir buffer ; CX = cluster to fixup (0 = root) ; DI = directory entry index(clipped to cluster if subdir) ; AX:SI-> dir entry (single entry for hashing) ; On Exit: ; None ; jmp fixup_hashing endif i2f_1009: ;-------- ; return dirbuf info ; On Entry: ; None ; On Exit: ; ES:DI -> 128 byte directory record buffer ; ES:SI -> dir bcb structure ; 0[si] = drive (FF = invalid) ; 1[si] = low byte of record number ; 2[si] = mid byte of record number ; 3[si] = hi byte of record number ; push cs ! pop es mov si,offset invalid_dir_bcb ret invalid_dir_bcb db 0ffh ; drive is invalid ; db ?,?,? ; don't bother about record number endif ;DELWATCH WindowsHooks: ;------------ ; On Entry: ; AH = 16h, it's a windows broadcast ; AL = subfunction, other regs as appropriate ; On Exit: ; Various ; if DOS5 cmp al,07h ; 1607: Virtual device init je WindowsDOSMGR endif test dx,1 ; is it a DOSX broadcast ? jnz WindowsExit cmp al,05h ; 1605: Windows enhanced mode init je WindowsStartup if DOS5 cmp al,06h ; 1606: Windows enhanced mode exit je WindowsShutdown endif WindowsExit: iret WindowsStartup: ;-------------- push ds call get_dseg ; DS -> our data if DOS5 inc criticalSectionEnable ; enable Int 2Ah for Windows inc WindowsHandleCheck endif ;;if 0 Put this back in, as instance data still required ;; Removed pointer to vxd in HEADER.A86 BAP mov SwStartupInfo+2,bx ; Commented out, as NWDOS.386 mov SwStartupInfo+4,es ; no longer needed. push ds pop es ; ES -> pcmode data mov bx,offset SwStartupInfo ;;endif jmp int2F_BIOS ; pass on to the BIOS if DOS5 WindowsShutdown: ;--------------- push ds call get_dseg ; DS -> our data dec criticalSectionEnable ; enable Int 2Ah for Windows dec WindowsHandleCheck pop ds sub dx,dx ; return success iret WindowsDOSMGR: ;------------- cmp bx,15h ; is it DOS manager? jne WindowsExit ; forget the others ; cmp cx,0 jcxz WindowsCX0 dec cx jcxz WindowsCX1 dec cx ! dec cx ! dec cx jcxz WindowsCX4 dec cx jcxz WindowsCX5 iret WindowsCX0: ;---------- push ds call get_dseg push ds pop es ; ES = DOS data segment pop ds lea bx,windowsData ; ES:BX -> secret variables inc cx ; tell them we've responded iret WindowsCX1: ;---------- mov bx,dx ; entry DX=1Fh, exit BX=1Fh mov ax,0B97Ch ; AX, DX are magic values mov dx,0A2ABh ; xor cx,cx ; CX = 0 iret WindowsCX4: ;---------- xor dx,dx ; xor cx,cx ; CX = 0 iret WindowsCX5: ;---------- ; entry: ES:DI -> device driver ; determine device driver size in bytes push ds test di,di ; not primary DEVICE= driver? jnz WindowsCX5NoDev ; can't have DMD preceeding it mov ax,es ; get device segment dec ax ; DMD is one paragraph lower down mov ds,ax ; DS:DI -> device DMD inc ax ; AX = device driver segment cmp ds:byte ptr 0[di],'D' ; see if 'D'device= jne WindowsCX5NoDev ; skip if not cmp ax,ds:word ptr 1[di] ; owned by the driver ? jne WindowsCX5NoDev ; skip if not mov ax,10h ; bytes per paragraph mul ds:word ptr 3[di] ; bytes in device driver pop ds mov bx,dx ; BX = high word xchg ax,cx ; CX = low word mov ax,0B97Ch ; AX, DX are magic values mov dx,0A2ABh iret WindowsCX5NoDev: ; ES:DI -> not an external device pop ds xor ax,ax xor dx,dx ; xor cx,cx ; CX = 0 iret endif eject PCMODE_DATA DSEG WORD extrn hmaRoot:word extrn last_drv:byte extrn phys_drv:byte extrn ddsc_ptr:dword extrn current_psp:word extrn current_dsk:byte extrn net_delay:word extrn nul_device:byte extrn error_code:word extrn error_class:byte extrn error_action:byte extrn error_locus:byte extrn file_ptr:dword extrn ldt_ptr:dword extrn current_device:dword extrn current_ldt:dword extrn current_dhndl:dword extrn current_ddsc:dword extrn yearsSince1980:byte extrn days_in_month:byte extrn name_buf:byte extrn int21regs_ptr:dword extrn int24_esbp:dword extrn int2FNext:dword extrn fdos_stub:dword extrn SwStartupInfo:word extrn err_drv:byte extrn rwmode:byte if DOS5 extrn indos_flag:byte, machine_id:byte, internal_data:byte, dmd_upper_root:word extrn criticalSectionEnable:byte extrn WindowsHandleCheck:byte GLOBAL_DATA dseg windowsData dw 5 ; version number ? dw $ ; dummy dw $ ; dummy dw offset indos_flag dw offset machine_id dw offset internal_data-10 dw offset dmd_upper_root else extrn bcb_root:dword endif end