当我尝试打印所有USB设备(Winapi)时,我只能看到一个USB字符串

发布于 2025-01-17 22:47:44 字数 1098 浏览 2 评论 0原文

每当将新的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;
}

I try to print a message whenever a new USB device is connected to my PC, but I don't want to create an application which just catches and treats the events triggered by the windows' kernel. So I used some specific functions in order to print the active USB devices and then, whenever a new device is plugged in, a signal produces something (a pop-up or something like that). Thus, firstly, I tried to enumerate all the USB devices, but I had no success as long as I receive only one line of text which represents a specific USB device, not all the USB devices connected. Here is the code

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

妥活 2025-01-24 22:47:45

CM_Get_Device_Interface_ListA返回项目列表是 双 null 终止列表(另请参阅为什么双空终止字符串而不是指向字符串的指针数组? 的基本原理)。文档中没有明确说明这一点,但可以从 Buffer 的参数类型推断:PZZSTR

它在 winnt.h 中声明如下:

typedef _NullNull_terminated_ CHAR *PZZSTR;

这实际上只是一个 char* 但带有 _NullNull_termminate_ SAL 注释。它允许静态代码分析器了解PZZSTR的附加语义,并为开发人员提供提示。

相关代码仅打印第一个 NUL 字符之前的字符,即它最多显示列表中的一项。要显示所有项目,您必须迭代字符串,直到找到空字符串:

    char const* current{ buffer };
    while (*current != '\0') {
        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() };
    // ...

The format used by 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? for rationale). This isn't explicitly spelled out in the documentation, but can be inferred from the argument type of Buffer: PZZSTR.

It is declared in winnt.h like this:

typedef _NullNull_terminated_ CHAR *PZZSTR;

This is really just a char* but with the _NullNull_terminated_ SAL annotation. It allows static code analyzers to know about the additional semantics of PZZSTR, and serves as a hint to developers.

The code in question only prints characters up to the first NUL character, i.e. it displays at most one item from the list. To display all items, you'll have to iterate over the strings until you find an empty string:

    char const* current{ buffer };
    while (*current != '\0') {
        std::cout << current << std::endl;
        current += strlen(current) + 1;
    }

That fixes the immediate issue. To make the code actually work, you'll have to fix the potential memory corruption bug. In the call to CM_Get_Device_Interface_ListA you're telling the API that buffer is pointing to length bytes of memory, but you allocated MAX bytes.

The arguments of Buffer and BufferLen must match the actual allocation. Speaking of which, you never actually clean up that memory. Using a std::vector solves both issues:

    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() };
    // ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文