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