|
Registriert seit: 4. Aug 2010 2 Beiträge Delphi 2 Desktop |
#33
Hello everybody
![]() Because the first method (WithZeroRights) doesn't work for me, I wrote another for ReadIdeDriveAsScsiDriveInNT method:
Delphi-Quellcode:
Sample usage:
unit HDScsiInfo;
interface uses Windows, SysUtils; const IDENTIFY_BUFFER_SIZE = 512; FILE_DEVICE_SCSI = $0000001b; IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI shl 16) + $0501); IDE_ATA_IDENTIFY = $EC; // Returns ID sector for ATA. IOCTL_SCSI_MINIPORT = $0004D008; // see NTDDSCSI.H for definition type TDiskData = array [0..256-1] of DWORD; TDriveInfo = record ControllerType: Integer; //0 - primary, 1 - secondary, 2 - Tertiary, 3 - Quaternary DriveMS: Integer; //0 - master, 1 - slave DriveModelNumber: String; DriveSerialNumber: String; DriveControllerRevisionNumber: String; ControllerBufferSizeOnDrive: Int64; DriveType: String; //fixed or removable or unknown DriveSizeBytes: Int64; end; THDScsiInfo = class (TObject) private FDriveNumber: Byte; FFileHandle: Cardinal; FInfoAvailable: Boolean; FProductRevision: string; FSerialNumber: string; FControllerType: Integer; FDriveMS: Integer; FDriveModelNumber: string; FControllerBufferSizeOnDrive: Int64; FDriveType: string; FDriveSizeBytes: Int64; procedure ReadInfo; procedure SetDriveNumber(const Value: Byte); procedure PrintIdeInfo(DiskData: TDiskData); public constructor Create; property DriveNumber: Byte read FDriveNumber write SetDriveNumber; property ProductRevision: string read FProductRevision; property SerialNumber: string read FSerialNumber; property ControllerType: Integer read FControllerType; property DriveMS: Integer read FDriveMS; property DriveModelNumber: string read FDriveModelNumber; property ControllerBufferSizeOnDrive: Int64 read FControllerBufferSizeOnDrive; property DriveType: string read FDriveType; property DriveSizeBytes: Int64 read FDriveSizeBytes; function IsInfoAvailable: Boolean; end; implementation type SRB_IO_CONTROL = record HeaderLength: Cardinal; Signature: array [0..8-1] of Byte; Timeout: Cardinal; ControlCode: Cardinal; ReturnCode: Cardinal; Length: Cardinal; end; PSRB_IO_CONTROL = ^SRB_IO_CONTROL; DRIVERSTATUS = record bDriverError: Byte;// Error code from driver, or 0 if no error. bIDEStatus: Byte;// Contents of IDE Error register. // Only valid when bDriverError is SMART_IDE_ERROR. bReserved: array [0..1] of Byte;// Reserved for future expansion. dwReserved: array [0..1] of Longword;// Reserved for future expansion. end; SENDCMDOUTPARAMS = record cBufferSize: Longword;// Size of bBuffer in bytes DriverStatus: DRIVERSTATUS;// Driver status structure. bBuffer: array [0..0] of Byte;// Buffer of arbitrary length in which to store the data read from the // drive. end; IDEREGS = record bFeaturesReg: Byte;// Used for specifying SMART "commands". bSectorCountReg: Byte;// IDE sector count register bSectorNumberReg: Byte;// IDE sector number register bCylLowReg: Byte;// IDE low order cylinder value bCylHighReg: Byte;// IDE high order cylinder value bDriveHeadReg: Byte;// IDE drive/head register bCommandReg: Byte;// Actual IDE command. bReserved: Byte;// reserved for future use. Must be zero. end; SENDCMDINPARAMS = record cBufferSize: Longword;// Buffer size in bytes irDriveRegs: IDEREGS; // Structure with drive register values. bDriveNumber: Byte;// Physical drive number to send // command to (0,1,2,3). bReserved: array[0..2] of Byte;// Reserved for future expansion. dwReserved: array [0..3] of Longword;// For future use. bBuffer: array [0..0] of Byte;// Input buffer. //!TODO: this is array of single element end; PSENDCMDINPARAMS = ^SENDCMDINPARAMS; PSENDCMDOUTPARAMS = ^SENDCMDOUTPARAMS; IDSECTOR = record wGenConfig: Word; wNumCyls: Word; wReserved: Word; wNumHeads: Word; wBytesPerTrack: Word; wBytesPerSector: Word; wSectorsPerTrack: Word; wVendorUnique: array [0..3-1] of Word; sSerialNumber: array [0..20-1] of AnsiChar; wBufferType: Word; wBufferSize: Word; wECCSize: Word; sFirmwareRev: array [0..8-1] of AnsiChar; sModelNumber: array [0..40-1] of AnsiChar; wMoreVendorUnique: Word; wDoubleWordIO: Word; wCapabilities: Word; wReserved1: Word; wPIOTiming: Word; wDMATiming: Word; wBS: Word; wNumCurrentCyls: Word; wNumCurrentHeads: Word; wNumCurrentSectorsPerTrack: Word; ulCurrentSectorCapacity: Cardinal; wMultSectorStuff: Word; ulTotalAddressableSectors: Cardinal; wSingleWordDMA: Word; wMultiWordDMA: Word; bReserved: array [0..128-1] of Byte; end; PIDSECTOR = ^IDSECTOR; TArrayDriveInfo = array of TDriveInfo; type DeviceQuery = record HeaderLength: Cardinal; Signature: array [0..8-1] of Byte; Timeout: Cardinal; ControlCode: Cardinal; ReturnCode: Cardinal; Length: Cardinal; cBufferSize: Longword;// Buffer size in bytes irDriveRegs: IDEREGS; // Structure with drive register values. bDriveNumber: Byte;// Physical drive number to send bReserved: array[0..2] of Byte;// Reserved for future expansion. dwReserved: array [0..3] of Longword;// For future use. bBuffer: array [0..0] of Byte;// Input buffer. //!TODO: this is array of single element end; function ConvertToString (diskdata: TDiskData; firstIndex: Integer; lastIndex: Integer; buf: PAnsiChar): PAnsiChar; var index: Integer; position: Integer; begin position := 0; // each integer has two characters stored in it backwards for index := firstIndex to lastIndex do begin // get high byte for 1st character buf[position] := AnsiChar(Chr(diskdata [index] div 256)); inc(position); // get low byte for 2nd character buf [position] := AnsiChar(Chr(diskdata [index] mod 256)); inc(position); end; // end the string buf[position] := Chr(0); // cut off the trailing blanks index := position - 1; while (index >0) do begin // if not IsSpace(AnsiChar(buf[index])) if (AnsiChar(buf[index]) <> ' ') then break; buf [index] := Chr(0); dec(index); end; Result := buf; end; constructor THDScsiInfo.Create; begin inherited; SetDriveNumber(0); end; function THDScsiInfo.IsInfoAvailable: Boolean; begin Result := FInfoAvailable end; procedure THDScsiInfo.PrintIdeInfo (DiskData: TDiskData); var nSectors: Int64; serialNumber: array [0..1024-1] of AnsiChar; modelNumber: array [0..1024-1] of AnsiChar; revisionNumber: array [0..1024-1] of AnsiChar; begin // copy the hard drive serial number to the buffer ConvertToString (DiskData, 10, 19, @serialNumber); ConvertToString (DiskData, 27, 46, @modelNumber); ConvertToString (DiskData, 23, 26, @revisionNumber); FControllerType := FDriveNumber div 2; FDriveMS := FDriveNumber mod 2; FDriveModelNumber := modelNumber; FSerialNumber := serialNumber; FProductRevision := revisionNumber; FControllerBufferSizeOnDrive := DiskData [21] * 512; if ((DiskData [0] and $0080) <> 0) then FDriveType := 'Removable' else if ((DiskData [0] and $0040) <> 0) then FDriveType := 'Fixed' else FDriveType := 'Unknown'; // calculate size based on 28 bit or 48 bit addressing // 48 bit addressing is reflected by bit 10 of word 83 if ((DiskData[83] and $400) <> 0) then begin nSectors := DiskData[103] * Int64(65536) * Int64(65536) * Int64(65536) + DiskData[102] * Int64(65536) * Int64(65536) + DiskData[101] * Int64(65536) + DiskData[100]; end else begin nSectors := DiskData [61] * 65536 + DiskData [60]; end; // there are 512 bytes in a sector FDriveSizeBytes := nSectors * 512; end; procedure THDScsiInfo.ReadInfo; type DataArry = array [0..256-1] of WORD; PDataArray = ^DataArry; const SENDIDLENGTH = sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE; var I: Integer; buffer: array [0..sizeof (SRB_IO_CONTROL) + SENDIDLENGTH - 1] of AnsiChar; dQuery: DeviceQuery; dummy: DWORD; pOut: PSENDCMDOUTPARAMS; pId: PIDSECTOR; DiskData: TDiskData; pIdSectorPtr: PWord; begin FInfoAvailable := False; FFileHandle := CreateFile (PChar(Format('\\.\Scsi%d:', [FDriveNumber])), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if (FFileHandle <> INVALID_HANDLE_VALUE) then begin ZeroMemory(@dQuery, SizeOf(dQuery)); dQuery.HeaderLength := sizeof (SRB_IO_CONTROL); dQuery.Timeout := 10000; dQuery.Length := SENDIDLENGTH; dQuery.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY; StrLCopy(@dQuery.Signature, 'SCSIDISK', 8); dQuery.irDriveRegs.bCommandReg := IDE_ATA_IDENTIFY; dQuery.bDriveNumber := FDriveNumber; if (DeviceIoControl (FFileHandle, IOCTL_SCSI_MINIPORT, @dQuery, SizeOf(dQuery), @buffer, sizeof (SRB_IO_CONTROL) + SENDIDLENGTH, dummy, nil)) then begin pOut := PSENDCMDOUTPARAMS(buffer + sizeof (SRB_IO_CONTROL)); //!TOCHECK pId := PIDSECTOR(@pOut^.bBuffer[0]); if (pId^.sModelNumber[0] <> Chr(0) ) then begin pIdSectorPtr := PWord(pId); for I := 0 to 256-1 do DiskData[I] := PDataArray(pIdSectorPtr)[I]; PrintIdeInfo (DiskData); FInfoAvailable := True; end; end; CloseHandle(FFileHandle); end; end; procedure THDScsiInfo.SetDriveNumber(const Value: Byte); begin FDriveNumber := Value; ReadInfo; end; end.
Delphi-Quellcode:
This works with my WD disk.
procedure ReadIdeDriveAsScsiDriveInNT;
var DriveNumber: Byte; HDDInfo: THDScsiInfo; begin HDDInfo := THDScsiInfo.Create(); try for DriveNumber := 0 to MAX_IDE_DRIVES - 1 do try HDDInfo.DriveNumber := DriveNumber; if HDDInfo.IsInfoAvailable then begin Writeln('Available Drive: ', HDDInfo.DriveNumber); Writeln('ControllerType: ', HDDInfo.ControllerType); Writeln('DriveMS: ', HDDInfo.DriveMS); Writeln('DriveModelNumber: ', HDDInfo.DriveModelNumber); Writeln('ControllerBufferSizeOnDrive: ', HDDInfo.ControllerBufferSizeOnDrive); Writeln('DriveType: ', HDDInfo.DriveType); Writeln('DriveSizeBytes: ', HDDInfo.DriveSizeBytes); Writeln('ProductRevision: ', HDDInfo.ProductRevision); Writeln('SerialNumber: ', HDDInfo.SerialNumber); end; except on E: Exception do Writeln(Format('DriveNumber %d, %s: %s', [DriveNumber, E.ClassName, E.Message])); end; finally HDDInfo.Free; end; end; begin ReadIdeDriveAsScsiDriveInNT; Write('Press <Enter>'); end. Sorry, I don't speak German ![]() |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |