使用IOCTL\u存储\u查询\u属性获取序列号

使用IOCTL\u存储\u查询\u属性获取序列号,c,windows,wmi,drivers,C,Windows,Wmi,Drivers,因此,我试图编写一个只连接到特定USB设备的微型过滤器驱动程序,以区分我使用的产品ID+供应商ID+序列号组合的设备 我可以成功地将IOCTL\u STORAGE\u QUERY\u属性发送到返回产品ID、供应商ID、序列号的设备 我遇到的问题是返回到我的微型过滤器的序列号对于某些USB是正确的,但不是所有的 当我打电话的时候 C:\Windows\system32>wmic diskdrive获取pnpdeviceid PNPDeviceID USBSTOR\DISK&VEN_SONY&PRO

因此,我试图编写一个只连接到特定USB设备的微型过滤器驱动程序,以区分我使用的产品ID+供应商ID+序列号组合的设备

我可以成功地将IOCTL\u STORAGE\u QUERY\u属性发送到返回产品ID、供应商ID、序列号的设备

我遇到的问题是返回到我的微型过滤器的序列号对于某些USB是正确的,但不是所有的

当我打电话的时候

C:\Windows\system32>wmic diskdrive获取pnpdeviceid
PNPDeviceID
USBSTOR\DISK&VEN_SONY&PROD_STORAGE_MEDIA&REV_PMAP\5C3000637C2070A595&0
USBSTOR\DISK&VEN_BM&PROD_&REV_1.10\070007AA1F02CF40063F&0

这些是从我的微型过滤器返回的序列号:

找到序列号57C03A050905。 找到序列号070007AA1F02CF400630。

可以看出,第二个设备的序列号已成功返回,但第一个设备的序列号未成功返回。那么,我的微型过滤器接收到的序列号是什么?这是否存储在可以查询的地方

如果需要,我可以附加代码,但由于我正确获得了一些序列号,我怀疑我的代码是错误的

编辑:代码

STORAGE_PROPERTY_QUERY query;
pQuery.PropertyId = StorageDeviceProperty;
pQuery.QueryType = PropertyStandardQuery

KeInitializeEvent(&event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY, pDeviceObject, (PVOID)&query, sizeof(query), infoBuffer,
                                        sizeof(infoBuffer), FALSE, &event, &ioStatusBlock);
if (Irp) {
    if(!NT_SUCCESS(IoCallDriver(pDeviceObject, Irp)))
        return STATUS_FLT_DO_NOT_ATTACH;
}
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
pDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)infoBuffer;

ULONG offset = pDescriptor->SerialNumberOfffset;
size_t size;
if (offset == 0) 
    return;

PCHAR c = offset + &buffer[0];
size = strlen(c);
*dest = ExAllocatePoolWithTag(PagedPool, size + 1, 'DIcI');
RtlZeroMemory(*dest, size + 1);
RtlCopyMemory(*dest, c, size + 1);

DbgPrint("Serial Number Found %s \n", *dest);
// String comparison of serial number and more processing
在我的外部硬盘上进行了测试,这是我从设备管理器得到的

575834314137363534565656 
从我的迷你过滤器:

WX41A7654VVV 
似乎设备管理器中的序列号是我从微型过滤器中获得的序列号的十六进制表示

57 58 34 31 41 37 36 35 34 56 56 56 

W  X  4  1  A  7  6  5  4  V  V  V 
所以,对于某些设备,它是以十六进制格式表示的,而其他设备是以字符格式表示的

那么,从内核级别获取序列号还是调用用户应用程序更容易呢?

是可变长度结构。成功后呼唤需要

检查其大小成员以确定字节数 结构实际上需要

但在您的代码中,我查看
infoBuffer,sizeof(infoBuffer)
——这意味着您对
存储设备描述符使用硬编码大小

确实需要发送
IOCTL\u STORAGE\u QUERY\u属性
并将大小成员与OutputBufferLength进行比较,如果它更大,则再次发送
IOCTL\u STORAGE\u QUERY\u属性
,并使用更大的OutputBufferLength


。。。由于我正确地获得了一些序列号,我怀疑我的代码是错误的
,这是一种完全错误的思维方式。。。发布您的代码,并询问是否有人能够发现在原始帖子中编辑的错误,以添加代码
infoBuffer,sizeof(infoBuffer)
-这表示您对
infoBuffer
使用硬编码数组-这已经是错误。它的大小未知,您需要在运行时查询它。正确的代码-真正包含许多错误的代码。您没有检查从
IoCallDriver
返回的状态。但是,它可以是
状态\缓冲区\溢出
。即使在
STATUS\u SUCCESS
上,您也需要检查
Size
存储设备\u描述符的成员,如果它大于
sizeof(infoBuffer)
则需要使用此
Size
缓冲区大小重新发送请求。调用
KeWaitForSingleObject
exist仅在
STATUS\u PENDING
的情况下才有意义,是什么让您认为设备id包含确切的序列号?这个字符串的确切格式是未记录的AFAIK。接受这个答案是因为它教会了我一些东西。虽然这并不能解决我的问题。OSR论坛上的Slava Imameev说:请求沿着设备堆栈传播。完成它的第一个驱动程序/筛选器报告一些ID。在所有情况下,这可能不是有效的硬件ID。此外,某些设备没有唯一的硬件ID。如果请求唯一ID,驱动程序将提供软件生成的ID。对于USB设备,此ID具有“&”符号。我很可能会创建一个用于调用用户级应用程序的端口,从中可以检索信息。谢谢你的帮助。@qwn-当然不是所有的硬件都有
SerialNumber
。这就是查询
存储\设备\描述符的正确方式。如果在某些情况下,
SerialNumber
未返回-不是因为代码无效,而是因为此信息不存在。当然也没什么不同-从用户或内核空间查询-这是对您问题的回答-
使用IOCTL\u STORAGE\u query\u属性获取序列号
。如果你真的想要另一个,你需要问另一个问题。如果你想了解其他信息,比如获取设备接口,你需要打电话
void PrintSerial(PDEVICE_OBJECT DeviceObject)
{
    STORAGE_PROPERTY_QUERY spq = { StorageDeviceProperty, PropertyStandardQuery }; 

    union {
        PVOID buf;
        PSTR psz;
        PSTORAGE_DEVICE_DESCRIPTOR psdd;
    };

    ULONG size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 0x100;

    NTSTATUS status;

    do 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        if (buf = ExAllocatePool(PagedPool, size))
        {
            switch (status = IoControlDevice(DeviceObject, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), buf, size))
            {
            case STATUS_SUCCESS:
            case STATUS_BUFFER_OVERFLOW:

                if (psdd->Version == sizeof(STORAGE_DEVICE_DESCRIPTOR))
                {
                    if (psdd->Size > size)
                    {
                        size = psdd->Size;
                        status = STATUS_BUFFER_OVERFLOW;
                    }
                    else
                    {
                        if (psdd->SerialNumberOffset)
                        {
                            DbgPrint("SerialNumber = %s\n", psz + psdd->SerialNumberOffset);
                        }
                        else
                        {
                            DbgPrint("SerialNumberOffset==0\n");
                        }
                    }
                }
                else
                {
                    status = STATUS_INVALID_PARAMETER;
                }
                break;
            }

            ExFreePool(buf);
        }
    } while (status == STATUS_BUFFER_OVERFLOW);
}

NTSTATUS IoControlDevice(
                       PDEVICE_OBJECT DeviceObject,
                       ULONG IoControlCode,
                       PVOID InputBuffer,
                       ULONG InputBufferLength,
                       PVOID OutputBuffer,
                       ULONG OutputBufferLength,
                       BOOLEAN InternalDeviceIoControl = FALSE
                       )
{
    KEVENT Event;
    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    IO_STATUS_BLOCK  IoStatusBlock;

    if (PIRP Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceObject, InputBuffer, InputBufferLength,
        OutputBuffer, OutputBufferLength, InternalDeviceIoControl, &Event, &IoStatusBlock))
    {
        NTSTATUS status = IofCallDriver(DeviceObject, Irp);

        if (status == STATUS_PENDING)
        {
            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 0);

            status = IoStatusBlock.Status;
        }

        return status;
    }

    return STATUS_INSUFFICIENT_RESOURCES;
}