MFC Icon Handler's IExtractIcon::GetIconLocation() never gets call
I'm using the MFC COM macros to implement an Icon Handler. The DLL gets
loaded, I eventually get a call to QueryInterface() (actully,
IPersistFile::QueryInterface()), and eventually a call to
IPersistFile::Load(). Next, I get another IPersistFile::QueryInterface call
which returns a pointer to the IExtractIcon interface, but none of the
IExtractIcon methods ever get called (except for AddRef() and Release());
specifically, GetIconLocation() is never called, and neither is ExtractIcon().
I've run this in the VS debugger, attaching to the explorer window and
putting breakpoints on all of my rouintes. Everything *seems* fine, except
that IExtractIcon never gets called.
I have to assume that I've done something wrong somewhere. My class
declaration looks like this:
class CCMIconHandler : public CWinApp
{
private: typedef CWinApp inherited;
public:
DECLARE_DYNCREATE(CCMIconHandler);
DECLARE_OLECREATE(CCMIconHandler);
CCMIconHandler (void);
virtual ~CCMIconHandler (void);
virtual BOOL InitInstance (void);
virtual int ExitInstance (void);
protected:
DECLARE_INTERFACE_MAP()
/*
IPersistFile.
*/
BEGIN_INTERFACE_PART(PersistFile, IPersistFile)
STDMETHOD_(HRESULT, GetClassID) (
CLSID* pClassID);
STDMETHOD_(HRESULT, Load) (
LPCOLESTR pszFileName,
DWORD dwMode);
STDMETHOD_(HRESULT, GetCurFile) (
LPOLESTR* pszFileName);
STDMETHOD_(HRESULT, IsDirty) (void);
STDMETHOD_(HRESULT, Save) (
LPCOLESTR pszFileName,
BOOL fRemember);
STDMETHOD_(HRESULT, SaveCompleted) (
LPCOLESTR pszFileName);
END_INTERFACE_PART(PersistFile)
/*
IExtractIcon
*/
BEGIN_INTERFACE_PART(ExtractIcon, IExtractIcon)
STDMETHOD_(HRESULT, Extract) (
LPCTSTR pszFile,
UINT nIconIndex,
HICON* phiconLarge,
HICON* phiconSmall,
UINT nIconSize);
STDMETHOD_(HRESULT, GetIconLocation)(
UINT uFlags,
LPTSTR smIconFile,
UINT cchMax,
int* piIndex,
UINT* pwFlags);
END_INTERFACE_PART(ExtractIcon)
protected:
CString fFileName; // Name of file for which icon is requested.
};
The code (more or less) looks like this:
/*
Allow dynamic creation of an object of this class.
*/
IMPLEMENT_DYNCREATE(CCMIconHandler, CWinApp);
/*
Implement a class factory for this object.
*/
IMPLEMENT_OLECREATE(CCMIconHandler, "CM Icon Handler",
0x897d3ada, 0xc314, 0x4e2e,
0xa9, 0x25, 0x84, 0x3b, 0x57, 0x82, 0x22, 0xce);
/*
Declarations for COM interface...
*/
BEGIN_INTERFACE_MAP(CCMIconHandler, CWinApp)
INTERFACE_PART(CCMIconHandler, IID_IPersistFile, PersistFile)
INTERFACE_PART(CCMIconHandler, IID_IExtractIcon, ExtractIcon)
END_INTERFACE_MAP()
;
/*
The one and only CCMIconHandler object
*/
CCMIconHandler theApp;
STDAPI
DllCanUnloadNow(void)
{
/*
Required for dynamic linking with MFC.
*/
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
return (::AfxDllCanUnloadNow());
} // DllCanUnloadNow
STDAPI
DllGetClassObject(
REFCLSID rclsid,
REFIID riid,
LPVOID* ppv)
{
/*
Required for dynamic linking with MFC.
*/
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
return (::AfxDllGetClassObject(rclsid, riid, ppv));
} // DllGetClassObject
STDAPI
DllRegisterServer(void)
{
/*
Required for dynamic linking with MFC.
*/
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
HRESULT result(S_OK); // Result code.
if (not COleObjectFactory::UpdateRegistryAll())
{
/*
Something went wrong; tell the caller we were unable to register
all of the object classes.
*/
result = SELFREG_E_CLASS;
}
return (result);
} // DllRegisterServer
STDAPI
DllUnregisterServer(void)
{
/*
Required for dynamic linking with MFC.
*/
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
HRESULT result(S_OK); // Result code.
if (not COleObjectFactory::UpdateRegistryAll(False))
{
/*
Something went wrong; tell the caller we were unable to unregister all
of the object classes.
*/
result = SELFREG_E_CLASS;
}
return (result);
} // DllUnregisterServer
ULONG
FAR EXPORT
CCMIconHandler::XPersistFile::AddRef(void)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
return (pThis->ExternalAddRef());
} // CCMIconHandler::XPersistFile::AddRef
HRESULT
FAR EXPORT
CCMIconHandler::XPersistFile::GetClassID(
CLSID* pClassID)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
return (E_NOTIMPL);
} // CCMIconHandler::XPersistFile::GetClassID
HRESULT
FAR EXPORT
CCMIconHandler::XPersistFile::GetCurFile(
LPOLESTR* /* pszFileName */)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
return (E_NOTIMPL);
} // CCMIconHandler::XPersistFile::GetCurFile
HRESULT
FAR EXPORT
CCMIconHandler::XPersistFile::IsDirty(void)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
return (E_NOTIMPL);
} // CCMIconHandler::XPersistFile::IsDirty
HRESULT
FAR EXPORT
CCMIconHandler::XPersistFile::Load(
LPCOLESTR pszFileName,
DWORD /* dwMode */)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
HRESULT result(E_FAIL); // Result of load operation.
// Copies the path to the <fFileName> field.
[...]
return (result);
} // CCMIconHandler::XPersistFile::Load
HRESULT
FAR EXPORT
CCMIconHandler::XPersistFile::QueryInterface(
REFIID iid,
LPVOID far* ppvObj)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
HRESULT result(E_NOINTERFACE); // Result of query operation.
if (nil != ppvObj)
{
result = pThis->ExternalQueryInterface(&iid, ppvObj);
}
return (result);
} // CCMIconHandler::XPersistFile::QueryInterface
ULONG
FAR EXPORT
CCMIconHandler::XPersistFile::Release(void)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
return (pThis->ExternalRelease());
} // CCMIconHandler::XPersistFile::Release
HRESULT
FAR EXPORT
CCMIconHandler::XPersistFile::Save(
LPCOLESTR /* pszFileName */,
BOOL /* fRemember */)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
return (E_NOTIMPL);
} // CCMIconHandler::XPersistFile::Save
HRESULT
FAR EXPORT
CCMIconHandler::XPersistFile::SaveCompleted(
LPCOLESTR /* pszFileName */)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
return (E_NOTIMPL);
} // CCMIconHandler::XPersistFile::SaveCompleted
ULONG
FAR EXPORT
CCMIconHandler::XExtractIcon::AddRef(void)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, ExtractIcon);
return (pThis->ExternalAddRef());
} // CCMIconHandler::XExtractIcon::AddRef
HRESULT
FAR EXPORT
CCMIconHandler::XExtractIcon::Extract(
LPCTSTR /* pszFile */,
UINT /* nIconIndex */,
HICON* phiconLarge,
HICON* phiconSmall,
UINT nIconSize)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, ExtractIcon);
// Code for extracting icons....
[...]
return (result);
} // CCMIconHandler::XExtractIcon::Extract
HRESULT
FAR EXPORT
CCMIconHandler::XExtractIcon::GetIconLocation(
UINT uFlags,
LPTSTR smIconFile,
UINT cchMax,
int* piIndex,
UINT* pwFlags)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, ExtractIcon);
// Code for locating icon.
[...]
return (result);
} // CCMIconHandler::XExtractIcon::GetIconLocation
HRESULT
FAR EXPORT
CCMIconHandler::XExtractIcon::QueryInterface(
REFIID iid,
LPVOID far* ppvObj)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, PersistFile);
HRESULT result(E_NOINTERFACE); // Result of query operation.
ASSERT(nil != ppvObj);
if (nil != ppvObj)
{
result = pThis->ExternalQueryInterface(&iid, ppvObj);
}
return (result);
} // CCMIconHandler::XExtractIcon::QueryInterface
ULONG
FAR EXPORT
CCMIconHandler::XExtractIcon::Release(void)
{
/*
Required for all interface methods...
*/
METHOD_PROLOGUE(CCMIconHandler, ExtractIcon);
return (pThis->ExternalRelease());
} // CCMIconHandler::XExtractIcon::Release
CCMIconHandler::CCMIconHandler(void)
{
} // CCMIconHandler::CCMIconHandler
CCMIconHandler::~CCMIconHandler(void)
{
} // CCMIconHandler::~CCMIconHandler
int
CCMIconHandler::ExitInstance(void)
{
return (inherited::ExitInstance());
} // CCMIconHandler::ExitInstance
BOOL
CCMIconHandler::InitInstance(void)
{
inherited::InitInstance();
// Register all OLE server (factories) as running. This enables the
// OLE libraries to create objects from other applications.
COleObjectFactory::RegisterAll();
return (True);
} // CCMIconHandler::InitInstance
It compiles fine and, as I said, it seems that *some* methods get called,
but the Shell never tries to extract an icon. Is there anything obvious that
anyone can see that I'm doing wrong? There doesn't seem to be much to it, so
I'm probably doing something stupid.