views:

188

answers:

2

Short of writing a function manually that translates a few known REFIID to names, such as:

if (riid == IID_IUnknown) return "IUnknown";
if (riid == IID_IShellBrowser) return "IShellBrowser";
...

Is there a system call that would return a reasonable debugging string for well-known (or even all) REFIIDs?

+1  A: 

You can lookup the predefined interfaces in the HKCR\Interface registry subtree. Any component can register its interfaces there if it wishes. However this is not mandatory - the component might skip this registration.

sharptooth
A: 

Thanks for the responses. Below is what I came up with based on your feedback - much appreciated!

CString ToString(const GUID & guid)
{
 // could use StringFromIID() - but that requires managing an OLE string
 CString str;
 str.Format(_T("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"),
  guid.Data1,
  guid.Data2,
  guid.Data3,
  guid.Data4[0],
  guid.Data4[1],
  guid.Data4[2],
  guid.Data4[3],
  guid.Data4[4],
  guid.Data4[5],
  guid.Data4[6],
  guid.Data4[7]);
 return str;
}

CString GetNameOf(REFIID riid)
{
 CString name(ToString(riid));
 try
 {
  // attempt to lookup the interface name from the registry
  RegistryKey::OpenKey(HKEY_CLASSES_ROOT, "Interface", KEY_READ).OpenSubKey("{"+name+"}", KEY_READ).GetDefaultValue(name);
 }
 catch (...)
 {
  // use simple string representation if no registry entry found
 }
 return name;
}
Mordachai
Never, ever, use `catch(...)`. There are many different philosophical reasons for that, but if you want to have a pragmatic one: to pass "Designed for Vista" verification, your application needs to never catch access violation exceptions. Depending on your compiler settings, `catch(...)` does just that.
Pavel Minaev
Also, to manage an OLE string (i.e. BSTR) in an MFC or ATL application, use `CComBSTR` class.
Pavel Minaev
There isn't any reason to invoke all of the overhead of an OLE string. Yes, there are mechanisms for it, but so what? They can't just go and change the way that they express GUIDs, so its not a moving target, so no risk taken by rolling my own, more efficient solution.
Mordachai
catch(...) is a perfectly acceptable mechanism. Sorry, I have yet to see such advice, and given the multifaceted nature of C++'s throw mechanism (i.e. the fact that there are an infinite number of possible types that can be thrown), and the fact that in this case there isn't any real risk in catching any of them, I fail to see the value of said advice.Further - access violation would not be a c++ throw, it would be a structured exception dispatch - and would not be caught by catch(...) anyway (assuming one even cares about the Vista criteria)
Mordachai
I would agree with you on the catch(...) issue as a general rule of thumb - that using catch(...) willy-nilly throughout one's code is not a grand idea. But I would say it most definitely has its places. Take for example a destructor for a class that manages an OS file through some other object which throws if there is an IO error while interacting with the underlying file... if there is a need to call such a function from within the dtor of your class, then one reasonable approach is to wrap said call in a try {} catch (...). Otherwise you basically guarantee that your app will CTD.
Mordachai
You can use StringFromGUID2() - it will happily accept a stack-allocated buffer, no need for OLE strings.
sharptooth