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
Create24BppBitmap(HDC hDC,INT cx,INT cy)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
BitmapFromIcon(HICON hIcon,INT cx,INT cy)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
CreateCheckImage(HDC hDC,BOOL bCheck,BOOL bEnabled)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
CreateCheckMask(HDC hDC)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
CreateRadioImage(HDC hDC,BOOL bCheck,BOOL bEnabled)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
CreateRadioMask(HDC hDC)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
PropSheetProc(HWND hwndDlg,UINT uMsg,LPARAM lParam)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
ShowFolderOptionsDialogThreadProc(LPVOID param)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
ShowFolderOptionsDialog(UINT Page,BOOL Async=FALSE)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
Options_RunDLLCommon(HWND hWnd,HINSTANCE hInst,int fOptions,DWORD nCmdShow)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
Options_RunDLL(HWND hWnd,HINSTANCE hInst,LPCSTR cmd,DWORD nCmdShow)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
Options_RunDLLA(HWND hWnd,HINSTANCE hInst,LPCSTR cmd,DWORD nCmdShow)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
Options_RunDLLW(HWND hWnd,HINSTANCE hInst,LPCWSTR cmd,DWORD nCmdShow)354 Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow)
355 {
356 Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow);
357 }
358