![]() |
Re: Problem beim auslesen der Festplatten Seriennummer
Mehr gibt es nicht. Aber für den Kopierschutz reicht mir ja die Seriennummer.
gimAuto IDE Primary Master Type: Fixed LBA sectors: 0 Cylinders: 0 Heads: 0 Tracks: 0 Sectors per track: 0 Size: 0 Mb Controller buffer size: 0 Kb ECC Code: 0 Model: FUJITSU MAP3367NC Firmware Revision: 0108 gimByName Device PhysicalDrive0: Type: Fixed Model: FUJITSU MAP3367NC Firmware Revision: 0108 Serial Number: UPR7P3C00KEA Beim Notebook mit IDE werden alle Details angezeigt. Gruß K.-D. |
Re: Problem beim auslesen der Festplatten Seriennummer
Wo wird denn
![]() Komisch irgendwie .. |
AW: Problem beim auslesen der Festplatten Seriennummer
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 :( |
AW: Problem beim auslesen der Festplatten Seriennummer
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
ich habe die auf der vorherigen Seite verwendete Unif hddinfo.pas benutzt, da ich vor dem gleichen Problem stehe; funktioniert hat sie ad-hoc allerdings nicht. Grund ist, dass PChar inzwischen PWideChar entspricht und somit die Adressen der Zeiger für das Lesen aus DeviceDescriptor nicht mehr passen. Ich habe die Definitionen und PCh und TCharArray entsprechend angepasst und nu läuft die Unit wieder. lg Sebastian |
AW: Problem beim auslesen der Festplatten Seriennummer
So ist
Delphi-Quellcode:
definiert:
PChar
Delphi-Quellcode:
Wenn man es richtig macht, kann man so eine Unit auch generell nutzbar erstellen (unabhängig von Ansi/Unicode)
type
PChar = {$IFDEF UNICODE}PWideChar{$ELSE}PAnsiChar{$ENDIF}; |
AW: Problem beim auslesen der Festplatten Seriennummer
Hi,
da bin ich bei dir ;-) Problem war bei mir, dass ich im ersten Moment nicht wusste / realisiert habe, wo dran das liegt, ich hatte erst einmal den DeviceIoControl Aufruf in Verdacht. Deswegen dachte ich, ich poste das mal, vlt. spart das jemanden irgenwann einmal Arbeit ;-) lg Sebastian |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz