Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Информация о физических дисках

01.01.2007

Посмотри функцию DeviceIoControl - может там что получиться. Я ее мало использовал, но что-то там было.

Там есть ссылка на CreateFile - эта функция под NT может действительно вернуть хэндл на физический диск.

You can use the CreateFile function to open a disk drive or a partition on a disk drive. The function returns a handle to the disk device; that handle can be used with the DeviceIOControl function.

Автор: AntonSaburov

Взято с Vingrad.ru https://forum.vingrad.ru


{ **** UBPFD *********** by delphibase.endimus.com ****

>> Поличение серийного номера IDE диска.

Функция получает серийный номер первого физического диска IDE (не серийный номер тома!).

Используется S.M.A.R.T. API, а под Windows NT/2K/XP запрос производится не напрямую к диску, а через miniport драйвер контроллера, что позволяет читать серийный номер не имея прав администратора.

Функция может не работать, если первый контролер в системе не ATA или если первое устройство не является винчестером, который поддерживает SMART (современные винчестеры поддерживают).

Если Вы хотите получить другие параметры диска/других дисков, то смотрите пример IdeInfo2 с моего сайта.

На Windows 9x требует наличия драйвера smartvsd.vxd (должен быть в стандартной поставке), просто скопируйте его в \windows\system\iosubsys и перезагрузите компьютер.

Зависимости: Windows, SysUtils

Автор:       Alex Konshin, akonshin@earthlink.net, Boston, USA

Copyright:   http://home.earthlink.net/~akonshin/index.htm

Дата:        30 декабря 2002 г.

 
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; // PSendCmdInParams;
 
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;
Пример использования:

var s : String;
    rc
: DWORD;
begin
  s
:= GetIdeDiskSerialNumber;
 
if s='' then
   
begin
      rc
:= GetLastError;
     
if rc=0 then WriteLn('IDE drive is not support SMART feature')
     
else WriteLn(SysErrorMessage(rc));
   
end
 
else WriteLn('Disk serial number: ''', s,'''');
end.

Автор:       Alex Konshin, akonshin@earthlink.net, Boston, USA