Search code examples
c++comatl

_com_ptr_t CreateInstance returns REGDB_E_CLASSNOTREG


I have an ATL project where I need to perform various initialization routines inside CComObjectRootEx::FinalConstruct. For demonstration purposes, consider the following implementation:

HRESULT FinalConstruct()
{
    return m_bInit ? S_OK : E_FAIL;
}

This should return the appropriate HRESULT to the caller, indicating whether the initialization of the object was successful.

However, the client always receives REGDB_E_CLASSNOTREG instead of E_FAIL in case of failure, when trying to create the server:

#include <Windows.h>
#import <finalconstructtest.dll>

int main()
{
    HRESULT hr = CoInitialize(0);
    {
        finalconstructtestLib::IFCClassPtr p;

        // Returns REGDB_E_CLASSNOTREG
        hr = p.CreateInstance(__uuidof(finalconstructtestLib::FCClass));         
    }
    CoUninitialize();
    return 0;
}

When I change the class context to CLSCTX_INPROC_SERVER however, the intended HRESULT is returned correctly:

// Returns E_FAIL
hr = p.CreateInstance(__uuidof(finalconstructtestLib::FCClass), nullptr, CLSCTX_INPROC_SERVER);

I've seen this post, where a similar behavior could be observed. However, I can't seem to find any reason why the class context affects the return value of FinalConstruct. Is this intended and perhaps documented somewhere?


Solution

  • CoCreateInstance API is not promising to forward the internal failure code to the caller. The implementation prefers to indicate the the source of the problem its own way, by returning REGDB_E_CLASSNOTREG meaning that it was unable to complete instantiation. Which is in turn true: it indeed was unable to create an instance (and the problem is not, for instance, related to missing interface, marshaling, permissions etc.). That is, the API prefers to suppress internal failure code to replace it with a documented one.

    If you prefer to indicate a specific instantiate failure, you are better off with succeeding with initial creating an instance, and then you can implement an interface with a property or method exposing status, or giving relevant HRESULT error (with or without IErrorInfo support etc).