coregisterclassobject doesn't work with a class factory marshalled from another thread

1.4k Views Asked by At

I'm trying to use CoRegisterClassObject to customize the way I load dll's that have com objects in them. I'm trying something out that will solve a problem I was having when the thread's apartment type didn't match the com object's. I'm having a problem though where coregisterclassobject returns S_OK, but doesn't seem to do anything, since the com object still relies on the registry to be created. Here's a sample that I wrote as a proof of concept that's failing (TestComObj is apartment threaded).

LPSTREAM factory_stream = NULL; //GLOBAL VARIABLE FOR TEST

DWORD __stdcall FactoryThread(LPVOID param)
{
   CoInitialize(NULL);

   CustomClassFactory *factory = new CustomClassFactory();
   factory->AddRef();
   CoMarshalInterThreadInterfaceInStream(IID_IClassFactory, (IClassFactory*)factory, &factory_stream);
   MSG msg;
   while (GetMessage(&msg, NULL, 0, 0)) 
   {
     TranslateMessage(&msg);
     DispatchMessage(&msg);
   }
   factory->Release();
   CoUninitialize();
   return 0;
}

And here's the relevant part of my main function.

CoInitializeEx(NULL, COINIT_MULTITHREADED);

HANDLE regThread = CreateThread(NULL, 0, FactoryThread, NULL, 0, NULL);
Sleep(5000); //ensures that the factory is registered

IClassFactory *factory = NULL;
CoGetInterfaceAndReleaseStream(factory_stream, IID_IClassFactory, (void**)&factory);

DWORD regNum = 0;
HRESULT res = CoRegisterClassObject(clsid, factory, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &regNum);
//res == S_OK
{
   TestComObjLib::ITestComObjPtr ptr;
   HRESULT hr = ptr.CreateInstance(__uuidof(TestComObjLib::TestComObjCoClass), NULL);
   //hr == E_NOINTERFACE HERE if not registered in the registry
}
CoRevokeClassObject(regNum);
CoUninitialize();

The idea was that since the registry shouldn't be used with CoRegisterClassObject, I needed to manually create the apartment threaded objects in an STA instead of the current MTA thread. I noticed that when not using CoRegisterClassObject, CoGetClassObject spawns a new thread and calls DllGetClassObject in that thread, so I figured the class factory just needed to be created in an STA and then the objects will live there.

The problem I'm seeing is that in the code above, it still uses the registry to create TestComObj, even though the ClassFactory behaves correctly normally. It's pretty simple right now. It just calls LoadLibrary on the correct dll, then calls dllgetclassobject, and calls createinstance on the result of that. When not dealing with apartment and threading issues, I can use it to create the com object without it being registered. So I'm not sure what's going wrong here.

0

There are 0 best solutions below