如何在过滤器驱动程序中获取磁盘驱动器序列号?

How do I get the disk drive serial number in filter driver?

我在windows中写了一个驱动程序,我需要磁盘驱动器序列号,对于用户模式我找到了this答案。 我的问题是可以将上面的代码转换为内核模式吗?如何转换? WMI 查询在筛选器驱动程序中是否可用?示例代码可以提供很大帮助。

编辑:

我找到了here这个代码,但是我如何重写他以获得序列号?

void GetSmbios()
{

    NTSTATUS status;
    GUID smbiosGUID = SMBIOS_DATA_GUID; // defined in wmiguid.h
    PVOID wmiObject = NULL;
    PWNODE_ALL_DATA dataBuffer;

    ULONG bufferSize;
    int TAG_SMBIOS = 'smbi';
    //
    // Get a WMI block handle to the SMBIOS_DATA_GUID
    //
    status = IoWMIOpenBlock((GUID *)&smbiosGUID, WMIGUID_QUERY,
        &wmiObject);
    if (!NT_SUCCESS(status)) 
    {
        return status;
    }

    //
    // Determine how much space is required for the data
    //
    status = IoWMIQueryAllData(wmiObject, &bufferSize, NULL);
    if (status != STATUS_BUFFER_TOO_SMALL) 
    {
        ObDereferenceObject(wmiObject);
        return status;
    }

    //
    // Allocate the necessary storage. This space must come out of NP-pool
    //
    dataBuffer = ExAllocatePoolWithTag(
        NonPagedPool,
        bufferSize,
        TAG_SMBIOS);

    if (dataBuffer == NULL) 
    {
        ObDereferenceObject(wmiObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

}

FILE_FS_VOLUME_INFORMATION contains field VolumeSerialNumber. This data structure might be retrieved with ZwQueryVolumeInformationFile(... FileFsVolumeInformation).

这需要卷的句柄或卷中的 file/directory。如果那不可行,但您有一个 DEVICE_OBJECT,您可以尝试使用 IRP_MJ_QUERY_VOLUME_INFORMATION and sending it with IoCallDriver() 构建您自己的 IRP,尽管我不知道这是否被批准——文档说这样一个 "request is sent by the I/O Manager."

分配内存后,我相信你需要再次调用IoWMIQueryAllData(),这次传递的是dataBuffer。

SMBIOS 似乎与磁盘驱动器无关,因此您需要将不同的 GUID 传递给 IoWMIOpenBlock()。也许 this one ({BF253431-1E4D-4F57-00E7-64B2CACC801E}), since your user-mode example and others 查询 Win32_PhysicalMedia 得到 SerialNumber.

但是,this 引用了一个(可能是用户模式)DLL,它是 Win32_PhysicalMedia 的提供程序。所以这在内核模式下可能无法访问。

但它也给出了如何从内核模式获取信息的提示:IOCTL。它提到 IOCTL_SMART_GET_VERSION,应该只是 SMART_GET_VERSION,和 here's an example: (在用户模式下,但您应该能够使用 ZwDeviceIoControlFile() 从内核模式执行类似操作)。请注意,它跟在另一个 ioctl 命令 SMART_RCV_DRIVE_DATA 之后,以获取序列号。

另一个听起来很有前途(而且更通用)的 ioctl 是 IOCTL_STORAGE_QUERY_PROPERTY,输入 STORAGE_PROPERTY_QUERY.PropertyId 设置为 StorageDeviceProperty,因此输出将是一个 STORAGE_DEVICE_DESCRIPTOR 结构,它有字段序列号偏移量:

Specifies the byte offset from the beginning of the structure to a null-terminated ASCII string that contains the device's serial number. If the device has no serial number, this member is zero.