home *** CD-ROM | disk | FTP | other *** search
- {$M 5120,0,655360}
- {$N-,E- no math support needed}
- {$X- function calls may not be discarded}
- {$I- disable I/O checking (trap errors by checking IOResult)}
-
- PROGRAM FSP;
- USES DOS; {for Registers}
- CONST
- ProgramName = 'FSP (Free SPace), v1.31 - DOS Multiple Hard Disk Space Utilization Utility.';
- AuthorsName = 'Freeware, copyright(c) May 12th, 1996 by David Daniel Anderson/ Reign Ware.';
- ChartHeader = 'DRIVE ALLOCATED FREE SPACE TOTAL SPACE FREE % LABEL';
- ChartWidth = 75;
- lf = #13#10;
- Black = 0;
- Blue = 1;
- Green = 2;
- Cyan = 3;
- Red = 4;
- Magenta = 5;
- Brown = 6;
- LightGray = 7;
- DarkGray = 8;
- LightBlue = 9;
- LightGreen = 10;
- LightCyan = 11;
- LightRed = 12;
- LightMagenta = 13;
- Yellow = 14;
- White = 15;
-
- { GetDriveType return values. REQUIRES DOS 3.x or greater}
-
- dtError = 0; { Drive physically isn't available }
- dtRemote = 1; { Remote (network) disk drive }
- dtFixed = 2; { Fixed (hard) disk drive }
- dtRemovable = 3; { Removable (floppy) disk drive }
- dtBadVer = $FF; { Invalid DOS version (DOS 3.x required) }
-
- VAR
- TS, TF, TU : REAL; {bytes of Total space Size/Free/Used}
- BaseOfScreen : WORD;
- Output_Redirected : BOOLEAN;
- {-----------------------------------------------------------------------------}
- PROCEDURE ShowUsage;
- BEGIN
- WriteLn (ProgramName);
- WriteLn (AuthorsName+lf);
- WriteLn ('Usage: FSP [/K] [/N] [/F]'+lf);
- WriteLn ('Where: /K = Keep screen (don''t clear)');
- WriteLn (' /N = report Network drives also');
- WriteLn (' /F = report Floppy drives also');
- Halt (1);
- END;
-
- FUNCTION RPad (bstr: STRING; len: BYTE): STRING;
- BEGIN
- WHILE (Length (bstr) < len) DO
- bstr := bstr + #32;
- RPad := bstr;
- END;
-
- FUNCTION LPad (bstr: STRING; len: BYTE): STRING;
- BEGIN
- WHILE (Length (bstr) < len) DO
- bstr := #32+bstr;
- LPad := bstr;
- END;
-
- FUNCTION WhereX: BYTE; ASSEMBLER;
- (* Routine from SWAG *)
- ASM
- MOV AH, 3 {Ask For current cursor position}
- MOV BH, 0 { On page 0 }
- Int 10h { Return inFormation in DX }
- Inc DL { Bios Assumes Zero-based. Crt.WhereX Uses 1 based }
- MOV AL, DL { Return X position in AL For use in Byte Result }
- END;
-
- FUNCTION WhereY: BYTE; ASSEMBLER;
- (* Routine from SWAG *)
- ASM
- MOV AH, 3 {Ask For current cursor position}
- MOV BH, 0 { On page 0 }
- Int 10h { Return inFormation in DX }
- Inc DH { Bios Assumes Zero-based. Crt.WhereY Uses 1 based }
- MOV AL, DH { Return Y position in AL For use in Byte Result }
- END;
-
- PROCEDURE GotoXY (X, Y: BYTE); ASSEMBLER;
- (* Routine from SWAG *)
- ASM
- MOV DH, Y { DH = Row (Y) }
- MOV DL, X { DL = Column (X) }
- Dec DH { Adjust For Zero-based Bios routines }
- Dec DL { Turbo Crt.GotoXY is 1-based }
- MOV BH, 0 { Display page 0 }
- MOV AH, 2 { Call For SET CURSOR POSITION }
- Int 10h
- END;
-
- PROCEDURE GetBaseOfScreen; ASSEMBLER;
- ASM
- MOV BaseOfScreen, $B000
- MOV AX, $0F00
- INT $10
- CMP AL, 2
- JE @XXX
- CMP AL, 7
- JE @XXX
- MOV BaseOfScreen, $B800
- @XXX:
- END;
-
- PROCEDURE FastWrite (X,Y: WORD; ColorAttr: BYTE; CONST MsgText: STRING); ASSEMBLER;
- (* From: Jens Larsson, found in SWAG *)
- ASM
- dec X
- dec Y
-
- mov AX, Y
- mov CL, 5
- shl AX, CL
- mov DI, AX
- mov CL, 2
- shl AX, CL
- add DI, AX
- shl X, 1
- add DI, X
-
- mov AX, BaseOfScreen;
- mov ES, AX
- xor CH, CH
- push DS
- lds SI, MsgText
- lodsb
- mov CL, AL
- mov AH, ColorAttr
- jcxz @@END
- @@l1:
- lodsb
- stosw
- loop @@L1
- @@end:
- pop DS
- END;
-
- PROCEDURE QWrite (Column, Line, fColor, bColor: BYTE; CONST fStr: STRING);
- VAR
- NumCol : WORD ABSOLUTE $0040 : $004A; { Number of CRT columns (1-based) }
- StrLen : BYTE ABSOLUTE fStr;
- Color : BYTE;
-
- BEGIN
- IF Output_Redirected THEN
- Write (fStr)
- ELSE BEGIN
- Color := fColor OR (bColor sHL 4);
- FastWrite (Column, Line, Color, fStr);
- GotoXY (WhereX+(StrLen MOD NumCol), WhereY+(StrLen DIV NumCol));
- END;
- END;
-
- PROCEDURE ClrScr; ASSEMBLER;
- (* Routine from SWAG *)
- ASM
- MOV AH, 0Fh
- Int 10h
- MOV AH, 0
- Int 10h
- END;
-
- FUNCTION Comma (r : REAL) : STRING; {Used in WriteDriveInfo & WriteTotalInfo}
- VAR s : STRING [14]; {Insert commas to break up number string}
- l : SHORTINT;
- BEGIN
- Str (r : 0 : 0, s);
- l := (Length (s) - 2);
- WHILE (l > 1) DO BEGIN
- Insert (',', s, l);
- Dec (l, 3);
- END;
- Comma := s;
- END;
-
- FUNCTION LeadingZero (w : WORD) : STRING;
- VAR s : STRING;
- BEGIN
- Str (w : 0, s);
- IF (Length (s) = 1) THEN
- s := '0'+s;
- LeadingZero := s;
- END;
-
- PROCEDURE UpperCase(VAR UpStr :STRING); ASSEMBLER;
- (* Routine to convert string to uppercase, from SWAG *)
- ASM
- Push ES { Save Registers to be used }
- Push DI
- Push CX
- LES DI,UpStr { Point ES:DI to string to be converted}
- Sub CX,CX { Clear CX }
- Mov CL,ES:[DI] { Load Length of string for looping }
- Cmp CX,0 { Check for a clear string }
- JE @Exit { If it was then exit }
- @ReadStr:
- Inc DI { Point to next Character }
- Cmp BYTE PTR ES:[DI],'z' { If Character above 'z' jump to end of}
- Ja @LoopEnd { loop. }
- Cmp BYTE PTR ES:[DI],'a' { if below 'a' jump to end of loop. }
- Jb @LoopEnd
- Sub BYTE PTR ES:[DI],32 { If not make it upper case }
- @LoopEnd:
- Loop @ReadStr { Loop Until done }
- @Exit:
- Pop CX { Restore registers }
- Pop DI
- Pop ES
- END;{UpperCase}
-
- FUNCTION UpStr (Source: STRING): STRING;
- BEGIN
- UpperCase (Source);
- UpStr := Source;
- END;
-
- FUNCTION OutputRedirected : BOOLEAN;
- (* FROM SWAG *)
- VAR
- Regs : REGISTERS;
- Handle : WORD ABSOLUTE Output;
- BEGIN
- WITH Regs DO
- BEGIN
- AX := $4400;
- BX := Handle;
- MsDos (Regs);
- IF (DL AND $82) = $82
- THEN OutputRedirected := FALSE
- ELSE OutputRedirected := TRUE;
- END; {With Regs}
- END; {OutputRedirected}
-
- FUNCTION DriveSize (D : BYTE) : LONGINT; { -1 not found, 1=>1 Giga }
- (* FROM SWAG *)
- VAR
- Regs : REGISTERS;
- BEGIN
- WITH Regs DO
- BEGIN
- AH := $36;
- DL := D;
- Intr ($21, Regs);
- IF AX = $FFFF THEN
- DriveSize := - 1 { Drive not found }
- ELSE
- IF (DX = $FFFF) OR (LONGINT (AX) * CX * DX = 1073725440)
- THEN DriveSize := 1
- ELSE DriveSize := LONGINT (AX) * CX * DX;
- END;
- END;
-
- FUNCTION DriveFree (D : BYTE) : LONGINT; { -1 not found, 1=>1 Giga }
- (* FROM SWAG *)
- VAR
- Regs : REGISTERS;
- BEGIN
- WITH Regs DO
- BEGIN
- AH := $36;
- DL := D;
- Intr ($21, Regs);
- IF AX = $FFFF THEN
- DriveFree := - 1 { Drive not found }
- ELSE
- IF (BX = $FFFF) OR (LONGINT (AX) * BX * CX = 1073725440)
- THEN DriveFree := 1
- ELSE DriveFree := LONGINT (AX) * BX * CX;
- END;
- END;
-
- FUNCTION GetDriveType(Drive : BYTE) : BYTE; ASSEMBLER;
- ASM
- MOV AH,30h
- INT 21h
- CMP AL,3
- JGE @@1
- MOV AL,dtBadVer
- JMP @@4
- @@1:
- MOV BL,Drive
- MOV AX,4409h
- INT 21h
- JNC @@2
- MOV AL,dtError
- JMP @@5
- @@2:
- CMP AL,True
- JNE @@3
- MOV AL,dtRemote
- JMP @@5
- @@3:
- MOV AX,4408h
- INT 21h
- CMP AL,True
- JNE @@4
- MOV AL,dtFixed
- JMP @@5
- @@4:
- MOV AL,dtRemovable
- @@5:
- END; { GetDriveType }
-
- FUNCTION IsCDROM (DRIVE: BYTE): BOOLEAN;
- (* FROM SWAG *)
- CONST
- CDROM_INTERRUPT = $2f;
- VAR
- Regs : REGISTERS;
-
- { Returns a code indicating whether a particular logical }
- { unit is supported by the Microsoft CD-ROM Extensions }
- { module (MSCDEX). }
-
- BEGIN
- Regs. AX := $150b;
- Regs. BX := $0000;
- Regs. CX := DRIVE-1;
- Intr (CDROM_INTERRUPT, Regs);
- IsCDROM := (Regs. AX <> $0000) AND (Regs. BX = $adad);
- END;
-
- FUNCTION IsDriveValid (cDrive : BYTE): BOOLEAN;
- { ** portion of a SWAG snippet -- modified for FSP
-
- Parameters: cDrive is the drive letter to check: 1 to 26 (A to Z).
-
- Returns: Function returns True only if the given drive is valid, and it
- is not SUBSTituted.
- }
- VAR
- rCPU: DOS. REGISTERS;
- bLocal,
- bSUBST : BOOLEAN;
- BEGIN
- bLocal := FALSE;
- bSUBST := FALSE;
- IsDriveValid := FALSE;
-
- rCPU. BX := cDrive;
- rCPU. AX := $4409;
- { --- Call the Dos IOCTL (InOutConTroL)-Functions --- }
- Intr ($21, rCPU);
- IF NOT ((rCPU. AX AND fCarry) = fCarry)
- THEN BEGIN { --- drive is valid, check status --- }
- bLocal := ((rCPU. DX AND $1000) = $0000);
- IF bLocal THEN bSUBST := ((rCPU. DX AND $8000) = $8000);
- IF (NOT bSUBST) THEN IsDriveValid := TRUE;
- END;
- END; { IsDriveValid }
-
- PROCEDURE WriteDTInf; {Called by WriteHeader to write Date & Time.}
- CONST
- Mon : ARRAY [1..12] OF STRING [9] =
- ('January', 'February', 'March', 'April', 'May', 'June', 'July',
- 'August', 'September', 'October', 'November', 'December');
- comma = #44;
- space = #32;
- colon = #58;
- VAR
- Year, Month, Day, dow,
- Hour, Min, Sec, hund : WORD;
- DStr : STRING [8];
- YStr : STRING [4];
- DateStr : STRING [ChartWidth - 8];
- OFFSET : BYTE;
- BEGIN
- GetDate (Year, Month, Day, dow);
- GetTime (Hour, Min, Sec, hund);
- Str (Day, DStr);
- Str (Year, YStr);
- DateStr := Mon [Month]+space+DStr+comma+space+YStr;
- OFFSET := Length (DateStr);
- DateStr [0] := Chr (ChartWidth - 8);
- FillChar (DateStr [OFFSET+1], (ChartWidth - (OFFSET+8)), space);
- QWrite (WhereX, WhereY, LightBlue, Black,
- (DateStr+LeadingZero(Hour)+colon+LeadingZero(Min)+colon+LeadingZero(Sec)));
- WriteLn;
- END;
-
- PROCEDURE WriteHeader; {Called by main.}
- VAR
- hyphens : STRING [ChartWidth];
- BEGIN
- QWrite (WhereX, WhereY, White, Blue, ProgramName); WriteLn;
- QWrite (WhereX, WhereY, White, Blue, AuthorsName); WriteLn;
-
- WriteDTInf;
- QWrite (WhereX, WhereY, LightCyan, Black, ChartHeader); WriteLn;
-
- hyphens [0] := Chr (ChartWidth);
- FillChar (hyphens [1], ChartWidth, '-');
- QWrite (WhereX, WhereY, LightCyan, Black, hyphens); WriteLn;
- END;
-
- PROCEDURE WriteSizes (u, f, s : REAL);
- BEGIN
- QWrite (WhereX, WhereY, LightRed, Black, LPad (Comma (U), 15));
- QWrite (WhereX, WhereY, LightGreen, Black, LPad (Comma (F), 15));
- QWrite (WhereX, WhereY, LightMagenta, Black, LPad (Comma (S), 15));
- END;
-
- PROCEDURE WritePercent (Free, Space : REAL); { Called by WriteDriveInfo }
- { & WriteTotalInfo. }
- VAR
- PF : REAL; {integer of Percentage Free, initially 10 x %}
- wStr : STRING [ChartWidth];
- BEGIN
- IF (Space > 0)
- THEN PF := 100 * (Free / Space) {Using 100 to give hundredths of %}
- ELSE PF := 0;
- Str (PF : 8 : 2, wStr);
- QWrite (WhereX, WhereY, White, Black, wStr+'%');
- END;
-
- PROCEDURE WriteDriveInfo (DriveNumber : BYTE); {Called by main.}
- VAR
- DS, DF, DU : LONGINT; {bytes of *partition* space Size/Free/Used}
- VolLabel : SEARCHREC;
- VolName : STRING [12];
- DriveLetter : CHAR;
- DotPos : BYTE;
- BEGIN
- DriveLetter := Chr (DriveNumber+64);
-
- DS := DriveSize (DriveNumber);
- IF (DS < 0) THEN
- BEGIN
- DS := 0;
- DF := 0;
- END
- ELSE
- DF := DriveFree (DriveNumber);
-
- DU := DS-DF;
- TS := TS+DS;
- TF := TF+DF;
- TU := TU+DU;
-
- QWrite (WhereX, WhereY, Yellow, Black, DriveLetter+' -=> ');
-
- WriteSizes (DU, DF, DS);
- WritePercent (DF, DS);
-
- FindFirst (DriveLetter+':\*.*', $8, VolLabel);
- IF (DosError <> 0) THEN
- VolName := '* none *'
- ELSE BEGIN
- VolName := VolLabel. Name;
- DotPos := Pos ('.', VolName);
- IF (DotPos <> 0) THEN
- VolName := RPad (Copy (VolName, 1, DotPos-1), 8) + Copy (VolName, DotPos+1, 3);
- { remove period if present, and pad first part of volume name }
- END;
- QWrite (WhereX, WhereY, Yellow, Black, ' '+VolName);
- WriteLn;
- END;
-
- PROCEDURE WriteTotalInfo; {Called by main.}
- VAR
- EQLine : STRING [ChartWidth];
- BEGIN
- EQLine [0] := Chr (ChartWidth);
- FillChar (EQLine [1], ChartWidth, '=');
- QWrite (WhereX, WhereY, LightGray, Black, EQline);
- WriteLn;
-
- QWrite (WhereX, WhereY, Yellow, Black, 'TOTALS=');
- WriteSizes (TU, TF, TS);
- WritePercent (TF, TS);
- WriteLn;
- END;
-
- PROCEDURE GetParams (VAR ChkFlp, ChkNet: BOOLEAN);
- VAR
- CmdLine : STRING;
- BEGIN
- CmdLine := UpStr (STRING (Ptr (PrefixSeg, $0080)^));
- IF (Pos ('?', CmdLine) > 0) THEN
- ShowUsage;
-
- IF NOT (Pos ('/K', CmdLine) > 0) THEN ClrScr;
- ChkNet := (Pos ('/N', CmdLine) > 0);
- ChkFlp := (Pos ('/F', CmdLine) > 0);
- TS := 0; TF := 0; TU := 0; { initialize global variables also }
- GetBaseOfScreen; { ditto }
- Output_Redirected := OutputRedirected; { ditto }
- END;
- {=============================================================================}
-
- VAR
- DriveNum, { loop counter, drive }
- DriveType : BYTE; { Type of drive: Fixed, Remote (Net) or Removable }
- ChkFlp,
- ChkNet,
- bSUBST, { drive local/remote?; SUBSTed or not? }
- CHECK : BOOLEAN; { Check this drive? }
-
- BEGIN
- GetParams (ChkFlp, ChkNet); {& init global vars}
- WriteHeader;
- FOR DriveNum := 1 TO 26 DO { Check all drives, up to 'Z' }
- IF IsDriveValid (DriveNum) THEN
- BEGIN
- DriveType := GetDriveType (DriveNum);
- IF (DriveType <> dtError) AND (NOT IsCDROM (DriveNum)) THEN
- BEGIN
- CHECK := FALSE;
- CASE DriveType OF
- dtFixed : CHECK := TRUE;
- dtRemote : IF (ChkNet) THEN CHECK := TRUE;
- dtRemovable : IF (ChkFlp) THEN CHECK := TRUE;
- END;
- IF CHECK THEN WriteDriveInfo (DriveNum);
- END;
- END;
- WriteTotalInfo; {using global vars}
- END.
-