Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#27

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 16. Dez 2006, 11:05
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:
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;
Und hier noch eine zwar nicht ganz korrekte, aber dennoch Funtionierende:
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!
SysErrorMessage(GetLastError); und bei der gegebenen Fehlermeldung ist wohl das Erste und Einfachste eine Vergößerung/Anpassung der Größer der Ein-/Ausgabepuffer.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat