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

863 lines
17 KiB
NASM

title INT21 - INT 21 handler for scheduler
.xlist
include kernel.inc
include tdb.inc
include pdb.inc
include eems.inc
include kdos.inc
ifdef WOW
include vint.inc
endif
.list
externFP FileCDR_notify
DataBegin
externB PhantArray
externB DOSDrives
externB CurDOSDrive
externW curTDB
DataEnd
assumes DS,NOTHING
sBegin CODE
assumes CS,CODE
;externNP GrowSFT
externNP PassOnThrough
externNP final_call_for_DOS
externNP real_DOS
externNP MyUpper
externNP Int21Handler
ifdef FE_SB
externNP MyIsDBCSLeadByte ;near call is fine
endif
externFP ResidentFindExeFile
externFP GetModuleHandle
externFP FlushCachedFileHandle
externFP WOWDelFile
public ASSIGNCALL
public NAMETRANS
public DLDRIVECALL1
public DLDRIVECALL2
public XENIXRENAME
public FCBCALL
public PATHDSDXCALL
public PATHDSSICALL
public SetCarryRet
public SetErrorDrvDSDX
;-----------------------------------------------------------------------;
; Select_Disk (DOS Call 0Eh) ;
; ;
; ;
; Arguments: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Wed Jan 28, 1987 00:40:48a -by- David N. Weise [dnw] ;
; Rewrote it. It used to save and restore the current disk inside of ;
; DOS on task swaps. Now it will restore on demand. ;
; ;
; Sat Jan 17, 1987 08:19:27p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc Select_Disk,<PUBLIC,NEAR>
cBegin nogen
SetKernelDS
cmp dl, CurDOSDrive ; Must set if not this!
jne MustSetIt
; See if it matches saved drive for TDB
cmp [CurTDB], 0 ; See if we have a TDB
je MustSetIt
push es
mov es, [CurTDB]
cmp es:[TDB_sig], TDB_SIGNATURE
jne DeadTDB
push ax
mov al, es:[TDB_Drive]
and al, 7Fh ; Zap save drive flag
cmp al, dl ; Drive the same?
pop ax
pop es
jne MustSetIt ; no, set it
mov al, DOSDrives ; Return number of logical drives
jmp DriveErrorRet ; Well, it really just returns!
DeadTDB:
pop es
MustSetIt:
push dx
inc dx ; A=1
call CheckDriveDL
pop dx
jnc cd_no_drive_check
call SetErrorDLDrv
jmp DriveErrorRet
cEnd nogen
;-----------------------------------------------------------------------;
; Change_Dir (DOS Call 3Bh) ;
; ;
; ;
; Arguments: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Wed Jan 28, 1987 00:40:48a -by- David N. Weise [dnw] ;
; Rewrote it. It used to save and restore the current directory ;
; on task swaps. Now it will restore on demand. ;
; ;
; Sat Jan 17, 1987 08:21:13p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc Change_Dir,<PUBLIC,NEAR>
cBegin nogen
call PathDrvDSDX
jnc cd_no_drive_check ; Drive OK
call SetErrorDrvDSDX
jmp SetCarryRet
cd_no_drive_check:
SetKernelDS
mov ds,CurTDB
UnSetKernelDS
cmp ds:[TDB_sig],TDB_SIGNATURE
jne Change_Dir1
and ds:[TDB_Drive],01111111b ; indicate save needed
Change_Dir1:
jmp PassOnThrough
cEnd nogen
;-----------------------------------------------------------------------;
; FileHandleCall (DOS Calls 3Eh,42h,45h,46h,57h,5Ch) ;
; ;
; Checks to see if the token in the PDB is 80h. 80h represents a ;
; file that was closed on a floppy by us in order to prompt for a ;
; file (see CloseOpenFiles). If the token is 80h then it is set ;
; to FFh. ;
; ;
; Arguments: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Tue Sep 29, 1987 03:30:46p -by- David N. Weise [davidw] ;
; Changed the special token from FEh to 80h to avoid conflict with ;
; Novell netware that starts with SFT FEh and counts down. ;
; ;
; Tue Apr 28, 1987 11:12:00a -by- Raymond E. Ozzie [-iris-] ;
; Changed to indirect thru PDB to get JFN under DOS 3.x. ;
; ;
; Sat Jan 17, 1987 01:54:54a -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc FileHandleCall,<PUBLIC,NEAR>
cBegin nogen
if1
; %OUT FileHandleCall DISABLED
endif
jmp final_call_for_DOS
cEnd nogen
;-----------------------------------------------------------------------;
; Xenix_Status (DOS Call 44h) ;
; ;
; ;
; Arguments: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; FileHandleCall ;
; PassOnThrough ;
; ;
; History: ;
; ;
; Mon 07-Aug-1989 23:45:48 -by- David N. Weise [davidw] ;
; Removed WinOldApp support. ;
; ;
; Sat Jan 17, 1987 10:17:31p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc Xenix_Status,<PUBLIC,NEAR>
cBegin nogen
cmp al,4
jb xs1
cmp al,7
jz xs1
cmp al,10
jz xs1
jmp PassOnThrough
xs1: jmp FileHandleCall
cEnd nogen
;********************************************************************
;
; Phantom drive Traps
;
;********************************************************************
;**
;
; AssignCall -- Trap for Define Macro Call 5F03h
;
; ENTRY:
; Regs for 5F03h except BP is standard INT 21h frame ptr
; EXIT:
; Through PassOnThrough or Error path if phantom drive detected
; USES:
; Flags and via DOS if error
;
AssignCall:
cmp ax,5F03h ; Only care about 03 call
jnz AssignCall_OK
cmp bl,4 ; With BL = 4 (assign block)
jnz AssignCall_OK
cmp byte ptr [si],0 ; Ignore this special case
jz AssignCall_OK
push dx
mov dx,si
call PathDrvDSDX
pop dx
jc AssignCall_bad
AssignCall_OK:
jmp PassOnThrough
AssignCall_bad:
push word ptr [si]
mov byte ptr [si],'$' ; Bogus drive letter
call real_DOS ; Set error
pop word ptr [si] ; reset string
jmp SetCarryRet
;**
;
; NameTrans -- Trap for NameTrans Call 60h
;
; ENTRY:
; Regs for 60h except BP is standard INT 21h frame ptr
; EXIT:
; Through PassOnThrough or Error path if phantom drive detected
; USES:
; Flags and via DOS if error
;
NameTrans:
push dx
mov dx,si ; Point with DS:DX to call PathDrvDSDX
call PathDrvDSDX
pop dx
jc @F
jmp POTJ1 ; Drive OK
@@:
push word ptr [si]
mov byte ptr [si],'$' ; Bogus drive letter
call real_DOS ; DOS sets error
pop word ptr [si] ; Restore users drive
jmp SetCarryRet ; Error
si_no_good:
call SetErrorDrvDSDX ; Set error
pop dx
jmp SetCarryRet ; Error
PathDSSICall: ; Simple clone of PathDSDXCall
push dx ; but start with offset in SI,
mov dx, si ; and we know this is a file open
call PathDrvDSDX ; call.
jc si_no_good
pop dx
pop ds
push ax
push [bp][6] ; Original flags
push cs
mov ax, codeoffset si_back_here ; Now have IRET frame
push ax
push [bp] ; Original bp+1
mov bp, sp
mov ax, [bp][8]
push ds
jmp PassOnThrough ; Do the DOS call
si_back_here:
pushf
inc bp
push bp ; pass back the correct flags
mov bp,sp
xchg ax, [bp][4]
jc @F
push dx
mov dx, si
call FileCDR_notify
pop dx
@@:
push [bp]
pop [bp][6]
add sp, 2
pop [bp][12]
pop ax
pop bp
dec bp
jmp f_iret
;**
;
; PathDSDXCall -- Trap for Calls which point to a path with DS:DX
;
; ENTRY:
; Regs for call except BP is standard INT 21h frame ptr
; EXIT:
; Through PassOnThrough or Error path if phantom drive detected
; USES:
; Flags and via DOS if error
;
PathDSDXCall:
call PathDrvDSDX
jnc @f
jmp pd_drive_no_good ; Drive not OK
@@:
; If OPEN with SHARING, check to see if this could be a file in
; the file handle cache. GetModuleHandle is fairly quick as
; opposed to fully qualifying the path involved, but that would
; mean two DOS calls in addition to the open. Kernel opens modules
; in compatibility mode, so sharing bits will barf if the file
; is in the cache. why is this a problem? CVW opens modules
; with sharing modes and we broke em when we fixed the fh cache.
; won't worry about other DOS calls like create or delete since
; they will damage things anyway.
;
ife SHARE_AWARE
cmp ah,3Dh ; open call?
jnz maybe_notify
test al, 01110000b ; sharing bits?
jz maybe_notify
call DealWithCachedModule
endif
maybe_notify:
ifdef WOW
cmp ah,41h ; Delete call?
jnz not_delete
call DealWithCachedModule ; Yes Flush it out of our cache
not_delete:
endif; WOW
cmp ah,5Bh
ja no_notify_jmp ; DOS call we don't know
cmp ah,3Dh
jnz nd_101
jmp diddle_share_bits ; Don't notify on open file.
nd_101:
cmp ah,4Eh
jz no_notify_jmp ; Don't notify on find first.
cmp ah,56h
jz no_notify_jmp ; Handle rename specially.
cmp ax, 4300h ; Get File Attributes
jz no_notify_jmp
pop ds
push ax
push [bp][6] ; Original flags
push cs
mov ax, codeoffset back_here ; Now have IRET frame
push ax
push [bp] ; Original bp+1
mov bp, sp
mov ax, [bp][8]
push ds
POTJ1:
jmp PassOnThrough ; Do the DOS call
no_notify_jmp:
jmps no_notify
back_here:
pushf
inc bp
push bp ; pass back the correct flags
mov bp,sp
xchg ax, [bp][4]
jc call_failed
call FileCDR_notify
call_failed:
push [bp]
pop [bp][6]
add sp, 2
pop [bp][12]
pop ax
pop bp
dec bp
jmp f_iret
diddle_share_bits: ; Make ALL opens use SHARE bits
if SHARE_AWARE
test al, 70h ; Any share bits now?
jnz no_notify ; yes, fine.
or al, OF_SHARE_DENY_NONE ; For Read access
test al, 3 ; Write or Read/Write access?
jz no_notify ; no, SHARE_DENY_NONE is fine
; yes, want SHARE_DENY_WRITE
xor al, OF_SHARE_DENY_WRITE OR OF_SHARE_DENY_NONE
endif
no_notify:
jmps POTJ ; Drive OK
pd_drive_no_good:
call SetErrorDrvDSDX ; Set error
jmps SetCarryRet ; Error
;**
;
; DLDriveCall1 -- Trap for Calls which have a drive number (A = 1) in DL
; and carry NOT set if error.
;
; ENTRY:
; Regs for call except BP is standard INT 21h frame ptr
; EXIT:
; Through PassOnThrough or Error path if phantom drive detected CARRY not
; diddled
; USES:
; Flags and via DOS if error
;
DLDriveCall1:
call CheckDriveDL
jnc POTJ ; Drive OK
call SetErrorDLDrv ; Set error
jmps DriveErrorRet ; Error
;**
;
; DLDriveCall2 -- Trap for Calls which have a drive number (A = 1) in DL
; and carry set if error.
;
; ENTRY:
; Regs for call except BP is standard INT 21h frame ptr
; EXIT:
; Through PassOnThrough or Error path if phantom drive detected CARRY set
; USES:
; Flags and via DOS if error
;
DLDriveCall2:
call CheckDriveDL
jnc POTJ ; Drive OK
call SetErrorDLDrv ; Set error
jmps SetCarryRet ; Error
;**
;
; FCBCall -- Trap for Calls which point to an FCB with DS:DX
;
; ENTRY:
; Regs for call except BP is standard INT 21h frame ptr
; EXIT:
; Through PassOnThrough or Error path if phantom drive detected
; USES:
; Flags and via DOS if error
;
FCBCall:
push dx
push si
mov si,dx
cmp byte ptr [si],0FFh ; Extended FCB?
jnz NotExt ; No
add si,7 ; Point to drive
NotExt:
mov dl,byte ptr [si] ; Get drive
or dl,dl
jz FCBOK ; default drive
call CheckDriveDL
jc FCBBad
FCBOK:
pop si
pop dx
POTJ:
jmp PassOnThrough
FCBBad:
push dx ; Save drive
mov dx,si ; Point to standard FCB
mov byte ptr [si],0F0h ; Known bogus drive
call real_DOS
pop dx
mov byte ptr [si],dl ; Restore user drive
pop si
pop dx
jmps DriveErrorRet
SetCarryRet:
or User_FL,00000001b ; Set carry
jmps DriveErrorRet
DriveErrorRet:
pop ds
pop bp
dec bp
FSTI
jmp f_iret
;**
;
; XenixRename -- Trap for Call 56h
;
; ENTRY:
; Regs for call except BP is standard INT 21h frame ptr
; EXIT:
; Through PassOnThrough or Error path if phantom drive detected CARRY set
; USES:
; Flags and via DOS if error
;
XenixRename:
; On rename we MUST deal with BOTH strings to prevent access to any
; phantom drives.
call PathDrvDSDX ; Check DS:DX drive
xchg di,dx ; ES:DI <-> DS:DX
push ds
push es
pop ds
pop es
jnc XR_010
jmp RenameError ; bad
XR_010:
call PathDrvDSDX ; Check ES:DI drive
jnc XR_020
jmp RenameError
XR_020:
xchg di,dx ; ES:DI <-> DS:DX
push ds
push es
pop ds
pop es
pop ds
push ax
push [bp][6] ; Original flags
push cs
mov ax, codeoffset back_here1 ; Now have FIRET frame
push ax
push [bp] ; Original bp+1
mov bp, sp
mov ax, [bp][8]
push ds
jmp PassOnThrough ; Do the DOS call
back_here1:
pushf
inc bp
push bp ; pass back the correct flags
mov bp,sp
xchg [bp][4], ax
jc call_failed1
;;; mov ah,41h ; delete file
call FileCDR_notify
;;; push ds
;;; push es
;;; pop ds
;;; pop es
;;; xchg di,dx
;;; mov ah,5Bh ; create new file
;;; call FileCDR_notify
;;; push ds
;;; push es
;;; pop ds
;;; pop es
;;; xchg di,dx
call_failed1:
push [bp]
pop [bp][6]
add sp, 2
pop [bp][12]
pop ax
pop bp
dec bp
jmp f_iret
RenameError:
xchg di,dx ; DS:DX <-> ES:DI
push ds
push es
pop ds
pop es
; We patch the ES:DI drive letter even if it isn't there.
; Since we are setting an error anyway this is OK.
push word ptr ES:[di]
mov byte ptr ES:[di],'$' ; Bogus drive letter
call SetErrorDrvDSDX ; Set error
pop word ptr ES:[di]
jmp SetCarryRet ; Error
;**
;
; PathDrvDSDX -- Check a path pointed to by DS:DX for phantom drives
;
; ENTRY:
; DS:DX points to path
; EXIT:
; Carry set if phantom drive detected
; Carry clear if no phantom drives detected
; USES:
; Flags
;
public PathDrvDSDX
PathDrvDSDX:
push si
mov si,dx ; Point with SI
mov dx,word ptr [si]; Get first two chars
or dl,dl ; NUL in first byte?
jz PDROK ; yes, OK
ifdef FE_SB
push ax
mov al,dl
call MyIsDBCSLeadByte ; see if char is DBC.
pop ax
jnc PDROK ; jump if char is a DBC
endif
or dh,dh ; NUL in second byte?
jz PDROK ; yes, OK
cmp dh,':' ; Drive given?
jnz PDROK ; No, OK
or dl,20h ; to lower case
sub dl,60h ; DL is drive #, A=1
call CheckDriveDL ; Check it out
jmps PDPPRET
PDROK:
clc
PDPPRET:
mov dx,si
pop si
ret
;**
;
; SetErrorDrvDSDX -- Set an error on a DS:DX call by calling the DOS
;
; ENTRY:
; DS:DX points to path with phantom drive
; All other regs approp for INT 21 CALL
; EXIT:
; DOS called to set up error
; USES:
; Flags
; Regs as for INT 21 CALL
;
SetErrorDrvDSDX:
push si
mov si,dx
push word ptr [si]
mov byte ptr [si],'$' ; Bogus drive letter
call real_DOS ; DOS sets error
pop word ptr [si] ; Restore users drive
pop si
ret
;**
;
; SetErrorDLDrv -- Set an error on a DL call by calling the DOS
;
; ENTRY:
; DL is drive # (A=1) of a phantom drive.
; All other regs approp for INT 21 CALL
; EXIT:
; DOS called to set up error
; USES:
; Flags
; Regs as for INT 21 CALL
;
SetErrorDLDrv:
push dx
mov dl,0F0h ; Bogus drive letter
call real_DOS ; DOS sets error
pop dx ; Restore users drive
ret43: ret
;**
;
; CheckDriveDL -- Check DL drive (A = 1)
;
; ENTRY:
; DL is drive # (A=1)
; EXIT:
; Carry Set if phantom drive
; Carry Clear if NOT phantom drive
; USES:
; Flags
;
CheckDriveDL:
push bx
mov bx,dx
dec bl ; A = 0
cmp bl,26 ; 0 >= DL < 26?
jae OKDRV ; No, cant be phantom then
xor bh,bh
add bx,dataOffset PhantArray; Index into PhantArray
push ds
SetKernelDS
cmp byte ptr ds:[bx],0 ; Non-zero entry means phantom
pop ds
UnSetKernelDS
stc
jnz BadDrv
OKDRV:
clc
BadDrv:
pop bx
ret
ife SHARE_AWARE
;**
;
; DealWithCachedModule -- closes a cached module if it looks like a filename
;
; ENTRY:
; Same as PathDSDXCall
;
; EXIT:
; Unchanged
;
; USES:
; None
;
; SIDE EFFECT:
; Closes entry in file handle cache if it has the same base name
;
public DealWithCachedModule
DealWithCachedModule:
pusha
push ds
push es ; save all registers
mov si, dx ; point ds:si to string
sub sp, 130 ; big number for paranoia
mov di, sp
push ss
pop es ; es:di to string
cld ; forwards
copy_name_loop:
lodsb ; get a char
cmp al, 0 ; end of string?
jz end_of_name
cmp al, ':' ; path seperator?
jz path_sep
cmp al, '\'
jz path_sep
cmp al, '/'
jz path_sep
call MyUpper ; upcase the char
stosb
ifdef FE_SB
call MyIsDBCSLeadByte
jc copy_name_loop ; copy second byte in east
movsb
endif
jmp short copy_name_loop
path_sep:
mov di, sp ; point back to beginning
jmp short copy_name_loop
end_of_name:
stosb
mov di, sp ; point back to beginning
SetKernelDS
cCall ResidentFindExeFile, <ss,di> ; find it
or ax, ax
jz @F
cCall FlushCachedFileHandle, <ax> ; flush it
@@:
add sp, 130
pop es
pop ds ; restore registers
popa
UnsetKernelDS
ret
endif
f_iret:
FIRET
sEnd CODE
end