/* * Function for dealing with the undocumented message and structure used by * Windows' console.dll for setting console info. * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf * for more information. */ VOID GuiApplyWindowsConsoleSettings(PGUI_CONSOLE_DATA GuiData, HANDLE hClientSection) { NTSTATUS Status = STATUS_SUCCESS; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL; ULONG ViewSize = 0; PCONSOLE_STATE_INFO pConInfo = NULL; CONSOLE_INFO ConInfo; GUI_CONSOLE_INFO GuiInfo; #if 0 SIZE_T Length; #endif if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for ourselves */ Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, hClientSection, NtCurrentProcess(), &hSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status); goto Quit; } /* Get a view of the shared section */ Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pConInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status); goto Quit; } _SEH2_TRY { /* Check that the section is well-sized */ if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) || (pConInfo->cbSize != sizeof(CONSOLE_STATE_INFO)) ) { DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n"); Status = STATUS_INVALID_VIEW_SIZE; _SEH2_YIELD(goto Quit); } // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow /* Retrieve terminal informations */ // Console information ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize; ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers; ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup; ConInfo.QuickEdit = !!pConInfo->QuickEdit; ConInfo.InsertMode = !!pConInfo->InsertMode; ConInfo.ScreenBufferSize = pConInfo->ScreenBufferSize; ConInfo.ConsoleSize = pConInfo->WindowSize; ConInfo.CursorSize = pConInfo->CursorSize; ConInfo.ScreenAttrib = pConInfo->ScreenColors; ConInfo.PopupAttrib = pConInfo->PopupColors; memcpy(&ConInfo.Colors, pConInfo->ColorTable, sizeof(ConInfo.Colors)); ConInfo.CodePage = pConInfo->CodePage; /**ConInfo.ConsoleTitle[MAX_PATH + 1] = pConInfo->ConsoleTitle; // FIXME: memcpy**/ #if 0 /* Title of the console, original one corresponding to the one set by the console leader */ Length = min(sizeof(pConInfo->ConsoleTitle) / sizeof(pConInfo->ConsoleTitle[0]) - 1, Console->OriginalTitle.Length / sizeof(WCHAR)); wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length); #endif // BOOLEAN ConInfo.CursorBlinkOn = pConInfo-> // BOOLEAN ConInfo.ForceCursorOff = pConInfo-> // Terminal information wcsncpy(GuiInfo.FaceName, pConInfo->FaceName, LF_FACESIZE); GuiInfo.FaceName[LF_FACESIZE - 1] = UNICODE_NULL; GuiInfo.FontFamily = pConInfo->FontFamily; GuiInfo.FontSize = pConInfo->FontSize; GuiInfo.FontWeight = pConInfo->FontWeight; GuiInfo.FullScreen = !!pConInfo->FullScreen; GuiInfo.AutoPosition = !!pConInfo->AutoPosition; GuiInfo.WindowOrigin = pConInfo->WindowPosition; // WORD GuiInfo.ShowWindow = pConInfo-> /* * If we don't set the default parameters, * apply them, otherwise just save them. */ #if 0 if (pConInfo->ShowDefaultParams == FALSE) #endif { /* Set the console informations */ ConSrvApplyUserSettings(Console, &ConInfo); /* Set the terminal informations */ // memcpy(&GuiData->GuiInfo, &GuiInfo, sizeof(GUI_CONSOLE_INFO)); /* Change the font */ InitFonts(GuiData, GuiInfo.FaceName, GuiInfo.FontFamily, GuiInfo.FontSize, GuiInfo.FontWeight); // HACK, needed because changing font may change the size of the window /**/TermResizeTerminal(Console);/**/ /* Move the window to the user's values */ GuiData->GuiInfo.AutoPosition = GuiInfo.AutoPosition; GuiData->GuiInfo.WindowOrigin = GuiInfo.WindowOrigin; GuiConsoleMoveWindow(GuiData); InvalidateRect(GuiData->hWindow, NULL, TRUE); /* * Apply full-screen mode. */ if (GuiInfo.FullScreen != GuiData->GuiInfo.FullScreen) { SwitchFullScreen(GuiData, GuiInfo.FullScreen); } } #if 0 /* * Save settings if needed */ // FIXME: Do it in the console properties applet ?? if (SaveSettings) { DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess); ConSrvWriteUserSettings(&ConInfo, ProcessId); GuiConsoleWriteUserSettings(&GuiInfo, ConInfo.ConsoleTitle, ProcessId); } #endif Status = STATUS_SUCCESS; }
/* * Function for dealing with the undocumented message and structure used by * Windows' console.dll for setting console info. * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf * for more information. */ VOID GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, HANDLE hClientSection) { NTSTATUS Status = STATUS_SUCCESS; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL; ULONG ViewSize = 0; PCONSOLE_STATE_INFO pConInfo = NULL; if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for ourselves */ Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, hClientSection, NtCurrentProcess(), &hSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status); goto Quit; } /* Get a view of the shared section */ Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pConInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status); goto Quit; } _SEH2_TRY { /* Check that the section is well-sized */ if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) || (pConInfo->cbSize < sizeof(CONSOLE_STATE_INFO)) ) { DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n"); Status = STATUS_INVALID_VIEW_SIZE; _SEH2_YIELD(goto Quit); } // TODO: Check that GuiData->hWindow == pConInfo->hWnd /* Retrieve terminal informations */ /* Console information */ #if 0 // FIXME: Things not set ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize; ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers; ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup; ConInfo.CodePage = pConInfo->CodePage; #endif /* * Apply the settings */ /* Set the console informations */ ConSrvApplyUserSettings(Console, pConInfo); /* Set the terminal informations */ /* Change the font */ InitFonts(GuiData, pConInfo->FaceName, pConInfo->FontFamily, pConInfo->FontSize, pConInfo->FontWeight); // HACK, needed because changing font may change the size of the window /**/TermResizeTerminal(Console);/**/ /* Move the window to the user's values */ GuiData->GuiInfo.AutoPosition = !!pConInfo->AutoPosition; GuiData->GuiInfo.WindowOrigin = pConInfo->WindowPosition; GuiConsoleMoveWindow(GuiData); InvalidateRect(GuiData->hWindow, NULL, TRUE); /* * Apply full-screen mode. */ if (!!pConInfo->FullScreen != GuiData->GuiInfo.FullScreen) { SwitchFullScreen(GuiData, !!pConInfo->FullScreen); } /* * The settings are saved in the registry by console.dll itself, if needed. */ // if (SaveSettings) // { // GuiConsoleWriteUserSettings(GuiInfo); // } Status = STATUS_SUCCESS; }
VOID GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, HANDLE hClientSection, BOOL SaveSettings) { NTSTATUS Status = STATUS_SUCCESS; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL; ULONG ViewSize = 0; PCONSOLE_PROPS pConInfo = NULL; PCONSOLE_INFO ConInfo = NULL; PTERMINAL_INFO TermInfo = NULL; PGUI_CONSOLE_INFO GuiInfo = NULL; if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for ourselves */ Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, hClientSection, NtCurrentProcess(), &hSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status); goto Quit; } /* Get a view of the shared section */ Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pConInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status); goto Quit; } _SEH2_TRY { /* Check that the section is well-sized */ if ( (ViewSize < sizeof(CONSOLE_PROPS)) || (pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) || (ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) ) { DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n"); Status = STATUS_INVALID_VIEW_SIZE; _SEH2_YIELD(goto Quit); } // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow /* Retrieve terminal informations */ ConInfo = &pConInfo->ci; TermInfo = &pConInfo->TerminalInfo; GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo); /* * If we don't set the default parameters, * apply them, otherwise just save them. */ if (pConInfo->ShowDefaultParams == FALSE) { /* Set the console informations */ ConSrvApplyUserSettings(Console, ConInfo); /* Set the terminal informations */ // memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO)); /* Change the font */ InitFonts(GuiData, GuiInfo->FaceName, GuiInfo->FontFamily, GuiInfo->FontSize, GuiInfo->FontWeight); // HACK, needed because changing font may change the size of the window /**/TermResizeTerminal(Console);/**/ /* Move the window to the user's values */ GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition; GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin; GuiConsoleMoveWindow(GuiData); InvalidateRect(GuiData->hWindow, NULL, TRUE); /* * Apply full-screen mode. */ if (GuiInfo->FullScreen != GuiData->GuiInfo.FullScreen) { SwitchFullScreen(GuiData, GuiInfo->FullScreen); } } /* * Save settings if needed */ // FIXME: Do it in the console properties applet ?? if (SaveSettings) { DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess); ConSrvWriteUserSettings(ConInfo, ProcessId); GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId); } Status = STATUS_SUCCESS; }
static ULONG NTAPI GuiConsoleInputThread(PVOID Param) { 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; /* The thread has been initialized, set the event */ NtSetEvent(GuiInitInfo->GuiThreadStartupEvent, NULL); Status = STATUS_SUCCESS; while (GetMessageW(&msg, NULL, 0, 0)) { switch (msg.message) { 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 | WS_HSCROLL | WS_VSCROLL, 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); InterlockedIncrement(&WindowCount); // // FIXME: TODO: Move everything there into conwnd.c!OnNcCreate() // /* Retrieve our real position */ // See conwnd.c!OnMove() GetWindowRect(GuiData->hWindow, &rcWnd); GuiData->GuiInfo.WindowOrigin.x = rcWnd.left; GuiData->GuiInfo.WindowOrigin.y = rcWnd.top; 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); 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); } continue; } case PM_DESTROY_CONSOLE: { 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)) { TranslateMessage(&TempMsg); DispatchMessageW(&TempMsg); }*/ while (PeekMessageW(&TempMsg, NULL, 0, 0, PM_REMOVE)) ; if (GuiData->hWindow == NULL) continue; DestroyWindow(GuiData->hWindow); NtSetEvent(GuiData->hGuiTermEvent, NULL); if (InterlockedDecrement(&WindowCount) == 0) { DPRINT("CONSRV: Going to quit the Input Thread 0x%p\n", InputThreadId); goto Quit; } continue; } } 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; }