Wednesday, February 04, 2009

Why does CeRapiInitEx return E_INVALIDARG?

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?

2 comments:

vincent said...

My post is not directly about Oledblib but more about POOM.
I wanted to know if there is a mean of listing custom properties of a pimitem contact when you don't know properties name ?
From what I know IItem::GetProps can be used to retrieve properties but you need to specify a property name.
So how can I list all contact properties including custom ones. I suppose I might have to directly query cedb pim.vol and I wanted to know if you have ever done that kind of things ?

João Paulo Figueira said...

Never worked with this, but planning to.