当我尝试打印所有 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 字节。

BufferBufferLen的参数必须与实际分配相匹配。说到这,你从来没有真正清理过那段记忆。使用 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() };
    // ...