这是Register implementation of a com interface的延续;直到现在我才有了需要调试的实际代码。
我有两个COM对象,一个实现IAudioSessionEvents,另一个实现IClassFactory并生成第一个对象。
以下代码注册这些对象(根据我对COM注册的理解):
BOOL RegisterClassManually(WCHAR* szGuid, WCHAR* szDllPath)
{
WCHAR szKeyName[1024];
wsprintf(szKeyName, TEXT("Software\\Classes\\CLSID\\%s"), szGuid);
if(!RegisterKeyValue(HKEY_CURRENT_USER, szKeyName, NULL, TEXT(DESCRIPTION_CONST))) return false;
wsprintf(szKeyName, TEXT("Software\\Classes\\CLSID\\%s\\InprocServer32"), szGuid);
if(!RegisterKeyValue(HKEY_CURRENT_USER, szKeyName, NULL, szDllPath)) return false;
if(!RegisterKeyValue(HKEY_CURRENT_USER, szKeyName, TEXT("ThreadingModel"), TEXT("Apartment"))) return false;
return true;
}
STDAPI DllRegisterServer()
{
//Write data to HKEY_CURRENT_USER\\Software\\Classes\\CLSID\\{GUID}
// Also ""\\InProcServer32
// Also "".ThreadingModel = "Apartment"
WCHAR* szGuid;
WCHAR szDllPath[512];
StringFromCLSID(CLSID_AudioEventsFactory, &szGuid);
if(g_dllModule == NULL) return SELFREG_E_CLASS;
GetModuleFileName(g_dllModule, szDllPath, 512);
if(!RegisterClassManually(szGuid, szDllPath)) return SELFREG_E_CLASS;
StringFromCLSID(CLSID_AudioEvents, &szGuid);
if(!RegisterClassManually(szGuid, szDllPath)) return SELFREG_E_CLASS;
return S_OK;
}
我省略了RegisterKeyValue(...),它已经确认按照预期正常工作的简单注册码。
此代码尝试使用这些COM对象:
IAudioSessionEvents* listener = NULL;
IClassFactory* factory = NULL;
//Fails on this call
hr = CoGetClassObject(CLSID_AudioEventsFactory, CLSCTX_ALL, NULL, __uuidof(IClassFactory), (void**)&factory);
if(hr != S_OK)
{
... Report Error ...
}
hr = factory->CreateInstance(NULL, __uuidof(IAudioSessionEvents), (void**)&listener);
对CoGetClassObject(...)的调用返回hr = 0x80040111(ClassFactory无法提供请求的类)。
DllGetClassObject的实现(每1800条信息指出了这个问题):
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
if (clsid == __uuidof(IClassFactory))
{
AudioEventsFactory *pFact = new AudioEventsFactory;
if (pFact == NULL)
return E_OUTOFMEMORY;
else
{
return pFact->QueryInterface(iid , ppv);
}
}
return CLASS_E_CLASSNOTAVAILABLE;
}
我在这里做错了什么?我怀疑它在COM注册中,但找不到任何实际上确切地说明注册表中所需的内容。我有点反向设计我现在储存的东西。
答案 0 :(得分:2)
本文COM in plain C非常好地描述了如何在不使用ATL的情况下实现COM dll。如1800所示,将调用DllGetClassObject来创建COM对象。另外The COM Programmer's Cookbook是关于COM的很好的参考。