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 "guiterm.h" 18 #include "guisettings.h" 19 20 /* FUNCTIONS ******************************************************************/ 21 22 BOOL 23 GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo) 24 { 25 /* Do nothing */ 26 return TRUE; 27 } 28 29 BOOL 30 GuiConsoleWriteUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo) 31 { 32 /* Do nothing */ 33 return TRUE; 34 } 35 36 VOID 37 GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo) 38 { 39 /* Do nothing */ 40 } 41 42 VOID 43 GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, 44 BOOL Defaults) 45 { 46 NTSTATUS Status; 47 PCONSRV_CONSOLE Console = GuiData->Console; 48 PCONSOLE_PROCESS_DATA ProcessData; 49 HANDLE hSection = NULL, hClientSection = NULL; 50 PVOID ThreadParameter = NULL; // Is either hClientSection or the console window handle, 51 // depending on whether we display the default settings or 52 // the settings of a particular console. 53 54 DPRINT("GuiConsoleShowConsoleProperties entered\n"); 55 56 if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; 57 58 /* Get the console leader process, our client */ 59 ProcessData = ConSrvGetConsoleLeaderProcess(Console); 60 61 /* 62 * Be sure we effectively have a properties dialog routine (that launches 63 * the console control panel applet). It resides in kernel32.dll (client). 64 */ 65 if (ProcessData->PropRoutine == NULL) goto Quit; 66 67 /* 68 * Create a memory section to be shared with the console control panel applet 69 * in the case we are displaying the settings of a particular console. 70 * In that case the ThreadParameter is the hClientSection handle. 71 * In the case we display the default console parameters, we don't need to 72 * create a memory section. We just need to open the applet, and in this case 73 * the ThreadParameter is the parent window handle of the applet's window, 74 * that is, the console window. 75 */ 76 if (!Defaults) 77 { 78 PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer; 79 LARGE_INTEGER SectionSize; 80 SIZE_T ViewSize = 0; 81 PCONSOLE_STATE_INFO pSharedInfo = NULL; 82 83 /* 84 * Create a memory section to share with the applet, and map it. 85 */ 86 SectionSize.QuadPart = sizeof(CONSOLE_STATE_INFO); // Standard size 87 SectionSize.QuadPart += Console->OriginalTitle.Length; // Add the length in bytes of the console title string 88 89 Status = NtCreateSection(&hSection, 90 SECTION_ALL_ACCESS, 91 NULL, 92 &SectionSize, 93 PAGE_READWRITE, 94 SEC_COMMIT, 95 NULL); 96 if (!NT_SUCCESS(Status)) 97 { 98 DPRINT1("Error: Impossible to create a shared section, Status = 0x%08lx\n", Status); 99 goto Quit; 100 } 101 102 Status = NtMapViewOfSection(hSection, 103 NtCurrentProcess(), 104 (PVOID*)&pSharedInfo, 105 0, 106 0, 107 NULL, 108 &ViewSize, 109 ViewUnmap, 110 0, 111 PAGE_READWRITE); 112 if (!NT_SUCCESS(Status)) 113 { 114 DPRINT1("Error: Impossible to map the shared section, Status = 0x%08lx\n", Status); 115 goto Quit; 116 } 117 118 119 /* 120 * Setup the shared console properties structure. 121 */ 122 123 /* Store the real size of the structure */ 124 pSharedInfo->cbSize = SectionSize.QuadPart; 125 126 /* 127 * When we setup the settings of a particular console, the parent window 128 * of the applet's window is the console window, and it is given via the 129 * hWnd member of the shared console info structure. 130 */ 131 pSharedInfo->hWnd = GuiData->hWindow; 132 133 /* Console information */ 134 pSharedInfo->HistoryBufferSize = Console->HistoryBufferSize; 135 pSharedInfo->NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; 136 pSharedInfo->HistoryNoDup = Console->HistoryNoDup; 137 pSharedInfo->QuickEdit = Console->QuickEdit; 138 pSharedInfo->InsertMode = Console->InsertMode; 139 /// pSharedInfo->InputBufferSize = 0; 140 pSharedInfo->ScreenBufferSize = ActiveBuffer->ScreenBufferSize; 141 pSharedInfo->WindowSize = ActiveBuffer->ViewSize; 142 pSharedInfo->CursorSize = ActiveBuffer->CursorInfo.dwSize; 143 if (GetType(ActiveBuffer) == TEXTMODE_BUFFER) 144 { 145 PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer; 146 147 pSharedInfo->ScreenAttributes = Buffer->ScreenDefaultAttrib; 148 pSharedInfo->PopupAttributes = Buffer->PopupDefaultAttrib; 149 } 150 else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) 151 { 152 // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer; 153 DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n"); 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 #if 0 // FIXME: Things not set 319 ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize; 320 ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers; 321 ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup; 322 ConInfo.CodePage = pConInfo->CodePage; // Done in ConSrvApplyUserSettings 323 #endif 324 325 /* 326 * Apply the settings 327 */ 328 329 /* Set the console informations */ 330 ConSrvApplyUserSettings(Console, pConInfo); 331 332 /* Set the terminal informations */ 333 334 /* Change the font */ 335 InitFonts(GuiData, 336 pConInfo->FaceName, 337 pConInfo->FontFamily, 338 pConInfo->FontSize, 339 pConInfo->FontWeight); 340 // HACK, needed because changing font may change the size of the window 341 /**/TermResizeTerminal(Console);/**/ 342 343 /* Move the window to the user's values */ 344 GuiData->GuiInfo.AutoPosition = !!pConInfo->AutoPosition; 345 GuiData->GuiInfo.WindowOrigin = pConInfo->WindowPosition; 346 GuiConsoleMoveWindow(GuiData); 347 348 InvalidateRect(GuiData->hWindow, NULL, TRUE); 349 350 /* 351 * Apply full-screen mode. 352 */ 353 if (!!pConInfo->FullScreen != GuiData->GuiInfo.FullScreen) 354 { 355 SwitchFullScreen(GuiData, !!pConInfo->FullScreen); 356 } 357 358 /* 359 * The settings are saved in the registry by console.dll itself, if needed. 360 */ 361 // if (SaveSettings) 362 // { 363 // GuiConsoleWriteUserSettings(GuiInfo); 364 // } 365 366 Status = STATUS_SUCCESS; 367 } 368 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 369 { 370 Status = _SEH2_GetExceptionCode(); 371 DPRINT1("GuiApplyUserSettings - Caught an exception, Status = 0x%08lx\n", Status); 372 } 373 _SEH2_END; 374 375 Quit: 376 /* Finally, close the section and return */ 377 if (hSection) 378 { 379 NtUnmapViewOfSection(NtCurrentProcess(), pConInfo); 380 NtClose(hSection); 381 } 382 383 LeaveCriticalSection(&Console->Lock); 384 return; 385 } 386 387 /* EOF */ 388