[Back to DRIVES SWAG index] [Back to Main SWAG index] [Original]

    USES CRT;

    {
    Here is my DRIVES routine again to return all valid drive letters on a
    PC. This is a fix from the last version which incorrectly addressed
    the local variables and wound up hosing memory. I also added some
    extensive comments for readability. Enjoy! }

    {*****************************************************************************
     * Function ...... Drives
     * Purpose ....... To return a string containing the valid drives for the
     * current system.
     * Parameters .... None
     * Returns ....... A string of the valid drive letters.
     * Notes ......... Rather than changing to each drive to see if it exists, we
     * can instead call DOS Function 26h - Parse a file name.
     * If the file name is invalid (eg, F:), then DOS will say
     * so. So, by testing each drive letter as a file name,
     * DOS will tell us which are good and which are bad!
     * Author ........ Martin Richardson
     * Date .......... August 6, 1993
     * Update ........ 02-01-94: Corrected problem where local VAR variables were
     *  not being used, but a random memory location was
     *  instead!
     * : Added comments for clarity.
     *****************************************************************************}
    FUNCTION Drives: STRING; ASSEMBLER;
    VAR
      DriveInfo:  ARRAY[1..2] OF CHAR;
      Buffer: ARRAY[1..40] OF CHAR;
      DriveString: ARRAY[1..25] OF CHAR;
    ASM
     PUSH  SI { Save Important Registers }
     PUSH  DI
     PUSH  ES
     PUSH  DS

     MOV SI, SS { The Stack Segment (SS) points to the }
     MOV DS, SI { VAR's above. Point DS to it... }
     PUSH  DS
     POP ES { ...and ES as well. }

     LEA SI, DriveInfo { DS:SI - Where we test each drive letter }
     LEA DI, Buffer { ES:DI - FCB Buffer }
     LEA BX, DriveString{ DS:BX - Our resultant string }

     MOV BYTE PTR [SI], '@' { The character before 'A' }
     XOR CX, CX { Zero out CX }

    @Scan:
     INC BYTE PTR [SI] { Next Drive Letter }
     MOV BYTE PTR [SI+1], ':'
     MOV AX, $2906 { DOS Function 29h - Parse Filename }
     INT 21h {  DS:SI - String to be parsed }
      {  ES:DI - FCB }
     LEA SI, DriveInfo { DS:SI }
     CMP AL, $FF{ AL = FFh if function fails (invalid }
     JE @NotValid { drive letter) }

     INC CX { Add one more to our string length... }
     PUSH  CX { ...and save it. }
     MOV CL, BYTE PTR DS:[SI]  { Grab the valid drive letter... }
     MOV [BX], CL  { ...and stuff it into our result }
     INC BX { Next position in result string }
     POP CX { Get our length counter back }

    @NotValid:
     CMP BYTE PTR [SI], 'Z' { Did we go through all letters? }
     JNE @Scan { Nope, so next letter }

     LEA SI, DriveString{ Store DriveString to #Result }
     LES DI, @Result
     INC DI
     REP MOVSB

     XCHG  AX, DI { This is the only way to store the }
     MOV DI, WORD PTR @Result  {  length that I can get to work. }
     SUB AX, DI
     DEC AX
     STOSB

     POP DS { Restore Important Registers }
     POP ES
     POP DI
     POP SI
    END;

    function DriveValid(Drive: Char): Boolean; assembler;
    asm
    mov  ah, 19h { Select DOS function 19h }
    int  21h { Call DOS for current disk drive }
    mov  bl, al { Save drive code in bl }
    mov  al, Drive  { Assign requested drive to al }
    sub  al, 'A' { Adjust so A:=0, B:=1, etc. }
    mov  dl, al { Save adjusted result in dl }
    mov  ah, 0eh { Select DOS function 0eh }
    int  21h { Call DOS to set default drive }
    mov  ah, 19h { Select DOS function 19h }
    int  21h { Get current drive again }
    mov  cx, 0  { Preset result to False }
    cmp  al, dl { Check if drives match }
    jne  @@1 { Jump if not--drive not valid }
    mov  cx, 1  { Preset result to True }
    @@1:
    mov  dl, bl { Restore original default drive }
    mov  ah, 0eh { Select DOS function 0eh }
    int  21h { Call DOS to set default drive }
    xchg ax, cx { Return function result in ax }
    end;

    BEGIN
         Clrscr;
         Writeln(Drives);
    END.

[Back to DRIVES SWAG index] [Back to Main SWAG index] [Original]