Mega Code Archive

 
Categories / Delphi / Hardware
 

SCSI 2 device serial number

Title: SCSI-2 device serial number Question: For IDE harddisk you can use S.M.A.R.T. API function for extracting serial number. For SCSI it does not work. Answer: program ScsiSN; // PURPOSE: Simple console application that display SCSI harddisk serial number {$APPTYPE CONSOLE} uses Windows, SysUtils; //------------------------------------------------------------- function GetDeviceHandle( sDeviceName : String ) : THandle; begin Result := CreateFile( PChar('\\.\'+sDeviceName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ) end; //------------------------------------------------------------- function ScsiHddSerialNumber( DeviceHandle : THandle ) : String; {$ALIGN ON} type TScsiPassThrough = record Length : Word; ScsiStatus : Byte; PathId : Byte; TargetId : Byte; Lun : Byte; CdbLength : Byte; SenseInfoLength : Byte; DataIn : Byte; DataTransferLength : ULONG; TimeOutValue : ULONG; DataBufferOffset : DWORD; SenseInfoOffset : ULONG; Cdb : Array[0..15] of Byte; end; TScsiPassThroughWithBuffers = record spt : TScsiPassThrough; bSenseBuf : Array[0..31] of Byte; bDataBuf : Array[0..191] of Byte; end; {ALIGN OFF} var dwReturned : DWORD; len : DWORD; Buffer : Array[ 0..SizeOf(TScsiPassThroughWithBuffers)+ SizeOf(TScsiPassThrough)-1] of Byte; sptwb : TScsiPassThroughWithBuffers absolute Buffer; begin Result := ''; FillChar(Buffer,SizeOf(Buffer),#0); with sptwb.spt do begin Length := SizeOf(TScsiPassThrough); CdbLength := 6; // CDB6GENERIC_LENGTH SenseInfoLength := 24; DataIn := 1; // SCSI_IOCTL_DATA_IN DataTransferLength := 192; TimeOutValue := 2; DataBufferOffset := PChar(@sptwb.bDataBuf)-PChar(@sptwb); SenseInfoOffset := PChar(@sptwb.bSenseBuf)-PChar(@sptwb); Cdb[0] := $12; // OperationCode := SCSIOP_INQUIRY; Cdb[1] := $01; // Flags := CDB_INQUIRY_EVPD; Vital product data Cdb[2] := $80; // PageCode Unit serial number Cdb[4] := 192; // AllocationLength end; len := sptwb.spt.DataBufferOffset+sptwb.spt.DataTransferLength; if DeviceIoControl( DeviceHandle, $0004d004, @sptwb, SizeOf(TScsiPassThrough), @sptwb, len, dwReturned, nil ) and ((PChar(@sptwb.bDataBuf)+1)^=#$80) then SetString( Result, PChar(@sptwb.bDataBuf)+4, Ord((PChar(@sptwb.bDataBuf)+3)^) ); end; //============================================================= var hDevice : THandle = 0; sSerNum, sDeviceName : String; begin sDeviceName := ParamStr(1); if sDeviceName='' then begin WriteLn; WriteLn('Display SCSI-2 device serial number.'); WriteLn; WriteLn('Using:'); WriteLn; if Win32Platform=VER_PLATFORM_WIN32_NT then // Windows NT/2000 WriteLn(' ScsiSN PhysicalDrive0') else WriteLn(' ScsiSN C:'); WriteLn(' ScsiSN Cdrom0'); WriteLn(' ScsiSN Tape0'); WriteLn; Exit; end; hDevice := GetDeviceHandle(sDeviceName); if hDevice=INVALID_HANDLE_VALUE then WriteLn('Error on GetDeviceHandle: ',SysErrorMessage(GetLastError)) else try sSerNum := ScsiHddSerialNumber(hDevice); if sSerNum='' then WriteLn('Error on DeviceIoControl: ', SysErrorMessageGetLastError)) else WriteLn('Device '+sDeviceName +' serial number = "',sSerNum,'"'); finally CloseHandle(hDevice); end; end. // For more information about SCSI commands: // ftp://ftp.t10.org/t10/drafts/scsi-1/ // ftp://ftp.t10.org/t10/drafts/spc/ // ftp://ftp.t10.org/t10/drafts/spc2/