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