我是com技术的新手,但是我想做的是为com创建一个基本的包装器,特别是音频com(mmdevapi)。它应该像这样工作:我的程序调用一个com(也是我创建的),最后将加载并返回指向音频接口(interface)的指针。我试图使所有内容都尽可能透明,但是我需要有关加载com时所进行的调用的更多信息。据我了解:

  • CoInitialize称为
  • CoCreateInstance:

    一种。在注册表中搜索dll

    b。加载库

    C。在DllGetClassObject上获取地址(我想它不会检查其他函数DllCanUnloadNow)

    d。跳转到传递程序所要求的clsid的函数(对于一个对象,一个clsid,因此一个dll中有多个对象?每个“对象”包含多个类?)和接口(interface)的ID。

    e。 DllGetClassObject返回指向该接口(interface)的void指针。
  • 因为dll与程序加载在相同的内存中,所以可以使用此指针从接口(interface)访问方法。

  • 如果我写的所有内容都是正确的,那么这应该适合我的需求(这是包装程序com的一部分,由主程序使用):
    STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppvObj) {
        //main();
        //print iid from here..
        LPOLESTR s;
        StringFromCLSID(rclsid, &s);
        OutputDebugStringW(s);
        CoTaskMemFree(s);
    
        StringFromCLSID(riid, &s);
        OutputDebugStringW(s);
        CoTaskMemFree(s);
    
        //prints: {BCDE0395-E52F-467C-8E3D-C4579291692E}  -the audio clsid
        //        {00000001-0000-0000-C000-000000000046}  -the requested interface
    
        // {D3C5025B-3634-4F74-9404-942ECEFC1152}  -contains the dll for audio
        static const GUID custom_Audio_GUID =
        { 0xd3c5025b, 0x3634, 0x4f74,{ 0x94, 0x4, 0x94, 0x2e, 0xce, 0xfc, 0x11, 0x52 } };
    
        CoInitialize(NULL);
        CoCreateInstance(custom_Audio_GUID, NULL, CLSCTX_INPROC_SERVER, riid, ppvObj);  //The program wants to access an interface from the audio com so I have to bypass this com,load the audio and request the interface and pass it to the program
    
        return S_OK;
    }
    

    因此,对于该程序,它不需要做其他任何事情(它可以使用QueryInterface并使用我的com返回的ppvObj占用其余接口(interface))。但是,当然,这是行不通的。它加载音频dll,生成代理,但音频不起作用。有任何想法吗?

    (自定义clsid是在CURRENT_USER中的CLSID中定义的。它仅包含InprocServer32 / Default -no公寓配置;我尚未定义DLLCanUnload,但我认为这不是问题)。

    最佳答案

    最后我解决了这个问题。什么问题?我无法使用CoGetClassObject或CoCreateInstance,因为那些函数加载了音频dll,并使用自定义clsid调用了DllGetClassObject,并在其下移动了mmdevapi.dll(原来的clsid现在托管了我的dll)。由于com属性,dll可以托管许多“对象”,每个对象都由clsid表示。每个对象都包含由IID标识的接口(interface)。现在,Chrome通常使用clsid {BCDE0395-E52F-467C-8E3D-C4579291692E}调用mmdevapi.dll的DllGetClassObject。在其DllGetClassObject函数内部,它试图通过查看程序传递给此函数的clsid(在长if语句或switch中)来找出类。如果找到匹配的clsid,则返回匹配的接口(interface),Chrome也指定了该接口(interface)。

    在我的情况下,我试图从mmdevapi dll获得与Chrome相同的接口(interface)(因为我正在将其调用转发到DllGetClassObject),使用代码:

    CoGetClassObject(custom_Audio_GUID, NULL, CLSCTX_INPROC_SERVER, riid, ppvObj);
    

    但是,custom_Audio_GUID与所请求的clsid不同,因此mmdevapi始终返回CLASS_E_CLASSNOTAVAILABLE。

    我的解决方案:
      HMODULE dll=LoadLibrary("mmdevapi.dll");    //I can load the exact dll I need,without the registry lookup
      Func load=(load)GetProcAddr(dll,"DllGetClassObject");
      load(rclsid, riid, ppvObj);   //and I can pass the exact params I want
    

    这对我尝试绕过com很有帮助。 (我是新来的,所以我的理解和术语中肯定存在错误,但这就是我对错误的理解)。

    09-30 20:35