Contributor: SALVATORE BESSO
unit Drives;
{ see TEST program below !! }
{ Unit Drives, written by Salvatore Besso }
{ mc8505@mclink.it }
{ This unit is freeware and is donated to }
{ the SWAG archival group. }
{ Finally, a Drives unit that correctly }
{ works in both real and protected mode, }
{ in a Windows 95 DOS box, and that doesn't }
{ require a media to be present in the }
{ removable drive. }
{ This unit is still not able to correctly }
{ recognize Iomega Zip drives in a Windows }
{ 95 DOS box for now (they are recognized }
{ as removable media). As soon as new }
{ informations will be available from the }
{ interrupt list of Ralph Brown, the unit }
{ will be modified. Actually informations }
{ about Iomega interrupt are very scarce. }
{ A new Dpmi unit is beyond the end of this }
{ unit }
{ Test program is beyond the end of the }
{ Drives and Dpmi units }
{ If you have any feedback, feel free to }
{ e-mail me }
interface
uses
 {$IFDEF DPMI}
 Dpmi,
 {$ENDIF}
 Dos;
const
 { dtXXXX constants - Drive Type }
 dtInvalid = 0ドル;
 dtUnknown = 1ドル;
 { Floppy disk }
 dt8Single = 2ドル;
 dt8Double = 4ドル;
 dt360 = 8ドル;
 dt1200 = 10ドル;
 dt720 = 20ドル;
 dt1440 = 40ドル;
 dt2880 = 80ドル;
 dtAnyFloppy = $FE;
 { Other media }
 dtTape = 100ドル;
 dtFloptical = 200ドル;
 dtRamDisk = 400ドル;
 dtCdRom = 800ドル;
 dtIomegaZip = 1000ドル;
 dtHardDisk = 80000ドル;
 { Other attributes }
 dtRemovable = 100000ドル;
 dtRemote = 200000ドル;
type
 PParamBlock = ^TParamBlock;
 TParamBlock = record
 SpecialFunctions: Byte; { Special functions }
 DeviceType : Byte; { Device type }
 DeviceAttributes: Word; { Device attributes }
 MaxCylinders : Word; { Number of cylinders }
 MediaType : Byte; { Media type }
 { Beginning of BIOS parameter block (BPB) }
 BytesPerSector : Word; { Bytes per sector }
 SectPerCluster : Byte; { Sectors per cluster }
 ReservedSectors : Word; { Number of reserved sectors }
 NumberFats : Byte; { Number of FATs }
 RootDirEntries : Word; { Number of root-directory entries }
 TotalSectors : Word; { Total number of sectors }
 MediaDescriptor : Byte; { Media descriptor }
 SectorsPerFat : Word; { Number of sectors per FAT }
 SectorsPerTrack : Word; { Number of sectors per track }
 NumberHeads : Word; { Number of heads }
 HiddenSectors : LongInt; { Number of hidden sectors }
 HugeSectors : LongInt { Number of sectors if TotalSectors = 0 }
 { End of BIOS parameter block (BPB) }
 end;
 PtrRec = record { replicated from OBJECTS.PAS to avoid using the unit }
 Ofs,Seg: Word
 end;
 DriveLetters = 'A'..'Z';
 DriveSet = Set of DriveLetters;
{ returns all available drives in a DriveSet type variable }
procedure GetDrives (var Drive: DriveSet);
{ returns drive type }
function GetDriveType (Drive: Char): LongInt;
implementation
procedure GetDrives (var Drive: DriveSet);
var
 DriveName: array[1..2] of Char;
 FCB : array[0..43] of Char;
 Dr : LongInt;
begin
 asm
 PUSH SI
 PUSH DI
 PUSH ES
 PUSH DS
 MOV SI,SS { Stack points to local variables }
 MOV DS,SI { also DS ... }
 PUSH DS
 POP ES { ...and ES }
 MOV BYTE PTR [DriveName],'A'
 MOV BYTE PTR [DriveName + 1],':'
 MOV WORD PTR [Dr],0
 MOV WORD PTR [Dr + 2],0
 MOV DX,1
 XOR CX,CX
 @@1: LEA SI,DriveName
 LEA DI,FCB
 MOV AX,290EH { Function 29H - Parse Filename - AL = options }
 INT 21H
 CMP AL,0FFH
 JE @@2
 PUSH DX
 PUSH CX
 MOV AX,4409H { SUBST drives are ignored }
 MOV BL,BYTE PTR [DriveName]
 SUB BL,'@'
 INT 21H
 JC @@2
 TEST DH,10000000B
 POP CX
 POP DX
 JNZ @@2
 OR WORD PTR [Dr],DX
 OR WORD PTR [Dr + 2],CX
 @@2: SHL DX,1
 RCL CX,1
 INC BYTE PTR [DriveName]
 CMP BYTE PTR [DriveName],'Z'
 JBE @@1
 SHL WORD PTR [Dr],1
 RCL WORD PTR [Dr + 2],1
 POP DS
 POP ES
 POP DI
 POP SI
 end;
 Drive := DriveSet (Dr)
end;
function GetDriveType (Drive: Char): LongInt;
var
 DPB : PParamBlock;
 SegInfo: Word;
 Regs : Registers;
 Temp : Byte;
 Result : LongInt;
 {$IFDEF DPMI}
 Size : LongInt;
 {$ENDIF}
function GetDevParms (Drive: Char; var DPB: PParamBlock; Segm: Word): Boolean;
var
 Regs: Registers;
begin
 GetDevParms := False;
 FillChar (Regs,SizeOf (Registers),0);
 Regs.AX := 440ドルD;
 Regs.BL := Byte (Drive) - 64;
 Regs.CH := 08ドル; { category: disk drive }
 Regs.CL := 60ドル; { device parameters }
 {$IFNDEF DPMI}
 Regs.DS := PtrRec (DPB).Seg;
 Regs.DX := PtrRec (DPB).Ofs;
 MsDos (Regs);
 {$ELSE}
 Regs.DS := Segm;
 Regs.DX := 0;
 if NOT DpmiMsDos (Regs) then Exit;
 {$ENDIF}
 GetDevParms := Regs.Flags and fCarry = 0
end;
function IsDriveRemote (Drive: Char): Boolean; assembler;
asm
 MOV AX,4409H { IOCTL - Check if block device remote }
 MOV BL,Drive { BL = drive }
 SUB BL,'@' { 1 = A:, 2 = B:, etc... }
 INT 21H
 XOR AX,AX
 JC @@1
 AND DH,00010000B
 JZ @@1
 INC AX
 @@1:
end;
function IsCDRomDrive (Drive: Char): Boolean; assembler;
asm
 MOV AX,150BH { MSCDEX.EXE installation test }
 XOR CH,CH { CX = drive }
 MOV CL,Drive
 SUB CL,'A' { 0 = A:, 1 = B:, etc... }
 INT 2FH
 PUSH AX
 POP CX
 XOR AX,AX
 JCXZ @@1
 TEST BX,0ADADH
 JZ @@1
 INC AX
 @@1:
end;
function IsIomegaZip: Boolean;
var
 Regs : Registers;
 Result: Boolean;
begin
 { Find first GUEST.EXE... }
 FillChar (Regs,SizeOf (Registers),0);
 Regs.AX := 5700ドル; { GUEST.EXE installation test }
 Regs.BX := 0201ドル; { Iomega ID ??? }
 Regs.DX := 496ドルF; { 'Io' }
 {$IFNDEF DPMI}
 Intr (2ドルF,Regs);
 {$ELSE}
 if NOT DpmiIntr (2ドルF,Regs) then Exit;
 {$ENDIF}
 Result := Regs.AL = $FF;
 if NOT Result then
 begin
 { ...GUEST.EXE not found: Find GUEST95.EXE... }
 { Interrupt informations for GUEST95.EXE still }
 { not available }
 end;
 IsIomegaZip := Result
end;
begin { GetDriveType }
 GetDriveType := dtInvalid;
 {$IFNDEF DPMI}
 New (DPB);
 SegInfo := 0;
 {$ELSE}
 Size := SizeOf (TParamBlock);
 if NOT DpmiGetMem (Pointer (DPB),SegInfo,Size) then Exit;
 {$ENDIF}
 FillChar (DPB^,SizeOf (TParamBlock),0);
 FillChar (Regs,SizeOf (Regs),0);
 Regs.AX := 4408ドル; { removable media ? }
 Regs.BL := Byte (Drive) - 64;
 {$IFNDEF DPMI}
 MsDos (Regs);
 {$ELSE}
 if NOT DpmiMsDos (Regs) then
 begin
 DpmiFreeMem (Pointer (DPB));
 Exit
 end;
 {$ENDIF}
 Temp := 0;
 if Regs.Flags and fCarry  0 then { error, check error code in AX }
 begin
 { Driver does NOT support this call, so guess as a hard disk }
 if Regs.AX = 1 then Temp := 3
 end
 else begin
 if Regs.AX = 0 then
 Temp := 2 { removable media, floppy, WORM, Floptical, ZIP }
 else Temp := 3 { or hard disk, ramdisk or CD-ROM }
 end;
 Result := dtInvalid;
 case Temp of
 { Removable }
 2: if GetDevParms (Drive,DPB,SegInfo) then
 begin
 case DPB^.DeviceType of
 0: Result := dt360;
 1: Result := dt1200;
 2: Result := dt720;
 3: Result := dt8Single;
 4: Result := dt8Double;
 5: if IsIomegaZip then Result := dtIomegaZip else Result := dtHardDisk;
 6: Result := dtTape;
 7: Result := dt1440;
 8: Result := dtFloptical;
 9: begin
 if (DPB^.MaxCylinders = 80) and (DPB^.NumberHeads = 2) then
 Result := dt2880
 else if IsIomegaZip then
 Result := dtIomegaZip
 else Result := dtUnknown
 end
 else Result := dtUnknown
 end;
 if Result> dtUnknown then Result := Result or dtRemovable
 end;
 { Fixed }
 3: if GetDevParms (Drive,DPB,SegInfo) then
 if DPB^.DeviceType = 5 then
 Result := dtHardDisk
 else Result := dtUnknown
 else Result := dtRamDisk
 end;
 if IsDriveRemote (Drive) then
 if IsCDRomDrive (Drive) then
 Result := dtCdRom or dtRemovable
 else Result := Result or dtRemote;
 {$IFNDEF DPMI}
 Dispose (DPB);
 {$ELSE}
 if NOT DpmiFreeMem (Pointer (DPB)) then Exit;
 {$ENDIF}
 GetDriveType := Result
end;
end.
(*
unit Dpmi;
{$IFNDEF DPMI}
 Error ! this code works in Protected Mode only
{$ENDIF}
{$G+,S-}
interface
uses
 Dos;
{ Virtual interrupt state values for use with the SetInterruptState and
 GetInterruptState functions. }
const
 intDisabled = False;
 intEnabled = True;
{ Return values for MemInitSwapFile and MemCloseSwapFile }
const
 rtmOK = 0ドル;
 rtmNoMemory = 1ドル;
 rtmFileIOError = 22ドル;
{ TRealModeRegs is a real mode registers data structure for use with the
 RealModeInt, RealModeCall, RealModeIntCall, and AllocRealCallback
 functions. }
type
 PRealModeRegs = ^TRealModeRegs;
 TRealModeRegs = record
 case Integer of
 0: (
 EDI,ESI,EBP,EXX,EBX,EDX,ECX,EAX: LongInt;
 Flags,ES,DS,FS,GS,IP,CS,SP,SS : Word
 );
 1: (
 DI,DIH,SI,SIH,BP,BPH,XX,XXH: Word;
 case Integer of
 0: (
 BX,BXH,DX,DXH,CX,CXH,AX,AXH: Word
 );
 1: (
 BL,BH,BLH,BHH,DL,DH,DLH,DHH,CL,CH,CLH,CHH,AL,AH,ALH,AHH: Byte
 )
 )
 end;
{ TDescriptor is an 8-byte structure for use with the GetDescriptor and
 SetDescriptor procedures. }
type
 PDescriptor = ^TDescriptor;
 TDescriptor = array[0..7] of Byte;
{ TVersionInfo is a DPMI version information structure for use with the
 GetVersionInfo procedure. }
type
 PVersionInfo = ^TVersionInfo;
 TVersionInfo = record
 MinorVersion : Byte; { AL }
 MajorVersion : Byte; { AH }
 Flags : Word; { BX }
 ProcessorType: Byte; { CL }
 Reserved : Byte; { CH }
 SlaveBaseInt : Byte; { DL }
 MasterBaseInt: Byte { DH }
 end;
{ Corresponds to procedure Intr but uses Registers instead of TRealModeRegs }
function DpmiIntr (IntNo: Byte; var Regs: Registers): Boolean;
{ Corresponds to procedure MsDos but uses Registers instead of TRealModeRegs }
function DpmiMsDos (var Regs: Registers): Boolean;
{ Corresponds to procedure GetMem; allocates memory in the first }
{ megabyte, accessible in both protected - through P - and real }
{ mode - through Segment:0000ドル }
function DpmiGetMem (var P: Pointer; var Segment: Word;
 var Size: Longint): Boolean;
{ Corresponds to procedure FreeMem; you must use it to deallocate }
{ memory allocated with DpmiGetMem }
function DpmiFreeMem (var P: Pointer): Boolean;
{ IncSelector returns the value to add to the first selector, and to }
{ the next ones, to access the descriptor array allocated by DpmiGetMem }
{ when blocks greater than 64 K are requested }
procedure IncSelector (var Selector: Word);
{ AllocSelectors allocates one or more selectors using Dpmi function }
{ 0000H. The return value is the base selector of the allocated block }
{ of selectors, or zero if the function is unsuccessful }
function AllocSelectors (Count: Word): Word;
{ FreeSelector frees a selector using Dpmi function 0001H. }
function FreeSelector (Selector: Word): Boolean;
{ SegmentToSelector maps a real mode segment onto a selector using Dpmi }
{ function 0002H. The return value is a selector, or zero if the function }
{ is unsuccessful. Selectors allocated with this function are permanent }
{ and can never be freed. If you need a temporary selector or pointer, use }
{ the AllocRealSelector or AllocRealPtr functions instead }
function SegmentToSelector (Segment: Word): Word;
{ SelectorToSegment returns the real mode segment address (paragraph) that }
{ corresponds to the base address of the given selector. The selector is }
{ assumed to be a valid selector that references real mode memory. If this }
{ is not the case, the return value is undefined }
function SelectorToSegment (Selector: Word): Word;
{ GetSelectorBase returns the 32-bit linear base address of a selector }
{ using Dpmi function 0006H. The return value is zero if the function }
{ is unsuccessful }
function GetSelectorBase (Selector: Word): LongInt;
{ SetSelectorBase sets the 32-bit linear base address of a selector }
{ using Dpmi function 0007H }
function SetSelectorBase (Selector: Word; Base: LongInt): Boolean;
{ GetSelectorLimit returns the limit of the specified selector. The }
{ return value is zero if the selector is invalid }
function GetSelectorLimit (Selector: Word): LongInt;
{ SetSelectorLimit sets the limit of a selector using Dpmi function 0008H }
function SetSelectorLimit (Selector: Word; Limit: LongInt): Boolean;
{ GetAccessRights returns the access rights for a selector. The return }
{ value is zero if the selector is invalid }
function GetAccessRights (Selector: Word): Word;
{ SetAccessRights sets the access rights for a selector using Dpmi }
{ function 0009H }
function SetAccessRights (Selector: Word; AccessRights: Word): Boolean;
{ AllocSelectorAlias creates an aliased selector using Dpmi function }
{ 000AH. The return value is a selector, or zero if the function is }
{ unsuccessful }
function AllocSelectorAlias (Selector: Word): Word;
{ GetDescriptor copies the LDT entry for the given selector into the }
{ given descriptor record using Dpmi function 000BH }
function GetDescriptor (Selector: Word; var Descriptor: TDescriptor): Boolean;
{ SetDescriptor copies the given descriptor record into the LDT entry }
{ for the given selector using Dpmi function 000CH }
function SetDescriptor (Selector: Word; var Descriptor: TDescriptor): Boolean;
{ AllocSpecificSelector allocates a specific selector using Dpmi function }
{ 000DH. The return value is True if the selector was allocated. Otherwise }
{ the return value is False }
function AllocSpecificSelector (Selector: Word): Boolean;
{ GetRealModeInt returns the contents of the given real mode interrupt }
{ vector using Dpmi function 0200H }
function GetRealModeInt (Int: Byte): Pointer;
{ SetRealModeInt sets the interrupt vector for the specified real mode }
{ interrupt using Dpmi function 0201H }
function SetRealModeInt (Int: Byte; Vector: Pointer): Boolean;
{ GetException returns the contents of the given exception vector using }
{ Dpmi function 0202H }
function GetException (Exception: Byte): Pointer;
{ SetException sets the exception vector for the specified exception }
{ using Dpmi function 0203H }
function SetException (Exception: Byte; Vector: Pointer): Boolean;
{ GetProtModeInt returns the contents of the given protected mode }
{ interrupt vector using Dpmi function 0204H }
function GetProtModeInt (Int: Byte): Pointer;
{ SetProtModeInt sets the interrupt vector for the specified protected }
{ mode interrupt using Dpmi function 0205H }
function SetProtModeInt (Int: Byte; Vector: Pointer): Boolean;
{ RealModeInt simulates a software interrupt instruction in real mode }
{ using Dpmi function 0300H }
function RealModeInt (Int: Byte; var Regs: TRealModeRegs): Boolean;
{ RealModeCall calls a real mode procedure with a far return frame using }
{ Dpmi function 0301H }
function RealModeCall (Proc: Pointer; var Regs: TRealModeRegs): Boolean;
{ RealModeIntCall calls a real mode procedure with an interrupt return }
{ frame using Dpmi function 0302H }
function RealModeIntCall (Proc: Pointer; var Regs: TRealModeRegs): Boolean;
{ AllocCallback allocates a real mode callback using Dpmi function 0303H. }
{ The return value is the real mode address of the callback, or zero if }
{ the function is unsuccessful }
function AllocCallback (Proc: Pointer; var Regs: TRealModeRegs): Pointer;
{ FreeCallback frees a real mode callback using DPMI function 0304H }
function FreeCallback (Callback: Pointer): Boolean;
{ GetVersionInfo returns Dpmi version information in the specified version }
{ information record using Dpmi function 0400H }
procedure GetVersionInfo (var Info: TVersionInfo);
{ SetInterruptState sets the virtual interrupt state to the specified }
{ value and returns the previous virtual interrupt state, corresponding }
{ to Dpmi functions 0900H and 0901H }
function SetInterruptState (Enable: Boolean): Boolean;
{ GetInterruptState returns the current virtual interrupt state using }
{ Dpmi function 0902H }
function GetInterruptState: Boolean;
{ AllocRealSelector allocates a new selector and maps it onto the given }
{ real mode segment address. The return value is a selector, or zero if }
{ the function is unsuccessful. This function corresponds to Dpmi function }
{ 0002H, except that the resulting selector can be freed (using Dpmi }
{ function 0001H) if required }
function AllocRealSelector (Segment: Word): Word;
{ AllocRealPtr corresponds to AllocRealSelector, except that it works on }
{ pointers instead of segments and selectors. The return value is a }
{ protected mode pointer that points to the same physical memory location }
{ as the specified real mode pointer. If the function is unsuccessful the }
{ return value is NIL }
function AllocRealPtr (RealAddr: Pointer): Pointer;
{ FreeRealPtr frees the selector used in a pointer that was allocated by }
{ AllocRealPtr }
function FreeRealPtr (RealPtr: Pointer): Boolean;
{ MemInitSwapFile opens a swapfile of size FileSize. If file exists and }
{ new size is larger, this function will grow the swap file, otherwise }
{ the call has no effect. File size is limited to 2 gigabytes. }
{ }
{ }
{ Returns: }
{ rtmOK - Successful }
{ rtmNoMemory - Not enough disk space }
{ rtmFileIOError - Could not open/grow file }
function MemInitSwapFile (FileName: PChar; FileSize: LongInt): Integer;
{ MemCloseSwapFile closes the swapfile if it was created by the current }
{ task. If Delete is non 0, the swap file is deleted. }
{ }
{ }
{ Returns: }
{ rtmOK - Successful }
{ rtmNoMemory - Not enough physical memory to run without }
{ swap file }
{ rtmFileIOError - Could not close/delete the file }
function MemCloseSwapFile (Delete: Integer): Integer;
implementation
var
 VersionInfo : TVersionInfo;
 Regs : Registers;
 RealModeRegs: TRealModeRegs;
 DPMIBits : Integer;
 SelIncr : Integer;
function DpmiIntr (IntNo: Byte; var Regs: Registers): Boolean;
var
 Err: Integer;
begin
 FillChar (RealModeRegs,SizeOf (TRealModeRegs),0);
 RealModeRegs.AX := Regs.AX;
 RealModeRegs.BX := Regs.BX;
 RealModeRegs.CX := Regs.CX;
 RealModeRegs.DX := Regs.DX;
 RealModeRegs.DI := Regs.DI;
 RealModeRegs.SI := Regs.SI;
 RealModeRegs.BP := Regs.BP;
 RealModeRegs.DS := Regs.DS;
 RealModeRegs.ES := Regs.ES;
 asm
 MOV AX,SEG RealModeRegs
 MOV ES,AX
 CMP DPMIBits,16
 JE @@1
 DB 66H
 MOV DI,OFFSET RealModeRegs
 DW 0000H
 JMP @@2
 @@1: MOV DI,OFFSET RealModeRegs
 @@2: MOV BL,IntNo
 XOR BH,BH
 XOR CX,CX
 MOV AX,0300H
 INT 31H
 XOR AX,AX
 JNC @@3
 MOV AX,-31
 @@3: MOV Err,AX
 end;
 if Err = 0 then
 begin
 Regs.AX := RealModeRegs.AX;
 Regs.BX := RealModeRegs.BX;
 Regs.CX := RealModeRegs.CX;
 Regs.DX := RealModeRegs.DX;
 Regs.DI := RealModeRegs.DI;
 Regs.SI := RealModeRegs.SI;
 Regs.BP := RealModeRegs.BP;
 Regs.DS := RealModeRegs.DS;
 Regs.ES := RealModeRegs.ES;
 Regs.Flags := RealModeRegs.Flags
 end;
 DpmiIntr := Err = 0
end;
function DpmiMsDos (var Regs: Registers): Boolean;
begin
 DpmiMsDos := DpmiIntr (21,ドルRegs)
end;
function DpmiGetMem (var P: Pointer; var Segment: Word;
 var Size: Longint): Boolean;
begin
 Regs.AX := 0100ドル;
 Regs.BX := (Size + 15) div 16;
 if Regs.BX = 0 then Regs.BX := $FFFF; { Size> 000ドルFFFF0 }
 Size := Regs.BX; { calculates memory }
 Size := Size * 16; { effectively allocated }
 Intr (31,ドルRegs);
 DpmiGetMem := Regs.Flags and fCarry = 0;
 if Regs.Flags and fCarry = 0 then
 begin
 P := Ptr (Regs.DX,0); { selector:offset pointer }
 Segment := Regs.AX { segment for real mode }
 end
 else begin
 Size := Regs.BX; { size of the largest }
 Size := Size * 16 { available block }
 end
end;
function DpmiFreeMem (var P: Pointer): Boolean;
begin
 Regs.AX := 0101ドル;
 Regs.DX := Seg (P^);
 Intr (31,ドルRegs);
 P := NIL;
 DpmiFreeMem := Regs.Flags and fCarry = 0
end;
procedure IncSelector (var Selector: Word);
begin
 Inc (Selector,SelIncr)
end;
function AllocSelectors (Count: Word): Word; assembler;
asm
 MOV CX,Count
 MOV AX,0000H
 INT 31H
 JNC @@1
 XOR AX,AX
@@1:
end;
function FreeSelector (Selector: Word): Boolean; assembler;
asm
 MOV BX,Selector
 MOV AX,0001H
 INT 31H
 SBB AX, AX
 INC AX
end;
function SegmentToSelector (Segment: Word): Word; assembler;
asm
 MOV BX,Segment
 MOV AX,0002H
 INT 31H
 JNC @@1
 XOR AX,AX
@@1:
end;
function SelectorToSegment (Selector: Word): Word; assembler;
asm
 MOV BX,Selector
 MOV AX,0006H
 INT 31H
 MOV AX,DX
 OR AX,CX
 ROR AX,4
end;
function GetSelectorBase (Selector: Word): LongInt; assembler;
asm
 MOV BX,Selector
 MOV AX,0006H
 INT 31H
 JNC @@1
 XCHG AX,CX
 XCHG AX,DX
 JNC @@1
 XOR AX,AX
 CWD
@@1:
end;
function SetSelectorBase (Selector: Word; Base: LongInt): Boolean; assembler;
asm
 MOV BX,Selector
 MOV DX,Base.Word[0]
 MOV CX,Base.Word[2]
 MOV AX,0007H
 INT 31H
 SBB AX,AX
 INC AX
end;
function GetSelectorLimit (Selector: Word): LongInt; assembler;
asm
 XOR AX,AX
 LSL AX,Selector
 XOR DX,DX
end;
function SetSelectorLimit (Selector: Word; Limit: LongInt): Boolean; assembler;
asm
 MOV BX,Selector
 MOV DX,Limit.Word[0]
 MOV CX,Limit.Word[2]
 MOV AX,0008H
 INT 31H
 SBB AX,AX
 INC AX
end;
function GetAccessRights (Selector: Word): Word; assembler;
asm
 XOR AX,AX
 LAR AX,Selector
 XCHG AL,AH
end;
function SetAccessRights (Selector: Word; AccessRights: Word): Boolean;
 assembler;
asm
 MOV BX,Selector
 MOV CX,AccessRights
 MOV AX,0009H
 INT 31H
 SBB AX,AX
 INC AX
end;
function AllocSelectorAlias (Selector: Word): Word; assembler;
asm
 MOV BX,Selector
 MOV AX,000AH
 INT 31H
 JNC @@1
 XOR AX,AX
@@1:
end;
function GetDescriptor (Selector: Word; var Descriptor: TDescriptor): Boolean;
 assembler;
asm
 MOV BX,Selector
 LES DI,Descriptor
 MOV AX,000BH
 INT 31H
 SBB AX,AX
 INC AX
end;
function SetDescriptor (Selector: Word; var Descriptor: TDescriptor): Boolean;
 assembler;
asm
 MOV BX,Selector
 LES DI,Descriptor
 MOV AX,000CH
 INT 31H
 SBB AX,AX
 INC AX
end;
function AllocSpecificSelector (Selector: Word): Boolean; assembler;
asm
 MOV BX,Selector
 MOV AX,000DH
 INT 31H
 SBB AX,AX
 INC AX
end;
function GetRealModeInt (Int: Byte): Pointer; assembler;
asm
 MOV BL,Int
 MOV AX,0200H
 INT 31H
 XCHG AX,CX
 XCHG AX,DX
 JNC @@1
 XOR AX,AX
 CWD
@@1:
end;
function SetRealModeInt (Int: Byte; Vector: Pointer): Boolean; assembler;
asm
 MOV BL,Int
 MOV DX,Vector.Word[0]
 MOV CX,Vector.Word[2]
 MOV AX,0201H
 INT 31H
 SBB AX,AX
 INC AX
end;
function GetException (Exception: Byte): Pointer; assembler;
asm
 MOV BL,Exception
 MOV AX,0202H
 INT 31H
 XCHG AX,CX
 XCHG AX,DX
 JNC @@1
 XOR AX,AX
 CWD
@@1:
end;
function SetException (Exception: Byte; Vector: Pointer): Boolean; assembler;
asm
 MOV BL,Exception
 MOV DX,Vector.Word[0]
 MOV CX,Vector.Word[2]
 MOV AX,0203H
 INT 31H
 SBB AX,AX
 INC AX
end;
function GetProtModeInt (Int: Byte): Pointer; assembler;
asm
 MOV BL,Int
 MOV AX,0204H
 INT 31H
 MOV AX,DX
 MOV DX,CX
end;
function SetProtModeInt (Int: Byte; Vector: Pointer): Boolean; assembler;
asm
 MOV BL,Int
 MOV DX,Vector.Word[0]
 MOV CX,Vector.Word[2]
 MOV AX,0205H
 INT 31H
 SBB AX,AX
 INC AX
end;
function RealModeInt (Int: Byte; var Regs: TRealModeRegs): Boolean; assembler;
asm
 MOV BL,Int
 XOR BH,BH
 XOR CX,CX
 LES DI,Regs
 MOV AX,0300H
 INT 31H
 SBB AX,AX
 INC AX
end;
function RealModeCall (Proc: Pointer; var Regs: TRealModeRegs): Boolean;
 assembler;
asm
 XOR BH,BH
 XOR CX,CX
 LES DI,Regs
 MOV AX,Proc.Word[0]
 MOV ES:[DI].TRealModeRegs.&IP,AX
 MOV AX,Proc.Word[2]
 MOV ES:[DI].TRealModeRegs.&CS,AX
 MOV AX,0301H
 INT 31H
 SBB AX,AX
 INC AX
end;
function RealModeIntCall (Proc: Pointer; var Regs: TRealModeRegs): Boolean;
 assembler;
asm
 XOR BH,BH
 XOR CX,CX
 LES DI,Regs
 MOV AX,Proc.Word[0]
 MOV ES:[DI].TRealModeRegs.&IP,AX
 MOV AX,Proc.Word[2]
 MOV ES:[DI].TRealModeRegs.&CS,AX
 MOV AX,0302H
 INT 31H
 SBB AX,AX
 INC AX
end;
function AllocCallback (Proc: Pointer; var Regs: TRealModeRegs): Pointer;
 assembler;
asm
 PUSH DS
 LDS SI,Proc
 LES DI,Regs
 MOV AX,0303H
 INT 31H
 POP DS
 XCHG AX,CX
 XCHG AX,DX
 JNC @@1
 XOR AX,AX
 CWD
@@1:
end;
function FreeCallback (Callback: Pointer): Boolean; assembler;
asm
 MOV DX,Callback.Word[0]
 MOV CX,Callback.Word[2]
 MOV AX,0304H
 INT 31H
 SBB AX,AX
 INC AX
end;
procedure GetVersionInfo (var Info: TVersionInfo); assembler;
asm
 MOV AX,0400H
 INT 31H
 LES DI,Info
 CLD
 STOSW
 XCHG AX,BX
 STOSW
 XCHG AX,CX
 STOSW
 XCHG AX,DX
 STOSW
end;
function SetInterruptState (Enable: Boolean): Boolean; assembler;
asm
 MOV AL,Enable
 MOV AH,09H
 INT 31H
end;
function GetInterruptState: Boolean; assembler;
asm
 MOV AX,0902H
 INT 31H
end;
function AllocRealSelector (Segment: Word): Word; assembler;
asm
 XOR BX,BX
 MOV AX,0000H
 MOV CX,1
 INT 31H
 JC @@1
 MOV BX,AX
 MOV DX,Segment
 ROL DX,4
 MOV CX,DX
 AND DL,0F0H
 AND CX,0FH
 MOV AX,0007H
 INT 31H
 MOV DX,0FFFFH
 XOR CX,CX
 MOV AX,0008H
 INT 31H
@@1: MOV AX,BX
end;
function AllocRealPtr (RealAddr: Pointer): Pointer; assembler;
asm
 PUSH RealAddr.Word[2]
 CALL AllocRealSelector
 MOV DX,AX
 OR AX,AX
 JE @@1
 MOV AX,RealAddr.Word[0]
@@1:
end;
function FreeRealPtr (RealPtr: Pointer): Boolean; assembler;
asm
 PUSH RealPtr.Word[2]
 CALL FreeSelector
end;
function MemInitSwapFile; external 'RTM' index 35;
function MemCloseSwapFile; external 'RTM' index 36;
begin
 GetVersionInfo (VersionInfo); { info on Dpmi services }
 if VersionInfo.Flags and 1  0 then { 16 or 32 bit implementation }
 DPMIBits := 32
 else DPMIBits := 16;
 Regs.AX := 0003ドル; { calculates the value to add to a }
 Intr (31,ドルRegs); { selector if memory allocation is }
 SelIncr := Regs.AX { greater than 64 K }
end.
*)
{ ---------------------------- }
{ Test program for Drives unit }
{ ---------------------------- }
(*
program Test;
uses
 Dos,
 Drives;
var
 AllDrives: DriveSet;
 D : DriveLetters;
 DriveType: LongInt;
 S : String;
function GetVolumeLabel (Drive: Char): String;
var
 SR: SearchRec;
begin
 GetVolumeLabel := '';
 FindFirst (Drive + ':\*.*',VolumeID,SR);
 if DosError = 0 then GetVolumeLabel := SR.Name
end;
begin
 GetDrives (AllDrives);
 for D := 'A' to 'Z' do
 begin
 if NOT (D in AllDrives) then Continue;
 DriveType := GetDriveType (D);
 if DriveType = dtInvalid then Continue;
 if DriveType and dtUnknown = dtUnknown then
 begin
 S := 'unknown drive';
 if DriveType and dtRemote = dtRemote then
 S := 'remote ' + S
 else S := 'local ' + S
 end
 else if DriveType and dtAnyFloppy  0 then
 begin
 S := ' floppy disk';
 case DriveType and dtAnyFloppy of
 dt8Single: S := '8" single density' + S;
 dt8Double: S := '8" double density' + S;
 dt360 : S := '320/360 KB' + S;
 dt720 : S := '720 KB' + S;
 dt1200 : S := '1.2 MB' + S;
 dt1440 : S := '1.44 MB' + S;
 dt2880 : S := '2.88 MB' + S
 end
 end
 else if DriveType and dtTape = dtTape then
 begin
 S := ' tape drive';
 if DriveType and dtRemote = dtRemote then
 S := 'remote' + S
 else S := 'local' + S
 end
 else if DriveType and dtFloptical = dtFloptical then
 begin
 S := ' floptical drive';
 if DriveType and dtRemote = dtRemote then
 S := 'remote' + S
 else S := 'local' + S
 end
 else if DriveType and dtCDRom = dtCDRom then
 begin
 S := ' CD-ROM drive';
 if DriveType and dtRemote = dtRemote then
 S := 'remote' + S
 else S := 'local' + S
 end
 else if DriveType and dtIomegaZip = dtIomegaZip then
 begin
 S := ' Iomega Zip drive';
 if DriveType and dtRemote = dtRemote then
 S := 'remote' + S
 else S := 'local' + S
 end
 else begin
 if DriveType and dtRemovable = dtRemovable then
 begin
 S := ' removable media';
 if DriveType and dtRemote = dtRemote then
 S := 'remote' + S
 else S := 'local' + S
 end
 else begin
 S := 'volume ' + GetVolumeLabel (D) + ' (';
 if DriveType and dtRemote = dtRemote then
 S := S + 'remote '
 else S := S + 'local ';
 if DriveType and dtRamDisk = dtRamDisk then
 begin
 S := S + 'ram';
 if Pos ('.',S)> 0 then Delete (S,Pos ('.',S),1)
 end
 else S := S + 'hard';
 S := S + ' disk)'
 end
 end;
 S := D + ': ' + S;
 WriteLn (S)
 end
end.
*)


AltStyle によって変換されたページ (->オリジナル) /