Esempio n. 1
0
/*
 * 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;
    }
Esempio n. 2
0
/*
 * 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;
    }
Esempio n. 3
0
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;
    }
Esempio n. 4
0
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;
}