📄 diskserialnumber.cpp
字号:
// DiskSerialNumber.cpp: implementation of the CDiskSerialNumber class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DiskSerialNumber.h"
#include <winioctl.h>
//(*Output Bbuffer for the VxD (rt_IdeDinfo record)*)
typedef struct _rt_IdeDInfo_
{
BYTE IDEExists[4];
BYTE DiskExists[8];
WORD DisksRawInfo[8*256];
} rt_IdeDInfo, *pt_IdeDInfo;
#define IDENTIFY_BUFFER_SIZE 512
//IOCTL commands
#define DFP_GET_VERSION 0x00074080
#define DFP_SEND_DRIVE_COMMAND 0x0007c084
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088
//Valid values for the bCommandReg member of IDEREGS.
#define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI.
#define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA.
//GETVERSIONOUTPARAMS contains the data returned from the
//Get Driver Version function.
typedef struct _GETVERSIONOUTPARAMS
{
BYTE bVersion; // Binary driver version.
BYTE bRevision; // Binary driver revision.
BYTE bReserved; // Not used.
BYTE bIDEDeviceMap; // Bit map of IDE devices.
DWORD fCapabilities; // Bit mask of driver capabilities.
DWORD dwReserved[4]; // For future use.
} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
////IDE registers
//typedef struct _IDEREGS
//{
// BYTE bFeaturesReg; // Used for specifying SMART "commands".
// BYTE bSectorCountReg; // IDE sector count register
// BYTE bSectorNumberReg; // IDE sector number register
// BYTE bCylLowReg; // IDE low order cylinder value
// BYTE bCylHighReg; // IDE high order cylinder value
// BYTE bDriveHeadReg; // IDE drive/head register
// BYTE bCommandReg; // Actual IDE command.
// BYTE bReserved; // 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 cBufferSize; // Buffer size in bytes
// IDEREGS irDriveRegs; // Structure with drive register values.
// BYTE bDriveNumber; // Physical drive number to send
// // command to (0,1,2,3).
// BYTE bReserved[3]; // Reserved for future expansion.
// DWORD dwReserved[4]; // For future use.
// BYTE bBuffer[1]; // Input buffer.
//} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
//
////Status returned from driver
//typedef struct _DRIVERSTATUS
//{
// BYTE bDriverError; // Error code from driver, or 0 if no error.
// BYTE bIDEStatus; // Contents of IDE Error register.
// //Only valid when bDriverError is SMART_IDE_ERROR.
// BYTE bReserved[2]; // Reserved for future expansion.
// DWORD dwReserved[2]; // Reserved for future expansion.
//} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
//
////Structure returned by PhysicalDrive IOCTL for several commands
//typedef struct _SENDCMDOUTPARAMS
//{
// DWORD cBufferSize; // Size of bBuffer in bytes
// DRIVERSTATUS DriverStatus; // Driver status structure.
// BYTE bBuffer[1]; // Buffer of arbitrary length in which to store the data read from the drive.
//} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
#define SENDIDLENGTH sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE
#define FILE_DEVICE_SCSI 0x0000001b
#define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501)
#define IOCTL_SCSI_MINIPORT 0x0004D008 // see NTDDSCSI.H for definition
typedef struct _SRB_IO_CONTROL
{
ULONG HeaderLength;
UCHAR Signature[8];
ULONG Timeout;
ULONG ControlCode;
ULONG ReturnCode;
ULONG Length;
} SRB_IO_CONTROL, *PSRB_IO_CONTROL;
//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];
CHAR sSerialNumber[20];
USHORT wBufferType;
USHORT wBufferSize;
USHORT wECCSize;
CHAR sFirmwareRev[8];
CHAR sModelNumber[40];
USHORT wMoreVendorUnique;
USHORT wDoubleWordIO;
USHORT wCapabilities;
USHORT wReserved1;
USHORT wPIOTiming;
USHORT wDMATiming;
USHORT wBS;
USHORT wNumCurrentCyls;
USHORT wNumCurrentHeads;
USHORT wNumCurrentSectorsPerTrack;
ULONG ulCurrentSectorCapacity;
USHORT wMultSectorStuff;
ULONG ulTotalAddressableSectors;
USHORT wSingleWordDMA;
USHORT wMultiWordDMA;
BYTE bReserved[128];
} IDSECTOR, *PIDSECTOR;
#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Types of queries
typedef enum _STORAGE_QUERY_TYPE {
PropertyStandardQuery = 0, // Retrieves the descriptor
PropertyExistsQuery, // Used to test whether the descriptor is supported
PropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptor
PropertyQueryMaxDefined // use to validate the value
} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;
// define some initial property id's
typedef enum _STORAGE_PROPERTY_ID {
StorageDeviceProperty = 0,
StorageAdapterProperty
} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
// Query structure - additional parameters for specific queries can follow the header
typedef struct _STORAGE_PROPERTY_QUERY {
STORAGE_PROPERTY_ID PropertyId; // ID of the property being retrieved
STORAGE_QUERY_TYPE QueryType; // Flags indicating the type of query being performed
UCHAR AdditionalParameters[1]; // Space for additional parameters if necessary
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;
//typedef enum _STORAGE_BUS_TYPE {
// BusTypeUnknown = 0x00,
// BusTypeScsi,
// BusTypeAtapi,
// BusTypeAta,
// BusType1394,
// BusTypeSsa,
// BusTypeFibre,
// BusTypeUsb,
// BusTypeRAID,
// BusTypeMaxReserved = 0x7F
//} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;
typedef struct _STORAGE_DEVICE_DESCRIPTOR {
// Sizeof(STORAGE_DEVICE_DESCRIPTOR)
ULONG Version;
// Total size of the descriptor, including the space for additional
// data and id strings
ULONG Size;
// The SCSI-2 device type
UCHAR DeviceType;
// The SCSI-2 device type modifier (if any) - this may be zero
UCHAR DeviceTypeModifier;
// Flag indicating whether the device's media (if any) is removable. This
// field should be ignored for media-less devices
BOOLEAN RemovableMedia;
// Flag indicating whether the device can support mulitple outstanding
// commands. The actual synchronization in this case is the responsibility
// of the port driver.
BOOLEAN CommandQueueing;
// Byte offset to the zero-terminated ascii string containing the device's
// vendor id string. For devices with no such ID this will be zero
ULONG VendorIdOffset;
// Byte offset to the zero-terminated ascii string containing the device's
// product id string. For devices with no such ID this will be zero
ULONG ProductIdOffset;
// Byte offset to the zero-terminated ascii string containing the device's
// product revision string. For devices with no such string this will be
// zero
ULONG ProductRevisionOffset;
// Byte offset to the zero-terminated ascii string containing the device's
// serial number. For devices with no serial number this will be zero
ULONG SerialNumberOffset;
// Contains the bus type (as defined above) of the device. It should be
// used to interpret the raw device properties at the end of this structure
// (if any)
STORAGE_BUS_TYPE BusType;
// The number of bytes of bus-specific data which have been appended to
// this descriptor
ULONG RawPropertiesLength;
// Place holder for the first byte of the bus specific property data
UCHAR RawDeviceProperties[1];
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;
typedef struct _MEDIA_SERAL_NUMBER_DATA {
ULONG SerialNumberLength;
ULONG Result;
ULONG Reserved[2];
UCHAR SerialNumberData[1];
} MEDIA_SERIAL_NUMBER_DATA, *PMEDIA_SERIAL_NUMBER_DATA;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDiskSerialNumber::CDiskSerialNumber()
{
m_nSerialCount=0;
}
CDiskSerialNumber::~CDiskSerialNumber()
{
}
BOOL CDiskSerialNumber::GetFirstDiskSerial(LPSTR szDiskSerial)
{
m_nReadCount=0;
OSVERSIONINFO version;
memset(&version,0,sizeof(version));
version.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(&version);
DWORD dwPlatform=version.dwPlatformId;
BOOL done=FALSE;
if(VER_PLATFORM_WIN32_NT==dwPlatform)
{
done=ReadPhysicalDriveInNTWithAdminRights();
if(FALSE==done)
done=ReadIdeDriveAsScsiDriveInNT();
if(FALSE==done)
done=ReadPhysicalDriveInNTWithZeroRights();
}
else
{
for(int i=0;i<10 && !done;i++)
done=ReadDrivePortsInWin9X();
}
return GetNextDiskSerial(szDiskSerial);
}
BOOL CDiskSerialNumber::GetNextDiskSerial(LPSTR szDiskSerial)
{
if(m_nReadCount>=m_nSerialCount)
return FALSE;
else
{
strcpy(szDiskSerial,m_szSerials[m_nReadCount++]);
return TRUE;
}
}
void CDiskSerialNumber::ConvertToString(LPSTR szDiskSerial, DWORD dwDiskData[], int nSize)
{
int position=0;
for(int i=0;i<nSize;i++)
{
szDiskSerial[position]=(char)(dwDiskData[i]/256);
if(' '!=szDiskSerial[position])//不接受空格
position++;
szDiskSerial[position]=(char)(dwDiskData[i]%256);
if(' '!=szDiskSerial[position])//不接受空格
position++;
}
szDiskSerial[position]='\0';
}
BOOL CDiskSerialNumber::ReadDrivePortsInWin9X()
{
BOOL done=FALSE;
//set the thread priority high so that we get exclusive access to the disk
SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
//1.Try to load the VxD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -