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