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 PROPSHEETHEADERW pinfo; 238 HPROPSHEETPAGE hppages[3]; 239 HPROPSHEETPAGE hpage; 240 UINT num_pages = 0; 241 242 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg, 0, NULL); 243 if (hpage) 244 hppages[num_pages++] = hpage; 245 246 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW, FolderOptionsViewDlg, 0, NULL); 247 if (hpage) 248 hppages[num_pages++] = hpage; 249 250 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES, FolderOptionsFileTypesDlg, 0, NULL); 251 if (hpage) 252 hppages[num_pages++] = hpage; 253 254 // the stub window to hide taskbar button 255 DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION; 256 DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW; 257 CMSGlobalFolderOptionsStub stub; 258 if (!stub.Create(NULL, NULL, NULL, style, exstyle)) 259 { 260 ERR("stub.Create failed\n"); 261 return 0; 262 } 263 264 memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW)); 265 pinfo.dwSize = sizeof(PROPSHEETHEADERW); 266 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_USEICONID | PSH_USECALLBACK; 267 pinfo.hwndParent = stub; 268 pinfo.nPages = num_pages; 269 pinfo.phpage = hppages; 270 pinfo.hInstance = shell32_hInstance; 271 pinfo.pszIcon = MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS); 272 pinfo.pszCaption = MAKEINTRESOURCEW(IDS_FOLDER_OPTIONS); 273 pinfo.pfnCallback = PropSheetProc; 274 pinfo.nStartPage = PtrToUlong(param); 275 276 PropertySheetW(&pinfo); 277 278 stub.DestroyWindow(); 279 return 0; 280 } 281 282 VOID WINAPI 283 ShowFolderOptionsDialog(UINT Page, BOOL Async = FALSE) 284 { 285 HWND hWnd = FindWindow(GlobalFolderOptionsClassName, NULL); 286 if (hWnd) 287 { 288 HWND hPop = GetLastActivePopup(hWnd); 289 if (hWnd == GetParent(hPop)) 290 { 291 PostMessage(hPop, PSM_SETCURSEL, Page, 0); 292 } 293 SetForegroundWindow(hPop); 294 return; 295 } 296 297 LPVOID param = UlongToPtr(Page); 298 if (Async) 299 SHCreateThread(ShowFolderOptionsDialogThreadProc, param, 0, 0); 300 else 301 ShowFolderOptionsDialogThreadProc(param); // Rundll32 caller cannot be async! 302 } 303 304 static VOID 305 Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow) 306 { 307 switch(fOptions) 308 { 309 case 0: 310 ShowFolderOptionsDialog(PAGE_GENERAL); 311 break; 312 313 case 1: // Taskbar settings 314 #if (NTDDI_VERSION >= NTDDI_VISTA) 315 case 3: // Start menu settings 316 case 4: // Tray icon settings 317 case 6: // Taskbar toolbars 318 #endif 319 PostMessage(GetShellWindow(), WM_PROGMAN_OPENSHELLSETTINGS, fOptions, 0); 320 break; 321 322 case 7: // Windows 8, 10 323 ShowFolderOptionsDialog(PAGE_VIEW); 324 break; 325 326 default: 327 FIXME("unrecognized options id %d\n", fOptions); 328 } 329 } 330 331 /************************************************************************* 332 * Options_RunDLL (SHELL32.@) 333 */ 334 EXTERN_C VOID WINAPI 335 Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) 336 { 337 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow); 338 } 339 340 /************************************************************************* 341 * Options_RunDLLA (SHELL32.@) 342 */ 343 EXTERN_C VOID WINAPI 344 Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) 345 { 346 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow); 347 } 348 349 /************************************************************************* 350 * Options_RunDLLW (SHELL32.@) 351 */ 352 EXTERN_C VOID WINAPI 353 Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow) 354 { 355 Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow); 356 } 357