// (c) Alex Konshin Mailto: alexk@mtgroup.ru 30 Jul 2000
PROGRAM
Idesn
;
// Purpose: Simple Console Application That Extract First First Ide Disk Serial Number.
{$ Apptype console}
Uses
Windows
,
Sysutils
;
// only for Win32Platform and SySerrorMessage
/ / -------------------------------------------------------------------------------------------- -------------
FUNCTION
GetidiskSerialNumber
:
String
;
Type
Tsrbiocontrol
=
packed
Record
Headerlength
:
Ulong
;
Signature
:
Array
[
0..7
]
Of
Charr
;
TIMEOUT
:
Ulong
;
Controlcode
:
Ulong
;
Returncode
:
Ulong
;
Length
:
Ulong
;
end
;
SRB_IO_CONTROL
=
Tsrbiocontrol
;
Psrbiocontrol
=
^
Tsrbiocontrol
;
TIDEREGS
=
packed
Record
BfeatureSreg
:
Byte
;
// use 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 for Future Use. Must be Zero.
end
;
Idegegs
=
TIDEREGS
;
PideRegs
=
^
TIDEREGS
;
Tsendcmdinparams
=
packed
Record
CBuffersize
:
DWORD
;
// buffer size in bytes
IrdriveRegs
:
TIDEREGS
;
// Structure with Drive Register Values.
BDRIVENUMBER
:
Byte
;
// Physical Drive Number to Send Command to (0, 1, 2, 3).
BRESERVED
:
Array
[
0..2
]
Of
Byte
;
// Reserved for Future Expansion.
DWRESERVED
:
Array
[
0..3
]
Of
DWORD
;
// forfuture us.
BBuffer
:
Array
[
0..0
]
Of
Byte
;
// Input buffer.
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
Charr
;
WBuffertype
:
Word
;
WBuffersize
:
Word
;
Weccsize
:
Word
;
Sfirmwarerev
:
Array
[
0..7
]
Of
Charr
;
Smodelnumber
:
Array
[
0..39
]
Of
Charr
;
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
;
// psendcmdinparams;
Buffer
:
Array
[
0 ..
Buffersize
-
1
]
Of
Byte
;
SRBControl
:
Tsrbiocontrol
Absolute
Buffer
;
Procedure
Changebyteorder
(
VAR
Data
;
Size
:
Integer
);
VAR
Ptr
:
Pchar
;
i
:
Integer
;
c
:
Charr
;
Begin
Ptr
: =
@
Data
;
for
i
: =
0
TO
(
Size
SHR
1
)
1
DO
Begin
c
: =
Ptr
^;
Ptr
^
: =
(
Ptr
1
^;
(
Ptr
1
) ^
: =
c
;
Incc
(
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:'
,
// Note: '//./c:' Required Administrative Permissions.
Generic_read
oral
Generic_Write
,
FILE_SHARE_READ
oral
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
: =
Pchar
(@
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
;
/ / =========================================================================================================================================================================================== =============
VAR
s
:
String
;
RC
:
DWORD
;
Begin
s
: =
GetidiskSerialNumber
;
IF
s
=
'' '
THEN
Begin
RC
: =
Getlasterror;
IF
RC
=
0
THEN
Writeln
(
'Ide Drive Is Not Support Smart Feature'
)
Else
Writeln
(
SYSERRORMESSAGE
(
RC
));
end
Else
Begin
Writeln
(
'Disk Serial Number:' ''
,
s
,
'' ''
);
Readln
;
end
;
end
.