{
获取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
=
0
then
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
=
packed
record
bFeaturesReg: BYTE;
bSectorCountReg: BYTE;
bSectorNumberReg: BYTE;
bCylLowReg: BYTE;
bCylHighReg: BYTE;
bDriveHeadReg: BYTE;
bCommandReg: BYTE;
bReserved: BYTE;
end
;
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
;
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: DWORD;
wMultSectorStuff: Word;
ulTotalAddressableSectors: DWORD;
wSingleWordDMA: Word;
wMultiWordDMA: Word;
bReserved:
array
[
0
..
127
]
of
BYTE;
end
;
PIdSector
=
^TIdSector;
TDriverStatus
=
packed
record
bDriverError: Byte;
bIDEStatus: Byte;
bReserved:
array
[
0
..
1
]
of
Byte;
dwReserved:
array
[
0
..
1
]
of
DWORD;
end
;
TSendCmdOutParams
=
packed
record
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 :
=
0
to
(Size
shr
1
)
-
1
do
begin
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
do
begin
cBufferSize :
=
IDENTIFY_BUFFER_SIZE;
with
irDriveRegs
do
begin
bSectorCountReg :
=
1
;
bSectorNumberReg :
=
1
;
bDriveHeadReg :
=
$A0;
bCommandReg :
=
$EC;
end
;
end
;
if
not
DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams)
-
1
,
@aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned,
nil
)
then
Exit;
finally
CloseHandle(hDevice);
end
;
with
PIdSector(@IdOutCmd.bBuffer)^
do
begin
ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
(Pchar(@sSerialNumber)
+
SizeOf(sSerialNumber))^ :
=
#
0
;
Result :
=
Pchar(@sSerialNumber);
end
;
end
;