0

I registered my 32-bit in-process component (just the CLSID\{clsid}, MyComponent.1 and MyComponent keys, and their subkeys) in HKEY_CURRENT_USER\Software\Classes with the WOW64 version of regsvr32. When I try to create it with CoCreateInstance() from my 32-bit process, it fails with REGDB_E_CLASSNOTREG.

But when I manually retrieve HKEY_CLASSES_ROOT\CLSID\{clsid}\InprocServer32 from my 32-bit process and load the DLL manually to call DllGetClassObject(), it succeeds!

I don't get it. What are CoCreateInstance() and CoGetClassObject() doing that makes them fail with REGDB_E_CLASSNOTREG when my code that does what they're supposed to do works?

//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;
}

I've also checked the registry with the WOW64 version of regedit, and the both HKEY_CLASSES_ROOT and HKEY_CURRENT_USER\Software\Classes look fine from there.

Edited to Add: I'm on Windows 7, not XP/Vista. According to this, it's an important difference.

Medinoc
  • 6,577
  • 20
  • 42
  • You could try SysInternals' PROCMON tool to check what registry keys are used. You can filter using .exe also to help narrow it down. – Simon Mourier Jun 18 '13 at 13:04
  • 1
    Regsvr32 doesn't write to HKCU, it writes HKLM. And COM doesn't use the HKCR alias like you did, it looks in HKCU first, then HKLM. Add in the registry redirector to make it confusing ;) Yes, use ProcMon to see what is actually going on. – Hans Passant Jun 18 '13 at 14:10

0 Answers0