#include <consrv.h>
-#define COBJMACROS
-#include <shlobj.h>
-
#define NDEBUG
#include <debug.h>
#define CONGUI_UPDATE_TIME 0
#define CONGUI_UPDATE_TIMER 1
-#define PM_CREATE_CONSOLE (WM_APP + 1)
-#define PM_DESTROY_CONSOLE (WM_APP + 2)
-
-
-/* Not defined in any header file */
-extern VOID NTAPI PrivateCsrssManualGuiCheck(LONG Check);
-// See winsrv/usersrv/init.c line 234
+#define PM_CREATE_CONSOLE (WM_APP + 1)
+#define PM_DESTROY_CONSOLE (WM_APP + 2)
/* GLOBALS ********************************************************************/
typedef struct _GUI_INIT_INFO
{
- PCONSOLE_INFO ConsoleInfo;
- PCONSOLE_START_INFO ConsoleStartInfo;
- ULONG ProcessId;
+ HANDLE GuiThreadStartupEvent;
+ ULONG_PTR InputThreadId;
+ HWINSTA WinSta;
+ HDESK Desktop;
+ HICON hIcon;
+ HICON hIconSm;
+ BOOLEAN IsWindowVisible;
+ GUI_CONSOLE_INFO TermInfo;
} GUI_INIT_INFO, *PGUI_INIT_INFO;
-static BOOL ConsInitialized = FALSE;
-static HWND NotifyWnd = NULL;
+static BOOL ConsInitialized = FALSE;
extern HICON ghDefaultIcon;
extern HICON ghDefaultIconSm;
/* FUNCTIONS ******************************************************************/
-static VOID
-GetScreenBufferSizeUnits(IN PCONSOLE_SCREEN_BUFFER Buffer,
- IN PGUI_CONSOLE_DATA GuiData,
- OUT PUINT WidthUnit,
- OUT PUINT HeightUnit)
-{
- if (Buffer == NULL || GuiData == NULL ||
- WidthUnit == NULL || HeightUnit == NULL)
- {
- return;
- }
-
- if (GetType(Buffer) == TEXTMODE_BUFFER)
- {
- *WidthUnit = GuiData->CharWidth ;
- *HeightUnit = GuiData->CharHeight;
- }
- else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
- {
- *WidthUnit = 1;
- *HeightUnit = 1;
- }
-}
-
VOID
GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData)
{
}
}
-static VOID
-SmallRectToRect(PGUI_CONSOLE_DATA GuiData, PRECT Rect, PSMALL_RECT SmallRect)
-{
- PCONSOLE_SCREEN_BUFFER Buffer = GuiData->ActiveBuffer;
- UINT WidthUnit, HeightUnit;
-
- GetScreenBufferSizeUnits(Buffer, GuiData, &WidthUnit, &HeightUnit);
-
- Rect->left = (SmallRect->Left - Buffer->ViewOrigin.X) * WidthUnit ;
- Rect->top = (SmallRect->Top - Buffer->ViewOrigin.Y) * HeightUnit;
- Rect->right = (SmallRect->Right + 1 - Buffer->ViewOrigin.X) * WidthUnit ;
- Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ViewOrigin.Y) * HeightUnit;
-}
-
static VOID
DrawRegion(PGUI_CONSOLE_DATA GuiData,
SMALL_RECT* Region)
SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen);
VOID
CreateSysMenu(HWND hWnd);
-static LRESULT CALLBACK
-GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+
+static ULONG NTAPI
+GuiConsoleInputThread(PVOID Param)
{
- HWND NewWindow;
- LONG WindowCount;
- MSG Msg;
+ NTSTATUS Status;
+ PCSR_THREAD pcsrt = NULL;
+ PGUI_INIT_INFO GuiInitInfo = (PGUI_INIT_INFO)Param;
+ DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo;
+ ULONG_PTR InputThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
+ HANDLE hThread = NULL;
+
+ LONG WindowCount = 0;
+ MSG msg;
+
+ /*
+ * This thread dispatches all the console notifications to the
+ * notification window. It is common for all the console windows
+ * in a given desktop in a window station.
+ */
+
+ /* Assign this console input thread to this desktop */
+ DesktopConsoleThreadInfo.DesktopHandle = GuiInitInfo->Desktop; // Duplicated desktop handle
+ DesktopConsoleThreadInfo.ThreadId = InputThreadId;
+ Status = NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+ &DesktopConsoleThreadInfo,
+ sizeof(DesktopConsoleThreadInfo));
+ if (!NT_SUCCESS(Status)) goto Quit;
+
+ /* Connect this CSR thread to the USER subsystem */
+ pcsrt = CsrConnectToUser();
+ if (pcsrt == NULL) goto Quit;
+ hThread = pcsrt->ThreadHandle;
+
+ /* Assign the desktop to this thread */
+ if (!SetThreadDesktop(DesktopConsoleThreadInfo.DesktopHandle)) goto Quit;
- switch (msg)
+ /* The thread has been initialized, set the event */
+ NtSetEvent(GuiInitInfo->GuiThreadStartupEvent, NULL);
+ Status = STATUS_SUCCESS;
+
+ while (GetMessageW(&msg, NULL, 0, 0))
{
- case WM_CREATE:
- {
- SetWindowLongW(hWnd, GWL_USERDATA, 0);
- return 0;
- }
-
- case PM_CREATE_CONSOLE:
+ switch (msg.message)
{
- PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
- PCONSRV_CONSOLE Console = GuiData->Console;
- RECT rcWnd;
-
- DPRINT("PM_CREATE_CONSOLE -- creating window\n");
-
- NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE,
- GUI_CONWND_CLASS,
- Console->Title.Buffer,
- WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- NULL,
- ConSrvDllInstance,
- (PVOID)GuiData);
- if (NULL != NewWindow)
+ case PM_CREATE_CONSOLE:
{
+ PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)msg.lParam;
+ PCONSRV_CONSOLE Console = GuiData->Console;
+ HWND NewWindow;
+ RECT rcWnd;
+
+ DPRINT("PM_CREATE_CONSOLE -- creating window\n");
+
+ NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE,
+ GUI_CONWND_CLASS,
+ Console->Title.Buffer,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ GuiData->IsWindowVisible ? HWND_DESKTOP : HWND_MESSAGE,
+ NULL,
+ ConSrvDllInstance,
+ (PVOID)GuiData);
+ if (NewWindow == NULL)
+ {
+ DPRINT1("Failed to create a new console window\n");
+ continue;
+ }
+
ASSERT(NewWindow == GuiData->hWindow);
- WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
- WindowCount++;
- SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
+ InterlockedIncrement(&WindowCount);
//
// FIXME: TODO: Move everything there into conwnd.c!OnNcCreate()
GuiData->GuiInfo.WindowOrigin.x = rcWnd.left;
GuiData->GuiInfo.WindowOrigin.y = rcWnd.top;
- /* Move and resize the window to the user's values */
- /* CAN WE DEADLOCK ?? */
- GuiConsoleMoveWindow(GuiData); // FIXME: This MUST be done via the CreateWindowExW call.
- SendMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
+ if (GuiData->IsWindowVisible)
+ {
+ /* Move and resize the window to the user's values */
+ /* CAN WE DEADLOCK ?? */
+ GuiConsoleMoveWindow(GuiData); // FIXME: This MUST be done via the CreateWindowExW call.
+ SendMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
+ }
// FIXME: HACK: Potential HACK for CORE-8129; see revision 63595.
CreateSysMenu(GuiData->hWindow);
- /* Switch to full-screen mode if necessary */
- // FIXME: Move elsewhere, it cause misdrawings of the window.
- if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE);
+ if (GuiData->IsWindowVisible)
+ {
+ /* Switch to full-screen mode if necessary */
+ // FIXME: Move elsewhere, it cause misdrawings of the window.
+ if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE);
+
+ DPRINT("PM_CREATE_CONSOLE -- showing window\n");
+ // ShowWindow(NewWindow, (int)GuiData->GuiInfo.ShowWindow);
+ ShowWindowAsync(NewWindow, (int)GuiData->GuiInfo.ShowWindow);
+ DPRINT("Window showed\n");
+ }
+ else
+ {
+ DPRINT("PM_CREATE_CONSOLE -- hidden window\n");
+ ShowWindowAsync(NewWindow, SW_HIDE);
+ }
- DPRINT("PM_CREATE_CONSOLE -- showing window\n");
- // ShowWindow(NewWindow, (int)wParam);
- ShowWindowAsync(NewWindow, (int)wParam);
- DPRINT("Window showed\n");
+ continue;
}
- return (LRESULT)NewWindow;
- }
-
- case PM_DESTROY_CONSOLE:
- {
- PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
-
- /* Exit the full screen mode if it was already set */
- // LeaveFullScreen(GuiData);
-
- /*
- * Window creation is done using a PostMessage(), so it's possible
- * that the window that we want to destroy doesn't exist yet.
- * So first empty the message queue.
- */
- /*
- while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
+ case PM_DESTROY_CONSOLE:
{
- TranslateMessage(&Msg);
- DispatchMessageW(&Msg);
- }*/
- while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) ;
+ PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)msg.lParam;
+ MSG TempMsg;
+
+ /* Exit the full screen mode if it was already set */
+ // LeaveFullScreen(GuiData);
+
+ /*
+ * Window creation is done using a PostMessage(), so it's possible
+ * that the window that we want to destroy doesn't exist yet.
+ * So first empty the message queue.
+ */
+ while (PeekMessageW(&TempMsg, NULL, 0, 0, PM_REMOVE))
+ {
+ DispatchMessageW(&TempMsg);
+ }
+
+ if (GuiData->hWindow == NULL) continue;
- if (GuiData->hWindow != NULL) /* && DestroyWindow(GuiData->hWindow) */
- {
DestroyWindow(GuiData->hWindow);
- WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
- WindowCount--;
- SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
- if (0 == WindowCount)
+ NtSetEvent(GuiData->hGuiTermEvent, NULL);
+
+ if (InterlockedDecrement(&WindowCount) == 0)
{
- NotifyWnd = NULL;
- DestroyWindow(hWnd);
- DPRINT("CONSRV: Going to quit the Gui Thread!!\n");
- PostQuitMessage(0);
+ DPRINT("CONSRV: Going to quit the Input Thread 0x%p\n", InputThreadId);
+ goto Quit;
}
- }
- return 0;
+ continue;
+ }
}
- default:
- return DefWindowProcW(hWnd, msg, wParam, lParam);
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+
+Quit:
+ DPRINT("CONSRV: Quit the Input Thread 0x%p, Status = 0x%08lx\n", InputThreadId, Status);
+
+ /* Remove this console input thread from this desktop */
+ // DesktopConsoleThreadInfo.DesktopHandle;
+ DesktopConsoleThreadInfo.ThreadId = 0;
+ NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+ &DesktopConsoleThreadInfo,
+ sizeof(DesktopConsoleThreadInfo));
+
+ /* Close the duplicated desktop handle */
+ CloseDesktop(DesktopConsoleThreadInfo.DesktopHandle); // NtUserCloseDesktop
+
+ /* Cleanup CSR thread */
+ if (pcsrt)
+ {
+ if (hThread != pcsrt->ThreadHandle)
+ DPRINT1("WARNING!! hThread (0x%p) != pcsrt->ThreadHandle (0x%p), you may expect crashes soon!!\n", hThread, pcsrt->ThreadHandle);
+
+ CsrDereferenceThread(pcsrt);
}
+
+ /* Exit the thread */
+ RtlExitUserThread(Status);
+ return 0;
}
-static DWORD NTAPI
-GuiConsoleGuiThread(PVOID Data)
+// FIXME: Maybe return a NTSTATUS
+static BOOL
+GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo,
+ IN HANDLE ConsoleLeaderProcessHandle,
+ IN OUT PGUI_INIT_INFO GuiInitInfo)
{
- MSG msg;
- PHANDLE GraphicsStartupEvent = (PHANDLE)Data;
+ BOOL Success = TRUE;
+ UNICODE_STRING DesktopPath;
+ DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo;
+ HWINSTA hWinSta;
+ HDESK hDesk;
+
+ NTSTATUS Status;
+ HANDLE hInputThread;
+ CLIENT_ID ClientId;
/*
- * This thread dispatches all the console notifications to the notify window.
- * It is common for all the console windows.
+ * Initialize and register the console window class, if needed.
*/
-
- PrivateCsrssManualGuiCheck(+1);
-
- NotifyWnd = CreateWindowW(L"ConSrvCreateNotify",
- L"",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- NULL,
- ConSrvDllInstance,
- NULL);
- if (NULL == NotifyWnd)
+ if (!ConsInitialized)
{
- PrivateCsrssManualGuiCheck(-1);
- SetEvent(*GraphicsStartupEvent);
- return 1;
+ if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE;
+ ConsInitialized = TRUE;
}
- SetEvent(*GraphicsStartupEvent);
+ /*
+ * Set-up the console input thread. We have
+ * one console input thread per desktop.
+ */
- while (GetMessageW(&msg, NULL, 0, 0))
+ if (!CsrImpersonateClient(NULL))
+ // return STATUS_BAD_IMPERSONATION_LEVEL;
+ return FALSE;
+
+ if (ConsoleInitInfo->DesktopLength)
{
- TranslateMessage(&msg);
- DispatchMessageW(&msg);
+ DesktopPath.MaximumLength = ConsoleInitInfo->DesktopLength;
+ DesktopPath.Length = DesktopPath.MaximumLength - sizeof(UNICODE_NULL);
+ DesktopPath.Buffer = ConsoleInitInfo->Desktop;
+ }
+ else
+ {
+ RtlInitUnicodeString(&DesktopPath, L"Default");
}
- DPRINT("CONSRV: Quit the Gui Thread!!\n");
- PrivateCsrssManualGuiCheck(-1);
+ hDesk = NtUserResolveDesktop(ConsoleLeaderProcessHandle,
+ &DesktopPath,
+ 0,
+ &hWinSta);
+ DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n",
+ &DesktopPath, hDesk, hWinSta);
- return 1;
-}
+ CsrRevertToSelf();
-static BOOL
-GuiInit(VOID)
-{
- WNDCLASSEXW wc;
+ if (hDesk == NULL) return FALSE;
- /* Exit if we were already initialized */
- // if (ConsInitialized) return TRUE;
+ /*
+ * We need to see whether we need to create a
+ * new console input thread for this desktop.
+ */
+ DesktopConsoleThreadInfo.DesktopHandle = hDesk;
+ DesktopConsoleThreadInfo.ThreadId = (ULONG_PTR)INVALID_HANDLE_VALUE; // Special value to say we just want to retrieve the thread ID.
+ NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+ &DesktopConsoleThreadInfo,
+ sizeof(DesktopConsoleThreadInfo));
+ DPRINT("NtUserConsoleControl returned ThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId);
/*
- * Initialize and register the different window classes, if needed.
+ * Save the opened window station and desktop handles in the initialization
+ * structure. They will be used later on, and released, by the GUI frontend.
*/
- if (!ConsInitialized)
+ GuiInitInfo->WinSta = hWinSta;
+ GuiInitInfo->Desktop = hDesk;
+
+ /* Here GuiInitInfo contains original handles */
+
+ /* If we already have a console input thread on this desktop... */
+ if (DesktopConsoleThreadInfo.ThreadId != 0)
{
- /* Initialize the notification window class */
- wc.cbSize = sizeof(WNDCLASSEXW);
- wc.lpszClassName = L"ConSrvCreateNotify";
- wc.lpfnWndProc = GuiConsoleNotifyWndProc;
- wc.style = 0;
- wc.hInstance = ConSrvDllInstance;
- wc.hIcon = NULL;
- wc.hIconSm = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- if (RegisterClassExW(&wc) == 0)
- {
- DPRINT1("Failed to register GUI notify wndproc\n");
- return FALSE;
- }
+ /* ... just use it... */
+ DPRINT("Using input thread InputThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId);
+ GuiInitInfo->InputThreadId = DesktopConsoleThreadInfo.ThreadId;
+ goto Quit;
+ }
- /* Initialize the console window class */
- if (!RegisterConWndClass(ConSrvDllInstance))
- return FALSE;
+ /* ... otherwise create a new one. */
- ConsInitialized = TRUE;
+ /* Initialize a startup event for the thread to signal it */
+ Status = NtCreateEvent(&GuiInitInfo->GuiThreadStartupEvent, EVENT_ALL_ACCESS,
+ NULL, SynchronizationEvent, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ Success = FALSE;
+ goto Quit;
}
/*
- * Set-up the notification window
+ * Duplicate the desktop handle for the console input thread internal needs.
+ * If it happens to need also a window station handle in the future, then
+ * it is there that you also need to duplicate the window station handle!
+ *
+ * Note also that we are going to temporarily overwrite the stored handles
+ * in GuiInitInfo because it happens that we use also this structure to give
+ * the duplicated handles to the input thread that is going to initialize.
+ * After the input thread finishes its initialization, we restore the handles
+ * in GuiInitInfo to their old values.
*/
- if (NULL == NotifyWnd)
+ Status = NtDuplicateObject(NtCurrentProcess(),
+ hDesk,
+ NtCurrentProcess(),
+ (PHANDLE)&GuiInitInfo->Desktop,
+ 0, 0, DUPLICATE_SAME_ACCESS);
+ if (!NT_SUCCESS(Status))
{
- HANDLE ThreadHandle;
- HANDLE GraphicsStartupEvent;
-
- GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- if (NULL == GraphicsStartupEvent) return FALSE;
-
- ThreadHandle = CreateThread(NULL,
- 0,
- GuiConsoleGuiThread,
- (PVOID)&GraphicsStartupEvent,
- 0,
- NULL);
- if (NULL == ThreadHandle)
- {
- CloseHandle(GraphicsStartupEvent);
- DPRINT1("CONSRV: Failed to create graphics console thread. Expect problems\n");
- return FALSE;
- }
- SetThreadPriority(ThreadHandle, THREAD_PRIORITY_HIGHEST);
- CloseHandle(ThreadHandle);
+ Success = FALSE;
+ goto Quit;
+ }
- WaitForSingleObject(GraphicsStartupEvent, INFINITE);
- CloseHandle(GraphicsStartupEvent);
+ /* Here GuiInitInfo contains duplicated handles */
+
+ Status = RtlCreateUserThread(NtCurrentProcess(),
+ NULL,
+ TRUE, // Start the thread in suspended state
+ 0,
+ 0,
+ 0,
+ (PVOID)GuiConsoleInputThread,
+ (PVOID)GuiInitInfo,
+ &hInputThread,
+ &ClientId);
+ if (NT_SUCCESS(Status))
+ {
+ /* Add it as a static server thread and resume it */
+ CsrAddStaticServerThread(hInputThread, &ClientId, 0);
+ Status = NtResumeThread(hInputThread, NULL);
+ }
+ DPRINT("Thread creation hInputThread = 0x%p, InputThreadId = 0x%p, Status = 0x%08lx\n",
+ hInputThread, ClientId.UniqueThread, Status);
- if (NULL == NotifyWnd)
- {
- DPRINT1("CONSRV: Failed to create notification window.\n");
- return FALSE;
- }
+ if (!NT_SUCCESS(Status) || hInputThread == NULL)
+ {
+ /* Close the thread's handle */
+ if (hInputThread) NtClose(hInputThread);
+
+ /* We need to close here the duplicated desktop handle */
+ CloseDesktop(GuiInitInfo->Desktop); // NtUserCloseDesktop
+
+ /* Close the startup event and bail out */
+ NtClose(GuiInitInfo->GuiThreadStartupEvent);
+
+ DPRINT1("CONSRV: Failed to create graphics console thread.\n");
+ Success = FALSE;
+ goto Quit;
}
- // ConsInitialized = TRUE;
+ /* No need to close hInputThread, this is done by CSR automatically */
- return TRUE;
-}
+ /* Wait for the thread to finish its initialization, and close the startup event */
+ NtWaitForSingleObject(GuiInitInfo->GuiThreadStartupEvent, FALSE, NULL);
+ NtClose(GuiInitInfo->GuiThreadStartupEvent);
+ /*
+ * Save the input thread ID for later use, and restore the original handles.
+ * The copies are held by the console input thread.
+ */
+ GuiInitInfo->InputThreadId = (ULONG_PTR)ClientId.UniqueThread;
+ GuiInitInfo->WinSta = hWinSta;
+ GuiInitInfo->Desktop = hDesk;
+
+ /* Here GuiInitInfo contains again original handles */
+
+Quit:
+ if (!Success)
+ {
+ /*
+ * Close the original handles. Do not use the copies in GuiInitInfo
+ * because we may have failed in the middle of the duplicate operation
+ * and the handles stored in GuiInitInfo may have changed.
+ */
+ CloseDesktop(hDesk); // NtUserCloseDesktop
+ CloseWindowStation(hWinSta); // NtUserCloseWindowStation
+ }
+
+ return Success;
+}
/******************************************************************************
IN PCONSRV_CONSOLE Console)
{
PGUI_INIT_INFO GuiInitInfo;
- PCONSOLE_INFO ConsoleInfo;
- PCONSOLE_START_INFO ConsoleStartInfo;
-
PGUI_CONSOLE_DATA GuiData;
- GUI_CONSOLE_INFO TermInfo;
- SIZE_T Length = 0;
- LPWSTR IconPath = NULL;
- INT IconIndex = 0;
-
- if (This == NULL || Console == NULL || This->OldData == NULL)
+ if (This == NULL || Console == NULL || This->Context2 == NULL)
return STATUS_INVALID_PARAMETER;
ASSERT(This->Console == Console);
- GuiInitInfo = This->OldData;
-
- if (GuiInitInfo->ConsoleInfo == NULL || GuiInitInfo->ConsoleStartInfo == NULL)
- return STATUS_INVALID_PARAMETER;
-
- ConsoleInfo = GuiInitInfo->ConsoleInfo;
- ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo;
-
- IconPath = ConsoleStartInfo->IconPath;
- IconIndex = ConsoleStartInfo->IconIndex;
-
+ GuiInitInfo = This->Context2;
/* Terminal data allocation */
- GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
+ GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiData));
if (!GuiData)
{
DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
return STATUS_UNSUCCESSFUL;
}
- ///// /* HACK */ Console->FrontEndIFace.Data = (PVOID)GuiData; /* HACK */
+ /// /* HACK */ Console->FrontEndIFace.Context = (PVOID)GuiData; /* HACK */
GuiData->Console = Console;
GuiData->ActiveBuffer = Console->ActiveBuffer;
GuiData->hWindow = NULL;
+ GuiData->IsWindowVisible = GuiInitInfo->IsWindowVisible;
/* The console can be resized */
Console->FixedSize = FALSE;
InitializeCriticalSection(&GuiData->Lock);
-
- /*
- * Load terminal settings
- */
-
- /* 1. Load the default settings */
- GuiConsoleGetDefaultSettings(&TermInfo, GuiInitInfo->ProcessId);
-
- /* 3. Load the remaining console settings via the registry. */
- if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
- {
- /* Load the terminal infos from the registry. */
- GuiConsoleReadUserSettings(&TermInfo,
- ConsoleInfo->ConsoleTitle,
- GuiInitInfo->ProcessId);
-
- /*
- * Now, update them with the properties the user might gave to us
- * via the STARTUPINFO structure before calling CreateProcess
- * (and which was transmitted via the ConsoleStartInfo structure).
- * We therefore overwrite the values read in the registry.
- */
- if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW)
- {
- TermInfo.ShowWindow = ConsoleStartInfo->wShowWindow;
- }
- if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
- {
- TermInfo.AutoPosition = FALSE;
- TermInfo.WindowOrigin.x = ConsoleStartInfo->dwWindowOrigin.X;
- TermInfo.WindowOrigin.y = ConsoleStartInfo->dwWindowOrigin.Y;
- }
- if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
- {
- TermInfo.FullScreen = TRUE;
- }
- }
-
-
/*
* Set up GUI data
*/
+ RtlCopyMemory(&GuiData->GuiInfo, &GuiInitInfo->TermInfo, sizeof(GuiInitInfo->TermInfo));
- // Font data
- Length = min(wcslen(TermInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
- wcsncpy(GuiData->GuiInfo.FaceName, TermInfo.FaceName, LF_FACESIZE);
- GuiData->GuiInfo.FaceName[Length] = L'\0';
- GuiData->GuiInfo.FontFamily = TermInfo.FontFamily;
- GuiData->GuiInfo.FontSize = TermInfo.FontSize;
- GuiData->GuiInfo.FontWeight = TermInfo.FontWeight;
-
- // Display
- GuiData->GuiInfo.FullScreen = TermInfo.FullScreen;
- GuiData->GuiInfo.ShowWindow = TermInfo.ShowWindow;
- GuiData->GuiInfo.AutoPosition = TermInfo.AutoPosition;
- GuiData->GuiInfo.WindowOrigin = TermInfo.WindowOrigin;
+ /* Initialize the icon handles */
+ if (GuiInitInfo->hIcon != NULL)
+ GuiData->hIcon = GuiInitInfo->hIcon;
+ else
+ GuiData->hIcon = ghDefaultIcon;
- /* Initialize the icon handles to their default values */
- GuiData->hIcon = ghDefaultIcon;
- GuiData->hIconSm = ghDefaultIconSm;
+ if (GuiInitInfo->hIconSm != NULL)
+ GuiData->hIconSm = GuiInitInfo->hIconSm;
+ else
+ GuiData->hIconSm = ghDefaultIconSm;
- /* Get the associated icon, if any */
- if (IconPath == NULL || IconPath[0] == L'\0')
- {
- IconPath = ConsoleStartInfo->AppPath;
- IconIndex = 0;
- }
- DPRINT("IconPath = %S ; IconIndex = %lu\n", (IconPath ? IconPath : L"n/a"), IconIndex);
- if (IconPath && IconPath[0] != L'\0')
- {
- HICON hIcon = NULL, hIconSm = NULL;
- PrivateExtractIconExW(IconPath,
- IconIndex,
- &hIcon,
- &hIconSm,
- 1);
- DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
- if (hIcon != NULL) GuiData->hIcon = hIcon;
- if (hIconSm != NULL) GuiData->hIconSm = hIconSm;
- }
ASSERT(GuiData->hIcon && GuiData->hIconSm);
/* Mouse is shown by default with its default cursor shape */
/* A priori don't ignore mouse signals */
GuiData->IgnoreNextMouseSignal = FALSE;
+ /* Initialize HACK FOR CORE-8394. See conwnd.c!OnMouse for more details. */
+ GuiData->HackCORE8394IgnoreNextMove = FALSE;
/* Close button and the corresponding system menu item are enabled by default */
GuiData->IsCloseButtonEnabled = TRUE;
GuiData->LineSelection = FALSE; // Default to block selection
// TODO: Retrieve the selection mode via the registry.
+ GuiData->InputThreadId = GuiInitInfo->InputThreadId;
+ GuiData->WinSta = GuiInitInfo->WinSta;
+ GuiData->Desktop = GuiInitInfo->Desktop;
+
+ /* Finally, finish to initialize the frontend structure */
+ This->Context = GuiData;
+ ConsoleFreeHeap(This->Context2);
+ This->Context2 = NULL;
+
/*
* We need to wait until the GUI has been fully initialized
* to retrieve custom settings i.e. WindowSize etc...
* Ideally we could use SendNotifyMessage for this but its not
* yet implemented.
*/
- GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+ NtCreateEvent(&GuiData->hGuiInitEvent, EVENT_ALL_ACCESS,
+ NULL, SynchronizationEvent, FALSE);
+ NtCreateEvent(&GuiData->hGuiTermEvent, EVENT_ALL_ACCESS,
+ NULL, SynchronizationEvent, FALSE);
DPRINT("GUI - Checkpoint\n");
/* Create the terminal window */
- PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, GuiData->GuiInfo.ShowWindow, (LPARAM)GuiData);
+ PostThreadMessageW(GuiData->InputThreadId, PM_CREATE_CONSOLE, 0, (LPARAM)GuiData);
/* Wait until initialization has finished */
- WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
+ NtWaitForSingleObject(GuiData->hGuiInitEvent, FALSE, NULL);
DPRINT("OK we created the console window\n");
- CloseHandle(GuiData->hGuiInitEvent);
+ NtClose(GuiData->hGuiInitEvent);
GuiData->hGuiInitEvent = NULL;
/* Check whether we really succeeded in initializing the terminal window */
return STATUS_UNSUCCESSFUL;
}
- /* Finally, finish to initialize the frontend structure */
- This->Data = GuiData;
- if (This->OldData) ConsoleFreeHeap(This->OldData);
- This->OldData = NULL;
-
return STATUS_SUCCESS;
}
static VOID NTAPI
GuiDeinitFrontEnd(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
+
+ DPRINT("Send PM_DESTROY_CONSOLE message and wait on hGuiTermEvent...\n");
+ PostThreadMessageW(GuiData->InputThreadId, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
+ NtWaitForSingleObject(GuiData->hGuiTermEvent, FALSE, NULL);
+ DPRINT("hGuiTermEvent set\n");
+ NtClose(GuiData->hGuiTermEvent);
+ GuiData->hGuiTermEvent = NULL;
- SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
+ CloseDesktop(GuiData->Desktop); // NtUserCloseDesktop
+ CloseWindowStation(GuiData->WinSta); // NtUserCloseWindowStation
DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n",
GuiData->hIcon, ghDefaultIcon, GuiData->hIconSm, ghDefaultIconSm);
DestroyIcon(GuiData->hIconSm);
}
- This->Data = NULL;
+ This->Context = NULL;
DeleteCriticalSection(&GuiData->Lock);
ConsoleFreeHeap(GuiData);
GuiDrawRegion(IN OUT PFRONTEND This,
SMALL_RECT* Region)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
+
+ /* Do nothing if the window is hidden */
+ if (!GuiData->IsWindowVisible) return;
+
DrawRegion(GuiData, Region);
}
PWCHAR Buffer,
UINT Length)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
PCONSOLE_SCREEN_BUFFER Buff;
SHORT CursorEndX, CursorEndY;
RECT ScrollRect;
if (NULL == GuiData || NULL == GuiData->hWindow) return;
+ /* Do nothing if the window is hidden */
+ if (!GuiData->IsWindowVisible) return;
+
Buff = GuiData->ActiveBuffer;
if (GetType(Buff) != TEXTMODE_BUFFER) return;
/* static */ VOID NTAPI
GuiRingBell(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
/* Emit an error beep sound */
SendNotifyMessage(GuiData->hWindow, PM_CONSOLE_BEEP, 0, 0);
GuiSetCursorInfo(IN OUT PFRONTEND This,
PCONSOLE_SCREEN_BUFFER Buff)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
+
+ /* Do nothing if the window is hidden */
+ if (!GuiData->IsWindowVisible) return TRUE;
if (GuiData->ActiveBuffer == Buff)
{
SHORT OldCursorX,
SHORT OldCursorY)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
+
+ /* Do nothing if the window is hidden */
+ if (!GuiData->IsWindowVisible) return TRUE;
if (GuiData->ActiveBuffer == Buff)
{
static VOID NTAPI
GuiResizeTerminal(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
/* Resize the window to the user's values */
PostMessageW(GuiData->hWindow, PM_RESIZE_TERMINAL, 0, 0);
static VOID NTAPI
GuiSetActiveScreenBuffer(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
PCONSOLE_SCREEN_BUFFER ActiveBuffer;
HPALETTE hPalette;
EnterCriticalSection(&GuiData->Lock);
GuiData->WindowSizeLock = TRUE;
- InterlockedExchangePointer(&GuiData->ActiveBuffer,
+ InterlockedExchangePointer((PVOID*)&GuiData->ActiveBuffer,
ConDrvGetActiveScreenBuffer(GuiData->Console));
GuiData->WindowSizeLock = FALSE;
/* Change the current palette */
if (ActiveBuffer->PaletteHandle == NULL)
- {
hPalette = GuiData->hSysPalette;
- }
else
- {
hPalette = ActiveBuffer->PaletteHandle;
- }
- DPRINT1("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette);
+ DPRINT("GuiSetActiveScreenBuffer using palette 0x%p\n", hPalette);
/* Set the new palette for the framebuffer */
SelectPalette(GuiData->hMemDC, hPalette, FALSE);
GuiReleaseScreenBuffer(IN OUT PFRONTEND This,
IN PCONSOLE_SCREEN_BUFFER ScreenBuffer)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
/*
* If we were notified to release a screen buffer that is not actually
EnterCriticalSection(&GuiData->Lock);
GuiData->WindowSizeLock = TRUE;
- InterlockedExchangePointer(&GuiData->ActiveBuffer, NULL);
+ InterlockedExchangePointer((PVOID*)&GuiData->ActiveBuffer, NULL);
GuiData->WindowSizeLock = FALSE;
LeaveCriticalSection(&GuiData->Lock);
static VOID NTAPI
GuiRefreshInternalInfo(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
/* Update the console leader information held by the window */
SetConWndConsoleLeaderCID(GuiData);
static VOID NTAPI
GuiChangeTitle(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
// PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0);
- SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
+ SetWindowTextW(GuiData->hWindow, GuiData->Console->Title.Buffer);
}
static BOOL NTAPI
GuiChangeIcon(IN OUT PFRONTEND This,
HICON IconHandle)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
HICON hIcon, hIconSm;
if (IconHandle == NULL)
}
if (hIcon == NULL)
- {
return FALSE;
- }
if (hIcon != GuiData->hIcon)
{
static HWND NTAPI
GuiGetConsoleWindowHandle(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
return GuiData->hWindow;
}
GuiGetLargestConsoleWindowSize(IN OUT PFRONTEND This,
PCOORD pSize)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
PCONSOLE_SCREEN_BUFFER ActiveBuffer;
- RECT WorkArea;
- LONG width, height;
+ HMONITOR hMonitor;
+ MONITORINFO MonitorInfo;
+ LONG Width, Height;
UINT WidthUnit, HeightUnit;
if (!pSize) return;
- if (!SystemParametersInfoW(SPI_GETWORKAREA, 0, &WorkArea, 0))
+ /*
+ * Retrieve the monitor that is mostly covered by the current console window;
+ * default to primary monitor otherwise.
+ */
+ MonitorInfo.cbSize = sizeof(MonitorInfo);
+ hMonitor = MonitorFromWindow(GuiData->hWindow, MONITOR_DEFAULTTOPRIMARY);
+ if (hMonitor && GetMonitorInfoW(hMonitor, &MonitorInfo))
{
- DPRINT1("SystemParametersInfoW failed - What to do ??\n");
- return;
+ /* Retrieve the width and height of the client area of this monitor */
+ Width = MonitorInfo.rcWork.right - MonitorInfo.rcWork.left;
+ Height = MonitorInfo.rcWork.bottom - MonitorInfo.rcWork.top;
+ }
+ else
+ {
+ /*
+ * Retrieve the width and height of the client area for a full-screen
+ * window on the primary display monitor.
+ */
+ Width = GetSystemMetrics(SM_CXFULLSCREEN);
+ Height = GetSystemMetrics(SM_CYFULLSCREEN);
+
+ // RECT WorkArea;
+ // SystemParametersInfoW(SPI_GETWORKAREA, 0, &WorkArea, 0);
+ // Width = WorkArea.right;
+ // Height = WorkArea.bottom;
}
ActiveBuffer = GuiData->ActiveBuffer;
+#if 0
+ // NOTE: This would be surprising if we wouldn't have an associated buffer...
if (ActiveBuffer)
- {
+#endif
GetScreenBufferSizeUnits(ActiveBuffer, GuiData, &WidthUnit, &HeightUnit);
- }
+#if 0
else
- {
- /* Default: text mode */
- WidthUnit = GuiData->CharWidth ;
- HeightUnit = GuiData->CharHeight;
- }
+ /* Default: graphics mode */
+ WidthUnit = HeightUnit = 1;
+#endif
- width = WorkArea.right;
- height = WorkArea.bottom;
+ Width -= (2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)));
+ Height -= (2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION));
- width -= (2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE)));
- height -= (2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION));
+ if (Width < 0) Width = 0;
+ if (Height < 0) Height = 0;
- if (width < 0) width = 0;
- if (height < 0) height = 0;
-
- pSize->X = (SHORT)(width / (int)WidthUnit ) /* HACK */ + 2;
- pSize->Y = (SHORT)(height / (int)HeightUnit) /* HACK */ + 1;
+ pSize->X = (SHORT)(Width / (int)WidthUnit ) /* HACK */ + 2;
+ pSize->Y = (SHORT)(Height / (int)HeightUnit) /* HACK */ + 1;
}
static BOOL NTAPI
GuiGetSelectionInfo(IN OUT PFRONTEND This,
PCONSOLE_SELECTION_INFO pSelectionInfo)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
if (pSelectionInfo == NULL) return FALSE;
- ZeroMemory(pSelectionInfo, sizeof(CONSOLE_SELECTION_INFO));
+ ZeroMemory(pSelectionInfo, sizeof(*pSelectionInfo));
if (GuiData->Selection.dwFlags != CONSOLE_NO_SELECTION)
- RtlCopyMemory(pSelectionInfo, &GuiData->Selection, sizeof(CONSOLE_SELECTION_INFO));
+ RtlCopyMemory(pSelectionInfo, &GuiData->Selection, sizeof(*pSelectionInfo));
return TRUE;
}
HPALETTE PaletteHandle,
UINT PaletteUsage)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
HPALETTE OldPalette;
// if (GetType(GuiData->ActiveBuffer) != GRAPHICS_BUFFER) return FALSE;
static ULONG NTAPI
GuiGetDisplayMode(IN OUT PFRONTEND This)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
ULONG DisplayMode = 0;
if (GuiData->GuiInfo.FullScreen)
GuiSetDisplayMode(IN OUT PFRONTEND This,
ULONG NewMode)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
BOOL FullScreen;
if (NewMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
return FALSE;
+ /* Do nothing if the window is hidden */
+ if (!GuiData->IsWindowVisible) return TRUE;
+
FullScreen = ((NewMode & CONSOLE_FULLSCREEN_MODE) != 0);
if (FullScreen != GuiData->GuiInfo.FullScreen)
GuiShowMouseCursor(IN OUT PFRONTEND This,
BOOL Show)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
- /* Set the reference count */
- if (Show) ++GuiData->MouseCursorRefCount;
- else --GuiData->MouseCursorRefCount;
+ if (GuiData->IsWindowVisible)
+ {
+ /* Set the reference count */
+ if (Show) ++GuiData->MouseCursorRefCount;
+ else --GuiData->MouseCursorRefCount;
- /* Effectively show (or hide) the cursor (use special values for (w|l)Param) */
- PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
+ /* Effectively show (or hide) the cursor (use special values for (w|l)Param) */
+ PostMessageW(GuiData->hWindow, WM_SETCURSOR, -1, -1);
+ }
return GuiData->MouseCursorRefCount;
}
GuiSetMouseCursor(IN OUT PFRONTEND This,
HCURSOR CursorHandle)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
+
+ /* Do nothing if the window is hidden */
+ if (!GuiData->IsWindowVisible) return TRUE;
/*
* Set the cursor's handle. If the given handle is NULL,
UINT CmdIdLow,
UINT CmdIdHigh)
{
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
GuiData->CmdIdLow = CmdIdLow ;
GuiData->CmdIdHigh = CmdIdHigh;
* for more information.
*/
- PGUI_CONSOLE_DATA GuiData = This->Data;
+ PGUI_CONSOLE_DATA GuiData = This->Context;
HMENU hSysMenu = GetSystemMenu(GuiData->hWindow, FALSE);
if (hSysMenu == NULL) return FALSE;
};
-static BOOL
-LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
- IN OUT PCONSOLE_INFO ConsoleInfo)
+NTSTATUS NTAPI
+GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
+ IN OUT PCONSOLE_STATE_INFO ConsoleInfo,
+ IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
+ IN HANDLE ConsoleLeaderProcessHandle)
{
-#define PATH_SEPARATOR L'\\'
+ PCONSOLE_START_INFO ConsoleStartInfo;
+ PGUI_INIT_INFO GuiInitInfo;
- BOOL RetVal = FALSE;
- HRESULT hRes = S_OK;
- LPWSTR LinkName = NULL;
- SIZE_T Length = 0;
+ if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL)
+ return STATUS_INVALID_PARAMETER;
- if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
- return FALSE;
+ ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo;
- ConsoleStartInfo->IconPath[0] = L'\0';
- ConsoleStartInfo->IconIndex = 0;
+ /*
+ * Initialize a private initialization info structure for later use.
+ * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
+ */
+ GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiInitInfo));
+ if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
- /* 1- Find the last path separator if any */
- LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
- if (LinkName == NULL)
- {
- LinkName = ConsoleStartInfo->ConsoleTitle;
- }
- else
+ /* Initialize GUI terminal emulator common functionalities */
+ if (!GuiInit(ConsoleInitInfo, ConsoleLeaderProcessHandle, GuiInitInfo))
{
- /* Skip the path separator */
- ++LinkName;
+ ConsoleFreeHeap(GuiInitInfo);
+ return STATUS_UNSUCCESSFUL;
}
- /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
- Length = wcslen(LinkName);
- if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
- return FALSE;
+ /*
+ * Load terminal settings
+ */
+#if 0
+ /* Impersonate the caller in order to retrieve settings in its context */
+ // if (!CsrImpersonateClient(NULL))
+ // return STATUS_UNSUCCESSFUL;
+ CsrImpersonateClient(NULL);
+
+ /* 1. Load the default settings */
+ GuiConsoleGetDefaultSettings(&GuiInitInfo->TermInfo);
+#endif
- /* 3- It may be a link. Try to retrieve some properties */
- hRes = CoInitialize(NULL);
- if (SUCCEEDED(hRes))
+ GuiInitInfo->TermInfo.ShowWindow = SW_SHOWNORMAL;
+
+ if (ConsoleInitInfo->IsWindowVisible)
{
- /* Get a pointer to the IShellLink interface */
- IShellLinkW* pshl = NULL;
- hRes = CoCreateInstance(&CLSID_ShellLink,
- NULL,
- CLSCTX_INPROC_SERVER,
- &IID_IShellLinkW,
- (LPVOID*)&pshl);
- if (SUCCEEDED(hRes))
+ /* 2. Load the remaining console settings via the registry */
+ if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
{
- /* Get a pointer to the IPersistFile interface */
- IPersistFile* ppf = NULL;
- hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
- if (SUCCEEDED(hRes))
+#if 0
+ /* Load the terminal infos from the registry */
+ GuiConsoleReadUserSettings(&GuiInitInfo->TermInfo);
+#endif
+
+ /*
+ * Now, update them with the properties the user might gave to us
+ * via the STARTUPINFO structure before calling CreateProcess
+ * (and which was transmitted via the ConsoleStartInfo structure).
+ * We therefore overwrite the values read in the registry.
+ */
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW)
{
- /* Load the shortcut */
- hRes = IPersistFile_Load(ppf, ConsoleStartInfo->ConsoleTitle, STGM_READ);
- if (SUCCEEDED(hRes))
- {
- /*
- * Finally we can get the properties !
- * Update the old ones if needed.
- */
- INT ShowCmd = 0;
- // WORD HotKey = 0;
-
- /* Reset the name of the console with the name of the shortcut */
- Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
- sizeof(ConsoleInfo->ConsoleTitle) / sizeof(ConsoleInfo->ConsoleTitle[0]) - 1);
- wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
- ConsoleInfo->ConsoleTitle[Length] = L'\0';
-
- /* Get the window showing command */
- hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
- if (SUCCEEDED(hRes)) ConsoleStartInfo->wShowWindow = (WORD)ShowCmd;
-
- /* Get the hotkey */
- // hRes = pshl->GetHotkey(&ShowCmd);
- // if (SUCCEEDED(hRes)) ConsoleStartInfo->HotKey = HotKey;
-
- /* Get the icon location, if any */
- hRes = IShellLinkW_GetIconLocation(pshl,
- ConsoleStartInfo->IconPath,
- sizeof(ConsoleStartInfo->IconPath)/sizeof(ConsoleStartInfo->IconPath[0]) - 1, // == MAX_PATH
- &ConsoleStartInfo->IconIndex);
- if (!SUCCEEDED(hRes))
- {
- ConsoleStartInfo->IconPath[0] = L'\0';
- ConsoleStartInfo->IconIndex = 0;
- }
-
- // FIXME: Since we still don't load console properties from the shortcut,
- // return false. When this will be done, we will return true instead.
- RetVal = FALSE;
- }
- IPersistFile_Release(ppf);
+ GuiInitInfo->TermInfo.ShowWindow = ConsoleStartInfo->wShowWindow;
+ }
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION)
+ {
+ ConsoleInfo->AutoPosition = FALSE;
+ ConsoleInfo->WindowPosition.x = ConsoleStartInfo->dwWindowOrigin.X;
+ ConsoleInfo->WindowPosition.y = ConsoleStartInfo->dwWindowOrigin.Y;
+ }
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
+ {
+ ConsoleInfo->FullScreen = TRUE;
}
- IShellLinkW_Release(pshl);
}
}
- CoUninitialize();
- return RetVal;
-}
+#if 0
+ /* Revert impersonation */
+ CsrRevertToSelf();
+#endif
-NTSTATUS NTAPI
-GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
- IN OUT PCONSOLE_INFO ConsoleInfo,
- IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId)
-{
- PCONSOLE_START_INFO ConsoleStartInfo = ExtraConsoleInfo;
- PGUI_INIT_INFO GuiInitInfo;
+ // Font data
+ StringCchCopyNW(GuiInitInfo->TermInfo.FaceName, ARRAYSIZE(GuiInitInfo->TermInfo.FaceName),
+ ConsoleInfo->FaceName, ARRAYSIZE(ConsoleInfo->FaceName));
+ GuiInitInfo->TermInfo.FontFamily = ConsoleInfo->FontFamily;
+ GuiInitInfo->TermInfo.FontSize = ConsoleInfo->FontSize;
+ GuiInitInfo->TermInfo.FontWeight = ConsoleInfo->FontWeight;
- if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleStartInfo == NULL)
- return STATUS_INVALID_PARAMETER;
+ // Display
+ GuiInitInfo->TermInfo.FullScreen = ConsoleInfo->FullScreen;
+ // GuiInitInfo->TermInfo.ShowWindow;
+ GuiInitInfo->TermInfo.AutoPosition = ConsoleInfo->AutoPosition;
+ GuiInitInfo->TermInfo.WindowOrigin = ConsoleInfo->WindowPosition;
- /* Initialize GUI terminal emulator common functionalities */
- if (!GuiInit()) return STATUS_UNSUCCESSFUL;
+ /* Initialize the icon handles */
+ // if (ConsoleStartInfo->hIcon != NULL)
+ GuiInitInfo->hIcon = ConsoleStartInfo->hIcon;
+ // else
+ // GuiInitInfo->hIcon = ghDefaultIcon;
- /*
- * Load per-application terminal settings.
- *
- * Check whether the process creating the console was launched via
- * a shell-link. ConsoleInfo->ConsoleTitle may be updated with the
- * name of the shortcut, and ConsoleStartInfo->Icon[Path|Index] too.
- */
- if (ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)
- {
- if (!LoadShellLinkConsoleInfo(ConsoleStartInfo, ConsoleInfo))
- {
- ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
- }
- }
+ // if (ConsoleStartInfo->hIconSm != NULL)
+ GuiInitInfo->hIconSm = ConsoleStartInfo->hIconSm;
+ // else
+ // GuiInitInfo->hIconSm = ghDefaultIconSm;
- /*
- * Initialize a private initialization info structure for later use.
- * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
- */
- GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_INIT_INFO));
- if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
+ // ASSERT(GuiInitInfo->hIcon && GuiInitInfo->hIconSm);
- // HACK: We suppose that the pointers will be valid in GuiInitFrontEnd...
- GuiInitInfo->ConsoleInfo = ConsoleInfo;
- GuiInitInfo->ConsoleStartInfo = ConsoleStartInfo;
- GuiInitInfo->ProcessId = ProcessId;
+ GuiInitInfo->IsWindowVisible = ConsoleInitInfo->IsWindowVisible;
/* Finally, initialize the frontend structure */
- FrontEnd->Vtbl = &GuiVtbl;
- FrontEnd->Data = NULL;
- FrontEnd->OldData = GuiInitInfo;
+ FrontEnd->Vtbl = &GuiVtbl;
+ FrontEnd->Context = NULL;
+ FrontEnd->Context2 = GuiInitInfo;
return STATUS_SUCCESS;
}
{
if (FrontEnd == NULL) return STATUS_INVALID_PARAMETER;
- if (FrontEnd->Data) GuiDeinitFrontEnd(FrontEnd);
- if (FrontEnd->OldData) ConsoleFreeHeap(FrontEnd->OldData);
+ if (FrontEnd->Context ) GuiDeinitFrontEnd(FrontEnd);
+ if (FrontEnd->Context2) ConsoleFreeHeap(FrontEnd->Context2);
return STATUS_SUCCESS;
}