Lost Website

You Are Here

Archive for February, 2010

Ubuntu bugs. Is that kind of handling usual?

without comments

I am the author of bug #501192 in Ubuntu. The bug is about the fact that glib, in Ubuntu, doesn’t use the distribution specific way of getting the default terminal emulator: the x-terminal-emulator link. It’s not a big deal but I could not find any references to it in Launchpad, and elsewhere so I did like what a Good User should do and filed a bug report.

Today the bug went straight out from “New” to “Fix released”. It was never acknowledged, and nobody ever said it was working on it. I have no idea in which distribution the fix was released so I don’t even know if I can use a fixed version on my Karmic box. The bug report page, usually pretty heavy on details on Launchpad, is hopelessly useless.

I can only hope this is a mistake on the part of the reporter. If the bug really has been fixed, then the report really should have more informations about the fix. I don’t file that much bug reports on Ubuntu so I have no idea if this is common practice.

I have asked for more explanations and will this blog up to date.

Written by François-Denis Gonthier

February 13th, 2010 at 10:59 pm

Posted in Linux,News,Ubuntu

Tagged with , , ,

RAII COM wrapper

without comments

COM stands for Component Object Model. This is the technology behind most of non-trivial things in Windows, the why of the obscure HKEY_CLASSES_ROOT registry subtree and the core of the infamous ActiveX technology.

Now, I don’t know much about COM programming so this won’t be a tutorial on the subject. I know just the minimum I need to safely work with MAPI in the context of what I do at Kryptiva.

COM programming include many concepts of typical object-oriented programming languages. It’s just a lot more verbose. You can view COM interfaces as structures containing pointers to functions. COM classes which implemented those interfaces are managed using reference counting. This means that whenever you carry a reference to a COM class around you need to increment the reference count manually and release it when you are done.

This is something tedious and error-prone but unavoidable when you are using COM objects in C. Luckily, C++.NET isn’t C and it means we can use RAII, just like the code I presented in Naivety in C++.

Before

Before presenting the simple wrapper, let’s see how plain COM programming would look like without the wrapper.

IUnknown *pUnk;
IMAPIProp *pprop;
HRESULT r;

pUnk = (IUnknown*)Marshal::GetIUnknownForObject(mapiObj).ToPointer();

r = pUnk->QueryInterface(::IID_IMAPIProp, (void **)&pprop);
if (FAILED(r))
  Marshal::ThrowExceptionForHR(r);

r = pProp->SaveChanges(FORCE_SAVE | KEEP_OPEN_READWRITE);
if (FAILED(r))
  throw gcnew MapiException(pProp, r, "Failed to save attachment data");

pUnk->Release();
pProp->Release();

This is simple MAPI code that I hacked as a demonstration. It doesn’t do anything interesting.

This code is pretty simple but gives an idea about how hairy code that is calling COM can get, especially if you throw along exception handling.

After

Here is the same code, using the simple wrapper that is listed below.

COM<IMAPIProp> ifProp;
COM<IUnknown> ifUnk;
HRESULT r;

pUnk.Ptr = static_cast<IUnknown *>(Marshal::GetIUnknownForObject(mapiObj).ToPointer());

r = ifUnk.Ptr->QueryInterface(::IID_IMAPIProp, reinterpret_cast<void**>(&ifSession.Ptr))
if (FAILED(r))
   Marshal::ThrowExceptionForHR(r);

r = pProp->SaveChanges(FORCE_SAVE | KEEP_OPEN_READWRITE);
if (FAILED(r))
   throw gcnew MapiException(pProp, r, "Failed to save attachment data");

You can see that the COM wrapper releases the COM objects which is a precious feature as the calling procedure gets more complete. If the end result is a bit anticlimatic, it is because error handling is still in the way. The wrapper I have made for error handling is a lot less pretty so I won’t be presenting it here.

The code itself

// RAII friendly wrapper over COM interface usage.
template <class C> class COM
{
public:
   C *Ptr;

COM<C>(C *pCom)
{
   assert(pCom);
   Ptr = pCom;
}

COM<C>()
{
   Ptr = 0;
}

COM<C>& operator=(const COM<C>& com)
{
   assert(com.Ptr != 0);
   Ptr = com.Ptr;
   Ptr->AddRef();
   return *this;
}

COM<C>(const COM<C>& com)
{
   assert(com.Ptr != 0);
   Ptr = com.Ptr;
   assert(Ptr->AddRef() >= 1);
}

~COM<C>()
{
   if (Ptr) assert(Ptr->Release() >= 0);
   Ptr = 0;
}
};

There is not much to say about this code. It’s very simple and does the job. The copy constructor is there to increase the reference count in case an instanciated COM object is passed between callers and callee.

I have added assert calls to catch potential problems I may have missed but none of them have ever been triggered.

Written by François-Denis Gonthier

February 10th, 2010 at 9:40 pm