[CONSOLE.DLL-CONSRV]
[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/win32/console/console.c
5 * PURPOSE: initialization of DLL
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@student.tugraz.at)
7 */
8
9 #include "console.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 #define NUM_APPLETS 1
15
16 LONG APIENTRY InitApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam);
17 INT_PTR CALLBACK OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
18 INT_PTR CALLBACK FontProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
19 INT_PTR CALLBACK LayoutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
20 INT_PTR CALLBACK ColorsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
21
22 HINSTANCE hApplet = 0;
23
24 /* Applets */
25 APPLET Applets[NUM_APPLETS] =
26 {
27 {IDC_CPLICON, IDS_CPLNAME, IDS_CPLDESCRIPTION, InitApplet}
28 };
29
30 /*
31 * Default 16-color palette for foreground and background
32 * (corresponding flags in comments).
33 */
34 const COLORREF s_Colors[16] =
35 {
36 RGB(0, 0, 0), // (Black)
37 RGB(0, 0, 128), // BLUE
38 RGB(0, 128, 0), // GREEN
39 RGB(0, 128, 128), // BLUE | GREEN
40 RGB(128, 0, 0), // RED
41 RGB(128, 0, 128), // BLUE | RED
42 RGB(128, 128, 0), // GREEN | RED
43 RGB(192, 192, 192), // BLUE | GREEN | RED
44
45 RGB(128, 128, 128), // (Grey) INTENSITY
46 RGB(0, 0, 255), // BLUE | INTENSITY
47 RGB(0, 255, 0), // GREEN | INTENSITY
48 RGB(0, 255, 255), // BLUE | GREEN | INTENSITY
49 RGB(255, 0, 0), // RED | INTENSITY
50 RGB(255, 0, 255), // BLUE | RED | INTENSITY
51 RGB(255, 255, 0), // GREEN | RED | INTENSITY
52 RGB(255, 255, 255) // BLUE | GREEN | RED | INTENSITY
53 };
54 /* Default attributes */
55 #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
56 #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \
57 BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
58 /* Cursor size */
59 #define CSR_DEFAULT_CURSOR_SIZE 25
60
61 static VOID
62 InitPropSheetPage(PROPSHEETPAGE *psp,
63 WORD idDlg,
64 DLGPROC DlgProc,
65 LPARAM lParam)
66 {
67 ZeroMemory(psp, sizeof(PROPSHEETPAGE));
68 psp->dwSize = sizeof(PROPSHEETPAGE);
69 psp->dwFlags = PSP_DEFAULT;
70 psp->hInstance = hApplet;
71 psp->pszTemplate = MAKEINTRESOURCE(idDlg);
72 psp->pfnDlgProc = DlgProc;
73 psp->lParam = lParam;
74 }
75
76 PCONSOLE_PROPS
77 AllocConsoleInfo()
78 {
79 /* Adapted for holding GUI terminal information */
80 return HeapAlloc(GetProcessHeap(),
81 HEAP_ZERO_MEMORY,
82 sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
83 }
84
85 VOID
86 InitConsoleDefaults(PCONSOLE_PROPS pConInfo)
87 {
88 PGUI_CONSOLE_INFO GuiInfo = NULL;
89
90 /* Initialize the default properties */
91 pConInfo->ci.HistoryBufferSize = 50;
92 pConInfo->ci.NumberOfHistoryBuffers = 4;
93 pConInfo->ci.HistoryNoDup = FALSE;
94 pConInfo->ci.FullScreen = FALSE;
95 pConInfo->ci.QuickEdit = FALSE;
96 pConInfo->ci.InsertMode = TRUE;
97 // pConInfo->ci.InputBufferSize;
98 pConInfo->ci.ScreenBufferSize = (COORD){80, 300};
99 pConInfo->ci.ConsoleSize = (COORD){80, 25 };
100 pConInfo->ci.CursorBlinkOn = TRUE;
101 pConInfo->ci.ForceCursorOff = FALSE;
102 pConInfo->ci.CursorSize = CSR_DEFAULT_CURSOR_SIZE;
103 pConInfo->ci.ScreenAttrib = DEFAULT_SCREEN_ATTRIB;
104 pConInfo->ci.PopupAttrib = DEFAULT_POPUP_ATTRIB;
105 pConInfo->ci.CodePage = 0;
106 pConInfo->ci.ConsoleTitle[0] = L'\0';
107
108 /* Adapted for holding GUI terminal information */
109 pConInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
110 GuiInfo = pConInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pConInfo + 1);
111 GuiInfo->FaceName[0] = L'\0';
112 GuiInfo->FontFamily = FF_DONTCARE;
113 GuiInfo->FontSize = 0;
114 GuiInfo->FontWeight = FW_DONTCARE;
115 GuiInfo->UseRasterFonts = TRUE;
116
117 GuiInfo->AutoPosition = TRUE;
118 GuiInfo->WindowOrigin = (POINT){0, 0};
119
120 memcpy(pConInfo->ci.Colors, s_Colors, sizeof(s_Colors));
121 }
122
123 INT_PTR
124 CALLBACK
125 ApplyProc(HWND hwndDlg,
126 UINT uMsg,
127 WPARAM wParam,
128 LPARAM lParam)
129 {
130 HWND hDlgCtrl;
131
132 UNREFERENCED_PARAMETER(lParam);
133
134 switch (uMsg)
135 {
136 case WM_INITDIALOG:
137 {
138 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_APPLY_CURRENT);
139 SendMessage(hDlgCtrl, BM_SETCHECK, BST_CHECKED, 0);
140 return TRUE;
141 }
142 case WM_COMMAND:
143 {
144 if (LOWORD(wParam) == IDOK)
145 {
146 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_APPLY_CURRENT);
147 if (SendMessage(hDlgCtrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
148 EndDialog(hwndDlg, IDC_RADIO_APPLY_CURRENT);
149 else
150 EndDialog(hwndDlg, IDC_RADIO_APPLY_ALL);
151 }
152 else if (LOWORD(wParam) == IDCANCEL)
153 {
154 EndDialog(hwndDlg, IDCANCEL);
155 }
156 break;
157 }
158 default:
159 break;
160 }
161
162 return FALSE;
163 }
164
165 BOOL
166 ApplyConsoleInfo(HWND hwndDlg,
167 PCONSOLE_PROPS pConInfo)
168 {
169 INT_PTR res = 0;
170
171 res = DialogBox(hApplet, MAKEINTRESOURCE(IDD_APPLYOPTIONS), hwndDlg, ApplyProc);
172 if (res == IDCANCEL)
173 {
174 /* Don't destroy when user presses cancel */
175 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
176 return TRUE;
177 }
178 else if (res == IDC_RADIO_APPLY_ALL || res == IDC_RADIO_APPLY_CURRENT)
179 {
180 HANDLE hSection;
181 PCONSOLE_PROPS pSharedInfo;
182
183 /*
184 * Create a memory section to share with the server, and map it.
185 */
186 /* Holds data for console.dll + console info + terminal-specific info */
187 hSection = CreateFileMapping(INVALID_HANDLE_VALUE,
188 NULL,
189 PAGE_READWRITE,
190 0,
191 sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO),
192 NULL);
193 if (!hSection)
194 {
195 DPRINT1("Error when creating file mapping, error = %d\n", GetLastError());
196 return FALSE;
197 }
198
199 pSharedInfo = MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS, 0, 0, 0);
200 if (!pSharedInfo)
201 {
202 DPRINT1("Error when mapping view of file, error = %d\n", GetLastError());
203 CloseHandle(hSection);
204 return FALSE;
205 }
206
207 /* We are applying the chosen configuration */
208 pConInfo->AppliedConfig = TRUE;
209
210 /* Copy the console info into the section */
211 RtlCopyMemory(pSharedInfo, pConInfo, sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
212 /* Offsetize */
213 pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pSharedInfo->TerminalInfo.TermInfo - (ULONG_PTR)pSharedInfo);
214
215 /* Unmap it */
216 UnmapViewOfFile(pSharedInfo);
217
218 /* Signal to the console server that it can apply the new configuration */
219 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
220 SendMessage(pConInfo->hConsoleWindow,
221 PM_APPLY_CONSOLE_INFO,
222 (WPARAM)hSection,
223 (LPARAM)(res == IDC_RADIO_APPLY_ALL));
224
225 /* Close the section and return */
226 CloseHandle(hSection);
227 return TRUE;
228 }
229
230 return TRUE;
231 }
232
233 /* First Applet */
234 LONG APIENTRY
235 InitApplet(HWND hWnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
236 {
237 HANDLE hSection = (HANDLE)wParam;
238 BOOL GuiTermInfo = FALSE;
239 PCONSOLE_PROPS pSharedInfo;
240 PCONSOLE_PROPS pConInfo;
241 WCHAR szTitle[MAX_PATH + 1];
242 PROPSHEETPAGE psp[4];
243 PROPSHEETHEADER psh;
244 INT i = 0;
245
246 UNREFERENCED_PARAMETER(uMsg);
247
248 /*
249 * CONSOLE.DLL shares information with CONSRV with wParam:
250 * wParam is a handle to a shared section holding a CONSOLE_PROPS struct.
251 *
252 * NOTE: lParam is not used.
253 */
254
255 /* Allocate a local buffer to hold console information */
256 pConInfo = AllocConsoleInfo();
257 if (!pConInfo) return 0;
258
259 /* Map the shared section */
260 pSharedInfo = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
261 if (pSharedInfo == NULL)
262 {
263 HeapFree(GetProcessHeap(), 0, pConInfo);
264 return 0;
265 }
266
267 // if (IsBadReadPtr((PVOID)pSharedInfo, sizeof(CONSOLE_PROPS)))
268 // {
269 // }
270
271 /* Find the console window and whether we must use default parameters */
272 pConInfo->hConsoleWindow = pSharedInfo->hConsoleWindow;
273 pConInfo->ShowDefaultParams = pSharedInfo->ShowDefaultParams;
274
275 /* Check that we are going to modify GUI terminal information */
276 GuiTermInfo = ( pSharedInfo->TerminalInfo.Size == sizeof(GUI_CONSOLE_INFO) &&
277 pSharedInfo->TerminalInfo.TermInfo != 0 );
278
279 if (pConInfo->ShowDefaultParams || !GuiTermInfo)
280 {
281 /* Use defaults */
282 InitConsoleDefaults(pConInfo);
283 }
284 else
285 {
286 /*
287 * Copy the shared data into our allocated buffer, and
288 * de-offsetize the address of terminal-specific information.
289 */
290 RtlCopyMemory(pConInfo, pSharedInfo, sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
291 pConInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)pConInfo->TerminalInfo.TermInfo);
292 }
293
294 /* Close the section */
295 UnmapViewOfFile(pSharedInfo);
296 CloseHandle(hSection);
297
298 /* Initialize the property sheet structure */
299 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
300 psh.dwSize = sizeof(PROPSHEETHEADER);
301 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | /* PSH_USEHICON */ PSH_USEICONID | PSH_NOAPPLYNOW;
302
303 if (pConInfo->ci.ConsoleTitle[0] != L'\0')
304 {
305 wcsncpy(szTitle, L"\"", sizeof(szTitle) / sizeof(szTitle[0]));
306 wcsncat(szTitle, pConInfo->ci.ConsoleTitle, sizeof(szTitle) / sizeof(szTitle[0]));
307 wcsncat(szTitle, L"\"", sizeof(szTitle) / sizeof(szTitle[0]));
308 }
309 else
310 {
311 wcscpy(szTitle, L"ReactOS Console");
312 }
313 psh.pszCaption = szTitle;
314
315 psh.hwndParent = pConInfo->hConsoleWindow;
316 psh.hInstance = hApplet;
317 // psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON));
318 psh.pszIcon = MAKEINTRESOURCE(IDC_CPLICON);
319 psh.nPages = 4;
320 psh.nStartPage = 0;
321 psh.ppsp = psp;
322
323 InitPropSheetPage(&psp[i++], IDD_PROPPAGEOPTIONS, (DLGPROC) OptionsProc, (LPARAM)pConInfo);
324 InitPropSheetPage(&psp[i++], IDD_PROPPAGEFONT, (DLGPROC) FontProc, (LPARAM)pConInfo);
325 InitPropSheetPage(&psp[i++], IDD_PROPPAGELAYOUT, (DLGPROC) LayoutProc, (LPARAM)pConInfo);
326 InitPropSheetPage(&psp[i++], IDD_PROPPAGECOLORS, (DLGPROC) ColorsProc, (LPARAM)pConInfo);
327
328 return (PropertySheet(&psh) != -1);
329 }
330
331 /* Control Panel Callback */
332 LONG CALLBACK
333 CPlApplet(HWND hwndCPl,
334 UINT uMsg,
335 LPARAM lParam1,
336 LPARAM lParam2)
337 {
338 switch (uMsg)
339 {
340 case CPL_INIT:
341 return TRUE;
342
343 case CPL_EXIT:
344 // TODO: Free allocated memory
345 break;
346
347 case CPL_GETCOUNT:
348 return NUM_APPLETS;
349
350 case CPL_INQUIRE:
351 {
352 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
353 CPlInfo->idIcon = Applets[0].idIcon;
354 CPlInfo->idName = Applets[0].idName;
355 CPlInfo->idInfo = Applets[0].idDescription;
356 break;
357 }
358
359 case CPL_DBLCLK:
360 InitApplet(hwndCPl, uMsg, lParam1, lParam2);
361 break;
362 }
363
364 return FALSE;
365 }
366
367
368 INT
369 WINAPI
370 DllMain(HINSTANCE hinstDLL,
371 DWORD dwReason,
372 LPVOID lpvReserved)
373 {
374 UNREFERENCED_PARAMETER(lpvReserved);
375
376 switch (dwReason)
377 {
378 case DLL_PROCESS_ATTACH:
379 case DLL_THREAD_ATTACH:
380 hApplet = hinstDLL;
381 break;
382 }
383
384 return TRUE;
385 }