正确获取硬盘序列号源码
GetVolumeInformation 只能用来获取卷序列号,这就意味着一旦用户重新格式化,
或者重新分区,那序列号又将改变.以下正确获取硬盘序列号的源码,我已将字符串处理函数
修正为安全版本.此程序在 VS2005 中编译通过.
输出样板:
Trying to read the drive IDs using physical access with admin rights
Primary Controller - Master drive
Drive Model Number________________: Maxtor 6Y080L0
Drive Serial Number_______________: Y2BNRXKE
Drive Controller Revision Number__: YAR41BW0
Controller Buffer Size on Drive___: 2097152 bytes
Drive Type________________________: Fixed
Drive Size________________________: 81964302336 bytes
Primary Controller - Slave drive
Drive Model Number________________: Maxtor 6E040L0
Drive Serial Number_______________: E1PT2A3E
Drive Controller Revision Number__: NAR61EA0
Controller Buffer Size on Drive___: 2097152 bytes
Drive Type________________________: Fixed
Drive Size________________________: 41110142976 bytes
Trying to read the drive IDs using the SCSI back door
Primary Controller - Master drive
Drive Model Number________________: Maxtor 6Y080L0
Drive Serial Number_______________: Y2BNRXKE
Drive Controller Revision Number__: YAR41BW0
Controller Buffer Size on Drive___: 2097152 bytes
Drive Type________________________: Fixed
Drive Size________________________: 81964302336 bytes
Secondary Controller - Master drive
Drive Model Number________________: Maxtor 6E040L0
Drive Serial Number_______________: E1PT2A3E
Drive Controller Revision Number__: NAR61EA0
Controller Buffer Size on Drive___: 2097152 bytes
Drive Type________________________: Fixed
Drive Size________________________: 41110142976 bytes
Trying to read the drive IDs using physical access with zero rights
**** STORAGE_DEVICE_DESCRIPTOR for drive 0 ****
Vendor Id = (
Product Id = Maxtor 6Y080L0
Product Revision = YAR41BW0
Serial Number = Y2BNRXKE
DeviceIOControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER error =
The request is not valid for this device.
**** STORAGE_DEVICE_DESCRIPTOR for drive 1 ****
Vendor Id = (
Product Id = Maxtor 6E040L0
Product Revision = NAR61EA0
Serial Number = E1PT2A3E
DeviceIOControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER error =
The request is not valid for this device.
Hard Drive Serial Number__________: Y2BNRXKE
Hard Drive Model Number___________: Maxtor 6Y080L0
Computer ID_______________________: 443360514
MAC Address: 00-0E-A6-A9-5A-11
源码:
//
//
//
//
//
//
//
diskid32.cpp
for displaying the details of hard drives in a command window
06/11/00 Lynn McGuire written with many contributions from others,
IDE drives only under Windows NT/2K and 9X,
maybe SCSI drives later
11/20/03 Lynn McGuire
10/26/05 Lynn McGuire
added ReadPhysicalDriveInNTWithZeroRights
fix the flipAndCodeBytes function
12/8/06
//
// Testing Passed with Visul Studio 2005.
Chunlin Deng
update the string function to security version.
#define PRINTING_TO_CONSOLE_ALLOWED
#include
#include
#include
#include
#include
#include
special include from the MS DDK
//
//#include "c:\win2kddk\inc\ddk\ntddk.h"
//#include "c:\win2kddk\inc\ntddstor.h"
#define TITLE
"DiskId32"
char HardDriveSerialNumber [1024];
char HardDriveModelNumber [1024];
void WriteConstantString (char *entry, char *string)
{
}
// Required to ensure correct PhysicalDrive IOCTL structure setup
#pragma pack(1)
#define
IDENTIFY_BUFFER_SIZE 512
//
IOCTL commands
#define DFP_GET_VERSION
#define DFP_SEND_DRIVE_COMMAND
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088
0x00074080
0x0007c084
#define FILE_DEVICE_SCSI
#define
IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501)
0x0000001b
#define
IOCTL_SCSI_MINIPORT 0x0004D008
//
see NTDDSCSI.H for definition
// GETVERSIONOUTPARAMS contains the data returned from the
// Get Driver Version function.
typedef struct _GETVERSIONOUTPARAMS
{
// Binary driver version.
// Binary driver revision.
// Not used.
BYTE bVersion;
BYTE bRevision;
BYTE bReserved;
BYTE bIDEDeviceMap; // Bit map of IDE devices.
DWORD fCapabilities; // Bit mask of driver capabilities.
DWORD dwReserved[4]; // For future use.
GETVERSIONOUTPARAMS,
}
*LPGETVERSIONOUTPARAMS;
*PGETVERSIONOUTPARAMS,
// Bits returned in the fCapabilities member of GETVERSIONOUTPARAMS
#define CAP_IDE_ID_FUNCTION
#define CAP_IDE_ATAPI_ID
#define CAP_IDE_EXECUTE_SMART_FUNCTION 4
1
// SMART commannds supported
// ATA ID command supported
// ATAPI ID command supported
2
//
IDE registers
typedef struct _IDEREGS
{
BYTE bFeaturesReg;
BYTE bSectorCountReg;
BYTE bSectorNumberReg;
BYTE bCylLowReg;
BYTE bCylHighReg;
BYTE bDriveHeadReg;
BYTE bCommandReg;
BYTE bReserved;
// Used for specifying SMART "commands".
// IDE sector count register
// IDE sector number register
// IDE low order cylinder value
// IDE high order cylinder value
// IDE drive/head register
// Actual IDE command.
// reserved for future use. Must be zero.
} IDEREGS, *PIDEREGS, *LPIDEREGS;
// SENDCMDINPARAMS contains the input parameters for the
// Send Command to Drive function.
typedef struct _SENDCMDINPARAMS
{
DWORD
IDEREGS
BYTE bDriveNumber;
cBufferSize;
irDriveRegs;
// Buffer size in bytes
// Structure with drive register values.
// Physical drive number to send
//
command to (0,1,2,3).
BYTE bReserved[3];
DWORD
BYTE
dwReserved[4]; // For future use.
bBuffer[1];
Input buffer.
//
// Reserved for future expansion.
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
// Valid values for the bCommandReg member of IDEREGS.
#define
#define
IDE_ATAPI_IDENTIFY 0xA1
IDE_ATA_IDENTIFY
// Returns ID sector for ATAPI.
0xEC // Returns ID sector for ATA.
// Status returned from driver
typedef struct _DRIVERSTATUS
{
BYTE bDriverError;
BYTE bIDEStatus;
BYTE bReserved[2];
DWORD dwReserved[2];
// Error code from driver, or 0 if no error.
// Contents of IDE Error register.
// Only valid when bDriverError is SMART_IDE_ERROR.
// Reserved for future expansion.
// Reserved for future expansion.
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
// Structure returned by PhysicalDrive IOCTL for several commands
typedef struct _SENDCMDOUTPARAMS
{
cBufferSize;
DWORD
DRIVERSTATUS DriverStatus;
BYTE
bBuffer[1];
// Size of bBuffer in bytes
// Driver status structure.
// Buffer of arbitrary length in which to store the data
read from the
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
// drive.
// The following struct defines the interesting part of the IDENTIFY
// buffer:
typedef struct _IDSECTOR
{
USHORT wGenConfig;
USHORT wNumCyls;
USHORT wReserved;
USHORT wNumHeads;
USHORT wBytesPerTrack;
USHORT wBytesPerSector;
USHORT wSectorsPerTrack;
USHORT wVendorUnique[3];
sSerialNumber[20];
sFirmwareRev[8];
sModelNumber[40];
CHAR
USHORT wBufferType;
USHORT wBufferSize;
USHORT wECCSize;
CHAR
CHAR
USHORT wMoreVendorUnique;
USHORT wDoubleWordIO;
USHORT wCapabilities;
USHORT wReserved1;
USHORT wPIOTiming;
USHORT wDMATiming;
USHORT wBS;
USHORT wNumCurrentCyls;
USHORT wNumCurrentHeads;
USHORT wNumCurrentSectorsPerTrack;
ULONG
USHORT wMultSectorStuff;
ULONG
USHORT wSingleWordDMA;
USHORT wMultiWordDMA;
BYTE
ulCurrentSectorCapacity;
ulTotalAddressableSectors;
bReserved[128];
} IDSECTOR, *PIDSECTOR;
typedef struct _SRB_IO_CONTROL
{
ULONG HeaderLength;
UCHAR Signature[8];
ULONG Timeout;
ULONG ControlCode;
ULONG ReturnCode;
ULONG Length;
} SRB_IO_CONTROL, *PSRB_IO_CONTROL;
// Define global buffers.
BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
char *ConvertToString (DWORD diskdata [256], int firstIndex, int lastIndex);
void PrintIdeInfo (int drive, DWORD diskdata [256]);
BOOL DoIDENTIFY (HANDLE, PSENDCMDINPARAMS, PSENDCMDOUTPARAMS,
BYTE, BYTE,
PDWORD);
// Max number of drives assuming primary/secondary, master/slave topology
#define MAX_IDE_DRIVES 16
int ReadPhysicalDriveInNTWithAdminRights (void)
{
int done = FALSE;
int drive = 0;
for (drive = 0; drive < MAX_IDE_DRIVES; drive++)
{
HANDLE hPhysicalDriveIOCTL = 0;
// Try to get a handle to PhysicalDrive IOCTL, report failure
//
and exit if can't.
char driveName [256];
sprintf_s (driveName, "\\\\.\\PhysicalDrive%d", drive);
// Windows NT, Windows 2000, must have admin rights
hPhysicalDriveIOCTL = CreateFile (driveName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE , NULL,
OPEN_EXISTING, 0, NULL);
// if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
//
//
printf ("Unable to open physical drive %d, error code: 0x%lX\n",
drive, GetLastError ());
if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
GETVERSIONOUTPARAMS VersionParams;
DWORD
cbBytesReturned = 0;
// Get the version, etc of PhysicalDrive IOCTL
memset ((void*) &VersionParams, 0, sizeof(VersionParams));
if ( ! DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION,
NULL,
0,
&VersionParams,
sizeof(VersionParams),
&cbBytesReturned, NULL) )
// printf ("DFP_GET_VERSION failed for drive %d\n", i);
// continue;
{
}
// If there is a IDE device at number "i" issue commands
// to the device
if (VersionParams.bIDEDeviceMap > 0)
{
BYTE
SENDCMDINPARAMS scip;
//SENDCMDOUTPARAMS OutCmd;
bIDCmd = 0;
// IDE or ATAPI IDENTIFY cmd
// Now, get the ID sector for all IDE devices in the system.
// If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
// otherwise use the IDE_ATA_IDENTIFY command
bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10) ? \
IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
memset (&scip, 0, sizeof(scip));
memset (IdOutCmd, 0, sizeof(IdOutCmd));
if ( DoIDENTIFY (hPhysicalDriveIOCTL,
&scip,
(PSENDCMDOUTPARAMS)&IdOutCmd,
(BYTE) bIDCmd,
(BYTE) drive,
&cbBytesReturned))
{
}
}
DWORD diskdata [256];
int ijk = 0;
USHORT *pIdSector = (USHORT *)
((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;
for (ijk = 0; ijk < 256; ijk++)
diskdata [ijk] = pIdSector [ijk];
PrintIdeInfo (drive, diskdata);
done = TRUE;