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