home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 31
/
CDASC_31_1996_juillet_aout.iso
/
vrac
/
fsp131.zip
/
FSP.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-05-12
|
14KB
|
528 lines
{$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.