Merge the following revisions from kernel-fun branch:
[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
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 } PropPages[] =
113 {
114 { IDD_BACKGROUND, BackgroundPageProc, NULL },
115 { IDD_SCREENSAVER, ScreenSaverPageProc, NULL },
116 { IDD_APPEARANCE, AppearancePageProc, NULL },
117 { IDD_SETTINGS, SettingsPageProc, SettingsPageCallbackProc },
118 };
119
120 /* Display Applet */
121 static LONG APIENTRY
122 DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
123 {
124 HPROPSHEETPAGE hpsp[MAX_DESK_PAGES];
125 PROPSHEETHEADER psh;
126 HPSXA hpsxa;
127 TCHAR Caption[1024];
128 LONG ret;
129 UINT i;
130
131 UNREFERENCED_PARAMETER(lParam);
132 UNREFERENCED_PARAMETER(wParam);
133 UNREFERENCED_PARAMETER(uMsg);
134 UNREFERENCED_PARAMETER(hwnd);
135
136 g_GlobalData.desktop_color = GetSysColor(COLOR_DESKTOP);
137
138 LoadString(hApplet, IDS_CPLNAME, Caption, sizeof(Caption) / sizeof(TCHAR));
139
140 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
141 psh.dwSize = sizeof(PROPSHEETHEADER);
142 psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
143 psh.hwndParent = hCPLWindow;
144 psh.hInstance = hApplet;
145 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_DESK_ICON));
146 psh.pszCaption = Caption;
147 psh.nPages = 0;
148 psh.nStartPage = 0;
149 psh.phpage = hpsp;
150
151 /* Allow shell extensions to replace the background page */
152 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Desk"), MAX_DESK_PAGES - psh.nPages);
153
154 for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
155 {
156 /* Override the background page if requested by a shell extension */
157 if (PropPages[i].idDlg == IDD_BACKGROUND && hpsxa != NULL &&
158 SHReplaceFromPropSheetExtArray(hpsxa, CPLPAGE_DISPLAY_BACKGROUND, PropSheetAddPage, (LPARAM)&psh) != 0)
159 {
160 /* The shell extension added one or more pages to replace the background page.
161 Don't create the built-in page anymore! */
162 continue;
163 }
164
165 InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc, PropPages[i].Callback);
166 }
167
168 /* NOTE: Don't call SHAddFromPropSheetExtArray here because this applet only allows
169 replacing the background page but not extending the applet by more pages */
170
171 ret = (LONG)(PropertySheet(&psh) != -1);
172
173 if (hpsxa != NULL)
174 SHDestroyPropSheetExtArray(hpsxa);
175
176 return ret;
177 }
178
179
180 /* Control Panel Callback */
181 LONG CALLBACK
182 CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
183 {
184 int i = (int)lParam1;
185
186 switch (uMsg)
187 {
188 case CPL_INIT:
189 return TRUE;
190
191 case CPL_GETCOUNT:
192 return NUM_APPLETS;
193
194 case CPL_INQUIRE:
195 {
196 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
197 CPlInfo->lData = 0;
198 CPlInfo->idIcon = Applets[i].idIcon;
199 CPlInfo->idName = Applets[i].idName;
200 CPlInfo->idInfo = Applets[i].idDescription;
201 }
202 break;
203
204 case CPL_DBLCLK:
205 hCPLWindow = hwndCPl;
206 Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
207 break;
208 }
209
210 return FALSE;
211 }
212
213 void
214 WINAPI
215 InstallScreenSaverW(
216 IN HWND hWindow,
217 IN HANDLE hInstance,
218 IN LPCWSTR pszFile,
219 IN UINT nCmdShow)
220 {
221 WCHAR pszSystemDir[MAX_PATH];
222 WCHAR pszDrive[2];
223 WCHAR pszPath[MAX_PATH];
224 WCHAR pszFilename[MAX_PATH];
225 WCHAR pszExt[MAX_PATH];
226 LPWSTR pszOutName;
227 UINT uCompressionType=FILE_COMPRESSION_NONE;
228 DWORD dwSourceSize;
229 DWORD dwTargetSize;
230 DWORD rc;
231
232 if (!pszFile)
233 {
234 DPRINT("InstallScreenSaver() null file\n");
235 SetLastError(ERROR_INVALID_PARAMETER);
236 return;
237 }
238 DPRINT("InstallScreenSaver() Installing screensaver %ls\n", pszFile);
239
240 rc = SetupGetFileCompressionInfoW(pszFile, &pszOutName, &dwSourceSize, &dwTargetSize, &uCompressionType);
241 if (ERROR_SUCCESS != rc)
242 {
243 DPRINT("InstallScreenSaver() SetupGetFileCompressionInfo failed with error 0x%lx\n", rc);
244 SetLastError(rc);
245 return;
246 }
247 if (!GetSystemDirectoryW((LPWSTR)pszSystemDir, sizeof(pszSystemDir)/sizeof(WCHAR)))
248 {
249 MyFree(pszOutName);
250 DPRINT("InstallScreenSaver() GetSystemDirectory failed with error 0x%lx\n", GetLastError());
251 return;
252 }
253 _wsplitpath(pszOutName, pszDrive, pszPath, pszFilename, pszExt);
254 MyFree(pszOutName);
255 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), L"\\");
256 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszFilename);
257 StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszExt);
258 rc = SetupDecompressOrCopyFileW(pszFile, pszSystemDir, &uCompressionType);
259 DPRINT("InstallScreenSaver() Copying to %ls, compression type %d return 0x%lx\n", pszFile, uCompressionType, rc);
260 }
261
262 void
263 WINAPI
264 InstallScreenSaverA(
265 IN HWND hWindow,
266 IN HANDLE hInstance,
267 IN LPCSTR pszFile,
268 IN UINT nCmdShow)
269 {
270 LPWSTR lpwString;
271
272 if (!pszFile)
273 {
274 DPRINT("InstallScreenSaver() null file\n");
275 SetLastError(ERROR_INVALID_PARAMETER);
276 return;
277 }
278 DPRINT("InstallScreenSaver() Install from file %s\n", pszFile);
279 lpwString = pSetupMultiByteToUnicode(pszFile, 0);
280 if (!lpwString)
281 {
282 DPRINT("InstallScreenSaver() not enough memory to convert string to unicode\n");
283 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
284 return;
285 }
286 InstallScreenSaverW(hWindow, hInstance, lpwString, nCmdShow);
287 MyFree(lpwString);
288 }
289
290 BOOL WINAPI
291 DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
292 {
293 UNREFERENCED_PARAMETER(lpvReserved);
294
295 switch (dwReason)
296 {
297 case DLL_PROCESS_ATTACH:
298 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
299 RegisterPreviewControl(hInstDLL);
300 // case DLL_THREAD_ATTACH:
301 hApplet = hInstDLL;
302 break;
303
304 case DLL_PROCESS_DETACH:
305 UnregisterPreviewControl(hInstDLL);
306 CoUninitialize();
307 break;
308 }
309
310 return TRUE;
311 }