319 lines
8.6 KiB
C++
319 lines
8.6 KiB
C++
/*****************************************************************************\
|
|
FILE: isfvcb.cpp
|
|
|
|
DESCRIPTION:
|
|
This is a base class that implements the default behavior of
|
|
IShellFolderViewCallBack. This allows default DefView implementation with this
|
|
callback to override specific behavior.
|
|
\*****************************************************************************/
|
|
|
|
#include "priv.h"
|
|
#include "isfvcb.h"
|
|
|
|
|
|
//===========================
|
|
// *** IShellFolderViewCB Interface ***
|
|
//===========================
|
|
|
|
/*****************************************************************************\
|
|
FUNCTION: _OnSetISFV
|
|
|
|
DESCRIPTION:
|
|
Same as ::SetSite();
|
|
\*****************************************************************************/
|
|
HRESULT CBaseFolderViewCB::_OnSetISFV(IShellFolderView * psfv)
|
|
{
|
|
IUnknown_Set((IUnknown **) &m_psfv, (IUnknown *) psfv);
|
|
return S_OK;
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
FUNCTION: IShellFolderViewCB::MessageSFVCB
|
|
|
|
DESCRIPTION:
|
|
\*****************************************************************************/
|
|
#define NOTHANDLED(m) case m: hr = E_NOTIMPL; break
|
|
|
|
HRESULT CBaseFolderViewCB::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case DVM_GETDETAILSOF:
|
|
hr = _OnGetDetailsOf((UINT)wParam, (PDETAILSINFO)lParam);
|
|
break;
|
|
|
|
case DVM_COLUMNCLICK:
|
|
hr = _OnColumnClick((UINT)wParam);
|
|
break;
|
|
|
|
case DVM_MERGEMENU:
|
|
hr = _OnMergeMenu((LPQCMINFO)lParam);
|
|
break;
|
|
|
|
case DVM_UNMERGEMENU:
|
|
hr = _OnUnMergeMenu((HMENU)lParam);
|
|
break;
|
|
|
|
case DVM_INVOKECOMMAND:
|
|
hr = _OnInvokeCommand((UINT)wParam);
|
|
break;
|
|
|
|
case DVM_GETHELPTEXT:
|
|
hr = _OnGetHelpText(lParam, wParam);
|
|
break;
|
|
|
|
case SFVM_GETHELPTOPIC:
|
|
hr = _OnGetHelpTopic((SFVM_HELPTOPIC_DATA *) lParam);
|
|
break;
|
|
|
|
case DVM_GETTOOLTIPTEXT:
|
|
// TODO: Implement
|
|
hr = E_NOTIMPL;
|
|
break;
|
|
|
|
case DVM_UPDATESTATUSBAR:
|
|
// TODO: Implement
|
|
hr = _OnUpdateStatusBar();
|
|
break;
|
|
|
|
case DVM_WINDOWCREATED:
|
|
hr = _OnWindowCreated();
|
|
break;
|
|
|
|
case SFVM_BACKGROUNDENUMDONE:
|
|
hr = _OnBackGroundEnumDone();
|
|
break;
|
|
|
|
case DVM_INITMENUPOPUP:
|
|
hr = _OnInitMenuPopup((HMENU) lParam, (UINT) HIWORD(wParam), (UINT) LOWORD(wParam));
|
|
break;
|
|
|
|
case DVM_RELEASE:
|
|
{
|
|
CBaseFolderViewCB * pfv = (CBaseFolderViewCB *) lParam;
|
|
if (pfv)
|
|
hr = pfv->Release();
|
|
}
|
|
break;
|
|
|
|
case DVM_DEFITEMCOUNT:
|
|
hr = _OnDefItemCount((LPINT)lParam);
|
|
break;
|
|
|
|
case DVM_DIDDRAGDROP:
|
|
hr = _OnDidDragDrop((DROPEFFECT)wParam, (IDataObject *)lParam);
|
|
break;
|
|
|
|
case DVM_REFRESH:
|
|
hr = _OnRefresh((BOOL) wParam);
|
|
break;
|
|
|
|
case SFVM_ADDPROPERTYPAGES:
|
|
hr = _OnAddPropertyPages((SFVM_PROPPAGE_DATA *)lParam);
|
|
break;
|
|
|
|
case DVM_BACKGROUNDENUM:
|
|
// WARNING! If we return S_OK from DVM_BACKGROUNDENUM, we also
|
|
// are promising that we support free threading on our IEnumIDList
|
|
// interface! This allows the shell to do enumeration on our
|
|
// IEnumIDList on a separate background thread.
|
|
hr = S_OK; // Always enum in background
|
|
break;
|
|
|
|
case SFVM_DONTCUSTOMIZE:
|
|
if (lParam)
|
|
*((BOOL *) lParam) = FALSE; // Yes, we are customizable.
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case SFVM_GETZONE:
|
|
hr = _OnGetZone((DWORD *) lParam, wParam);
|
|
break;
|
|
|
|
case SFVM_GETPANE:
|
|
hr = _OnGetPane((DWORD) wParam, (DWORD *)lParam);
|
|
break;
|
|
|
|
case SFVM_SETISFV:
|
|
hr = _OnSetISFV((IShellFolderView *)lParam);
|
|
break;
|
|
|
|
case SFVM_GETNOTIFY:
|
|
hr = _OnGetNotify((LPITEMIDLIST *) wParam, (LONG *) lParam);
|
|
break;
|
|
|
|
case SFVM_FSNOTIFY:
|
|
hr = _OnFSNotify((LPITEMIDLIST *) wParam, (LONG *) lParam);
|
|
break;
|
|
|
|
case SFVM_QUERYFSNOTIFY:
|
|
hr = _OnQueryFSNotify((SHChangeNotifyEntry *) lParam);
|
|
break;
|
|
|
|
case SFVM_SIZE:
|
|
hr = _OnSize((LONG) wParam, (LONG) lParam);
|
|
break;
|
|
|
|
case SFVM_THISIDLIST:
|
|
hr = _OnThisIDList((LPITEMIDLIST *) lParam);
|
|
break;
|
|
|
|
|
|
// The following are some we could do.
|
|
// SFVM_HWNDMAIN
|
|
|
|
// Others that aren't currently handled.
|
|
NOTHANDLED(DVM_GETBUTTONINFO);
|
|
NOTHANDLED(DVM_GETBUTTONS);
|
|
NOTHANDLED(DVM_SELCHANGE);
|
|
NOTHANDLED(DVM_DRAWITEM);
|
|
NOTHANDLED(DVM_MEASUREITEM);
|
|
NOTHANDLED(DVM_EXITMENULOOP);
|
|
NOTHANDLED(DVM_GETCCHMAX);
|
|
NOTHANDLED(DVM_WINDOWDESTROY);
|
|
NOTHANDLED(DVM_SETFOCUS);
|
|
NOTHANDLED(DVM_KILLFOCUS);
|
|
NOTHANDLED(DVM_QUERYCOPYHOOK);
|
|
NOTHANDLED(DVM_NOTIFYCOPYHOOK);
|
|
NOTHANDLED(DVM_DEFVIEWMODE);
|
|
#if 0
|
|
NOTHANDLED(DVM_INSERTITEM); // Too verbose
|
|
NOTHANDLED(DVM_DELETEITEM);
|
|
#endif
|
|
|
|
NOTHANDLED(DVM_GETWORKINGDIR);
|
|
NOTHANDLED(DVM_GETCOLSAVESTREAM);
|
|
NOTHANDLED(DVM_SELECTALL);
|
|
NOTHANDLED(DVM_SUPPORTSIDENTIFY);
|
|
NOTHANDLED(DVM_FOLDERISPARENT);
|
|
default:
|
|
hr = E_NOTIMPL;
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/****************************************************\
|
|
Constructor
|
|
\****************************************************/
|
|
CBaseFolderViewCB::CBaseFolderViewCB() : m_cRef(1), m_dwSignature(c_dwSignature)
|
|
{
|
|
DllAddRef();
|
|
|
|
// This needs to be allocated in Zero Inited Memory.
|
|
// Assert that all Member Variables are inited to Zero.
|
|
ASSERT(!m_psfv);
|
|
|
|
}
|
|
|
|
|
|
/****************************************************\
|
|
Destructor
|
|
\****************************************************/
|
|
CBaseFolderViewCB::~CBaseFolderViewCB()
|
|
{
|
|
m_dwSignature = 0; // Turn off _IShellFolderViewCallBack
|
|
IUnknown_Set((IUnknown **)&m_psfv, NULL);
|
|
DllRelease();
|
|
}
|
|
|
|
|
|
//===========================
|
|
// *** IUnknown Interface ***
|
|
//===========================
|
|
|
|
ULONG CBaseFolderViewCB::AddRef()
|
|
{
|
|
m_cRef++;
|
|
return m_cRef;
|
|
}
|
|
|
|
ULONG CBaseFolderViewCB::Release()
|
|
{
|
|
ASSERT(m_cRef > 0);
|
|
m_cRef--;
|
|
|
|
if (m_cRef > 0)
|
|
return m_cRef;
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
// {7982F251-C37A-11d1-9823-006097DF5BD4}
|
|
static const GUID CIID_PrivateThis = { 0x7982f251, 0xc37a, 0x11d1, { 0x98, 0x23, 0x0, 0x60, 0x97, 0xdf, 0x5b, 0xd4 } };
|
|
|
|
HRESULT CBaseFolderViewCB::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IShellFolderViewCB))
|
|
{
|
|
*ppvObj = SAFECAST(this, IShellFolderViewCB*);
|
|
}
|
|
else
|
|
if (IsEqualIID(riid, IID_IObjectWithSite))
|
|
{
|
|
*ppvObj = SAFECAST(this, IObjectWithSite*);
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CBaseFolderViewCB::_IShellFolderViewCallBack(IShellView * psvOuter, IShellFolder * psf, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
IShellFolderViewCB * psfvcb = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
|
|
// Now this is a total hack. I am bastardizing the pszOuter param to really be the this pointer that
|
|
// is the IShellFolderViewCB interface of the CBaseFolderViewCB object. I use the SFVM_WINDOWDESTROY event to
|
|
// release the object but DefView calls us back with one more message before we completely go away
|
|
// and that message is SFVM_SETISFV. Everytime the SFVM_SETISFV is called with a NULL lParam, it's
|
|
// equivalent to calling ::SetSite(NULL). We can ignore this because we release the back pointer in our
|
|
// destructor.
|
|
if (((SFVM_SETISFV == uMsg) && !lParam) ||
|
|
(SFVM_PRERELEASE == uMsg))
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
// psvOuter is really our CBaseFolderViewCB. Sniff around to make sure.
|
|
// Note that this casting must exactly invert the casts that we do in
|
|
// CBaseFolder::_CreateShellView.
|
|
|
|
CBaseFolderViewCB *pbfvcb = (CBaseFolderViewCB *)(IShellFolderViewCB *)psvOuter;
|
|
|
|
if (EVAL(!IsBadReadPtr(pbfvcb, sizeof(CBaseFolderViewCB))) &&
|
|
EVAL(pbfvcb->m_dwSignature == c_dwSignature))
|
|
{
|
|
|
|
// psvOuter is really our CBaseFolderViewCB and let's make sure with this QI.
|
|
hr = psvOuter->QueryInterface(IID_IShellFolderViewCB, (void **) &psfvcb);
|
|
if (EVAL(psfvcb))
|
|
{
|
|
hr = psfvcb->MessageSFVCB(uMsg, wParam, lParam);
|
|
|
|
if ((SFVM_WINDOWDESTROY == uMsg)) // (DVM_WINDOWDESTROY == SFVM_WINDOWDESTROY)
|
|
{
|
|
ASSERT(!lParam); // Sometimes callers want this to be freed.
|
|
psvOuter->Release(); // We are releasing the psvOuter that DefView is holding. We shouldn't be called again.
|
|
}
|
|
|
|
psfvcb->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|