我是com技术的新手,但我要做的是为com创建一个基本的包装器,特别是音频com(mmdevapi)。它应该像这样工作:我的程序调用一个com(也是由我创建),最后将加载并返回一个指向音频接口的指针。我试图让所有内容尽可能透明但我需要更多关于加载com时调用的信息。根据我的理解:
CoInitialize称为
CoCreateInstance的:
一个。在注册表中搜索dll
湾加载库
℃。在DllGetClassObject上获取地址(我猜它没有检查其他函数DllCanUnloadNow)
d。跳转到传递程序请求的clsid的函数(一个clsid用于非常对象 - 所以在一个dll中有多个对象?每个"对象"包含多个类?)和接口' s标识。
即DllGetClassObject返回一个指向接口的void指针。
如果我写的所有内容都是正确的,那么这应该符合我的需要(这是主程序使用的包装程序的一部分):
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但我不认为这是一个问题)。
答案 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时对我有用。 (我很新,所以我的理解和术语肯定有错误,但这就是我理解错误的方法。)