VC 之获取硬盘序列号

硬盘物理序列号是硬盘的出厂序列号,它是全球都是唯一的,不会随着系统的安装、硬盘的格式化等操作而改变,跟mac地址一样都具有唯一性。

1,第一步:创建设备对象,得到设备句柄,设备为硬盘。
{
CString sFilePath;
sFilePath.Format("\\\\.\\PHYSICALDRIVE%d", driver);
HANDLE hFile
=::CreateFile(sFilePath,
                     GENERIC_READ | GENERIC_WRITE,
                     FILE_SHARE_READ | FILE_SHARE_WRITE,
                     NULL, OPEN_EXISTING,
                     0, NULL);
DWORD dwBytesReturned;
GETVERSIONINPARAMS gvopVersionParams;
DeviceIoControl(hFile,       //向设备对象发送
SMART_GET_VERSION设备请求,获取硬盘属性
                SMART_GET_VERSION,
                NULL,
                0,
                &gvopVersionParams,
                sizeof(gvopVersionParams),
                 &dwBytesReturned, NULL);
 if(gvopVersionParams.bIDEDeviceMap <= 0)    return -2; 
2。第二步,发送SMART_RCV_DRIVE_DATA设备请求,获取硬盘详细信息。
    // IDE or ATAPI IDENTIFY cmd
    int btIDCmd = 0;
    SENDCMDINPARAMS InParams;
    int nDrive =0;
    btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;


    // 输出参数
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];

    if(DoIdentify(hFile,
                    &InParams,
                    (PSENDCMDOUTPARAMS)btIDOutCmd,
                    (BYTE)btIDCmd,
                    (BYTE)nDrive, &dwBytesReturned) == FALSE)    return -3;
    ::CloseHandle(hFile);

    DWORD dwDiskData[256];
    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件

    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    for(int i=0; i < 256; i++)    dwDiskData[i] = pIDSector[i];

    // 取系列号
    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));

    // 取模型号
    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));

    return 0;
}

BOOL __fastcall DoIdentify( HANDLE hPhysicalDriveIOCTL,
                            PSENDCMDINPARAMS pSCIP,
                            PSENDCMDOUTPARAMS pSCOP,
                            BYTE btIDCmd,
                            BYTE btDriveNum,
                            PDWORD pdwBytesReturned)
{
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    pSCIP->irDriveRegs.bFeaturesReg = 0;
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    pSCIP->irDriveRegs.bCylLowReg  = 0;
    pSCIP->irDriveRegs.bCylHighReg = 0;

    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    pSCIP->bDriveNumber = btDriveNum;
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;

    return DeviceIoControl(    hPhysicalDriveIOCTL,
                            SMART_RCV_DRIVE_DATA,
                            (LPVOID)pSCIP,
                            sizeof(SENDCMDINPARAMS) - 1,
                            (LPVOID)pSCOP,
                            sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
                            pdwBytesReturned, NULL);
}

char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
{
    static char szResBuf[1024];
    char ss[256];
    int nIndex = 0;
    int nPosition = 0;

    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    {
        ss[nPosition] = (char)(dwDiskData[nIndex] / 256);
        nPosition++;

        // Get low BYTE for 2nd character
        ss[nPosition] = (char)(dwDiskData[nIndex] % 256);
        nPosition++;
    }

    // End the string
    ss[nPosition] = '\0';

    int i, index=0;
    for(i=0; i<nPosition; i++)
    {
        if(ss[i]==0 || ss[i]==32)    continue;
        szResBuf[index]=ss[i];
        index++;
    }
    szResBuf[index]=0;

    return szResBuf;
}

详细信息请搜索msdn。

上述代码在WinXP sp2平台测试通过。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: VC6.0是一个老旧的编程工具,但是它仍然可以读取硬盘序列号硬盘序列号硬盘唯一的标识符,可以帮助我们区分不同的硬盘。下面是读取硬盘序列号的步骤: 1. 在VC6.0中创建一个新的Win32控制台应用程序。 2. 在源文件中添加头文件#include <windows.h>,此头文件中定义了读取硬盘序列号的API函数。 3. 在主函数中,使用GetVolumeInformationA函数来获取硬盘的信息,如下: char szVolumeSerialNumber[256]; DWORD dwSerialNumber; DWORD dwMaxComponentLength; DWORD dwFileSystemFlags; char szFileSystemName[256]; BOOL bSuccess = GetVolumeInformationA("C:\\", NULL, 0, &dwSerialNumber, &dwMaxComponentLength, &dwFileSystemFlags, szFileSystemName, 256); 4. 上述代码中,C:\\表示要获取硬盘的驱动器号,NULL表示不需要获取卷标,0表示卷标缓冲区的大小,而dwSerialNumber即为所获取硬盘序列号。 5. 将硬盘序列号转换成字符串格式: sprintf(szVolumeSerialNumber, "%08X", dwSerialNumber); 6. 最终,将读取到的硬盘序列号输出到控制台: printf("Hard Disk Serial Number: %s\n", szVolumeSerialNumber); 通过以上步骤,就可以利用VC6.0读取硬盘序列号了,这对于某些需要以硬盘序列号作为标识的程序很有用。 ### 回答2: VC6.0是微软早期的编程开发工具之一,使用它可以读取硬盘序列号硬盘序列号是指硬盘唯一的标识符,每个硬盘都具有独特的序列号。读取硬盘序列号可以实现硬件设备的唯一标识和数据安全性的保证。 在VC6.0中,读取硬盘序列号需要用到Windows API函数GetVolumeInformation,这个函数的作用是获取指定磁盘卷的相关信息,包括卷标、文件系统和序列号等。 具体步骤如下: 1.调用GetVolumeInformation函数,指定需要获取信息的硬盘驱动器号(例如:C盘为0、D盘为1等)。 2.将函数返回的信息存储在变量中,其中包括硬盘序列号等。 3.将硬盘序列号转换成字符串型,以便于进行后续操作。 需要注意的是,这种方法只适用于单个硬盘的情况,若系统中存在多个硬盘,则需要通过遍历硬盘列表的方式获取每个硬盘序列号。 最后,VC6.0读取硬盘序列号还需要考虑兼容性问题。由于VC6.0是一个比较老的开发工具,可以使用的Windows API函数和数据类型可能不够丰富,因此需要在开发过程中进行充分测试和调试,确保程序在各个平台上都能正常运行。 ### 回答3: VC++6.0读取硬盘序列号可以使用Windows API函数来实现。具体步骤如下: 1. 打开硬盘设备文件 可以使用CreateFile函数打开硬盘设备文件,设备名称可以通过GetLogicalDriveStrings函数获取。 2. 发送IO控制命令 使用DeviceIoControl函数发送IO控制命令获取硬盘序列号。使用的命令为IOCTL_STORAGE_QUERY_PROPERTY,具体细节可以参考Microsoft官方文档。 3. 解析获取到的数据 硬盘序列号是以十六进制形式存储在结构体中的,需要将其转换为字符串形式。具体实现可以参考以下代码示例: ```c++ HANDLE hDevice; DWORD bytesReturned; STORAGE_PROPERTY_QUERY query; query.PropertyId = StorageDeviceProperty; query.QueryType = PropertyStandardQuery; STORAGE_DEVICE_DESCRIPTOR descriptor; if (GetLogicalDriveStrings(0, NULL) == 0) { cout << "无法获取磁盘设备名称!" << endl; return 0; } TCHAR driveStrings[MAX_PATH]; if (GetLogicalDriveStrings(MAX_PATH, driveStrings) == 0) { cout << "无法获取磁盘设备名称!" << endl; return 0; } TCHAR* drive = driveStrings; while (*drive != 0) { TCHAR drivePath[MAX_PATH] = { 0 }; _sntprintf(drivePath, MAX_PATH - 1, _T("\\\\.\\%c:"), *drive); hDevice = CreateFile(drivePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDevice != INVALID_HANDLE_VALUE) { if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &descriptor, sizeof(descriptor), &bytesReturned, NULL)) { DWORD serialNumberOffset = descriptor.SerialNumberOffset; if (serialNumberOffset != 0) { char serialNumber[255]; ZeroMemory(serialNumber, sizeof(serialNumber)); memcpy(serialNumber, ((char*)&descriptor) + serialNumberOffset, (descriptor.SerialNumberLength - 1) * 2 + 1); cout << "磁盘" << *drive << "的序列号为:" << serialNumber << endl; } } CloseHandle(hDevice); } drive += _tcslen(drive) + 1; } ``` 以上代码可遍历系统中的所有磁盘,输出磁盘序列号
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值