; Project name : File library ; Description : ASM library for DOS file handling. ;--------------- Equates ----------------------------- ; DOS DTA (Disk Transfer Area) struc DTA ; Undocumented fields .reserved resb 21 ; Documented fields .bFileAttr resb 1 ; 15h, Attribute of matching file .wFileTime resb 2 ; 16h, File time .wFileDate resb 2 ; 18h, File date .dwFileSize resb 4 ; 1Ah, File size in bytes .szFile resb 13 ; 1Eh, ASCIZ filename + extension endstruc ; Bits for file attribute byte FLG_FATTR_RDONLY EQU (1<<0) ; Read only FLG_FATTR_HIDDEN EQU (1<<1) ; Hidden FLG_FATTR_SYS EQU (1<<2) ; System FLG_FATTR_LABEL EQU (1<<3) ; Volume Label FLG_FATTR_DIR EQU (1<<4) ; Directory FLG_FATTR_ARCH EQU (1<<5) ; Archive ; File access and sharing modes VAL_FACCS_READ EQU 0 ; Read only VAL_FACCS_WRITE EQU 1 ; Write only VAL_FACCS_RW EQU 2 ; Read and Write ; DOS File I/O error codes ERR_DOS_SUCCESS EQU 0 ; No error ERR_DOS_FUNC EQU 1 ; Function number invalid ERR_DOS_NOFILE EQU 2 ; File not found ERR_DOS_NOPATH EQU 3 ; Path not found ERR_DOS_TOOMANY EQU 4 ; Too many open files ERR_DOS_DENIED EQU 5 ; Access denied ERR_DOS_HANDLE EQU 6 ; Invalid handle ERR_DOS_CODE EQU 12 ; Access code invalid ERR_DOS_NOMORE EQU 18 ; No more files ;-------------- Private global variables ------------- ; Section containing initialized data ;SECTION .data ; DOS file I/O related error strings g_szNoErr: db "No error",STOP g_szFunc: db "Function number invalid",STOP g_szNoFile: db "File not found",STOP g_szNoPath: db "Path not found",STOP g_szTooMany: db "Too many open files",STOP g_szDenied: db "Access denied",STOP g_szHandle: db "Invalid handle",STOP g_szCode: db "Access code invalid",STOP g_szNoMore: db "No more files",STOP g_szUnknown: db "Unknown file I/O error",STOP ;-------------- Public functions --------------------- ; Section containing code SECTION .text ;-------------------------------------------------------------------- ; Returns pointer to error string. ; Pointer is always valid, even if error code is not. ; ; File_GetErrStr ; Parameters: ; AX: DOS File I/O error code ; Returns: ; ES:DI: Ptr to error string ; Corrupts registers: ; Nothing ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_GetErrStr: mov di, g_szNoMore ; Assume ERR_DOS_NOMORE cmp ax, ERR_DOS_NOMORE je .Return mov di, g_szCode ; Assume ERR_DOS_CODE cmp ax, ERR_DOS_CODE je .Return mov di, g_szUnknown ; Assume unknown error cmp ax, ERR_DOS_HANDLE ; Can use lookup? ja .Return ; If not, return mov di, ax ; Copy error code to DI shl di, 1 ; Shift for word lookup mov di, [cs:di+.rgwErrLookup] ALIGN JUMP_ALIGN .Return: push cs ; Copy CS... pop es ; ...to ES ret ALIGN WORD_ALIGN .rgwErrLookup: dw g_szNoErr ; 0 dw g_szFunc ; 1 dw g_szNoFile ; 2 dw g_szNoPath ; 3 dw g_szTooMany ; 4 dw g_szDenied ; 5 dw g_szHandle ; 6 ;-------------------------------------------------------------------- ; Opens file for reading and writing. ; File must be closed with File_Close when no longer needed. ; ; File_Open ; Parameters: ; AL: File access and sharing mode: ; VAL_FACCS_READ Open file for reading ; VAL_FACCS_WRITE Open file for writing ; VAL_FACCS_RW Open file for read and write ; DS:DX: Ptr to destination ASCIZ file name ; Returns: ; AX: DOS error code if CF set ; BX: File handle if CF cleared ; CF: Clear if file opened successfully ; Set if error ; Corrupts registers: ; AX, BX ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_Open: mov ah, 3Dh ; Open Existing File int 21h mov bx, ax ; Copy handle to BX ret ;-------------------------------------------------------------------- ; Closes file. ; ; File_Close ; Parameters: ; BX: File handle ; Returns: ; AX: DOS error code if CF set ; CF: Clear if file closed successfully ; Set if error ; Corrupts registers: ; AX ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_Close: mov ah, 3Eh ; Open Existing File int 21h ret ;-------------------------------------------------------------------- ; Reads binary data from file. ; File position is updated so next read will start where ; previous read stopped. ; ; File_Read ; Parameters: ; BX: File handle ; CX: Number of bytes to read ; ES:DI: Ptr to destination buffer ; Returns: ; AX: Number of bytes actually read if successful (EOF check) ; DOS error code if CF set ; CF: Clear if successful ; Set if error ; Corrupts registers: ; Nothing ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_Read: push ds push dx push es ; Copy ES... pop ds ; ...to DS mov dx, di ; DS:DX now points to destination buffer mov ah, 3Fh ; Read from File or Device int 21h pop dx pop ds ret ;-------------------------------------------------------------------- ; Writes binary data to file. ; File position is updated so next write will start where ; previous write stopped. ; ; File_Write ; Parameters: ; BX: File handle ; CX: Number of bytes to write ; ES:DI: Ptr to source buffer ; Returns: ; AX: Number of bytes actually written if successful (EOF check) ; DOS error code if CF set ; CF: Clear if successful ; Set if error ; Corrupts registers: ; Nothing ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_Write: push ds push dx push es ; Copy ES... pop ds ; ...to DS mov dx, di ; DS:DX now points to source buffer mov ah, 40h ; Write to File or Device int 21h pop dx pop ds ret ;-------------------------------------------------------------------- ; Sets current file position to wanted offset. ; ; File_SetFilePos ; Parameters: ; BX: File handle ; CX:DX: New offset (signed) ; Returns: ; AX: DOS error code if CF set ; CF: Clear if successful ; Set if error ; Corrupts registers: ; Nothing ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_SetFilePos: push dx mov ax, 42h<<8 ; Set Current File Position (from file start) int 21h pop dx ret ;-------------------------------------------------------------------- ; Changes current default drive. ; ; File_SetDrive ; Parameters: ; DL: New default drive (00h=A:, 01h=B: ...) ; Returns: ; AL: Number of potentially valid drive letters available ; Corrupts registers: ; AH ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_SetDrive: mov ah, 0Eh ; Select Default Drive int 21h ret ;-------------------------------------------------------------------- ; Returns current default drive and number of ; potentially drive letters available. ; ; File_GetDrive ; Parameters: ; Nothing ; Returns: ; AL: Number of potentially valid drive letters available ; AH: Current default drive (00h=A:, 01h=B: ...) ; Corrupts registers: ; Nothing ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_GetDrive: push dx mov ah, 19h ; Get Current Default Drive int 21h ; Get drive to AL mov dl, al ; Copy drive number to DL call File_SetDrive ; Set to current and get drive letter count mov ah, dl ; Copy current drive to AH pop dx ret ;-------------------------------------------------------------------- ; Checks are the potentially valid drive letters returned by ; File_SetDrive and File_GetDrive actually valid or not. ; ; File_IsDrive ; Parameters: ; DL: Drive number (00h=A:, 01h=B: ...) ; Returns: ; AL: 00h if valid drive number, FFh if invalid drive number ; ZF: Set if drive number is valid ; Cleared if drive number is invalid ; Corrupts registers: ; AH ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_IsDrive: push ds push bx inc dx ; 00h=default drive, 01h=A:, 02h=B: ... mov ah, 32h ; Get DOS Drive Parameter Block for Specific Drive int 21h dec dx ; Restore DX test al, al ; Set ZF according to result pop bx pop ds ret ;-------------------------------------------------------------------- ; Returns number of valid drive letters. ; ; File_GetValidDrvCnt ; Parameters: ; Nothing ; Returns: ; CX: Number of valid drives ; Corrupts registers: ; AX, DX ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_GetValidDrvCnt: call File_GetDrive ; Get potential drive letters to AL eMOVZX cx, al ; Letter count to CX xor dx, dx ; Zero DX (DH=valid count, DL=drv num) ALIGN JUMP_ALIGN .LetterLoop: call File_IsDrive not al ; Invert return bits and al, 1 ; Clear all but bit 1 add dh, al ; Increment valid count inc dx ; Increment drive number loop .LetterLoop ; Loop while drive letters left mov cl, dh ; Valid drv count to CX ret ;-------------------------------------------------------------------- ; Return device number for Nth valid drive. ; This function does not check if index in CX is valid. ; ; File_GetNthValidDrv ; Parameters: ; CX: Index of valid drive to look for ; Returns: ; AX: Drive letter (A, B...) ; DX: Drive device number (00h=A:, 01h=B: ...) ; Corrupts registers: ; CX ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_GetNthValidDrv: inc cx ; Index to count mov dx, -1 ; Dev num, increments to zero ALIGN JUMP_ALIGN .DrvLoop: inc dx ; Increment device number call File_IsDrive ; Is drive valid? jnz .DrvLoop ; Loop if not loop .DrvLoop ; Loop until wanted drive found mov ax, dx ; Drive device number to AX add ax, 'A' ; Dev number to drive letter ret ;-------------------------------------------------------------------- ; Changes current directory. ; ; File_ChangeDir ; Parameters: ; DS:DX Ptr to destination ASCIZ path name ; Returns: ; AX: DOS Error code ; CF: Clear if successful ; Set if error ; Corrupts registers: ; Nothing ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_ChangeDir: mov ah, 3Bh ; Set Current Directory int 21h ret ;-------------------------------------------------------------------- ; Finds files from wanted path using search wildcard characters. ; ; File_FindAndCount ; Parameters: ; DS:DX Ptr to ASCIZ path or file name (* and ? wildcards allowed) ; Returns: ; CX: Number of files found ; Corrupts registers: ; AX ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_IsFile: File_FindAndCount: xor cx, cx ; Zero file count call File_FindFirst ; Find first file jc .Return ; Return if no files found ALIGN JUMP_ALIGN .IsNextLoop: inc cx ; Increment file count call File_FindNext ; Find next file jnc .IsNextLoop ; Loop while files left ALIGN JUMP_ALIGN .Return: ret ;-------------------------------------------------------------------- ; Finds files from wanted path using search wildcard characters. ; Ptr to DTA is returned for wanted file. ; ; File_GetDTA ; Parameters: ; CX: Index for file whose DTA is to be returned ; DS:DX Ptr to ASCIZ path or file name (* and ? wildcards allowed) ; Returns: ; DS:BX: Ptr to file DTA ; CF: Set if file was not found ; Cleared if file found and DTA is returned ; Corrupts registers: ; AX, DX ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_GetDTA: call File_FindFirst ; Find first file jc .RetErr ; Return if no files found xor dx, dx ; Zero file index ALIGN JUMP_ALIGN .IsNextLoop: cmp cx, dx ; Wanted file found? je .RetDTA ; If so, jump to return DTA inc dx ; Increment index for next file call File_FindNext ; Find next file jnc .IsNextLoop ; Loop while files left .RetErr: ret ALIGN JUMP_ALIGN .RetDTA: push cs ; Push code segment pop ds ; CS to DS mov bx, 80h ; DTA starts at DOS PSP:80h ret ;-------------- Private functions --------------------- ;-------------------------------------------------------------------- ; Find first file or directory. ; ; File_FindFirst ; Parameters: ; DS:DX Ptr to ASCIZ path or file name (* and ? wildcards allowed) ; Returns: ; AX: DOS Error code ; CF: Set if file was not found ; Cleared if file was found ; Corrupts registers: ; Nothing ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_FindFirst: push cx ;mov cx, FLG_FATTR_DIR ; Directories and files xor cx, cx mov ax, 4Eh<<8 ; Find First Matching File int 21h pop cx ret ;-------------------------------------------------------------------- ; Find next file or directory. File_FindFirst must always be called ; before calling File_FindNext. ; ; File_FindNext ; Parameters: ; Nothing ; Returns: ; AX: DOS Error code ; CF: Set if file was not found ; Cleared if file was found ; Corrupts registers: ; Nothing ;-------------------------------------------------------------------- ALIGN JUMP_ALIGN File_FindNext: mov ah, 4Fh ; Find Next Matching File int 21h ret