mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-12-01 18:15:47 +00:00
626 lines
17 KiB
NASM
626 lines
17 KiB
NASM
|
;
|
|||
|
; xenix file calls for MSDOS
|
|||
|
;
|
|||
|
|
|||
|
INCLUDE DOSSEG.ASM
|
|||
|
|
|||
|
IFNDEF KANJI
|
|||
|
KANJI EQU 0 ;FALSE
|
|||
|
ENDIF
|
|||
|
|
|||
|
CODE SEGMENT BYTE PUBLIC 'CODE'
|
|||
|
ASSUME SS:DOSGROUP,CS:DOSGROUP
|
|||
|
|
|||
|
.xlist
|
|||
|
.xcref
|
|||
|
INCLUDE DOSSYM.ASM
|
|||
|
INCLUDE DEVSYM.ASM
|
|||
|
.cref
|
|||
|
.list
|
|||
|
|
|||
|
TITLE XENIX - IO system to mimic UNIX
|
|||
|
NAME XENIX
|
|||
|
|
|||
|
i_need NoSetDir,BYTE
|
|||
|
i_need CURDRV,BYTE
|
|||
|
i_need IOCALL,BYTE
|
|||
|
i_need IOMED,BYTE
|
|||
|
i_need IOSCNT,WORD
|
|||
|
i_need IOXAD,DWORD
|
|||
|
i_need DIRSTART,WORD
|
|||
|
i_need ATTRIB,BYTE
|
|||
|
i_need THISFCB,DWORD
|
|||
|
i_need AuxStack,BYTE
|
|||
|
i_need Creating,BYTE
|
|||
|
i_need ThisDRV,BYTE
|
|||
|
i_need NAME1,BYTE
|
|||
|
i_need LastEnt,WORD
|
|||
|
i_need ThisDPB,DWORD
|
|||
|
i_need EntLast,WORD
|
|||
|
i_need CurrentPDB,WORD
|
|||
|
i_need sft_addr,DWORD ; pointer to head of table
|
|||
|
i_need CURBUF,DWORD ; pointer to current buffer
|
|||
|
i_need DMAADD,DWORD ; pointer to current dma address
|
|||
|
|
|||
|
BREAK <Local data>
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
DATA SEGMENT BYTE PUBLIC 'DATA'
|
|||
|
|
|||
|
|
|||
|
PushSave DW ?
|
|||
|
PushES DW ?
|
|||
|
PushBX DW ?
|
|||
|
|
|||
|
xenix_count DW ?
|
|||
|
|
|||
|
DATA ENDS
|
|||
|
CODE SEGMENT BYTE PUBLIC 'CODE'
|
|||
|
|
|||
|
|
|||
|
BREAK <get_sf_from_sfn - translate a sfn into sf pointer>
|
|||
|
;
|
|||
|
; get_sf_from_sfn
|
|||
|
; input: AX has sfn (0 based)
|
|||
|
; DS is DOSGROUP
|
|||
|
; output: JNC <found>
|
|||
|
; ES:DI is sf entry
|
|||
|
; JC <error>
|
|||
|
; ES,DI indeterminate
|
|||
|
;
|
|||
|
procedure get_sf_from_sfn,NEAR
|
|||
|
ASSUME DS:DOSGROUP,ES:NOTHING
|
|||
|
PUSH AX ; we trash AX in process
|
|||
|
LES DI,[sft_addr]
|
|||
|
|
|||
|
get_sfn_loop:
|
|||
|
CMP DI,-1 ; end of chain of tables?
|
|||
|
JZ get_sf_invalid ; I guess so...
|
|||
|
SUB AX,ES:[DI].sft_count ; chop number of entries in this table
|
|||
|
JL get_sf_gotten ; sfn is in this table
|
|||
|
LES DI,ES:[DI].sft_link ; step to next table
|
|||
|
JMP get_sfn_loop
|
|||
|
|
|||
|
get_sf_gotten:
|
|||
|
ADD AX,ES:[DI].sft_count ; reset to index in this table
|
|||
|
PUSH BX
|
|||
|
MOV BX,SIZE sf_entry
|
|||
|
MUL BL ; number of bytes offset into table
|
|||
|
POP BX
|
|||
|
ADD AX,sft_table ; offset into sf table structure
|
|||
|
ADD DI,AX ; offset into memory
|
|||
|
CLC
|
|||
|
JMP SHORT get_sf_ret
|
|||
|
|
|||
|
get_sf_jfn_invalid:
|
|||
|
get_sf_invalid:
|
|||
|
STC
|
|||
|
|
|||
|
get_sf_jfn_ret:
|
|||
|
get_sf_ret:
|
|||
|
POP AX ; remember him?
|
|||
|
RET
|
|||
|
get_sf_from_sfn ENDP
|
|||
|
|
|||
|
BREAK <get_sf_from_jfn - translate a jfn into sf pointer>
|
|||
|
;
|
|||
|
; get_sf_from_jfn
|
|||
|
; input: BX is jfn 0 based
|
|||
|
; DS is DOSGROUP
|
|||
|
; output: JNC <found>
|
|||
|
; ES:DI is sf entry
|
|||
|
; JC <error>
|
|||
|
; ES,DI is indeterminate
|
|||
|
;
|
|||
|
procedure get_sf_from_jfn,NEAR
|
|||
|
ASSUME DS:DOSGROUP,ES:NOTHING
|
|||
|
PUSH AX ; save him
|
|||
|
invoke get_jfn_pointer
|
|||
|
JC get_sf_jfn_invalid
|
|||
|
MOV AL,ES:[DI] ; get sfn
|
|||
|
CMP AL,0FFh ; is it free?
|
|||
|
JZ get_sf_jfn_invalid ; yep... error
|
|||
|
XOR AH,AH
|
|||
|
invoke get_sf_from_sfn ; check this sfn out...
|
|||
|
JMP SHORT get_sf_jfn_ret ; condition codes are properly set
|
|||
|
|
|||
|
get_sf_from_jfn ENDP
|
|||
|
|
|||
|
BREAK <get_jfn_pointer - map a jfn into a pointer to jfn>
|
|||
|
;
|
|||
|
; get_jfn_pointer
|
|||
|
; input: BX is jfn
|
|||
|
; DS is DOSGROUP
|
|||
|
; output: JNC <found>
|
|||
|
; ES:DI is pointer to jfn
|
|||
|
; JC <bad jfn>
|
|||
|
;
|
|||
|
procedure Get_jfn_pointer,NEAR
|
|||
|
ASSUME DS:DOSGROUP,ES:NOTHING
|
|||
|
CMP BX,FilPerProc
|
|||
|
JAE get_jfn_bad
|
|||
|
MOV ES,[CurrentPDB]
|
|||
|
MOV DI,BX
|
|||
|
ADD DI,PDB_JFN_Table
|
|||
|
CLC
|
|||
|
RET
|
|||
|
|
|||
|
get_jfn_bad:
|
|||
|
STC
|
|||
|
RET
|
|||
|
get_jfn_pointer ENDP
|
|||
|
|
|||
|
|
|||
|
BREAK <$Close - release a handle>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; MOV BX, handle
|
|||
|
; MOV AH, Close
|
|||
|
; INT int_command
|
|||
|
;
|
|||
|
; Error return:
|
|||
|
; AX = error_invalid_handle
|
|||
|
;
|
|||
|
procedure $Close,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
context DS
|
|||
|
|
|||
|
invoke get_jfn_pointer ; get jfn loc
|
|||
|
JNC close_jfn
|
|||
|
close_bad_handle:
|
|||
|
error error_invalid_handle
|
|||
|
|
|||
|
close_jfn:
|
|||
|
MOV AL,BYTE PTR ES:[DI]
|
|||
|
CMP AL,0FFh
|
|||
|
JE close_bad_handle
|
|||
|
MOV BYTE PTR ES:[DI],0FFh;
|
|||
|
XOR AH,AH
|
|||
|
invoke get_sf_from_sfn
|
|||
|
JC close_bad_handle
|
|||
|
PUSH ES
|
|||
|
POP DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
DEC [DI].sf_ref_count ; no more reference
|
|||
|
LEA DX,[DI].sf_fcb
|
|||
|
;
|
|||
|
; need to restuff Attrib if we are closing a protected file
|
|||
|
;
|
|||
|
TEST [DI.sf_fcb.fcb_DevID],devid_file_clean+devid_device
|
|||
|
JNZ close_ok
|
|||
|
PUSH WORD PTR [DI].sf_attr
|
|||
|
invoke MOVNAMENOSET
|
|||
|
POP BX
|
|||
|
MOV [Attrib],BL
|
|||
|
invoke FCB_CLOSE_INNER
|
|||
|
CMP AL,0FFh ; file not found error?
|
|||
|
JNZ close_ok
|
|||
|
error error_file_not_found
|
|||
|
close_ok:
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
$Close ENDP
|
|||
|
|
|||
|
|
|||
|
BREAK <PushDMA, PopDMA, ptr_normalize - set up local dma and save old>
|
|||
|
; PushDMA
|
|||
|
; input: DS:DX is DMA
|
|||
|
; output: DS:DX is normalized , ES:BX destroyed
|
|||
|
; [DMAADD] is now set up to DS:DX
|
|||
|
; old DMA is pushed
|
|||
|
|
|||
|
procedure PushDMA,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
MOV PushES,ES
|
|||
|
MOV PushBX,BX
|
|||
|
POP PushSave
|
|||
|
LES BX,DWORD PTR [DMAADD] ; get old dma
|
|||
|
PUSH ES
|
|||
|
PUSH BX
|
|||
|
PUSH PushSave
|
|||
|
invoke ptr_normalize ; get new dma
|
|||
|
MOV WORD PTR [DMAADD],DX ; save IT!
|
|||
|
MOV WORD PTR [DMAADD+2],DS
|
|||
|
MOV ES,PushES
|
|||
|
MOV BX,PushBX
|
|||
|
RET
|
|||
|
PushDMA ENDP
|
|||
|
|
|||
|
; PopDMA
|
|||
|
; input: old DMA under ret address on stack
|
|||
|
; output: [DMAADD] set to old version and stack popped
|
|||
|
procedure PopDMA,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
POP PushSave
|
|||
|
POP WORD PTR [DMAADD]
|
|||
|
POP WORD PTR [DMAADD+2]
|
|||
|
PUSH PushSave
|
|||
|
RET
|
|||
|
PopDMA ENDP
|
|||
|
|
|||
|
; ptr_normalize
|
|||
|
; input: DS:DX is a pointer
|
|||
|
; output: DS:DX is normalized (DX < 10h)
|
|||
|
procedure ptr_normalize,NEAR
|
|||
|
PUSH CX ; T1 = CX
|
|||
|
PUSH DX ; T2 = DX
|
|||
|
MOV CL,4
|
|||
|
SHR DX,CL ; DX = (DX >> 4) (using CX)
|
|||
|
MOV CX,DS
|
|||
|
ADD CX,DX
|
|||
|
MOV DS,CX ; DS = DS + DX (using CX)
|
|||
|
POP DX
|
|||
|
AND DX,0Fh ; DX = T2 & 0Fh
|
|||
|
POP CX ; CX = T1
|
|||
|
|
|||
|
; PUSH AX
|
|||
|
; PUSH DX
|
|||
|
; MOV AX,DS
|
|||
|
; PUSH CX
|
|||
|
; MOV CL,4
|
|||
|
; SHR DX,CL ; get upper part of dx
|
|||
|
; POP CX
|
|||
|
; ADD AX,DX ; add into seg address
|
|||
|
; MOV DS,AX
|
|||
|
; POP DX
|
|||
|
; AND DX,0Fh ; save low part
|
|||
|
; POP AX
|
|||
|
|
|||
|
RET
|
|||
|
ptr_normalize ENDP
|
|||
|
|
|||
|
BREAK <$Read - Do file/device I/O>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; LDS DX, buf
|
|||
|
; MOV CX, count
|
|||
|
; MOV BX, handle
|
|||
|
; MOV AH, Read
|
|||
|
; INT int_command
|
|||
|
; AX has number of bytes read
|
|||
|
; Errors:
|
|||
|
; AX = read_invalid_handle
|
|||
|
; = read_access_denied
|
|||
|
;
|
|||
|
|
|||
|
procedure $Read,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
invoke PushDMA
|
|||
|
CALL IO_setup
|
|||
|
JC IO_err
|
|||
|
CMP ES:[DI].sf_mode,open_for_write
|
|||
|
JNE read_setup
|
|||
|
IO_bad_mode:
|
|||
|
MOV AL,read_access_denied
|
|||
|
IO_err:
|
|||
|
invoke PopDMA
|
|||
|
transfer SYS_RET_ERR
|
|||
|
|
|||
|
read_setup:
|
|||
|
invoke $FCB_RANDOM_READ_BLOCK ; do read
|
|||
|
IO_done:
|
|||
|
invoke get_user_stack ; get old frame
|
|||
|
MOV AX,[SI].user_CX ; get returned CX
|
|||
|
MOV CX,xenix_count
|
|||
|
MOV [SI].user_CX,CX ; stash our CX
|
|||
|
invoke PopDMA ; get old DMA
|
|||
|
transfer SYS_RET_OK
|
|||
|
$Read ENDP
|
|||
|
|
|||
|
BREAK <$Write - Do file/device I/O>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; LDS DX, buf
|
|||
|
; MOV CX, count
|
|||
|
; MOV BX, handle
|
|||
|
; MOV AH, Write
|
|||
|
; INT int_command
|
|||
|
; AX has number of bytes written
|
|||
|
; Errors:
|
|||
|
; AX = write_invalid_handle
|
|||
|
; = write_access_denied
|
|||
|
;
|
|||
|
|
|||
|
procedure $Write,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
invoke PushDMA
|
|||
|
CALL IO_setup
|
|||
|
JC IO_err
|
|||
|
CMP ES:[DI].sf_mode,open_for_read
|
|||
|
JE IO_bad_mode
|
|||
|
invoke $FCB_RANDOM_WRITE_BLOCK ; do write
|
|||
|
JMP IO_done
|
|||
|
|
|||
|
$write ENDP
|
|||
|
|
|||
|
IO_setup:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
context DS
|
|||
|
MOV xenix_count,CX
|
|||
|
invoke Get_sf_from_jfn
|
|||
|
; ES:DI is sf pointer
|
|||
|
MOV AL,read_invalid_handle ;Assume an error
|
|||
|
MOV CX,xenix_count
|
|||
|
LEA DX,[DI].sf_fcb
|
|||
|
PUSH ES
|
|||
|
POP DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
RET
|
|||
|
|
|||
|
BREAK <$LSEEK - set random record field>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; MOV DX, offsetlow
|
|||
|
; MOV CX, offsethigh
|
|||
|
; MOV BX, handle
|
|||
|
; MOV AL, method
|
|||
|
; MOV AH, LSeek
|
|||
|
; INT int_command
|
|||
|
; DX:AX has the new location of the pointer
|
|||
|
; Error returns:
|
|||
|
; AX = error_invalid_handle
|
|||
|
; = error_invalid_function
|
|||
|
procedure $LSEEK,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
CMP AL,3
|
|||
|
JB lseek_get_sf
|
|||
|
error error_invalid_function
|
|||
|
|
|||
|
lseek_get_sf:
|
|||
|
context DS
|
|||
|
invoke get_sf_from_jfn
|
|||
|
PUSH ES
|
|||
|
POP DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
JC lseek_bad
|
|||
|
;
|
|||
|
; don't seek device
|
|||
|
;
|
|||
|
TEST [DI.sf_fcb+fcb_devid],devid_device
|
|||
|
JZ lseek_dispatch
|
|||
|
XOR AX,AX
|
|||
|
XOR DX,DX
|
|||
|
JMP SHORT lseek_ret
|
|||
|
lseek_dispatch:
|
|||
|
DEC AL
|
|||
|
JL lseek_beginning
|
|||
|
DEC AL
|
|||
|
JL lseek_current
|
|||
|
; move from end of file
|
|||
|
; first, get end of file
|
|||
|
XCHG AX,DX ; AX <- low
|
|||
|
XCHG DX,CX ; DX <- high
|
|||
|
ASSUME DS:NOTHING
|
|||
|
ADD AX,[DI+sf_fcb+fcb_FILSIZ]
|
|||
|
ADC DX,[DI+sf_fcb+fcb_FILSIZ+2]
|
|||
|
JMP SHORT lseek_ret
|
|||
|
|
|||
|
lseek_beginning:
|
|||
|
XCHG AX,DX ; AX <- low
|
|||
|
XCHG DX,CX ; DX <- high
|
|||
|
|
|||
|
lseek_ret:
|
|||
|
MOV WORD PTR [DI+sf_fcb+fcb_RR],AX
|
|||
|
MOV WORD PTR [DI+sf_fcb+fcb_RR+2],DX
|
|||
|
invoke get_user_stack
|
|||
|
MOV [SI.user_DX],DX
|
|||
|
MOV [SI.user_AX],AX
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
lseek_current:
|
|||
|
; ES:DI is pointer to sf... need to invoke set random record for place
|
|||
|
XCHG AX,DX ; AX <- low
|
|||
|
XCHG DX,CX ; DX <- high
|
|||
|
ADD AX,WORD PTR [DI+sf_fcb+fcb_RR]
|
|||
|
ADC DX,WORD PTR [DI+sf_fcb+fcb_RR+2]
|
|||
|
JMP lseek_ret
|
|||
|
|
|||
|
lseek_bad:
|
|||
|
error error_invalid_handle
|
|||
|
$lseek ENDP
|
|||
|
|
|||
|
|
|||
|
BREAK <$IOCTL - return/set device dependent stuff>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; MOV BX, Handle
|
|||
|
; MOV DX, Data
|
|||
|
;
|
|||
|
; (or LDS DX,BUF
|
|||
|
; MOV CX,COUNT)
|
|||
|
;
|
|||
|
; MOV AH, Ioctl
|
|||
|
; MOV AL, Request
|
|||
|
; INT 21h
|
|||
|
;
|
|||
|
; Error returns:
|
|||
|
; AX = error_invalid_handle
|
|||
|
; = error_invalid_function
|
|||
|
; = error_invalid_data
|
|||
|
|
|||
|
procedure $IOCTL,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
MOV SI,DS ;Stash DS for calls 2,3,4 and 5
|
|||
|
context DS
|
|||
|
CMP AL,3
|
|||
|
JA ioctl_check_block ;Block device
|
|||
|
PUSH DX
|
|||
|
invoke get_sf_from_jfn
|
|||
|
POP DX ;Restore DATA
|
|||
|
JNC ioctl_check_permissions ; have valid handle
|
|||
|
error error_invalid_handle
|
|||
|
|
|||
|
ioctl_check_permissions:
|
|||
|
CMP AL,2
|
|||
|
JAE ioctl_control_string
|
|||
|
CMP AL,0
|
|||
|
MOV AL,BYTE PTR ES:[DI+sf_fcb+fcb_devid]
|
|||
|
JZ ioctl_read ; read the byte
|
|||
|
OR DH,DH
|
|||
|
JZ ioctl_check_device ; can I set with this data?
|
|||
|
error error_invalid_data ; no DH <> 0
|
|||
|
|
|||
|
ioctl_check_device:
|
|||
|
TEST AL,devid_ISDEV ; can I set this handle?
|
|||
|
JZ ioctl_bad_fun ; no, it is a file.
|
|||
|
MOV BYTE PTR ES:[DI+sf_fcb+fcb_devid],DL
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
ioctl_read:
|
|||
|
XOR AH,AH
|
|||
|
TEST AL,devid_ISDEV ; Should I set high byte
|
|||
|
JZ ioctl_no_high ; no
|
|||
|
LES DI,DWORD PTR ES:[DI+sf_fcb+fcb_FIRCLUS] ;Get device pointer
|
|||
|
MOV AH,BYTE PTR ES:[DI.SDEVATT+1] ;Get high byte
|
|||
|
ioctl_no_high:
|
|||
|
invoke get_user_stack
|
|||
|
MOV DX,AX
|
|||
|
MOV [SI.user_DX],DX
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
ioctl_control_string:
|
|||
|
TEST BYTE PTR ES:[DI+sf_fcb+fcb_devid],devid_ISDEV ; can I?
|
|||
|
JZ ioctl_bad_fun ; no, it is a file.
|
|||
|
LES DI,DWORD PTR ES:[DI+sf_fcb+fcb_FIRCLUS] ;Get device pointer
|
|||
|
XOR BL,BL ; Unit number of char dev = 0
|
|||
|
JMP SHORT ioctl_do_string
|
|||
|
|
|||
|
ioctl_check_block:
|
|||
|
DEC AL
|
|||
|
DEC AL ;4=2,5=3,6=4,7=5
|
|||
|
CMP AL,3
|
|||
|
JBE ioctl_get_dev
|
|||
|
|
|||
|
MOV AH,1
|
|||
|
SUB AL,4 ;6=0,7=1
|
|||
|
JZ ioctl_get_status
|
|||
|
MOV AH,3
|
|||
|
DEC AL
|
|||
|
JNZ ioctl_bad_fun
|
|||
|
|
|||
|
ioctl_get_status:
|
|||
|
PUSH AX
|
|||
|
invoke GET_IO_FCB
|
|||
|
POP AX
|
|||
|
JC ioctl_acc_err
|
|||
|
invoke IOFUNC
|
|||
|
MOV AH,AL
|
|||
|
MOV AL,0FFH
|
|||
|
JNZ ioctl_status_ret
|
|||
|
INC AL
|
|||
|
ioctl_status_ret:
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
ioctl_bad_fun:
|
|||
|
error error_invalid_function
|
|||
|
|
|||
|
ioctl_acc_err:
|
|||
|
error error_access_denied
|
|||
|
|
|||
|
ioctl_get_dev:
|
|||
|
PUSH CX
|
|||
|
PUSH DX
|
|||
|
PUSH AX
|
|||
|
PUSH SI ;DS in disguise
|
|||
|
MOV AL,BL ;Drive
|
|||
|
invoke GETTHISDRV
|
|||
|
JC ioctl_bad_drv
|
|||
|
invoke FATREAD ;"get" the drive
|
|||
|
MOV BL,ES:[BP.dpb_UNIT] ; Unit number
|
|||
|
LES DI,ES:[BP.dpb_driver_addr]
|
|||
|
CLC ;Make sure error jump not taken
|
|||
|
ioctl_bad_drv:
|
|||
|
POP SI
|
|||
|
POP AX
|
|||
|
POP DX
|
|||
|
POP CX
|
|||
|
JC ioctl_acc_err
|
|||
|
ioctl_do_string:
|
|||
|
TEST ES:[DI.SDEVATT],DEVIOCTL ;See if device accepts control
|
|||
|
JZ ioctl_bad_fun ;NO
|
|||
|
DEC AL
|
|||
|
DEC AL
|
|||
|
JZ ioctl_control_read
|
|||
|
MOV [IOCALL.REQFUNC],DEVWRIOCTL
|
|||
|
JMP SHORT ioctl_control_call
|
|||
|
ioctl_control_read:
|
|||
|
MOV [IOCALL.REQFUNC],DEVRDIOCTL
|
|||
|
ioctl_control_call:
|
|||
|
MOV AL,DRDWRHL
|
|||
|
MOV AH,BL ;Unit number
|
|||
|
MOV WORD PTR [IOCALL.REQLEN],AX
|
|||
|
XOR AX,AX
|
|||
|
MOV [IOCALL.REQSTAT],AX
|
|||
|
MOV [IOMED],AL
|
|||
|
MOV [IOSCNT],CX
|
|||
|
MOV WORD PTR [IOXAD],DX
|
|||
|
MOV WORD PTR [IOXAD+2],SI
|
|||
|
PUSH ES
|
|||
|
POP DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV SI,DI ;DS:SI -> driver
|
|||
|
PUSH SS
|
|||
|
POP ES
|
|||
|
MOV BX,OFFSET DOSGROUP:IOCALL ;ES:BX -> Call header
|
|||
|
invoke DEVIOCALL2
|
|||
|
MOV AX,[IOSCNT] ;Get actual bytes transferred
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
$IOCTL ENDP
|
|||
|
|
|||
|
BREAK <File_Times - modify write times on a handle>
|
|||
|
;
|
|||
|
; Assembler usage:
|
|||
|
; MOV AH, FileTimes
|
|||
|
; MOV AL, func
|
|||
|
; MOV BX, handle
|
|||
|
; ; if AL = 1 then then next two are mandatory
|
|||
|
; MOV CX, time
|
|||
|
; MOV DX, date
|
|||
|
; INT 21h
|
|||
|
; ; if AL = 0 then CX/DX has the last write time/date
|
|||
|
; ; for the handle.
|
|||
|
;
|
|||
|
; Error returns:
|
|||
|
; AX = error_invalid_function
|
|||
|
; = error_invalid_handle
|
|||
|
;
|
|||
|
procedure $File_times,near
|
|||
|
CMP AL,2
|
|||
|
JB filetimes_ok
|
|||
|
error error_invalid_function
|
|||
|
|
|||
|
filetimes_ok:
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
CALL Get_sf_from_jfn
|
|||
|
JNC filetimes_disp
|
|||
|
error error_invalid_handle
|
|||
|
|
|||
|
filetimes_disp:
|
|||
|
OR AL,AL
|
|||
|
JNZ filetimes_set
|
|||
|
MOV CX,ES:[DI.sf_fcb.fcb_FTIME]
|
|||
|
MOV DX,ES:[DI.sf_fcb.fcb_FDATE]
|
|||
|
invoke Get_user_stack
|
|||
|
MOV [SI.user_CX],CX
|
|||
|
MOV [SI.user_DX],DX
|
|||
|
transfer SYS_RET_OK
|
|||
|
|
|||
|
filetimes_set:
|
|||
|
MOV ES:[DI.sf_fcb.fcb_FTIME],CX
|
|||
|
MOV ES:[DI.sf_fcb.fcb_FDATE],DX
|
|||
|
AND ES:[DI.sf_fcb.fcb_DEVID],NOT devid_file_clean
|
|||
|
transfer SYS_RET_OK
|
|||
|
$file_times ENDP
|
|||
|
|
|||
|
do_ext
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
END
|
|||
|
|