home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / basic / library / qb_pds / qb_lib / getdirs.asm < prev    next >
Encoding:
Assembly Source File  |  1990-04-08  |  14.0 KB  |  406 lines

  1. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. ;
  3. ;    Name :    GETDIRS.ASM
  4. ;
  5. ;    Revised :    08-Apr-1990
  6. ;
  7. ;   Overview :    This is a HIGHLY specialized function which reads the ENTIRE
  8. ;        DIRECTORY of a given disk(ette).
  9. ;        It finds ALL sub-directories on the drive, and places their
  10. ;        names in the passed array.
  11. ;        An INTEGER value is RETURNed, which is the number of
  12. ;        directories found.
  13. ;
  14. ;      Notes :    - Due to the structure of the program, successful assembly
  15. ;        requires the Microsoft MACRO ASSEMBLER, V 5.1 +.
  16. ;        - This routine has an INTERNAL limit on the maximum number of
  17. ;        sub-directories it will find, controlled by "MaxDirs"
  18. ;        - This routine would be declared in your source program as
  19. ;        an external FUNCTION routine, via the statement -
  20. ;
  21. ;        DECLARE FUNCTION GetDirs% (Drv%, SSeg%, SOff%)
  22. ;
  23. ; Parameters :    The parameters to the above CALL are defined as follows:
  24. ;
  25. ;        Drv    = Represents the drive in which the disk(ette) to be
  26. ;            read is located; for example Drive = 1 = use
  27. ;            drive A:, Drive = 2 = use drive B:, etc.
  28. ;        NOTE :    The calling program MUST insure that the Drive parm
  29. ;            is acceptable - this program will not check.
  30. ;
  31. ;        SSeg    = The SEGMENT address of a DYNAMIC ARRAY which has been
  32. ;            DIMmed to hold the names of all the SubDirs found by
  33. ;            this routine.  This array is defined as -
  34. ;            {arrayname} (1 to MaxDirs) AS STRING * 66
  35. ;
  36. ;        SOff    = The OFFSET address of the above array.
  37. ;
  38. ;        The easiest way to CALL this FUNCTION is as follows -
  39. ;
  40. ;    NmbrOfSubDirs% = GetDirs% (1, VARSEG(SDarray(2)),VARPTR(SDArray(2)))
  41. ;
  42. ;        - Note that SDarray starts at element 2.  This is so that,
  43. ;        on return, SDarray(1) may be filled in with the some string
  44. ;        identifying it as the ROOT directory (this routine ignores
  45. ;        SDarray(1)).
  46. ;        - Note, too, that the integer returned by this routine will be
  47. ;        adjusted to INCLUDE the root directory even though this routine
  48. ;        does NOT place the root directory path into SDarray(1).
  49. ;        (This helps you when you do a FOR...NEXT loop, since the
  50. ;        numeric return of this program can be used directly to print
  51. ;        the SDarray() contents)
  52. ;
  53. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  54.  
  55.     .MODEL    MEDIUM,BASIC
  56.     .DATA
  57.  
  58.     MaxDirs EQU    100        ; INTERNAL LIMIT ON NUMBER OF SUB-DIRS
  59.  
  60.     DirRoot DB    'A:*.*',0    ; Used to search for VOLUME LABEL
  61.     Path    DB    'A:\',0,0,0,0
  62.     Subs    DB    MaxDirs dup(66 dup(0))    ; Stores sub-Directories
  63.     DirBlank    DB    'A:\',63 dup(0)
  64.  
  65.     Return_To    DB    'A:\',64 dup(0) ; Returns here when done
  66.  
  67.     _NewDTABuffer    DB    128 dup(0)
  68.     _DTABuff    EQU    OFFSET    _NewDTABuffer
  69.     _DTAFileAttr    EQU    _DTABuff + 21
  70.     _DTAFileName    EQU    _DTABuff + 30
  71.  
  72.     START_SUBS    EQU    OFFSET Subs
  73.     PATH_ROOT    EQU    OFFSET Path
  74.     START_DIRBLANK     EQU    OFFSET DirBlank
  75.     PATH_RETURN    EQU    OFFSET Return_To
  76.  
  77.     EVEN
  78.  
  79.     CtrSubDir    DW    ?    ; Counter for # sub directories found
  80.     PtrSubDir    DW    ?    ; Keeps track of pointer to SDarray()
  81.     CtrSubLoop    DW    ?
  82.     SegSubDir    DW    ?    ; SEGMENT address of passed SDarray()
  83.     OffSubDir    DW    ?    ; OFFSET  address of passed SDarray()
  84. ;==============================================================================
  85.     .CODE
  86.  
  87. GetDirs     PROC    USES DS ES SI DI, DRIVE:word, SDSEG:word, SDOFF:word
  88. LOCAL        OldDTASeg:word, OldDTAOff:word, CurrDrive:word
  89.  
  90. ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  91.  
  92. SubEND    MACRO
  93.     mov    byte ptr[DI],'\'        ; This will allow this entry in SubDirs
  94.     mov    byte ptr[DI+1],'*'    ;    to be used as a new
  95.     mov    byte ptr[DI+2],'.'    ;    search criteria
  96.     mov    byte ptr[DI+3],'*'
  97.     mov    byte ptr[DI+4],0    ; Makes it an ASCIIZ string
  98.     ENDM
  99. ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  100. DTAClr    MACRO
  101. LOCAL CD_Loop
  102.     mov    DI,_DTAFileName     ; ES:DI = start of FileName
  103.                     ;    in New_DTABuff
  104.     mov    CX,49            ; We will MOVe 49 words here (98 bytes)
  105.     xor    AX,AX            ;    (i.e., 98 bytes of 0)
  106. CD_Loop:
  107.     stosw
  108.     loop    CD_Loop
  109.     ENDM
  110. ;******************************************************************************
  111. ;            Start Of Main Program Code
  112. ;******************************************************************************
  113.     xor    AX,AX            ; Clear to 0 to for the next 4 lines
  114.     mov    CtrSubDir,AX
  115.     mov    PtrSubDir,AX
  116.     mov    CtrSubLoop,AX
  117. ;------------------------------------------------------------------------------
  118. ;    Below, we will obtain the drive ID of the current default drive and
  119. ;    path and store them so that we can return to the starting drive and
  120. ;    path upon exit from this routine.
  121. ;------------------------------------------------------------------------------
  122.     mov    AH,19h            ; Get and store the Current DRIVE ID
  123.     int    21h
  124.     xor    AH,AH            ; Clear out AH
  125.     mov    CurrDrive,AX        ; CurrDrive of 0 = A, of 1 = B, etc
  126.  
  127.     add    AL,65            ; Make AL = letter equivalent of drive
  128.     mov    SI,PATH_RETURN
  129.     mov    [SI],AL
  130.     add    SI,3            ; DS:SI = buffer for next int 21h call
  131.  
  132.     sub    AL,64            ; Adjust AL from letter to drive value
  133.     mov    DL,AL            ; DL = Current default drive
  134.     mov    AH,47h            ; "GET CURRENT DIRECTORY" request
  135.     int    21h
  136. ;------------------------------------------------------------------------------
  137. ;    Since this routine makes extensive use of the DTA, we will protect the
  138. ;    DTA which the CALLing program uses by setting up a new DTA,
  139. ;    temporarily, for this routine to use.  Therefore, we must store the
  140. ;    SEGMENT:OFFSET address of the current DTA so that we can restore it on
  141. ;    exit from this routine
  142. ;------------------------------------------------------------------------------
  143.     mov    AH,02Fh         ; "GET DTA ADDR" Service of int 21h
  144.     int    21h
  145.     mov    OldDTASeg,ES        ; Save the entry value for the DTA
  146.     mov    OldDTAOff,BX
  147. ;------------------------------------------------------------------------------
  148. ;    Now we can get the passed parameters for the SEGMENT and OFFSET of the
  149. ;    DYNAMIC array which will hold the file names.
  150. ;    Then we can the passed DRIVE parameter and change the current default
  151. ;    drive / path to ROOT of the passed DRIVE.
  152. ;------------------------------------------------------------------------------
  153.     mov    BX,SDSEG        ; Save the SEGMENT address of SDarray
  154.     mov    AX,[BX]
  155.     mov    SegSubDir,AX        ; Place it into SegSubDir
  156.     mov    BX,SDOFF        ; Save the OFFSET address of SDarray
  157.     mov    AX,[BX]
  158.     mov    OffSubDir,AX        ; Place it into OffSubDir
  159.  
  160.     mov    BX,DRIVE        ; BX = the address of the passed parm,
  161.                     ;    DRIVE (1 = A; 2 = B;, etc)
  162.     mov    AX,[BX]         ; AX = the value of the DRIVE parm
  163.  
  164.     dec    AL            ; Note the disparity here!
  165.     mov    DL,AL            ; Put PASSED DRIVE SPEC into DL
  166.     mov    AH,0Eh            ; "SELECT DISK" request of int 21h
  167.     int    21h
  168. ;------------------------------------------------------------------------------
  169. ;    Now we will use the passed DRIVE parm to fill in our search strings
  170. ;------------------------------------------------------------------------------
  171.     mov    BX,DRIVE
  172.     mov    AX,[BX]
  173.     add    AL,64            ; Convert passed DRIVE number to letter value
  174.     mov    SI,OFFSET DirRoot
  175.     mov    [SI],AL
  176.     mov    SI,START_DIRBLANK
  177.     mov    [SI],AL
  178.     mov    SI,PATH_ROOT
  179.     mov    [SI],AL
  180.  
  181.     mov    DX,START_DIRBLANK    ; DX = ROOT of passed Drive Spec
  182.     mov    AH,03Bh         ; "SET DIRECTORY" to ROOT of passed Spec
  183.     int    21h
  184.  
  185.     mov    AX,DS
  186.     mov    ES,AX            ; Be Sure ES = DS for now
  187. ;------------------------------------------------------------------------------
  188. ;    Below, we will be sure that the SubDirs area is blank before we start,
  189. ;    and that each row starts with the passed DRIVE parameter, followed by
  190. ;    ":\" - this will allow us to later use these subdir names as full path
  191. ;    specs when searching for other subdirectories.
  192. ;------------------------------------------------------------------------------
  193.     mov    SI,START_DIRBLANK
  194.     mov    DI,START_SUBS
  195.     xor    BX,BX
  196. ReplaceDriveSpec:
  197.     mov    CX,66            ; This loop transfers the drive spec
  198.     rep    movsb            ;    and the trailing 63 "0"'s
  199.                     ;    into each of the SubDirs
  200.     mov    SI,START_DIRBLANK    ; Point DS:SI at start of Blank format
  201.     inc    BX            ; Keep count of how many SubDirs
  202.                     ;    have been filled
  203.     cmp    BX,MaxDirs        ; Have we hit the INTERNAL limit?
  204.     jb    ReplaceDriveSpec
  205. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  206.  
  207. Start_Of_Program:
  208.     mov    DX,_DTABuff        ; Prepare to set NEW DTA temporarily
  209.     mov    AH,01Ah         ; "SET DTA ADDR" Service of int 21h
  210.     int    21h
  211.     clc                ; Clear Carry Flag to start
  212.  
  213.     mov    AX,DS
  214.     mov    ES,AX            ; Make ES = DS
  215.     mov    DI,PATH_ROOT        ; The "Path" variable now points to
  216.     inc    DI            ;    an ASCIIZ string which can be
  217.     inc    DI            ;    used to find all files in ROOT
  218.     SubEND
  219. ;------------------------------------------------------------------------------
  220. ;    The process below starts in the ROOT directory and is designed to find
  221. ;    all files EXCEPT the volume label, including ALL sub-directory entries.
  222. ;------------------------------------------------------------------------------
  223.     mov    SI,_DTABuff        ; Point SI at start of _NewDTABuffer
  224.     mov    DX,PATH_ROOT        ; "Path" is the ROOT Dir entry
  225.     mov    CX,16h            ; Find ANY ATTRIBUTE file
  226.     mov    AH,04Eh         ; "FIND FIRST MATCH" Service of int 21h
  227.     int    21h
  228.  
  229.     jnc    DiskNotEmpty        ; If CARRY, disk is 100% EMPTY
  230.     jmp    RetToCaller
  231. ;------------------------------------------------------------------------------
  232. ;    We have determined that the disk(ette) is NOT empty, since some sort of
  233. ;    directory entry has been found.
  234. ;    Note that this entry CANNOT be either a "." or ".." type file, since we
  235. ;    are in the ROOT directory at this point.
  236. ;    Let us first see if we have hit a sub-directory, or a "real" file -
  237. ;    note at this point, DS:SI points at start of _NewDTABuffer.
  238. ;------------------------------------------------------------------------------
  239. DiskNotEmpty:
  240.     mov    SI,_DTAFileAttr     ; DS:SI now = attribute of found file
  241.     cmp    byte ptr[SI],10h    ; Is this a sub-Directory?
  242.     jne    GetNextMatch        ;    - No - just try again
  243.  
  244.     mov    DI,START_SUBS        ; Point DI at start of SubDirs - past
  245.     add    DI,3            ;    the "A:\" portion
  246.     mov    CX,CtrSubDir
  247.     inc    CtrSubDir        ; Keep count of SubDirs, too
  248.     mov    AX,66            ; Save new starting point in SubDirs
  249.     mul    CL
  250.     add    DI,AX
  251.     mov    PtrSubDir,DI
  252.     mov    SI,_DTAFileName     ; DS:SI = name in _NewDTABuffer area
  253. RecordFirstLevelSubDir:
  254.     lodsb
  255.     cmp    AL,0            ; Note 0 = terminator of sub-Dir name
  256.     je    EndSubDirName
  257.     stosb
  258.     jmp    short    RecordFirstLevelSubDir
  259. EndSubDirName:
  260.     SubEND                ; Finish sub-Dir name with search criteria
  261. ;------------------------------------------------------------------------------
  262. ;    At this point, we are still in the ROOT, and must now look for another
  263. ;    matching subdir (if any exist).
  264. ;------------------------------------------------------------------------------
  265. GetNextMatch:
  266.     DTAClr                ; Point DI at start of _NewDTABuffer
  267.     mov    SI,_DTABuff
  268.     mov    DX,PATH_ROOT        ; Because we are still in the ROOT...
  269.     mov    CX,16h
  270.     mov    AH,04Fh         ; "FIND NEXT MATCH" Service of int 21h
  271.     int    21h
  272.     jnc    DiskNotEmpty
  273. ;------------------------------------------------------------------------------
  274. ;    At this point, we have finished the ROOT directory and recorded all
  275. ;    the sub-directories into the SDarray.
  276. ;    Note that number of sub-directories is in the variable,
  277. ;    CtrSubDir, while the offset into the SDarray is in PtrSubDir.
  278. ;------------------------------------------------------------------------------
  279.     mov    CX,CtrSubDir
  280.     cmp    CX,0
  281.     jne    SubDirStepTwo        ; Exit here if NO sub-directories
  282.     jmp    RetToCaller
  283. SubDirStepTwo:
  284.     mov    SI,START_SUBS
  285.     mov    AX,66
  286.     mov    CX,CtrSubLoop        ; This will keep place as we step thru
  287.     inc    CtrSubLoop
  288.     cmp    CX,CtrSubDir
  289.     jb    SubDirStepThree
  290.     jmp    short    RetToCaller    ; This is the END OF THE SHOW
  291. SubDirStepThree:
  292.     mul    CL
  293.     add    SI,AX            ; Now DS:SI points at right offset
  294.                     ;    into SDarray()
  295.     mov    DX,SI            ; For use a few steps from now
  296.  
  297.     mov    SI,_DTABuff
  298.     mov    CX,16h
  299.     mov    AH,04Eh         ; "FIND FIRST" in this SubDir
  300.     int    21h
  301.  
  302.     jc    SubDirStepTwo        ; Try the NEXT sub-Directory
  303. FoundSubDirFile:
  304.     mov    SI,_DTAFileAttr
  305.     mov    AL,[SI]
  306.     cmp    AL,10h            ; Is this a sub-sub...?
  307.     jne    MoreFilesInSubDir    ;    - No
  308.     add    SI,09            ;    - Maybe... but
  309.     cmp    byte ptr[SI],'.'    ;    ignore all "." and ".."
  310.     je    MoreFilesInSubDir
  311.  
  312.     mov    AX,PtrSubDir
  313.     add    AX,66
  314.     mov    DI,AX
  315.     mov    PtrSubDir,AX        ; PtrSubDir = next open row SDarray
  316.     inc    CtrSubDir        ; Keep the count straight
  317.     mov    SI,DX
  318.     add    SI,3
  319. MoveSubSubName:
  320.     lodsb
  321.     cmp    AL,'*'
  322.     je    MakeNewPath
  323.     stosb
  324.     jmp    short    MoveSubSubName
  325. MakeNewPath:
  326.     mov    SI,_DTAFileName     ; Again points at _NewDTABuffer FileName
  327. MNPAA:
  328.     lodsb
  329.     cmp    AL,0
  330.     je    EndNewPath
  331.     stosb
  332.     jmp    short    MNPAA
  333. EndNewPath:
  334.     SubEND
  335. MoreFilesInSubDir:
  336.     DTAClr
  337.     mov    CX,16h
  338.     mov    SI,_DTABuff        ; DS:DX still points at correct SubDirs
  339.     mov    AH,04Fh
  340.     int    21h
  341.  
  342.     jnc    FoundSubDirFile
  343.     jmp    SubDirStepTwo
  344. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  345.  
  346. RetToCaller:
  347.     mov    BX,DS            ; Save DS temporarily
  348.     mov    AX,OldDTASeg        ; Here we restore the entry DTA address
  349.     mov    DS,AX
  350.     ASSUME    DS:NOTHING
  351.  
  352.     mov    DX,OldDTAOff
  353.     mov    AH,01Ah         ; "SET DTA ADDR" Service of int 21h
  354.     int    21h
  355.  
  356.     mov    DS,BX            ; Now restore DS from BX
  357.     ASSUME    DS:DGROUP
  358.  
  359.     mov    DX,CurrDrive
  360.     mov    AH,0Eh
  361.     int    21h            ; Restore Entry Default Drive
  362.  
  363.     mov    DX,PATH_RETURN        ; Restore Entry Default Directory
  364.     mov    AH,03Bh
  365.     int    21h
  366.  
  367.     mov    AX,CtrSubDir
  368.     mov    CL,66            ; CL = max length of a SubDirName
  369.     mul    CL            ; Multiply by the number of found
  370.                     ;    SubDirs to get total # bytes
  371.                     ;    to move.
  372.     mov    CX,AX            ; CX will control the loop
  373.     jcxz    FastExitGetDirs     ; If CX = 0 then NO subdirs were found
  374.  
  375.     mov    SI,START_SUBS        ; Point DS:SI at start of SubDir Names
  376.     mov    AX,SegSubDir
  377.     mov    ES,AX
  378.     mov    DI,OffSubDir        ; Point ES:DI at start of SDarray
  379. TransSDChar:
  380.     lodsb                ; Move all the characters,
  381.                     ;    except for trailing "*.*"
  382.     cmp    AL,'*'
  383.     je    Lose_This_Char
  384.     cmp    AL,'.'
  385.     je    Lose_This_Char
  386.     cmp    AL,32            ; If the AL value < 32, substitute
  387.                     ;    blank spaces, since you may
  388.                     ;    need / want to use the QB
  389.     jae    Keep_Sub_Dir_Char    ;    function, "RTRIM$" (eliminate
  390.                     ;    the trailing CHR$(0)'s)
  391. Lose_This_Char:
  392.     mov    AL,32            ; Replace offending char with blank
  393. Keep_Sub_Dir_Char:
  394.     stosb
  395.     loop    TransSDChar
  396.  
  397.     mov    AX,CtrSubDir        ; Return number of subdirectories
  398.     inc    AX            ; Correct the count for root dir
  399. FastExitGetDirs:
  400.     ret                            ; PROGRAM TERMINATION
  401.  
  402. GetDirs     ENDP
  403.         END
  404.  
  405. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  406.