[SHELL32]

- CDefView: Set the site of the context menu to the CDefView essentialy reverting r68727 which was wrong.
- CDefaultContextMenu: Implement IObjectWithSite interface. Don't use CWM_GETISHELLBROWSER to get a pointer to the shell browser. Do a IUnknown_QueryService to the site instead asking for either the shell browser or the shell view (and it is fine if there is none of them).
- Rename IDefaultContextMenu_Constructor to CDefaultContextMenu_CreateInstance and use ShellObjectCreatorInit to simplify its code.

svn path=/trunk/; revision=72327
This commit is contained in:
Giannis Adamopoulos 2016-08-18 13:50:56 +00:00
parent 9fab725041
commit 4c322eaeef
2 changed files with 117 additions and 148 deletions

View file

@ -1210,6 +1210,8 @@ HRESULT CDefView::OpenSelectedItems()
if (FAILED(hResult)) if (FAILED(hResult))
goto cleanup; goto cleanup;
IUnknown_SetSite(m_pCM, (IShellView *)this);
hResult = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY); hResult = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
if (FAILED(hResult)) if (FAILED(hResult))
goto cleanup; goto cleanup;
@ -1229,7 +1231,10 @@ cleanup:
DestroyMenu(hMenu); DestroyMenu(hMenu);
if (m_pCM) if (m_pCM)
{
IUnknown_SetSite(m_pCM, NULL);
m_pCM.Release(); m_pCM.Release();
}
return hResult; return hResult;
} }
@ -1263,6 +1268,8 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
if (FAILED( hResult)) if (FAILED( hResult))
goto cleanup; goto cleanup;
IUnknown_SetSite(m_pCM, (IShellView *)this);
hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL); hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
if (FAILED( hResult)) if (FAILED( hResult))
goto cleanup; goto cleanup;
@ -1280,7 +1287,10 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
cleanup: cleanup:
if (m_pCM) if (m_pCM)
{
IUnknown_SetSite(m_pCM, NULL);
m_pCM.Release(); m_pCM.Release();
}
if (hMenu) if (hMenu)
DestroyMenu(hMenu); DestroyMenu(hMenu);
@ -1301,6 +1311,8 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
if (FAILED( hResult)) if (FAILED( hResult))
goto cleanup; goto cleanup;
IUnknown_SetSite(m_pCM, (IShellView *)this);
hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL); hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
if (FAILED( hResult)) if (FAILED( hResult))
goto cleanup; goto cleanup;
@ -1309,7 +1321,10 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
cleanup: cleanup:
if (m_pCM) if (m_pCM)
{
IUnknown_SetSite(m_pCM, NULL);
m_pCM.Release(); m_pCM.Release();
}
if (hMenu) if (hMenu)
DestroyMenu(hMenu); DestroyMenu(hMenu);

View file

@ -6,12 +6,6 @@
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
*/ */
/*
TODO:
The code in NotifyShellViewWindow to deliver commands to the view is broken. It is an excellent
example of the wrong way to do it.
*/
#include "precomp.h" #include "precomp.h"
extern "C" extern "C"
@ -61,9 +55,11 @@ struct _StaticInvokeCommandMap_
class CDefaultContextMenu : class CDefaultContextMenu :
public CComObjectRootEx<CComMultiThreadModelNoCS>, public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IContextMenu3 public IContextMenu3,
public IObjectWithSite
{ {
private: private:
CComPtr<IUnknown> m_site;
CComPtr<IShellFolder> m_psf; CComPtr<IShellFolder> m_psf;
UINT m_cidl; UINT m_cidl;
PCUITEMID_CHILD_ARRAY m_apidl; PCUITEMID_CHILD_ARRAY m_apidl;
@ -87,6 +83,7 @@ class CDefaultContextMenu :
UINT BuildBackgroundContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags); UINT BuildBackgroundContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu); UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu);
UINT BuildShellItemContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags); UINT BuildShellItemContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
HRESULT NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi, BOOL bRefresh);
HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink); HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink);
HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi);
@ -121,10 +118,15 @@ class CDefaultContextMenu :
// IContextMenu3 // IContextMenu3
virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult); virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
// IObjectWithSite
virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
BEGIN_COM_MAP(CDefaultContextMenu) BEGIN_COM_MAP(CDefaultContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2) COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3) COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
END_COM_MAP() END_COM_MAP()
}; };
@ -992,21 +994,23 @@ CDefaultContextMenu::QueryContextMenu(
return S_OK; return S_OK;
} }
static
HRESULT HRESULT
NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi, BOOL bRefresh) CDefaultContextMenu::NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi, BOOL bRefresh)
{ {
/* Note: CWM_GETISHELLBROWSER returns not referenced object */ CComPtr<IShellView> psv;
LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
if (!lpSB)
return E_FAIL;
CComPtr<IShellView> lpSV; HRESULT hr;
if (FAILED(lpSB->QueryActiveShellView(&lpSV)))
return E_FAIL; if (!m_site)
return E_FAIL;;
/* Get a pointer to the shell browser */
hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
HWND hwndSV = NULL; HWND hwndSV = NULL;
if (SUCCEEDED(lpSV->GetWindow(&hwndSV))) if (SUCCEEDED(psv->GetWindow(&hwndSV)))
SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0); SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
return S_OK; return S_OK;
} }
@ -1015,19 +1019,16 @@ HRESULT
CDefaultContextMenu::DoRefresh( CDefaultContextMenu::DoRefresh(
LPCMINVOKECOMMANDINFO lpcmi) LPCMINVOKECOMMANDINFO lpcmi)
{ {
CComPtr<IPersistFolder2> ppf2 = NULL; if (!m_site)
LPITEMIDLIST pidl; return E_FAIL;;
HRESULT hr = m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
if (SUCCEEDED(hr)) /* Get a pointer to the shell view */
{ CComPtr<IShellView> psv;
hr = ppf2->GetCurFolder(&pidl); HRESULT hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
if (SUCCEEDED(hr)) if (FAILED_UNEXPECTEDLY(hr))
{ return hr;
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, NULL);
ILFree(pidl); return psv->Refresh();
}
}
return hr;
} }
HRESULT HRESULT
@ -1208,69 +1209,44 @@ CDefaultContextMenu::DoCopyOrCut(
CComPtr<IDataObject> pDataObj; CComPtr<IDataObject> pDataObj;
HRESULT hr; HRESULT hr;
if (SUCCEEDED(SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj)))) hr = SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
{ if(FAILED_UNEXPECTEDLY(hr))
if (!bCopy)
{
FORMATETC formatetc;
STGMEDIUM medium;
InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL);
pDataObj->GetData(&formatetc, &medium);
DWORD * pdwFlag = (DWORD*)GlobalLock(medium.hGlobal);
if (pdwFlag)
*pdwFlag = DROPEFFECT_MOVE;
GlobalUnlock(medium.hGlobal);
pDataObj->SetData(&formatetc, &medium, TRUE);
}
hr = OleSetClipboard(pDataObj);
return hr; return hr;
if (!bCopy)
{
FORMATETC formatetc;
STGMEDIUM medium;
InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL);
pDataObj->GetData(&formatetc, &medium);
DWORD * pdwFlag = (DWORD*)GlobalLock(medium.hGlobal);
if (pdwFlag)
*pdwFlag = DROPEFFECT_MOVE;
GlobalUnlock(medium.hGlobal);
pDataObj->SetData(&formatetc, &medium, TRUE);
} }
/* Note: CWM_GETISHELLBROWSER returns not referenced object */ return OleSetClipboard(pDataObj);
LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
if (!lpSB)
{
ERR("failed to get shellbrowser\n");
return E_FAIL;
}
CComPtr<IShellView> lpSV;
hr = lpSB->QueryActiveShellView(&lpSV);
if (FAILED(hr))
{
ERR("failed to query the active shellview\n");
return hr;
}
hr = lpSV->GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IDataObject, &pDataObj));
if (SUCCEEDED(hr))
{
hr = OleSetClipboard(pDataObj);
if (FAILED(hr))
ERR("OleSetClipboard failed");
pDataObj->Release();
} else
ERR("failed to get item object\n");
return hr;
} }
HRESULT HRESULT
CDefaultContextMenu::DoRename( CDefaultContextMenu::DoRename(
LPCMINVOKECOMMANDINFO lpcmi) LPCMINVOKECOMMANDINFO lpcmi)
{ {
/* get the active IShellView. Note: CWM_GETISHELLBROWSER returns not referenced object */ CComPtr<IShellBrowser> psb;
LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0); HRESULT hr;
if (!lpSB)
{ if (!m_site)
ERR("CWM_GETISHELLBROWSER failed\n");
return E_FAIL; return E_FAIL;
}
/* Get a pointer to the shell browser */
hr = IUnknown_QueryService(m_site, SID_IShellBrowser, IID_PPV_ARG(IShellBrowser, &psb));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
/* is the treeview focused */ /* is the treeview focused */
HWND hwnd; HWND hwnd;
if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwnd))) if (SUCCEEDED(psb->GetControlWindow(FCW_TREE, &hwnd)))
{ {
HTREEITEM hItem = TreeView_GetSelection(hwnd); HTREEITEM hItem = TreeView_GetSelection(hwnd);
if (hItem) if (hItem)
@ -1278,12 +1254,9 @@ CDefaultContextMenu::DoRename(
} }
CComPtr<IShellView> lpSV; CComPtr<IShellView> lpSV;
HRESULT hr = lpSB->QueryActiveShellView(&lpSV); hr = psb->QueryActiveShellView(&lpSV);
if (FAILED(hr)) if (FAILED_UNEXPECTEDLY(hr))
{
ERR("CWM_GETISHELLBROWSER failed\n");
return hr; return hr;
}
SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT; SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
lpSV->SelectItem(m_apidl[0], selFlags); lpSV->SelectItem(m_apidl[0], selFlags);
@ -1423,24 +1396,20 @@ CDefaultContextMenu::DoCreateNewFolder(
return E_FAIL; return E_FAIL;
/* Show and select the new item in the def view */ /* Show and select the new item in the def view */
CComPtr<IShellBrowser> lpSB;
CComPtr<IShellView> lpSV;
LPITEMIDLIST pidl; LPITEMIDLIST pidl;
PITEMID_CHILD pidlNewItem; PITEMID_CHILD pidlNewItem;
CComPtr<IShellView> psv;
/* Notify the view object about the new item */ /* Notify the view object about the new item */
SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, (LPCVOID)wszName, NULL); SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, (LPCVOID)wszName, NULL);
/* FIXME: I think that this can be implemented using callbacks to the shell folder */ if (!m_site)
return S_OK;
/* Note: CWM_GETISHELLBROWSER returns shell browser without adding reference */ /* Get a pointer to the shell view */
lpSB = (LPSHELLBROWSER)SendMessageA(lpici->hwnd, CWM_GETISHELLBROWSER, 0, 0); hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
if (!lpSB) if (FAILED_UNEXPECTEDLY(hr))
return E_FAIL; return S_OK;
hr = lpSB->QueryActiveShellView(&lpSV);
if (FAILED(hr))
return hr;
/* Attempt to get the pidl of the new item */ /* Attempt to get the pidl of the new item */
hr = SHILCreateFromPathW(wszName, &pidl, NULL); hr = SHILCreateFromPathW(wszName, &pidl, NULL);
@ -1449,7 +1418,7 @@ CDefaultContextMenu::DoCreateNewFolder(
pidlNewItem = ILFindLastID(pidl); pidlNewItem = ILFindLastID(pidl);
hr = lpSV->SelectItem(pidlNewItem, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | hr = psv->SelectItem(pidlNewItem, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE |
SVSI_FOCUSED | SVSI_SELECT); SVSI_FOCUSED | SVSI_SELECT);
SHFree(pidl); SHFree(pidl);
@ -1528,7 +1497,7 @@ CDefaultContextMenu::DoDynamicShellExtensions(
DWORD DWORD
CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry) CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry)
{ {
LPSHELLBROWSER lpSB; CComPtr<IShellBrowser> psb;
HWND hwndTree; HWND hwndTree;
LPCWSTR FlagsName; LPCWSTR FlagsName;
WCHAR wszKey[256]; WCHAR wszKey[256];
@ -1536,13 +1505,16 @@ CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticSh
DWORD wFlags; DWORD wFlags;
DWORD cbVerb; DWORD cbVerb;
if (!m_site)
return 0;
/* Get a pointer to the shell browser */ /* Get a pointer to the shell browser */
lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0); hr = IUnknown_QueryService(m_site, SID_IShellBrowser, IID_PPV_ARG(IShellBrowser, &psb));
if (lpSB == NULL) if (FAILED_UNEXPECTEDLY(hr))
return 0; return 0;
/* See if we are in Explore or Browse mode. If the browser's tree is present, we are in Explore mode.*/ /* See if we are in Explore or Browse mode. If the browser's tree is present, we are in Explore mode.*/
if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree) if (SUCCEEDED(psb->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree)
FlagsName = L"ExplorerFlags"; FlagsName = L"ExplorerFlags";
else else
FlagsName = L"BrowserFlags"; FlagsName = L"BrowserFlags";
@ -1565,15 +1537,18 @@ HRESULT
CDefaultContextMenu::TryToBrowse( CDefaultContextMenu::TryToBrowse(
LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags) LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags)
{ {
LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageW(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0); CComPtr<IShellBrowser> psb;
HRESULT hr; HRESULT hr;
if (lpSB == NULL) if (!m_site)
return E_FAIL; return E_FAIL;
hr = lpSB->BrowseObject(ILCombine(m_pidlFolder, pidl), wFlags); /* Get a pointer to the shell browser */
hr = IUnknown_QueryService(m_site, SID_IShellBrowser, IID_PPV_ARG(IShellBrowser, &psb));
if (FAILED_UNEXPECTEDLY(hr))
return 0;
return hr; return psb->BrowseObject(ILCombine(m_pidlFolder, pidl), wFlags);
} }
HRESULT HRESULT
@ -1865,42 +1840,29 @@ CDefaultContextMenu::HandleMenuMsg2(
return S_OK; return S_OK;
} }
HRESULT
WINAPI
CDefaultContextMenu::SetSite(IUnknown *pUnkSite)
{
m_site = pUnkSite;
return S_OK;
}
HRESULT
WINAPI
CDefaultContextMenu::GetSite(REFIID riid, void **ppvSite)
{
if (!m_site)
return E_FAIL;
return m_site->QueryInterface(riid, ppvSite);
}
static static
HRESULT HRESULT
IDefaultContextMenu_Constructor( CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv)
const DEFCONTEXTMENU *pdcm,
REFIID riid,
void **ppv)
{ {
if (ppv == NULL) return ShellObjectCreatorInit<CDefaultContextMenu>(pdcm, riid, ppv);
return E_POINTER;
*ppv = NULL;
CComObject<CDefaultContextMenu> *pCM;
HRESULT hr = CComObject<CDefaultContextMenu>::CreateInstance(&pCM);
if (FAILED(hr))
return hr;
pCM->AddRef(); // CreateInstance returns object with 0 ref count */
CComPtr<IUnknown> pResult;
hr = pCM->QueryInterface(riid, (void **)&pResult);
if (FAILED(hr))
{
pCM->Release();
return hr;
}
hr = pCM->Initialize(pdcm);
if (FAILED(hr))
{
pCM->Release();
return hr;
}
*ppv = pResult.Detach();
pCM->Release();
TRACE("This(%p) cidl %u\n", *ppv, pdcm->cidl);
return S_OK;
} }
/************************************************************************* /*************************************************************************
@ -1910,17 +1872,9 @@ IDefaultContextMenu_Constructor(
HRESULT HRESULT
WINAPI WINAPI
SHCreateDefaultContextMenu( SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv)
const DEFCONTEXTMENU *pdcm,
REFIID riid,
void **ppv)
{ {
*ppv = NULL; return CDefaultContextMenu_CreateInstance(pdcm, riid, ppv);
HRESULT hr = IDefaultContextMenu_Constructor(pdcm, riid, ppv);
if (FAILED(hr))
ERR("IDefaultContextMenu_Constructor failed: %x\n", hr);
TRACE("pcm %p hr %x\n", pdcm, hr);
return hr;
} }
/************************************************************************* /*************************************************************************