1 /* 2 * 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 // Folder Options: 27 // CLASSKEY = HKEY_CLASSES_ROOT\CLSID\{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF} 28 29 ///////////////////////////////////////////////////////////////////////////// 30 // strings 31 32 // path to shell32 33 LPCWSTR g_pszShell32 = L"%SystemRoot%\\system32\\shell32.dll"; 34 35 // the space characters 36 LPCWSTR g_pszSpace = L" \t\n\r\f\v"; 37 38 ///////////////////////////////////////////////////////////////////////////// 39 // utility functions 40 41 HBITMAP Create24BppBitmap(HDC hDC, INT cx, INT cy) 42 { 43 BITMAPINFO bi; 44 LPVOID pvBits; 45 46 ZeroMemory(&bi, sizeof(bi)); 47 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 48 bi.bmiHeader.biWidth = cx; 49 bi.bmiHeader.biHeight = cy; 50 bi.bmiHeader.biPlanes = 1; 51 bi.bmiHeader.biBitCount = 24; 52 bi.bmiHeader.biCompression = BI_RGB; 53 54 HBITMAP hbm = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0); 55 return hbm; 56 } 57 58 HBITMAP BitmapFromIcon(HICON hIcon, INT cx, INT cy) 59 { 60 HDC hDC = CreateCompatibleDC(NULL); 61 if (!hDC) 62 return NULL; 63 64 HBITMAP hbm = Create24BppBitmap(hDC, cx, cy); 65 if (!hbm) 66 { 67 DeleteDC(hDC); 68 return NULL; 69 } 70 71 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 72 { 73 RECT rc = { 0, 0, cx, cy }; 74 FillRect(hDC, &rc, HBRUSH(COLOR_3DFACE + 1)); 75 if (hIcon) 76 { 77 DrawIconEx(hDC, 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL); 78 } 79 } 80 SelectObject(hDC, hbmOld); 81 DeleteDC(hDC); 82 83 return hbm; 84 } 85 86 HBITMAP CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled) 87 { 88 INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); 89 INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); 90 91 HBITMAP hbm = Create24BppBitmap(hDC, cxSmallIcon, cySmallIcon); 92 if (hbm == NULL) 93 return NULL; // failure 94 95 RECT Rect, BoxRect; 96 SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); 97 BoxRect = Rect; 98 InflateRect(&BoxRect, -1, -1); 99 100 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 101 { 102 UINT uState = DFCS_BUTTONCHECK | DFCS_FLAT | DFCS_MONO; 103 if (bCheck) 104 uState |= DFCS_CHECKED; 105 if (!bEnabled) 106 uState |= DFCS_INACTIVE; 107 DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); 108 } 109 SelectObject(hDC, hbmOld); 110 111 return hbm; // success 112 } 113 114 HBITMAP CreateCheckMask(HDC hDC) 115 { 116 INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); 117 INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); 118 119 HBITMAP hbm = CreateBitmap(cxSmallIcon, cySmallIcon, 1, 1, NULL); 120 if (hbm == NULL) 121 return NULL; // failure 122 123 RECT Rect, BoxRect; 124 SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); 125 BoxRect = Rect; 126 InflateRect(&BoxRect, -1, -1); 127 128 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 129 { 130 FillRect(hDC, &Rect, HBRUSH(GetStockObject(WHITE_BRUSH))); 131 FillRect(hDC, &BoxRect, HBRUSH(GetStockObject(BLACK_BRUSH))); 132 } 133 SelectObject(hDC, hbmOld); 134 135 return hbm; // success 136 } 137 138 HBITMAP CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled) 139 { 140 INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); 141 INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); 142 143 HBITMAP hbm = Create24BppBitmap(hDC, cxSmallIcon, cySmallIcon); 144 if (hbm == NULL) 145 return NULL; // failure 146 147 RECT Rect, BoxRect; 148 SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); 149 BoxRect = Rect; 150 InflateRect(&BoxRect, -1, -1); 151 152 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 153 { 154 UINT uState = DFCS_BUTTONRADIOIMAGE | DFCS_FLAT | DFCS_MONO; 155 if (bCheck) 156 uState |= DFCS_CHECKED; 157 if (!bEnabled) 158 uState |= DFCS_INACTIVE; 159 DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); 160 } 161 SelectObject(hDC, hbmOld); 162 163 return hbm; // success 164 } 165 166 HBITMAP CreateRadioMask(HDC hDC) 167 { 168 INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); 169 INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); 170 171 HBITMAP hbm = CreateBitmap(cxSmallIcon, cySmallIcon, 1, 1, NULL); 172 if (hbm == NULL) 173 return NULL; // failure 174 175 RECT Rect, BoxRect; 176 SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); 177 BoxRect = Rect; 178 InflateRect(&BoxRect, -1, -1); 179 180 HGDIOBJ hbmOld = SelectObject(hDC, hbm); 181 { 182 FillRect(hDC, &Rect, HBRUSH(GetStockObject(WHITE_BRUSH))); 183 UINT uState = DFCS_BUTTONRADIOMASK | DFCS_FLAT | DFCS_MONO; 184 DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); 185 } 186 SelectObject(hDC, hbmOld); 187 188 return hbm; // success 189 } 190 191 ///////////////////////////////////////////////////////////////////////////// 192 193 // CMSGlobalFolderOptionsStub --- The owner window of Folder Options. 194 // This window hides taskbar button of Folder Options. 195 196 #define GlobalFolderOptionsClassName _T("MSGlobalFolderOptionsStub") 197 198 class CMSGlobalFolderOptionsStub : public CWindowImpl<CMSGlobalFolderOptionsStub> 199 { 200 public: 201 DECLARE_WND_CLASS_EX(GlobalFolderOptionsClassName, 0, COLOR_WINDOWTEXT) 202 203 BEGIN_MSG_MAP(CMSGlobalFolderOptionsStub) 204 END_MSG_MAP() 205 }; 206 207 ///////////////////////////////////////////////////////////////////////////// 208 209 EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj); 210 211 static int CALLBACK 212 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam) 213 { 214 // NOTE: This callback is needed to set large icon correctly. 215 HICON hIcon; 216 switch (uMsg) 217 { 218 case PSCB_INITIALIZED: 219 { 220 hIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS)); 221 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 222 break; 223 } 224 } 225 return 0; 226 } 227 228 enum { 229 PAGE_GENERAL, 230 PAGE_VIEW, 231 PAGE_FILETYPES 232 }; 233 234 static DWORD CALLBACK 235 ShowFolderOptionsDialogThreadProc(LPVOID param) 236 { 237 CCoInit com; // Required when started from rundll32 (SHAutoComplete in PickIconDlg) 238 PROPSHEETHEADERW pinfo; 239 HPROPSHEETPAGE hppages[3]; 240 HPROPSHEETPAGE hpage; 241 UINT num_pages = 0; 242 243 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg, 0, NULL); 244 if (hpage) 245 hppages[num_pages++] = hpage; 246 247 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW, FolderOptionsViewDlg, 0, NULL); 248 if (hpage) 249 hppages[num_pages++] = hpage; 250 251 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES, FolderOptionsFileTypesDlg, 0, NULL); 252 if (hpage) 253 hppages[num_pages++] = hpage; 254 255 // the stub window to hide taskbar button 256 DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION; 257 DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW; 258 CMSGlobalFolderOptionsStub stub; 259 if (!stub.Create(NULL, NULL, NULL, style, exstyle)) 260 { 261 ERR("stub.Create failed\n"); 262 return 0; 263 } 264 265 memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW)); 266 pinfo.dwSize = sizeof(PROPSHEETHEADERW); 267 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_USEICONID | PSH_USECALLBACK; 268 pinfo.hwndParent = stub; 269 pinfo.nPages = num_pages; 270 pinfo.phpage = hppages; 271 pinfo.hInstance = shell32_hInstance; 272 pinfo.pszIcon = MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS); 273 pinfo.pszCaption = MAKEINTRESOURCEW(IDS_FOLDER_OPTIONS); 274 pinfo.pfnCallback = PropSheetProc; 275 pinfo.nStartPage = PtrToUlong(param); 276 277 PropertySheetW(&pinfo); 278 279 stub.DestroyWindow(); 280 return 0; 281 } 282 283 VOID WINAPI 284 ShowFolderOptionsDialog(UINT Page, BOOL Async = FALSE) 285 { 286 HWND hWnd = FindWindow(GlobalFolderOptionsClassName, NULL); 287 if (hWnd) 288 { 289 HWND hPop = GetLastActivePopup(hWnd); 290 if (hWnd == GetParent(hPop)) 291 { 292 PostMessage(hPop, PSM_SETCURSEL, Page, 0); 293 } 294 SetForegroundWindow(hPop); 295 return; 296 } 297 298 LPVOID param = UlongToPtr(Page); 299 if (Async) 300 SHCreateThread(ShowFolderOptionsDialogThreadProc, param, 0, 0); 301 else 302 ShowFolderOptionsDialogThreadProc(param); // Rundll32 caller cannot be async! 303 } 304 305 static VOID 306 Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow) 307 { 308 switch(fOptions) 309 { 310 case 0: 311 ShowFolderOptionsDialog(PAGE_GENERAL); 312 break; 313 314 case 1: // Taskbar settings 315 #if (NTDDI_VERSION >= NTDDI_VISTA) 316 case 3: // Start menu settings 317 case 4: // Tray icon settings 318 case 6: // Taskbar toolbars 319 #endif 320 PostMessage(GetShellWindow(), WM_PROGMAN_OPENSHELLSETTINGS, fOptions, 0); 321 break; 322 323 case 7: // Windows 8, 10 324 ShowFolderOptionsDialog(PAGE_VIEW); 325 break; 326 327 default: 328 FIXME("unrecognized options id %d\n", fOptions); 329 } 330 } 331 332 /************************************************************************* 333 * Options_RunDLL (SHELL32.@) 334 */ 335 EXTERN_C VOID WINAPI 336 Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) 337 { 338 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow); 339 } 340 341 /************************************************************************* 342 * Options_RunDLLA (SHELL32.@) 343 */ 344 EXTERN_C VOID WINAPI 345 Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) 346 { 347 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow); 348 } 349 350 /************************************************************************* 351 * Options_RunDLLW (SHELL32.@) 352 */ 353 EXTERN_C VOID WINAPI 354 Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow) 355 { 356 Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow); 357 } 358