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