COM对象注册损坏

时间:2009-04-04 04:24:07

标签: c++ windows com

这是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注册中,但找不到任何实际上确切地说明注册表中所需的内容。我有点反向设计我现在储存的东西。

1 个答案:

答案 0 :(得分:2)

本文COM in plain C非常好地描述了如何在不使用ATL的情况下实现COM dll。如1800所示,将调用DllGetClassObject来创建COM对象。另外The COM Programmer's Cookbook是关于COM的很好的参考。