The hard disk serial number (serial number) is not equal to the volume name. Although the latter is easy to obtain, it will be overwritten after formatting the partition, which is unreliable. Unfortunately, many friends often cannot tell this point.
To obtain the physical serial number of the hard disk, You Can Use WMI, that is, win32_physicalmedia.serialnumber. Unfortunately, WMI of Windows 98/me does not support this class, and an exception occurs during access.
Inspired by Lu Lin's example, we can also use S. m. a. r. t. interface. You can call the deviceiocontrol () API in ring3 to obtain the hard disk information without writing VxD or driver. In this way, this problem is solved. I have encapsulated it and used a lot of P/invoke technology, a complete library. Windows 98-2003 is supported.
It is easy to use:
Harddiskinfo HDD = atapidevice. gethddinfo (0); // the first hard disk
Console. writeline ("module number: {0}", HDD. modulenumber );
Console. writeline ("serial number: {0}", HDD. serialnumber );
Console. writeline ("firmware: {0}", HDD. Firmware );
Console. writeline ("Capacity: {0} m", HDD. capacity );
The following is all the code:
Using system;
Using system. runtime. interopservices;
Using system. text;
Namespace sunmast. Hardware
{
[Serializable]
Public struct harddiskinfo
{
/// <Summary>
/// Model
/// </Summary>
Public String modulenumber;
/// <Summary>
/// Firmware version
/// </Summary>
Public String firmware;
/// <Summary>
/// Serial number
/// </Summary>
Public String serialnumber;
/// <Summary>
/// Capacity, in MB
/// </Summary>
Public uint capacity;
}
# Region internal structs
[Structlayout (layoutkind. Sequential, pack = 1)]
Internal struct getversionoutparams
{
Public byte bversion;
Public byte brevision;
Public byte breserved;
Public byte bidedevicemap;
Public uint fcapabilities;
[Financialas (unmanagedtype. byvalarray, sizeconst = 4)]
Public uint [] dwreserved; // for future use.
}
[Structlayout (layoutkind. Sequential, pack = 1)]
Internal struct ideregs
{
Public byte bfeaturesreg;
Public byte bsectorcounregulatory;
Public byte bsectornumberreg;
Public byte bcyllowreg;
Public byte bcylhighreg;
Public byte bdriveheadreg;
Public byte bcommandreg;
Public byte breserved;
}
[Structlayout (layoutkind. Sequential, pack = 1)]
Internal struct sendcmdinparams
{
Public uint cbuffersize;
Public ideregs irdriveregs;
Public byte bdrivenumber;
[Financialas (unmanagedtype. byvalarray, sizeconst = 3)]
Public byte [] breserved;
[Financialas (unmanagedtype. byvalarray, sizeconst = 4)]
Public uint [] dwreserved;
Public byte bbuffer;
}
[Structlayout (layoutkind. Sequential, pack = 1)]
Internal struct driverstatus
{
Public byte bdrivererror;
Public byte bidestatus;
[Financialas (unmanagedtype. byvalarray, sizeconst = 2)]
Public byte [] breserved;
[Financialas (unmanagedtype. byvalarray, sizeconst = 2)]
Public uint [] dwreserved;
}
[Structlayout (layoutkind. Sequential, pack = 1)]
Internal struct sendcmdoutparams
{
Public uint cbuffersize;
Public driverstatus;
Public idsector bbuffer;
}
[Structlayout (layoutkind. Sequential, pack = 1, size = 512)]
Internal struct idsector
{
Public ushort wgenconfig;
Public ushort wnumcyls;
Public ushort wreserved;
Public ushort wnumheads;
Public ushort wbytespertrack;
Public ushort wbytespersector;
Public ushort wsectorspertrack;
[Financialas (unmanagedtype. byvalarray, sizeconst = 3)]
Public ushort [] wvendorunique;
[Financialas (unmanagedtype. byvalarray, sizeconst = 20)]
Public byte [] sserialnumber;
Public ushort wbuffertype;
Public ushort wbuffersize;
Public ushort weccsize;
[Financialas (unmanagedtype. byvalarray, sizeconst = 8)]
Public byte [] sfirmwarerev;
[Financialas (unmanagedtype. byvalarray, sizeconst = 40)]
Public byte [] smodelnumber;
Public ushort wmorevendorunique;
Public ushort wdoublewordio;
Public ushort wcapabilities;
Public ushort wreserved1;
Public ushort wpiotiming;
Public ushort wdmatiming;
Public ushort WBS;
Public ushort wnumcurrentcyls;
Public ushort wnumcurrentheads;
Public ushort wnumcurrentsectorspertrack;
Public uint ulcurrentsectorcapacity;
Public ushort wmultsectorstuff;
Public uint ultotaladdressablesectors;
Public ushort wsingleworddma;
Public ushort wmultiworddma;
[Financialas (unmanagedtype. byvalarray, sizeconst = 128)]
Public byte [] breserved;
}
# Endregion
/// <Summary>
/// Atapi driver
/// </Summary>
Public class atapidevice
{
# Region dllimport
[Dllimport ("kernel32.dll", setlasterror = true)]
Static extern int closehandle (intptr hobject );
[Dllimport ("kernel32.dll", setlasterror = true)]
Static extern intptr createfile (
String lpfilename,
Uint dwdesiredaccess,
Uint dww.mode,
Intptr lpsecurityattributes,
Uint dwcreationdisposition,
Uint dwflagsandattributes,
Intptr htemplatefile );
[Dllimport ("kernel32.dll")]
Static extern int deviceiocontrol (
Intptr hdevice,
Uint dwiocontrolcode,
Intptr lpinbuffer,
Uint ninbuffersize,
Ref getversionoutparams lpoutbuffer,
Uint noutbuffersize,
Ref uint lpbytesreturned,
[Out] intptr lpoverlapped );
[Dllimport ("kernel32.dll")]
Static extern int deviceiocontrol (
Intptr hdevice,
Uint dwiocontrolcode,
Ref sendcmdinparams lpinbuffer,
Uint ninbuffersize,
Ref sendcmdoutparams lpoutbuffer,
Uint noutbuffersize,
Ref uint lpbytesreturned,
[Out] intptr lpoverlapped );
Const uint dfp_get_version = 0x00074080;
Const uint dfp_send_drive_command = 0x0007c084;
Const uint dfp_receive_drive_data = 0x0007c088;
Const uint generic_read = 0x80000000;
Const uint generic_write = 0x40000000;
Const uint file_1__read = 0x00000001;
Const uint file_pai_write = 0x00000002;
Const uint create_new = 1;
Const uint open_existing = 3;
# Endregion
# Region gethddinfo
/// <Summary>
/// Obtain hard disk Information
/// </Summary>
/// <Param name = "driveindex"> hard disk number </param>
/// <Returns> hard disk Information </returns>
/// <Remarks>
/// Reference lu0 article: http://lu0s1.3322.org/App/2k1103.html
/// By sunmast for everyone
/// Thanks lu0 for his great works
/// In Windows 98/Me, S. m.a. R. T is not installed by default. Copy smartvsd. Vxd to the % System % \ iosubsys directory.
/// In Windows 2000/2003, you need the permissions of the Administrators group.
/// </Remarks>
/// <Example>
/// Atapidevice. gethddinfo ()
/// </Example>
Public static harddiskinfo gethddinfo (byte driveindex)
{
Switch (environment. osversion. Platform)
{
Case platformid. win32windows:
Return gethddinfo9x (driveindex );
Case platformid. win32nt:
Return gethddinfont (driveindex );
Case platformid. win32s:
Throw new notsupportedexception ("win32s is not supported .");
Case platformid. wince:
Throw new notsupportedexception ("wince is not supported .");
Default:
Throw new notsupportedexception ("unknown platform .");
}
}
# Region gethddinfo9x
Private Static harddiskinfo gethddinfo9x (byte driveindex)
{
Getversionoutparams vers = new getversionoutparams ();
Sendcmdinparams inparam = new sendcmdinparams ();
Sendcmdoutparams outparam = new sendcmdoutparams ();
Uint bytesreturned = 0;
Intptr hdevice = createfile (
@ "\. \ Smartvsd ",
0,
0,
Intptr. Zero,
Create_new,
0,
Intptr. Zero );
If (hdevice = intptr. Zero)
{
Throw new exception ("Open smartvsd. VxD failed .");
}
If (0 = deviceiocontrol (
Hdevice,
Dfp_get_version,
Intptr. Zero,
0,
Ref vers,
(Uint) Marshal. sizeof (VERs ),
Ref bytesreturned,
Intptr. Zero ))
{
Closehandle (hdevice );
Throw new exception ("deviceiocontrol failed: dfp_get_version ");
}
// If ide identify command not supported, fails
If (0 = (vers. fcapabilities & 1 ))
{
Closehandle (hdevice );
Throw new exception ("error: ide identify command not supported .");
}
If (0! = (Driveindex & 1 ))
{
Inparam. irdriveregs. bdriveheadreg = 0xb0;
}
Else
{
Inparam. irdriveregs. bdriveheadreg = 0xa0;
}
If (0! = (Vers. fcapabilities & (16> driveindex )))
{
// We don't detect a atapi device.
Closehandle (hdevice );
Throw new exception (string. Format ("drive {0} is a atapi device, we don't detect it", driveindex + 1 ));
}
Else
{
Inparam. irdriveregs. bcommandreg = 0xec;
}
Inparam. bdrivenumber = driveindex;
Inparam. irdriveregs. bsectorcounreg = 1;
Inparam. irdriveregs. bsectornumberreg = 1;
Inparam. cbuffersize = 512;
If (0 = deviceiocontrol (
Hdevice,
Dfp_receive_drive_data,
Ref inparam,
(Uint) Marshal. sizeof (inparam ),
Ref outparam,
(Uint) Marshal. sizeof (outparam ),
Ref bytesreturned,
Intptr. Zero ))
{
Closehandle (hdevice );
Throw new exception ("deviceiocontrol failed: dfp_receive_drive_data ");
}
Closehandle (hdevice );
Return getharddiskinfo (outparam. bbuffer );
}
# Endregion
# Region gethddinfont
Private Static harddiskinfo gethddinfont (byte driveindex)
{
Getversionoutparams vers = new getversionoutparams ();
Sendcmdinparams inparam = new sendcmdinparams ();
Sendcmdoutparams outparam = new sendcmdoutparams ();
Uint bytesreturned = 0;
// We start in NT/Win2000
Intptr hdevice = createfile (
String. Format (@ "\. \ physicaldrive {0}", driveindex ),
Generic_read | generic_write,
File_pai_read | file_pai_write,
Intptr. Zero,
Open_existing,
0,
Intptr. Zero );
If (hdevice = intptr. Zero)
{
Throw new exception ("createfile faild .");
}
If (0 = deviceiocontrol (
Hdevice,
Dfp_get_version,
Intptr. Zero,
0,
Ref vers,
(Uint) Marshal. sizeof (VERs ),
Ref bytesreturned,
Intptr. Zero ))
{
Closehandle (hdevice );
Throw new exception (string. Format ("drive {0} may not exists.", driveindex + 1 ));
}
// If ide identify command not supported, fails
If (0 = (vers. fcapabilities & 1 ))
{
Closehandle (hdevice );
Throw new exception ("error: ide identify command not supported .");
}
// Identify the IDE drives
If (0! = (Driveindex & 1 ))
{
Inparam. irdriveregs. bdriveheadreg = 0xb0;
}
Else
{
Inparam. irdriveregs. bdriveheadreg = 0xa0;
}
If (0! = (Vers. fcapabilities & (16> driveindex )))
{
// We don't detect a atapi device.
Closehandle (hdevice );
Throw new exception (string. Format ("drive {0} is a atapi device, we don't detect it.", driveindex + 1 ));
}
Else
{
Inparam. irdriveregs. bcommandreg = 0xec;
}
Inparam. bdrivenumber = driveindex;
Inparam. irdriveregs. bsectorcounreg = 1;
Inparam. irdriveregs. bsectornumberreg = 1;
Inparam. cbuffersize = 512;
If (0 = deviceiocontrol (
Hdevice,
Dfp_receive_drive_data,
Ref inparam,
(Uint) Marshal. sizeof (inparam ),
Ref outparam,
(Uint) Marshal. sizeof (outparam ),
Ref bytesreturned,
Intptr. Zero ))
{
Closehandle (hdevice );
Throw new exception ("deviceiocontrol failed: dfp_receive_drive_data ");
}
Closehandle (hdevice );
Return getharddiskinfo (outparam. bbuffer );
}
# Endregion
Private Static harddiskinfo getharddiskinfo (idsector phdinfo)
{
Harddiskinfo hddinfo = new harddiskinfo ();
Changebyteorder (phdinfo. smodelnumber );
Hddinfo. modulenumber = encoding. ASCII. getstring (phdinfo. smodelnumber). Trim ();
Changebyteorder (phdinfo. sfirmwarerev );
Hddinfo. Firmware = encoding. ASCII. getstring (phdinfo. sfirmwarerev). Trim ();
Changebyteorder (phdinfo. sserialnumber );
Hddinfo. serialnumber = encoding. ASCII. getstring (phdinfo. sserialnumber). Trim ();
Hddinfo. capacity = phdinfo. ultotaladdressablesectors/2/1024;
Return hddinfo;
}
Private Static void changebyteorder (byte [] chararray)
{
Byte temp;
For (INT I = 0; I <chararray. length; I + = 2)
{
Temp = chararray [I];
Chararray [I] = chararray [I + 1];
Chararray [I + 1] = temp;
}
}
# Endregion
}
}
Note:
In Windows 98/Me, S. m.a. R. T is not installed by default. Copy smartvsd. Vxd to the % System % \ iosubsys directory.
In Windows 2000/2003, you need the permissions of the Administrators group.
Do not try it on a machine with a SCSI hard disk, because the SCSI hard disk does not have a serial number at all.
Ultimately, the copyright belongs to Lu Lin. No one can take this code as one.