当我尝试打印所有 USB 设备 (WinAPI) 时,我只能看到一个 USB 字符串
I can see only one USB string when I try to print all the USB devices (WinAPI)
每当新的 USB 设备连接到我的 PC 时,我都会尝试打印一条消息,但我不想创建一个应用程序来捕获和处理由 windows' 内核触发的事件。所以我使用了一些特定的功能来打印活动的 USB 设备,然后,每当插入一个新设备时,就会产生一个信号(弹出窗口或类似的东西)。因此,首先,我尝试枚举所有 USB 设备,但只要我只收到代表特定 USB 设备的一行文本,而不是所有连接的 USB 设备,我就没有成功。这是代码
#pragma comment(lib, "Cfgmgr32")
#include <iostream>
#include <Windows.h>
#include <cfgmgr32.h>
#include <initguid.h>
#include <Usbiodef.h>
#define MAX 1024
int main()
{
ULONG length;
auto eroare1 = CM_Get_Device_Interface_List_SizeA(
&length,
(LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
NULL,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT
);
if (eroare1 != CR_SUCCESS)
{
std::cout << "eroare 1";
}
PSZ buffer;
buffer = new char[MAX];
auto eroare2 = CM_Get_Device_Interface_ListA(
(LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
NULL,
buffer
length,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT
);
if (eroare2 != CR_SUCCESS)
{
std::cout << "eroare";
}
std::cout << buffer << std::endl;
}
CM_Get_Device_Interface_ListA
to return a list of items is a double-null-terminated list (see also Why double-null-terminated strings instead of an array of pointers to strings? 所使用的格式)。这在文档中没有明确说明,但可以从 Buffer
的参数类型推断出来:PZZSTR
.
在winnt.h中是这样声明的:
typedef _NullNull_terminated_ CHAR *PZZSTR;
这实际上只是一个 char*
但带有 _NullNull_terminated_
SAL annotation。它允许静态代码分析器了解 PZZSTR
的附加语义,并作为对开发人员的提示。
有问题的代码只打印第一个 NUL 字符之前的字符,即它最多显示列表中的一个项目。要显示所有项目,您必须遍历字符串直到找到空字符串:
char const* current{ buffer };
while (*current != '[=11=]') {
std::cout << current << std::endl;
current += strlen(current) + 1;
}
这解决了眼前的问题。要使代码实际工作,您必须修复潜在的内存损坏错误。在对 CM_Get_Device_Interface_ListA
的调用中,您告诉 API buffer
指向 length
字节的内存,但您分配了 MAX
字节。
Buffer
和BufferLen
的参数必须与实际分配相匹配。说到这,你从来没有真正清理过那段记忆。使用 std::vector
解决了这两个问题:
std::vector<char> buffer(length);
auto eroare2 = CM_Get_Device_Interface_ListA(
(LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
NULL,
buffer.data(),
buffer.size(),
CM_GET_DEVICE_INTERFACE_LIST_PRESENT
);
// ...
char const* current{ buffer.data() };
// ...
每当新的 USB 设备连接到我的 PC 时,我都会尝试打印一条消息,但我不想创建一个应用程序来捕获和处理由 windows' 内核触发的事件。所以我使用了一些特定的功能来打印活动的 USB 设备,然后,每当插入一个新设备时,就会产生一个信号(弹出窗口或类似的东西)。因此,首先,我尝试枚举所有 USB 设备,但只要我只收到代表特定 USB 设备的一行文本,而不是所有连接的 USB 设备,我就没有成功。这是代码
#pragma comment(lib, "Cfgmgr32")
#include <iostream>
#include <Windows.h>
#include <cfgmgr32.h>
#include <initguid.h>
#include <Usbiodef.h>
#define MAX 1024
int main()
{
ULONG length;
auto eroare1 = CM_Get_Device_Interface_List_SizeA(
&length,
(LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
NULL,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT
);
if (eroare1 != CR_SUCCESS)
{
std::cout << "eroare 1";
}
PSZ buffer;
buffer = new char[MAX];
auto eroare2 = CM_Get_Device_Interface_ListA(
(LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
NULL,
buffer
length,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT
);
if (eroare2 != CR_SUCCESS)
{
std::cout << "eroare";
}
std::cout << buffer << std::endl;
}
CM_Get_Device_Interface_ListA
to return a list of items is a double-null-terminated list (see also Why double-null-terminated strings instead of an array of pointers to strings? 所使用的格式)。这在文档中没有明确说明,但可以从 Buffer
的参数类型推断出来:PZZSTR
.
在winnt.h中是这样声明的:
typedef _NullNull_terminated_ CHAR *PZZSTR;
这实际上只是一个 char*
但带有 _NullNull_terminated_
SAL annotation。它允许静态代码分析器了解 PZZSTR
的附加语义,并作为对开发人员的提示。
有问题的代码只打印第一个 NUL 字符之前的字符,即它最多显示列表中的一个项目。要显示所有项目,您必须遍历字符串直到找到空字符串:
char const* current{ buffer };
while (*current != '[=11=]') {
std::cout << current << std::endl;
current += strlen(current) + 1;
}
这解决了眼前的问题。要使代码实际工作,您必须修复潜在的内存损坏错误。在对 CM_Get_Device_Interface_ListA
的调用中,您告诉 API buffer
指向 length
字节的内存,但您分配了 MAX
字节。
Buffer
和BufferLen
的参数必须与实际分配相匹配。说到这,你从来没有真正清理过那段记忆。使用 std::vector
解决了这两个问题:
std::vector<char> buffer(length);
auto eroare2 = CM_Get_Device_Interface_ListA(
(LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
NULL,
buffer.data(),
buffer.size(),
CM_GET_DEVICE_INTERFACE_LIST_PRESENT
);
// ...
char const* current{ buffer.data() };
// ...