驅動下如何獲取硬碟序列號
最近公司有個專案,需要在驅動模式及使用者模式下,獲取硬碟的序列號,在網上找了半天,大多是使用者模式的程式碼,而且許多已經過時,於是參照了一下,改寫成核心模式下的程式碼,本人是驅動的菜鳥,希望此程式碼能對那些和我一樣的菜鳥有所幫助。
#include < ntdddisk.h>
#include <ntstrsafe.h>
#define _in
#define _out
typedef struct _IDENTIFY_DATA {
USHORT GeneralConfiguration; // 00 00
USHORT NumberOfCylinders; // 02 1
USHORT Reserved1; // 04 2
USHORT NumberOfHeads; // 06 3
USHORT UnformattedBytesPerTrack; // 08 4
USHORT UnformattedBytesPerSector; // 0A 5
USHORT SectorsPerTrack; // 0C 6
USHORT VendorUnique1[3]; // 0E 7-9
USHORT SerialNumber[10]; // 14 10-19
USHORT BufferType; // 28 20
USHORT BufferSectorSize; // 2A 21
USHORT NumberOfEccBytes; // 2C 22
USHORT FirmwareRevision[4]; // 2E 23-26
USHORT ModelNumber[20]; // 36 27-46
UCHAR MaximumBlockTransfer; // 5E 47
UCHAR VendorUnique2; // 5F
USHORT DoubleWordIo; // 60 48
USHORT Capabilities; // 62 49
USHORT Reserved2; // 64 50
UCHAR VendorUnique3; // 66 51
UCHAR PioCycleTimingMode; // 67
UCHAR VendorUnique4; // 68 52
UCHAR DmaCycleTimingMode; // 69
USHORT TranslationFieldsValid:1; // 6A 53
USHORT Reserved3:15;
USHORT NumberOfCurrentCylinders; // 6C 54
USHORT NumberOfCurrentHeads; // 6E 55
USHORT CurrentSectorsPerTrack; // 70 56
ULONG CurrentSectorCapacity; // 72 57-58
USHORT CurrentMultiSectorSetting; // 59
ULONG UserAddressableSectors; // 60-61
USHORT SingleWordDMASupport : 8; // 62
USHORT SingleWordDMAActive : 8;
USHORT MultiWordDMASupport : 8; // 63
USHORT MultiWordDMAActive : 8;
USHORT AdvancedPIOModes : 8; // 64
USHORT Reserved4 : 8;
USHORT MinimumMWXferCycleTime; // 65
USHORT RecommendedMWXferCycleTime; // 66
USHORT MinimumPIOCycleTime; // 67
USHORT MinimumPIOCycleTimeIORDY; // 68
USHORT Reserved5[2]; // 69-70
USHORT ReleaseTimeOverlapped; // 71
USHORT ReleaseTimeServiceCommand; // 72
USHORT MajorRevision; // 73
USHORT MinorRevision; // 74
USHORT Reserved6[50]; // 75-126
USHORT SpecialFunctionsEnabled; // 127
USHORT Reserved7[128]; // 128-255
} IDENTIFY_DATA, *PIDENTIFY_DATA;
typedef struct _HardDiskInfo
{
char szSerialNumber[21];
char szModelNumber[41];
char szRevision[21];
}HardDiskInfo,*PHardDiskInfo;
typedef enum
{
HDSERIALNO = 1,
HDMODELNO = 1<<1,
HDREVISION = 1<<2,
HDALLINFO = HDSERIALNO | HDMODELNO | HDREVISION
} HDInfoRequest;
int ConvertToString(_in PUSHORT pData, _in int iFirstIndex, _in int iLastIndex, _out char* szOutBuf )
{
int iIndex = 0;
int iPosition = 0;
BOOL bNoneSpace = FALSE;
if(iFirstIndex > iLastIndex)
{
int iTmp = iFirstIndex;
iFirstIndex = iLastIndex;
iLastIndex = iTmp;
}
if(iLastIndex > 0xFF)
return 0;
//memset(szOutBuf,0,iLastIndex-iFirstIndex+1);
for(iIndex = iFirstIndex; iIndex<= iLastIndex;++iIndex)
{
char ch = pData[iIndex] >> 8;
if(ch != ' ')
{
bNoneSpace = TRUE;
}
if(bNoneSpace)
szOutBuf[iPosition++] = ch;
ch = pData[iIndex] & 0xFF;
if(ch != ' ')
{
bNoneSpace = TRUE;
}
if(bNoneSpace)
szOutBuf[iPosition++] = ch;
}
iPosition--;
while(szOutBuf[iPosition] == ' ')
iPosition--;
szOutBuf[++iPosition] = 0;
return iPosition;
}
NTSTATUS ReadPhysicalDriveInNTUsingSmart( _in int iDrive,_out PHardDiskInfo pHDInfo,_in HDInfoRequest hdRequest )
{
HANDLE hPhysicalDriveIOCTL = 0;
wchar_t szDriveName [40];
NTSTATUS ret = STATUS_UNSUCCESSFUL;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uDrivePath;
IO_STATUS_BLOCK iosb;
#ifdef DBG
__asm int 3
#endif
ret = RtlStringCchPrintfW(szDriveName,sizeof(szDriveName)/sizeof(wchar_t), L"\\DosDevices\\PhysicalDrive%d", iDrive);
if(!NT_SUCCESS(ret))
return ret;
RtlInitUnicodeString(&uDrivePath,szDriveName);
InitializeObjectAttributes(&oa, &uDrivePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE ,(HANDLE)NULL, NULL);
ret = ZwCreateFile(&hPhysicalDriveIOCTL,
FILE_READ_DATA | FILE_READ_ATTRIBUTES |FILE_WRITE_DATA,
&oa,
&iosb,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if(NT_SUCCESS(ret))
{
ULONG ulCommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE;
DWORD BytesReturned = 0;
PSENDCMDINPARAMS pCmdParam;
DbgPrint(("Open Disk file succeded!"));
pCmdParam = (PSENDCMDINPARAMS) ExAllocatePoolWithTag (NonPagedPool,ulCommandSize, (ULONG)"_EL_");
if(pCmdParam != NULL)
{
pCmdParam -> irDriveRegs.bCommandReg = 0xEC;// Returns ID sector for ATA
ret = ZwDeviceIoControlFile(hPhysicalDriveIOCTL,
NULL,
NULL,
NULL,
&iosb,
SMART_RCV_DRIVE_DATA,
pCmdParam,sizeof(SENDCMDINPARAMS),
pCmdParam,ulCommandSize
);
if(NT_SUCCESS(ret))
{
// Print the IDENTIFY data
USHORT *punIdSector = (USHORT *)(PIDENTIFY_DATA) ((PSENDCMDOUTPARAMS) pCmdParam) -> bBuffer;
if(hdRequest & HDSERIALNO)
ConvertToString (punIdSector, 10, 19, pHDInfo->szSerialNumber);
if(hdRequest & HDMODELNO)
ConvertToString (punIdSector, 27, 46, pHDInfo->szModelNumber);
if(hdRequest & HDREVISION)
ConvertToString (punIdSector, 23, 26, pHDInfo->szRevision);
}
ExFreePoolWithTag(pCmdParam, (ULONG)"_EL_");
}
ZwClose(hPhysicalDriveIOCTL);
}
else
{
DbgPrint(("Open Disk file failed!"));
}
return ret;
}
BOOL GetHardDiskSerial( char* szSerial )
{
HardDiskInfo hdInfo;
BOOL iRet = FALSE;
strcpy(szSerial,"");
if(NT_SUCCESS(ReadPhysicalDriveInNTUsingSmart(0,&hdInfo,HDALLINFO)))
{
strcat(szSerial,hdInfo.szSerialNumber);
strcat(szSerial," ");
/*strcat(szSerial," ");
strcat(szSerial,hdInfo.szModelNumber);
strcat(szSerial," ");
strcat(szSerial,hdInfo.szRevision);*/
DbgPrint(("Hard disk serial is %s\n",szSerial));
iRet = TRUE;
}
return iRet;
}