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