Reactos
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
24WINE_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
33LPCWSTR g_pszShell32 = L"%SystemRoot%\\system32\\shell32.dll";
34
35// the space characters
36LPCWSTR g_pszSpace = L" \t\n\r\f\v";
37
38/////////////////////////////////////////////////////////////////////////////
39// utility functions
40
41HBITMAP 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
58HBITMAP 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
87/////////////////////////////////////////////////////////////////////////////
88
89// CMSGlobalFolderOptionsStub --- The owner window of Folder Options.
90// This window hides taskbar button of Folder Options.
91
92#define GlobalFolderOptionsClassName _T("MSGlobalFolderOptionsStub")
93
94class CMSGlobalFolderOptionsStub : public CWindowImpl<CMSGlobalFolderOptionsStub>
95{
96public:
97 DECLARE_WND_CLASS_EX(GlobalFolderOptionsClassName, 0, COLOR_WINDOWTEXT)
98
99 BEGIN_MSG_MAP(CMSGlobalFolderOptionsStub)
100 END_MSG_MAP()
101};
102
103/////////////////////////////////////////////////////////////////////////////
104
105EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
106
107static int CALLBACK
108PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
109{
110 // NOTE: This callback is needed to set large icon correctly.
111 HICON hIcon;
112 switch (uMsg)
113 {
114 case PSCB_INITIALIZED:
115 {
116 hIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS));
117 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
118 break;
119 }
120 }
121 return 0;
122}
123
124enum {
125 PAGE_GENERAL,
126 PAGE_VIEW,
127 PAGE_FILETYPES
128};
129
130static DWORD CALLBACK
131ShowFolderOptionsDialogThreadProc(LPVOID param)
132{
133 CCoInit com; // Required when started from rundll32 (IRegTreeOptions, SHAutoComplete (in PickIconDlg))
134 PROPSHEETHEADERW pinfo;
135 HPROPSHEETPAGE hppages[3];
136 HPROPSHEETPAGE hpage;
137 UINT num_pages = 0;
138
139 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg, 0, NULL);
140 if (hpage)
141 hppages[num_pages++] = hpage;
142
143 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW, FolderOptionsViewDlg, 0, NULL);
144 if (hpage)
145 hppages[num_pages++] = hpage;
146
147 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES, FolderOptionsFileTypesDlg, 0, NULL);
148 if (hpage)
149 hppages[num_pages++] = hpage;
150
151 // the stub window to hide taskbar button
152 DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
153 DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW;
154 CMSGlobalFolderOptionsStub stub;
155 if (!stub.Create(NULL, NULL, NULL, style, exstyle))
156 {
157 ERR("stub.Create failed\n");
158 return 0;
159 }
160
161 memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW));
162 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
163 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_USEICONID | PSH_USECALLBACK;
164 pinfo.hwndParent = stub;
165 pinfo.nPages = num_pages;
166 pinfo.phpage = hppages;
167 pinfo.hInstance = shell32_hInstance;
168 pinfo.pszIcon = MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS);
169 pinfo.pszCaption = MAKEINTRESOURCEW(IDS_FOLDER_OPTIONS);
170 pinfo.pfnCallback = PropSheetProc;
171 pinfo.nStartPage = PtrToUlong(param);
172
173 PropertySheetW(&pinfo);
174
175 stub.DestroyWindow();
176 return 0;
177}
178
179VOID WINAPI
180ShowFolderOptionsDialog(UINT Page, BOOL Async = FALSE)
181{
182 HWND hWnd = FindWindow(GlobalFolderOptionsClassName, NULL);
183 if (hWnd)
184 {
185 HWND hPop = GetLastActivePopup(hWnd);
186 if (hWnd == GetParent(hPop))
187 {
188 PostMessage(hPop, PSM_SETCURSEL, Page, 0);
189 }
190 SetForegroundWindow(hPop);
191 return;
192 }
193
194 LPVOID param = UlongToPtr(Page);
195 if (Async)
196 SHCreateThread(ShowFolderOptionsDialogThreadProc, param, 0, 0);
197 else
198 ShowFolderOptionsDialogThreadProc(param); // Rundll32 caller cannot be async!
199}
200
201static VOID
202Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow)
203{
204 switch(fOptions)
205 {
206 case 0:
207 ShowFolderOptionsDialog(PAGE_GENERAL);
208 break;
209
210 case 1: // Taskbar settings
211#if (NTDDI_VERSION >= NTDDI_VISTA)
212 case 3: // Start menu settings
213 case 4: // Tray icon settings
214 case 6: // Taskbar toolbars
215#endif
216 PostMessage(GetShellWindow(), WM_PROGMAN_OPENSHELLSETTINGS, fOptions, 0);
217 break;
218
219 case 7: // Windows 8, 10
220 ShowFolderOptionsDialog(PAGE_VIEW);
221 break;
222
223 default:
224 FIXME("unrecognized options id %d\n", fOptions);
225 }
226}
227
228/*************************************************************************
229 * Options_RunDLL (SHELL32.@)
230 */
231EXTERN_C VOID WINAPI
232Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
233{
234 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow);
235}
236
237/*************************************************************************
238 * Options_RunDLLA (SHELL32.@)
239 */
240EXTERN_C VOID WINAPI
241Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
242{
243 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow);
244}
245
246/*************************************************************************
247 * Options_RunDLLW (SHELL32.@)
248 */
249EXTERN_C VOID WINAPI
250Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow)
251{
252 Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow);
253}