C语言 我如何在过滤器驱动程序中获得磁盘驱动器序列号



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

编辑:

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

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;
    }
}

分配内存后,我认为您需要再次调用IoWMIQueryAllData(),这一次传递dataBuffer。

SMBIOS似乎与磁盘驱动器无关,因此您需要将不同的GUID传递给IoWMIOpenBlock()。也许这一个({BF253431-1E4D-4F57-00E7-64B2CACC801E}),因为你的用户模式的例子和其他人查询Win32_PhysicalMedia获得SerialNumber。

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

但是它也给出了如何从内核模式获取信息的提示:ioctl。它提到了IOCTL_SMART_GET_VERSION,它应该只是SMART_GET_VERSION,这里有一个例子:(在用户模式下,但是您应该能够使用ZwDeviceIoControlFile()从内核模式做类似的事情)。注意,它后面跟着另一个ioctl命令SMART_RCV_DRIVE_DATA来获取序列号。

另一个听起来很有前途(而且更通用)的ioctl是IOCTL_STORAGE_QUERY_PROPERTY,输入为STORAGE_PROPERTY_QUERY。PropertyId设置为storage_deviceproperty,因此输出将是一个STORAGE_DEVICE_DESCRIPTOR结构,该结构具有字段SerialNumberOffset:

指定从结构开头到包含设备序列号的以空结尾的ASCII字符串的字节偏移量。如果设备没有序列号,则该成员为0。

FILE_FS_VOLUME_INFORMATION包含VolumeSerialNumber字段。这个数据结构可以用ZwQueryVolumeInformationFile(... FileFsVolumeInformation)来检索。

需要一个对卷或卷中的文件/目录的句柄。如果这是不可行的,但是您有一个DEVICE_OBJECT,您可以尝试使用IRP_MJ_QUERY_VOLUME_INFORMATION构建自己的IRP,并使用IoCallDriver()发送它,尽管我不知道这是否被批准—文档说这样的"请求是由I/O管理器发送的"。

最新更新