ba7cfcddc5cff43e4e924f240bb062e1d3f14b29
[reactos.git] / reactos / dll / cpl / desk / desk.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: dll/cpl/desk/desk.c
5 * PURPOSE: ReactOS Display Control Panel
6 *
7 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
8 */
9
10 #include "desk.h"
11 #include <shellapi.h>
12 #include <cplext.h>
13 #include <debug.h>
14
15 #define NUM_APPLETS (1)
16
17 static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam);
18
19 INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
20 INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
21 INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
22 INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
23 UINT CALLBACK SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
24
25 HINSTANCE hApplet = 0;
26 HWND hCPLWindow;
27
28 /* Applets */
29 APPLET Applets[NUM_APPLETS] =
30 {
31 {
32 IDC_DESK_ICON,
33 IDS_CPLNAME,
34 IDS_CPLDESCRIPTION,
35 DisplayApplet
36 }
37 };
38
39 HMENU
40 LoadPopupMenu(IN HINSTANCE hInstance,
41 IN LPCTSTR lpMenuName)
42 {
43 HMENU hMenu, hSubMenu = NULL;
44
45 hMenu = LoadMenu(hInstance,
46 lpMenuName);
47
48 if (hMenu != NULL)
49 {
50 hSubMenu = GetSubMenu(hMenu,
51 0);
52 if (hSubMenu != NULL &&
53 !RemoveMenu(hMenu,
54 0,
55 MF_BYPOSITION))
56 {
57 hSubMenu = NULL;
58 }
59
60 DestroyMenu(hMenu);
61 }
62
63 return hSubMenu;
64 }
65
66 static BOOL CALLBACK
67 PropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam)
68 {
69 PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
70 if (ppsh != NULL && ppsh->nPages < MAX_DESK_PAGES)
71 {
72 ppsh->phpage[ppsh->nPages++] = hpage;
73 return TRUE;
74 }
75
76 return FALSE;
77 }
78
79 static BOOL
80 InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc, LPFNPSPCALLBACK pfnCallback)
81 {
82 HPROPSHEETPAGE hPage;
83 PROPSHEETPAGE psp;
84
85 if (ppsh->nPages < MAX_DESK_PAGES)
86 {
87 ZeroMemory(&psp, sizeof(psp));
88 psp.dwSize = sizeof(psp);
89 psp.dwFlags = PSP_DEFAULT;
90 if (pfnCallback != NULL)
91 psp.dwFlags |= PSP_USECALLBACK;
92 psp.hInstance = hApplet;
93 psp.pszTemplate = MAKEINTRESOURCE(idDlg);
94 psp.pfnDlgProc = DlgProc;
95 psp.pfnCallback = pfnCallback;
96
97 hPage = CreatePropertySheetPage(&psp);
98 if (hPage != NULL)
99 {
100 return PropSheetAddPage(hPage, (LPARAM)ppsh);
101 }
102 }
103
104 return FALSE;
105 }
106
107 static const struct
108 {
109 WORD idDlg;
110 DLGPROC DlgProc;
111 LPFNPSPCALLBACK Callback;
112 LPWSTR Name;
113 } PropPages[] =
114 {
115 { IDD_BACKGROUND, BackgroundPageProc, NULL, L"Desktop" },
116 { IDD_SCREENSAVER, ScreenSaverPageProc, NULL, L"Screen Saver" },
117 { IDD_APPEARANCE, AppearancePageProc, NULL, L"Appearance" },
118 { IDD_SETTINGS, SettingsPageProc, SettingsPageCallbackProc, L"Settings" },
119 };
120
121 /* Display Applet */
122 static LONG APIENTRY
123 DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
124 {
125 HPROPSHEETPAGE hpsp[MAX_DESK_PAGES];
126 PROPSHEETHEADER psh;
127 HPSXA hpsxa;
128 TCHAR Caption[1024];
129 LONG ret;
130 UINT i;
131 LPWSTR *argv = NULL;
132 LPCWSTR pwszSelectedTab = NULL;
133 LPCWSTR pwszFile = NULL;
134 LPCWSTR pwszAction = NULL;
135
136 UNREFERENCED_PARAMETER(wParam);
137
138 hCPLWindow = hwnd;
139
140 if (uMsg == CPL_STARTWPARMSW && lParam)
141 {
142 int argc;
143 int i;
144 LPCWSTR pszCommandLine = (LPCWSTR)lParam;
145
146 argv = CommandLineToArgvW(pszCommandLine, &argc);
147
148 if (argv && argc)
149 {
150 for (i = 0; i<argc; i++)
151 {
152 if (argv[i][0] == L'@')
153 pwszSelectedTab = &argv[i][1];
154 else if (wcsncmp(argv[i], L"/Action:", 8) == 0)
155 pwszAction = &argv[i][8];
156 else if (wcsncmp(argv[i], L"/file:", 6) == 0)
157 pwszFile = &argv[i][6];
158 }
159 }
160
161 /* HACK: shell32 doesn't give the correct params to CPL_STARTWPARMSW so we need to ... improvise */
162 if (wcsncmp(pszCommandLine, L"/file:", 6) == 0)
163 {
164 LPCWSTR pwszType = wcsrchr(pszCommandLine, L'.');
165 if (pwszType && wcsicmp(pwszType, L".msstyles") == 0)
166 {
167 pwszFile = &pszCommandLine[6];
168 pwszSelectedTab = L"Appearance";
169 pwszAction = L"OpenMSTheme";
170 }
171 }
172 }
173
174 g_GlobalData.pwszFile = pwszFile;
175 g_GlobalData.pwszAction = pwszAction;
176 g_GlobalData.desktop_color = GetSysColor(COLOR_DESKTOP);
177
178 LoadString(hApplet, IDS_CPLNAME, Caption, sizeof(Caption) / sizeof(TCHAR));
179
180 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
181 psh.dwSize = sizeof(PROPSHEETHEADER);
182 psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
183 psh.hwndParent = hCPLWindow;
184 psh.hInstance = hApplet;
185 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_DESK_ICON));
186 psh.pszCaption = Caption;
187 psh.nPages = 0;
188 psh.nStartPage = 0;
189 psh.phpage = hpsp;
190
191 /* Allow shell extensions to replace the background page */
192 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Desk"), MAX_DESK_PAGES - psh.nPages);
193
194 for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
195 {
196 if (pwszSelectedTab && wcsicmp(pwszSelectedTab, PropPages[i].Name) == 0)
197 psh.nStartPage = i;
198
199 /* Override the background page if requested by a shell extension */
200 if (PropPages[i].idDlg == IDD_BACKGROUND && hpsxa != NULL &&
201 SHReplaceFromPropSheetExtArray(hpsxa, CPLPAGE_DISPLAY_BACKGROUND, PropSheetAddPage, (LPARAM)&psh) != 0)
202 {
203 /* The shell extension added one or more pages to replace the background page.
204 Don't create the built-in page anymore! */
205 continue;
206 }
207
208 InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc, PropPages[i].Callback);
209 }
210
211 /* NOTE: Don't call SHAddFromPropSheetExtArray here because this applet only allows
212 replacing the background page but not extending the applet by more pages */
213
214 ret = (LONG)(PropertySheet(&psh) != -1);
215
216 if (hpsxa != NULL)
217 SHDestroyPropSheetExtArray(hpsxa);
218
219 if (argv)
220 LocalFree(argv);
221
222 return TRUE;
223 }
224
225
226 /* Control Panel Callback */
227 LONG CALLBACK
228 CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
229 {
230 int i = (int)lParam1;
231
232 switch (uMsg)
233 {
234 case CPL_INIT:
235 return TRUE;
236
237 case CPL_GETCOUNT:
238 return NUM_APPLETS;
239
240 case CPL_INQUIRE:
241 {
242 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
243 CPlInfo->lData = 0;
244 CPlInfo->idIcon = Applets[i].idIcon;
245 CPlInfo->idName = Applets[i].idName;
246 CPlInfo->idInfo = Applets[i].idDescription;
247 }
248 break;
249
250 case CPL_DBLCLK:
251 Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
252 break;
253 case CPL_STARTWPARMSW:
254 return Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
255 }
256
257 return FALSE;
258 }
259
260 void
261 WINAPI
262 InstallScreenSaverW(
263 IN HWND hWindow,
264 IN HANDLE hInstance,
265 IN LPCWSTR pszFile,
266 IN UINT nCmdShow)
267 {
268 WCHAR pszSystemDir[MAX_PATH];
269 WCHAR pszDrive[3];
270 WCHAR pszPath[MAX_PATH];
271 WCHAR pszFilename[MAX_PATH];
272 WCHAR pszExt[MAX_PATH];
273 LPWSTR pszOutName;
274 UINT uCompressionType=FILE_COMPRESSION_NONE;
275 DWORD dwSourceSize;
276 DWORD dwTargetSize;
277 DWORD rc;
278
279 if (!pszFile)
280 {
281 DPRINT("InstallScreenSaver() null file\n");
282 SetLastError(ERROR_INVALID_PARAMETER);
283 return;
284 }
285 DPRINT("InstallScreenSaver() Installing screensaver %ls\n", pszFile);
286
287 rc = SetupGetFileCompressionInfoW(pszFile, &pszOutName, &dwSourceSize, &dwTargetSize, &uCompressionType);
288 if (ERROR_SUCCESS != rc)
289 {
290 DPRINT("InstallScreenSaver() SetupGetFileCompressionInfo failed with error 0x%lx\n", rc);
291 SetLastError(rc);
292 return;
293 }
294 if (!GetSystemDirectoryW((LPWSTR)pszSystemDir, sizeof(pszSystemDir)/sizeof(WCHAR)))
295 {
296 MyFree(pszOutName);
297 DPRINT("InstallScreenSaver() GetSystemDirectory failed with error 0x%lx\n", GetLastError());
298 return;
299 }
300 _wsplitpath(pszOutName, pszDrive, pszPath, pszFilename, pszExt);
301 MyFree(pszOutName);
302 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), L"\\");
303 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszFilename);
304 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszExt);
305 rc = SetupDecompressOrCopyFileW(pszFile, pszSystemDir, &uCompressionType);
306 DPRINT("InstallScreenSaver() Copying to %ls, compression type %d return 0x%lx\n", pszFile, uCompressionType, rc);
307 }
308
309 void
310 WINAPI
311 InstallScreenSaverA(
312 IN HWND hWindow,
313 IN HANDLE hInstance,
314 IN LPCSTR pszFile,
315 IN UINT nCmdShow)
316 {
317 LPWSTR lpwString;
318
319 if (!pszFile)
320 {
321 DPRINT("InstallScreenSaver() null file\n");
322 SetLastError(ERROR_INVALID_PARAMETER);
323 return;
324 }
325 DPRINT("InstallScreenSaver() Install from file %s\n", pszFile);
326 lpwString = pSetupMultiByteToUnicode(pszFile, 0);
327 if (!lpwString)
328 {
329 DPRINT("InstallScreenSaver() not enough memory to convert string to unicode\n");
330 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
331 return;
332 }
333 InstallScreenSaverW(hWindow, hInstance, lpwString, nCmdShow);
334 MyFree(lpwString);
335 }
336
337 BOOL WINAPI
338 DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
339 {
340 UNREFERENCED_PARAMETER(lpvReserved);
341
342 switch (dwReason)
343 {
344 case DLL_PROCESS_ATTACH:
345 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
346 RegisterPreviewControl(hInstDLL);
347 // case DLL_THREAD_ATTACH:
348 hApplet = hInstDLL;
349 break;
350
351 case DLL_PROCESS_DETACH:
352 UnregisterPreviewControl(hInstDLL);
353 CoUninitialize();
354 break;
355 }
356
357 return TRUE;
358 }