GetIdeDiskSerialNumber

// (c) Alex Konshin    mailto:alexk@mtgroup.ru      30 jul 2000

program  IdeSN ;

// PURPOSE: Simple console application that extract first IDE disk serial number.

{$APPTYPE CONSOLE}

uses
   Windows ,
   SysUtils ;  // only for Win32Platform and SysErrorMessage

//-------------------------------------------------------------
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:' ,  // Note: '//./C:' required administrative permissions.
         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  begin
     WriteLn ( 'Disk serial number: ''' ,  s , '''' );
     Readln ;
   end ;
end .
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值