所以我正在尝试编写一个仅连接到特定USB设备的微过滤器驱动程序,以区分所述设备,我使用了产品ID +供应商ID +序列号的组合。
我可以成功将IOCTL_STORAGE_QUERY_PROPERTY发送到返回产品ID,供应商ID,序列号的设备。
我遇到的问题是返回到我的minifilter的序列号对于某些USB是正确的,但不是全部。
例如:当我打电话时
C:\Windows\system32>wmic diskdrive get pnpdeviceid
PNPDeviceID
USBSTOR\DISK&VEN_SONY&PROD_STORAGE_MEDIA&REV_PMAP\5C3000637C2070A595&0
USBSTOR\DISK&VEN_BM&PROD_&REV_1.10\070007AA1F02CF40063F&0
这些是我的minifilter返回的序列号:
Serial Number found 57C03A050905.
Serial Number found 070007AA1F02CF400630.
可以看出第二个设备的序列号已成功返回,但第一个没有。那么我的minifilter接收的序列号是多少?这是存储在可以查询的地方吗?
如果需要,我可以附加代码,但由于我正确获得了一些序列号,我怀疑我的代码是错误的。
编辑:代码
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
来自我的minifilter:
WX41A7654VVV
设备管理器中的序列号似乎是我从minifilter获得的序列号的十六进制表示
57 58 34 31 41 37 36 35 34 56 56 56
W X 4 1 A 7 6 5 4 V V V
所以对于某些设备,它以十六进制格式表示,而其他设备是Char格式?
那么无论如何从内核级别获取序列号,或者只是更容易调用用户应用程序?
答案 0 :(得分:0)
STORAGE_DEVICE_DESCRIPTOR
是可变长度结构。成功通话后IOCTL_STORAGE_QUERY_PROPERTY
需要
检查其大小成员以确定其字节数 结构实际上需要。
但在我的代码中我查看infoBuffer, sizeof(infoBuffer)
- 这意味着您使用STORAGE_DEVICE_DESCRIPTOR
的硬编码大小。
确实需要发送IOCTL_STORAGE_QUERY_PROPERTY
并将大小成员与 OutputBufferLength 进行比较,如果更大 - 再次使用较大的 OutputBufferLength发送IOCTL_STORAGE_QUERY_PROPERTY
。
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;
}