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
InitPropSheetPage(PROPSHEETPAGEW * psp,WORD idDlg,DLGPROC DlgProc)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
InitDefaultConsoleInfo(PCONSOLE_STATE_INFO pConInfo)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
ApplyProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
ApplyConsoleInfo(HWND hwndDlg)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)
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 static int CALLBACK
PropSheetProc(HWND hwndDlg,UINT uMsg,LPARAM lParam)137 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
138 {
139 // NOTE: This callback is needed to set large icon correctly.
140 HICON hIcon;
141 switch (uMsg)
142 {
143 case PSCB_INITIALIZED:
144 {
145 hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_CPLICON));
146 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
147 break;
148 }
149 }
150 return 0;
151 }
152
153 /* First Applet */
154 static LONG
155 APIENTRY
InitApplet(HANDLE hSectionOrWnd)156 InitApplet(HANDLE hSectionOrWnd)
157 {
158 INT_PTR Result;
159 PCONSOLE_STATE_INFO pSharedInfo = NULL;
160 WCHAR szTitle[MAX_PATH + 1];
161 PROPSHEETPAGEW psp[4];
162 PROPSHEETHEADERW psh;
163 INT i = 0;
164
165 /*
166 * Because of Windows compatibility, we need to behave the same concerning
167 * information sharing with CONSRV. For some obscure reason the designers
168 * decided to use the CPlApplet hWnd parameter as being either a handle to
169 * the applet's parent caller's window (in case we ask for displaying
170 * the global console settings), or a handle to a shared section holding
171 * a CONSOLE_STATE_INFO structure (they don't use the extra l/wParams).
172 */
173
174 /*
175 * Try to open the shared section via the handle parameter. If we succeed,
176 * it means we were called by CONSRV for retrieving/setting parameters for
177 * a given console. If we fail, it means we are retrieving/setting default
178 * global parameters (and we were either called by CONSRV or directly by
179 * the user via the Control Panel, etc...)
180 */
181 pSharedInfo = MapViewOfFile(hSectionOrWnd, FILE_MAP_READ, 0, 0, 0);
182 if (pSharedInfo != NULL)
183 {
184 /*
185 * We succeeded. We were called by CONSRV and are retrieving
186 * parameters for a given console.
187 */
188
189 /* Copy the shared data into our allocated buffer */
190 DPRINT1("pSharedInfo->cbSize == %lu ; sizeof(CONSOLE_STATE_INFO) == %u\n",
191 pSharedInfo->cbSize, sizeof(CONSOLE_STATE_INFO));
192 ASSERT(pSharedInfo->cbSize >= sizeof(CONSOLE_STATE_INFO));
193
194 /* Allocate a local buffer to hold console information */
195 ConInfo = HeapAlloc(GetProcessHeap(),
196 HEAP_ZERO_MEMORY,
197 pSharedInfo->cbSize);
198 if (ConInfo)
199 RtlCopyMemory(ConInfo, pSharedInfo, pSharedInfo->cbSize);
200
201 /* Close the section */
202 UnmapViewOfFile(pSharedInfo);
203 CloseHandle(hSectionOrWnd);
204
205 if (!ConInfo) return 0;
206 }
207 else
208 {
209 /*
210 * We failed. We are retrieving the default global parameters.
211 */
212
213 /* Allocate a local buffer to hold console information */
214 ConInfo = HeapAlloc(GetProcessHeap(),
215 HEAP_ZERO_MEMORY,
216 sizeof(CONSOLE_STATE_INFO));
217 if (!ConInfo) return 0;
218
219 /*
220 * Setting the console window handle to NULL indicates we are
221 * retrieving/setting the default console parameters.
222 */
223 ConInfo->hWnd = NULL;
224 ConInfo->ConsoleTitle[0] = UNICODE_NULL;
225
226 /* Use defaults */
227 InitDefaultConsoleInfo(ConInfo);
228 }
229
230 /* Initialize the font support -- additional TrueType font cache and current preview font */
231 InitTTFontCache();
232 RefreshFontPreview(&FontPreview, ConInfo);
233
234 /* Initialize the property sheet structure */
235 ZeroMemory(&psh, sizeof(psh));
236 psh.dwSize = sizeof(psh);
237 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | /* PSH_USEHICON | */ PSH_USEICONID | PSH_NOAPPLYNOW | PSH_USECALLBACK;
238
239 if (ConInfo->ConsoleTitle[0] != UNICODE_NULL)
240 {
241 StringCchPrintfW(szTitle, ARRAYSIZE(szTitle), L"\"%s\"", ConInfo->ConsoleTitle);
242 psh.pszCaption = szTitle;
243 }
244 else
245 {
246 psh.pszCaption = MAKEINTRESOURCEW(IDS_CPLNAME);
247 }
248
249 if (pSharedInfo != NULL)
250 {
251 /* We were started from a console window: this is our parent (or ConInfo->hWnd is NULL) */
252 psh.hwndParent = ConInfo->hWnd;
253 }
254 else
255 {
256 /* We were started in another way (--> default parameters). Caller's window is our parent. */
257 psh.hwndParent = (HWND)hSectionOrWnd;
258 }
259
260 psh.hInstance = hApplet;
261 // psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCEW(IDC_CPLICON));
262 psh.pszIcon = MAKEINTRESOURCEW(IDC_CPLICON);
263 psh.nPages = ARRAYSIZE(psp);
264 psh.nStartPage = 0;
265 psh.ppsp = psp;
266 psh.pfnCallback = PropSheetProc;
267
268 InitPropSheetPage(&psp[i++], IDD_PROPPAGEOPTIONS, OptionsProc);
269 InitPropSheetPage(&psp[i++], IDD_PROPPAGEFONT , FontProc );
270 InitPropSheetPage(&psp[i++], IDD_PROPPAGELAYOUT , LayoutProc );
271 InitPropSheetPage(&psp[i++], IDD_PROPPAGECOLORS , ColorsProc );
272
273 /* Display the property sheet */
274 RegisterWinPrevClass(hApplet);
275 Result = PropertySheetW(&psh);
276 UnRegisterWinPrevClass(hApplet);
277
278 /* Clear the font support */
279 ResetFontPreview(&FontPreview);
280 ClearTTFontCache();
281
282 /* Apply the console settings if necessary */
283 if (SetConsoleInfo)
284 {
285 HANDLE hSection;
286
287 /*
288 * Create a memory section to share with CONSRV, and map it.
289 */
290 hSection = CreateFileMappingW(INVALID_HANDLE_VALUE,
291 NULL,
292 PAGE_READWRITE,
293 0,
294 ConInfo->cbSize,
295 NULL);
296 if (!hSection)
297 {
298 DPRINT1("Error when creating file mapping, error = %d\n", GetLastError());
299 goto Quit;
300 }
301
302 pSharedInfo = MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS, 0, 0, 0);
303 if (!pSharedInfo)
304 {
305 DPRINT1("Error when mapping view of file, error = %d\n", GetLastError());
306 CloseHandle(hSection);
307 goto Quit;
308 }
309
310 /* Copy the console information into the section and unmap it */
311 RtlCopyMemory(pSharedInfo, ConInfo, ConInfo->cbSize);
312 UnmapViewOfFile(pSharedInfo);
313
314 /*
315 * Signal to CONSRV that it can apply the new settings.
316 *
317 * NOTE: SetConsoleInfo set to TRUE by ApplyConsoleInfo()
318 * *only* when ConInfo->hWnd != NULL and the user did not
319 * press IDCANCEL in the confirmation dialog.
320 */
321 ASSERT(ConInfo->hWnd);
322 SendMessageW(ConInfo->hWnd, WM_SETCONSOLEINFO, (WPARAM)hSection, 0);
323
324 /* Close the section and return */
325 CloseHandle(hSection);
326 }
327
328 /* Save the console settings */
329 if (SaveConsoleInfo)
330 {
331 /* Default settings saved when ConInfo->hWnd == NULL */
332 ConCfgWriteUserSettings(ConInfo, ConInfo->hWnd == NULL);
333 }
334
335 Quit:
336 /* Cleanup */
337 HeapFree(GetProcessHeap(), 0, ConInfo);
338 ConInfo = NULL;
339
340 return (Result != -1);
341 }
342
343 /* Control Panel Callback */
344 LONG
345 CALLBACK
CPlApplet(HWND hwndCPl,UINT uMsg,LPARAM lParam1,LPARAM lParam2)346 CPlApplet(HWND hwndCPl,
347 UINT uMsg,
348 LPARAM lParam1,
349 LPARAM lParam2)
350 {
351 switch (uMsg)
352 {
353 case CPL_INIT:
354 return TRUE;
355
356 case CPL_EXIT:
357 // TODO: Free allocated memory
358 break;
359
360 case CPL_GETCOUNT:
361 return 1;
362
363 case CPL_INQUIRE:
364 {
365 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
366 CPlInfo->idIcon = IDC_CPLICON;
367 CPlInfo->idName = IDS_CPLNAME;
368 CPlInfo->idInfo = IDS_CPLDESCRIPTION;
369 break;
370 }
371
372 case CPL_DBLCLK:
373 InitApplet((HANDLE)hwndCPl);
374 break;
375 }
376
377 return FALSE;
378 }
379
380 INT
381 WINAPI
DllMain(HINSTANCE hinstDLL,DWORD dwReason,LPVOID lpvReserved)382 DllMain(HINSTANCE hinstDLL,
383 DWORD dwReason,
384 LPVOID lpvReserved)
385 {
386 UNREFERENCED_PARAMETER(lpvReserved);
387
388 switch (dwReason)
389 {
390 case DLL_PROCESS_ATTACH:
391 hApplet = hinstDLL;
392 DisableThreadLibraryCalls(hinstDLL);
393 break;
394 }
395
396 return TRUE;
397 }
398