使用DeviceIoControl()

时间:2016-02-24 14:43:36

标签: windows winapi

我根据Blacktempel在this帖子中提出的建议,使用DeviceIoControl函数检索物理硬盘的序列号。获得这个号码原则上工作正常,但我(仍然)有序列号格式的问题,因为它随着时间的推移不断变换。在正常用户或管理员运行程序之间,我在某些计算机上遇到了格式更改。

例如,我使用以下格式检索了一个数字:

WD-WCAZAF632086

当我第一次测试程序时,几周后看起来像:

2020202057202d4443575a414641333630323638

这仍然是相同的数字,只有字符已被十六进制代码替换并成对交换。我遇到过不同的格式,比如普通字符串,字符交换成双字符串。在其他值中,我需要检查此编号以验证软件许可证是否对某台计算机有效。有一个不稳定和未知的格式是令人讨厌的,如果格式改变为我还没有意识到的东西,我冒险软件许可证检查失败,尽管许可证仍然有效。

有谁知道如何以稳定的格式获取序列号,或者如何预测格式以便进行比较?

这是我用来检索第一个物理光盘序列号的最小C ++代码示例。我使用Visual Studio 2015构建它:

#include "stdafx.h"
#include "Windows.h"

#include <string>
#include <vector>
#include <iostream>

bool GetDeviceString(std::string &serialnumber)
{
    HANDLE deviceHandle = CreateFileW(L"//./PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);  // Get Handle to device

    if (deviceHandle == INVALID_HANDLE_VALUE) // Check if Handle is valid
        return false;

    STORAGE_PROPERTY_QUERY query{};
    query.PropertyId = StorageDeviceProperty;
    query.QueryType = PropertyStandardQuery;

    STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
    DWORD dwBytesReturned;

    if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
        &query, sizeof(STORAGE_PROPERTY_QUERY),
        &storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL))
    {

    }

    // Alloc the output buffer
    const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
    std::vector<BYTE> pOutBuffer(dwOutBufferSize,0);

    if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
        &query, sizeof(STORAGE_PROPERTY_QUERY),
        pOutBuffer.data(), dwOutBufferSize,
        &dwBytesReturned, NULL))
    {
        // handle error, do cleanup and return
    }

    STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer.data();
    const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
    if (dwSerialNumberOffset != 0)
    {
        // Finally, get the serial number
        serialnumber = (char*)(pOutBuffer.data() + dwSerialNumberOffset);
    }
}

int main()
{
    std::string serialnumber;

    if (GetDeviceString(serialnumber))
    {
        std::cout << "serial number of first disc: " << serialnumber << std::endl;
    }
    else
    {
        std::cout << "Failed!" << std::endl;
    }
    std::cin.ignore();

    return 0;
}

0 个答案:

没有答案