home *** CD-ROM | disk | FTP | other *** search
- ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;
- ; Module Name : FileDir.ASM
- ;
- ; Last Revised : 07/04/90 08:45am
- ;
- ; Purpose : This is a specialized function which reads ALL the
- ; ENTRIES in a given DIRECTORY PATHNAME which match
- ; the passed parameter, below, 'PathName'.
- ; Note you MUST define a DYNAMIC array to hold the
- ; output from this routine in your source program
- ; before you use this.
- ;
- ; Assumptions : Due to the structure of the program, successful
- ; assembly requires the Microsoft MACRO ASSEMBLER,
- ; V 5.1 +
- ;
- ; This routine would be declared in your source program as an EXTERNAL
- ; FUNCTION routine, via the statement -
- ;
- ; DECLARE FUNCTION FileDir% (PathName$, FSeg%, FOff%)
- ;
- ; Parameters : The parameters to the above CALL are defined as
- ; follows:
- ;
- ; PathName - the ASCIIZ string of a given DOS PATHNAME to be
- ; read, including a filespec or "*.*" - REMEMBER that
- ; ASCIIZ strings ALWAYS end with a CHR$(0) character!
- ;
- ; FSeg - The SEGMENT address of the DYNAMIC ARRAY used to
- ; hold the output of this routine.
- ; This array MUST be defined as DYNAMIC, MUST be
- ; defined as STRING * 42 (fixed length strings, each
- ; 42 bytes long), and MUST be <= 1550 STRINGS in size.
- ; Therefore, this routine will return NO MORE THAN
- ; 1550 STRINGS$ of data from the disk(ette).
- ;
- ; IF YOU DO NOT MAKE THE ARRAY LARGE ENOUGH TO HOLD ALL THE ENTRIES,
- ; THIS PROGRAM WILL BEHAVE UNPREDICTABLY!
- ;
- ; FNOff - The OFFSET address of the above array.
- ;
- ;
- ; The easiest way to CALL this FUNCTION is as follows -
- ;
- ; NmbrOfFiles% = FileDir (PathName, VARSEG(FNarray(0)), VARPTR(FNarray(0)))
- ;
- ; The format of each string is defined below in the .DATA item starting
- ; with "FileName".
- ; This is similar to the DOS "DIR" list format, except that there is 1
- ; space between all items, and the LAST item is the base 10 equivalent
- ; of the file's current attribute byte.
- ; All entries returned in the FNarray are in full ASCII text, suitable
- ; for screen display or sending direct to the printer.
- ;
- ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- .MODEL MEDIUM,BASIC
- .DATA
-
- NewDTABuffer DB 128 dup(0)
- DTABuff EQU OFFSET NewDTABuffer
- DTAFileAttr EQU DTABuff + 21
- DTAFileTime EQU DTABuff + 22
- DTAFileDate EQU DTABuff + 24
- DTAFileSize EQU DTABuff + 26
- DTAFileName EQU DTABuff + 30
-
- FileName DB ' .'
- FileExt DB ' '
- DB ' '
- FileSize DB ' '
- DB ' '
- FileMM DB '00-'
- FileDD DB '00-'
- FileYY DB '1900'
- DB ' '
- FileTime DB '00:00' ; This 24 hour clock allows easy SORTing
- DB ' '
- FileAttr DB ' '
-
- FILEBUF EQU OFFSET FileName
-
- ClrStrng DB ' . 00-00-1900 00:00 '
-
- ;============================================================================
-
- .CODE
-
- FileDir PROC USES DS ES SI DI, PATHNAME:WORD, VARSEG:WORD, VAROFF:WORD
- LOCAL OldDTASeg:WORD, OldDTAOff:WORD, PathToUse:WORD, FileCtr:WORD, \
- DimSeg:WORD, DimOff:WORD
-
- ;****************************************************************************
- ; Start Of Main Program Code
- ;****************************************************************************
-
- mov FileCtr,0 ; Initialize counter for files found
-
- ;*****************************************************************************
- ; Since this routine makes extensive use of the DTA, we will protect the
- ; original DTA which the CALLing program uses by setting up a new DTA,
- ; temporarily, for this routine to use.
- ; Therefore, we must store the SEGMENT:OFFSET address of the current DTA
- ; so that we can restore it on exit from this routine.
- ;*****************************************************************************
-
- mov AH,02Fh ; "GET DTA ADDR" Service of int 21h
- int 21h
- mov OldDTASeg,ES ; Save the entry value for the DTA
- mov OldDTAOff,BX
-
- ;*****************************************************************************
- ; Now we can get the passed parameters for the SEGMENT and OFFSET of the
- ; DYNAMIC array which will hold the file names.
- ; Then we can get the passed DRIVE parameter and change the current
- ; default drive and path to ROOT DIRECTORY of the passed DRIVE.
- ;*****************************************************************************
-
- mov BX,VARSEG ; Save the SEGMENT portion of the
- mov AX,[BX] ; address of FNarray() in the
- mov DimSeg,AX ; DimSeg variable.
- mov BX,VAROFF ; Save the OFFSET portion of the
- mov AX,[BX] ; address of FNarray() in the
- mov DimOff,AX ; DimOff variable.
-
- mov BX,PATHNAME ; BX = the addr. of the passed PathName
- mov DX,[BX+2] ; Note that DS:DX = offset of ASCIIZ
- ; PathName
- mov PathToUse,DX ; Store this address for later use
-
- ;-----------------------------------------------------------------------------
-
- Start_Program:
-
- mov AX,DimSeg ; Now we point ES:DI at FNarray(0)
- mov ES,AX
- mov DI,DimOff
-
- mov DX,DTABuff ; Prepare to create a NEW DTA temporarily
- mov AH,01Ah ; "SET DTA ADDR" Service of int 21h
- int 21h
-
- clc ; Clear Carry Flag to start
-
- Find_First_Match:
-
- mov SI,DTABuff ; Point SI at start of NewDTABuffer
- mov CX,16h ; Find ANY ATTRIBUTE file
- mov DX,PathToUse ; DS:DX = passed ASCIIZ PathName parm
- mov AH,04Eh ; "FIND FIRST MATCH" Service of int 21h
- int 21h
-
- jnc Found_A_File ; If CARRY, disk is 100% EMPTY
- jmp Ret_To_Caller
-
- Found_A_File:
-
- push DS
- pop ES ; Be sure that ES = DS for this
-
- mov DI,OFFSET FileAttr ; Point DI at start of FileAttr
- mov SI,DTAFileAttr
- mov AL,[SI] ; Put File Attrib into AL
- call EightBitToASCII
-
- mov DI,FILEBUF
- mov SI,DTAFileName ; SI points at start of FileName in the NewDTABuffer
- mov CX,8 ; (which CANNOT be > 8 bytes long)
-
- Record_The_FileName:
-
- lodsb
- cmp AL,'.' ; Find the "." between FileName and Ext
- je Record_The_Ext
- cmp AL,0
- jne NotHexZero
- mov AL,20h
-
- NotHexZero:
-
- stosb
- loop Record_The_FileName
-
- Record_The_Ext:
-
- cmp Byte Ptr[SI],'.' ; This could be the "." between FileName
- jne RTE_A ; and the FileExt if FileName is
- inc SI ; EXACTLY 8 chars long!
-
- RTE_A:
-
- mov DI,OFFSET FileExt
-
- Record_FileExt:
-
- lodsb
- cmp AL,0
- je Record_FileTime
- stosb
- jmp short Record_FileExt
-
- ;*****************************************************************************
- ; At this point, we have recorded the FileName, The FileExt, and the
- ; FileAttr. Now we will record the File's Date and Time.
- ;*****************************************************************************
-
- Record_FileTime:
-
- mov DI,OFFSET FileTime
- mov SI,DTAFileTime
- mov AX,[SI] ; AX = TIME File last modified
-
- and AX,0F800h ; MASK to get the HOURS value
- mov CL,11
- shr AX,CL
- call EightBitToASCII ; Record the HOURS value in ASCII form
-
- mov AX,[SI] ; Put TIME value into AX again
- mov DI,OFFSET FileTime
- add DI,3 ; Point DI at MINUTES area of FileTime
-
- and AX,07E0h ; MASK to get MINUTES value
- mov CL,5
- shr AX,CL
- call EightBitToASCII ; Record the MINUTES in ASCII form
-
- mov DI,OFFSET FileMM
- mov SI,DTABuff
- add SI,24
- mov AX,[SI] ; AX now = DATE file last modified
-
- and AX,01E0h ; MASK DATE to get Month value
- mov CL,05
- shr AX,CL
- call EightBitToASCII ; Record MONTH as ASCII
-
- mov AX,[SI] ; Put DATE back into AX
- mov DI,OFFSET FileDD
- and AX,001Fh ; MASK DATE to get Days
- call EightBitToASCII ; Record DAYS as ASCII
-
- mov DI,OFFSET FileYY
- mov AX,[SI] ; AX = DATE again
- and AX,0FE00h ; MASK to get YEARS since 1980
- mov CL,09
- shr AX,CL
- cmp AL,20h
- ja Next_Century
- add AL,80
- add DI,2
- jmp short Record_The_Year
-
- Next_Century:
-
- mov Byte Ptr[DI],32h
- mov Byte Ptr[DI+1],30h
- inc DI
- inc DI
- sub AL,20h
-
- Record_The_Year:
-
- call EightBitToASCII
-
- ;*****************************************************************************
- ; Now we will record the File's Size in Bytes, and then we are done
- ;*****************************************************************************
-
- mov SI,DTAFileSize
- mov DI,OFFSET FileSize
- add DI,8
- mov AX,[SI]
- mov DX,[SI+2] ; FileSize now in DX:AX
-
- push BP
- xchg BP,DX
- mov BX,0Ah
- mov CL,030h
-
- File_Size_One:
-
- cmp BP,0
- jz File_Size_Two
-
- xchg BP,AX
- xor DX,DX
- div BX
- xchg BP,AX
- div BX
- or DL,CL
- mov [DI],DL
- dec DI
- jmp SHORT File_Size_One
-
- File_Size_Two:
-
- xor DX,DX
- div BX
- or DL,CL
- mov [DI],DL
- dec DI
- cmp AX,0
- jnz File_Size_Two
- pop BP
-
- ;*****************************************************************************
- ; Now we can transfer this data into FNarray()
- ;*****************************************************************************
-
- mov DI,DimOff
- mov AX,DimSeg
- mov ES,AX
- mov SI,FILEBUF
- mov CX,21
- rep MOVSW
-
- mov AX,DimOff
- add AX,42
- mov DimOff,AX
-
- push DS
- pop ES ; Make ES = DS again
- inc FileCtr ; Keep Count of files recorded
-
- mov DI,FILEBUF
- mov SI,OFFSET ClrStrng
- mov CX,21
- rep MOVSW ; Clear out the FileName area for next time
-
- Get_Next_Match:
-
- mov DI,DTAFileName ; ES:DI = start of FileName in NewDTABuff
- mov CX,49 ; We will MOVe 49 words here (98 bytes)
- xor AX,AX
-
- CD_Loop:
-
- stosw
- loop CD_Loop
-
- mov SI,DTABuff
- mov CX,16h
- mov DX,PathToUse
- mov AH,04Fh ; "FIND NEXT MATCH" Service of int 21h
- int 21h
-
- jc Ret_To_Caller
- jmp Found_A_File
-
- Ret_To_Caller:
-
- push DS ; Save DS temporarily
-
- mov AX,OldDTASeg ; Here we restore the entry DTA addr
- mov DS,AX
- mov DX,OldDTAOff
- mov AH,01Ah ; "SET DTA ADDR" Service of int 21h
- int 21h
-
- pop DS ; Now restore DS from BX
- mov AX,FileCtr ; Return number of files (not
- ; including directories)
-
- ret ; PROGRAM TERMINATION
-
- FileDir ENDP
-
- ;*****************************************************************************
- ; End Of Main Program Code
- ;*****************************************************************************
- ; Sub-Routine Section
- ;*****************************************************************************
-
- EightBitToASCII PROC NEAR ; Converts an 8-bit value in AL to
- ; ASCII equivalent. On entry,
- mov DL,AL ; ES:DI must point to the start
- inc DI ; of a buffer large enough to
- xor CX,CX ; hold the number.
-
- EBTA_One:
-
- mov AL,DL
- xor AH,AH
- mov CL,10
- div CL
-
- mov DL,AL
- mov AL,AH
- add AL,30h
- mov [DI],AL
- dec DI
- cmp DL,0
- jnz EBTA_One
- ret
-
- EightBitToASCII ENDP
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;
- END
- ;
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-