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