1 /* 2 * ReactOS Explorer 3 * 4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org> 5 * 2015 Robert Naumann <gonzomdx@gmail.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #include "precomp.h" 23 24 #define I_UNCHECKED 1 25 #define I_CHECKED 2 26 27 // TODO: Windows Explorer appears to be calling NewLinkHere / ConfigStartMenu directly for both items. 28 VOID OnAddStartMenuItems(HWND hDlg) 29 { 30 WCHAR szPath[MAX_PATH]; 31 32 if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, szPath))) 33 { 34 WCHAR szCommand[MAX_PATH] = L"appwiz.cpl,NewLinkHere "; 35 if (SUCCEEDED(StringCchCatW(szCommand, _countof(szCommand), szPath))) 36 ShellExecuteW(hDlg, L"open", L"rundll32.exe", szCommand, NULL, SW_SHOWNORMAL); 37 } 38 } 39 40 VOID OnRemoveStartmenuItems(HWND hDlg) 41 { 42 ShellExecuteW(hDlg, L"open", L"rundll32.exe", L"appwiz.cpl,ConfigStartMenu", NULL, SW_SHOWNORMAL); 43 } 44 45 VOID OnAdvancedStartMenuItems() 46 { 47 WCHAR szPath[MAX_PATH]; 48 49 if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, szPath))) 50 { 51 ShellExecuteW(NULL, L"explore", szPath, NULL, NULL, SW_SHOWNORMAL); 52 } 53 } 54 55 static BOOL RecentHasShortcut(HWND hwnd) 56 { 57 WCHAR szPath[MAX_PATH]; 58 if (FAILED(SHGetFolderPathW(hwnd, CSIDL_RECENT | CSIDL_FLAG_CREATE, NULL, 0, szPath))) 59 return FALSE; 60 61 // Find shortcut files in Recent 62 WIN32_FIND_DATAW find; 63 PathAppendW(szPath, L"*.lnk"); 64 HANDLE hFind = FindFirstFileW(szPath, &find); 65 if (hFind == INVALID_HANDLE_VALUE) 66 return FALSE; 67 68 FindClose(hFind); 69 return TRUE; 70 } 71 72 static VOID OnClearRecentItems(HWND hwnd) 73 { 74 SHAddToRecentDocs(SHARD_PIDL, NULL); 75 EnableWindow(GetDlgItem(hwnd, IDC_CLASSICSTART_CLEAR), RecentHasShortcut(hwnd)); 76 } 77 78 struct CUSTOMIZE_ENTRY; 79 typedef DWORD (CALLBACK *FN_CUSTOMIZE_READ)(const CUSTOMIZE_ENTRY *entry); 80 typedef BOOL (CALLBACK *FN_CUSTOMIZE_WRITE)(const CUSTOMIZE_ENTRY *entry, DWORD dwValue); 81 82 struct CUSTOMIZE_ENTRY 83 { 84 LPARAM id; 85 LPCWSTR name; 86 BOOL bDefaultValue; 87 RESTRICTIONS policy1, policy2; 88 }; 89 90 static const CUSTOMIZE_ENTRY s_CustomizeEntries[] = 91 { 92 { 93 IDS_ADVANCED_DISPLAY_ADMINTOOLS, L"StartMenuAdminTools", TRUE, 94 }, 95 { 96 IDS_ADVANCED_DISPLAY_FAVORITES, L"StartMenuFavorites", FALSE, 97 REST_NOFAVORITESMENU 98 }, 99 { 100 IDS_ADVANCED_DISPLAY_LOG_OFF, L"StartMenuLogoff", FALSE, 101 REST_STARTMENULOGOFF 102 }, 103 { 104 IDS_ADVANCED_DISPLAY_RUN, L"StartMenuRun", TRUE, 105 REST_NORUN 106 }, 107 { 108 IDS_ADVANCED_EXPAND_MY_DOCUMENTS, L"CascadeMyDocuments", FALSE, 109 REST_NOSMMYDOCS 110 }, 111 { 112 IDS_ADVANCED_EXPAND_MY_PICTURES, L"CascadeMyPictures", FALSE, 113 REST_NOSMMYPICS 114 }, 115 { 116 IDS_ADVANCED_EXPAND_CONTROL_PANEL, L"CascadeControlPanel", FALSE, 117 REST_NOSETFOLDERS, REST_NOCONTROLPANEL, 118 }, 119 { 120 IDS_ADVANCED_EXPAND_PRINTERS, L"CascadePrinters", FALSE, 121 REST_NOSETFOLDERS 122 }, 123 { 124 IDS_ADVANCED_EXPAND_NET_CONNECTIONS, L"CascadeNetworkConnections", FALSE, 125 REST_NOSETFOLDERS, REST_NONETWORKCONNECTIONS 126 }, 127 }; 128 129 static VOID AddCustomizeItem(HWND hTreeView, const CUSTOMIZE_ENTRY *entry) 130 { 131 if (SHRestricted(entry->policy1) || SHRestricted(entry->policy2)) 132 { 133 TRACE("%p: Restricted\n", entry->id); 134 return; // Restricted. Don't show 135 } 136 137 TV_INSERTSTRUCT Insert = { TVI_ROOT, TVI_LAST }; 138 Insert.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_PARAM; 139 140 WCHAR szText[MAX_PATH]; 141 LoadStringW(GetModuleHandleW(L"shell32.dll"), entry->id, szText, _countof(szText)); 142 Insert.item.pszText = szText; 143 Insert.item.lParam = entry->id; 144 Insert.item.stateMask = TVIS_STATEIMAGEMASK; 145 BOOL bChecked = GetAdvancedBool(entry->name, entry->bDefaultValue); 146 Insert.item.state = INDEXTOSTATEIMAGEMASK(bChecked ? I_CHECKED : I_UNCHECKED); 147 TRACE("%p: %d\n", entry->id, bChecked); 148 TreeView_InsertItem(hTreeView, &Insert); 149 } 150 151 static void CustomizeClassic_OnInitDialog(HWND hwnd) 152 { 153 EnableWindow(GetDlgItem(hwnd, IDC_CLASSICSTART_CLEAR), RecentHasShortcut(hwnd)); 154 155 HWND hTreeView = GetDlgItem(hwnd, IDC_CLASSICSTART_SETTINGS); 156 157 DWORD_PTR style = GetWindowLongPtrW(hTreeView, GWL_STYLE); 158 SetWindowLongPtrW(hTreeView, GWL_STYLE, style | TVS_CHECKBOXES); 159 160 for (auto& entry : s_CustomizeEntries) 161 { 162 AddCustomizeItem(hTreeView, &entry); 163 } 164 } 165 166 static BOOL CustomizeClassic_OnOK(HWND hwnd) 167 { 168 HWND hTreeView = GetDlgItem(hwnd, IDC_CLASSICSTART_SETTINGS); 169 170 for (HTREEITEM hItem = TreeView_GetFirstVisible(hTreeView); 171 hItem != NULL; 172 hItem = TreeView_GetNextVisible(hTreeView, hItem)) 173 { 174 TV_ITEM item = { TVIF_PARAM | TVIF_STATE }; 175 item.hItem = hItem; 176 item.stateMask = TVIS_STATEIMAGEMASK; 177 TreeView_GetItem(hTreeView, &item); 178 179 BOOL bChecked = !!(item.state & INDEXTOSTATEIMAGEMASK(I_CHECKED)); 180 for (auto& entry : s_CustomizeEntries) 181 { 182 if (SHRestricted(entry.policy1) || SHRestricted(entry.policy2)) 183 continue; 184 185 if (item.lParam == entry.id) 186 { 187 TRACE("%p: %d\n", item.lParam, bChecked); 188 SetAdvancedDword(entry.name, bChecked); 189 break; 190 } 191 } 192 } 193 194 SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"TraySettings", 195 SMTO_ABORTIFHUNG, 200, NULL); 196 return TRUE; 197 } 198 199 INT_PTR CALLBACK CustomizeClassicProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 200 { 201 switch (Message) 202 { 203 case WM_INITDIALOG: 204 CustomizeClassic_OnInitDialog(hwnd); 205 return TRUE; 206 case WM_COMMAND: 207 switch (LOWORD(wParam)) 208 { 209 case IDC_CLASSICSTART_ADD: 210 OnAddStartMenuItems(hwnd); 211 break; 212 case IDC_CLASSICSTART_REMOVE: 213 OnRemoveStartmenuItems(hwnd); 214 break; 215 case IDC_CLASSICSTART_ADVANCED: 216 OnAdvancedStartMenuItems(); 217 break; 218 case IDC_CLASSICSTART_CLEAR: 219 OnClearRecentItems(hwnd); 220 break; 221 case IDOK: 222 if (CustomizeClassic_OnOK(hwnd)) 223 { 224 EndDialog(hwnd, IDOK); 225 } 226 break; 227 case IDCANCEL: 228 EndDialog(hwnd, IDCANCEL); 229 break; 230 } 231 break; 232 default: 233 return FALSE; 234 } 235 return TRUE; 236 } 237 238 VOID ShowCustomizeClassic(HINSTANCE hInst, HWND hExplorer) 239 { 240 DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_CLASSICSTART_CUSTOMIZE), hExplorer, CustomizeClassicProc); 241 } 242