Windows设备:获取;地点“;UVC网络摄像头给定IMFActivate*的字符串

Windows设备:获取;地点“;UVC网络摄像头给定IMFActivate*的字符串,windows,winapi,ms-media-foundation,device-manager,uvc,Windows,Winapi,Ms Media Foundation,Device Manager,Uvc,当转到Windows的“设备管理器”并单击(几乎)列表中的任何设备时,“常规”选项卡中的一条信息称为“位置”。这是一个字符串,它是: 人类可读,如“关于NVIDIA GeForce GTX 1080” 半有用,如“位置0(内部高清音频总线)”或“PCI总线9,设备0,功能0” USB位置,如“Port#0004.Hub#0015”或“0009.0000.0000.004.000.000.000.000.000” 这些信息可以通过Windows的API获得 我要寻找的是从给定的IMFActiv

当转到Windows的“设备管理器”并单击(几乎)列表中的任何设备时,“常规”选项卡中的一条信息称为“位置”。这是一个字符串,它是:

  • 人类可读,如“关于NVIDIA GeForce GTX 1080”
  • 半有用,如“位置0(内部高清音频总线)”或“PCI总线9,设备0,功能0”
  • USB位置,如“Port#0004.Hub#0015”或“0009.0000.0000.004.000.000.000.000.000”
这些信息可以通过Windows的API获得

我要寻找的是从给定的
IMFActivate
对象获取信息

有没有办法做到这一点?我找不到如何从激活对象获取“设备”信息。我唯一拥有的数据是它的“符号链接”(在我的例子中,这个字符串:
\?\usb\vid\u 04b4&pid\u 8888&mi\u 00#9&4fe28be&0&0000{e5323777-f976-4f5b-9b55-b94699c46e44}\global
),但该链接的格式与我在“位置”中看到的字符串完全不同

因此,我的问题是:给定设备的
IMFActivate
对象,如何获取设备的“位置”字符串

更新

下面是我用来“转换”符号链接的代码,该链接由
IMFActivate
提供,它是一个设备id字符串,可由设置api函数识别,然后提取“位置字符串”:

更新2

以下是在“声音、视频和游戏控制器”下的
devmgmt.msc
中看到的3个音频输入设备:

  • 中景生活影院(TM),位置:0000.0014.0000.013.003.000.000.000.000.000(符号链接:
    \?\SWD\MMDEVAPI{0.0.1.00000000}.{751fe058-cef2-4d28-bbeb-e438981938d7}{2eef81be-33fa-4800-9670-1cd474972c3f}
  • MS LifeCam Studio(TM),位置:0000.0014.0000.013.004.004.000.000.000(符号链接:
    \?\SWD\MMDEVAPI{0.0.1.00000000}.{59267d2e-940b-45f5-8655-45372787bd85}{2eef81be-33fa-4800-9670-1cd474972c3f}
  • SUB2r USB 3.0高清网络摄像头,位置:0009.0000.0000.004.000.000.000.000.000.000(符号链接:
    \?\SWD\MMDEVAPI{0.0.1.00000000}.{26a4f608-cbd8-4206-b958-d57ee6847153}{2eef81be-33fa-4800-9670-1CD47972C3F}
所有3个都是USB设备,所有3个都在调用
MFEnumDeviceSources
时列出,但它们的“符号链接”不解析为硬件设备。

使用
MF\u DEVSOURCE\u ATTRIBUTE\u SOURCE\u TYPE\u VIDCAP\u SYMBOLIC\u LINK
MF\u DEVSOURCE\u ATTRIBUTE\u SOURCE\u TYPE\u AUDCAP\u SYMBOLIC\u LINK
返回的字符串这是我们可以用作输入的设备接口字符串。要获取位置信息(如果存在),需要执行3个步骤:

  • 打电话给 -结果我们得到了设备实例 设备标识符
  • 在调用中使用返回的字符串
  • 最后打电话给
  • 代码示例:

    CONFIGRET PrintLocation(PCWSTR pszDeviceInterface)
    {
        ULONG cb = 0, rcb = 64;
    
        static volatile UCHAR guz;
    
        PVOID stack = alloca(guz);
        DEVPROPTYPE PropertyType;
    
        CONFIGRET err;
    
        union {
            PVOID pv;
            PWSTR sz;
            PBYTE pb;
        };
    
        do 
        {
            if (cb < rcb)
            {
                rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
            }
    
            if (!(err = CM_Get_Device_Interface_PropertyW(pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, pb, &rcb, 0)))
            {
                if (PropertyType == DEVPROP_TYPE_STRING)
                {
                    DbgPrint("InstanceId=%S\n", sz);
    
                    DEVINST dnDevInst;
    
                    if (!(err = CM_Locate_DevNodeW(&dnDevInst, sz, CM_LOCATE_DEVNODE_NORMAL)))
                    {
                        do 
                        {
                            if (cb < rcb)
                            {
                                rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
                            }
    
                            if (!(err = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_Device_LocationInfo, &PropertyType, pb, &rcb, 0)))
                            {
                                if (PropertyType == DEVPROP_TYPE_STRING)
                                {
                                    DbgPrint("Location=%S\n", sz);
                                }
                                else
                                {
                                    err = CR_WRONG_TYPE;
                                }
                            }
    
                        } while (err == CR_BUFFER_SMALL);
                    }
                }
                else
                {
                    err = CR_WRONG_TYPE;
                }
    
                break;
            }
    
        } while (err == CR_BUFFER_SMALL);
    
        return err;
    }
    
    对于
    IMFActivate
    ,我们可以使用下一个代码:

    void mftest()
    {
        IMFAttributes *pAttributes;
    
        if (SUCCEEDED(MFCreateAttributes(&pAttributes, 1)))
        {
            UINT32 count, cchLength;
            IMFActivate **ppDevices, *pDevice;
    
            if (SUCCEEDED(pAttributes->SetGUID(
                MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)) && 
                SUCCEEDED(MFEnumDeviceSources(pAttributes, &ppDevices, &count)) &&
                count)
            {
                PVOID pv = ppDevices;
    
                do 
                {
                    pDevice = *ppDevices++;
    
                    PWSTR pszDeviceInterface;
    
                    if (SUCCEEDED(pDevice->GetAllocatedString(
                        MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &pszDeviceInterface, &cchLength)))
                    {
                        DbgPrint("%S\n", pszDeviceInterface);
    
                        PrintLocation(pszDeviceInterface);
    
                        CoTaskMemFree(pszDeviceInterface);
                    }
    
                } while (--count);
    
                CoTaskMemFree(pv);
            }
    
            pAttributes->Release();
        }
    }
    

    如果您有符号链接(sz)-调用
    CM\u Locate\u DEVNODE(&dnevinst,sz,CM\u Locate\u DEVNODE\u NORMAL)
    ,然后调用
    CM\u Get\u DEVNODE\u PropertyW(dnevinst,&devkey\u Device\u LocationInfo,&PropertyType,pb,&rcb,0)
    ,您得到了位置调用
    CM\u Locate\u Locate\u DEVNODE()
    返回
    CR\u无效的设备ID
    。我想,
    IMFActivation
    对象提供的“符号链接”不是安装api所期望的:((请参阅我的原始帖子,了解该链接的示例)是的,我错了。这里确实需要设备id,在您的情况下,它将是
    usb\vid_04b4&pid_8888&mi_00\9&4fe28be&0&0000
    我确切知道内部(未记录)规则如何从设备id(append\\?\、convert\ to#、append class guid)生成符号链接,在您的情况下,这是
    {e5323777-f976-4f5b-9b55-b94699c46e44}
    (静态\u KSCATEGORY\u VIDEO\u CAMERA),但如何以文档化的方式实现这一点不确定找到正确的方式-需要先调用
    CM\u获取设备接口\u属性(pszDeviceInterface,&DEVPKEY\u Device\u InstanceId
    ,带有
    IMFAttributes::Get[Allocated]string
    返回的字符串,然后已经在call
    CM\u Locate\u DevNode
    CM\u Get\u DevNode\u属性中使用返回的设备id,我找不到“location”的最大长度是
    MAX\u PATH
    1024
    或其他什么。它“感觉”像
    MAX\u PATH
    应该是它,但我不能确认这一点。@YePhIcK-我通常不喜欢硬编码缓冲区大小,而是在循环中动态分配它-从一些合理的大小开始,如果
    CR\u buffer\u SMALL
    分配额外的空间-像
    PrintLocation
    那样,该方法对视频捕获设备非常有效。失败(
    CM\u Get\u DevNode\u PropertyW()
    返回
    CR\u NO\u这样的值
    )用于音频捕获设备。只是做个笔记here@YePhIcK-是的,对于音频,不返回位置。但这不是错误。不是每个设备都有位置信息。这取决于每个具体设备-有些有,有些没有。查看
    devmgmt.msc
    -您得到了相同的结果。并且一些属性对接口有意义(
    CM\u Get\u Device\u Interface\u PropertyW
    )和一些仅用于设备实例的(
    CM\u Get\u DevNode\u PropertyW
    )-请注意,同一个设备实例可以有多个接口。因为此位置仅存在于devnode中,而不存在于interface中。还可以尝试查找
    devpkey.h
    中定义的其他键。例如,您可以将
    devpkey\u device\u LocationInfo
    更改为
    devpkey\u device\u FriendlyName
    query.i for
    MF\u DEVSOURCE\ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK
    got
    microscope(高清音频设备)
    Device id is
    SWD\MMDEVAPI\{0.0.1.00000000}.{6630cade-5c94-4e5f-8a6e-ee02877a4f3f}
    CONFIGRET PrintLocationSimp(PCWSTR pszDeviceInterface)
    {
        WCHAR buf[1024];
    
        DEVPROPTYPE PropertyType;
    
        ULONG BufferSize = sizeof(buf);
    
        CONFIGRET err;
    
        if (!(err = CM_Get_Device_Interface_PropertyW(pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, (PBYTE)buf, &BufferSize, 0)))
        {
            if (PropertyType == DEVPROP_TYPE_STRING)
            {
                DbgPrint("InstanceId=%S\n", buf);
    
                DEVINST dnDevInst;
    
                if (!(err = CM_Locate_DevNodeW(&dnDevInst, buf, CM_LOCATE_DEVNODE_NORMAL)))
                {
                    BufferSize = sizeof(buf);
    
                    if (!(err = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_Device_LocationInfo, &PropertyType, (PBYTE)buf, &BufferSize, 0)))
                    {
                        if (PropertyType == DEVPROP_TYPE_STRING)
                        {
                            DbgPrint("Location=%S\n", buf);
                        }
                        else
                        {
                            err = CR_WRONG_TYPE;
                        }
                    }
                }
            }
            else
            {
                err = CR_WRONG_TYPE;
            }
        }
    
        return err;
    }
    
    void mftest()
    {
        IMFAttributes *pAttributes;
    
        if (SUCCEEDED(MFCreateAttributes(&pAttributes, 1)))
        {
            UINT32 count, cchLength;
            IMFActivate **ppDevices, *pDevice;
    
            if (SUCCEEDED(pAttributes->SetGUID(
                MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)) && 
                SUCCEEDED(MFEnumDeviceSources(pAttributes, &ppDevices, &count)) &&
                count)
            {
                PVOID pv = ppDevices;
    
                do 
                {
                    pDevice = *ppDevices++;
    
                    PWSTR pszDeviceInterface;
    
                    if (SUCCEEDED(pDevice->GetAllocatedString(
                        MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &pszDeviceInterface, &cchLength)))
                    {
                        DbgPrint("%S\n", pszDeviceInterface);
    
                        PrintLocation(pszDeviceInterface);
    
                        CoTaskMemFree(pszDeviceInterface);
                    }
    
                } while (--count);
    
                CoTaskMemFree(pv);
            }
    
            pAttributes->Release();
        }
    }