获取磁盘序列号 <br>摘 要:不是取得卷标号,而是物理ID号<br>关键字:磁盘序列号<br>类 别:系统控制<br> <br> <br>type<br> MIDPtr = ^MIDRec;<br> MIDRec = Record<br> InfoLevel: word;<br> SerialNum: LongInt;<br> VolLabel: Packed Array [0..10] of Char;<br> FileSysType: Packed Array [0..7] of Char;<br> end;<br><br>function GetDriveSerialNum(MID: MIDPtr; drive: Word): Boolean; assembler;<br>asm<br> push DS { Just for safety, I dont think its really needed }<br> mov ax,440Dh { Function Get Media ID }<br> mov bx,drive { drive no (0-Default, 1-A ...) }<br> mov cx,0866h { category and minor code }<br> lds dx,MID { Load pointeraddr. }<br> call DOS3Call { Supposed to be faster than INT 21H }<br> jc @@err<br> mov al,1 { No carry so return TRUE }<br> jmp @@ok<br> @@err:<br> mov al,0 { Carry set so return FALSE }<br> @@ok:<br> pop DS { Restore DS, were not supposed to change it }<br>end;<br><br>procedure TForm1.NrBtnClick(Sender: TObject);<br>var<br> Info: MIDRec;<br>begin<br> Info.InfoLevel:=0; { Information Level }<br> If GetDriveSerialNum(@Info,0) then { Do something with it... }<br> ListBox.Items.Add(IntToStr(Info.SerialNum)+' '+Info.VolLabel);<br>end;<br><br><br><br>--------------------------------------------------------------------------------<br>BOOL GetVolumeInformation(<br><br> LPCTSTR lpRootPathName, // address of root directory of the file system<br> LPTSTR lpVolumeNameBuffer, // address of name of the volume<br> DWORD nVolumeNameSize, // length of lpVolumeNameBuffer<br> LPDWORD lpVolumeSerialNumber, // address of volume serial number<br> LPDWORD lpMaximumComponentLength, // address of system's maximum filename length<br> LPDWORD lpFileSystemFlags, // address of file system flags<br> LPTSTR lpFileSystemNameBuffer, // address of name of file system<br> DWORD nFileSystemNameSize // length of lpFileSystemNameBuffer<br>  
;<br><br><br><br>--------------------------------------------------------------------------------<br>获取SCSI硬盘序列号<br><br>问题提出/摘要:<br><br>对于IDE硬盘,你可以使用S.M.A.R.T. API的函数来获取序列号。但对SCSI硬盘,它无法工作。但我们可以使用DeviceIoControl来获取DeviceIoControl设备序列号.<br><br> <br><br> <br><br>回答:<br><br> 下面是代码:<br><br> program ScsiSN;<br><br> <br><br> // 目的:简单的控制台程序来显示SCSI硬盘的序列号<br><br> <br><br> {$APPTYPE CONSOLE}<br><br> <br><br> uses<br><br> Windows, SysUtils;<br><br> <br><br> //-------------------------------------------------------------<br><br> function GetDeviceHandle( sDeviceName : String ) : THandle;<br><br> begin<br><br> Result := CreateFile( PChar('//./'+sDeviceName),<br><br> GENERIC_READ or GENERIC_WRITE,<br><br> FILE_SHARE_READ or FILE_SHARE_WRITE,<br><br> nil, OPEN_EXISTING, 0, 0 )<br><br> end;<br><br> <br><br> //-------------------------------------------------------------<br><br> function ScsiHddSerialNumber( DeviceHandle : THandle ) : String;<br><br> {$ALIGN ON}<br><br> type<br><br> TScsiPassThrough = record<br><br> Length : Word;<br><br> ScsiStatus : Byte;<br><br> PathId : Byte;<br><br> TargetId : Byte;<br><br> Lun : Byte;<br><br> CdbLength : Byte;<br><br> SenseInfoLength : Byte;<br><br> DataIn : Byte;<br><br> DataTransferLength : ULONG;<br><br> TimeOutValue : ULONG;<br><br> DataBufferOffset : DWORD;<br><br> SenseInfoOffset : ULONG;<br><br> Cdb : Array[0..15] of Byte;<br><br> end;<br><br> TScsiPassThroughWithBuffers = record<br><br> spt : TScsiPassThrough;<br><br> bSenseBuf : Array[0..31] of Byte;<br><br> bDataBuf : Array[0..191] of Byte;<br><br> end;<br><br> {ALIGN OFF}<br><br> var dwReturned : DWORD;<br><br> len : DWORD;<br><br> Buffer : Array[0..255] of Byte;<br><br> sptwb : TScsiPassThroughWithBuffers absolute Buffer;<br><br> begin<br><br> Result := '';<br><br> FillChar(Buffer,SizeOf(Buffer),#0);<br><br> with sptwb.spt do<br><br> begin<br><br> Length := SizeOf(TScsiPassThrough);<br><br> CdbLength := 6; // CDB6GENERIC_LENGTH<br><br> SenseInfoLength := 24;<br><br> DataIn := 1; // SCSI_IOCTL_DATA_IN<br><br> DataTransferLength := 192;<br><br> TimeOutValue := 2;<br><br> DataBufferOffset := PChar(@sptwb.bDataBuf)-PChar(@sptwb);<br><br> SenseInfoOffset := PChar(@sptwb.bSenseBuf)-PChar(@sptwb);<br><br> Cdb[0] := $12; // OperationCode := SCSIOP_INQUIRY;<br><br> Cdb[1] := $01; // Flags := CDB_INQUIRY_EVPD; Vital product data<br><br> Cdb[2] := $80; // PageCode Unit serial number<br><br> Cdb[4] := 192; // AllocationLength<br><br> end;<br><br> len := sptwb.spt.DataBufferOffset+sptwb.spt.DataTransferLength;<br><br> if DeviceIoControl( DeviceHandle, $0004d004, @sptwb, SizeOf(TScsiPassThrough), @sptwb, len, dwReturned, nil )<br><br> and ((PChar(@sptwb.bDataBuf)+1)^=#$80)<br><br> then<br><br> SetString( Result, PChar(@sptwb.bDataBuf)+4,<br><br> Ord((PChar(@sptwb.bDataBuf)+3)^) );<br><br> end;<br><br> <br><br> <br><br> //=============================================================<br><br> var<br><br> hDevice : THandle = 0;<br><br> sSerNum, sDeviceName : String;<br><br> <br><br> begin<br><br> sDeviceName := ParamStr(1);<br><br> if sDeviceName='' then<br><br> begin<br><br> WriteLn;<br><br> WriteLn('Display SCSI-2 device serial number.');<br><br> WriteLn;<br><br> WriteLn('Using:');<br><br> WriteLn;<br><br> if Win32Platform=VER_PLATFORM_WIN32_NT then // Windows NT/2000<br><br> WriteLn(' ScsiSN PhysicalDrive0')<br><br> else<br><br> WriteLn(' ScsiSN C:');<br><br> WriteLn(' ScsiSN Cdrom0');<br><br> WriteLn(' ScsiSN Tape0');<br><br> WriteLn;<br><br> Exit;<br><br> end;<br><br> hDevice := GetDeviceHandle(sDeviceName);<br><br> if hDevice=INVALID_HANDLE_VALUE then<br><br> WriteLn('Error on GetDeviceHandle: ',SysErrorMessage(GetLastError))<br><br> else<br><br> try<br><br> sSerNum := ScsiHddSerialNumber(hDevice);<br><br> if sSerNum='' then<br><br> WriteLn('Error on DeviceIoControl: ',<br><br> SysErrorMessageGetLastError))<br><br> else<br><br> WriteLn('Device '+sDeviceName<br><br> +' serial number = "',sSerNum,'"');<br><br> finally<br><br> CloseHandle(hDevice);<br><br> end;<br><br> end.<br><br> <br><br> // 以下站点可获取更多关于SCSI命令的信息:<br><br> // ftp://ftp.t10.org/t10/drafts/scsi-1/<br><br> <br><br> // ftp://ftp.t10.org/t10/drafts/spc/<br><br> <br><br> // ftp://ftp.t10.org/t10/drafts/spc2/ <br><br><br><br>