I think I have whiplash: in the space of a few hours I've gone from writing web services in C# to implementing COM stuff in C++. I don't do much C++ any more, so the adjustment has been somewhat extremely painful.
See, I'm trying to implement a new
protocol handler to integrate with Windows Search. I have some content in a database, and I want to surface it along with other search results using Windows Desktop Search or the native Vista stuff. In the process,
this set of posts has been an excellent resource. In fact, it's nearly the only resource for writing protocol handlers as far as I can tell.
While I was reading the posts and (slowly) implementing away, I decided that it would be a good idea to follow the suggestion turn on ATL QueryInterface debugging. Especially given that my code appeared to be doing nothing. So I was a bit annoyed to see output like this in DebugView:
[3552] CProtocolHandler
[3552] -
[3552] - failed
Those dashes are supposed to have interface names or IDs before them, and they're supposed to tell me what interfaces are being QueryInterfaced for. What's worse is that when I followed the link in the articles and read
this, it looked as if the problem was fixed in VS2005, which I'm using. But it obviously wasn't.
Soon enough, I was down in the bowels of the ATL code (atlbase.h, no less), trying to figure out what's up. Well, eventually I spotted it: the code change they made to AtlDumpIID to fix the problem in VS2003 is still broken in the case where the registry keys can't be read. In that case, instead of dumping the raw ID, they dump…nothing.
I'm guessing that this is a Vista (which I'm using) problem that has to do with security being a lot more locked down. At any rate, if you encounter a similar problem, you'll want to change AtlDumpIID to something like the code below. I'm sure you can do better - this sometimes prints IDs twice, but it was the smallest change I could make to get the effect I wanted.
#if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI)
__forceinline HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr) throw()
{
USES_CONVERSION_EX;
CRegKey key;
TCHAR szName[100];
DWORD dwType;
DWORD dw = sizeof(szName);
LPOLESTR pszGUID = NULL;
if (FAILED(StringFromCLSID(iid, &pszGUID)))
return hr;
OutputDebugString(pszClassName);
OutputDebugString(_T(" - "));
LPTSTR lpszGUID = OLE2T_EX(pszGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
#ifndef _UNICODE
if(lpszGUID == NULL)
{
CoTaskMemFree(pszGUID);
return hr;
}
#endif
// Attempt to find it in the interfaces section
if (key.Open(HKEY_CLASSES_ROOT, _T("Interface"), KEY_READ) == ERROR_SUCCESS)
{
if (key.Open(key, lpszGUID, KEY_READ) == ERROR_SUCCESS)
{
*szName = 0;
if (RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw) == ERROR_SUCCESS)
{
OutputDebugString(szName);
}
else
{
OutputDebugString(lpszGUID);
}
}
else
{
OutputDebugString(lpszGUID);
}
}
// Attempt to find it in the clsid section
if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) == ERROR_SUCCESS)
{
if (key.Open(key, lpszGUID, KEY_READ) == ERROR_SUCCESS)
{
*szName = 0;
if (RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw) == ERROR_SUCCESS)
{
OutputDebugString(_T("(CLSID\?\?\?) "));
OutputDebugString(szName);
}
else
{
OutputDebugString(lpszGUID);
}
}
else
{
OutputDebugString(lpszGUID);
}
}
else
OutputDebugString(lpszGUID);
if (hr != S_OK)
OutputDebugString(_T(" - failed"));
OutputDebugString(_T("\n"));
CoTaskMemFree(pszGUID);
return hr;
}
#endif // _ATL_DEBUG_INTERFACES || _ATL_DEBUG_QI
Posted
Apr 11 2007, 12:35 PM
by
craig-andera