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 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 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 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