生活随笔
收集整理的這篇文章主要介紹了
Windows下使用C++(Win32SDK)编程无需提权读取硬盘序列号
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在需要對(duì)計(jì)算機(jī)進(jìn)行標(biāo)識(shí)的場(chǎng)景下,我們一般會(huì)選擇獲取一些硬件信息。然而CPU序列號(hào)可能有重復(fù)、網(wǎng)卡MAC地址和計(jì)算機(jī)名又能被輕易地修改,所以其中最可靠的應(yīng)該就是硬盤序列號(hào)了。Windows下硬盤序列號(hào)的獲取本身并不復(fù)雜,而關(guān)鍵在于如何在無(wú)需權(quán)限提升的情況下獲取到硬盤序列號(hào)。為了解決這個(gè)問(wèn)題,我也查了很多資料,基本上各大博客中貼出的都是需要權(quán)限提升的代碼。
最終,在DiskID32的源碼中,我找到了不提權(quán)獲取硬盤序列號(hào)的辦法。不過(guò)其源碼只能使用MBCS多字節(jié)字符集方式編譯,而無(wú)法使用Unicode字符集編譯,為此,我進(jìn)行了一些修改,使之兼容兩種方式。下面將經(jīng)過(guò)我修改、測(cè)試后的代碼貼出來(lái),供大家參考。
其中,獲取硬盤序列號(hào)的函數(shù)命名為GetHDSerial,該函數(shù)依賴flipAndCodeBytes函數(shù)。前者使用說(shuō)明如下:
#include <locale.h>
#include <tchar.h>
#include <windows.h>
#include <stdio.h>char * flipAndCodeBytes(const char * str,int pos,int flip,char * buf)
{int i;int j = 0;int k = 0;buf[0] = '\0';if (pos <= 0)return buf;if (!j){char p = 0;// First try to gather all characters representing hex digits only.j = 1;k = 0;buf[k] = 0;for (i = pos; j && str[i] != '\0'; ++i){char c = tolower(str[i]);if (isspace(c))c = '0';++p;buf[k] <<= 4;if (c >= '0' && c <= '9')buf[k] |= (unsigned char)(c - '0');else if (c >= 'a' && c <= 'f')buf[k] |= (unsigned char)(c - 'a' + 10);else{j = 0;break;}if (p == 2){if (buf[k] != '\0' && !isprint(buf[k])){j = 0;break;}++k;p = 0;buf[k] = 0;}}}if (!j){// There are non-digit characters, gather them as is.j = 1;k = 0;for (i = pos; j && str[i] != '\0'; ++i){char c = str[i];if (!isprint(c)){j = 0;break;}buf[k++] = c;}}if (!j){// The characters are not there or are not printable.k = 0;}buf[k] = '\0';if (flip)// Flip adjacent charactersfor (j = 0; j < k; j += 2){char t = buf[j];buf[j] = buf[j + 1];buf[j + 1] = t;}// Trim any beginning and end spacei = j = -1;for (k = 0; buf[k] != '\0'; ++k){if (!isspace(buf[k])){if (i < 0)i = k;j = k;}}if ((i >= 0) && (j >= 0)){for (k = i; (k <= j) && (buf[k] != '\0'); ++k)buf[k - i] = buf[k];buf[k - i] = '\0';}return buf;
}/************************************************************************
GetHDSerial:用于獲取指定編號(hào)的硬盤序列號(hào),無(wú)需任何權(quán)限提升
參數(shù):
PCHAR pszIDBuff:傳入的字符串緩沖區(qū),用于接收硬盤序列號(hào)
int nBuffLen:傳入的字符串緩沖區(qū)大小,當(dāng)硬盤序列號(hào)大于該值時(shí),只復(fù)制nBuffLen長(zhǎng)度
int nDriveID:要獲取的驅(qū)動(dòng)器編號(hào),從0開始,到15為止
返回值:
成功獲取到的硬盤序列號(hào)長(zhǎng)度,為0表示獲取失敗
作者:
famous214(blog.csdn.net/LPWSTR)
源碼參考了diskid32(https://www.winsim.com/diskid32/diskid32.html)
版本歷史:
20171226 第一版,從diskid32源碼中提取
20171226 第二版,兼容Unicode編譯方式
20171230 重構(gòu)后發(fā)布第三版
************************************************************************/
ULONG GetHDSerial(PCHAR pszIDBuff, int nBuffLen, int nDriveID)
{HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;ULONG ulSerialLen = 0;__try{// Try to get a handle to PhysicalDrive IOCTL, report failure// and exit if can't.TCHAR szDriveName[32];wsprintf(szDriveName, TEXT("\\\\.\\PhysicalDrive%d"), nDriveID);// Windows NT, Windows 2000, Windows XP - admin rights not requiredhPhysicalDrive = CreateFile(szDriveName, 0,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING, 0, NULL);if (hPhysicalDrive == INVALID_HANDLE_VALUE){__leave;}STORAGE_PROPERTY_QUERY query;DWORD cbBytesReturned = 0;static char local_buffer[10000];memset((void *)&query, 0, sizeof(query));query.PropertyId = StorageDeviceProperty;query.QueryType = PropertyStandardQuery;memset(local_buffer, 0, sizeof(local_buffer));if (DeviceIoControl(hPhysicalDrive, IOCTL_STORAGE_QUERY_PROPERTY,&query,sizeof(query),&local_buffer[0],sizeof(local_buffer),&cbBytesReturned, NULL)){STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *)& local_buffer;char serialNumber[1000];flipAndCodeBytes(local_buffer,descrip->SerialNumberOffset,1, serialNumber);if (isalnum(serialNumber[0])){ULONG ulSerialLenTemp = strnlen(serialNumber, nBuffLen - 1);memcpy(pszIDBuff, serialNumber, ulSerialLenTemp);pszIDBuff[ulSerialLenTemp] = NULL;ulSerialLen = ulSerialLenTemp;__leave;}}}__finally{if (hPhysicalDrive != INVALID_HANDLE_VALUE){CloseHandle(hPhysicalDrive);}return ulSerialLen;}
}void GetAllHDSerial(void)
{const int MAX_IDE_DRIVES = 16;static char szBuff[0x100];for (int nDriveNum = 0; nDriveNum < MAX_IDE_DRIVES; nDriveNum++){ULONG ulLen = GetHDSerial(szBuff, sizeof(szBuff), nDriveNum);if (ulLen > 0){_tprintf(TEXT("第%d塊硬盤的序列號(hào)為:%hs\n"), nDriveNum + 1, szBuff);}}
}int main()
{setlocale(LC_ALL, "chs");GetAllHDSerial();system("pause");return 0;
}
總結(jié)
以上是生活随笔為你收集整理的Windows下使用C++(Win32SDK)编程无需提权读取硬盘序列号的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。