获取硬盘序列号(IDE,SATA,SCSI)
{
获取SCSI硬盘出厂系列号
需要系统管理员权限,不支持磁盘阵列
这里只取了第0个或第1个硬盘的序列号
}
function GetScsiSerialNumber(const i: smallint): string;
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;
var
dwReturned: DWORD;
len: DWORD;
Buffer: array[0..SizeOf(TScsiPassThroughWithBuffers) + SizeOf(TScsiPassThrough) -1] of Byte;
sptwb: TScsiPassThroughWithBuffers absolute Buffer;
hDevice: thandle;
begin
Result :='';
if SysUtils.win32Platform = VER_PLATFORM_WIN32_NT then
begin
if i =0then
hDevice := CreateFile('\\.\PhysicalDrive0',
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, 0, 0)
else
hDevice := CreateFile('\\.\PhysicalDrive1',
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, 0, 0);
end
else exit;
if hDevice = invalid_handle_value then exit;
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(hDevice, $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;
{
获取IDE和SATA硬盘出厂系列号
需要系统管理员权限,不支持磁盘阵列
这里只取了第0个硬盘的序列号,要取其它硬盘只需要改变PhysicalDrive0后的数字
}
function GetIdeSerialNumber: pchar;
const IDENTIFY_BUFFER_SIZE =512;
type
TIDERegs =packedrecord
bFeaturesReg: BYTE;
bSectorCountReg: BYTE;
bSectorNumberReg: BYTE;
bCylLowReg: BYTE;
bCylHighReg: BYTE;
bDriveHeadReg: BYTE;
bCommandReg: BYTE;
bReserved: BYTE;
end;
TSendCmdInParams =packedrecord
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;
TIdSector =packedrecord
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: DWORD;
wMultSectorStuff: Word;
ulTotalAddressableSectors: DWORD;
wSingleWordDMA: Word;
wMultiWordDMA: Word;
bReserved: array[0..127] of BYTE;
end;
PIdSector = ^TIdSector;
TDriverStatus =packedrecord
bDriverError: Byte;
bIDEStatus: Byte;
bReserved: array[0..1] of Byte;
dwReserved: array[0..1] of DWORD;
end;
TSendCmdOutParams =packedrecord
cBufferSize: DWORD;
DriverStatus: TDriverStatus;
bBuffer: array[0..0] of BYTE;
end;
procedure ChangeByteOrder(var Data; Size: Integer);
var
ptr: Pchar;
i: Integer;
c: Char;
begin
ptr := @Data;
for I :=0to (Size shr1) -1dobegin
c := ptr^;
ptr^ := (ptr +1)^;
(ptr +1)^ := c;
Inc(ptr, 2);
end;
end;
var
hDevice: Thandle;
cbBytesReturned: DWORD;
SCIP: TSendCmdInParams;
aIdOutCmd: array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE -1) -1] of Byte;
IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;
begin
Result :='';
if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then
// Windows NT, Windows 2000
hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0)
else
// Version Windows 95 OSR2, Windows 98
hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
if hDevice = INVALID_HANDLE_VALUE then Exit;
try
FillChar(SCIP, SizeOf(TSendCmdInParams) -1, #0);
FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);
cbBytesReturned :=0;
with SCIP dobegin
cBufferSize := IDENTIFY_BUFFER_SIZE;
with irDriveRegs dobegin
bSectorCountReg :=1;
bSectorNumberReg :=1;
bDriveHeadReg := $A0;
bCommandReg := $EC;
end;
end;
ifnot DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams) -1,
@aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil) then Exit;
finally
CloseHandle(hDevice);
end;
with PIdSector(@IdOutCmd.bBuffer)^ dobegin
ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
(Pchar(@sSerialNumber) + SizeOf(sSerialNumber))^ := #0;
Result := Pchar(@sSerialNumber);
end;
end;
获取SCSI硬盘出厂系列号
需要系统管理员权限,不支持磁盘阵列
这里只取了第0个或第1个硬盘的序列号
}
function GetScsiSerialNumber(const i: smallint): string;
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;
var
dwReturned: DWORD;
len: DWORD;
Buffer: array[0..SizeOf(TScsiPassThroughWithBuffers) + SizeOf(TScsiPassThrough) -1] of Byte;
sptwb: TScsiPassThroughWithBuffers absolute Buffer;
hDevice: thandle;
begin
Result :='';
if SysUtils.win32Platform = VER_PLATFORM_WIN32_NT then
begin
if i =0then
hDevice := CreateFile('\\.\PhysicalDrive0',
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, 0, 0)
else
hDevice := CreateFile('\\.\PhysicalDrive1',
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, 0, 0);
end
else exit;
if hDevice = invalid_handle_value then exit;
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(hDevice, $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;
{
获取IDE和SATA硬盘出厂系列号
需要系统管理员权限,不支持磁盘阵列
这里只取了第0个硬盘的序列号,要取其它硬盘只需要改变PhysicalDrive0后的数字
}
function GetIdeSerialNumber: pchar;
const IDENTIFY_BUFFER_SIZE =512;
type
TIDERegs =packedrecord
bFeaturesReg: BYTE;
bSectorCountReg: BYTE;
bSectorNumberReg: BYTE;
bCylLowReg: BYTE;
bCylHighReg: BYTE;
bDriveHeadReg: BYTE;
bCommandReg: BYTE;
bReserved: BYTE;
end;
TSendCmdInParams =packedrecord
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;
TIdSector =packedrecord
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: DWORD;
wMultSectorStuff: Word;
ulTotalAddressableSectors: DWORD;
wSingleWordDMA: Word;
wMultiWordDMA: Word;
bReserved: array[0..127] of BYTE;
end;
PIdSector = ^TIdSector;
TDriverStatus =packedrecord
bDriverError: Byte;
bIDEStatus: Byte;
bReserved: array[0..1] of Byte;
dwReserved: array[0..1] of DWORD;
end;
TSendCmdOutParams =packedrecord
cBufferSize: DWORD;
DriverStatus: TDriverStatus;
bBuffer: array[0..0] of BYTE;
end;
procedure ChangeByteOrder(var Data; Size: Integer);
var
ptr: Pchar;
i: Integer;
c: Char;
begin
ptr := @Data;
for I :=0to (Size shr1) -1dobegin
c := ptr^;
ptr^ := (ptr +1)^;
(ptr +1)^ := c;
Inc(ptr, 2);
end;
end;
var
hDevice: Thandle;
cbBytesReturned: DWORD;
SCIP: TSendCmdInParams;
aIdOutCmd: array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE -1) -1] of Byte;
IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;
begin
Result :='';
if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then
// Windows NT, Windows 2000
hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0)
else
// Version Windows 95 OSR2, Windows 98
hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
if hDevice = INVALID_HANDLE_VALUE then Exit;
try
FillChar(SCIP, SizeOf(TSendCmdInParams) -1, #0);
FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);
cbBytesReturned :=0;
with SCIP dobegin
cBufferSize := IDENTIFY_BUFFER_SIZE;
with irDriveRegs dobegin
bSectorCountReg :=1;
bSectorNumberReg :=1;
bDriveHeadReg := $A0;
bCommandReg := $EC;
end;
end;
ifnot DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams) -1,
@aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil) then Exit;
finally
CloseHandle(hDevice);
end;
with PIdSector(@IdOutCmd.bBuffer)^ dobegin
ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
(Pchar(@sSerialNumber) + SizeOf(sSerialNumber))^ := #0;
Result := Pchar(@sSerialNumber);
end;
end;