Search code examples
c++winapiexceptioncom

Throwing C++ exceptions with CoInitialize and CoUninitialize


I have a function like this:

bool op1();
bool op2();

bool foo() {
  CoInitialize(nullptr);
  if (!op1()) {
    CoUninitialize();
    return false;
  }
  // do more stuff, then call op2...
  if (!op2()) {
    CoUninitialize();
    return false;
  }
  // happy path
  CoUninitialize();
  return true;
}

I want to refactor foo() to throw exceptions:

void foo() {
  CoInitialize(nullptr);
  if (!op1()) {
    CoUninitialize(); // I'm lazy, can't I automate this call?
    throw std::exception("Failed");
  }
  // ...

But I have to call CoUninitialize() each time I have an error.

I thought about wrapping the COM init calls inside a class, so the destructor will do the cleanup, but having an unused object feels strange to my eyes:

class comlib {
public:
  comlib() { CoInitialize(nullptr); }
  ~comlib() { CoUninitialize(); } // automated!
};

void foo() {
  comlib nobodyEverCallsMe;
  if (!op1()) {
    throw std::exception("Failed");
  }
  // ...

Is there a better approach to this?


Solution

  • Raymond Chen has been using this method for a while so I'm sure it's OK, just remember to only call CoUninitialize if CoInitialize SUCCEEDED!

    class CCoInitialize {
      HRESULT m_hr;
    public:
      CCoInitialize() : m_hr(CoInitialize(NULL)) { }
      ~CCoInitialize() { if (SUCCEEDED(m_hr)) CoUninitialize(); }
      operator HRESULT() const { return m_hr; }
    };
    
    
    void Something()
    {
      CCoInitialize init;
      ...
    }
    

    Some people might want to throw in the constructor if CoInitialize fails but I feel that's unnecessary because other COM calls down the line will fail. Only do it if you need to capture the exact HRESULT failure code from CoInitialize.