我是com技术的新手,但是我想做的是为com创建一个基本的包装器,特别是音频com(mmdevapi)。它应该像这样工作:我的程序调用一个com(也是我创建的),最后将加载并返回指向音频接口(interface)的指针。我试图使所有内容都尽可能透明,但是我需要有关加载com时所进行的调用的更多信息。据我了解:
一种。在注册表中搜索dll
b。加载库
C。在DllGetClassObject上获取地址(我想它不会检查其他函数DllCanUnloadNow)
d。跳转到传递程序所要求的clsid的函数(对于一个对象,一个clsid,因此一个dll中有多个对象?每个“对象”包含多个类?)和接口(interface)的ID。
e。 DllGetClassObject返回指向该接口(interface)的void指针。
如果我写的所有内容都是正确的,那么这应该适合我的需求(这是包装程序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很有帮助。 (我是新来的,所以我的理解和术语中肯定存在错误,但这就是我对错误的理解)。