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.
.



Relevant Pages

  • Re: #import generates different code
    ... Yes I have tried generating Raw wrappers and a similar issue is occuring. ... IDispatch and use the directive interface it works. ... > What directives are you using for #import now? ... >> by checking the returned HRESULT. ...
    (microsoft.public.vc.language)
  • Re: about casting
    ... One very strange thing is that I looked in the code to try to find if some other interface class is sent into some ... I looked more into the code and found that in some places is IStringList used as a parameter instead of IStringList2. ... HRESULT ErrorMessage; ...
    (microsoft.public.vc.mfc)
  • Re: #import generates different code
    ... "Unlike interface members, dispinterface members cannot use the retval ... HRESULT or SCODEs to long. ... > Yes I have tried generating Raw wrappers and a similar issue is occuring. ... >> What directives are you using for #import now? ...
    (microsoft.public.vc.language)
  • connection point event is not fire from com component
    ... I have a com component and fire event to an MFC application using ... HRESULT CScribbleExtractor::Extract ... //Create an instance of the interface defined in the COM DLL ... //Variable for the connection point cookie ...
    (microsoft.public.vc.atl)
  • Re: CoCreateInstance and "Class not registered" error...
    ... present in the registry under HKCR/Classes. ... an in-proc server, but does its threading model match the ... interface from this dll. ... HRESULT hresult ...
    (microsoft.public.vc.atl)