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