This was a very hard debugging session. Suddenly I found that while using exactly the same DLLs,
Wizard was failing to open a RAPI connection while
Console was working without any issues. Yes, the code and the binaries were the same. I tried everything, from file and directory rights to the .NET trust, not forgetting the application threading model. Nothing worked: Wizard consistently reported an
E_INVALIDARG error when calling
CeRapiInitEx (both static and dynamically linked). What to do?
Out of desperation I called the RAPI initialization code on the main form constructor. Surprise: it works! If I move the code to the button event handler it failed. Then I tried the code on the form load event, only to find that the code also failed. What could be happening between the main form constructor and the form event handling code?
Wait, let's try the code at the
end of the main form constructor.
Voilá, it failed. At the start of the constructor I get an
S_OK and at the end I get an
E_INVALIDARG. Why? Some time ago I tried to be really smart (lesson: don't try to be smart) and wrote some code that would test the presence of a particular database engine OLE DB
CLSID so that the user would see a list of the available engines on her PC. This actually worked badly and instead of dynamically building the UI labels, I went back to static text
but I forgot to remove the calls. They look like this:
DPTRACK_API int IsLocalEngineInstalled(GUID guid)
{
CComPtr<IDBInitialize> spInitialize;
HRESULT hr;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = CoCreateInstance(guid, NULL, CLSCTX_INPROC_SERVER,
IID_IDBInitialize,
(void**)&spInitialize);
CoUninitialize();
return SUCCEEDED(hr);
}
After removing the calls to this toxic code, Wizard works again! Why is CeRapiInitEx sensitive to COM initialization?