![]() |
Problem beim auslesen der Festplatten Seriennummer
Hallo,
ich schreibe gerade für uns ein Inventory Tool welches Hard- und Software der Geräte erfasst. Zur Identifizierung des Gerätes mit unseren Stammdaten wird eine Equipment Nummer benutzt, welche normalerweise bei der Installation auf dem Gerät hinterlegt wird. Nun kommt es leider vor das ein Gerät z.B. neu installiert wird ohne unser Wissen :wall: Aus diesem Grund wollte ich zur Identifizierung des Gerätes einen weiteren Parameter hinzuziehen, mit dem ich erkennen kann ob es ein bekanntes Gerät ist. Hier in der DP habe ich folgende Funktion gefunden zum auslesen der HDD Seriennummer. Sie funktioniert auch einwandfrei bei 90% unserer Geräte. Nur bei den restlichen bekomme ich beim anlegen des handle ein INVALID_HANDLE_VALUE zurück. Die Platten unterstützen aber definitiv S.M.A.R.T. und HD-Tune kann auch problemlos die Seriennummer auslesen. Hier mal die Funktion die ich benutze:
Delphi-Quellcode:
Eine Beispielplatte bei der es nicht geht ist z.B. eine Seagate Momentus 5400 ST98823A 80GB
function GetIdeSerialNumber ():string;
const IDENTIFY_BUFFER_SIZE = 512; type TIDERegs = packed 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; TSendCmdInParams = packed record // Buffer size in bytes cBufferSize : DWORD; // Structure with drive register values. irDriveRegs : TIDERegs; // Physical drive number to send command to (0,1,2,3). bDriveNumber : BYTE; bReserved : Array[0..2] of Byte; dwReserved : Array[0..3] of DWORD; bBuffer : Array[0..0] of Byte; // Input buffer. end; TIdSector = packed record wGenConfig : Word; wNumCyls : Word; wReserved : Word; wNumHeads : Word; wBytesPerTrack : Word; wBytesPerSector : Word; wSectorsPerTrack : Word; wVendorUnique : Array[0..2] of Word; sSerialNumber : Array[0..19] of CHAR; wBufferType : Word; wBufferSize : Word; wECCSize : Word; sFirmwareRev : Array[0..7] of Char; sModelNumber : Array[0..39] of Char; wMoreVendorUnique : Word; wDoubleWordIO : Word; wCapabilities : Word; wReserved1 : Word; wPIOTiming : Word; wDMATiming : Word; wBS : Word; wNumCurrentCyls : Word; wNumCurrentHeads : Word; wNumCurrentSectorsPerTrack : Word; ulCurrentSectorCapacity : DWORD; wMultSectorStuff : Word; ulTotalAddressableSectors : DWORD; wSingleWordDMA : Word; wMultiWordDMA : Word; bReserved : Array[0..127] of BYTE; end; PIdSector = ^TIdSector; TDriverStatus = packed record // Error code from driver, or 0 if no error. bDriverError : Byte; // Contents of IDE Error register. Only valid when bDriverError is SMART_IDE_ERROR. bIDEStatus : Byte; bReserved : Array[0..1] of Byte; dwReserved : Array[0..1] of DWORD; end; TSendCmdOutParams = packed record // Size of bBuffer in bytes cBufferSize : DWORD; // Driver status structure. DriverStatus : TDriverStatus; // Buffer of arbitrary length in which to store the data read from the drive. bBuffer : Array[0..0] of BYTE; end; var hDevice : THandle; cbBytesReturned : DWORD; SCIP : TSendCmdInParams; aIdOutCmd : Array [0..(SizeOf(TSendCmdOutParams)+IDENTIFY_BUFFER_SIZE-1)-1] of Byte; IdOutCmd : TSendCmdOutParams absolute aIdOutCmd; procedure ChangeByteOrder( var Data; Size : Integer ); var ptr : PChar; i : Integer; c : Char; begin ptr := @Data; for i := 0 to (Size shr 1)-1 do begin c := ptr^; ptr^ := (ptr+1)^; (ptr+1)^ := c; Inc(ptr,2); end; end; begin Result := ''; // return empty string on error if SysUtils.Win32Platform=VER_PLATFORM_WIN32_NT then // Windows NT, Windows 2000 begin // warning! change name for other drives: ex.: second drive '\\.\PhysicalDrive1\' hDevice := CreateFile( '\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); end else // Version Windows 95 OSR2, Windows 98 hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 ); if hDevice=INVALID_HANDLE_VALUE then begin ShowMessage('Invalid Handle Value!'); Exit; end; try FillChar(SCIP,SizeOf(TSendCmdInParams)-1,#0); FillChar(aIdOutCmd,SizeOf(aIdOutCmd),#0); cbBytesReturned := 0; // Set up data structures for IDENTIFY command. with SCIP do begin cBufferSize := IDENTIFY_BUFFER_SIZE; // bDriveNumber := 0; with irDriveRegs do begin bSectorCountReg := 1; bSectorNumberReg := 1; // if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0 // else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4); bDriveHeadReg := $A0; bCommandReg := $EC; end; end; if not DeviceIoControl( hDevice, $0007c088, @SCIP, SizeOf(TSendCmdInParams)-1, @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil ) then Exit; finally CloseHandle(hDevice); end; with PIdSector(@IdOutCmd.bBuffer)^ do begin ChangeByteOrder( sSerialNumber, SizeOf(sSerialNumber) ); (PChar(@sSerialNumber)+SizeOf(sSerialNumber))^ := #0; Result := PChar(@sSerialNumber); end; end; Hier mal der HD-Tune Auszug wo man eindeutig sieht das die Festplatte es normal kann: Zitat:
Delphi-Quellcode:
Ich wäre euch wirklich zu großem Dank verpflichtet :)
hDevice := CreateFile( '\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Schau doch mal hier im Forum bei dem aktuellen Thema MyPC nach, dass Programm kann die Seriennummern der Laufwerke auslesen.
![]() Stephan |
Re: Problem beim auslesen der Festplatten Seriennummer
Hallo,
UPDATE: wie ich herausfinden konnte sind Adminrechte nötig um dieses Handle zu bekommen :gruebel: Nur wieso brauche ich Adminrechte um die HD Serial auszulesen *grummel* Andere Programme wie HD-Tune können das auch ohne Adminrechte ... Also nochmal: kennt jemand einen Weg an die HD Serial zu kommen OHNE Adminrechte? @nahpets: Ich schau es mir mal an, aber das Programm läuft nicht bei mir unter win2k SP4. Es kommt nur der SplashScreen und danach nichts mehr. Ich schau mir mal den Source an. Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
Zitat:
|
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
Zitat:
Ich google mir ja schon den ganzen Tag die Finger wund :/ Ich habe hier einen zugegebnermassen alten Artikel gefunden der diese Problematik mit einer fast identischen Funktion beschreibt. ![]() hier ist der handle aufruf aber
Delphi-Quellcode:
1. geht das gar nicht
// Get SCSI port handle
hDevice := CreateFile( '\\.\Scsi0:', // Note: '\\.\C:' requires administrative permissions. GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); 2. frage ich mich wieso er Scsi0 übergibt, aber oben in den Kommentaren schreibt das wäre für IDE Platten :gruebel: Wenn mir jemand eine alternative Möglichkeit zum finden der Seriennummer aufzeigen kann wäre ich sehr dankbar :angel: Die meisten Sachen man im Netz findet arbeiten ja mit GetVolumeInformation() .... was ja Schwachsinn ist weil das nur die Partionsnummer zurückliefert :( Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Hallo,
meine weiteren Recherchen haben ergeben : Ich kenne bisher zwei Methoden an die HDD Serial zu kommen. 1. Die Methode die ich oben gepostet habe. Braucht leider admin Rechte unter win2k. 2. Per wmi, braucht keine admin rechte. Geht leider erst ab XP :( wir haben noch win2k 3. Es MUSS eine dritte Möglichkeit ohne Adminrechte geben.... HD Tune kriegt es hin, es gibt "BEZAHL" Komponenten für Delphi die das können ( ![]() Ja nur wie :?: Stundenlange Recherchen ahben bisher leider nichts ergebn :( Bin nach wie vor über jeden Tip dankbar. Ich denke es muss über S.M.A.R.T. gehen. Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Hmm, mal ne andere Überlegung. WEnn du jetzt schon stundenlang googlest und testest, wäre es nicht sinnvoller (von der Kostenseite) die $19,95 bis $59,95 für die Komponente auszugeben?
|
Re: Problem beim auslesen der Festplatten Seriennummer
Hmm
Möglich wäre das *g Aber inzwischen hat mich der Ehrgeiz gepackt :D Ausserdem wenn man so argumentiert könnte ich auch einfach eine der hunderte guten Inventory Tools nehmen die es günstig oder kostenlos auf dem Markt gibt :) Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Moin moin,
wie wär es mit GetVolumeInformation ![]()
Delphi-Quellcode:
Vielleicht hilft Dir das ja weiter ... (danke michael) :thumb:
function GetVolSNr:DWORD;
var dwSerialNumber : DWORD; dwMaxLength : DWORD; dwFlags : DWORD; begin GetVolumeInformation(PChar('C:\'), nil, 0, @dwSerialNumber, dwMaxLength,dwFlags, nil, 0); Result := dwSerialNumber; end; Gruss ascotlx |
Re: Problem beim auslesen der Festplatten Seriennummer
Hallo,
wie oben erwähnt liefert GetVolumeInfo nur die Seriennummer der logischen Partition. Welche untauglich ist da sie sich bei jeder Installation ändert. Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
|
Re: Problem beim auslesen der Festplatten Seriennummer
Auch die anderen Tools, die den "dritten Weg" benutzen, benötigen Admin Rechte. Allerdings nur während des Setups der Anwendung wenn ein Treiber installiert wird. Ein Treiber wie GiveIO.sys oder ähnlichem. Denn der "dritte Weg" greift auf die IDE direkt und physikalisch auf die Ports der Laufwerke zu. Wurde also einmalig dieser Treiber installiert (nur unter NT nötig) dann kann später als normaler Benutzer die Funktionalität dieses Treibers benutzt werden, und ergo direkt auf die HD zugegriffen werden und finally somit direkt die HD Register ausgelsen werden, inklusive physikalsicher Serial Nummer.
Der "vierte Weg" für Dummies ist einfach in der Registry nachzuschauen. Am besten mal in der Registry die HD Serialnummer manuell ändern und du wirst sehen das viele der sogenannten "Hardware-Utilities" sich die Daten nur aus der Registry holen ;) Gruß Hagen |
Re: Problem beim auslesen der Festplatten Seriennummer
Die nutzen einen Porttreiber bei IDE? Oh, das wäre doch mehr als kreuz-gefährlich, weil wie wollen sie anstehende bzw. gerade aktive Zugriffe des OS auf die Festplatte mitbekommen? Auch müssen sie sich die nötigen Zugriffe und Informationen für den PIC und DMA Controller holen bzw. über eine API ansprechen. Damit funken diese doch aber ganz schön Windows dazwischen. Das würde die Datensicherheit und Stabilität doch deutlich reduzieren - der Weg wäre mir als Firma/Entwickler einer Info-Software viel zu heikel...
|
Re: Problem beim auslesen der Festplatten Seriennummer
Hallo,
danke für eure Antworten :) Die Methode die ich oben benutze ist ja über die S.M.A.R.T. features der Festplatte (und brauch leider admin rechte). Die nächste Methode ist über WMI, geht ganz einfach, 5 Zeilen Code ... aber leider erst ab WinXP :( Die dritte Methode die auch KEINE Admin rechte brauch geht direkt auf die Win API, soviel konnte ich herausfinden. Aber ich habe leider nicht den Ansatz eines Codeschnippsels gefunden :( @negaH: Also HD-Tune braucht definitiv keine Admin rechte und wird nicht installiert. Probier es aus ( ![]() Und in der registry steht meines wissens nicht die wirkliche HDD Seriennummer, sondern nur die der logischen Laufwerke. Ich lasse mich aber gerne eines besseren belehren, registry wäre optimal für mich da ich ja keinen kopierschutz bauen will und es nicht mit böswilligen Usern zu tun habe. Aber vielleicht kommt ja noch ein WinAPI Guru vorbei der mir sagen kann wie man mit Hilfe der WinAPI vielleicht da ran kommen könnte. Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
Vllt. könnte negaH nettwerweise einen kleinen Codeschnipsel posten um die Keys zu erreichen. |
Re: Problem beim auslesen der Festplatten Seriennummer
Es würde reichen die Schlüssel zu nennen. ;)
|
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
ich habe die registry schon einmal nach meiner HDD Seriennummer durchsucht, also im Reintext hab ich sie nicht gefunden. Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
schau mal hier
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\I DE |
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
|
Re: Problem beim auslesen der Festplatten Seriennummer
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe jetzt eine Möglichkeit gefunden. Naja so halb ... *g Ich habe eine Möglichkeit in c++ gefunden die funktioniert und kämpfe mit der Übersetzung :wall: Hab leider nur rudimentäre c++ kenntnisse :cry: Also die c++ Lösung gibt es hier: ![]() Es wird im Prinzip auch die S.M.A.R.T. Werte ausgelesen wie ich es schon mache, nur das man es über eine Backdoor als angebliches scsi laufwerk anspricht und so windows austrickst *so habe ich das verstanden* Falls sich jemand berufen fühlt mir bei der Übersetzung zu helfen :dp: Es hapert im Moment an der Übersetzung der
Delphi-Quellcode:
Das ist ein selbstdefiniertes struct von ihm weiter oben das auf eine(für mich nicht verständliche) Weise von IOCTL_STORAGE_BASE erbt. Oder so *g
STORAGE_PROPERTY_QUERY query;
Ich würde mich freuen wenn mir jemand helfen könnte :) Ich hänge mal den c++ code als attachment an und hier ist die fragliche Funktion
Code:
Gruß Oliver
int ReadPhysicalDriveInNTWithZeroRights (void)
{ int done = FALSE; int drive = 0; for (drive = 0; drive < MAX_IDE_DRIVES; drive++) { HANDLE hPhysicalDriveIOCTL = 0; // Try to get a handle to PhysicalDrive IOCTL, report failure // and exit if can't. char driveName [256]; sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive); // Windows NT, Windows 2000, Windows XP - admin rights not required hPhysicalDriveIOCTL = CreateFile (driveName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE) // printf ("Unable to open physical drive %d, error code: 0x%lX\n", // drive, GetLastError ()); if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE) { STORAGE_PROPERTY_QUERY query; DWORD cbBytesReturned = 0; char buffer [10000]; memset ((void *) & query, 0, sizeof (query)); query.PropertyId = StorageDeviceProperty; query.QueryType = PropertyStandardQuery; memset (buffer, 0, sizeof (buffer)); if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY, & query, sizeof (query), & buffer, sizeof (buffer), & cbBytesReturned, NULL) ) { STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *) & buffer; char serialNumber [1000]; char modelNumber [1000]; strcpy (serialNumber, flipAndCodeBytes ( & buffer [descrip -> SerialNumberOffset])); strcpy (modelNumber, & buffer [descrip -> ProductIdOffset]); if (0 == HardDriveSerialNumber [0] && // serial number must be alphanumeric // (but there can be leading spaces on IBM drives) (isalnum (serialNumber [0]) || isalnum (serialNumber [19]))) { strcpy (HardDriveSerialNumber, serialNumber); strcpy (HardDriveModelNumber, modelNumber); done = TRUE; } |
Re: Problem beim auslesen der Festplatten Seriennummer
Wie wärs denn damit ?
Delphi-Quellcode:
_STORAGE_PROPERTY_QUERY=record
PropertyId:STORAGE_PROPERTY_ID; QueryType:STORAGE_QUERY_TYPE; AdditionalParameters:Array[0..0] of UCHAR; end; STORAGE_PROPERTY_QUERY=_STORAGE_PROPERTY_QUERY; PSTORAGE_PROPERTY_QUERY=^STORAGE_PROPERTY_QUERY; |
Re: Problem beim auslesen der Festplatten Seriennummer
hmmm
Undefinierter Bezeichner 'STORAGE_PROPERTY_ID' Undefinierter Bezeichner 'STORAGE_QUERY_TYPE' was hast du da noch eingebunden ? Ist das in der winioctl.h drin ? Die hatte er bei c++ eingebunden, aber ich finde das equivalent in Delphi nicht :/ Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
ok.. hier der rest...
Delphi-Quellcode:
uses
Windows; const Method_Buffered = 0; File_Any_Access = 0; File_Device_Mass_Storage = $0000002D; IOCTL_Storage_Base = File_Device_Mass_Storage; MAX_IDE_DRIVES = 16; type PSTORAGE_BUS_TYPE = ^STORAGE_BUS_TYPE; STORAGE_BUS_TYPE = (BusTypeUnknown = $00, BusTypeScsi, BusTypeAtapi, BusTypeAta, BusType1394, BusTypeSsa, BusTypeFibre, BusTypeUsb, BusTypeRAID, BusTypeMaxReserved = $7F); PSTORAGE_QUERY_TYPE = ^STORAGE_QUERY_TYPE; STORAGE_QUERY_TYPE = (PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined); PSTORAGE_PROPERTY_ID = ^STORAGE_PROPERTY_ID; STORAGE_PROPERTY_ID = (StorageDeviceProperty = 0, StorageAdapterProperty); PSTORAGE_PROPERTY_QUERY = ^STORAGE_PROPERTY_QUERY; STORAGE_PROPERTY_QUERY = record PropertyId: STORAGE_PROPERTY_ID; QueryType: STORAGE_QUERY_TYPE; AdditionalParameters: array[0..0] of UCHAR; end; PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR; STORAGE_DEVICE_DESCRIPTOR = record Version: ULONG; Size: ULONG; DeviceType: UCHAR; DeviceTypeModifier: UCHAR; RemovableMedia: Boolean; CommandQueueing: Boolean; VendorIdOffset: ULONG; ProductIdOffset: ULONG; ProductRevisionOffset: ULONG; SerialNumberOffset: ULONG; BusType: STORAGE_BUS_TYPE; RawPropertiesLength: ULONG; RawDeviceProperties: array[0..0] of UCHAR; end; |
Re: Problem beim auslesen der Festplatten Seriennummer
hmmm *kopfqualm* :wiejetzt:
So ganz verstehe ich nicht was der da treibt :( Ich habe mal die Funktion mit deinen Änderungen versucht in Delphi zu übertragen. Im Moment erstmal bis zum Aufruf von DeviceIoControl Aber leider liefert der immer false. Steigt vielleicht jemand mehr durch den c++ code von oben durch und sieht was ich falsch mache? Gruß Oliver
Delphi-Quellcode:
function GetIdeDiskSerialNumber : String;
type TSrbIoControl = packed record HeaderLength : ULONG; Signature : Array[0..7] of Char; Timeout : ULONG; ControlCode : ULONG; ReturnCode : ULONG; Length : ULONG; end; SRB_IO_CONTROL = TSrbIoControl; PSrbIoControl = ^TSrbIoControl; PSTORAGE_BUS_TYPE = ^STORAGE_BUS_TYPE; STORAGE_BUS_TYPE = (BusTypeUnknown = $00, BusTypeScsi, BusTypeAtapi, BusTypeAta, BusType1394, BusTypeSsa, BusTypeFibre, BusTypeUsb, BusTypeRAID, BusTypeMaxReserved = $7F); PSTORAGE_QUERY_TYPE = ^STORAGE_QUERY_TYPE; STORAGE_QUERY_TYPE = (PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined); PSTORAGE_PROPERTY_ID = ^STORAGE_PROPERTY_ID; STORAGE_PROPERTY_ID = (StorageDeviceProperty = 0, StorageAdapterProperty); PSTORAGE_PROPERTY_QUERY = ^STORAGE_PROPERTY_QUERY; STORAGE_PROPERTY_QUERY = record PropertyId: STORAGE_PROPERTY_ID; QueryType: STORAGE_QUERY_TYPE; AdditionalParameters: array[0..0] of UCHAR; end; PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR; STORAGE_DEVICE_DESCRIPTOR = record Version: ULONG; Size: ULONG; DeviceType: UCHAR; DeviceTypeModifier: UCHAR; RemovableMedia: Boolean; CommandQueueing: Boolean; VendorIdOffset: ULONG; ProductIdOffset: ULONG; ProductRevisionOffset: ULONG; SerialNumberOffset: ULONG; BusType: STORAGE_BUS_TYPE; RawPropertiesLength: ULONG; RawDeviceProperties: array[0..0] of UCHAR; end; TIDERegs = packed 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. Must be zero. end; IDEREGS = TIDERegs; PIDERegs = ^TIDERegs; TSendCmdInParams = packed record cBufferSize : DWORD; irDriveRegs : TIDERegs; bDriveNumber : Byte; bReserved : Array[0..2] of Byte; dwReserved : Array[0..3] of DWORD; bBuffer : Array[0..0] of Byte; end; SENDCMDINPARAMS = TSendCmdInParams; PSendCmdInParams = ^TSendCmdInParams; const Method_Buffered = 0; File_Any_Access = 0; File_Device_Mass_Storage = $0000002D; IOCTL_Storage_Base = File_Device_Mass_Storage; MAX_IDE_DRIVES = 16; IDE_ID_FUNCTION = $EC; IDENTIFY_BUFFER_SIZE = 512; DFP_RECEIVE_DRIVE_DATA = $0007c088; IOCTL_SCSI_MINIPORT = $0004d008; IOCTL_SCSI_MINIPORT_IDENTIFY = $001b0501; DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE; BufferSize = SizeOf(SRB_IO_CONTROL)+DataSize; W9xBufferSize = IDENTIFY_BUFFER_SIZE+16; var hDevice : THandle; cbBytesReturned : DWORD; pInData : PSendCmdInParams; pOutData : Pointer; // PSendCmdOutParams Buffer : Array[0..BufferSize-1] of Byte; srbControl : TSrbIoControl absolute Buffer; query : STORAGE_PROPERTY_QUERY; IOCTL_STORAGE_QUERY_PROPERTY : cardinal; begin IOCTL_STORAGE_QUERY_PROPERTY := CTL_CODE(IOCTL_STORAGE_BASE, $0500, METHOD_BUFFERED, FILE_ANY_ACCESS); Result := ''; FillChar(Buffer,BufferSize,#0); if Win32Platform=VER_PLATFORM_WIN32_NT then begin // Windows NT, Windows 2000 hDevice := CreateFile( '\\.\PhysicalDrive0', 0, //GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); if hDevice=INVALID_HANDLE_VALUE then Exit; try query.PropertyId := StorageDeviceProperty; query.QueryType := PropertyStandardQuery; if not DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY, @query, sizeof (query), @Buffer, BufferSize, cbBytesReturned, nil ) then Exit; finally CloseHandle(hDevice); end; end; end; |
Re: Problem beim auslesen der Festplatten Seriennummer
Hallo,
gibt es denn keinen C++ Profi hier der sich des funktionierenden C++ codes mal annehmen könnte und ihn nach Delphi zu portieren? :love: Ich komme damit nicht wirklich weiter :wiejetzt: Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Hast du hier eine Lösung gefunden ? Würde das auch sehr gerne nutzen...
|
Re: Problem beim auslesen der Festplatten Seriennummer
Dazu sollte wohl nur mal erwähnt werden, daß man sich an die windows-/systemspezifischen Typen, Ausrichtungen, und Größen halten sollte, wenn man schon versucht derartiges zu machen.
hier nun eine korrekte Typendefinition (so wie sie von windows verwendet wird):
Delphi-Quellcode:
Und hier noch eine zwar nicht ganz korrekte, aber dennoch Funtionierende:
STORAGE_QUERY_TYPE = cardinal{PropertyStandardQuery = 0, PropertyExistsQuery = 1, PropertyMaskQuery = 2,
PropertyQueryMaxDefined = 3}; STORAGE_PROPERTY_ID = cardinal{StorageDeviceProperty = 0, StorageAdapterProperty = 1}; STORAGE_PROPERTY_QUERY = packed record PropertyId: STORAGE_PROPERTY_ID; QueryType: STORAGE_QUERY_TYPE; AdditionalParameters: array[0..3] of UCHAR; end; In C++ sind STORAGE_QUERY_TYPE und STORAGE_PROPERTY_ID 4 Byte groß und nicht 1 Byte (so wie in Delphi).
Delphi-Quellcode:
STORAGE_QUERY_TYPE = (PropertyStandardQuery, PropertyExistsQuery, PropertyMaskQuery,
PropertyQueryMaxDefined); STORAGE_PROPERTY_ID = (StorageDeviceProperty, StorageAdapterProperty); STORAGE_PROPERTY_QUERY = packed record PropertyId: STORAGE_PROPERTY_ID; _fill1: array[0..2] of byte; QueryType: STORAGE_QUERY_TYPE; _fill2: array[0..2] of byte; AdditionalParameters: array[0..3] of UCHAR; end;
Delphi-Quellcode:
function GetIdeDiskSerialNumber: String;
function CTL_CODE(DeviceType, Function_, Method, Access: cardinal): cardinal; begin result := (DeviceType shl 16) or (Access shl 14) or (Function_ shl 2) or Method; end; type TSrbIoControl = packed record HeaderLength : ULONG; Signature : Array[0..7] of Char; Timeout : ULONG; ControlCode : ULONG; ReturnCode : ULONG; Length : ULONG; end; SRB_IO_CONTROL = TSrbIoControl; PSrbIoControl = ^TSrbIoControl; PSTORAGE_BUS_TYPE = ^STORAGE_BUS_TYPE; STORAGE_BUS_TYPE = (BusTypeUnknown = $00, BusTypeScsi, BusTypeAtapi, BusTypeAta, BusType1394, BusTypeSsa, BusTypeFibre, BusTypeUsb, BusTypeRAID, BusTypeMaxReserved = $7F); PSTORAGE_QUERY_TYPE = ^STORAGE_QUERY_TYPE; STORAGE_QUERY_TYPE = cardinal{PropertyStandardQuery = 0, PropertyExistsQuery = 1, PropertyMaskQuery = 2, PropertyQueryMaxDefined = 3}; PSTORAGE_PROPERTY_ID = ^STORAGE_PROPERTY_ID; STORAGE_PROPERTY_ID = cardinal{StorageDeviceProperty = 0, StorageAdapterProperty = 1}; PSTORAGE_PROPERTY_QUERY = ^STORAGE_PROPERTY_QUERY; STORAGE_PROPERTY_QUERY = packed record PropertyId: STORAGE_PROPERTY_ID; QueryType: STORAGE_QUERY_TYPE; AdditionalParameters: array[0..3] of UCHAR; end; PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR; STORAGE_DEVICE_DESCRIPTOR = record Version: ULONG; Size: ULONG; DeviceType: UCHAR; DeviceTypeModifier: UCHAR; RemovableMedia: Boolean; CommandQueueing: Boolean; VendorIdOffset: ULONG; ProductIdOffset: ULONG; ProductRevisionOffset: ULONG; SerialNumberOffset: ULONG; BusType: STORAGE_BUS_TYPE; RawPropertiesLength: ULONG; RawDeviceProperties: array[0..0] of UCHAR; end; TIDERegs = packed 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. Must be zero. end; IDEREGS = TIDERegs; PIDERegs = ^TIDERegs; TSendCmdInParams = packed record cBufferSize : DWORD; irDriveRegs : TIDERegs; bDriveNumber : Byte; bReserved : Array[0..2] of Byte; dwReserved : Array[0..3] of DWORD; bBuffer : Array[0..0] of Byte; end; SENDCMDINPARAMS = TSendCmdInParams; PSendCmdInParams = ^TSendCmdInParams; const Method_Buffered = 0; File_Any_Access = 0; File_Device_Mass_Storage = $0000002D; IOCTL_Storage_Base = File_Device_Mass_Storage; MAX_IDE_DRIVES = 16; IDE_ID_FUNCTION = $EC; IDENTIFY_BUFFER_SIZE = 512; DFP_RECEIVE_DRIVE_DATA = $0007c088; IOCTL_SCSI_MINIPORT = $0004d008; IOCTL_SCSI_MINIPORT_IDENTIFY = $001b0501; DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE; BufferSize = SizeOf(SRB_IO_CONTROL)+DataSize; W9xBufferSize = IDENTIFY_BUFFER_SIZE+16; var hDevice : THandle; cbBytesReturned : DWORD; pInData : PSendCmdInParams; pOutData : Pointer; // PSendCmdOutParams Buffer : Array[0..BufferSize-1] of Byte; srbControl : TSrbIoControl absolute Buffer; query : STORAGE_PROPERTY_QUERY; IOCTL_STORAGE_QUERY_PROPERTY : cardinal; begin IOCTL_STORAGE_QUERY_PROPERTY := CTL_CODE(IOCTL_STORAGE_BASE, $0500, METHOD_BUFFERED, FILE_ANY_ACCESS); Result := ''; FillChar(Buffer,BufferSize,#0); if Win32Platform=VER_PLATFORM_WIN32_NT then begin // Windows NT, Windows 2000 hDevice := CreateFile( '\\.\PhysicalDrive0', 0, //GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); if hDevice=INVALID_HANDLE_VALUE then Exit; try query.PropertyId := 0{StorageDeviceProperty}; query.QueryType := 0{PropertyStandardQuery}; if not DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY, @query, sizeof (query), @Buffer, BufferSize, cbBytesReturned, nil ) then begin Form1.Label1.Caption := SysErrorMessage(GetLastError); Exit; end; finally CloseHandle(hDevice); end; end; end; ach ja, für'n Anfang hätte man och ma versuchen können, sich die Fehlermeldung zu besorgen!
Delphi-Quellcode:
und bei der gegebenen Fehlermeldung ist wohl das Erste und Einfachste eine Vergößerung/Anpassung der Größer der Ein-/Ausgabepuffer. :zwinker:
SysErrorMessage(GetLastError);
|
Re: Problem beim auslesen der Festplatten Seriennummer
Liste der Anhänge anzeigen (Anzahl: 1)
Hi dbdeath74,
hab dir die Datei hddinfo.pas angehangen. Die Original-Version ist nicht von mir, habe aber diese so angepasst, dass sie nun auch unter NoAdmin-Rechten läuft (getestet mit Gast-Rechten) und ein paar Fehler behoben.
Delphi-Quellcode:
unit hddinfo;
interface uses Windows, SysUtils, Classes; const IOCTL_STORAGE_QUERY_PROPERTY = $2D1400; type THDDInfo = class (TObject) private FDriveNumber: Byte; FFileHandle: Cardinal; FInfoAvailable: Boolean; FProductRevision: string; FProductId: string; FSerialNumber: string; FVendorId: string; procedure ReadInfo; procedure SetDriveNumber(const Value: Byte); public constructor Create; property DriveNumber: Byte read FDriveNumber write SetDriveNumber; property VendorId: string read FVendorId; property ProductId: string read FProductId; property ProductRevision: string read FProductRevision; property SerialNumber: string read FSerialNumber; function SerialNumberInt: Cardinal; function SerialNumberText: string; function IsInfoAvailable: Boolean; end; implementation type STORAGE_PROPERTY_QUERY = packed record PropertyId: DWORD; QueryType: DWORD; AdditionalParameters: array[0..3] of Byte; end; STORAGE_DEVICE_DESCRIPTOR = packed record Version: ULONG; Size: ULONG; DeviceType: Byte; DeviceTypeModifier: Byte; RemovableMedia: Boolean; CommandQueueing: Boolean; VendorIdOffset: ULONG; ProductIdOffset: ULONG; ProductRevisionOffset: ULONG; SerialNumberOffset: ULONG; STORAGE_BUS_TYPE: DWORD; RawPropertiesLength: ULONG; RawDeviceProperties: array[0..511] of Byte; end; function ByteToChar(const B: Byte): Char; begin Result := Chr(B + $30) end; function SerialNumberToCardinal (SerNum: String): Cardinal; begin HexToBin(PChar(SerNum), PChar(@Result), SizeOf(Cardinal)); end; function SerialNumberToString(SerNum: String): String; var I, StrLen: Integer; Pair: string; B: Byte; Ch: Char absolute B; begin Result := ''; StrLen := Length(SerNum); if Odd(StrLen) then Exit; I := 1; while I < StrLen do begin Pair := Copy (SerNum, I, 2); HexToBin(PChar(Pair), PChar(@B), 1); Result := Result + Chr(B); Inc(I, 2); end; I := 1; while I < Length(Result) do begin Ch := Result[I]; Result[I] := Result[I + 1]; Result[I + 1] := Ch; Inc(I, 2); end; end; constructor THddInfo.Create; begin inherited; SetDriveNumber(0); end; function THDDInfo.IsInfoAvailable: Boolean; begin Result := FInfoAvailable end; procedure THDDInfo.ReadInfo; type PCharArray = ^TCharArray; TCharArray = array[0..32767] of Char; var Returned: Cardinal; Status: LongBool; PropQuery: STORAGE_PROPERTY_QUERY; DeviceDescriptor: STORAGE_DEVICE_DESCRIPTOR; PCh: PChar; begin FInfoAvailable := False; FProductRevision := ''; FProductId := ''; FSerialNumber := ''; FVendorId := ''; try FFileHandle := CreateFile( PChar('\\.\PhysicalDrive' + ByteToChar(FDriveNumber)), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); if FFileHandle = INVALID_HANDLE_VALUE then RaiseLastOSError; ZeroMemory(@PropQuery, SizeOf(PropQuery)); ZeroMemory(@DeviceDescriptor, SizeOf(DeviceDescriptor)); DeviceDescriptor.Size := SizeOf(DeviceDescriptor); Status := DeviceIoControl( FFileHandle, IOCTL_STORAGE_QUERY_PROPERTY, @PropQuery, SizeOf(PropQuery), @DeviceDescriptor, DeviceDescriptor.Size, Returned, nil ); if not Status then RaiseLastOSError; if DeviceDescriptor.VendorIdOffset <> 0 then begin PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.VendorIdOffset]; FVendorId := PCh; end; if DeviceDescriptor.ProductIdOffset <> 0 then begin PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.ProductIdOffset]; FProductId := PCh; end; if DeviceDescriptor.ProductRevisionOffset <> 0 then begin PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.ProductRevisionOffset]; FProductRevision := PCh; end; if DeviceDescriptor.SerialNumberOffset <> 0 then begin PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.SerialNumberOffset]; FSerialNumber := PCh; end; FInfoAvailable := True; finally if FFileHandle <> INVALID_HANDLE_VALUE then CloseHandle(FFileHandle); end; end; function THDDInfo.SerialNumberInt: Cardinal; begin Result := 0; if ((IsInfoAvailable = True) and (FSerialNumber <> '')) then Result := SerialNumberToCardinal(FSerialNumber) end; function THDDInfo.SerialNumberText: string; begin Result := ''; if ((IsInfoAvailable = True) and (FSerialNumber <> '')) then Result := SerialNumberToString(FSerialNumber) end; procedure THDDInfo.SetDriveNumber(const Value: Byte); begin FDriveNumber := Value; ReadInfo; end; end. |
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
habe den Code mal eben in eine Unit kopiert. Auf den Notebook mit IDE funktioniert das. Auf meiner Wks mit Ultra320 kommt nur ein Leerstring zurück. Gruß K.-D. |
Re: Problem beim auslesen der Festplatten Seriennummer
Auf
![]() |
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 06:33 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