执行的函数为getscsisn,在NT下正常,但是在2000下或者98/Me下,出错。
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. Must be zero.
; end;
; IDEREGS = TIDERegs;
; PIDERegs = ^TIDERegs;
; TSendCmdInParams = packed record
; ; cBufferSize: DWORD;
; ; irDriveRegs: TIDERegs;
; ; bDriveNumber: Byte;
; ; bReserved: array[0..2] of Byte;
; ; dwReserved: array[0..3] of DWORD;
; ; bBuffer: array[0..0] of Byte;
; 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; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;// PSendCmdOutParams
; 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 := @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;
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..255] 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;
function getscsisn: string;
const
; hDevice: THandle = 0;
var
; sSerNum, sDeviceName: string;
; rc: DWORD;
begin
; sDeviceName := 'C:';
; hDevice := GetDeviceHandle(sDeviceName);
; if hDevice <> INVALID_HANDLE_VALUE then
; try
; ; SSerNum := trim(GetIdeDiskSerialNumber);
; ; if SSernum = #39 then
; ; ; sSerNum := trim(ScsiHddSerialNumber(hDevice));
; ; result := sSerNum;
; finally
; ; CloseHandle(hDevice);
; end;
end;