[WIN32K:NTUSER] Make NtUserResolveDesktop() and IntResolveDesktop() work in a more...
[reactos.git] / win32ss / user / winsrv / consrv / frontends / gui / guiterm.c
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 SetWindowTextW(GuiData->hWindow, GuiData->Console->Title.Buffer);
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 HWND NTAPI
916 GuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
917 {
918 PGUI_CONSOLE_DATA GuiData = This->Context;
919 return GuiData->hWindow;
920 }
921
922 static VOID NTAPI
923 GuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
924 PCOORD pSize)
925 {
926 PGUI_CONSOLE_DATA GuiData = This->Context;
927 PCONSOLE_SCREEN_BUFFER ActiveBuffer;
928 HMONITOR hMonitor;
929 MONITORINFO MonitorInfo;
930 LONG Width, Height;
931 UINT WidthUnit, HeightUnit;
932
933 if (!pSize) return;
934
935 /*
936 * Retrieve the monitor that is mostly covered by the current console window;
937 * default to primary monitor otherwise.
938 */
939 MonitorInfo.cbSize = sizeof(MonitorInfo);
940 hMonitor = MonitorFromWindow(GuiData->hWindow, MONITOR_DEFAULTTOPRIMARY);
941 if (hMonitor && GetMonitorInfoW(hMonitor, &MonitorInfo))
942 {
943 /* Retrieve the width and height of the client area of this monitor */
944 Width = MonitorInfo.rcWork.right - MonitorInfo.rcWork.left;
945 Height = MonitorInfo.rcWork.bottom - MonitorInfo.rcWork.top;
946 }
947 else
948 {
949 /*
950 * Retrieve the width and height of the client area for a full-screen
951 * window on the primary display monitor.
952 */
953 Width = GetSystemMetrics(SM_CXFULLSCREEN);
954 Height = GetSystemMetrics(SM_CYFULLSCREEN);
955
956 // RECT WorkArea;
957 // SystemParametersInfoW(SPI_GETWORKAREA, 0, &WorkArea, 0);
958 // Width = WorkArea.right;
959 // Height = WorkArea.bottom;
960 }
961
962 ActiveBuffer = GuiData->ActiveBuffer;
963 #if 0
964 // NOTE: This would be surprising if we wouldn't have an associated buffer...
965 if (ActiveBuffer)
966 #endif
967 GetScreenBufferSizeUnits(ActiveBuffer, GuiData, &WidthUnit, &HeightUnit);
968 #if 0
969 else
970 /* Default: graphics mode */
971 WidthUnit = HeightUnit = 1;
972 #endif
973
974 Width -= (2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)));
975 Height -= (2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION));
976
977 if (Width < 0) Width = 0;
978 if (Height < 0) Height = 0;
979
980 pSize->X = (SHORT)(Width / (int)WidthUnit ) /* HACK */ + 2;
981 pSize->Y = (SHORT)(Height / (int)HeightUnit) /* HACK */ + 1;
982 }
983
984 static BOOL NTAPI
985 GuiGetSelectionInfo(IN OUT PFRONTEND This,
986 PCONSOLE_SELECTION_INFO pSelectionInfo)
987 {
988 PGUI_CONSOLE_DATA GuiData = This->Context;
989
990 if (pSelectionInfo == NULL) return FALSE;
991
992 ZeroMemory(pSelectionInfo, sizeof(*pSelectionInfo));
993 if (GuiData->Selection.dwFlags != CONSOLE_NO_SELECTION)
994 RtlCopyMemory(pSelectionInfo, &GuiData->Selection, sizeof(*pSelectionInfo));
995
996 return TRUE;
997 }
998
999 static BOOL NTAPI
1000 GuiSetPalette(IN OUT PFRONTEND This,
1001 HPALETTE PaletteHandle,
1002 UINT PaletteUsage)
1003 {
1004 PGUI_CONSOLE_DATA GuiData = This->Context;
1005 HPALETTE OldPalette;
1006
1007 // if (GetType(GuiData->ActiveBuffer) != GRAPHICS_BUFFER) return FALSE;
1008 if (PaletteHandle == NULL) return FALSE;
1009
1010 /* Set the new palette for the framebuffer */
1011 OldPalette = SelectPalette(GuiData->hMemDC, PaletteHandle, FALSE);
1012 if (OldPalette == NULL) return FALSE;
1013
1014 /* Specify the use of the system palette for the framebuffer */
1015 SetSystemPaletteUse(GuiData->hMemDC, PaletteUsage);
1016
1017 /* Realize the (logical) palette */
1018 RealizePalette(GuiData->hMemDC);
1019
1020 /* Save the original system palette handle */
1021 if (GuiData->hSysPalette == NULL) GuiData->hSysPalette = OldPalette;
1022
1023 return TRUE;
1024 }
1025
1026 static ULONG NTAPI
1027 GuiGetDisplayMode(IN OUT PFRONTEND This)
1028 {
1029 PGUI_CONSOLE_DATA GuiData = This->Context;
1030 ULONG DisplayMode = 0;
1031
1032 if (GuiData->GuiInfo.FullScreen)
1033 DisplayMode |= CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN
1034 else
1035 DisplayMode |= CONSOLE_WINDOWED;
1036
1037 return DisplayMode;
1038 }
1039
1040 static BOOL NTAPI
1041 GuiSetDisplayMode(IN OUT PFRONTEND This,
1042 ULONG NewMode)
1043 {
1044 PGUI_CONSOLE_DATA GuiData = This->Context;
1045 BOOL FullScreen;
1046
1047 if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
1048 return FALSE;
1049
1050 /* Do nothing if the window is hidden */
1051 if (!GuiData->IsWindowVisible) return TRUE;
1052
1053 FullScreen = ((NewMode & CONSOLE_FULLSCREEN_MODE) != 0);
1054
1055 if (FullScreen != GuiData->GuiInfo.FullScreen)
1056 {
1057 SwitchFullScreen(GuiData, FullScreen);
1058 }
1059
1060 return TRUE;
1061 }
1062
1063 static INT NTAPI
1064 GuiShowMouseCursor(IN OUT PFRONTEND This,
1065 BOOL Show)
1066 {
1067 PGUI_CONSOLE_DATA GuiData = This->Context;
1068
1069 if (GuiData->IsWindowVisible)
1070 {
1071 /* Set the reference count */
1072 if (Show) ++GuiData->MouseCursorRefCount;
1073 else --GuiData->MouseCursorRefCount;
1074
1075 /* Effectively show (or hide) the cursor (use special values for (w|l)Param) */
1076 PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
1077 }
1078
1079 return GuiData->MouseCursorRefCount;
1080 }
1081
1082 static BOOL NTAPI
1083 GuiSetMouseCursor(IN OUT PFRONTEND This,
1084 HCURSOR CursorHandle)
1085 {
1086 PGUI_CONSOLE_DATA GuiData = This->Context;
1087
1088 /* Do nothing if the window is hidden */
1089 if (!GuiData->IsWindowVisible) return TRUE;
1090
1091 /*
1092 * Set the cursor's handle. If the given handle is NULL,
1093 * then restore the default cursor.
1094 */
1095 GuiData->hCursor = (CursorHandle ? CursorHandle : ghDefaultCursor);
1096
1097 /* Effectively modify the shape of the cursor (use special values for (w|l)Param) */
1098 PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
1099
1100 return TRUE;
1101 }
1102
1103 static HMENU NTAPI
1104 GuiMenuControl(IN OUT PFRONTEND This,
1105 UINT CmdIdLow,
1106 UINT CmdIdHigh)
1107 {
1108 PGUI_CONSOLE_DATA GuiData = This->Context;
1109
1110 GuiData->CmdIdLow = CmdIdLow ;
1111 GuiData->CmdIdHigh = CmdIdHigh;
1112
1113 return GetSystemMenu(GuiData->hWindow, FALSE);
1114 }
1115
1116 static BOOL NTAPI
1117 GuiSetMenuClose(IN OUT PFRONTEND This,
1118 BOOL Enable)
1119 {
1120 /*
1121 * NOTE: See http://www.mail-archive.com/harbour@harbour-project.org/msg27509.html
1122 * or http://harbour-devel.1590103.n2.nabble.com/Question-about-hb-gt-win-CtrlHandler-usage-td4670862i20.html
1123 * for more information.
1124 */
1125
1126 PGUI_CONSOLE_DATA GuiData = This->Context;
1127 HMENU hSysMenu = GetSystemMenu(GuiData->hWindow, FALSE);
1128
1129 if (hSysMenu == NULL) return FALSE;
1130
1131 GuiData->IsCloseButtonEnabled = Enable;
1132 EnableMenuItem(hSysMenu, SC_CLOSE, MF_BYCOMMAND | (Enable ? MF_ENABLED : MF_GRAYED));
1133
1134 return TRUE;
1135 }
1136
1137 static FRONTEND_VTBL GuiVtbl =
1138 {
1139 GuiInitFrontEnd,
1140 GuiDeinitFrontEnd,
1141 GuiDrawRegion,
1142 GuiWriteStream,
1143 GuiRingBell,
1144 GuiSetCursorInfo,
1145 GuiSetScreenInfo,
1146 GuiResizeTerminal,
1147 GuiSetActiveScreenBuffer,
1148 GuiReleaseScreenBuffer,
1149 GuiRefreshInternalInfo,
1150 GuiChangeTitle,
1151 GuiChangeIcon,
1152 GuiGetConsoleWindowHandle,
1153 GuiGetLargestConsoleWindowSize,
1154 GuiGetSelectionInfo,
1155 GuiSetPalette,
1156 GuiGetDisplayMode,
1157 GuiSetDisplayMode,
1158 GuiShowMouseCursor,
1159 GuiSetMouseCursor,
1160 GuiMenuControl,
1161 GuiSetMenuClose,
1162 };
1163
1164
1165 NTSTATUS NTAPI
1166 GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
1167 IN OUT PCONSOLE_STATE_INFO ConsoleInfo,
1168 IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
1169 IN HANDLE ConsoleLeaderProcessHandle)
1170 {
1171 PCONSOLE_START_INFO ConsoleStartInfo;
1172 PGUI_INIT_INFO GuiInitInfo;
1173 USEROBJECTFLAGS UserObjectFlags;
1174
1175 if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL)
1176 return STATUS_INVALID_PARAMETER;
1177
1178 ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo;
1179
1180 /*
1181 * Initialize a private initialization info structure for later use.
1182 * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
1183 */
1184 GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiInitInfo));
1185 if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
1186
1187 /* Initialize GUI terminal emulator common functionalities */
1188 if (!GuiInit(ConsoleInitInfo, ConsoleLeaderProcessHandle, GuiInitInfo))
1189 {
1190 ConsoleFreeHeap(GuiInitInfo);
1191 return STATUS_UNSUCCESSFUL;
1192 }
1193
1194 GuiInitInfo->IsWindowVisible = ConsoleInitInfo->IsWindowVisible;
1195 if (GuiInitInfo->IsWindowVisible)
1196 {
1197 /* Don't show the console if the window station is not interactive */
1198 if (GetUserObjectInformationW(GuiInitInfo->WinSta,
1199 UOI_FLAGS,
1200 &UserObjectFlags,
1201 sizeof(UserObjectFlags),
1202 NULL))
1203 {
1204 if (!(UserObjectFlags.dwFlags & WSF_VISIBLE))
1205 GuiInitInfo->IsWindowVisible = FALSE;
1206 }
1207 }
1208
1209 /*
1210 * Load terminal settings
1211 */
1212 #if 0
1213 /* Impersonate the caller in order to retrieve settings in its context */
1214 // if (!CsrImpersonateClient(NULL))
1215 // return STATUS_UNSUCCESSFUL;
1216 CsrImpersonateClient(NULL);
1217
1218 /* 1. Load the default settings */
1219 GuiConsoleGetDefaultSettings(&GuiInitInfo->TermInfo);
1220 #endif
1221
1222 GuiInitInfo->TermInfo.ShowWindow = SW_SHOWNORMAL;
1223
1224 if (GuiInitInfo->IsWindowVisible)
1225 {
1226 /* 2. Load the remaining console settings via the registry */
1227 if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
1228 {
1229 #if 0
1230 /* Load the terminal infos from the registry */
1231 GuiConsoleReadUserSettings(&GuiInitInfo->TermInfo);
1232 #endif
1233
1234 /*
1235 * Now, update them with the properties the user might gave to us
1236 * via the STARTUPINFO structure before calling CreateProcess
1237 * (and which was transmitted via the ConsoleStartInfo structure).
1238 * We therefore overwrite the values read in the registry.
1239 */
1240 if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW)
1241 {
1242 GuiInitInfo->TermInfo.ShowWindow = ConsoleStartInfo->wShowWindow;
1243 }
1244 if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
1245 {
1246 ConsoleInfo->AutoPosition = FALSE;
1247 ConsoleInfo->WindowPosition.x = ConsoleStartInfo->dwWindowOrigin.X;
1248 ConsoleInfo->WindowPosition.y = ConsoleStartInfo->dwWindowOrigin.Y;
1249 }
1250 if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
1251 {
1252 ConsoleInfo->FullScreen = TRUE;
1253 }
1254 }
1255 }
1256
1257 #if 0
1258 /* Revert impersonation */
1259 CsrRevertToSelf();
1260 #endif
1261
1262 // Font data
1263 StringCchCopyNW(GuiInitInfo->TermInfo.FaceName, ARRAYSIZE(GuiInitInfo->TermInfo.FaceName),
1264 ConsoleInfo->FaceName, ARRAYSIZE(ConsoleInfo->FaceName));
1265 GuiInitInfo->TermInfo.FontFamily = ConsoleInfo->FontFamily;
1266 GuiInitInfo->TermInfo.FontSize = ConsoleInfo->FontSize;
1267 GuiInitInfo->TermInfo.FontWeight = ConsoleInfo->FontWeight;
1268
1269 // Display
1270 GuiInitInfo->TermInfo.FullScreen = ConsoleInfo->FullScreen;
1271 GuiInitInfo->TermInfo.AutoPosition = ConsoleInfo->AutoPosition;
1272 GuiInitInfo->TermInfo.WindowOrigin = ConsoleInfo->WindowPosition;
1273
1274 /* Initialize the icon handles */
1275 // if (ConsoleStartInfo->hIcon != NULL)
1276 GuiInitInfo->hIcon = ConsoleStartInfo->hIcon;
1277 // else
1278 // GuiInitInfo->hIcon = ghDefaultIcon;
1279
1280 // if (ConsoleStartInfo->hIconSm != NULL)
1281 GuiInitInfo->hIconSm = ConsoleStartInfo->hIconSm;
1282 // else
1283 // GuiInitInfo->hIconSm = ghDefaultIconSm;
1284
1285 // ASSERT(GuiInitInfo->hIcon && GuiInitInfo->hIconSm);
1286
1287 /* Finally, initialize the frontend structure */
1288 FrontEnd->Vtbl = &GuiVtbl;
1289 FrontEnd->Context = NULL;
1290 FrontEnd->Context2 = GuiInitInfo;
1291
1292 return STATUS_SUCCESS;
1293 }
1294
1295 NTSTATUS NTAPI
1296 GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd)
1297 {
1298 if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
1299
1300 if (FrontEnd->Context ) GuiDeinitFrontEnd(FrontEnd);
1301 if (FrontEnd->Context2) ConsoleFreeHeap(FrontEnd->Context2);
1302
1303 return STATUS_SUCCESS;
1304 }
1305
1306 /* EOF */