home *** CD-ROM | disk | FTP | other *** search
- unit Drives;
- {
- Drives Unit for:
- Getting and setting drive labels.
- Getting and setting drive serial number.
- Testing if a drive is ready.
- Determining the type of drive (hard/3.5/5.25...)
- Return last DOS error status.
-
- All procedures and functions are protected from DOS critical errors.
-
- Author: William R. Florac
- Company: FITCO, Verona, WI (wee little company from my house)
- Copyright 1996, FITCO. All rights reserved.
-
- 1) Users of Drives.pas must accept this disclaimer of warranty:
- This Unit is supplied as is. The Fitco disclaims all
- warranties, expressed or implied, including, without limitation,
- the warranties of merchantability and of fitness for any purpose.
- Fitco assumes no liability for damages, direct or conse-
- quential, which may result from the use of this Unit."
-
- 2) This Unit is donated to the public as public domain except as
- noted below.
-
- 3) You must copy all Software without modification and must include
- all pages, if the Software is distributed without inclusion in your
- software product. If you are incorporating the Software in
- conjunction with and as a part of your software product which adds
- substantial value, you may modify and include portions of the
- Software.
-
- 4) Fitco retains the copyright for this Unit. You may not distribute
- the source code (PAS) or its compiled unit (DCU) for profit.
-
- 5) If you do find this Unit handy and you feel guilty
- for using such a great product without paying someone,
- please feel free to send a few bucks ($25) to support further
- development.
-
- 6) This file was formated with tabs set to 2.
-
- Please forward any comments or suggestions to Bill Florac at:
- email: flash@etcconnect.com
- www: http://sumac.etcconnect.com/~fitco/
- mail: FITCO
- 209 Jenna Dr
- Verona, WI 53593
-
- Revision History
- 2/28/96
- 1.0 released
- }
-
-
- interface
-
- uses
- SysUtils, WinProcs, WinTypes;
-
- type
- TDriveStyle = (tUnknown, tNoDrive, t3Floppy, t5Floppy, tFixed, tRFixed,
- tNetwork, tCDROM, tTape);
-
- PDeviceParams = ^TDeviceParams;
- TDeviceParams = record
- bSpecFunc: byte; {Special functions}
- bDevType: byte; {Device type}
- wDevAttr: word; {Device attributes}
- wCylinders: word; {Number of cylinders}
- bMediaType: byte; {Media type}
- { Beginning of BIOS parameter block (BPB)}
- wBytesPerSec: word; {Bytes per sector}
- bSecPerClust: byte; {Sectors per cluster}
- wResSectors: word; {Number of reserved sectors}
- bFATs: byte; {Number of FATs}
- wRootDirEnts: word; {Number of root-directory entries}
- wSectors: word; {Total number of sectors}
- bMedia: byte; {Media descriptor}
- wFATsecs: word; {Number of sectors per FAT}
- wSecPerTrack: word; {Number of sectors per track}
- wHeads: word; {Number of heads}
- dwHiddenSecs: longInt; {Number of hidden sectors}
- dwHugeSectors: longInt; {Number of sectors if wSectors == 0}
- reserved: array[0..10] of char;
- { End of BIOS parameter block (BPB)}
- end;
-
- {parameter block for getting serial number}
- PSerialNumberParams = ^TSerialNumberParams;
- TSerialNumberParams = record
- wInfoLevel: word;
- dwDiskSerialNumber: longint;
- caLabel: array[0..10] of char;
- baFileSystem: array[0..7] of char;
- end;
-
-
- {parameter block to get extened error codes}
- PExtErrorParams = ^TExtErrorParams;
- TExtErrorParams = record
- eCode: word;
- eClass: word;
- eAction: word;
- eLocus: word;
- eVolume: String;
- end;
-
- {structure for FCB}
- TEFCB = record
- Flag: byte;
- Reserved: array [0..4] of char;
- Attribute: byte;
- Drive: byte;
- Name: array [0..7] of char;
- Extension: array [0..2] of char;
- Misc: array [0..24] of char;
- end;
-
- DriveLabel = string[11];
-
- {my exception class}
- EDriveException = Class(Exception);
-
- const
- {$I strings} { can be found at the END of this module !}
-
- {standard calls}
- function DriveReady(wDrive: word): boolean;
- {Tests to see if a drive is ready. (floppy there and door closed)}
-
- function GetDriveLabel(wDrive: word): string;
- function SetDriveLabel(wDrive: word; s: string): boolean;
- {Gets and sets drive label}
-
- function GetDriveSerialNumber(wDrive: word): LongInt;
- function SetDriveSerialNumber(wDrive: word; SerialNumber: LongInt): boolean;
- {Gets and sets drive serial number}
-
- function GetDefaultDrive: word;
- {Returns current default drive}
-
- function GetDriveStyle(wDrive: word): TDriveStyle;
- {Returns the drive style (hard, 3-1/2, 5-1/4...)}
-
- procedure GetExtendedErrorInfo(ep: PExtErrorParams);
- {Gets the parameters for the last DOS error. Useful after a DriveReady failure.}
-
- {other calls}
- function IsCDROMDrive(wDrive: word): boolean;
- function WriteDriveSNParam(wDrive: word; psnp: PSerialNumberParams): boolean;
- function ReadDriveSNParam(wDrive: word; psnp: PSerialNumberParams): boolean;
- function GetDeviceParameters(wDrive: word; var dp: TDeviceParams): boolean;
-
-
- implementation
-
- {determins if the drive is ready w/o critical errors enabled}
- function DriveReady(wDrive: word): boolean;
- var
- OldErrorMode: Word;
- begin
- {turn off errors}
- OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
- try
- if DiskSize(wDrive) = -1
- then result := false
- else result := true;
- finally
- {turn on errors}
- SetErrorMode(OldErrorMode);
- end;
-
- end;
-
- {get drive parameters w/o drive access}
- function GetDeviceParameters(wDrive: word; var dp: TDeviceParams): boolean;
- begin
- result := TRUE; {Assume success}
- asm
- push ds
- mov bx, wDrive
- mov ch, 08h {Device category--must be 08h}
- mov cl, 60h {MS-DOS IOCTL Get Device Parameters}
- lds dx, dp
- mov ax, 440Dh
- int 21h
- jnc @gdp_done {CF SET if error}
- mov result, FALSE
- @gdp_done:
- pop ds
- end;
- end;
-
- {gets last error message from DOS}
- procedure GetExtendedErrorInfo(ep: PExtErrorParams);
- var
- tCode: word;
- tClass: byte;
- tAction: byte;
- tLocus: byte;
- begin
- asm
- push ds
- push bp
- mov bx, 0
- mov ah, 59h
- int 21h
- mov tCode, ax
- mov tClass, bh
- mov tAction, bl
- mov tLocus, ch
- pop bp
- pop ds
- end;
- ep^.eCode := tCode;
- ep^.eClass := tClass;
- ep^.eAction := tAction;
- ep^.eLocus := tLocus;
- ep^.eVolume := '?'; {don't support this for now}
- end;
-
- {get volume serial number for a drive: 0=default, 1=A...}
- {returns -1 if unable to read}
- function GetDriveSerialNumber(wDrive: word): LongInt;
- var
- snp: TSerialNumberParams;
- begin
- snp.dwDiskSerialNumber := 0;
- if ReadDriveSNParam(wDrive, @snp)
- then Result := snp.dwDiskSerialNumber
- else Result := -1;
- end;
-
-
- {set volume serial number for a drive: 0=default, 1=A... }
- {returns true if it was sucessful}
- function SetDriveSerialNumber(wDrive: word; SerialNumber: LongInt): boolean;
- var
- snp: TSerialNumberParams;
- begin
- result := false;
- {get current parameters}
- if ReadDriveSNParam(wDrive, @snp) then begin
- {change serial number}
- snp.dwDiskSerialNumber := SerialNumber;
- {and write back out}
- if WriteDriveSNParam(wDrive, @snp) then result := true;
- end;
- end;
-
- {Write Drive parameters: 0=default, 1=A...}
- {Note: wDrive and psnp are treate as var with assembler directive}
- {This interupt does NOT generate a critical error!}
- function WriteDriveSNParam(wDrive: word; psnp: PSerialNumberParams): boolean; assembler;
- asm
- push ds {ds might get changed so save it}
- mov bx, wDrive
- mov al, 01h
- mov ah, 69h
- lds dx, psnp
- int 21h
- jnc @no_error {CF SET if error}
- xor ax,ax {set false}
- jmp @exit
- @no_error:
- mov ax, 1 {set true}
- @exit:
- pop ds {restore ds}
- end;
-
- {Read Drive parameters: 0=default, 1=A...}
- {Note: wDrive and psnp are treate as var with assembler directive}
- {This interupt does NOT generate a critical error!}
- function ReadDriveSNParam(wDrive: word; psnp: PSerialNumberParams): boolean; assembler;
- asm
- push ds
- mov bx, wDrive
- mov al, 00h
- mov ah, 69h
- lds dx, psnp
- int 21h
- jnc @no_error {CF SET if error}
- xor ax,ax {set false}
- jmp @exit
- @no_error:
- mov ax, 1 {set true}
- @exit:
- pop ds
- end;
-
- {sets the label of the drive specified: wDrive: 0=default 1=A...}
- {returns true if it was sucessful}
- function SetDriveLabel(wDrive: word; s: string): boolean;
- const
- EFCB: TEFCB = (
- Flag: $FF; { Extended FCB Flag }
- Reserved: (#0,#0,#0,#0,#0); { Reserved}
- Attribute: $08; { Volume Label Attribute}
- Drive: 2; { Drive Identifier}
- Name: '????????'; { File Name}
- Extension: '???'; { File Extension}
- Misc: (#0, #0, #0, #0, #0, { Misc. Info filled by DOS}
- ' ',' ',' ',' ',' ',' ',' ',' ', { Misc. Info filled by DOS}
- ' ',' ',' ', { Misc. Info filled by DOS}
- #0, #0, #0, #0, #0, #0, #0, #0, #0 { Misc. Info filled by DOS}
- )
- );
- var
- Ps: pchar;
- err: integer;
- x: integer;
-
- begin
- {abort if drive not ready}
- if not DriveReady(wDrive) then begin
- result := false;
- exit;
- end;
- {assume ok}
- result := true;
-
- {default things that change in constant varaiable}
- EFCB.Name := '????????';
- EFCB.Extension := '???';
- EFCB.Drive := wDrive;
-
- {See if it exist using a FCB}
- asm
- {Check to see; if the volume label exists}
- {point DTA to ourself}
- mov dx,offset EFCB
- mov ah,1Ah
- int 21h
- {point to default FCB}
- mov dx, offset EFCB
- mov ah, 11h
- int 21h
- {Exit if label is not present}
- cmp al, 0
- jne @exit
- {Else delete the volume label}
- mov dx, offset EFCB
- mov ah, 013h
- int 21h
- or al,al
- jz @exit
- mov result, 0
- @exit:
- end;
-
- if not result then exit;
-
- {if string is empty, then just erase}
- if length(s) = 0 then exit;
- {format string}
- for x := length(s) + 1 to 11 do s[x] := ' ';
- s[0] := char(11);
- {add drive letter!}
- if wdrive = 0
- then s := '\' + s + #0
- else s := chr(64+wdrive) + ':\' + s + #0;
- ps := @s[1];
-
- {on now make new one it!}
- asm
- push ds
- lds dx, ps
- mov cx, faVolumeID
- mov ah,3Ch
- int 21h
- {CF set if error}
- jnc @noerror
- mov result, FALSE
- jmp @exit
- @noerror:
- {close file ax = handle}
- mov bx,ax
- mov ah,3Eh
- int 21h
- @exit:
- pop ds
- end
- end;
-
- {Get label from drive. 0=default, 1=A...}
- {return string of 11 character or "NO NAME" if not found}
- function GetDriveLabel(wDrive: word): string;
- const
- pattern: string[6] = 'c:\*.*';
- var
- sr: TsearchRec;
- OldErrorMode: Word;
- DotPos: Byte;
- begin
- {get default drive}
- if wDrive = 0
- then wDrive := GetDefaultDrive
- else dec(wDrive);
-
- {switch out drive letter}
- pattern[1] := char(65 + wDrive);
-
- {stop errors and try}
- OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
- try
- if FindFirst(Pattern, faVolumeID, sr) = 0 then begin
- Result := sr.Name;
- DotPos := Pos('.', Result);
- if DotPos <> 0 then Delete(Result, DotPos, 1);
- end
- else result := 'NO NAME'
- finally
- {restore errorsa}
- SetErrorMode(OldErrorMode);
- end;
- end;
-
- function GetDefaultDrive: word; assembler;
- asm
- mov ah, 19h {convert default to real}
- int 21h
- xor ah, ah {clear hi byte}
- end;
-
- {Determine id drive is a CDROM, 0=default, 1=A ...}
- function IsCDROMDrive(wDrive: word): boolean; assembler;
- var
- wTempDrive: word;
- asm
- mov ax, wDrive
- or ax, ax
- jnz @not_default
- mov ah, 19h {convert default to drive}
- int 21h
- xor ah, ah
- mov wTempDrive, ax
- jmp @test_it
- @not_default: {zero base it}
- dec ax
- mov wTempDrive, ax
- @test_it:
- mov ax, 1500h {first test for presence of MSCDEX}
- xor bx, bx
- int 2fh
- mov ax, bx {MSCDEX is not there if bx is zero}
- or ax, ax {so return FALSE}
- jz @no_mscdex
- mov ax, 150bh {MSCDEX driver check API}
- mov cx, wTempDrive {...cx is drive index}
- int 2fh
- or ax, ax
- @no_mscdex:
- end;
-
- {returns drive type}
- {read BOIS not drive so floppy does not have to be in drive}
- {I don't have all types of drive so not all could be tested}
- function GetDriveStyle(wDrive: word): TDriveStyle;
- var
- x: word;
- wTempDrive: word;
- dp: TDeviceParams;
- begin
- {convert default to drive}
- if wDrive = 0
- then wTempDrive := GetDefaultDrive
- else wTempDrive := wDrive - 1;
- x := GetDriveType(wTempDrive);
-
- {get types}
- case x of
- drive_Removable: begin
- dp.bSpecFunc := 0; {need to clear this}
- if GetDeviceParameters(wDrive,dp) then begin
- case dp.bDevType of
- 0,1: result := t5floppy; {320K/360K/1.2M}
- 2,7,9: result := t3floppy; {720K/1.44M/2.88M}
- 5: result := tRFixed; {yes a removable fixed drive!}
- 6: result := tTape; {tape}
- else result := tUnknown;
- end;
- end
- else result := tUnknown;
- end;
- drive_Fixed:
- if IsCDROMDrive(wDrive)
- then result := tCDROM
- else result := tFixed;
- drive_Remote:
- if IsCDROMDrive(wDrive) {I think this is possible on a network!}
- then result := tCDROM
- else result := tNetWork;
- else result := tUnknown;
- end;
- end;
-
- end. {of unit}
-
- { ---------------- STRINGS.PAS ---------------------------------}
- { CUT }
-
- {string constants for drives.pas}
-
- {The error class may be one of the following}
- eClassStr: array[0..$0D] of string = (
- {OK }'OK',
- {ERRCLASS_OUTRES (01h) }'Out of resource, such as storage.',
- {ERRCLASS_TEMPSIT (02h) }'Not an error, temporary situation (file or record lock)',
- {ERRCLASS_AUTH (03h) }'Authorization problem.',
- {ERRCLASS_INTRN (04h) }'Internal error in system.',
- {ERRCLASS_HRDFAIL (05h) }'Hardware failure.',
- {ERRCLASS_SYSFAIL (06h) }'System software failure (missing or incorrect configuration files).',
- {ERRCLASS_APPERR (07h) }'Application error.',
- {ERRCLASS_NOTFND (08h) }'File or item not found.',
- {ERRCLASS_BADFMT (09h) }'File or item with an invalid format or type.',
- {ERRCLASS_LOCKED (0Ah) }'Interlocked file or item.',
- {ERRCLASS_MEDIA (0Bh) }'Wrong disk in drive, bad spot on disk, or other storage-medium problem.',
- {ERRCLASS_ALREADY (0Ch) }'Existing file or item.',
- {ERRCLASS_UNK (0Dh) }'Unknown.');
-
- {*The suggested action may be one of the following:}
- eActionStr: array[0..$07] of string = (
- {OK }'OK',
- {ERRACT_RETRY (01h) }'Retry immediately.',
- {ERRACT_DLYRET (02h) }'Delay and retry.',
- {ERRACT_USER (03h) }'Bad user input, get new values.',
- {ERRACT_ABORT (04h) }'Terminate in an orderly manner.',
- {ERRACT_PANIC (05h) }'Terminate immediately.',
- {ERRACT_IGNORE (06h) }'Ignore the error.',
- {ERRACT_INTRET (07h) }'Remove the cause of the error (to change disks, for example) and then retry.');
-
- {The error location may be one of the following:}
- eLocusStr: array[0..$05] of string = (
- {OK }'OK',
- {ERRLOC_UNK (01h) }'Unknown',
- {ERRLOC_DISK (02h) }'Random-access device, such as a disk drive',
- {ERRLOC_NET (03h) }'Network',
- {ERRLOC_SERDEV (04h) }'Serial device',
- {ERRLOC_MEM (05h) }'Memory');
-
- {MS DOS error codes}
- eDosErrorStr: array[0..$5A] of string = (
- {0000h non error} 'OK',
- {0001h} 'ERROR_INVALID_FUNCTION',
- {0002h} 'ERROR_FILE_NOT_FOUND',
- {0003h} 'ERROR_PATH_NOT_FOUND',
- {0004h} 'ERROR_TOO_MANY_OPEN_FILES',
- {0005h} 'ERROR_ACCESS_DENIED',
- {0006h} 'ERROR_INVALID_HANDLE',
- {0007h} 'ERROR_ARENA_TRASHED',
- {0008h} 'ERROR_NOT_ENOUGH_MEMORY',
- {0009h} 'ERROR_INVALID_BLOCK',
- {000Ah} 'ERROR_BAD_ENVIRONMENT',
- {000Bh} 'ERROR_BAD_FORMAT',
- {000Ch} 'ERROR_INVALID_ACCESS',
- {000Dh} 'ERROR_INVALID_DATA',
- {000Eh} 'Reserved',
- {000Fh} 'ERROR_INVALID_DRIVE',
- {0010h} 'ERROR_CURRENT_DIRECTORY',
- {0011h} 'ERROR_NOT_SAME_DEVICE',
- {0012h} 'ERROR_NO_MORE_FILES',
- {0013h} 'ERROR_WRITE_PROTECT',
- {0014h} 'ERROR_BAD_UNIT',
- {0015h} 'ERROR_NOT_READY',
- {0016h} 'ERROR_BAD_COMMAND',
- {0017h} 'ERROR_CRC',
- {0018h} 'ERROR_BAD_LENGTH',
- {0019h} 'ERROR_SEEK',
- {001Ah} 'ERROR_NOT_DOS_DISK',
- {001Bh} 'ERROR_SECTOR_NOT_FOUND',
- {001Ch} 'ERROR_OUT_OF_PAPER',
- {001Dh} 'ERROR_WRITE_FAULT',
- {001Eh} 'ERROR_READ_FAULT',
- {001Fh} 'ERROR_GEN_FAILURE',
- {0020h} 'ERROR_SHARING_VIOLATION',
- {0021h} 'ERROR_LOCK_VIOLATION',
- {0022h} 'ERROR_WRONG_DISK',
- {0023h} 'ERROR_FCB_UNAVAILABLE',
- {0024h} 'ERROR_SHARING_BUFFER_EXCEEDED',
- {0025h} 'ERROR_CODE_PAGE_MISMATCHED',
- {0026h} 'ERROR_HANDLE_EOF',
- {0027h} 'ERROR_HANDLE_DISK_FULL',
- {0028h} 'Reserved',
- {0029h} 'Reserved',
- {002Ah} 'Reserved',
- {002Bh} 'Reserved',
- {002Ch} 'Reserved',
- {002Dh} 'Reserved',
- {002Eh} 'Reserved',
- {002Fh} 'Reserved',
- {0030h} 'Reserved',
- {0031h} 'Reserved',
- {0032h} 'ERROR_NOT_SUPPORTED',
- {0033h} 'ERROR_REM_NOT_LIST',
- {0034h} 'ERROR_DUP_NAME',
- {0035h} 'ERROR_BAD_NETPATH',
- {0036h} 'ERROR_NETWORK_BUSY',
- {0037h} 'ERROR_DEV_NOT_EXIST',
- {0038h} 'ERROR_TOO_MANY_CMDS',
- {0039h} 'ERROR_ADAP_HDW_ERR',
- {003Ah} 'ERROR_BAD_NET_RESP',
- {003Bh} 'ERROR_UNEXP_NET_ERR',
- {003Ch} 'ERROR_BAD_REM_ADAP',
- {003Dh} 'ERROR_PRINTQ _FULL',
- {003Eh} 'ERROR_NO_SPOOL_SPACE',
- {003Fh} 'ERROR_PRINT_CANCELLED',
- {0040h} 'ERROR_NETNAME_DELETED',
- {0041h} 'ERROR_NETWORK_ACCESS_DENIED',
- {0042h} 'ERROR_BAD_DEV_TYPE',
- {0043h} 'ERROR_BAD_NET_NAME',
- {0044h} 'ERROR_TOO_MANY_NAMES',
- {0045h} 'ERROR_TOO_MANY_SESS',
- {0046h} 'ERROR_SHARING_PAUSED',
- {0047h} 'ERROR_ERROR_REQ _NOT_ACCEP',
- {0048h} 'ERROR_REDIR_PAUSED',
- {0049h} 'Reserved',
- {004Ah} 'Reserved',
- {004Bh} 'Reserved',
- {004Ch} 'Reserved',
- {004Dh} 'Reserved',
- {004Eh} 'Reserved',
- {004Fh} 'Reserved',
- {0050h} 'ERROR_FILE_EXISTS',
- {0051h} 'ERROR_DUP_FCB',
- {0052h} 'ERROR_CANNOT_MAKE',
- {0053h} 'ERROR_FAIL_I24',
- {0054h} 'ERROR_OUT_OF_STRUCTURES',
- {0055h} 'ERROR_ALREADY_ASSIGNED',
- {0056h} 'ERROR_INVALID_PASSWORD',
- {0057h} 'ERROR_INVALID_PARAMETER',
- {0058h} 'ERROR_NET_WRITE_FAULT',
- {0059h} 'Function not supported on Network',
- {005Ah} 'ERROR_SYS_COMP_NOT_LOADED');
-
- cDriveStr: array[0..8] of string = (
- 'Unknown',
- 'NoDrive',
- '3-1/2" floppy',
- '5-1/4" floppy',
- 'hard',
- 'removable hard',
- 'network',
- 'CD ROM',
- 'tape');