REGDB_E_CLASSNOTREG与客户端和服务器32位,注册表看起来没问题

时间:2013-06-18 12:45:54

标签: c++ com windows-7-x64 wow64

我在CLSID\{clsid}中使用WOW64版本注册了我的32位进程内组件(仅MyComponent.1MyComponentHKEY_CURRENT_USER\Software\Classes键及其子键) REGSVR32。当我尝试使用来自我的32位进程的CoCreateInstance()创建它时,它失败了REGDB_E_CLASSNOTREG。

但是当我从32位进程手动检索HKEY_CLASSES_ROOT\CLSID\{clsid}\InprocServer32并手动加载DLL以调用DllGetClassObject()时,它会成功!

我不明白。什么是CoCreateInstance()和CoGetClassObject()这样做,当我的代码执行他们应该做的工作时,它们会因REGDB_E_CLASSNOTREG而失败?

//This code fails with REGDB_E_CLASSNOTREG
STDMETHODIMP CreateTestCOM1(ITestCOM ** ppTestCOM, void **ppContext)
{
    assert(ppContext!=NULL);
    if(ppContext==NULL)
        return E_INVALIDARG;

    *ppContext = NULL;
    HRESULT hr = E_NOTIMPL;
//I tried both CoCreateInstance and CoGetClassObject, they both fail.
#if 0
    hr = CoCreateInstance(CLSID_TestCOM, NULL, CLSCTX_INPROC_SERVER, IID_ITestCOM, reinterpret_cast< void ** >(ppTestCOM));
#else
    IClassFactory *pFactory = NULL;
    hr = CoGetClassObject(CLSID_TestCOM, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, reinterpret_cast< void ** >(&pFactory));
    if(SUCCEEDED(hr))
    {
        hr = pFactory->CreateInstance(NULL, IID_ITestCOM, reinterpret_cast< void ** >(ppTestCOM));
        RELEASE_INTERFACE(pFactory);
    }
#endif
    return hr;
}
//This code works perfectly.
STDMETHODIMP CreateTestCOM3(ITestCOM ** ppTestCOM, void **ppContext)
{
    HRESULT hrRet = E_FAIL;
    LPTSTR libFileName = NULL;
    HKEY hMyClsidKey = NULL;
    DWORD err = RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID\\{4883259C-527B-4327-B9BF-6C22079045B5}"), 0, KEY_READ, &hMyClsidKey);
    if(err != ERROR_SUCCESS)
    {
        _tprintf(_T("CreateTestCOM3: RegOpenKeyEx({CLSID}) failed with error %lu.\n"), err);
        hrRet = (err==ERROR_FILE_NOT_FOUND ? REGDB_E_CLASSNOTREG : E_UNEXPECTED);
    }
    else
    {
        HKEY hInprocKey = NULL;
        err = RegOpenKeyEx(hMyClsidKey, _T("InprocServer32"), 0, KEY_READ, &hInprocKey);
        if(err != ERROR_SUCCESS)
        {
            _tprintf(_T("CreateTestCOM3: RegOpenKeyEx(InprocServer32) failed with error %lu.\n"), err);
            hrRet = (err==ERROR_FILE_NOT_FOUND ? REGDB_E_KEYMISSING : E_UNEXPECTED);
        }
        else
        {
            TCHAR buf[MAX_PATH] = _T("");
            DWORD cbData = sizeof buf;
            DWORD type = 0;
            err = RegQueryValueEx(hInprocKey, NULL, NULL, &type, reinterpret_cast<LPBYTE>(buf), &cbData);
            if(err != ERROR_SUCCESS)
            {
                _tprintf(_T("CreateTestCOM3: RegQueryValueEx() failed with error %lu.\n"), err);
            }
            else if(type != REG_SZ)
            {
                _putts(_T("CreateTestCOM3: Inproc key's default value is not a REG_SZ."));
            }
            else if((cbData & 1) != 0)
            {
                _putts(_T("CreateTestCOM3: Inproc key's default value has odd size."));
            }
            else if(buf[MAX_PATH-1] != _T('\0'))
            {
                _putts(_T("CreateTestCOM3: Inproc key's default value is too long."));
            }
            else
            {
                libFileName = _tcsdup(buf);
                _tprintf(_T("CreateTestCOM3: Successfully retrieved DLL path: %s\n"), libFileName);
            }

            RegCloseKey(hInprocKey);
        }
        RegCloseKey(hMyClsidKey);
    }

    if(libFileName != NULL)
    {
        //LoadLibrary(), GetProcAddress(), DllGetClassObject(), IClassFactory::CreateInstance().
        hrRet = CreateTestCOMFromDLL(libFileName, ppTestCOM, ppContext);

        free(libFileName);
    }
    return hrRet;
}

我还使用WOW64版本的regedit检查了注册表,HKEY_CLASSES_ROOTHKEY_CURRENT_USER\Software\Classes从那里看起来很好。

编辑添加:我使用的是Windows 7,而不是XP / Vista。根据{{​​3}},这是一个重要的区别。

0 个答案:

没有答案