From 55469633cfbf20ba34bc747a80001bd4c7c4afb4 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Mon, 9 Jul 2018 00:01:12 +0900 Subject: [PATCH] [SHELL32] Add 'Properties' menu item in My Computer (#647) - Add a Shell_DefaultContextMenuCallBack() helper function. - Implement the IContextMenuCB interface in CDrivesFolder. CORE-12509 --- dll/win32/shell32/folders/CDesktopFolder.cpp | 28 +---------- dll/win32/shell32/folders/CDrivesFolder.cpp | 52 +++++++++++++++++++- dll/win32/shell32/folders/CDrivesFolder.h | 7 ++- dll/win32/shell32/folders/CFSFolder.cpp | 28 +---------- dll/win32/shell32/precomp.h | 3 ++ dll/win32/shell32/shlfolder.cpp | 41 +++++++++++++++ 6 files changed, 102 insertions(+), 57 deletions(-) diff --git a/dll/win32/shell32/folders/CDesktopFolder.cpp b/dll/win32/shell32/folders/CDesktopFolder.cpp index 9a1a452ea8b..b5bb839603c 100644 --- a/dll/win32/shell32/folders/CDesktopFolder.cpp +++ b/dll/win32/shell32/folders/CDesktopFolder.cpp @@ -864,33 +864,7 @@ HRESULT WINAPI CDesktopFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IData if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES) return S_OK; - PIDLIST_ABSOLUTE pidlFolder; - PUITEMID_CHILD *apidl; - UINT cidl; - HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - if (cidl > 1) - ERR("SHMultiFileProperties is not yet implemented\n"); - - STRRET strFile; - hr = GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strFile); - if (SUCCEEDED(hr)) - { - hr = SH_ShowPropertiesDialog(strFile.pOleStr, pidlFolder, apidl); - if (FAILED(hr)) - ERR("SH_ShowPropertiesDialog failed\n"); - } - else - { - ERR("Failed to get display name\n"); - } - - SHFree(pidlFolder); - _ILFreeaPidl(apidl, cidl); - - return hr; + return Shell_DefaultContextMenuCallBack(this, pdtobj); } /************************************************************************* diff --git a/dll/win32/shell32/folders/CDrivesFolder.cpp b/dll/win32/shell32/folders/CDrivesFolder.cpp index 77f64201968..15ccef2da80 100644 --- a/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -669,8 +669,21 @@ HRESULT WINAPI CDrivesFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVO } else if (IsEqualIID(riid, IID_IContextMenu)) { - WARN("IContextMenu not implemented\n"); - hr = E_NOTIMPL; + HKEY hKeys[16]; + UINT cKeys = 0; + AddClassKeyToArray(L"Directory\\Background", hKeys, &cKeys); + + DEFCONTEXTMENU dcm; + dcm.hwnd = hwndOwner; + dcm.pcmcb = this; + dcm.pidlFolder = pidlRoot; + dcm.psf = this; + dcm.cidl = 0; + dcm.apidl = NULL; + dcm.cKeys = cKeys; + dcm.aKeys = hKeys; + dcm.punkAssociationInfo = NULL; + hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut); } else if (IsEqualIID(riid, IID_IShellView)) { @@ -1059,3 +1072,38 @@ HRESULT WINAPI CDrivesFolder::GetCurFolder(LPITEMIDLIST *pidl) *pidl = ILClone(pidlRoot); return S_OK; } + +/************************************************************************/ +/* IContextMenuCB interface */ + +HRESULT WINAPI CDrivesFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg != DFM_MERGECONTEXTMENU && uMsg != DFM_INVOKECOMMAND) + return S_OK; + + /* no data object means no selection */ + if (!pdtobj) + { + if (uMsg == DFM_INVOKECOMMAND && wParam == 1) // #1 + { + // "System" properties + ShellExecuteW(hwndOwner, NULL, L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL); + } + else if (uMsg == DFM_MERGECONTEXTMENU) + { + QCMINFO *pqcminfo = (QCMINFO *)lParam; + HMENU hpopup = CreatePopupMenu(); + _InsertMenuItemW(hpopup, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); // #0 + _InsertMenuItemW(hpopup, 1, TRUE, 1, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED); // #1 + Shell_MergeMenus(pqcminfo->hmenu, hpopup, pqcminfo->indexMenu++, pqcminfo->idCmdFirst, pqcminfo->idCmdLast, MM_ADDSEPARATOR); + DestroyMenu(hpopup); + } + + return S_OK; + } + + if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES) + return S_OK; + + return Shell_DefaultContextMenuCallBack(this, pdtobj); +} diff --git a/dll/win32/shell32/folders/CDrivesFolder.h b/dll/win32/shell32/folders/CDrivesFolder.h index f0adc4960aa..f83057d79dc 100644 --- a/dll/win32/shell32/folders/CDrivesFolder.h +++ b/dll/win32/shell32/folders/CDrivesFolder.h @@ -27,7 +27,8 @@ class CDrivesFolder : public CComCoClass, public CComObjectRootEx, public IShellFolder2, - public IPersistFolder2 + public IPersistFolder2, + public IContextMenuCB { private: /* both paths are parsible from the desktop */ @@ -69,6 +70,9 @@ class CDrivesFolder : // IPersistFolder2 virtual HRESULT WINAPI GetCurFolder(LPITEMIDLIST * pidl); + // IContextMenuCB + virtual HRESULT WINAPI CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam); + DECLARE_REGISTRY_RESOURCEID(IDR_MYCOMPUTER) DECLARE_CENTRAL_INSTANCE_NOT_AGGREGATABLE(CDrivesFolder) @@ -80,6 +84,7 @@ class CDrivesFolder : COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder) COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2) COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + COM_INTERFACE_ENTRY_IID(IID_IContextMenuCB, IContextMenuCB) END_COM_MAP() }; diff --git a/dll/win32/shell32/folders/CFSFolder.cpp b/dll/win32/shell32/folders/CFSFolder.cpp index 77d87e6f829..ad205c47e10 100644 --- a/dll/win32/shell32/folders/CFSFolder.cpp +++ b/dll/win32/shell32/folders/CFSFolder.cpp @@ -1624,31 +1624,5 @@ HRESULT WINAPI CFSFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObjec if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES) return S_OK; - PIDLIST_ABSOLUTE pidlFolder; - PUITEMID_CHILD *apidl; - UINT cidl; - HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - if (cidl > 1) - ERR("SHMultiFileProperties is not yet implemented\n"); - - STRRET strFile; - hr = GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strFile); - if (SUCCEEDED(hr)) - { - hr = SH_ShowPropertiesDialog(strFile.pOleStr, pidlFolder, apidl); - if (FAILED(hr)) - ERR("SH_ShowPropertiesDialog failed\n"); - } - else - { - ERR("Failed to get display name\n"); - } - - SHFree(pidlFolder); - _ILFreeaPidl(apidl, cidl); - - return hr; + return Shell_DefaultContextMenuCallBack(this, pdtobj); } diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h index 75c136664d8..4e694f7b864 100644 --- a/dll/win32/shell32/precomp.h +++ b/dll/win32/shell32/precomp.h @@ -120,4 +120,7 @@ AddPropSheetPageCallback(HPROPSHEETPAGE hPage, LPARAM lParam) return FALSE; } +HRESULT WINAPI +Shell_DefaultContextMenuCallBack(IShellFolder *psf, IDataObject *pdtobj); + #endif /* _PRECOMP_H__ */ diff --git a/dll/win32/shell32/shlfolder.cpp b/dll/win32/shell32/shlfolder.cpp index 0b4d0f19a99..f652378616e 100644 --- a/dll/win32/shell32/shlfolder.cpp +++ b/dll/win32/shell32/shlfolder.cpp @@ -3,6 +3,7 @@ * * Copyright 1997 Marcus Meissner * Copyright 1998, 1999, 2002 Juergen Schmied + * Copyright 2018 Katayama Hirofumi MZ * * IShellFolder2 and related interfaces * @@ -441,3 +442,43 @@ SHOpenFolderAndSelectItems(LPITEMIDLIST pidlFolder, else return E_FAIL; } + +/* + * for internal use + */ +HRESULT WINAPI +Shell_DefaultContextMenuCallBack(IShellFolder *psf, IDataObject *pdtobj) +{ + PIDLIST_ABSOLUTE pidlFolder; + PUITEMID_CHILD *apidl; + UINT cidl; + HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + if (cidl > 1) + { + ERR("SHMultiFileProperties is not yet implemented\n"); + SHFree(pidlFolder); + _ILFreeaPidl(apidl, cidl); + return E_FAIL; + } + + STRRET strFile; + hr = psf->GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strFile); + if (SUCCEEDED(hr)) + { + hr = SH_ShowPropertiesDialog(strFile.pOleStr, pidlFolder, apidl); + if (FAILED(hr)) + ERR("SH_ShowPropertiesDialog failed\n"); + } + else + { + ERR("Failed to get display name\n"); + } + + SHFree(pidlFolder); + _ILFreeaPidl(apidl, cidl); + + return hr; +}