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 -- 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 /* Save the console settings */ 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 */ 307 RtlCopyMemory(pSharedInfo, ConInfo, ConInfo->cbSize); 308 309 /* Unmap it */ 310 UnmapViewOfFile(pSharedInfo); 311 312 /* Signal to CONSRV that it can apply the new configuration */ 313 SendMessageW(ConInfo->hWnd, WM_SETCONSOLEINFO, (WPARAM)hSection, 0); 314 315 /* Close the section and return */ 316 CloseHandle(hSection); 317 } 318 319 if (SaveConsoleInfo) 320 { 321 /* Default settings saved when ConInfo->hWnd == NULL */ 322 ConCfgWriteUserSettings(ConInfo, ConInfo->hWnd == NULL); 323 } 324 325 Quit: 326 /* Cleanup */ 327 HeapFree(GetProcessHeap(), 0, ConInfo); 328 ConInfo = NULL; 329 330 return (Result != -1); 331 } 332 333 /* Control Panel Callback */ 334 LONG 335 CALLBACK 336 CPlApplet(HWND hwndCPl, 337 UINT uMsg, 338 LPARAM lParam1, 339 LPARAM lParam2) 340 { 341 switch (uMsg) 342 { 343 case CPL_INIT: 344 return TRUE; 345 346 case CPL_EXIT: 347 // TODO: Free allocated memory 348 break; 349 350 case CPL_GETCOUNT: 351 return 1; 352 353 case CPL_INQUIRE: 354 { 355 CPLINFO *CPlInfo = (CPLINFO*)lParam2; 356 CPlInfo->idIcon = IDC_CPLICON; 357 CPlInfo->idName = IDS_CPLNAME; 358 CPlInfo->idInfo = IDS_CPLDESCRIPTION; 359 break; 360 } 361 362 case CPL_DBLCLK: 363 InitApplet((HANDLE)hwndCPl); 364 break; 365 } 366 367 return FALSE; 368 } 369 370 INT 371 WINAPI 372 DllMain(HINSTANCE hinstDLL, 373 DWORD dwReason, 374 LPVOID lpvReserved) 375 { 376 UNREFERENCED_PARAMETER(lpvReserved); 377 378 switch (dwReason) 379 { 380 case DLL_PROCESS_ATTACH: 381 hApplet = hinstDLL; 382 DisableThreadLibraryCalls(hinstDLL); 383 break; 384 } 385 386 return TRUE; 387 } 388