[EXPLORER][SHELL32] Show/hide 'Admin tools' menu (#6598)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Mon, 11 Mar 2024 12:58:30 +0000 (21:58 +0900)
committerGitHub <noreply@github.com>
Mon, 11 Mar 2024 12:58:30 +0000 (21:58 +0900)
Improve Start Menu customization.
JIRA issue: CORE-16956
- Add IsPidlPrograms helper function.
- Specify a PIDL for Programs menu.
- Check the "StartMenuAdminTools" registry value.
- Don't add "Admin Tools" menu item into
  CMenuSFToolbar::FillToolbar if necessary.

base/shell/explorer/startmnucust.cpp
dll/win32/shell32/shellmenu/CMenuToolbars.cpp
dll/win32/shell32/shellmenu/CStartMenu.cpp

index 0fe0fb9..059c2d0 100644 (file)
@@ -89,7 +89,9 @@ struct CUSTOMIZE_ENTRY
 
 static const CUSTOMIZE_ENTRY s_CustomizeEntries[] =
 {
-    // FIXME: Make "StartMenuAdminTools" effective for IDS_ADVANCED_DISPLAY_ADMINTOOLS
+    {
+        IDS_ADVANCED_DISPLAY_ADMINTOOLS, L"StartMenuAdminTools", TRUE,
+    },
     {
         IDS_ADVANCED_DISPLAY_FAVORITES, L"StartMenuFavorites", FALSE,
         REST_NOFAVORITESMENU
index 0d5cd9c..cb83e02 100644 (file)
@@ -1323,6 +1323,18 @@ int CALLBACK PidlListSort(void* item1, void* item2, LPARAM lParam)
     return (int)(short)LOWORD(hr);
 }
 
+static BOOL IsPidlPrograms(LPCITEMIDLIST pidlTarget)
+{
+    WCHAR szTarget[MAX_PATH], szPath[MAX_PATH];
+    if (!SHGetPathFromIDListW(pidlTarget, szTarget))
+        return FALSE;
+    SHGetSpecialFolderPathW(NULL, szPath, CSIDL_COMMON_PROGRAMS, FALSE);
+    if (lstrcmpiW(szTarget, szPath) == 0)
+        return TRUE;
+    SHGetSpecialFolderPathW(NULL, szPath, CSIDL_PROGRAMS, FALSE);
+    return (lstrcmpiW(szTarget, szPath) == 0);
+}
+
 HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst)
 {
     HRESULT hr;
@@ -1361,17 +1373,26 @@ HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst)
 
     DPA_Sort(dpaSort, PidlListSort, (LPARAM) m_shellFolder.p);
 
-    for (int i = 0; i<DPA_GetPtrCount(dpaSort);)
-    {
-        PWSTR MenuString;
+    BOOL StartMenuAdminTools = SHRegGetBoolUSValueW(
+        L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
+        L"StartMenuAdminTools", FALSE, TRUE);
 
-        INT index = 0;
-        INT indexOpen = 0;
+    BOOL bMustHideAdminTools = IsPidlPrograms(m_idList) && StartMenuAdminTools;
+    TRACE("StartMenuAdminTools: %d\n", StartMenuAdminTools);
+    TRACE("bMustHideAdminTools: %d\n", bMustHideAdminTools);
 
-        STRRET sr = { STRRET_CSTR, { 0 } };
+    WCHAR szAdminTools[MAX_PATH];
+    if (bMustHideAdminTools)
+    {
+        LoadStringW(GetModuleHandleW(L"shell32.dll"), IDS_ADMINISTRATIVETOOLS,
+                    szAdminTools, _countof(szAdminTools));
+    }
 
+    for (int i = 0; i<DPA_GetPtrCount(dpaSort);)
+    {
         item = (LPITEMIDLIST)DPA_GetPtr(dpaSort, i);
 
+        STRRET sr = { STRRET_CSTR };
         hr = m_shellFolder->GetDisplayNameOf(item, SIGDN_NORMALDISPLAY, &sr);
         if (FAILED_UNEXPECTEDLY(hr))
         {
@@ -1379,9 +1400,18 @@ HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst)
             return hr;
         }
 
+        PWSTR MenuString;
         StrRetToStr(&sr, NULL, &MenuString);
 
-        index = SHMapPIDLToSystemImageListIndex(m_shellFolder, item, &indexOpen);
+        if (bMustHideAdminTools && lstrcmpiW(MenuString, szAdminTools) == 0)
+        {
+            ++i;
+            CoTaskMemFree(MenuString);
+            continue;
+        }
+
+        INT indexOpen = 0;
+        INT index = SHMapPIDLToSystemImageListIndex(m_shellFolder, item, &indexOpen);
 
         LPCITEMIDLIST itemc = item;
 
index 9f450a6..f2975ee 100644 (file)
@@ -237,26 +237,33 @@ private:
         AddOrSetMenuItem(hMenu, IDM_PRINTERSANDFAXES, CSIDL_PRINTERS, bExpand, FALSE, FALSE);
     }
 
-    HRESULT AddStartMenuItems(IShellMenu *pShellMenu, INT csidl, DWORD dwFlags)
+    HRESULT AddStartMenuItems(IShellMenu *pShellMenu, INT csidl, DWORD dwFlags, IShellFolder *psf = NULL)
     {
-        CComHeapPtr<ITEMIDLIST> pidlMenu;
+        CComHeapPtr<ITEMIDLIST> pidlFolder;
         CComPtr<IShellFolder> psfDesktop;
         CComPtr<IShellFolder> pShellFolder;
         HRESULT hr;
 
-        hr = SHGetFolderLocation(NULL, csidl, 0, 0, &pidlMenu);
+        hr = SHGetFolderLocation(NULL, csidl, 0, 0, &pidlFolder);
         if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
-        hr = SHGetDesktopFolder(&psfDesktop);
-        if (FAILED_UNEXPECTEDLY(hr))
-            return hr;
+        if (psf)
+        {
+            pShellFolder = psf;
+        }
+        else
+        {
+            hr = SHGetDesktopFolder(&psfDesktop);
+            if (FAILED_UNEXPECTEDLY(hr))
+                return hr;
 
-        hr = psfDesktop->BindToObject(pidlMenu, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
-        if (FAILED_UNEXPECTEDLY(hr))
-            return hr;
+            hr = psfDesktop->BindToObject(pidlFolder, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
+            if (FAILED_UNEXPECTEDLY(hr))
+                return hr;
+        }
 
-        hr = pShellMenu->SetShellFolder(pShellFolder, NULL, NULL, dwFlags);
+        hr = pShellMenu->SetShellFolder(pShellFolder, pidlFolder, NULL, dwFlags);
         if (FAILED_UNEXPECTEDLY(hr))
             return hr;
 
@@ -281,8 +288,7 @@ private:
         {
             case IDM_PROGRAMS:
             {
-                if (m_psfPrograms)
-                    hr = pShellMenu->SetShellFolder(m_psfPrograms, NULL, NULL, SMSET_TOP);
+                hr = AddStartMenuItems(pShellMenu, CSIDL_PROGRAMS, SMSET_TOP, m_psfPrograms);
                 break;
             }
             case IDM_FAVORITES: