1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Console Server DLL 4 * FILE: win32ss/user/winsrv/consrv/frontends/gui/guiterm.c 5 * PURPOSE: GUI Terminal Front-End 6 * PROGRAMMERS: G� van Geldorp 7 * Johannes Anderwald 8 * Jeffrey Morlan 9 * Hermes Belusca-Maito (hermes.belusca@sfr.fr) 10 */ 11 12 /* INCLUDES *******************************************************************/ 13 14 #include <consrv.h> 15 16 #define NDEBUG 17 #include <debug.h> 18 19 #include "concfg/font.h" 20 #include "guiterm.h" 21 #include "resource.h" 22 23 // HACK!! Remove it when the hack in GuiWriteStream is fixed 24 #define CONGUI_UPDATE_TIME 0 25 #define CONGUI_UPDATE_TIMER 1 26 27 #define PM_CREATE_CONSOLE (WM_APP + 1) 28 #define PM_DESTROY_CONSOLE (WM_APP + 2) 29 30 31 /* GLOBALS ********************************************************************/ 32 33 typedef struct _GUI_INIT_INFO 34 { 35 HANDLE GuiThreadStartupEvent; 36 ULONG_PTR InputThreadId; 37 HWINSTA WinSta; 38 HDESK Desktop; 39 HICON hIcon; 40 HICON hIconSm; 41 BOOLEAN IsWindowVisible; 42 GUI_CONSOLE_INFO TermInfo; 43 } GUI_INIT_INFO, *PGUI_INIT_INFO; 44 45 static BOOL ConsInitialized = FALSE; 46 47 extern HICON ghDefaultIcon; 48 extern HICON ghDefaultIconSm; 49 extern HCURSOR ghDefaultCursor; 50 51 VOID 52 SetConWndConsoleLeaderCID(IN PGUI_CONSOLE_DATA GuiData); 53 BOOLEAN 54 RegisterConWndClass(IN HINSTANCE hInstance); 55 BOOLEAN 56 UnRegisterConWndClass(HINSTANCE hInstance); 57 58 /* FUNCTIONS ******************************************************************/ 59 60 VOID 61 GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData) 62 { 63 /* Move the window if needed (not positioned by the system) */ 64 if (!GuiData->GuiInfo.AutoPosition) 65 { 66 SetWindowPos(GuiData->hWindow, 67 NULL, 68 GuiData->GuiInfo.WindowOrigin.x, 69 GuiData->GuiInfo.WindowOrigin.y, 70 0, 0, 71 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); 72 } 73 } 74 75 static VOID 76 DrawRegion(PGUI_CONSOLE_DATA GuiData, 77 SMALL_RECT* Region) 78 { 79 RECT RegionRect; 80 81 SmallRectToRect(GuiData, &RegionRect, Region); 82 /* Do not erase the background: it speeds up redrawing and reduce flickering */ 83 InvalidateRect(GuiData->hWindow, &RegionRect, FALSE); 84 /**UpdateWindow(GuiData->hWindow);**/ 85 } 86 87 VOID 88 InvalidateCell(PGUI_CONSOLE_DATA GuiData, 89 SHORT x, SHORT y) 90 { 91 SMALL_RECT CellRect = { x, y, x, y }; 92 DrawRegion(GuiData, &CellRect); 93 } 94 95 96 /****************************************************************************** 97 * GUI Terminal Initialization * 98 ******************************************************************************/ 99 100 // FIXME: HACK: Potential HACK for CORE-8129; see revision 63595. 101 VOID 102 CreateSysMenu(HWND hWnd); 103 104 static ULONG NTAPI 105 GuiConsoleInputThread(PVOID Param) 106 { 107 NTSTATUS Status; 108 PCSR_THREAD pcsrt = NULL; 109 PGUI_INIT_INFO GuiInitInfo = (PGUI_INIT_INFO)Param; 110 DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo; 111 ULONG_PTR InputThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread); 112 HANDLE hThread = NULL; 113 114 LONG WindowCount = 0; 115 MSG msg; 116 117 /* 118 * This thread dispatches all the console notifications to the 119 * notification window. It is common for all the console windows 120 * in a given desktop in a window station. 121 */ 122 123 /* Assign this console input thread to this desktop */ 124 DesktopConsoleThreadInfo.DesktopHandle = GuiInitInfo->Desktop; // Duplicated desktop handle 125 DesktopConsoleThreadInfo.ThreadId = InputThreadId; 126 Status = NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread, 127 &DesktopConsoleThreadInfo, 128 sizeof(DesktopConsoleThreadInfo)); 129 if (!NT_SUCCESS(Status)) goto Quit; 130 131 /* Connect this CSR thread to the USER subsystem */ 132 pcsrt = CsrConnectToUser(); 133 if (pcsrt == NULL) goto Quit; 134 hThread = pcsrt->ThreadHandle; 135 136 /* Assign the desktop to this thread */ 137 if (!SetThreadDesktop(DesktopConsoleThreadInfo.DesktopHandle)) goto Quit; 138 139 /* The thread has been initialized, set the event */ 140 NtSetEvent(GuiInitInfo->GuiThreadStartupEvent, NULL); 141 Status = STATUS_SUCCESS; 142 143 while (GetMessageW(&msg, NULL, 0, 0)) 144 { 145 switch (msg.message) 146 { 147 case PM_CREATE_CONSOLE: 148 { 149 PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)msg.lParam; 150 PCONSRV_CONSOLE Console = GuiData->Console; 151 HWND NewWindow; 152 RECT rcWnd; 153 154 DPRINT("PM_CREATE_CONSOLE -- creating window\n"); 155 156 NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE, 157 GUI_CONWND_CLASS, 158 Console->Title.Buffer, 159 WS_OVERLAPPEDWINDOW, 160 CW_USEDEFAULT, 161 CW_USEDEFAULT, 162 CW_USEDEFAULT, 163 CW_USEDEFAULT, 164 GuiData->IsWindowVisible ? HWND_DESKTOP : HWND_MESSAGE, 165 NULL, 166 ConSrvDllInstance, 167 (PVOID)GuiData); 168 if (NewWindow == NULL) 169 { 170 DPRINT1("Failed to create a new console window\n"); 171 continue; 172 } 173 174 ASSERT(NewWindow == GuiData->hWindow); 175 176 _InterlockedIncrement(&WindowCount); 177 178 // 179 // FIXME: TODO: Move everything there into conwnd.c!OnNcCreate() 180 // 181 182 /* Retrieve our real position */ 183 // See conwnd.c!OnMove() 184 GetWindowRect(GuiData->hWindow, &rcWnd); 185 GuiData->GuiInfo.WindowOrigin.x = rcWnd.left; 186 GuiData->GuiInfo.WindowOrigin.y = rcWnd.top; 187 188 if (GuiData->IsWindowVisible) 189 { 190 /* Move and resize the window to the user's values */ 191 /* CAN WE DEADLOCK ?? */ 192 GuiConsoleMoveWindow(GuiData); // FIXME: This MUST be done via the CreateWindowExW call. 193 SendMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0); 194 } 195 196 // FIXME: HACK: Potential HACK for CORE-8129; see revision 63595. 197 CreateSysMenu(GuiData->hWindow); 198 199 if (GuiData->IsWindowVisible) 200 { 201 /* Switch to full-screen mode if necessary */ 202 // FIXME: Move elsewhere, it cause misdrawings of the window. 203 if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE); 204 205 DPRINT("PM_CREATE_CONSOLE -- showing window\n"); 206 ShowWindowAsync(NewWindow, (int)GuiData->GuiInfo.ShowWindow); 207 } 208 else 209 { 210 DPRINT("PM_CREATE_CONSOLE -- hidden window\n"); 211 ShowWindowAsync(NewWindow, SW_HIDE); 212 } 213 214 continue; 215 } 216 217 case PM_DESTROY_CONSOLE: 218 { 219 PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)msg.lParam; 220 MSG TempMsg; 221 222 /* Exit the full screen mode if it was already set */ 223 // LeaveFullScreen(GuiData); 224 225 /* 226 * Window creation is done using a PostMessage(), so it's possible 227 * that the window that we want to destroy doesn't exist yet. 228 * So first empty the message queue. 229 */ 230 while (PeekMessageW(&TempMsg, NULL, 0, 0, PM_REMOVE)) 231 { 232 DispatchMessageW(&TempMsg); 233 } 234 235 if (GuiData->hWindow == NULL) continue; 236 237 DestroyWindow(GuiData->hWindow); 238 239 NtSetEvent(GuiData->hGuiTermEvent, NULL); 240 241 if (_InterlockedDecrement(&WindowCount) == 0) 242 { 243 DPRINT("CONSRV: Going to quit the Input Thread 0x%p\n", InputThreadId); 244 goto Quit; 245 } 246 247 continue; 248 } 249 } 250 251 TranslateMessage(&msg); 252 DispatchMessageW(&msg); 253 } 254 255 Quit: 256 DPRINT("CONSRV: Quit the Input Thread 0x%p, Status = 0x%08lx\n", InputThreadId, Status); 257 258 /* Remove this console input thread from this desktop */ 259 // DesktopConsoleThreadInfo.DesktopHandle; 260 DesktopConsoleThreadInfo.ThreadId = 0; 261 NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread, 262 &DesktopConsoleThreadInfo, 263 sizeof(DesktopConsoleThreadInfo)); 264 265 /* Close the duplicated desktop handle */ 266 CloseDesktop(DesktopConsoleThreadInfo.DesktopHandle); // NtUserCloseDesktop 267 268 /* Cleanup CSR thread */ 269 if (pcsrt) 270 { 271 if (hThread != pcsrt->ThreadHandle) 272 DPRINT1("WARNING!! hThread (0x%p) != pcsrt->ThreadHandle (0x%p), you may expect crashes soon!!\n", hThread, pcsrt->ThreadHandle); 273 274 CsrDereferenceThread(pcsrt); 275 } 276 277 /* Exit the thread */ 278 RtlExitUserThread(Status); 279 return 0; 280 } 281 282 // FIXME: Maybe return a NTSTATUS 283 static BOOL 284 GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo, 285 IN HANDLE ConsoleLeaderProcessHandle, 286 IN OUT PGUI_INIT_INFO GuiInitInfo) 287 { 288 BOOL Success = TRUE; 289 UNICODE_STRING DesktopPath; 290 DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo; 291 HWINSTA hWinSta; 292 HDESK hDesk; 293 294 NTSTATUS Status; 295 HANDLE hInputThread; 296 CLIENT_ID ClientId; 297 298 /* Perform one-time initialization */ 299 if (!ConsInitialized) 300 { 301 /* Initialize and register the console window class */ 302 if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE; 303 304 /* Initialize the font support -- additional TrueType fonts cache */ 305 InitTTFontCache(); 306 307 ConsInitialized = TRUE; 308 } 309 310 /* 311 * Set-up the console input thread. We have 312 * one console input thread per desktop. 313 */ 314 315 if (!CsrImpersonateClient(NULL)) 316 // return STATUS_BAD_IMPERSONATION_LEVEL; 317 return FALSE; 318 319 if (ConsoleInitInfo->DesktopLength) 320 { 321 DesktopPath.MaximumLength = ConsoleInitInfo->DesktopLength; 322 DesktopPath.Length = DesktopPath.MaximumLength - sizeof(UNICODE_NULL); 323 DesktopPath.Buffer = ConsoleInitInfo->Desktop; 324 } 325 else 326 { 327 RtlInitUnicodeString(&DesktopPath, L"Default"); 328 } 329 330 hDesk = NtUserResolveDesktop(ConsoleLeaderProcessHandle, 331 &DesktopPath, 332 FALSE, 333 &hWinSta); 334 DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n", 335 &DesktopPath, hDesk, hWinSta); 336 337 CsrRevertToSelf(); 338 339 if (hDesk == NULL) return FALSE; 340 341 /* 342 * We need to see whether we need to create a 343 * new console input thread for this desktop. 344 */ 345 DesktopConsoleThreadInfo.DesktopHandle = hDesk; 346 DesktopConsoleThreadInfo.ThreadId = (ULONG_PTR)INVALID_HANDLE_VALUE; // Special value to say we just want to retrieve the thread ID. 347 NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread, 348 &DesktopConsoleThreadInfo, 349 sizeof(DesktopConsoleThreadInfo)); 350 DPRINT("NtUserConsoleControl returned ThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId); 351 352 /* 353 * Save the opened window station and desktop handles in the initialization 354 * structure. They will be used later on, and released, by the GUI frontend. 355 */ 356 GuiInitInfo->WinSta = hWinSta; 357 GuiInitInfo->Desktop = hDesk; 358 359 /* Here GuiInitInfo contains original handles */ 360 361 /* If we already have a console input thread on this desktop... */ 362 if (DesktopConsoleThreadInfo.ThreadId != 0) 363 { 364 /* ... just use it... */ 365 DPRINT("Using input thread InputThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId); 366 GuiInitInfo->InputThreadId = DesktopConsoleThreadInfo.ThreadId; 367 goto Quit; 368 } 369 370 /* ... otherwise create a new one. */ 371 372 /* Initialize a startup event for the thread to signal it */ 373 Status = NtCreateEvent(&GuiInitInfo->GuiThreadStartupEvent, EVENT_ALL_ACCESS, 374 NULL, SynchronizationEvent, FALSE); 375 if (!NT_SUCCESS(Status)) 376 { 377 Success = FALSE; 378 goto Quit; 379 } 380 381 /* 382 * Duplicate the desktop handle for the console input thread internal needs. 383 * If it happens to need also a window station handle in the future, then 384 * it is there that you also need to duplicate the window station handle! 385 * 386 * Note also that we are going to temporarily overwrite the stored handles 387 * in GuiInitInfo because it happens that we use also this structure to give 388 * the duplicated handles to the input thread that is going to initialize. 389 * After the input thread finishes its initialization, we restore the handles 390 * in GuiInitInfo to their old values. 391 */ 392 Status = NtDuplicateObject(NtCurrentProcess(), 393 hDesk, 394 NtCurrentProcess(), 395 (PHANDLE)&GuiInitInfo->Desktop, 396 0, 0, DUPLICATE_SAME_ACCESS); 397 if (!NT_SUCCESS(Status)) 398 { 399 Success = FALSE; 400 goto Quit; 401 } 402 403 /* Here GuiInitInfo contains duplicated handles */ 404 405 Status = RtlCreateUserThread(NtCurrentProcess(), 406 NULL, 407 TRUE, // Start the thread in suspended state 408 0, 409 0, 410 0, 411 (PVOID)GuiConsoleInputThread, 412 (PVOID)GuiInitInfo, 413 &hInputThread, 414 &ClientId); 415 if (NT_SUCCESS(Status)) 416 { 417 /* Add it as a static server thread and resume it */ 418 CsrAddStaticServerThread(hInputThread, &ClientId, 0); 419 Status = NtResumeThread(hInputThread, NULL); 420 } 421 DPRINT("Thread creation hInputThread = 0x%p, InputThreadId = 0x%p, Status = 0x%08lx\n", 422 hInputThread, ClientId.UniqueThread, Status); 423 424 if (!NT_SUCCESS(Status) || hInputThread == NULL) 425 { 426 /* Close the thread's handle */ 427 if (hInputThread) NtClose(hInputThread); 428 429 /* We need to close here the duplicated desktop handle */ 430 CloseDesktop(GuiInitInfo->Desktop); // NtUserCloseDesktop 431 432 /* Close the startup event and bail out */ 433 NtClose(GuiInitInfo->GuiThreadStartupEvent); 434 435 DPRINT1("CONSRV: Failed to create graphics console thread.\n"); 436 Success = FALSE; 437 goto Quit; 438 } 439 440 /* No need to close hInputThread, this is done by CSR automatically */ 441 442 /* Wait for the thread to finish its initialization, and close the startup event */ 443 NtWaitForSingleObject(GuiInitInfo->GuiThreadStartupEvent, FALSE, NULL); 444 NtClose(GuiInitInfo->GuiThreadStartupEvent); 445 446 /* 447 * Save the input thread ID for later use, and restore the original handles. 448 * The copies are held by the console input thread. 449 */ 450 GuiInitInfo->InputThreadId = (ULONG_PTR)ClientId.UniqueThread; 451 GuiInitInfo->WinSta = hWinSta; 452 GuiInitInfo->Desktop = hDesk; 453 454 /* Here GuiInitInfo contains again original handles */ 455 456 Quit: 457 if (!Success) 458 { 459 /* 460 * Close the original handles. Do not use the copies in GuiInitInfo 461 * because we may have failed in the middle of the duplicate operation 462 * and the handles stored in GuiInitInfo may have changed. 463 */ 464 CloseDesktop(hDesk); // NtUserCloseDesktop 465 CloseWindowStation(hWinSta); // NtUserCloseWindowStation 466 } 467 468 return Success; 469 } 470 471 472 /****************************************************************************** 473 * GUI Console Driver * 474 ******************************************************************************/ 475 476 static VOID NTAPI 477 GuiDeinitFrontEnd(IN OUT PFRONTEND This); 478 479 static NTSTATUS NTAPI 480 GuiInitFrontEnd(IN OUT PFRONTEND This, 481 IN PCONSRV_CONSOLE Console) 482 { 483 PGUI_INIT_INFO GuiInitInfo; 484 PGUI_CONSOLE_DATA GuiData; 485 486 if (This == NULL || Console == NULL || This->Context2 == NULL) 487 return STATUS_INVALID_PARAMETER; 488 489 ASSERT(This->Console == Console); 490 491 GuiInitInfo = This->Context2; 492 493 /* Terminal data allocation */ 494 GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiData)); 495 if (!GuiData) 496 { 497 DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n"); 498 return STATUS_UNSUCCESSFUL; 499 } 500 /// /* HACK */ Console->FrontEndIFace.Context = (PVOID)GuiData; /* HACK */ 501 GuiData->Console = Console; 502 GuiData->ActiveBuffer = Console->ActiveBuffer; 503 GuiData->hWindow = NULL; 504 GuiData->IsWindowVisible = GuiInitInfo->IsWindowVisible; 505 506 /* The console can be resized */ 507 Console->FixedSize = FALSE; 508 509 InitializeCriticalSection(&GuiData->Lock); 510 511 /* 512 * Set up GUI data 513 */ 514 RtlCopyMemory(&GuiData->GuiInfo, &GuiInitInfo->TermInfo, sizeof(GuiInitInfo->TermInfo)); 515 516 /* Initialize the icon handles */ 517 if (GuiInitInfo->hIcon != NULL) 518 GuiData->hIcon = GuiInitInfo->hIcon; 519 else 520 GuiData->hIcon = ghDefaultIcon; 521 522 if (GuiInitInfo->hIconSm != NULL) 523 GuiData->hIconSm = GuiInitInfo->hIconSm; 524 else 525 GuiData->hIconSm = ghDefaultIconSm; 526 527 ASSERT(GuiData->hIcon && GuiData->hIconSm); 528 529 /* Mouse is shown by default with its default cursor shape */ 530 GuiData->hCursor = ghDefaultCursor; 531 GuiData->MouseCursorRefCount = 0; 532 533 /* A priori don't ignore mouse signals */ 534 GuiData->IgnoreNextMouseSignal = FALSE; 535 /* Initialize HACK FOR CORE-8394. See conwnd.c!OnMouse for more details. */ 536 GuiData->HackCORE8394IgnoreNextMove = FALSE; 537 538 /* Close button and the corresponding system menu item are enabled by default */ 539 GuiData->IsCloseButtonEnabled = TRUE; 540 541 /* There is no user-reserved menu id range by default */ 542 GuiData->CmdIdLow = GuiData->CmdIdHigh = 0; 543 544 /* Initialize the selection */ 545 RtlZeroMemory(&GuiData->Selection, sizeof(GuiData->Selection)); 546 GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION; 547 RtlZeroMemory(&GuiData->dwSelectionCursor, sizeof(GuiData->dwSelectionCursor)); 548 GuiData->LineSelection = FALSE; // Default to block selection 549 // TODO: Retrieve the selection mode via the registry. 550 551 GuiData->InputThreadId = GuiInitInfo->InputThreadId; 552 GuiData->WinSta = GuiInitInfo->WinSta; 553 GuiData->Desktop = GuiInitInfo->Desktop; 554 555 /* Finally, finish to initialize the frontend structure */ 556 This->Context = GuiData; 557 ConsoleFreeHeap(This->Context2); 558 This->Context2 = NULL; 559 560 /* 561 * We need to wait until the GUI has been fully initialized 562 * to retrieve custom settings i.e. WindowSize etc... 563 * Ideally we could use SendNotifyMessage for this but its not 564 * yet implemented. 565 */ 566 NtCreateEvent(&GuiData->hGuiInitEvent, EVENT_ALL_ACCESS, 567 NULL, SynchronizationEvent, FALSE); 568 NtCreateEvent(&GuiData->hGuiTermEvent, EVENT_ALL_ACCESS, 569 NULL, SynchronizationEvent, FALSE); 570 571 DPRINT("GUI - Checkpoint\n"); 572 573 /* Create the terminal window */ 574 PostThreadMessageW(GuiData->InputThreadId, PM_CREATE_CONSOLE, 0, (LPARAM)GuiData); 575 576 /* Wait until initialization has finished */ 577 NtWaitForSingleObject(GuiData->hGuiInitEvent, FALSE, NULL); 578 DPRINT("OK we created the console window\n"); 579 NtClose(GuiData->hGuiInitEvent); 580 GuiData->hGuiInitEvent = NULL; 581 582 /* Check whether we really succeeded in initializing the terminal window */ 583 if (GuiData->hWindow == NULL) 584 { 585 DPRINT("GuiInitConsole - We failed at creating a new terminal window\n"); 586 GuiDeinitFrontEnd(This); 587 return STATUS_UNSUCCESSFUL; 588 } 589 590 return STATUS_SUCCESS; 591 } 592 593 static VOID NTAPI 594 GuiDeinitFrontEnd(IN OUT PFRONTEND This) 595 { 596 PGUI_CONSOLE_DATA GuiData = This->Context; 597 598 DPRINT("Send PM_DESTROY_CONSOLE message and wait on hGuiTermEvent...\n"); 599 PostThreadMessageW(GuiData->InputThreadId, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData); 600 NtWaitForSingleObject(GuiData->hGuiTermEvent, FALSE, NULL); 601 DPRINT("hGuiTermEvent set\n"); 602 NtClose(GuiData->hGuiTermEvent); 603 GuiData->hGuiTermEvent = NULL; 604 605 CloseDesktop(GuiData->Desktop); // NtUserCloseDesktop 606 CloseWindowStation(GuiData->WinSta); // NtUserCloseWindowStation 607 608 DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n", 609 GuiData->hIcon, ghDefaultIcon, GuiData->hIconSm, ghDefaultIconSm); 610 if (GuiData->hIcon != NULL && GuiData->hIcon != ghDefaultIcon) 611 { 612 DPRINT("Destroy hIcon\n"); 613 DestroyIcon(GuiData->hIcon); 614 } 615 if (GuiData->hIconSm != NULL && GuiData->hIconSm != ghDefaultIconSm) 616 { 617 DPRINT("Destroy hIconSm\n"); 618 DestroyIcon(GuiData->hIconSm); 619 } 620 621 This->Context = NULL; 622 DeleteCriticalSection(&GuiData->Lock); 623 ConsoleFreeHeap(GuiData); 624 625 DPRINT("Quit GuiDeinitFrontEnd\n"); 626 } 627 628 static VOID NTAPI 629 GuiDrawRegion(IN OUT PFRONTEND This, 630 SMALL_RECT* Region) 631 { 632 PGUI_CONSOLE_DATA GuiData = This->Context; 633 634 /* Do nothing if the window is hidden */ 635 if (!GuiData->IsWindowVisible) return; 636 637 DrawRegion(GuiData, Region); 638 } 639 640 static VOID NTAPI 641 GuiWriteStream(IN OUT PFRONTEND This, 642 SMALL_RECT* Region, 643 SHORT CursorStartX, 644 SHORT CursorStartY, 645 UINT ScrolledLines, 646 PWCHAR Buffer, 647 UINT Length) 648 { 649 PGUI_CONSOLE_DATA GuiData = This->Context; 650 PCONSOLE_SCREEN_BUFFER Buff; 651 SHORT CursorEndX, CursorEndY; 652 RECT ScrollRect; 653 654 if (NULL == GuiData || NULL == GuiData->hWindow) return; 655 656 /* Do nothing if the window is hidden */ 657 if (!GuiData->IsWindowVisible) return; 658 659 Buff = GuiData->ActiveBuffer; 660 if (GetType(Buff) != TEXTMODE_BUFFER) return; 661 662 if (0 != ScrolledLines) 663 { 664 ScrollRect.left = 0; 665 ScrollRect.top = 0; 666 ScrollRect.right = Buff->ViewSize.X * GuiData->CharWidth; 667 ScrollRect.bottom = Region->Top * GuiData->CharHeight; 668 669 ScrollWindowEx(GuiData->hWindow, 670 0, 671 -(int)(ScrolledLines * GuiData->CharHeight), 672 &ScrollRect, 673 NULL, 674 NULL, 675 NULL, 676 SW_INVALIDATE); 677 } 678 679 DrawRegion(GuiData, Region); 680 681 if (CursorStartX < Region->Left || Region->Right < CursorStartX 682 || CursorStartY < Region->Top || Region->Bottom < CursorStartY) 683 { 684 InvalidateCell(GuiData, CursorStartX, CursorStartY); 685 } 686 687 CursorEndX = Buff->CursorPosition.X; 688 CursorEndY = Buff->CursorPosition.Y; 689 if ((CursorEndX < Region->Left || Region->Right < CursorEndX 690 || CursorEndY < Region->Top || Region->Bottom < CursorEndY) 691 && (CursorEndX != CursorStartX || CursorEndY != CursorStartY)) 692 { 693 InvalidateCell(GuiData, CursorEndX, CursorEndY); 694 } 695 696 // HACK!! 697 // Set up the update timer (very short interval) - this is a "hack" for getting the OS to 698 // repaint the window without having it just freeze up and stay on the screen permanently. 699 Buff->CursorBlinkOn = TRUE; 700 SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL); 701 } 702 703 /* static */ VOID NTAPI 704 GuiRingBell(IN OUT PFRONTEND This) 705 { 706 PGUI_CONSOLE_DATA GuiData = This->Context; 707 708 /* Emit an error beep sound */ 709 SendNotifyMessage(GuiData->hWindow, PM_CONSOLE_BEEP, 0, 0); 710 } 711 712 static BOOL NTAPI 713 GuiSetCursorInfo(IN OUT PFRONTEND This, 714 PCONSOLE_SCREEN_BUFFER Buff) 715 { 716 PGUI_CONSOLE_DATA GuiData = This->Context; 717 718 /* Do nothing if the window is hidden */ 719 if (!GuiData->IsWindowVisible) return TRUE; 720 721 if (GuiData->ActiveBuffer == Buff) 722 { 723 InvalidateCell(GuiData, Buff->CursorPosition.X, Buff->CursorPosition.Y); 724 } 725 726 return TRUE; 727 } 728 729 static BOOL NTAPI 730 GuiSetScreenInfo(IN OUT PFRONTEND This, 731 PCONSOLE_SCREEN_BUFFER Buff, 732 SHORT OldCursorX, 733 SHORT OldCursorY) 734 { 735 PGUI_CONSOLE_DATA GuiData = This->Context; 736 737 /* Do nothing if the window is hidden */ 738 if (!GuiData->IsWindowVisible) return TRUE; 739 740 if (GuiData->ActiveBuffer == Buff) 741 { 742 /* Redraw char at old position (remove cursor) */ 743 InvalidateCell(GuiData, OldCursorX, OldCursorY); 744 /* Redraw char at new position (show cursor) */ 745 InvalidateCell(GuiData, Buff->CursorPosition.X, Buff->CursorPosition.Y); 746 } 747 748 return TRUE; 749 } 750 751 static VOID NTAPI 752 GuiResizeTerminal(IN OUT PFRONTEND This) 753 { 754 PGUI_CONSOLE_DATA GuiData = This->Context; 755 756 /* Resize the window to the user's values */ 757 PostMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0); 758 } 759 760 static VOID NTAPI 761 GuiSetActiveScreenBuffer(IN OUT PFRONTEND This) 762 { 763 PGUI_CONSOLE_DATA GuiData = This->Context; 764 PCONSOLE_SCREEN_BUFFER ActiveBuffer; 765 HPALETTE hPalette; 766 767 EnterCriticalSection(&GuiData->Lock); 768 GuiData->WindowSizeLock = TRUE; 769 770 InterlockedExchangePointer((PVOID*)&GuiData->ActiveBuffer, 771 ConDrvGetActiveScreenBuffer((PCONSOLE)GuiData->Console)); 772 773 GuiData->WindowSizeLock = FALSE; 774 LeaveCriticalSection(&GuiData->Lock); 775 776 ActiveBuffer = GuiData->ActiveBuffer; 777 778 /* Change the current palette */ 779 if (ActiveBuffer->PaletteHandle == NULL) 780 hPalette = GuiData->hSysPalette; 781 else 782 hPalette = ActiveBuffer->PaletteHandle; 783 784 DPRINT("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette); 785 786 /* Set the new palette for the framebuffer */ 787 SelectPalette(GuiData->hMemDC, hPalette, FALSE); 788 789 /* Specify the use of the system palette for the framebuffer */ 790 SetSystemPaletteUse(GuiData->hMemDC, ActiveBuffer->PaletteUsage); 791 792 /* Realize the (logical) palette */ 793 RealizePalette(GuiData->hMemDC); 794 795 GuiResizeTerminal(This); 796 // ConioDrawConsole(Console); 797 } 798 799 static VOID NTAPI 800 GuiReleaseScreenBuffer(IN OUT PFRONTEND This, 801 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer) 802 { 803 PGUI_CONSOLE_DATA GuiData = This->Context; 804 805 /* 806 * If we were notified to release a screen buffer that is not actually 807 * ours, then just ignore the notification... 808 */ 809 if (ScreenBuffer != GuiData->ActiveBuffer) return; 810 811 /* 812 * ... else, we must release our active buffer. Two cases are present: 813 * - If ScreenBuffer (== GuiData->ActiveBuffer) IS NOT the console 814 * active screen buffer, then we can safely switch to it. 815 * - If ScreenBuffer IS the console active screen buffer, we must release 816 * it ONLY. 817 */ 818 819 /* Release the old active palette and set the default one */ 820 if (GetCurrentObject(GuiData->hMemDC, OBJ_PAL) == ScreenBuffer->PaletteHandle) 821 { 822 /* Set the new palette */ 823 SelectPalette(GuiData->hMemDC, GuiData->hSysPalette, FALSE); 824 } 825 826 /* Set the adequate active screen buffer */ 827 if (ScreenBuffer != GuiData->Console->ActiveBuffer) 828 { 829 GuiSetActiveScreenBuffer(This); 830 } 831 else 832 { 833 EnterCriticalSection(&GuiData->Lock); 834 GuiData->WindowSizeLock = TRUE; 835 836 InterlockedExchangePointer((PVOID*)&GuiData->ActiveBuffer, NULL); 837 838 GuiData->WindowSizeLock = FALSE; 839 LeaveCriticalSection(&GuiData->Lock); 840 } 841 } 842 843 static BOOL NTAPI 844 GuiSetMouseCursor(IN OUT PFRONTEND This, 845 HCURSOR CursorHandle); 846 847 static VOID NTAPI 848 GuiRefreshInternalInfo(IN OUT PFRONTEND This) 849 { 850 PGUI_CONSOLE_DATA GuiData = This->Context; 851 852 /* Update the console leader information held by the window */ 853 SetConWndConsoleLeaderCID(GuiData); 854 855 /* 856 * HACK: 857 * We reset the cursor here so that, when a console app quits, we reset 858 * the cursor to the default one. It's quite a hack since it doesn't proceed 859 * per - console process... This must be fixed. 860 * 861 * See GuiInitConsole(...) for more information. 862 */ 863 864 /* Mouse is shown by default with its default cursor shape */ 865 GuiData->MouseCursorRefCount = 0; // Reinitialize the reference counter 866 GuiSetMouseCursor(This, NULL); 867 } 868 869 static VOID NTAPI 870 GuiChangeTitle(IN OUT PFRONTEND This) 871 { 872 PGUI_CONSOLE_DATA GuiData = This->Context; 873 PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0); 874 } 875 876 static BOOL NTAPI 877 GuiChangeIcon(IN OUT PFRONTEND This, 878 HICON IconHandle) 879 { 880 PGUI_CONSOLE_DATA GuiData = This->Context; 881 HICON hIcon, hIconSm; 882 883 if (IconHandle == NULL) 884 { 885 hIcon = ghDefaultIcon; 886 hIconSm = ghDefaultIconSm; 887 } 888 else 889 { 890 hIcon = CopyIcon(IconHandle); 891 hIconSm = CopyIcon(IconHandle); 892 } 893 894 if (hIcon == NULL) 895 return FALSE; 896 897 if (hIcon != GuiData->hIcon) 898 { 899 if (GuiData->hIcon != NULL && GuiData->hIcon != ghDefaultIcon) 900 { 901 DestroyIcon(GuiData->hIcon); 902 } 903 if (GuiData->hIconSm != NULL && GuiData->hIconSm != ghDefaultIconSm) 904 { 905 DestroyIcon(GuiData->hIconSm); 906 } 907 908 GuiData->hIcon = hIcon; 909 GuiData->hIconSm = hIconSm; 910 911 DPRINT("Set icons in GuiChangeIcon\n"); 912 PostMessageW(GuiData->hWindow, WM_SETICON, ICON_BIG , (LPARAM)GuiData->hIcon ); 913 PostMessageW(GuiData->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)GuiData->hIconSm); 914 } 915 916 return TRUE; 917 } 918 919 static HDESK NTAPI 920 GuiGetThreadConsoleDesktop(IN OUT PFRONTEND This) 921 { 922 PGUI_CONSOLE_DATA GuiData = This->Context; 923 return GuiData->Desktop; 924 } 925 926 static HWND NTAPI 927 GuiGetConsoleWindowHandle(IN OUT PFRONTEND This) 928 { 929 PGUI_CONSOLE_DATA GuiData = This->Context; 930 return GuiData->hWindow; 931 } 932 933 static VOID NTAPI 934 GuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This, 935 PCOORD pSize) 936 { 937 PGUI_CONSOLE_DATA GuiData = This->Context; 938 PCONSOLE_SCREEN_BUFFER ActiveBuffer; 939 HMONITOR hMonitor; 940 MONITORINFO MonitorInfo; 941 LONG Width, Height; 942 UINT WidthUnit, HeightUnit; 943 944 if (!pSize) return; 945 946 /* 947 * Retrieve the monitor that is mostly covered by the current console window; 948 * default to primary monitor otherwise. 949 */ 950 MonitorInfo.cbSize = sizeof(MonitorInfo); 951 hMonitor = MonitorFromWindow(GuiData->hWindow, MONITOR_DEFAULTTOPRIMARY); 952 if (hMonitor && GetMonitorInfoW(hMonitor, &MonitorInfo)) 953 { 954 /* Retrieve the width and height of the client area of this monitor */ 955 Width = MonitorInfo.rcWork.right - MonitorInfo.rcWork.left; 956 Height = MonitorInfo.rcWork.bottom - MonitorInfo.rcWork.top; 957 } 958 else 959 { 960 /* 961 * Retrieve the width and height of the client area for a full-screen 962 * window on the primary display monitor. 963 */ 964 Width = GetSystemMetrics(SM_CXFULLSCREEN); 965 Height = GetSystemMetrics(SM_CYFULLSCREEN); 966 967 // RECT WorkArea; 968 // SystemParametersInfoW(SPI_GETWORKAREA, 0, &WorkArea, 0); 969 // Width = WorkArea.right; 970 // Height = WorkArea.bottom; 971 } 972 973 ActiveBuffer = GuiData->ActiveBuffer; 974 #if 0 975 // NOTE: This would be surprising if we wouldn't have an associated buffer... 976 if (ActiveBuffer) 977 #endif 978 GetScreenBufferSizeUnits(ActiveBuffer, GuiData, &WidthUnit, &HeightUnit); 979 #if 0 980 else 981 /* Default: graphics mode */ 982 WidthUnit = HeightUnit = 1; 983 #endif 984 985 Width -= (2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE))); 986 Height -= (2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION)); 987 988 if (Width < 0) Width = 0; 989 if (Height < 0) Height = 0; 990 991 pSize->X = (SHORT)(Width / (int)WidthUnit ) /* HACK */ + 2; 992 pSize->Y = (SHORT)(Height / (int)HeightUnit) /* HACK */ + 1; 993 } 994 995 static BOOL NTAPI 996 GuiGetSelectionInfo(IN OUT PFRONTEND This, 997 PCONSOLE_SELECTION_INFO pSelectionInfo) 998 { 999 PGUI_CONSOLE_DATA GuiData = This->Context; 1000 1001 if (pSelectionInfo == NULL) return FALSE; 1002 1003 ZeroMemory(pSelectionInfo, sizeof(*pSelectionInfo)); 1004 if (GuiData->Selection.dwFlags != CONSOLE_NO_SELECTION) 1005 RtlCopyMemory(pSelectionInfo, &GuiData->Selection, sizeof(*pSelectionInfo)); 1006 1007 return TRUE; 1008 } 1009 1010 static BOOL NTAPI 1011 GuiSetPalette(IN OUT PFRONTEND This, 1012 HPALETTE PaletteHandle, 1013 UINT PaletteUsage) 1014 { 1015 PGUI_CONSOLE_DATA GuiData = This->Context; 1016 HPALETTE OldPalette; 1017 1018 // if (GetType(GuiData->ActiveBuffer) != GRAPHICS_BUFFER) return FALSE; 1019 if (PaletteHandle == NULL) return FALSE; 1020 1021 /* Set the new palette for the framebuffer */ 1022 OldPalette = SelectPalette(GuiData->hMemDC, PaletteHandle, FALSE); 1023 if (OldPalette == NULL) return FALSE; 1024 1025 /* Specify the use of the system palette for the framebuffer */ 1026 SetSystemPaletteUse(GuiData->hMemDC, PaletteUsage); 1027 1028 /* Realize the (logical) palette */ 1029 RealizePalette(GuiData->hMemDC); 1030 1031 /* Save the original system palette handle */ 1032 if (GuiData->hSysPalette == NULL) GuiData->hSysPalette = OldPalette; 1033 1034 return TRUE; 1035 } 1036 1037 static ULONG NTAPI 1038 GuiGetDisplayMode(IN OUT PFRONTEND This) 1039 { 1040 PGUI_CONSOLE_DATA GuiData = This->Context; 1041 ULONG DisplayMode = 0; 1042 1043 if (GuiData->GuiInfo.FullScreen) 1044 DisplayMode |= CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN 1045 else 1046 DisplayMode |= CONSOLE_WINDOWED; 1047 1048 return DisplayMode; 1049 } 1050 1051 static BOOL NTAPI 1052 GuiSetDisplayMode(IN OUT PFRONTEND This, 1053 ULONG NewMode) 1054 { 1055 PGUI_CONSOLE_DATA GuiData = This->Context; 1056 BOOL FullScreen; 1057 1058 if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE)) 1059 return FALSE; 1060 1061 /* Do nothing if the window is hidden */ 1062 if (!GuiData->IsWindowVisible) return TRUE; 1063 1064 FullScreen = ((NewMode & CONSOLE_FULLSCREEN_MODE) != 0); 1065 1066 if (FullScreen != GuiData->GuiInfo.FullScreen) 1067 { 1068 SwitchFullScreen(GuiData, FullScreen); 1069 } 1070 1071 return TRUE; 1072 } 1073 1074 static INT NTAPI 1075 GuiShowMouseCursor(IN OUT PFRONTEND This, 1076 BOOL Show) 1077 { 1078 PGUI_CONSOLE_DATA GuiData = This->Context; 1079 1080 if (GuiData->IsWindowVisible) 1081 { 1082 /* Set the reference count */ 1083 if (Show) ++GuiData->MouseCursorRefCount; 1084 else --GuiData->MouseCursorRefCount; 1085 1086 /* Effectively show (or hide) the cursor (use special values for (w|l)Param) */ 1087 PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1); 1088 } 1089 1090 return GuiData->MouseCursorRefCount; 1091 } 1092 1093 static BOOL NTAPI 1094 GuiSetMouseCursor(IN OUT PFRONTEND This, 1095 HCURSOR CursorHandle) 1096 { 1097 PGUI_CONSOLE_DATA GuiData = This->Context; 1098 1099 /* Do nothing if the window is hidden */ 1100 if (!GuiData->IsWindowVisible) return TRUE; 1101 1102 /* 1103 * Set the cursor's handle. If the given handle is NULL, 1104 * then restore the default cursor. 1105 */ 1106 GuiData->hCursor = (CursorHandle ? CursorHandle : ghDefaultCursor); 1107 1108 /* Effectively modify the shape of the cursor (use special values for (w|l)Param) */ 1109 PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1); 1110 1111 return TRUE; 1112 } 1113 1114 static HMENU NTAPI 1115 GuiMenuControl(IN OUT PFRONTEND This, 1116 UINT CmdIdLow, 1117 UINT CmdIdHigh) 1118 { 1119 PGUI_CONSOLE_DATA GuiData = This->Context; 1120 1121 GuiData->CmdIdLow = CmdIdLow ; 1122 GuiData->CmdIdHigh = CmdIdHigh; 1123 1124 return GuiData->hSysMenu; 1125 } 1126 1127 static BOOL NTAPI 1128 GuiSetMenuClose(IN OUT PFRONTEND This, 1129 BOOL Enable) 1130 { 1131 /* 1132 * NOTE: See http://www.mail-archive.com/harbour@harbour-project.org/msg27509.html 1133 * or http://harbour-devel.1590103.n2.nabble.com/Question-about-hb-gt-win-CtrlHandler-usage-td4670862i20.html 1134 * for more information. 1135 */ 1136 1137 PGUI_CONSOLE_DATA GuiData = This->Context; 1138 1139 if (GuiData->hSysMenu == NULL) return FALSE; 1140 1141 GuiData->IsCloseButtonEnabled = Enable; 1142 EnableMenuItem(GuiData->hSysMenu, SC_CLOSE, MF_BYCOMMAND | (Enable ? MF_ENABLED : MF_GRAYED)); 1143 1144 return TRUE; 1145 } 1146 1147 static FRONTEND_VTBL GuiVtbl = 1148 { 1149 GuiInitFrontEnd, 1150 GuiDeinitFrontEnd, 1151 GuiDrawRegion, 1152 GuiWriteStream, 1153 GuiRingBell, 1154 GuiSetCursorInfo, 1155 GuiSetScreenInfo, 1156 GuiResizeTerminal, 1157 GuiSetActiveScreenBuffer, 1158 GuiReleaseScreenBuffer, 1159 GuiRefreshInternalInfo, 1160 GuiChangeTitle, 1161 GuiChangeIcon, 1162 GuiGetThreadConsoleDesktop, 1163 GuiGetConsoleWindowHandle, 1164 GuiGetLargestConsoleWindowSize, 1165 GuiGetSelectionInfo, 1166 GuiSetPalette, 1167 GuiGetDisplayMode, 1168 GuiSetDisplayMode, 1169 GuiShowMouseCursor, 1170 GuiSetMouseCursor, 1171 GuiMenuControl, 1172 GuiSetMenuClose, 1173 }; 1174 1175 1176 NTSTATUS NTAPI 1177 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, 1178 IN OUT PCONSOLE_STATE_INFO ConsoleInfo, 1179 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, 1180 IN HANDLE ConsoleLeaderProcessHandle) 1181 { 1182 PCONSOLE_START_INFO ConsoleStartInfo; 1183 PGUI_INIT_INFO GuiInitInfo; 1184 USEROBJECTFLAGS UserObjectFlags; 1185 1186 if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL) 1187 return STATUS_INVALID_PARAMETER; 1188 1189 ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo; 1190 1191 /* 1192 * Initialize a private initialization info structure for later use. 1193 * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd. 1194 */ 1195 GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiInitInfo)); 1196 if (GuiInitInfo == NULL) return STATUS_NO_MEMORY; 1197 1198 /* Initialize GUI terminal emulator common functionalities */ 1199 if (!GuiInit(ConsoleInitInfo, ConsoleLeaderProcessHandle, GuiInitInfo)) 1200 { 1201 ConsoleFreeHeap(GuiInitInfo); 1202 return STATUS_UNSUCCESSFUL; 1203 } 1204 1205 GuiInitInfo->IsWindowVisible = ConsoleInitInfo->IsWindowVisible; 1206 if (GuiInitInfo->IsWindowVisible) 1207 { 1208 /* Don't show the console if the window station is not interactive */ 1209 if (GetUserObjectInformationW(GuiInitInfo->WinSta, 1210 UOI_FLAGS, 1211 &UserObjectFlags, 1212 sizeof(UserObjectFlags), 1213 NULL)) 1214 { 1215 if (!(UserObjectFlags.dwFlags & WSF_VISIBLE)) 1216 GuiInitInfo->IsWindowVisible = FALSE; 1217 } 1218 } 1219 1220 /* 1221 * Load terminal settings 1222 */ 1223 #if 0 1224 /* Impersonate the caller in order to retrieve settings in its context */ 1225 // if (!CsrImpersonateClient(NULL)) 1226 // return STATUS_UNSUCCESSFUL; 1227 CsrImpersonateClient(NULL); 1228 1229 /* 1. Load the default settings */ 1230 GuiConsoleGetDefaultSettings(&GuiInitInfo->TermInfo); 1231 #endif 1232 1233 GuiInitInfo->TermInfo.ShowWindow = SW_SHOWNORMAL; 1234 1235 if (GuiInitInfo->IsWindowVisible) 1236 { 1237 /* 2. Load the remaining console settings via the registry */ 1238 if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) 1239 { 1240 #if 0 1241 /* Load the terminal information from the registry */ 1242 GuiConsoleReadUserSettings(&GuiInitInfo->TermInfo); 1243 #endif 1244 1245 /* 1246 * Now, update them with the properties the user might gave to us 1247 * via the STARTUPINFO structure before calling CreateProcess 1248 * (and which was transmitted via the ConsoleStartInfo structure). 1249 * We therefore overwrite the values read in the registry. 1250 */ 1251 if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW) 1252 { 1253 GuiInitInfo->TermInfo.ShowWindow = ConsoleStartInfo->wShowWindow; 1254 } 1255 if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION) 1256 { 1257 ConsoleInfo->AutoPosition = FALSE; 1258 ConsoleInfo->WindowPosition.x = ConsoleStartInfo->dwWindowOrigin.X; 1259 ConsoleInfo->WindowPosition.y = ConsoleStartInfo->dwWindowOrigin.Y; 1260 } 1261 if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN) 1262 { 1263 ConsoleInfo->FullScreen = TRUE; 1264 } 1265 } 1266 } 1267 1268 #if 0 1269 /* Revert impersonation */ 1270 CsrRevertToSelf(); 1271 #endif 1272 1273 // Font data 1274 StringCchCopyNW(GuiInitInfo->TermInfo.FaceName, ARRAYSIZE(GuiInitInfo->TermInfo.FaceName), 1275 ConsoleInfo->FaceName, ARRAYSIZE(ConsoleInfo->FaceName)); 1276 GuiInitInfo->TermInfo.FontFamily = ConsoleInfo->FontFamily; 1277 GuiInitInfo->TermInfo.FontSize = ConsoleInfo->FontSize; 1278 GuiInitInfo->TermInfo.FontWeight = ConsoleInfo->FontWeight; 1279 1280 // Display 1281 GuiInitInfo->TermInfo.FullScreen = ConsoleInfo->FullScreen; 1282 GuiInitInfo->TermInfo.AutoPosition = ConsoleInfo->AutoPosition; 1283 GuiInitInfo->TermInfo.WindowOrigin = ConsoleInfo->WindowPosition; 1284 1285 /* Initialize the icon handles */ 1286 // if (ConsoleStartInfo->hIcon != NULL) 1287 GuiInitInfo->hIcon = ConsoleStartInfo->hIcon; 1288 // else 1289 // GuiInitInfo->hIcon = ghDefaultIcon; 1290 1291 // if (ConsoleStartInfo->hIconSm != NULL) 1292 GuiInitInfo->hIconSm = ConsoleStartInfo->hIconSm; 1293 // else 1294 // GuiInitInfo->hIconSm = ghDefaultIconSm; 1295 1296 // ASSERT(GuiInitInfo->hIcon && GuiInitInfo->hIconSm); 1297 1298 /* Finally, initialize the frontend structure */ 1299 FrontEnd->Vtbl = &GuiVtbl; 1300 FrontEnd->Context = NULL; 1301 FrontEnd->Context2 = GuiInitInfo; 1302 1303 return STATUS_SUCCESS; 1304 } 1305 1306 NTSTATUS NTAPI 1307 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd) 1308 { 1309 if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER; 1310 1311 if (FrontEnd->Context ) GuiDeinitFrontEnd(FrontEnd); 1312 if (FrontEnd->Context2) ConsoleFreeHeap(FrontEnd->Context2); 1313 1314 return STATUS_SUCCESS; 1315 } 1316 1317 /* EOF */ 1318