static LRESULT CALLBACK TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { /* PTUI_CONSOLE_DATA TuiData = NULL; PCONSOLE Console = NULL; TuiData = TuiGetGuiData(hWnd); if (TuiData == NULL) return 0; */ switch (msg) { case WM_CHAR: case WM_SYSCHAR: case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: case WM_SYSKEYUP: { if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE)) { MSG Message; Message.hwnd = hWnd; Message.message = msg; Message.wParam = wParam; Message.lParam = lParam; ConioProcessKey(ActiveConsole->Console, &Message); LeaveCriticalSection(&ActiveConsole->Console->Lock); } break; } case WM_ACTIVATE: { if (ConDrvValidateConsoleUnsafe(ActiveConsole->Console, CONSOLE_RUNNING, TRUE)) { if (LOWORD(wParam) != WA_INACTIVE) { SetFocus(hWnd); ConioDrawConsole(ActiveConsole->Console); } LeaveCriticalSection(&ActiveConsole->Console->Lock); } break; } default: break; } return DefWindowProcW(hWnd, msg, wParam, lParam); }
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; }
/* * 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; }
VOID GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, BOOL Defaults) { NTSTATUS Status; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL, hClientSection = NULL; LARGE_INTEGER SectionSize; ULONG ViewSize = 0; SIZE_T Length = 0; PCONSOLE_PROPS pSharedInfo = NULL; PGUI_CONSOLE_INFO GuiInfo = NULL; DPRINT("GuiConsoleShowConsoleProperties entered\n"); if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* * Create a memory section to share with the applet, and map it. */ /* Holds data for console.dll + console info + terminal-specific info */ SectionSize.QuadPart = sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO); Status = NtCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to create a shared section, Status = 0x%08lx\n", Status); goto Quit; } Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pSharedInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to map the shared section, Status = 0x%08lx\n", Status); goto Quit; } /* * Setup the shared console properties structure. */ /* Header */ pSharedInfo->hConsoleWindow = GuiData->hWindow; pSharedInfo->ShowDefaultParams = Defaults; /* * We fill-in the fields only if we display * our properties, not the default ones. */ if (!Defaults) { /* Console information */ pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize; pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup; pSharedInfo->ci.QuickEdit = Console->QuickEdit; pSharedInfo->ci.InsertMode = Console->InsertMode; /////////////pSharedInfo->ci.InputBufferSize = 0; pSharedInfo->ci.ScreenBufferSize = ActiveBuffer->ScreenBufferSize; pSharedInfo->ci.ConsoleSize = ActiveBuffer->ViewSize; pSharedInfo->ci.CursorBlinkOn; pSharedInfo->ci.ForceCursorOff; pSharedInfo->ci.CursorSize = ActiveBuffer->CursorInfo.dwSize; if (GetType(ActiveBuffer) == TEXTMODE_BUFFER) { PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer; pSharedInfo->ci.ScreenAttrib = Buffer->ScreenDefaultAttrib; pSharedInfo->ci.PopupAttrib = Buffer->PopupDefaultAttrib; } else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) { // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer; DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n"); // FIXME: Gather defaults from the registry ? pSharedInfo->ci.ScreenAttrib = DEFAULT_SCREEN_ATTRIB; pSharedInfo->ci.PopupAttrib = DEFAULT_POPUP_ATTRIB ; } pSharedInfo->ci.CodePage; /* GUI Information */ pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO); GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1); wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE); GuiInfo->FaceName[LF_FACESIZE - 1] = UNICODE_NULL; GuiInfo->FontFamily = GuiData->GuiInfo.FontFamily; GuiInfo->FontSize = GuiData->GuiInfo.FontSize; GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight; GuiInfo->FullScreen = GuiData->GuiInfo.FullScreen; GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition; GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin; /* Offsetize */ pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo); /* Palette */ memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors)); /* Title of the console, original one corresponding to the one set by the console leader */ Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1, Console->OriginalTitle.Length / sizeof(WCHAR)); wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length); } else { Length = 0; // FIXME: Load the default parameters from the registry. } /* Null-terminate the title */ pSharedInfo->ci.ConsoleTitle[Length] = L'\0'; /* Unmap the view */ NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo); /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for the client */ Status = NtDuplicateObject(NtCurrentProcess(), hSection, ProcessData->Process->ProcessHandle, &hClientSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to duplicate section handle for client, Status = 0x%08lx\n", Status); goto Quit; } /* Start the properties dialog */ if (ProcessData->PropRoutine) { _SEH2_TRY { HANDLE Thread = NULL; _SEH2_TRY { Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, ProcessData->PropRoutine, (PVOID)hClientSection, 0, NULL); if (NULL == Thread) { DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError()); } else { DPRINT("ProcessData->PropRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); /// WaitForSingleObject(Thread, INFINITE); } } _SEH2_FINALLY { CloseHandle(Thread); } _SEH2_END; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = 0x%08lx\n", Status); } _SEH2_END; }
VOID GuiPaintTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer, PGUI_CONSOLE_DATA GuiData, PRECT rcView, PRECT rcFramebuffer) { PCONSRV_CONSOLE Console = Buffer->Header.Console; // ASSERT(Console == GuiData->Console); ULONG TopLine, BottomLine, LeftChar, RightChar; ULONG Line, Char, Start; PCHAR_INFO From; PWCHAR To; WORD LastAttribute, Attribute; ULONG CursorX, CursorY, CursorHeight; HBRUSH CursorBrush, OldBrush; HFONT OldFont, NewFont; BOOLEAN IsUnderline; if (Buffer->Buffer == NULL) return; if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; rcFramebuffer->left = Buffer->ViewOrigin.X * GuiData->CharWidth + rcView->left; rcFramebuffer->top = Buffer->ViewOrigin.Y * GuiData->CharHeight + rcView->top; rcFramebuffer->right = Buffer->ViewOrigin.X * GuiData->CharWidth + rcView->right; rcFramebuffer->bottom = Buffer->ViewOrigin.Y * GuiData->CharHeight + rcView->bottom; LeftChar = rcFramebuffer->left / GuiData->CharWidth; TopLine = rcFramebuffer->top / GuiData->CharHeight; RightChar = rcFramebuffer->right / GuiData->CharWidth; BottomLine = rcFramebuffer->bottom / GuiData->CharHeight; if (RightChar >= (ULONG)Buffer->ScreenBufferSize.X) RightChar = Buffer->ScreenBufferSize.X - 1; if (BottomLine >= (ULONG)Buffer->ScreenBufferSize.Y) BottomLine = Buffer->ScreenBufferSize.Y - 1; LastAttribute = ConioCoordToPointer(Buffer, LeftChar, TopLine)->Attributes; SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute))); SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute))); /* We use the underscore flag as a underline flag */ IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE); /* Select the new font */ NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL]; OldFont = SelectObject(GuiData->hMemDC, NewFont); for (Line = TopLine; Line <= BottomLine; Line++) { WCHAR LineBuffer[80]; // Buffer containing a part or all the line to be displayed From = ConioCoordToPointer(Buffer, LeftChar, Line); // Get the first code of the line Start = LeftChar; To = LineBuffer; for (Char = LeftChar; Char <= RightChar; Char++) { /* * We flush the buffer if the new attribute is different * from the current one, or if the buffer is full. */ if (From->Attributes != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR))) { TextOutW(GuiData->hMemDC, Start * GuiData->CharWidth, Line * GuiData->CharHeight, LineBuffer, Char - Start); Start = Char; To = LineBuffer; Attribute = From->Attributes; if (Attribute != LastAttribute) { LastAttribute = Attribute; SetTextColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, TextAttribFromAttrib(LastAttribute))); SetBkColor(GuiData->hMemDC, PaletteRGBFromAttrib(Console, BkgdAttribFromAttrib(LastAttribute))); /* Change underline state if needed */ if (!!(LastAttribute & COMMON_LVB_UNDERSCORE) != IsUnderline) { IsUnderline = !!(LastAttribute & COMMON_LVB_UNDERSCORE); /* Select the new font */ NewFont = GuiData->Font[IsUnderline ? FONT_BOLD : FONT_NORMAL]; /* OldFont = */ SelectObject(GuiData->hMemDC, NewFont); } } } *(To++) = (From++)->Char.UnicodeChar; } TextOutW(GuiData->hMemDC, Start * GuiData->CharWidth, Line * GuiData->CharHeight, LineBuffer, RightChar - Start + 1); } /* Restore the old font */ SelectObject(GuiData->hMemDC, OldFont); /* * Draw the caret */ if (Buffer->CursorInfo.bVisible && Buffer->CursorBlinkOn && !Buffer->ForceCursorOff) { CursorX = Buffer->CursorPosition.X; CursorY = Buffer->CursorPosition.Y; if (LeftChar <= CursorX && CursorX <= RightChar && TopLine <= CursorY && CursorY <= BottomLine) { CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight); Attribute = ConioCoordToPointer(Buffer, Buffer->CursorPosition.X, Buffer->CursorPosition.Y)->Attributes; if (Attribute == DEFAULT_SCREEN_ATTRIB) Attribute = Buffer->ScreenDefaultAttrib; CursorBrush = CreateSolidBrush(PaletteRGBFromAttrib(Console, TextAttribFromAttrib(Attribute))); OldBrush = SelectObject(GuiData->hMemDC, CursorBrush); PatBlt(GuiData->hMemDC, CursorX * GuiData->CharWidth, CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight), GuiData->CharWidth, CursorHeight, PATCOPY); SelectObject(GuiData->hMemDC, OldBrush); DeleteObject(CursorBrush); } } LeaveCriticalSection(&Console->Lock); }
VOID NTAPI ConDrvDeleteConsole(IN PCONSOLE Console) { DPRINT("ConDrvDeleteConsole(0x%p)\n", Console); /* * Forbid validation of any console by other threads * during the deletion of this console. */ ConDrvLockConsoleListExclusive(); /* * If the console is already being destroyed, i.e. not running * or finishing to be initialized, just return. */ if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE) && !ConDrvValidateConsoleUnsafe(Console, CONSOLE_INITIALIZING, TRUE)) { /* Unlock the console list and return */ ConDrvUnlockConsoleList(); return; } /* * We are about to be destroyed. Signal it to other people * so that they can terminate what they are doing, and that * they cannot longer validate the console. */ Console->State = CONSOLE_TERMINATING; /* * Allow other threads to finish their job: basically, unlock * all other calls to EnterCriticalSection(&Console->Lock); by * ConDrvValidateConsoleUnsafe functions so that they just see * that we are not in CONSOLE_RUNNING state anymore, or unlock * other concurrent calls to ConDrvDeleteConsole so that they * can see that we are in fact already deleting the console. */ LeaveCriticalSection(&Console->Lock); ConDrvUnlockConsoleList(); /* Deregister the terminal */ DPRINT("Deregister terminal\n"); ConDrvDetachTerminal(Console); DPRINT("Terminal deregistered\n"); /*** * Check that the console is in terminating state before continuing * (the cleanup code must not change the state of the console... * ...unless to cancel console deletion ?). ***/ ConDrvLockConsoleListExclusive(); if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_TERMINATING, TRUE)) { ConDrvUnlockConsoleList(); return; } /* We are now in destruction */ Console->State = CONSOLE_IN_DESTRUCTION; /* We really delete the console. Reset the count to be sure. */ Console->ReferenceCount = 0; /* Remove the console from the list */ RemoveConsole(Console); /* Delete the last screen buffer */ ConDrvDeleteScreenBuffer(Console->ActiveBuffer); Console->ActiveBuffer = NULL; if (!IsListEmpty(&Console->BufferList)) { /***ConDrvUnlockConsoleList();***/ ASSERTMSG("BUGBUGBUG!! screen buffer list not empty\n", FALSE); } /* Deinitialize the input buffer */ ConDrvDeinitInputBuffer(Console); if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent); DPRINT("ConDrvDeleteConsole - Unlocking\n"); LeaveCriticalSection(&Console->Lock); DPRINT("ConDrvDeleteConsole - Destroying lock\n"); DeleteCriticalSection(&Console->Lock); DPRINT("ConDrvDeleteConsole - Lock destroyed ; freeing console\n"); ConsoleFreeHeap(Console); DPRINT("ConDrvDeleteConsole - Console destroyed\n"); /* Unlock the console list and return */ ConDrvUnlockConsoleList(); }
VOID GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, BOOL Defaults) { NTSTATUS Status; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL, hClientSection = NULL; PVOID ThreadParameter = NULL; // Is either hClientSection or the console window handle, // depending on whether we display the default settings or // the settings of a particular console. DPRINT("GuiConsoleShowConsoleProperties entered\n"); if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* * Be sure we effectively have a properties dialog routine (that launches * the console control panel applet). It resides in kernel32.dll (client). */ if (ProcessData->PropRoutine == NULL) goto Quit; /* * Create a memory section to be shared with the console control panel applet * in the case we are displaying the settings of a particular console. * In that case the ThreadParameter is the hClientSection handle. * In the case we display the default console parameters, we don't need to * create a memory section. We just need to open the applet, and in this case * the ThreadParameter is the parent window handle of the applet's window, * that is, the console window. */ if (!Defaults) { PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer; LARGE_INTEGER SectionSize; ULONG ViewSize = 0; PCONSOLE_STATE_INFO pSharedInfo = NULL; /* * Create a memory section to share with the applet, and map it. */ SectionSize.QuadPart = sizeof(CONSOLE_STATE_INFO); // Standard size SectionSize.QuadPart += Console->OriginalTitle.Length; // Add the length in bytes of the console title string Status = NtCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to create a shared section, Status = 0x%08lx\n", Status); goto Quit; } Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pSharedInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to map the shared section, Status = 0x%08lx\n", Status); goto Quit; } /* * Setup the shared console properties structure. */ /* Store the real size of the structure */ pSharedInfo->cbSize = SectionSize.QuadPart; /* * When we setup the settings of a particular console, the parent window * of the applet's window is the console window, and it is given via the * hWnd member of the shared console info structure. */ pSharedInfo->hWnd = GuiData->hWindow; /* Console information */ pSharedInfo->HistoryBufferSize = Console->HistoryBufferSize; pSharedInfo->NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; pSharedInfo->HistoryNoDup = Console->HistoryNoDup; pSharedInfo->QuickEdit = Console->QuickEdit; pSharedInfo->InsertMode = Console->InsertMode; /// pSharedInfo->InputBufferSize = 0; pSharedInfo->ScreenBufferSize = ActiveBuffer->ScreenBufferSize; pSharedInfo->WindowSize = ActiveBuffer->ViewSize; pSharedInfo->CursorSize = ActiveBuffer->CursorInfo.dwSize; if (GetType(ActiveBuffer) == TEXTMODE_BUFFER) { PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer; pSharedInfo->ScreenAttributes = Buffer->ScreenDefaultAttrib; pSharedInfo->PopupAttributes = Buffer->PopupDefaultAttrib; } else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) { // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer; DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n"); // FIXME: Gather defaults from the registry ? pSharedInfo->ScreenAttributes = DEFAULT_SCREEN_ATTRIB; pSharedInfo->PopupAttributes = DEFAULT_POPUP_ATTRIB ; } /// pSharedInfo->CodePage; /* GUI Information */ wcsncpy(pSharedInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE); pSharedInfo->FaceName[LF_FACESIZE - 1] = UNICODE_NULL; pSharedInfo->FontFamily = GuiData->GuiInfo.FontFamily; pSharedInfo->FontSize = GuiData->GuiInfo.FontSize; pSharedInfo->FontWeight = GuiData->GuiInfo.FontWeight; pSharedInfo->FullScreen = GuiData->GuiInfo.FullScreen; pSharedInfo->AutoPosition = GuiData->GuiInfo.AutoPosition; pSharedInfo->WindowPosition = GuiData->GuiInfo.WindowOrigin; /* Palette */ RtlCopyMemory(pSharedInfo->ColorTable, Console->Colors, sizeof(Console->Colors)); /* Copy the original title of the console and null-terminate it */ RtlCopyMemory(pSharedInfo->ConsoleTitle, Console->OriginalTitle.Buffer, Console->OriginalTitle.Length); pSharedInfo->ConsoleTitle[Console->OriginalTitle.Length / sizeof(WCHAR)] = UNICODE_NULL; /* Unmap the view */ NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo); /* Duplicate the section handle for the client */ Status = NtDuplicateObject(NtCurrentProcess(), hSection, ProcessData->Process->ProcessHandle, &hClientSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to duplicate section handle for client, Status = 0x%08lx\n", Status); goto Quit; } /* For the settings of a particular console, use the shared client section handle as the thread parameter */ ThreadParameter = (PVOID)hClientSection; } else { /* For the default settings, use the console window handle as the thread parameter */ ThreadParameter = (PVOID)GuiData->hWindow; } /* Start the console control panel applet */ _SEH2_TRY { HANDLE Thread = NULL; _SEH2_TRY { Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, ProcessData->PropRoutine, ThreadParameter, 0, NULL); if (NULL == Thread) { DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError()); } else { DPRINT("ProcessData->PropRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); } } _SEH2_FINALLY { CloseHandle(Thread); } _SEH2_END; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = 0x%08lx\n", Status); } _SEH2_END; Quit: /* We have finished, close the section handle if any */ if (hSection) NtClose(hSection); LeaveCriticalSection(&Console->Lock); return; }
/* * 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; }