Содержание материала

 

Посмотри функцию 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

 Поличение серийного номера 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,  


Code:

 

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;


Пример использования:

Code:

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, Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра., Boston, USA

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить