Re: CComPtr strange behaviour
On Sun, 26 Jul 2009 22:19:12 -0400, Igor Tandetnik wrote:
Alexander Lamaison wrote:
CComPtr<IUnknown> object;
object = context_menu(hwnd, cpidl, apidl).p;
Notice that those lines ends in '.p'. For some reason, without this,
this code returns invalid pointers and the program crashes when it
tries to use them! Why?
Show implementation of context_menu.
Context menu is implemented by the subclasses and the implementation looks
like this:
CComPtr<IContextMenu> CHostFolder::context_menu(
HWND hwnd, UINT cpidl, PCUITEMID_CHILD_ARRAY apidl)
{
HKEY *akeys; UINT ckeys;
ATLENSURE_THROW(SUCCEEDED(
CRegistry::GetHostFolderAssocKeys(&ckeys, &akeys)),
E_UNEXPECTED // Might fail if registry is corrupted
);
CComPtr<IShellFolder> spThisFolder = this;
ATLENSURE_THROW(spThisFolder, E_OUTOFMEMORY);
// Create default context menu from list of PIDLs
CComPtr<IContextMenu> spMenu;
HRESULT hr = ::CDefFolderMenu_Create2(
root_pidl(), hwnd, cpidl, apidl, spThisFolder,
MenuCallback, ckeys, akeys, &spMenu);
if (FAILED(hr))
throw com_exception(hr);
return spMenu;
}
However, I think my crashed were caused by calling methods and an
IExtractIconW and that one's fetch methods looks like this:
CComPtr<IExtractIconW> CHostFolder::extract_icon_w(
HWND /*hwnd*/, PCUITEMID_CHILD /*pidl*/)
{
TRACE("Request: IExtractIconW");
return this;
}
This seems very strange! It's not that the
QueryInterface fails---that would just return NULL---but that it
succeeds and returns an invalid pointer.
So there's something wrong with your implementation of QueryInterface,
or with your interface map (neither of which you have shown).
My interface map is split over the three classes in my hierarchy and
chained as appropriate:
class CFolder : // Abstract superclass
public ATL::CComObjectRoot,
public IPersistFolder3,
public IShellFolder2,
public IPersistIDList,
public IShellDetails
{
public:
BEGIN_COM_MAP(CFolder)
COM_INTERFACE_ENTRY(IPersistFolder3)
COM_INTERFACE_ENTRY(IShellFolder2)
COM_INTERFACE_ENTRY(IShellDetails)
COM_INTERFACE_ENTRY(IPersistIDList)
COM_INTERFACE_ENTRY2(IPersist, IPersistFolder3)
COM_INTERFACE_ENTRY2(IPersistFolder, IPersistFolder3)
COM_INTERFACE_ENTRY2(IPersistFolder2, IPersistFolder3)
COM_INTERFACE_ENTRY2(IShellFolder, IShellFolder2)
END_COM_MAP()
....
class CSwishFolder : // Implement the previously mentioned folder_object()
public swish::shell_folder::folder::CFolder
{
public:
BEGIN_COM_MAP(CSwishFolder)
COM_INTERFACE_ENTRY(IShellFolder)
COM_INTERFACE_ENTRY_CHAIN(CFolder)
END_COM_MAP()
....
class ATL_NO_VTABLE CHostFolder : // Implements context_menu(),
// extract_icon_w() etc.
public IExtractIcon,
public swish::shell_folder::folder::CSwishFolder
{
public:
BEGIN_COM_MAP(CHostFolder)
COM_INTERFACE_ENTRY(IExtractIcon)
COM_INTERFACE_ENTRY_CHAIN(CSwishFolder)
END_COM_MAP()
Does this look right?
Does anyone know why this behaves this way?
Most likely, because you have a bug elsewhere in your code.
My complete source code is viewable here:
http://www.doc.ic.ac.uk/~awl03/cgi-bin/trac.cgi/swish/browser/branches/feature_write/swish/shell_folder/SwishFolder.cpp#L86
Many thanks.
Alex Lamaison