1 /* 2 * 'General' tab property sheet of Folder Options 3 * 4 * Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org> 5 * Copyright 2016-2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@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 St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "precomp.h" 23 24 WINE_DEFAULT_DEBUG_CHANNEL (fprop); 25 26 typedef struct REGSHELLSTATE 27 { 28 DWORD dwSize; 29 SHELLSTATE ss; 30 } REGSHELLSTATE, *PREGSHELLSTATE; 31 32 #define REGSHELLSTATE_SIZE 0x24 33 34 static const LPCWSTR s_pszExplorerKey = 35 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"; 36 37 extern "C" 38 BOOL WINAPI SHSettingsChanged(LPCVOID unused, LPCVOID inpRegKey); 39 40 ///////////////////////////////////////////////////////////////////////////// 41 // Shell settings 42 43 static void 44 IntGetDefaultShellState(REGSHELLSTATE& rss) 45 { 46 ZeroMemory(&rss, sizeof(rss)); 47 rss.dwSize = REGSHELLSTATE_SIZE; 48 49 rss.ss.fShowAllObjects = TRUE; 50 rss.ss.fShowExtensions = TRUE; 51 52 rss.ss.fShowCompColor = TRUE; 53 rss.ss.fDoubleClickInWebView = TRUE; 54 rss.ss.fShowInfoTip = TRUE; 55 56 rss.ss.iSortDirection = 1; 57 rss.ss.version = 0xD; 58 rss.ss.fStartPanelOn = TRUE; 59 } 60 61 // bDoubleClick is TRUE if "Double-click to open an item (single-click to select)". 62 // bDoubleClick is FALSE if "Single-click to open an item (point to select)". 63 ////////////////////////////////////////////////////////////////////////////// 64 // API Monitor: 65 // SHLWAPI.dll RegOpenKeyExW ( 0x000000c8, NULL, 0, MAXIMUM_ALLOWED, 0x00def234 ) ERROR_SUCCESS 0.0000243 66 // SHLWAPI.dll RegSetValueExW ( 0x000003e8, "ShellState", 0, REG_BINARY, 0x000c2050, 36 ) ERROR_SUCCESS 0.0001028 67 // SHLWAPI.dll RegCloseKey ( 0x000003e8 ) ERROR_SUCCESS 0.0000081 68 // Explorer.EXE SHSettingsChanged ( 0, "ShellState" ) 0.0000131 69 static BOOL 70 IntSetShellStateSettings(BOOL bDoubleClick, BOOL bUseCommonTasks) 71 { 72 REGSHELLSTATE rss; 73 DWORD dwSize = sizeof(rss); 74 LSTATUS nStatus; 75 76 // read ShellState 77 nStatus = SHGetValueW(HKEY_CURRENT_USER, 78 s_pszExplorerKey, 79 L"ShellState", 80 NULL, 81 &rss, 82 &dwSize); 83 if (nStatus != ERROR_SUCCESS || rss.dwSize < REGSHELLSTATE_SIZE) 84 { 85 IntGetDefaultShellState(rss); 86 } 87 88 // update ShellState 89 rss.ss.fDoubleClickInWebView = (bDoubleClick ? TRUE : FALSE); 90 rss.ss.fWebView = (bUseCommonTasks ? TRUE : FALSE); 91 92 // write ShellState 93 rss.dwSize = dwSize = REGSHELLSTATE_SIZE; 94 nStatus = SHSetValueW(HKEY_CURRENT_USER, 95 s_pszExplorerKey, 96 L"ShellState", 97 REG_BINARY, 98 &rss, 99 dwSize); 100 if (nStatus != ERROR_SUCCESS) 101 return FALSE; 102 103 SHSettingsChanged(0, L"ShellState"); 104 return TRUE; 105 } 106 107 ////////////////////////////////////////////////////////////////////////////// 108 // API Monitor: 109 // SHLWAPI.dll RegOpenKeyExW ( 0x000000c8, NULL, 0, MAXIMUM_ALLOWED, 0x0007e484 ) ERROR_SUCCESS 0.0000388 110 // SHLWAPI.dll RegQueryValueExW ( 0x000005a8, "ShellState", NULL, 0x0007e474, 0x000c2050, 0x0007e4fc ) ERROR_SUCCESS 0.0000271 111 // SHLWAPI.dll RegCloseKey ( 0x000005a8 ) ERROR_SUCCESS 0.0000112 112 static BOOL 113 IntGetShellStateSettings(BOOL& bDoubleClick, BOOL& bUseCommonTasks) 114 { 115 REGSHELLSTATE rss; 116 DWORD dwSize = sizeof(rss); 117 LSTATUS nStatus; 118 bDoubleClick = TRUE; 119 bUseCommonTasks = FALSE; 120 121 // read ShellState 122 nStatus = SHGetValueW(HKEY_CURRENT_USER, s_pszExplorerKey, 123 L"ShellState", NULL, &rss, &dwSize); 124 if (nStatus != ERROR_SUCCESS || rss.dwSize < REGSHELLSTATE_SIZE) 125 return FALSE; 126 127 bDoubleClick = !!rss.ss.fDoubleClickInWebView; 128 bUseCommonTasks = !!rss.ss.fWebView; 129 return TRUE; 130 } 131 132 // bIconUnderline is TRUE if "Underline icon titles only when I point at them". 133 // bIconUnderline is FALSE if "Underline icon titles consistent with my browser". 134 ////////////////////////////////////////////////////////////////////////////// 135 // API Monitor: 136 // SHELL32.dll SHRegGetUSValueW ( "Software\Microsoft\Windows\CurrentVersion\Explorer", "IconUnderline", NULL, 0x00d2f324, 0x00d2f328, FALSE, 0x00d2f32c, 4 ) ERROR_SUCCESS 0.0002484 137 // SHELL32.dll IsDlgButtonChecked ( 0x0005009e, 30104 ) BST_CHECKED 0.0000212 138 // SHELL32.dll SHRegSetUSValueW ( "Software\Microsoft\Windows\CurrentVersion\Explorer", "IconUnderline", 0, 0x00d2f314, 4, 6 ) ERROR_SUCCESS 0.0008300 139 // Explorer.EXE SHSettingsChanged ( 0, "Software\Microsoft\Windows\CurrentVersion\Explorer\IconUnderline" ) 0.0000092 140 static BOOL IntSetUnderlineState(BOOL bIconUnderline) 141 { 142 LSTATUS Status; 143 DWORD dwValue = (bIconUnderline ? 3 : 2), dwSize = sizeof(DWORD); 144 Status = SHRegSetUSValue(s_pszExplorerKey, L"IconUnderline", REG_NONE, 145 &dwValue, dwSize, SHREGSET_FORCE_HKCU | SHREGSET_HKLM); 146 if (Status != ERROR_SUCCESS) 147 return FALSE; 148 149 SHSettingsChanged(0, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\IconUnderline"); 150 return TRUE; 151 } 152 153 static BOOL IntGetUnderlineState(VOID) 154 { 155 DWORD dwValue, dwDefault = 2, dwSize = sizeof(DWORD); 156 SHRegGetUSValue(s_pszExplorerKey, L"IconUnderline", NULL, &dwValue, &dwSize, FALSE, &dwDefault, sizeof(DWORD)); 157 return dwValue == 3; 158 } 159 160 // bNewWindowMode is TRUE if "Open each folder in its own window". 161 // bNewWindowMode is FALSE if "Open each folder in the same window". 162 ////////////////////////////////////////////////////////////////////////////// 163 // API Monitor: 164 // SHELL32.dll RegCreateKeyExW ( HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState", 0, NULL, 0, KEY_SET_VALUE, NULL, 0x00d2f2b8, NULL ) ERROR_SUCCESS 0.0000455 165 // SHELL32.dll RegSetValueExW ( 0x00000854, "Settings", 0, REG_BINARY, 0x0210f170, 12 ) ERROR_SUCCESS 0.0001472 166 // SHELL32.dll RegSetValueExW ( 0x00000854, "FullPath", 0, REG_DWORD, 0x00d2f2ac, 4 ) ERROR_SUCCESS 0.0000168 167 // SHELL32.dll RegCloseKey ( 0x00000854 ) ERROR_SUCCESS 0.0000000 168 static BOOL IntSetNewWindowMode(BOOL bNewWindowMode) 169 { 170 CABINETSTATE cs; 171 if (!ReadCabinetState(&cs, sizeof(cs))) 172 return FALSE; 173 174 cs.fNewWindowMode = (bNewWindowMode ? TRUE : FALSE); 175 return WriteCabinetState(&cs); 176 } 177 178 static BOOL IntGetNewWindowMode(VOID) 179 { 180 CABINETSTATE cs; 181 if (!ReadCabinetState(&cs, sizeof(cs))) 182 return FALSE; 183 184 return !!cs.fNewWindowMode; 185 } 186 187 ///////////////////////////////////////////////////////////////////////////// 188 // GeneralDlg 189 190 typedef struct GENERAL_DIALOG 191 { 192 HICON hTaskIcon; 193 HICON hFolderIcon; 194 HICON hClickIcon; 195 } GENERAL_DIALOG, *PGENERAL_DIALOG; 196 197 static VOID 198 GeneralDlg_UpdateIcons(HWND hDlg, UINT nCtrlID, PGENERAL_DIALOG pGeneral) 199 { 200 HICON hTaskIcon = NULL, hFolderIcon = NULL, hClickIcon = NULL; 201 LPTSTR lpTaskIconName = NULL, lpFolderIconName = NULL, lpClickIconName = NULL; 202 203 // Show task setting icon. 204 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED) 205 lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_SHOW_COMMON_TASKS); 206 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_CLASSICFOLDERS) == BST_CHECKED) 207 lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_CLASSIC_FOLDERS); 208 209 if (lpTaskIconName) 210 { 211 hTaskIcon = (HICON)LoadImage(shell32_hInstance, lpTaskIconName, 212 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 213 if (hTaskIcon) 214 { 215 HWND hwndTaskIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_TASKICON); 216 SendMessage(hwndTaskIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hTaskIcon); 217 } 218 } 219 220 // Show Folder setting icons 221 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED) 222 lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_SOME_WINDOW); 223 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_OWNWINDOW) == BST_CHECKED) 224 lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_NEW_WINDOW); 225 226 if (lpFolderIconName) 227 { 228 hFolderIcon = (HICON)LoadImage(shell32_hInstance, lpFolderIconName, 229 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 230 if (hFolderIcon) 231 { 232 HWND hwndFolderIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_FOLDERICON); 233 SendMessage(hwndFolderIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hFolderIcon); 234 } 235 } 236 237 // Show click setting icon 238 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED) 239 lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_SINGLE_CLICK_TO_OPEN); 240 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_DOUBLECLICK) == BST_CHECKED) 241 lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_DOUBLE_CLICK_TO_OPEN); 242 243 if (lpClickIconName) 244 { 245 hClickIcon = (HICON)LoadImage(shell32_hInstance, lpClickIconName, 246 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 247 if (hClickIcon) 248 { 249 HWND hwndClickIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_CLICKICON); 250 SendMessage(hwndClickIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hClickIcon); 251 } 252 } 253 254 // Replace icons 255 if (hTaskIcon) 256 { 257 DestroyIcon(pGeneral->hTaskIcon); 258 pGeneral->hTaskIcon = hTaskIcon; 259 } 260 if (hFolderIcon) 261 { 262 DestroyIcon(pGeneral->hFolderIcon); 263 pGeneral->hFolderIcon = hFolderIcon; 264 } 265 if (hClickIcon) 266 { 267 DestroyIcon(pGeneral->hClickIcon); 268 pGeneral->hClickIcon = hClickIcon; 269 } 270 271 if (nCtrlID == IDC_FOLDER_OPTIONS_SINGLECLICK) 272 { 273 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULBROWSER), TRUE); 274 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULPOINT), TRUE); 275 } 276 277 if (nCtrlID == IDC_FOLDER_OPTIONS_DOUBLECLICK) 278 { 279 CheckRadioButton(hDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULBROWSER); 280 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULBROWSER), FALSE); 281 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULPOINT), FALSE); 282 } 283 } 284 285 static void 286 GeneralDlg_StoreToUI(HWND hwndDlg, BOOL bDoubleClick, BOOL bUseCommonTasks, 287 BOOL bUnderline, BOOL bNewWindowMode, PGENERAL_DIALOG pGeneral) 288 { 289 if (bUseCommonTasks) 290 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS, IDC_FOLDER_OPTIONS_COMMONTASKS); 291 else 292 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS); 293 294 if (bDoubleClick) 295 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK); 296 else 297 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK, IDC_FOLDER_OPTIONS_SINGLECLICK); 298 299 if (bNewWindowMode) 300 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW); 301 else 302 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW, IDC_FOLDER_OPTIONS_SAMEWINDOW); 303 304 if (!bDoubleClick) 305 { 306 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER), TRUE); 307 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULPOINT), TRUE); 308 if (bUnderline) 309 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULPOINT); 310 else 311 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULBROWSER); 312 } 313 else 314 { 315 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER), FALSE); 316 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULPOINT), FALSE); 317 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULBROWSER); 318 } 319 } 320 321 static BOOL 322 GeneralDlg_OnInitDialog(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 323 { 324 BOOL bDoubleClick = TRUE; 325 BOOL bUseCommonTasks = FALSE; 326 BOOL bUnderline = IntGetUnderlineState(); 327 BOOL bNewWindowMode = IntGetNewWindowMode(); 328 329 IntGetShellStateSettings(bDoubleClick, bUseCommonTasks); 330 331 GeneralDlg_StoreToUI(hwndDlg, bDoubleClick, bUseCommonTasks, bUnderline, bNewWindowMode, pGeneral); 332 GeneralDlg_UpdateIcons(hwndDlg, 0, pGeneral); 333 334 return TRUE; 335 } 336 337 static void 338 GeneralDlg_OnRestoreDefaults(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 339 { 340 // default values 341 BOOL bDoubleClick = TRUE; 342 BOOL bUseCommonTasks = FALSE; 343 BOOL bUnderline = FALSE; 344 BOOL bNewWindowMode = FALSE; 345 346 GeneralDlg_StoreToUI(hwndDlg, bDoubleClick, bUseCommonTasks, bUnderline, bNewWindowMode, pGeneral); 347 GeneralDlg_UpdateIcons(hwndDlg, 0, pGeneral); 348 } 349 350 static BOOL 351 GeneralDlg_OnApply(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 352 { 353 BOOL bDoubleClick = !(IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED); 354 BOOL bUseCommonTasks = (IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED); 355 BOOL bUnderline = (IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_ULPOINT) == BST_CHECKED); 356 BOOL bNewWindowMode = !(IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED); 357 358 IntSetUnderlineState(bUnderline); 359 IntSetNewWindowMode(bNewWindowMode); 360 IntSetShellStateSettings(bDoubleClick, bUseCommonTasks); 361 return TRUE; 362 } 363 364 INT_PTR CALLBACK 365 FolderOptionsGeneralDlg( 366 HWND hwndDlg, 367 UINT uMsg, 368 WPARAM wParam, 369 LPARAM lParam) 370 { 371 static GENERAL_DIALOG general; 372 373 switch (uMsg) 374 { 375 case WM_INITDIALOG: 376 general.hTaskIcon = NULL; 377 general.hFolderIcon = NULL; 378 general.hClickIcon = NULL; 379 return GeneralDlg_OnInitDialog(hwndDlg, &general); 380 381 case WM_COMMAND: 382 switch (LOWORD(wParam)) 383 { 384 case IDC_FOLDER_OPTIONS_COMMONTASKS: 385 case IDC_FOLDER_OPTIONS_CLASSICFOLDERS: 386 case IDC_FOLDER_OPTIONS_SAMEWINDOW: 387 case IDC_FOLDER_OPTIONS_OWNWINDOW: 388 case IDC_FOLDER_OPTIONS_SINGLECLICK: 389 case IDC_FOLDER_OPTIONS_DOUBLECLICK: 390 case IDC_FOLDER_OPTIONS_ULBROWSER: 391 case IDC_FOLDER_OPTIONS_ULPOINT: 392 if (HIWORD(wParam) == BN_CLICKED) 393 { 394 GeneralDlg_UpdateIcons(hwndDlg, LOWORD(wParam), &general); 395 396 // Enable the 'Apply' button 397 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 398 } 399 break; 400 case IDC_FOLDER_OPTIONS_RESTORE: 401 if (HIWORD(wParam) == BN_CLICKED) 402 { 403 GeneralDlg_OnRestoreDefaults(hwndDlg, &general); 404 405 // Enable the 'Apply' button 406 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 407 } 408 break; 409 } 410 break; 411 412 case WM_NOTIFY: 413 { 414 LPNMHDR pnmh = (LPNMHDR)lParam; 415 416 switch (pnmh->code) 417 { 418 case PSN_SETACTIVE: 419 break; 420 421 case PSN_APPLY: 422 return GeneralDlg_OnApply(hwndDlg, &general); 423 } 424 break; 425 } 426 427 case WM_DESTROY: 428 DestroyIcon(general.hTaskIcon); 429 DestroyIcon(general.hFolderIcon); 430 DestroyIcon(general.hClickIcon); 431 break; 432 433 default: 434 return FALSE; 435 } 436 return FALSE; 437 } 438