d2cd2d7caaa2c79a0f293def79933a9e4fd2a522
[reactos.git] / dll / cpl / console / console.c
1 /*
2 * PROJECT: ReactOS Console Configuration DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/console/console.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 #include "console.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 INT_PTR CALLBACK OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
16 INT_PTR CALLBACK FontProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
17 INT_PTR CALLBACK LayoutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
18 INT_PTR CALLBACK ColorsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
19
20 HINSTANCE hApplet = NULL;
21
22 /* Local copy of the console information */
23 PCONSOLE_STATE_INFO ConInfo = NULL;
24 /* What to do with the console information */
25 static BOOL SetConsoleInfo = FALSE;
26 static BOOL SaveConsoleInfo = FALSE;
27
28 static VOID
29 InitPropSheetPage(PROPSHEETPAGEW *psp,
30 WORD idDlg,
31 DLGPROC DlgProc)
32 {
33 ZeroMemory(psp, sizeof(*psp));
34 psp->dwSize = sizeof(*psp);
35 psp->dwFlags = PSP_DEFAULT;
36 psp->hInstance = hApplet;
37 psp->pszTemplate = MAKEINTRESOURCEW(idDlg);
38 psp->pfnDlgProc = DlgProc;
39 psp->lParam = 0;
40 }
41
42 static VOID
43 InitDefaultConsoleInfo(PCONSOLE_STATE_INFO pConInfo)
44 {
45 // FIXME: Also retrieve the value of REG_DWORD CurrentPage.
46 ConCfgGetDefaultSettings(pConInfo);
47 }
48
49 static INT_PTR
50 CALLBACK
51 ApplyProc(HWND hwndDlg,
52 UINT uMsg,
53 WPARAM wParam,
54 LPARAM lParam)
55 {
56 UNREFERENCED_PARAMETER(lParam);
57
58 switch (uMsg)
59 {
60 case WM_INITDIALOG:
61 {
62 CheckDlgButton(hwndDlg, IDC_RADIO_APPLY_CURRENT, BST_CHECKED);
63 return TRUE;
64 }
65 case WM_COMMAND:
66 {
67 if (LOWORD(wParam) == IDOK)
68 {
69 if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_APPLY_CURRENT) == BST_CHECKED)
70 EndDialog(hwndDlg, IDC_RADIO_APPLY_CURRENT);
71 else
72 EndDialog(hwndDlg, IDC_RADIO_APPLY_ALL);
73 }
74 else if (LOWORD(wParam) == IDCANCEL)
75 {
76 EndDialog(hwndDlg, IDCANCEL);
77 }
78 break;
79 }
80 default:
81 break;
82 }
83
84 return FALSE;
85 }
86
87 VOID
88 ApplyConsoleInfo(HWND hwndDlg)
89 {
90 static BOOL ConsoleInfoAlreadySaved = FALSE;
91
92 /*
93 * We already applied all the console properties (and saved if needed).
94 * Nothing more needs to be done.
95 */
96 if (ConsoleInfoAlreadySaved)
97 goto Done;
98
99 /*
100 * If we are setting the default parameters, just save them,
101 * otherwise display the confirmation & apply dialog.
102 */
103 if (ConInfo->hWnd == NULL)
104 {
105 SetConsoleInfo = FALSE;
106 SaveConsoleInfo = TRUE;
107 }
108 else
109 {
110 INT_PTR res = DialogBoxW(hApplet, MAKEINTRESOURCEW(IDD_APPLYOPTIONS), hwndDlg, ApplyProc);
111
112 SetConsoleInfo = (res != IDCANCEL);
113 SaveConsoleInfo = (res == IDC_RADIO_APPLY_ALL);
114
115 if (SetConsoleInfo == FALSE)
116 {
117 /* Don't destroy when the user presses cancel */
118 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
119 return;
120 }
121 }
122
123 /*
124 * We applied all the console properties (and saved if needed).
125 * Set the flag so that if this function is called again, we won't
126 * need to redo everything again.
127 */
128 ConsoleInfoAlreadySaved = TRUE;
129
130 Done:
131 /* Options have been applied */
132 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
133 return;
134 }
135
136 /* First Applet */
137 static LONG
138 APIENTRY
139 InitApplet(HANDLE hSectionOrWnd)
140 {
141 INT_PTR Result;
142 PCONSOLE_STATE_INFO pSharedInfo = NULL;
143 WCHAR szTitle[MAX_PATH + 1];
144 PROPSHEETPAGEW psp[4];
145 PROPSHEETHEADERW psh;
146 INT i = 0;
147
148 /*
149 * Because of Windows compatibility, we need to behave the same concerning
150 * information sharing with CONSRV. For some obscure reason the designers
151 * decided to use the CPlApplet hWnd parameter as being either a handle to
152 * the applet's parent caller's window (in case we ask for displaying
153 * the global console settings), or a handle to a shared section holding
154 * a CONSOLE_STATE_INFO structure (they don't use the extra l/wParams).
155 */
156
157 /*
158 * Try to open the shared section via the handle parameter. If we succeed,
159 * it means we were called by CONSRV for retrieving/setting parameters for
160 * a given console. If we fail, it means we are retrieving/setting default
161 * global parameters (and we were either called by CONSRV or directly by
162 * the user via the Control Panel, etc...)
163 */
164 pSharedInfo = MapViewOfFile(hSectionOrWnd, FILE_MAP_READ, 0, 0, 0);
165 if (pSharedInfo != NULL)
166 {
167 /*
168 * We succeeded. We were called by CONSRV and are retrieving
169 * parameters for a given console.
170 */
171
172 /* Copy the shared data into our allocated buffer */
173 DPRINT1("pSharedInfo->cbSize == %lu ; sizeof(CONSOLE_STATE_INFO) == %u\n",
174 pSharedInfo->cbSize, sizeof(CONSOLE_STATE_INFO));
175 ASSERT(pSharedInfo->cbSize >= sizeof(CONSOLE_STATE_INFO));
176
177 /* Allocate a local buffer to hold console information */
178 ConInfo = HeapAlloc(GetProcessHeap(),
179 HEAP_ZERO_MEMORY,
180 pSharedInfo->cbSize);
181 if (ConInfo)
182 RtlCopyMemory(ConInfo, pSharedInfo, pSharedInfo->cbSize);
183
184 /* Close the section */
185 UnmapViewOfFile(pSharedInfo);
186 CloseHandle(hSectionOrWnd);
187
188 if (!ConInfo) return 0;
189 }
190 else
191 {
192 /*
193 * We failed. We are retrieving the default global parameters.
194 */
195
196 /* Allocate a local buffer to hold console information */
197 ConInfo = HeapAlloc(GetProcessHeap(),
198 HEAP_ZERO_MEMORY,
199 sizeof(CONSOLE_STATE_INFO));
200 if (!ConInfo) return 0;
201
202 /*
203 * Setting the console window handle to NULL indicates we are
204 * retrieving/setting the default console parameters.
205 */
206 ConInfo->hWnd = NULL;
207 ConInfo->ConsoleTitle[0] = UNICODE_NULL;
208
209 /* Use defaults */
210 InitDefaultConsoleInfo(ConInfo);
211 }
212
213 /* Initialize the font support */
214 hCurrentFont = CreateConsoleFont(ConInfo);
215 if (hCurrentFont == NULL)
216 DPRINT1("InitApplet: CreateConsoleFont failed\n");
217
218 /* Initialize the property sheet structure */
219 ZeroMemory(&psh, sizeof(psh));
220 psh.dwSize = sizeof(psh);
221 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | /* PSH_USEHICON */ PSH_USEICONID | PSH_NOAPPLYNOW;
222
223 if (ConInfo->ConsoleTitle[0] != UNICODE_NULL)
224 {
225 wcsncpy(szTitle, L"\"", MAX_PATH);
226 wcsncat(szTitle, ConInfo->ConsoleTitle, MAX_PATH - wcslen(szTitle));
227 wcsncat(szTitle, L"\"", MAX_PATH - wcslen(szTitle));
228 }
229 else
230 {
231 wcscpy(szTitle, L"ReactOS Console");
232 }
233 psh.pszCaption = szTitle;
234
235 if (pSharedInfo != NULL)
236 {
237 /* We were started from a console window: this is our parent (or ConInfo->hWnd is NULL) */
238 psh.hwndParent = ConInfo->hWnd;
239 }
240 else
241 {
242 /* We were started in another way (--> default parameters). Caller's window is our parent. */
243 psh.hwndParent = (HWND)hSectionOrWnd;
244 }
245
246 psh.hInstance = hApplet;
247 // psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCEW(IDC_CPLICON));
248 psh.pszIcon = MAKEINTRESOURCEW(IDC_CPLICON);
249 psh.nPages = ARRAYSIZE(psp);
250 psh.nStartPage = 0;
251 psh.ppsp = psp;
252
253 InitPropSheetPage(&psp[i++], IDD_PROPPAGEOPTIONS, OptionsProc);
254 InitPropSheetPage(&psp[i++], IDD_PROPPAGEFONT , FontProc );
255 InitPropSheetPage(&psp[i++], IDD_PROPPAGELAYOUT , LayoutProc );
256 InitPropSheetPage(&psp[i++], IDD_PROPPAGECOLORS , ColorsProc );
257
258 /* Display the property sheet */
259 RegisterWinPrevClass(hApplet);
260 Result = PropertySheetW(&psh);
261 UnRegisterWinPrevClass(hApplet);
262
263 /* First cleanup */
264 if (hCurrentFont) DeleteObject(hCurrentFont);
265 hCurrentFont = NULL;
266
267 /* Save the console settings */
268 if (SetConsoleInfo)
269 {
270 HANDLE hSection;
271
272 /*
273 * Create a memory section to share with CONSRV, and map it.
274 */
275 hSection = CreateFileMappingW(INVALID_HANDLE_VALUE,
276 NULL,
277 PAGE_READWRITE,
278 0,
279 ConInfo->cbSize,
280 NULL);
281 if (!hSection)
282 {
283 DPRINT1("Error when creating file mapping, error = %d\n", GetLastError());
284 goto Quit;
285 }
286
287 pSharedInfo = MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS, 0, 0, 0);
288 if (!pSharedInfo)
289 {
290 DPRINT1("Error when mapping view of file, error = %d\n", GetLastError());
291 CloseHandle(hSection);
292 goto Quit;
293 }
294
295 /* Copy the console information into the section */
296 RtlCopyMemory(pSharedInfo, ConInfo, ConInfo->cbSize);
297
298 /* Unmap it */
299 UnmapViewOfFile(pSharedInfo);
300
301 /* Signal to CONSRV that it can apply the new configuration */
302 SendMessageW(ConInfo->hWnd, WM_SETCONSOLEINFO, (WPARAM)hSection, 0);
303
304 /* Close the section and return */
305 CloseHandle(hSection);
306 }
307
308 if (SaveConsoleInfo)
309 {
310 /* Default settings saved when ConInfo->hWnd == NULL */
311 ConCfgWriteUserSettings(ConInfo, ConInfo->hWnd == NULL);
312 }
313
314 Quit:
315 /* Cleanup */
316 HeapFree(GetProcessHeap(), 0, ConInfo);
317 ConInfo = NULL;
318
319 return (Result != -1);
320 }
321
322 /* Control Panel Callback */
323 LONG
324 CALLBACK
325 CPlApplet(HWND hwndCPl,
326 UINT uMsg,
327 LPARAM lParam1,
328 LPARAM lParam2)
329 {
330 switch (uMsg)
331 {
332 case CPL_INIT:
333 return TRUE;
334
335 case CPL_EXIT:
336 // TODO: Free allocated memory
337 break;
338
339 case CPL_GETCOUNT:
340 return 1;
341
342 case CPL_INQUIRE:
343 {
344 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
345 CPlInfo->idIcon = IDC_CPLICON;
346 CPlInfo->idName = IDS_CPLNAME;
347 CPlInfo->idInfo = IDS_CPLDESCRIPTION;
348 break;
349 }
350
351 case CPL_DBLCLK:
352 InitApplet((HANDLE)hwndCPl);
353 break;
354 }
355
356 return FALSE;
357 }
358
359 INT
360 WINAPI
361 DllMain(HINSTANCE hinstDLL,
362 DWORD dwReason,
363 LPVOID lpvReserved)
364 {
365 UNREFERENCED_PARAMETER(lpvReserved);
366
367 switch (dwReason)
368 {
369 case DLL_PROCESS_ATTACH:
370 hApplet = hinstDLL;
371 DisableThreadLibraryCalls(hinstDLL);
372 break;
373 }
374
375 return TRUE;
376 }