home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 November / Chip_2002-11_cd1.bin / zkuste / delphi / unity / d56 / DW / DW10242.ZIP / DriveWorks.pas < prev    next >
Pascal/Delphi Source File  |  2002-07-08  |  21KB  |  735 lines

  1. (*----------------------------- DriveWorks.pas -------------------------
  2.  V1.0.236 - 08.07.2002 current release
  3. ------------------------------------------------------------------------*)
  4. unit DriveWorks;
  5.  
  6. interface
  7.  
  8. uses Classes, Windows, SysUtils, MMSystem, NumWorks, StringWorks, ShellApi;
  9.  
  10. type
  11.   TDWDriveShellInfo = packed record
  12.      Icon : hIcon;
  13.      Image : integer;
  14.      DisplayName,
  15.      TypeName : string
  16.   end;
  17.   TDWEjectRemovableResult = (dwejeUnsupported,
  18.                              dwejeVolumeLocked,
  19.                              dwejeUnremovable,
  20.                              dwejeRequestFailed,
  21.                              dwejeAllReady);
  22.  
  23.   TDiocRegisters = record
  24.     EBX, EDX, ECX, EAX, EDI, ESI, Flags: DWORD;
  25.   end;
  26.  
  27.   TVWin32CtlCode = (ccNone, ccVWin32IntIoctl, ccVWin32Int26,
  28.     ccVWin32Int25, ccVWin32Int13);
  29.  
  30.   TBiosParamBlock = packed record
  31.     BytesPerSector: Word;
  32.     SectorsPerCluster: Byte;
  33.     ReservedSectors: Word;
  34.     NumFats: Byte;
  35.     NumRootEntries: Word;
  36.     NumSectors: Word;
  37.     MediaID: Byte;
  38.     SectorsPerFat: Word;
  39.     SectorsPerTrack: Word;
  40.     NumHeads: Word;
  41.     HiddenSectors: Word;
  42.     Dummy1: Word;
  43.     TotalSectors: LongInt;
  44.     Dummy2: array[0..5] of Byte;
  45.   end;
  46.  
  47.   TDeviceParamBlock = packed record
  48.     Special: Byte;
  49.     DeviceType: Byte;
  50.     DeviceAttr: Word;
  51.     NumCylinders: Word;
  52.     MediaType: Byte;
  53.     BiosParamBlock: TBiosParamBlock;
  54.   end;
  55.  
  56.   TFormatParamBlock = packed record
  57.     Reserved: Byte;
  58.     Head: Word;
  59.     Cylinder: Word;
  60.   end;
  61.  
  62.   TDriveInformation = record
  63.      VolumeName  : string;
  64.      VolumeSerialNumber,
  65.      MaximumComponentLength,
  66.      FileSystemFlags : DWord;
  67.      FileSystemName : string;
  68.   end;
  69.  
  70.   TDiskGeometry = record
  71.      Cylinders: Integer;
  72.      MediaType: Integer;
  73.      TracksPerCylinder: DWord;
  74.      SectorsPerTrack: DWord;
  75.      BytesPerSector: DWord;
  76.   end;
  77.  
  78. (*V1.0.236*)
  79. function GetDriveShellInfo(const Drive: Char): TDWDriveShellInfo;
  80. function EjectRemovable(const Drive: Char): TDWEjectRemovableResult;
  81.  
  82. function ApplicationHostDrive: Char;
  83. function AvailableDrives: TStringList;
  84. function CloseCD(Drive: Char): Boolean;
  85. function DrivesCount: Integer;
  86. function DiskInDrive(Drive: Char): Boolean;
  87. function DiskWriteProtected(Drive:  Char):  Boolean;
  88. function DriveSectorsPerCluster(Drive: Char): Integer;
  89. function DriveBytesPerSector(Drive: Char): Integer;
  90. function DriveBytesPerCluster(Drive: Char): Integer;
  91. function DriveFreeClusters(Drive: Char): Integer;
  92. function DriveTotalClusters(Drive: Char): Integer;
  93. function DriveFreeSpace(Drive: Char): Int64;
  94. function DriveTotalSpace(Drive: Char): Int64;
  95. function DriveSerialNumber(Drive: Char): String;
  96. function DriveSerialNumberInt(Drive: Char): Integer;
  97. function DriveVolumeName(Drive: Char): String;
  98. function DriveMaxFilenameLength(Drive: Char): Integer;
  99. function DriveCasePreserved(Drive: Char): Boolean;
  100. function DriveSectorsPerTrack(Drive: Char): Integer;
  101. function DriveReservedSectors(Drive: Char): Integer;
  102. function DriveTracksCount(Drive: Char): Integer;
  103. function DriveHeadCount(Drive: Char): Integer;
  104. function DriveFATCount(Drive: Char): Integer;
  105. function DriveRootEntries(Drive: Char): Integer;
  106. function DriveHiddenSectors(Drive: Char): Integer;
  107. function DriveCylinders(Drive: Char): Integer;
  108. function DriveSectorsPerFAT(Drive: Char): Integer;
  109. function DriveFilesystemName(Drive: Char): String;
  110. function HardDrives: TStringList;
  111. function HardDrivesLong: TStringList;
  112. function OpenCD(Drive: Char): Boolean;
  113. function SystemHostDrive: Char;
  114.  
  115. function ValidDriveLetter(Drive: Char): Boolean;
  116. function ValidateDriveLetter(Drive: Char): Char;
  117. function DriveLetterToIndex(Drive: Char): Byte;
  118. function DriveIndexToLetter(Drive: Byte): Char;
  119. function GetVolumeInformationX (Drive: Char; var V : TDriveInformation): Boolean;
  120. function VWin32(CtlCode: TVWin32CtlCode; var Regs: TDiocRegisters): Boolean;
  121. function GetDeviceParamBlock(Drive: Char; var ParamBlock: TDeviceParamBlock): Word;
  122. function SetDeviceParamBlock(Drive: Char; var ParamBlock: TDeviceParamBlock): Word;
  123. function FloppyReady(const Drive: char): Boolean;
  124.  
  125. function CompareDiskStruct(Drive: Char; var BPC, SPC, BPS, FC, TC: Integer; var FS, TS, DSN: Int64): Boolean;
  126.  
  127. var bbb:TDeviceParamBlock;
  128.  
  129. implementation
  130.  
  131. function GetDriveShellInfo(const Drive: Char): TDWDriveShellInfo;
  132. var
  133.   SHFileInfo : TSHFileInfo;
  134. begin
  135.   ShGetFileInfo (PChar(Drive + ':\'),
  136.                  0,
  137.                  SHFileInfo,
  138.                  SizeOf (TSHFileInfo),
  139.                  SHGFI_TYPENAME or
  140.                     SHGFI_DISPLAYNAME or
  141.                     SHGFI_SYSICONINDEX or
  142.                     SHGFI_ICON);
  143.   with result do
  144.   begin
  145.     Icon  := SHFileInfo.hIcon;
  146.     Image := SHFileInfo.iIcon;
  147.     DisplayName := SHFileInfo.szDisplayName;
  148.     TypeName := SHFileInfo.szTypeName
  149.   end
  150. end;
  151.  
  152. function EjectRemovable(const Drive: Char): TDWEjectRemovableResult;
  153. var
  154.   hDevice : THandle;
  155.   Nb : DWORD;
  156.   Reg : TDiocRegisters;
  157.   VersionInfo : TOSVersionInfo;
  158. const
  159.   VWIN32_DIOC_DOS_IOCTL = 1;
  160.   IOCTL_STORAGE_EJECT_MEDIA = 2967560;
  161. begin
  162.   result:= dwejeUnsupported;
  163.   VersionInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
  164.   GetVersionEx(VersionInfo);
  165.   if VersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
  166.     hDevice := CreateFile(PChar('\\.\' + Drive + ':'), GENERIC_READ,
  167.                           FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0)
  168.   else
  169.     hDevice := CreateFile('\\.\VWIN32', 0, 0, nil, 0,
  170.                           FILE_FLAG_DELETE_ON_CLOSE, 0);
  171.   if hDevice = INVALID_HANDLE_VALUE then
  172.     RaiseLastWin32Error;
  173.   if VersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then begin
  174.     if not DeviceIoControl(hDevice, IOCTL_STORAGE_EJECT_MEDIA,
  175.                     nil, 0, nil, 0, Nb, nil) then
  176.       RaiseLastWin32Error;
  177.   end else begin
  178.     with Reg do begin
  179.       EAX := $440D;
  180.       EBX := Byte(Drive) - $40;
  181.       ECX := $0849;
  182.     end;
  183.     DeviceIoControl(hDevice, VWIN32_DIOC_DOS_IOCTL,
  184.                     @Reg, SizeOf(Reg), @Reg, SizeOf(Reg), Nb, nil);
  185.     if Reg.Flags and 1 = 1 then case Reg.EAX of
  186.       $01: result:= dwejeUnsupported;
  187.       $B1: result:= dwejeVolumeLocked;
  188.       $B2: result:= dwejeUnremovable;
  189.       $B5: result:= dwejeRequestFailed;
  190.     end else result:= dwejeAllReady;
  191.   end;
  192.   CloseHandle(hDevice);
  193. end;
  194.  
  195. function ApplicationHostDrive: Char;
  196. begin
  197.    result:= ParamStr(0)[1];
  198. end;
  199.  
  200. function AvailableDrives: TStringList;
  201. var
  202.   i: Integer;
  203.   C: String;
  204.   DType: Integer;
  205.   DriveString: String;
  206. begin
  207.   result:= TStringList.Create;
  208.   (* Zeichen 65 = A und 90 = Z -- Schleife durch alle m÷glichen Laufwerke *)
  209.   for i := 65 to 90 do
  210.   begin
  211.     (* Aktuellen Schleifenindex in entsprechenden Laufwerksbezeichner wandeln *)
  212.     C := chr(i)+':\';
  213.  
  214.     (* Die Funktion GetDriveType() ermittelt den Medientyp des Laufwerks *)
  215.     DType := GetDriveType(PChar(C));
  216.  
  217.     (* Ermittelten Medientyp auswerten und entsprechende Meldung generieren *)
  218.     case DType of
  219.       0: DriveString:= C+' Unbekannter Laufwerkstyp';
  220.       1: DriveString:= C+' Kein Stammverzeichnis gefunden';
  221.       DRIVE_REMOVABLE: DriveString:= C+' WechseldatentrΣger';
  222.       DRIVE_FIXED: DriveString:= C+' Festplatte';
  223.       DRIVE_REMOTE: DriveString:= C+' Netzwerklaufwerk';
  224.       DRIVE_CDROM: DriveString := C+' CD-ROM Laufwerk';
  225.       DRIVE_RAMDISK: DriveString := C+' RAM Disk';
  226.     end;
  227.     (* Gⁿltige Laufwerksbezeichner in Liste aufnehmen *)
  228.     if not ((DType = 0) or (DType = 1)) then result.Add(DriveString);
  229.   end;
  230. end;
  231.  
  232. function CloseCD(Drive: Char): Boolean;
  233. var
  234.   Res: MciError;
  235.   OpenParm: TMCI_Open_Parms;
  236.   Flags: DWORD;
  237.   S: string;
  238.   DeviceID: Word;
  239. begin
  240.   Result := False;
  241.   S      := Drive + ':';
  242.   Flags  := mci_Open_Type or mci_Open_Element;
  243.   with OpenParm do 
  244.   begin
  245.     dwCallback       := 0;
  246.     lpstrDeviceType  := 'CDAudio';
  247.     lpstrElementName := PChar(S);
  248.   end;
  249.   Res := mciSendCommand(0, mci_Open, Flags, Longint(@OpenParm));
  250.   if Res = 0 then Exit;
  251.   DeviceID := OpenParm.wDeviceID;
  252.   try
  253.     Res := mciSendCommand(DeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, 0);
  254.     if Res = 0 then Exit;
  255.     Result := True;
  256.   finally
  257.     mciSendCommand(DeviceID, mci_Close, Flags, Longint(@OpenParm));
  258.   end;
  259. end;
  260.  
  261. function DrivesCount: Integer;
  262. var
  263.    TempList: TStringList;
  264. begin
  265.    TempList:= AvailableDrives;
  266.    result:= TempList.Count;
  267.    TempList.Free;
  268. end;
  269.  
  270. function DiskInDrive(Drive: Char): Boolean;
  271. var
  272.    DriveNumber:  Byte;
  273.    ErrorMode  : Word;
  274. begin
  275.   result := FALSE;
  276.   DriveNumber := ORD( UpCase(Drive) );
  277.   ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
  278.   try
  279.     if DiskSize(DriveNumber-ORD('A')+1) <> -1 then result:= TRUE;
  280.   finally
  281.     SetErrorMode(ErrorMode)
  282.   end;
  283. end;
  284.  
  285. function DiskWriteProtected(Drive:  Char):  Boolean;
  286. var
  287.    ErrorMode:  Word;
  288.    PathName :  String;
  289.    TempName :  String;
  290. begin
  291.   ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
  292.   try
  293.     Assert(Upcase(drive) in ['A'..'Z'], 'Invalid drive specification');
  294.     PathName := drive + ':\';
  295.     SetLength(TempName, MAX_PATH+1);
  296.     GetTempFileName(PChar(PathName), 'RWRO', 0, PChar(TempName));
  297.     result := (GetLastError = Windows.ERROR_WRITE_PROTECT);
  298.     if not result then result := not DeleteFile(TempName);
  299.   finally
  300.     SetErrorMode(ErrorMode)
  301.   end;
  302. end;
  303.  
  304. function DriveSectorsPerCluster(Drive: Char): Integer;
  305. var
  306.    RootPath: String;
  307.    SectorsPerCluster,
  308.    BytesPerSector,
  309.    NumFreeClusters,
  310.    TotalClusters: DWord;
  311. begin
  312.    Drive:= ValidateDriveLetter(Drive);
  313.    RootPath:= Drive + ':\';
  314.    if GetDiskFreeSpace(PChar(RootPath), SectorsPerCluster,
  315.       BytesPerSector, NumFreeClusters, TotalClusters) then
  316.       result:= SectorsPerCluster else result:= -1;
  317. end;
  318.  
  319. function DriveBytesPerSector(Drive: Char): Integer;
  320. var
  321.    RootPath: String;
  322.    SectorsPerCluster,
  323.    BytesPerSector,
  324.    NumFreeClusters,
  325.    TotalClusters: DWord;
  326. begin
  327.    Drive:= ValidateDriveLetter(Drive);
  328.    RootPath:= Drive + ':\';
  329.    if GetDiskFreeSpace(PChar(RootPath), SectorsPerCluster,
  330.       BytesPerSector, NumFreeClusters, TotalClusters) then
  331.       result:= BytesPerSector else result:= -1;
  332. end;
  333.  
  334. function DriveBytesPerCluster(Drive: Char): Integer;
  335. begin
  336.    result:= DriveBytesPerSector(Drive) * DriveSectorsPerCluster(Drive);
  337. end;
  338.  
  339. function DriveFreeClusters(Drive: Char): Integer;
  340. var
  341.    RootPath: String;
  342.    SectorsPerCluster,
  343.    BytesPerSector,
  344.    NumFreeClusters,
  345.    TotalClusters: DWord;
  346. begin
  347.    Drive:= ValidateDriveLetter(Drive);
  348.    RootPath:= Drive + ':\';
  349.    if GetDiskFreeSpace(PChar(RootPath), SectorsPerCluster,
  350.       BytesPerSector, NumFreeClusters, TotalClusters) then
  351.       result:= NumFreeClusters else result:= -1;
  352. end;
  353.  
  354. function DriveTotalClusters(Drive: Char): Integer;
  355. var
  356.    RootPath: String;
  357.    SectorsPerCluster,
  358.    BytesPerSector,
  359.    NumFreeClusters,
  360.    TotalClusters: DWord;
  361. begin
  362.    Drive:= ValidateDriveLetter(Drive);
  363.    RootPath:= Drive + ':\';
  364.    if GetDiskFreeSpace(PChar(RootPath), SectorsPerCluster,
  365.       BytesPerSector, NumFreeClusters, TotalClusters) then
  366.       result:= TotalClusters else result:= -1;
  367. end;
  368.  
  369. function DriveFreeSpace(Drive: Char): Int64;
  370. begin
  371.    result:= DiskFree(DriveLetterToIndex(Drive));
  372. end;
  373.  
  374. function DriveTotalSpace(Drive: Char): Int64;
  375. begin
  376.    result:= DiskSize(DriveLetterToIndex(Drive));
  377. end;
  378.  
  379. function DriveSerialNumber(Drive: Char): String;
  380. var
  381.    DI: TDriveInformation;
  382.    TempStr: String;
  383. begin
  384.    Drive:= ValidateDriveLetter(Drive);
  385.    GetVolumeInformationX(Drive, DI);
  386.    TempStr:= IntToHex(DI.VolumeSerialNumber, 8);
  387.    result:= Copy(TempStr, 1, 4) + '-' + Copy(TempStr, 5, 4);
  388. end;
  389.  
  390. function DriveSerialNumberInt(Drive: Char): Integer;
  391. var
  392.    DI: TDriveInformation;
  393. begin
  394.    Drive:= ValidateDriveLetter(Drive);
  395.    GetVolumeInformationX(Drive, DI);
  396.    result:= DI.VolumeSerialNumber;
  397. end;
  398.  
  399. function DriveVolumeName(Drive: Char): String;
  400. var
  401.    DI: TDriveInformation;
  402. begin
  403.    Drive:= ValidateDriveLetter(Drive);
  404.    GetVolumeInformationX(Drive, DI);
  405.    result:= DI.VolumeName;
  406. end;
  407.  
  408. function DriveMaxFilenameLength(Drive: Char): Integer;
  409. var
  410.    DI: TDriveInformation;
  411. begin
  412.    Drive:= ValidateDriveLetter(Drive);
  413.    GetVolumeInformationX(Drive, DI);
  414.    result:= DI.MaximumComponentLength;
  415. end;
  416.  
  417. function DriveCasePreserved(Drive: Char): Boolean;
  418. var
  419.    DI: TDriveInformation;
  420. begin
  421.    Drive:= ValidateDriveLetter(Drive);
  422.    GetVolumeInformationX(Drive, DI);
  423.    result:= TRUE;//([FS_CASE_IS_PRESERVED] in DI.FileSystemFlags);
  424. end;
  425.  
  426. function DriveSectorsPerTrack(Drive: Char): Integer;
  427. var
  428.    DPB: TDeviceParamBlock;
  429. begin
  430.    Drive:= ValidateDriveLetter(Drive);
  431.    GetDeviceParamBlock(Drive, DPB);
  432.    result:= DPB.BiosParamBlock.SectorsPerTrack;
  433. end;
  434.  
  435. function DriveReservedSectors(Drive: Char): Integer;
  436. var
  437.    DPB: TDeviceParamBlock;
  438. begin
  439.    Drive:= ValidateDriveLetter(Drive);
  440.    GetDeviceParamBlock(Drive, DPB);
  441.    result:= DPB.BiosParamBlock.ReservedSectors;
  442. end;
  443.  
  444. function DriveTracksCount(Drive: Char): Integer;
  445. var
  446.    TotalSectors, TracksOn: Integer;
  447. begin
  448.    Drive:= ValidateDriveLetter(Drive);
  449.    TotalSectors:= RoundUp(DriveTotalClusters(Drive) * DriveSectorsPerCluster(Drive));
  450.    TracksOn:= RoundUp(TotalSectors div DriveSectorsPerTrack(Drive))+1;
  451.    result:= RoundUp(TracksOn div DriveHeadCount(Drive));
  452. end;
  453.  
  454. function DriveHeadCount(Drive: Char): Integer;
  455. var
  456.    DPB: TDeviceParamBlock;
  457. begin
  458.    Drive:= ValidateDriveLetter(Drive);
  459.    GetDeviceParamBlock(Drive, DPB);
  460.    result:= DPB.BiosParamBlock.NumHeads;
  461. end;
  462.  
  463. function DriveFATCount(Drive: Char): Integer;
  464. var
  465.    DPB: TDeviceParamBlock;
  466. begin
  467.    Drive:= ValidateDriveLetter(Drive);
  468.    GetDeviceParamBlock(Drive, DPB);
  469.    result:= DPB.BiosParamBlock.NumFats;
  470. end;
  471.  
  472. function DriveRootEntries(Drive: Char): Integer;
  473. var
  474.    DPB: TDeviceParamBlock;
  475. begin
  476.    Drive:= ValidateDriveLetter(Drive);
  477.    GetDeviceParamBlock(Drive, DPB);
  478.    result:= DPB.BiosParamBlock.NumRootEntries;
  479. end;
  480.  
  481. function DriveHiddenSectors(Drive: Char): Integer;
  482. var
  483.    DPB: TDeviceParamBlock;
  484. begin
  485.    Drive:= ValidateDriveLetter(Drive);
  486.    GetDeviceParamBlock(Drive, DPB);
  487.    result:= DPB.BiosParamBlock.HiddenSectors;
  488. end;
  489.  
  490. function DriveCylinders(Drive: Char): Integer;
  491. var
  492.    DPB: TDeviceParamBlock;
  493. begin
  494.    Drive:= ValidateDriveLetter(Drive);
  495.    GetDeviceParamBlock(Drive, DPB);
  496.    result:= DPB.NumCylinders;
  497. end;
  498.  
  499. function DriveSectorsPerFAT(Drive: Char): Integer;
  500. var
  501.    DPB: TDeviceParamBlock;
  502. begin
  503.    Drive:= ValidateDriveLetter(Drive);
  504.    GetDeviceParamBlock(Drive, DPB);
  505.    result:= DPB.BiosParamBlock.SectorsPerFat;
  506. end;
  507.  
  508. function DriveFilesystemName(Drive: Char): String;
  509. var
  510.    DI: TDriveInformation;
  511. begin
  512.    Drive:= ValidateDriveLetter(Drive);
  513.    GetVolumeInformationX(Drive, DI);
  514.    result:= DI.FileSystemName;
  515. end;
  516.  
  517. function HardDrives: TStringList;
  518. var
  519.   i: Integer;
  520.   C: String;
  521.   DType: Integer;
  522. //  DriveString: String;
  523. begin
  524.   result:= TStringList.Create;
  525.   (* Zeichen 65 = A und 90 = Z -- Schleife durch alle m÷glichen Laufwerke *)
  526.   for i := 65 to 90 do
  527.   begin
  528.     (* Aktuellen Schleifenindex in entsprechenden Laufwerksbezeichner wandeln *)
  529.     C := chr(i)+':\';
  530.  
  531.     (* Die Funktion GetDriveType() ermittelt den Medientyp des Laufwerks *)
  532.     DType := GetDriveType(PChar(C));
  533.  
  534.     (* Gⁿltige Laufwerksbezeichner in Liste aufnehmen *)
  535.     if ( DType = DRIVE_FIXED ) then begin
  536.       result.Add(C);
  537.     end;
  538.   end;
  539. end;
  540.  
  541. function HardDrivesLong: TStringList;
  542. var
  543.   i: Integer;
  544.   C: String;
  545.   DType: Integer;
  546.   DriveString: String;
  547. begin
  548.   result:= TStringList.Create;
  549.   (* Zeichen 65 = A und 90 = Z -- Schleife durch alle m÷glichen Laufwerke *)
  550.   for i := 65 to 90 do
  551.   begin
  552.     (* Aktuellen Schleifenindex in entsprechenden Laufwerksbezeichner wandeln *)
  553.     C := chr(i)+':\';
  554.  
  555.     (* Die Funktion GetDriveType() ermittelt den Medientyp des Laufwerks *)
  556.     DType := GetDriveType(PChar(C));
  557.  
  558.     (* Ermittelten Medientyp auswerten und entsprechende Meldung generieren *)
  559.     case DType of
  560.       DRIVE_FIXED: begin
  561.          DriveString:= DriveVolumeName(Chr(I));
  562.          DriveString:= PChar(Copy(DriveString, 1, StringLen(DriveString)) +
  563.             ' (' + Chr(I) + ':)');
  564.          result.Add(DriveString);
  565.       end;
  566.     end;
  567.   end;
  568. end;
  569.  
  570. function OpenCD(Drive: Char): Boolean;
  571. var
  572.   Res: MciError;
  573.   OpenParm: TMCI_Open_Parms;
  574.   Flags: DWORD;
  575.   S: string;
  576.   DeviceID: Word;
  577. begin
  578.   Result := False;
  579.   S      := Drive + ':';
  580.   Flags  := mci_Open_Type or mci_Open_Element;
  581.   with OpenParm do 
  582.   begin
  583.     dwCallback       := 0;
  584.     lpstrDeviceType  := 'CDAudio';
  585.     lpstrElementName := PChar(S);
  586.   end;
  587.   Res := mciSendCommand(0, mci_Open, Flags, Longint(@OpenParm));
  588.   if Res = 0 then Exit;
  589.   DeviceID := OpenParm.wDeviceID;
  590.   try
  591.     Res := mciSendCommand(DeviceID, MCI_SET, MCI_SET_DOOR_OPEN, 0);
  592.     if Res = 0 then Exit;
  593.     Result := True;
  594.   finally
  595.     mciSendCommand(DeviceID, mci_Close, Flags, Longint(@OpenParm));
  596.   end;
  597. end;
  598.  
  599. function SystemHostDrive: Char;
  600. var
  601.    SysDir: Pchar;
  602. begin
  603.    SysDir:= StrAlloc(MAX_PATH);
  604.    GetWindowsDirectory(SysDir, MAX_PATH+1);
  605.    result:= SysDir[0];
  606. end;
  607.  
  608. //---------------------------------------------------------------------
  609.  
  610. function ValidDriveLetter(Drive: Char): Boolean;
  611. begin
  612.    result:= not ((Ord(UpCase(Drive)) < 65) or (Ord(UpCase(Drive)) > 90));
  613. end;
  614.  
  615. function ValidateDriveLetter(Drive: Char): Char;
  616. begin
  617.    if ValidDriveLetter(Drive) then result:= UpCase(Drive) else result:= 'C';
  618. end;
  619.  
  620. function DriveLetterToIndex(Drive: Char): Byte;
  621. begin
  622.    Drive:= ValidateDriveLetter(Drive);
  623.    result:= (Ord(Drive) - 64);
  624. end;
  625.  
  626.  
  627. function DriveIndexToLetter(Drive: Byte): Char;
  628. begin
  629.    if (Drive > 0) and (Drive < 27) then result:= UpCase(Chr(Drive))
  630.    else result:= 'C';
  631. end;
  632.  
  633. function GetVolumeInformationX (Drive: Char; var V : TDriveInformation): Boolean;
  634.  var
  635.    EM : integer;
  636.  begin
  637.    EM := SetErrorMode (SEM_FAILCRITICALERRORS);
  638.    result:= FALSE;
  639.    Drive:= ValidateDriveLetter(Drive);
  640.    try
  641.      with V do
  642.      begin
  643.        SetLength (VolumeName, MAX_PATH);
  644.        SetLength (FileSystemName, MAX_PATH);
  645.        VolumeSerialNumber := 0;
  646.        MaximumComponentLength := 0;
  647.        FileSystemFlags := 0;
  648.          GetVolumeInformation (PChar (Drive+':\'), PChar (VolumeName), MAX_PATH,
  649.          @VolumeSerialNumber, MaximumComponentLength, FileSystemFlags,
  650.          PChar (FileSystemName), MAX_PATH);
  651.      end;
  652.    finally
  653.      SetErrorMode (EM);
  654.    end;
  655. end;
  656.  
  657. function VWin32(CtlCode: TVWin32CtlCode; var Regs: TDiocRegisters): Boolean;
  658. var
  659.   hDevice: THandle;
  660.   Count: DWORD;
  661. begin
  662.    hDevice := CreateFile('\\.\VWIN32', 0, 0, nil, 0,
  663.       FILE_FLAG_DELETE_ON_CLOSE, 0);
  664.    Result := DeviceIoControl(hDevice, Ord(CtlCode), @Regs, SizeOf(Regs),
  665.                @Regs, SizeOf(Regs), Count, nil);
  666.    CloseHandle(hDevice);
  667. end;
  668.  
  669. function GetDeviceParamBlock(Drive: Char; var ParamBlock: TDeviceParamBlock): Word;
  670. var
  671.   Regs: TDiocRegisters;
  672. begin
  673. with Regs do
  674.    begin
  675.       EAX := $440D;
  676.       EBX := Ord(UpCase(Drive)) - Ord('@');
  677.       ECX := $0860;
  678.       EDX := LongInt(@ParamBlock);
  679.       VWin32(ccVWin32IntIoctl, Regs);
  680.       if (Flags and 1) <> 0 then
  681.          Result := LoWord(EAX)
  682.       else
  683.          Result := 0;
  684.    end;
  685. end;
  686.  
  687. function SetDeviceParamBlock(Drive: Char; var ParamBlock: TDeviceParamBlock): Word;
  688. var
  689.   Regs: TDiocRegisters;
  690. begin
  691.    with Regs do
  692.       begin
  693.          EAX := $440D;
  694.          EBX := Ord(UpCase(Drive)) - Ord('@');
  695.          ECX := $0840;
  696.          EDX := LongInt(@ParamBlock);
  697.          VWin32(ccVWin32IntIoctl, Regs);
  698.          if (Flags and 1) <> 0 then
  699.             Result := LoWord(EAX)
  700.          else
  701.             Result := 0;
  702.       end;
  703. end;
  704.  
  705. function FloppyReady(const Drive: char): Boolean;
  706. var
  707.   DrvNum: byte;
  708.   EMode: Word;
  709. begin
  710.   result := false;
  711.   DrvNum := ord(Drive);
  712.   if DrvNum >= ord('a') then dec(DrvNum,$20);
  713.   EMode := SetErrorMode(SEM_FAILCRITICALERRORS);
  714.   try
  715.     if DiskSize(DrvNum-$40) <> -1 then result := true
  716.     else messagebeep(0);
  717.   finally
  718.     SetErrorMode(EMode);
  719.   end;
  720. end;
  721.  
  722. function CompareDiskStruct(Drive: Char; var BPC, SPC, BPS, FC, TC: Integer; var FS, TS, DSN: Int64): Boolean;
  723. begin
  724.    result:= ((BPC = DriveBytesPerCluster(Drive)) and
  725.              (SPC = DriveSectorsPerCluster(Drive)) and
  726.              (BPS = DriveBytesPerSector(Drive)) and
  727.              (FC  = DriveFreeClusters(Drive)) and
  728.              (TC  = DriveTotalClusters(Drive)) and
  729.              (FS  = DriveFreeSpace(Drive)) and
  730.              (TS  = DriveTotalSpace(Drive)) and
  731.              (DSN = DriveSerialNumberInt(Drive)));
  732. end;
  733.  
  734. end.
  735.