1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Console Server DLL 4 * FILE: win32ss/user/winsrv/consrv/frontends/gui/guisettings.c 5 * PURPOSE: GUI Terminal Front-End Settings Management 6 * PROGRAMMERS: Johannes Anderwald 7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr) 8 */ 9 10 /* INCLUDES *******************************************************************/ 11 12 #include <consrv.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 #include "concfg/font.h" 18 #include "guiterm.h" 19 #include "guisettings.h" 20 21 /* FUNCTIONS ******************************************************************/ 22 23 BOOL 24 GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo) 25 { 26 /* Do nothing */ 27 return TRUE; 28 } 29 30 BOOL 31 GuiConsoleWriteUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo) 32 { 33 /* Do nothing */ 34 return TRUE; 35 } 36 37 VOID 38 GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo) 39 { 40 /* Do nothing */ 41 } 42 43 VOID 44 GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, 45 BOOL Defaults) 46 { 47 NTSTATUS Status; 48 PCONSRV_CONSOLE Console = GuiData->Console; 49 PCONSOLE_PROCESS_DATA ProcessData; 50 HANDLE hSection = NULL, hClientSection = NULL; 51 PVOID ThreadParameter = NULL; // Is either hClientSection or the console window handle, 52 // depending on whether we display the default settings or 53 // the settings of a particular console. 54 55 DPRINT("GuiConsoleShowConsoleProperties entered\n"); 56 57 if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; 58 59 /* Get the console leader process, our client */ 60 ProcessData = ConSrvGetConsoleLeaderProcess(Console); 61 62 /* 63 * Be sure we effectively have a properties dialog routine (that launches 64 * the console control panel applet). It resides in kernel32.dll (client). 65 */ 66 if (ProcessData->PropRoutine == NULL) goto Quit; 67 68 /* 69 * Create a memory section to be shared with the console control panel applet 70 * in the case we are displaying the settings of a particular console. 71 * In that case the ThreadParameter is the hClientSection handle. 72 * In the case we display the default console parameters, we don't need to 73 * create a memory section. We just need to open the applet, and in this case 74 * the ThreadParameter is the parent window handle of the applet's window, 75 * that is, the console window. 76 */ 77 if (!Defaults) 78 { 79 PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer; 80 LARGE_INTEGER SectionSize; 81 SIZE_T ViewSize = 0; 82 PCONSOLE_STATE_INFO pSharedInfo = NULL; 83 84 /* 85 * Create a memory section to share with the applet, and map it. 86 */ 87 SectionSize.QuadPart = sizeof(CONSOLE_STATE_INFO); // Standard size 88 SectionSize.QuadPart += Console->OriginalTitle.Length; // Add the length in bytes of the console title string 89 90 Status = NtCreateSection(&hSection, 91 SECTION_ALL_ACCESS, 92 NULL, 93 &SectionSize, 94 PAGE_READWRITE, 95 SEC_COMMIT, 96 NULL); 97 if (!NT_SUCCESS(Status)) 98 { 99 DPRINT1("Error: Impossible to create a shared section, Status = 0x%08lx\n", Status); 100 goto Quit; 101 } 102 103 Status = NtMapViewOfSection(hSection, 104 NtCurrentProcess(), 105 (PVOID*)&pSharedInfo, 106 0, 107 0, 108 NULL, 109 &ViewSize, 110 ViewUnmap, 111 0, 112 PAGE_READWRITE); 113 if (!NT_SUCCESS(Status)) 114 { 115 DPRINT1("Error: Impossible to map the shared section, Status = 0x%08lx\n", Status); 116 goto Quit; 117 } 118 119 120 /* 121 * Setup the shared console properties structure. 122 */ 123 124 /* Store the real size of the structure */ 125 pSharedInfo->cbSize = SectionSize.QuadPart; 126 127 /* 128 * When we setup the settings of a particular console, the parent window 129 * of the applet's window is the console window, and it is given via the 130 * hWnd member of the shared console info structure. 131 */ 132 pSharedInfo->hWnd = GuiData->hWindow; 133 134 /* Console information */ 135 pSharedInfo->QuickEdit = Console->QuickEdit; 136 pSharedInfo->InsertMode = Console->InsertMode; 137 pSharedInfo->NumberOfHistoryBuffers = Console->MaxNumberOfHistoryBuffers; 138 pSharedInfo->HistoryBufferSize = Console->HistoryBufferSize; 139 pSharedInfo->HistoryNoDup = Console->HistoryNoDup; 140 /// pSharedInfo->InputBufferSize = 0; 141 pSharedInfo->ScreenBufferSize = ActiveBuffer->ScreenBufferSize; 142 pSharedInfo->WindowSize = ActiveBuffer->ViewSize; 143 pSharedInfo->CursorSize = ActiveBuffer->CursorInfo.dwSize; 144 if (GetType(ActiveBuffer) == TEXTMODE_BUFFER) 145 { 146 PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer; 147 148 pSharedInfo->ScreenAttributes = Buffer->ScreenDefaultAttrib; 149 pSharedInfo->PopupAttributes = Buffer->PopupDefaultAttrib; 150 } 151 else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) 152 { 153 // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer; 154 155 // FIXME: Gather defaults from the registry ? 156 pSharedInfo->ScreenAttributes = DEFAULT_SCREEN_ATTRIB; 157 pSharedInfo->PopupAttributes = DEFAULT_POPUP_ATTRIB; 158 } 159 160 /* We display the output code page only */ 161 pSharedInfo->CodePage = Console->OutputCodePage; 162 163 /* GUI Information */ 164 StringCchCopyNW(pSharedInfo->FaceName, ARRAYSIZE(pSharedInfo->FaceName), 165 GuiData->GuiInfo.FaceName, ARRAYSIZE(GuiData->GuiInfo.FaceName)); 166 pSharedInfo->FontFamily = GuiData->GuiInfo.FontFamily; 167 pSharedInfo->FontSize = GuiData->GuiInfo.FontSize; 168 pSharedInfo->FontWeight = GuiData->GuiInfo.FontWeight; 169 pSharedInfo->FullScreen = GuiData->GuiInfo.FullScreen; 170 pSharedInfo->AutoPosition = GuiData->GuiInfo.AutoPosition; 171 pSharedInfo->WindowPosition = GuiData->GuiInfo.WindowOrigin; 172 173 /* Palette */ 174 RtlCopyMemory(pSharedInfo->ColorTable, 175 Console->Colors, sizeof(Console->Colors)); 176 177 /* Copy the original title of the console and null-terminate it */ 178 RtlCopyMemory(pSharedInfo->ConsoleTitle, 179 Console->OriginalTitle.Buffer, 180 Console->OriginalTitle.Length); 181 182 pSharedInfo->ConsoleTitle[Console->OriginalTitle.Length / sizeof(WCHAR)] = UNICODE_NULL; 183 184 185 /* Unmap the view */ 186 NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo); 187 188 /* Duplicate the section handle for the client */ 189 Status = NtDuplicateObject(NtCurrentProcess(), 190 hSection, 191 ProcessData->Process->ProcessHandle, 192 &hClientSection, 193 0, 0, DUPLICATE_SAME_ACCESS); 194 if (!NT_SUCCESS(Status)) 195 { 196 DPRINT1("Error: Impossible to duplicate section handle for client, Status = 0x%08lx\n", Status); 197 goto Quit; 198 } 199 200 /* For the settings of a particular console, use the shared client section handle as the thread parameter */ 201 ThreadParameter = (PVOID)hClientSection; 202 } 203 else 204 { 205 /* For the default settings, use the console window handle as the thread parameter */ 206 ThreadParameter = (PVOID)GuiData->hWindow; 207 } 208 209 /* Start the console control panel applet */ 210 _SEH2_TRY 211 { 212 HANDLE Thread = NULL; 213 214 _SEH2_TRY 215 { 216 Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, 217 ProcessData->PropRoutine, 218 ThreadParameter, 0, NULL); 219 if (NULL == Thread) 220 { 221 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError()); 222 } 223 else 224 { 225 DPRINT("ProcessData->PropRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", 226 ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); 227 } 228 } 229 _SEH2_FINALLY 230 { 231 CloseHandle(Thread); 232 } 233 _SEH2_END; 234 } 235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 236 { 237 Status = _SEH2_GetExceptionCode(); 238 DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = 0x%08lx\n", Status); 239 } 240 _SEH2_END; 241 242 Quit: 243 /* We have finished, close the section handle if any */ 244 if (hSection) NtClose(hSection); 245 246 LeaveCriticalSection(&Console->Lock); 247 return; 248 } 249 250 /* 251 * Function for dealing with the undocumented message and structure used by 252 * Windows' console.dll for setting console info. 253 * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c 254 * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf 255 * for more information. 256 */ 257 VOID 258 GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, 259 HANDLE hClientSection) 260 { 261 NTSTATUS Status = STATUS_SUCCESS; 262 PCONSRV_CONSOLE Console = GuiData->Console; 263 PCONSOLE_PROCESS_DATA ProcessData; 264 HANDLE hSection = NULL; 265 SIZE_T ViewSize = 0; 266 PCONSOLE_STATE_INFO pConInfo = NULL; 267 268 if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; 269 270 /* Get the console leader process, our client */ 271 ProcessData = ConSrvGetConsoleLeaderProcess(Console); 272 273 /* Duplicate the section handle for ourselves */ 274 Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, 275 hClientSection, 276 NtCurrentProcess(), 277 &hSection, 278 0, 0, DUPLICATE_SAME_ACCESS); 279 if (!NT_SUCCESS(Status)) 280 { 281 DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status); 282 goto Quit; 283 } 284 285 /* Get a view of the shared section */ 286 Status = NtMapViewOfSection(hSection, 287 NtCurrentProcess(), 288 (PVOID*)&pConInfo, 289 0, 290 0, 291 NULL, 292 &ViewSize, 293 ViewUnmap, 294 0, 295 PAGE_READWRITE); 296 if (!NT_SUCCESS(Status)) 297 { 298 DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status); 299 goto Quit; 300 } 301 302 _SEH2_TRY 303 { 304 /* Check that the section is well-sized */ 305 if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) || 306 (pConInfo->cbSize < sizeof(CONSOLE_STATE_INFO)) ) 307 { 308 DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n"); 309 Status = STATUS_INVALID_VIEW_SIZE; 310 _SEH2_YIELD(goto Quit); 311 } 312 313 // TODO: Check that GuiData->hWindow == pConInfo->hWnd 314 315 /* Retrieve terminal informations */ 316 317 /* Console information */ 318 319 /* 320 * Apply the settings 321 */ 322 323 /* Set the console informations */ 324 ConSrvApplyUserSettings(Console, pConInfo); 325 326 /* Set the terminal informations */ 327 328 /* Refresh the additional TrueType fonts cache and change the font */ 329 RefreshTTFontCache(); 330 InitFonts(GuiData, 331 pConInfo->FaceName, 332 pConInfo->FontFamily, 333 pConInfo->FontSize, 334 pConInfo->FontWeight); 335 // HACK, needed because changing font may change the size of the window 336 /**/TermResizeTerminal(Console);/**/ 337 338 /* Move the window to the user's values */ 339 GuiData->GuiInfo.AutoPosition = !!pConInfo->AutoPosition; 340 GuiData->GuiInfo.WindowOrigin = pConInfo->WindowPosition; 341 GuiConsoleMoveWindow(GuiData); 342 343 InvalidateRect(GuiData->hWindow, NULL, TRUE); 344 345 /* 346 * Apply full-screen mode. 347 */ 348 if (!!pConInfo->FullScreen != GuiData->GuiInfo.FullScreen) 349 { 350 SwitchFullScreen(GuiData, !!pConInfo->FullScreen); 351 } 352 353 /* 354 * The settings are saved in the registry by console.dll itself, if needed. 355 */ 356 // if (SaveSettings) 357 // { 358 // GuiConsoleWriteUserSettings(GuiInfo); 359 // } 360 361 Status = STATUS_SUCCESS; 362 } 363 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 364 { 365 Status = _SEH2_GetExceptionCode(); 366 DPRINT1("GuiApplyUserSettings - Caught an exception, Status = 0x%08lx\n", Status); 367 } 368 _SEH2_END; 369 370 Quit: 371 /* Finally, close the section and return */ 372 if (hSection) 373 { 374 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo); 375 NtClose(hSection); 376 } 377 378 LeaveCriticalSection(&Console->Lock); 379 return; 380 } 381 382 /* EOF */ 383