COM包装器调用链C ++

时间:2017-10-01 14:17:19

标签: c++ audio com wrapper

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

  1. CoInitialize称为

  2. CoCreateInstance的:

    一个。在注册表中搜索dll

    湾加载库

    ℃。在DllGetClassObject上获取地址(我猜它没有检查其他函数DllCanUnloadNow)

    d。跳转到传递程序请求的clsid的函数(一个clsid用于非常对象 - 所以在一个dll中有多个对象?每个"对象"包含多个类?)和接口' s标识。

    即DllGetClassObject返回一个指向接口的void指针。

    1. 因为dll加载到与程序相同的内存中,所以可以使用此指针从界面访问方法。
  3. 如果我写的所有内容都是正确的,那么这应该符合我的需要(这是主程序使用的包装程序的一部分):

    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等其余接口)。但是,当然,它不起作用。它加载音频dll,产生一个代理,但音频不起作用。有什么想法吗?

    (自定义clsid在CLSID中的CURRENT_USER中定义。它只包含InprocServer32 / Default -no apartment config;我还没有定义DLLCanUnload但我不认为这是一个问题)。

1 个答案:

答案 0 :(得分:2)

最后我解决了这个问题。什么问题?我无法使用CoGetClassObject或CoCreateInstance,因为这些函数加载了音频dll并使用自定义 clsid调用了DllGetClassObject,我在其中移动了mmdevapi.dll(原始clsid现在正在托管 my < / em> dll)。由于com属性,dll可以托管许多&#34;对象&#34; ,每一个都由一个clsid代表。每个对象都包含由IID标识的接口。现在,通常Chrome浏览器使用clsid {BCDE0395-E52F-467C-8E3D-C4579291692E}调用mmdevapi.dll的DllGetClassObject。在它的DllGetClassObject函数中,它试图通过查看程序传递给该函数的clsid来计算出类(在long if语句或开关中)。如果找到匹配的clsid,则返回匹配的接口,其iid也由Chrome指定。

就我而言,我试图使用以下代码从mmdevapi dll获取与Chrome相同的界面(因为我将其调用转发给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时对我有用。 (我很新,所以我的理解和术语肯定有错误,但这就是我理解错误的方法。)