DeviceHelper.pas
上传用户:wanyu_2000
上传日期:2021-02-21
资源大小:527k
文件大小:5k
源码类别:

DVD

开发平台:

Delphi

  1. {-----------------------------------------------------------------------------
  2.  Unit Name: DeviceHelper
  3.  Author:    Andrew Semack / Dancemammal
  4.  Purpose:   collect info about availible CD / DVD devices
  5.  History:
  6. -----------------------------------------------------------------------------}
  7. unit DeviceHelper;
  8. // TODO : There unit to help any universal SCSI functions which used in library classes }
  9. interface
  10. uses
  11.   Windows, sysutils, SCSIUnit, SCSITypes, Classes,
  12.   CDROMIOCTL, SCSIDefs, CovertFuncs;
  13. type
  14.   TSPTIWriter = record
  15.     HaId: Byte;
  16.     Target: Byte;
  17.     Lun: Byte;
  18.     Vendor: ShortString;
  19.     ProductId: ShortString;
  20.     Revision: ShortString;
  21.     VendorSpec: ShortString;
  22.     Description: ShortString;
  23.     DriveLetter: Char;
  24.     DriveHandle: Thandle;
  25.   end;
  26. type
  27.   TSPTIWriters = record
  28.     ActiveCdRom: Byte;
  29.     CdRomCount: Byte;
  30.     CdRom: array[0..25] of TSPTIWriter;
  31.   end;
  32. type
  33.   SCSI_ADDRESS = record
  34.     Length: LongInt;
  35.     PortNumber: Byte;
  36.     PathId: Byte;
  37.     TargetId: Byte;
  38.     Lun: Byte;
  39.   end;
  40.   PSCSI_ADDRESS = ^SCSI_ADDRESS;
  41. function GatherDeviceID(Adapter, Target, Lun: byte; Letter: char): TBurnerID;
  42. function GetDriveNumbers(var CDRoms: TSPTIWriters): integer;
  43. procedure GetDriveInformation(i: byte; var CdRoms: TSPTIWriters);
  44. function GetSPTICdRomDrives(var CdRoms: TSPTIWriters): Boolean;
  45. implementation
  46. function GatherDeviceID(Adapter, Target, Lun: byte; Letter: char): TBurnerID;
  47. begin
  48.   Result := GatherDWORD(Adapter, Target,
  49.     ((Lun and 7) shl 5) or (ORD(Letter) and $1F), 0);
  50. end;
  51. function GetDriveNumbers(var CDRoms: TSPTIWriters): integer;
  52. var
  53.   i: integer;
  54.   szDrives: array[0..105] of Char;
  55.   p: PChar;
  56. begin
  57.   CdRoms.CdRomCount := 0;
  58.   GetLogicalDriveStrings(105, szDrives);
  59.   p := szDrives;
  60.   i := 0;
  61.   while p^ <> '' do
  62.   begin
  63.     if GetDriveType(p) = DRIVE_CDROM then
  64.     begin
  65.       CdRoms.CdRom[i].DriveLetter := p^; // + ':';
  66.       i := CdRoms.CdRomCount + 1;
  67.       CdRoms.CdRomCount := CdRoms.CdRomCount + 1;
  68.     end;
  69.     p := p + lstrlen(p) + 1;
  70.   end;
  71.   Result := CdRoms.CdRomCount;
  72. end;
  73. procedure GetDriveInformation(i: byte; var CdRoms: TSPTIWriters);
  74. var
  75.   fh: THandle;
  76.   buf: array[0..1023] of Char;
  77.   buf2: array[0..31] of Char;
  78.   status: Bool;
  79.   pswb: PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
  80.   pscsiAddr: PSCSI_ADDRESS;
  81.   length, returned: integer;
  82.   inqData: array[0..99] of Char; // was array[0..99] of Byte;
  83.   dwFlags: DWord;
  84.   DriveString: PChar;
  85. begin
  86.   dwFlags := GENERIC_READ;
  87.   if getOsVersion >= OS_WIN2K then
  88.     dwFlags := dwFlags or GENERIC_WRITE;
  89.   StrPCopy(@buf2, Format('\.%s:', [CdRoms.CdRom[i].DriveLetter]));
  90.   fh := CreateFile(buf2, dwFlags, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
  91.     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  92.   if fh = INVALID_HANDLE_VALUE then
  93.   begin
  94.     // It seems that with no Administrator privileges
  95.     // the handle value will be invalid
  96.     Exit;
  97.   end;
  98.   (*
  99.    * Get the drive inquiry data
  100.    *)
  101.   ZeroMemory(@buf, 1024);
  102.   ZeroMemory(@inqData, 100);
  103.   pswb := PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER(@buf);
  104.   pswb^.spt.Length := sizeof(SCSI_PASS_THROUGH);
  105.   pswb^.spt.CdbLength := 6;
  106.   pswb^.spt.SenseInfoLength := 24;
  107.   pswb^.spt.DataIn := SCSI_IOCTL_DATA_IN;
  108.   pswb^.spt.DataTransferLength := 100;
  109.   pswb^.spt.TimeOutValue := 2;
  110.   pswb^.spt.DataBuffer := @inqData;
  111.   pswb^.spt.SenseInfoOffset := SizeOf(pswb^.spt) + SizeOf(pswb^.Filler);
  112.   pswb^.spt.Cdb[0] := $12;
  113.   pswb^.spt.Cdb[4] := $64;
  114.   length := sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
  115.   status := DeviceIoControl(fh,
  116.     IOCTL_SCSI_PASS_THROUGH_DIRECT,
  117.     pswb,
  118.     length,
  119.     pswb,
  120.     length,
  121.     Cardinal(returned),
  122.     nil);
  123.   if not status then
  124.   begin
  125.     // CloseHandle( fh );
  126.     Exit;
  127.   end;
  128.   DriveString := @inqData;
  129.   Inc(DriveString, 8);
  130.   CdRoms.CdRom[i].Vendor := Copy(DriveString, 1, 8); // Vendor
  131.   CdRoms.CdRom[i].ProductId := Copy(DriveString, 8 + 1, 16);
  132.   // Product ID
  133.   CdRoms.CdRom[i].Revision := Copy(DriveString, 24 + 1, 4);
  134.   // Revision
  135.   CdRoms.CdRom[i].VendorSpec := Copy(DriveString, 28 + 1, 20);
  136.   // Vendor Spec.
  137.   CdRoms.CdRom[i].Description := CdRoms.CdRom[i].Vendor +
  138.     CdRoms.CdRom[i].ProductId + CdRoms.CdRom[i].Revision;
  139.   CdRoms.CdRom[i].DriveHandle := fh;
  140.   (*
  141.    * get the address (path/tgt/lun) of the drive via IOCTL_SCSI_GET_ADDRESS
  142.    *)
  143.   ZeroMemory(@buf, 1024);
  144.   pscsiAddr := PSCSI_ADDRESS(@buf);
  145.   pscsiAddr^.Length := sizeof(SCSI_ADDRESS);
  146.   if (DeviceIoControl(fh, IOCTL_SCSI_GET_ADDRESS, nil, 0,
  147.     pscsiAddr, sizeof(SCSI_ADDRESS), Cardinal(returned),
  148.     nil)) then
  149.   begin
  150.     CDRoms.CdRom[i].HaId := pscsiAddr^.PortNumber;
  151.     CDRoms.CdRom[i].Target := pscsiAddr^.TargetId;
  152.     CDRoms.CdRom[i].Lun := pscsiAddr^.Lun;
  153.   end
  154.   else
  155.   begin
  156.     Exit;
  157.   end;
  158.   // CloseHandle( fh );
  159. end;
  160. function GetSPTICdRomDrives(var CdRoms: TSPTIWriters): Boolean;
  161. var
  162.   Index: integer;
  163. begin
  164.   Result := False;
  165.   if GetDriveNumbers(CdRoms) > 0 then
  166.   begin
  167.     for Index := 0 to CdRoms.CdRomCount - 1 do
  168.     begin
  169.       GetDriveInformation(Index, CdRoms);
  170.     end;
  171.     Result := True;
  172.   end;
  173. end;
  174. end.