From b7aae3cdfd3aae4646b434d47bb7bc6264b639d2 Mon Sep 17 00:00:00 2001 From: Joachim Henze Date: Sat, 26 Feb 2022 19:05:52 +0100 Subject: [PATCH] [0.4.9][SHELL32] Add 'Properties' menu item in My Computer (#647) CORE-12509 - Add a Shell_DefaultContextMenuCallBack() helper function. - Implement the IContextMenuCB interface in CDrivesFolder. It regressed by some unknown commit in between SVN r70702 to r73408 fix picked from 0.4.10-dev-329-g 55469633cfbf20ba34bc747a80001bd4c7c4afb4 --- dll/win32/shell32/folders/CDesktopFolder.cpp | 28 +--------- dll/win32/shell32/folders/CDrivesFolder.cpp | 57 +++++++++++++++++++- 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, 107 insertions(+), 57 deletions(-) diff --git a/dll/win32/shell32/folders/CDesktopFolder.cpp b/dll/win32/shell32/folders/CDesktopFolder.cpp index a9ad663b3b8..277499fbc41 100644 --- a/dll/win32/shell32/folders/CDesktopFolder.cpp +++ b/dll/win32/shell32/folders/CDesktopFolder.cpp @@ -867,33 +867,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 a4c09b1f9e7..50e1651f369 100644 --- a/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -618,8 +618,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)) { @@ -1008,3 +1021,43 @@ 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", + L"shell32.dll,Control_RunDLL sysdm.cpl", + 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 15039eac607..328a1af4bdb 100644 --- a/dll/win32/shell32/folders/CFSFolder.cpp +++ b/dll/win32/shell32/folders/CFSFolder.cpp @@ -1573,31 +1573,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 f85423ea853..1e6446f20fd 100644 --- a/dll/win32/shell32/precomp.h +++ b/dll/win32/shell32/precomp.h @@ -117,4 +117,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; +}