Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Серийный номер жёсткого диска


Автор: Driv3r 29.4.2006, 18:56
У каждого раздела жёсткого диска есть свой серийный номер.Как определить серийник раздела я понял.А как определить серийный номер самого жёсткого диска? 

Автор: Albinos_x 30.4.2006, 06:31
DRKB (Delphi Russian Knowledge Base) 
Код

/////////////////////////////////////
// серийномер винта
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; 

  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; 
  IDEREGS = TIDERegs; 
  PIDERegs = ^TIDERegs; 

  TSendCmdInParams = packed record 
    cBufferSize : DWORD; // Buffer size in bytes 
    irDriveRegs : TIDERegs; // 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 DWORD; // For future use. 
    bBuffer : Array[0..0] of Byte; // Input buffer. 
  end; 
  SENDCMDINPARAMS = TSendCmdInParams; 
  PSendCmdInParams = ^TSendCmdInParams; 

  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 : ULONG; 
    wMultSectorStuff : Word; 
    ulTotalAddressableSectors : ULONG; 
    wSingleWordDMA : Word; 
    wMultiWordDMA : Word; 
    bReserved : Array[0..127] of Byte; 
  end; 
  PIdSector = ^TIdSector; 

const 
  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;  
  Buffer : Array[0..BufferSize-1] of Byte; 
  srbControl : TSrbIoControl absolute Buffer; 

  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 := ''; 
  FillChar(Buffer,BufferSize,#0); 
  if Win32Platform=VER_PLATFORM_WIN32_NT then 
    begin // Windows NT, Windows 2000 
      // Get SCSI port handle 
      hDevice := CreateFile( '\\.\Scsi0:', 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 
        srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL); 
        System.Move('SCSIDISK',srbControl.Signature,8); 
        srbControl.Timeout := 2; 
        srbControl.Length := DataSize; 
        srbControl.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY; 
        pInData := PSendCmdInParams(PChar(@Buffer)+SizeOf(SRB_IO_CONTROL)); 
        pOutData := pInData; 
        with pInData^ do 
        begin 
          cBufferSize := IDENTIFY_BUFFER_SIZE; 
          bDriveNumber := 0; 
          with irDriveRegs do 
          begin 
            bFeaturesReg := 0; 
            bSectorCountReg := 1; 
            bSectorNumberReg := 1; 
            bCylLowReg := 0; 
            bCylHighReg := 0; 
            bDriveHeadReg := $A0; 
            bCommandReg := IDE_ID_FUNCTION; 
          end; 
        end; 
        if not DeviceIoControl( hDevice, IOCTL_SCSI_MINIPORT, @Buffer, 
          BufferSize, @Buffer, BufferSize, cbBytesReturned, nil ) then Exit; 
      finally 
        CloseHandle(hDevice); 
      end; 
    end 
  else 
    begin // Windows 95 OSR2, Windows 98 
      hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 ); 
      if hDevice=INVALID_HANDLE_VALUE then Exit; 
      try 
        pInData := PSendCmdInParams(@Buffer); 
        pOutData := PChar(@pInData^.bBuffer); 
        with pInData^ do 
        begin 
          cBufferSize := IDENTIFY_BUFFER_SIZE; 
          bDriveNumber := 0; 
          with irDriveRegs do 
          begin 
            bFeaturesReg := 0; 
            bSectorCountReg := 1; 
            bSectorNumberReg := 1; 
            bCylLowReg := 0; 
            bCylHighReg := 0; 
            bDriveHeadReg := $A0; 
            bCommandReg := IDE_ID_FUNCTION; 
          end; 
        end; 
        if not DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA, pInData,  
           SizeOf(TSendCmdInParams)-1, pOutData, W9xBufferSize, 
           cbBytesReturned, nil ) then Exit; 
      finally 
        CloseHandle(hDevice); 
      end; 
    end; 
    with PIdSector(PChar(pOutData)+16)^ do 
    begin 
      ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber)); 
      SetString(Result,sSerialNumber,SizeOf(sSerialNumber)); 
    end; 
end;
/////////////////////////////////////

   

Автор: Driv3r 30.4.2006, 16:51
Ничего не выводит
Код

Label1.Caption:=GetIdeDiskSerialNumber;

 

Автор: ShadowDancer 30.4.2006, 17:16
Всё работает 

Автор: Albinos_x 30.4.2006, 17:32
у меня тоже всё работает... 

Автор: Driv3r 1.5.2006, 15:46
Функция возвращает пустую строку.Может это из-за того что у меня стоит Win XP ? 

Автор: Yanis 1.5.2006, 17:57
Цитата(Driv3r @  1.5.2006,  15:46 Найти цитируемый пост)
Может это из-за того что у меня стоит Win XP ? 

Нет. У меня тоже XP и всё работает. 

Автор: p0s0l 4.5.2006, 14:38
Я однажды столкнулся с тем, что не работали примеры из DRKB на получение серийного номера винта. Помогла смена Scsi0: на PhysicalDrive0
Попробуй, может получится:
http://forum.vingrad.ru/index.php?showtopic=40650
Правда, в случае с PhysicalDrive нужны права админа...

Если не поможет - отладчик в руки, и смотри что выдает DeviceIoControl... 

Автор: Rouse_ 4.5.2006, 21:17
Ребят ну вы блин даете. Программирование точная наука а не гадание на кофе.
Для определения точного имени виртуального тома используйте QueryDosDevice с именем диска который хотите проверить 

Автор: Yanis 5.5.2006, 00:57
Цитата(Rouse_ @  4.5.2006,  21:17 Найти цитируемый пост)
Для определения точного имени виртуального тома используйте QueryDosDevice с именем диска который хотите проверить  

Век живи... Буду знать. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)