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 static int CALLBACK 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 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 */ 231 FontPreview.hFont = CreateConsoleFont(ConInfo); 232 if (FontPreview.hFont == NULL) 233 DPRINT1("InitApplet: CreateConsoleFont() failed\n"); 234 GetFontCellSize(NULL, FontPreview.hFont, &FontPreview.CharHeight, &FontPreview.CharWidth); 235 236 /* Initialize the property sheet structure */ 237 ZeroMemory(&psh, sizeof(psh)); 238 psh.dwSize = sizeof(psh); 239 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | /* PSH_USEHICON | */ PSH_USEICONID | PSH_NOAPPLYNOW | PSH_USECALLBACK; 240 241 if (ConInfo->ConsoleTitle[0] != UNICODE_NULL) 242 StringCchPrintfW(szTitle, ARRAYSIZE(szTitle), L"\"%s\"", ConInfo->ConsoleTitle); 243 else 244 StringCchCopyW(szTitle, ARRAYSIZE(szTitle), L"ReactOS Console"); 245 psh.pszCaption = szTitle; 246 247 if (pSharedInfo != NULL) 248 { 249 /* We were started from a console window: this is our parent (or ConInfo->hWnd is NULL) */ 250 psh.hwndParent = ConInfo->hWnd; 251 } 252 else 253 { 254 /* We were started in another way (--> default parameters). Caller's window is our parent. */ 255 psh.hwndParent = (HWND)hSectionOrWnd; 256 } 257 258 psh.hInstance = hApplet; 259 // psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCEW(IDC_CPLICON)); 260 psh.pszIcon = MAKEINTRESOURCEW(IDC_CPLICON); 261 psh.nPages = ARRAYSIZE(psp); 262 psh.nStartPage = 0; 263 psh.ppsp = psp; 264 psh.pfnCallback = PropSheetProc; 265 266 InitPropSheetPage(&psp[i++], IDD_PROPPAGEOPTIONS, OptionsProc); 267 InitPropSheetPage(&psp[i++], IDD_PROPPAGEFONT , FontProc ); 268 InitPropSheetPage(&psp[i++], IDD_PROPPAGELAYOUT , LayoutProc ); 269 InitPropSheetPage(&psp[i++], IDD_PROPPAGECOLORS , ColorsProc ); 270 271 /* Display the property sheet */ 272 RegisterWinPrevClass(hApplet); 273 Result = PropertySheetW(&psh); 274 UnRegisterWinPrevClass(hApplet); 275 276 /* Clear the font support */ 277 if (FontPreview.hFont) DeleteObject(FontPreview.hFont); 278 FontPreview.hFont = NULL; 279 280 /* Save the console settings */ 281 if (SetConsoleInfo) 282 { 283 HANDLE hSection; 284 285 /* 286 * Create a memory section to share with CONSRV, and map it. 287 */ 288 hSection = CreateFileMappingW(INVALID_HANDLE_VALUE, 289 NULL, 290 PAGE_READWRITE, 291 0, 292 ConInfo->cbSize, 293 NULL); 294 if (!hSection) 295 { 296 DPRINT1("Error when creating file mapping, error = %d\n", GetLastError()); 297 goto Quit; 298 } 299 300 pSharedInfo = MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS, 0, 0, 0); 301 if (!pSharedInfo) 302 { 303 DPRINT1("Error when mapping view of file, error = %d\n", GetLastError()); 304 CloseHandle(hSection); 305 goto Quit; 306 } 307 308 /* Copy the console information into the section */ 309 RtlCopyMemory(pSharedInfo, ConInfo, ConInfo->cbSize); 310 311 /* Unmap it */ 312 UnmapViewOfFile(pSharedInfo); 313 314 /* Signal to CONSRV that it can apply the new configuration */ 315 SendMessageW(ConInfo->hWnd, WM_SETCONSOLEINFO, (WPARAM)hSection, 0); 316 317 /* Close the section and return */ 318 CloseHandle(hSection); 319 } 320 321 if (SaveConsoleInfo) 322 { 323 /* Default settings saved when ConInfo->hWnd == NULL */ 324 ConCfgWriteUserSettings(ConInfo, ConInfo->hWnd == NULL); 325 } 326 327 Quit: 328 /* Cleanup */ 329 HeapFree(GetProcessHeap(), 0, ConInfo); 330 ConInfo = NULL; 331 332 return (Result != -1); 333 } 334 335 /* Control Panel Callback */ 336 LONG 337 CALLBACK 338 CPlApplet(HWND hwndCPl, 339 UINT uMsg, 340 LPARAM lParam1, 341 LPARAM lParam2) 342 { 343 switch (uMsg) 344 { 345 case CPL_INIT: 346 return TRUE; 347 348 case CPL_EXIT: 349 // TODO: Free allocated memory 350 break; 351 352 case CPL_GETCOUNT: 353 return 1; 354 355 case CPL_INQUIRE: 356 { 357 CPLINFO *CPlInfo = (CPLINFO*)lParam2; 358 CPlInfo->idIcon = IDC_CPLICON; 359 CPlInfo->idName = IDS_CPLNAME; 360 CPlInfo->idInfo = IDS_CPLDESCRIPTION; 361 break; 362 } 363 364 case CPL_DBLCLK: 365 InitApplet((HANDLE)hwndCPl); 366 break; 367 } 368 369 return FALSE; 370 } 371 372 INT 373 WINAPI 374 DllMain(HINSTANCE hinstDLL, 375 DWORD dwReason, 376 LPVOID lpvReserved) 377 { 378 UNREFERENCED_PARAMETER(lpvReserved); 379 380 switch (dwReason) 381 { 382 case DLL_PROCESS_ATTACH: 383 hApplet = hinstDLL; 384 DisableThreadLibraryCalls(hinstDLL); 385 break; 386 } 387 388 return TRUE; 389 } 390