diff --git a/reactos/dll/cpl/console/font.c b/reactos/dll/cpl/console/font.c index d714e63fa13..aa57201c9b0 100644 --- a/reactos/dll/cpl/console/font.c +++ b/reactos/dll/cpl/console/font.c @@ -72,7 +72,7 @@ GuiData->CharWidth = Metrics.tmMaxCharWidth; GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading; - /* Measure real char width more precisely if possible. */ + /* Measure real char width more precisely if possible */ if (GetTextExtentPoint32W(drawItem->hDC, L"R", 1, &CharSize)) GuiData->CharWidth = CharSize.cx; } @@ -102,12 +102,9 @@ EnumFontNamesProc(PLOGFONTW lplf, HWND hwndCombo = (HWND)lParam; LPWSTR pszName = lplf->lfFaceName; - BOOL fFixed; - BOOL fTrueType; - /* Record the font's attributes (Fixedwidth and Truetype) */ - fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH); - fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS) ? TRUE : FALSE; + // BOOL fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH); + // BOOL fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS); /* * According to: http://support.microsoft.com/kb/247815 @@ -158,7 +155,8 @@ EnumFontNamesProc(PLOGFONTW lplf, /* Reject TrueType fonts that are not FF_MODERN */ if ((FontType == TRUETYPE_FONTTYPE) && ((lplf->lfPitchAndFamily & 0xF0) != FF_MODERN)) { - DPRINT1("TrueType font '%S' rejected because it's not FF_MODERN (lfPitchAndFamily = %d)\n", pszName, lplf->lfPitchAndFamily); + DPRINT1("TrueType font '%S' rejected because it's not FF_MODERN (lfPitchAndFamily = %d)\n", + pszName, lplf->lfPitchAndFamily); return TRUE; } @@ -166,14 +164,16 @@ EnumFontNamesProc(PLOGFONTW lplf, #if 0 if ((FontType != TRUETYPE_FONTTYPE) && (lplf->lfCharSet != OEM_CHARSET)) { - DPRINT1("Non-TrueType font '%S' rejected because it's not OEM_CHARSET %d\n", pszName, lplf->lfCharSet); + DPRINT1("Non-TrueType font '%S' rejected because it's not OEM_CHARSET %d\n", + pszName, lplf->lfCharSet); return TRUE; } #else // Improved criterium if ((FontType != TRUETYPE_FONTTYPE) && ((lplf->lfCharSet != ANSI_CHARSET) && (lplf->lfCharSet != DEFAULT_CHARSET) && (lplf->lfCharSet != OEM_CHARSET))) { - DPRINT1("Non-TrueType font '%S' rejected because it's not ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n", pszName, lplf->lfCharSet); + DPRINT1("Non-TrueType font '%S' rejected because it's not ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n", + pszName, lplf->lfCharSet); return TRUE; } #endif @@ -205,7 +205,8 @@ EnumFontNamesProc(PLOGFONTW lplf, DPRINT1("Add font '%S' (lfPitchAndFamily = %d)\n", pszName, lplf->lfPitchAndFamily); /* Store this information in the list-item's userdata area */ - SendMessageW(hwndCombo, LB_SETITEMDATA, idx, MAKEWPARAM(fFixed, fTrueType)); + // SendMessageW(hwndCombo, LB_SETITEMDATA, idx, MAKEWPARAM(fFixed, fTrueType)); + SendMessageW(hwndCombo, LB_SETITEMDATA, idx, (WPARAM)FontType); } return TRUE; @@ -247,7 +248,7 @@ EnumFontSizesProc(PLOGFONTW lplf, } else { - int i; + ULONG i; for (i = 0; i < sizeof(TrueTypePoints) / sizeof(TrueTypePoints[0]); ++i) { swprintf(FontSize, L"%2d", TrueTypePoints[i]); @@ -273,7 +274,6 @@ EnumFontSizesProc(PLOGFONTW lplf, } - static VOID FontSizeChange(HWND hwndDlg, PGUI_CONSOLE_INFO GuiInfo); diff --git a/reactos/dll/cpl/console/lang/bg-BG.rc b/reactos/dll/cpl/console/lang/bg-BG.rc index e6f62b7530b..4b19a1c893c 100644 --- a/reactos/dll/cpl/console/lang/bg-BG.rc +++ b/reactos/dll/cpl/console/lang/bg-BG.rc @@ -35,10 +35,10 @@ BEGIN LTEXT "Прозоречен преглед:", -1, 10, 10, 94, 10 LTEXT "Размер:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Шрифт:", -1, 10, 105, 33, 10 CHECKBOX "&Получери шрифтове", IDC_CHECK_BOLD_FONTS, 38, 105, 85, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Всеки знак е:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/cs-CZ.rc b/reactos/dll/cpl/console/lang/cs-CZ.rc index afda11d7d58..b7cac0e052d 100644 --- a/reactos/dll/cpl/console/lang/cs-CZ.rc +++ b/reactos/dll/cpl/console/lang/cs-CZ.rc @@ -41,10 +41,10 @@ BEGIN LTEXT "Náhled okna:", -1, 10, 10, 94, 10 LTEXT "Velikost:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Písmo:", -1, 10, 105, 33, 10 CHECKBOX "&Tučná písma", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Každý znak je:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/de-DE.rc b/reactos/dll/cpl/console/lang/de-DE.rc index 5ea5d53f846..9309217167b 100644 --- a/reactos/dll/cpl/console/lang/de-DE.rc +++ b/reactos/dll/cpl/console/lang/de-DE.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "Fenstervorschau", -1, 10, 7, 65, 10 LTEXT "Größe", -1, 130, 10, 30, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 115, 70 - LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Schrift", -1, 10, 105, 35, 10 CHECKBOX "&Fette Schriften", IDC_CHECK_BOLD_FONTS, 45, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 10, 155, 200, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 15, 165, 95, 35 LTEXT "Jedes Zeichen ist:", -1, 130, 165, 75, 10 diff --git a/reactos/dll/cpl/console/lang/en-US.rc b/reactos/dll/cpl/console/lang/en-US.rc index d4d9e576f2b..07d23e5ae62 100644 --- a/reactos/dll/cpl/console/lang/en-US.rc +++ b/reactos/dll/cpl/console/lang/en-US.rc @@ -35,10 +35,10 @@ BEGIN LTEXT "Window Preview:", -1, 10, 10, 94, 10 LTEXT "Size:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Font:", -1, 10, 105, 33, 10 CHECKBOX "&Bold fonts", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Each character is:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/es-ES.rc b/reactos/dll/cpl/console/lang/es-ES.rc index 4cb83e117ee..7c4efda92a4 100644 --- a/reactos/dll/cpl/console/lang/es-ES.rc +++ b/reactos/dll/cpl/console/lang/es-ES.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "Ventana de Previsualización", -1, 10, 7, 65, 10 LTEXT "Tamaño", -1, 130, 10, 30, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 115, 70 - LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Fuente", -1, 10, 105, 35, 10 CHECKBOX "&Negrita", IDC_CHECK_BOLD_FONTS, 45, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 10, 155, 200, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 15, 165, 95, 35 LTEXT "Cada caracter es:", -1, 130, 165, 75, 10 diff --git a/reactos/dll/cpl/console/lang/fr-FR.rc b/reactos/dll/cpl/console/lang/fr-FR.rc index 4e57984b2fb..f0ab9fdcd3f 100644 --- a/reactos/dll/cpl/console/lang/fr-FR.rc +++ b/reactos/dll/cpl/console/lang/fr-FR.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "Fenêtre de Prévisualisation :", -1, 10, 10, 94, 10 LTEXT "Taille :", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Police :", -1, 10, 105, 33, 10 CHECKBOX "&Gras", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Chaque caractère utilise :", -1, 124, 166, 85, 10 diff --git a/reactos/dll/cpl/console/lang/he-IL.rc b/reactos/dll/cpl/console/lang/he-IL.rc index a68475013f4..0a29198e2fd 100644 --- a/reactos/dll/cpl/console/lang/he-IL.rc +++ b/reactos/dll/cpl/console/lang/he-IL.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "תצוגה מקדימה:", -1, 10, 10, 94, 10 LTEXT "גודל:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "גופן:", -1, 10, 105, 33, 10 CHECKBOX "גופנים מודגשים", IDC_CHECK_BOLD_FONTS, 41, 105, 33, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Each character is:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/id-ID.rc b/reactos/dll/cpl/console/lang/id-ID.rc index e84bcbfe107..48ef1dab638 100644 --- a/reactos/dll/cpl/console/lang/id-ID.rc +++ b/reactos/dll/cpl/console/lang/id-ID.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "Tinjauan Jendela", -1, 10, 7, 65, 10 LTEXT "Ukuran", -1, 130, 10, 30, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 115, 70 - LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Font", -1, 10, 105, 35, 10 CHECKBOX "Font &tebal", IDC_CHECK_BOLD_FONTS, 45, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 10, 155, 200, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 15, 165, 95, 35 LTEXT "Setiap karakter adalah:", -1, 130, 165, 75, 10 diff --git a/reactos/dll/cpl/console/lang/it-IT.rc b/reactos/dll/cpl/console/lang/it-IT.rc index cfc0bd31e9b..f0d3c6c341e 100644 --- a/reactos/dll/cpl/console/lang/it-IT.rc +++ b/reactos/dll/cpl/console/lang/it-IT.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "Anteprima", -1, 10, 7, 65, 10 LTEXT "Dimansione", -1, 130, 10, 30, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 115, 70 - LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Font", -1, 10, 105, 35, 10 CHECKBOX "&Grassetto fonts", IDC_CHECK_BOLD_FONTS, 45, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 10, 155, 200, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 15, 165, 95, 35 LTEXT "Ogni carattere è:", -1, 130, 165, 75, 10 diff --git a/reactos/dll/cpl/console/lang/no-NO.rc b/reactos/dll/cpl/console/lang/no-NO.rc index 634812113d8..aba111646b2 100644 --- a/reactos/dll/cpl/console/lang/no-NO.rc +++ b/reactos/dll/cpl/console/lang/no-NO.rc @@ -35,10 +35,10 @@ BEGIN LTEXT "Vindu forhåndsvisning:", -1, 10, 10, 94, 10 LTEXT "Størrelse:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Skrift:", -1, 10, 105, 33, 10 CHECKBOX "&Fet skrift", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Hver tegn er:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/pl-PL.rc b/reactos/dll/cpl/console/lang/pl-PL.rc index bcee44f7b5c..72384009036 100644 --- a/reactos/dll/cpl/console/lang/pl-PL.rc +++ b/reactos/dll/cpl/console/lang/pl-PL.rc @@ -42,10 +42,10 @@ BEGIN LTEXT "Okno podglądu", -1, 10, 7, 65, 10 LTEXT "Rozmiar", -1, 130, 10, 30, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 115, 70 - LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 130, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Czcionka", -1, 10, 105, 35, 10 CHECKBOX "&Pogrubiona czcionka", IDC_CHECK_BOLD_FONTS, 45, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 50, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 10, 155, 200, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 15, 165, 95, 35 LTEXT "Pogrubiona czcionka:", -1, 130, 165, 75, 10 diff --git a/reactos/dll/cpl/console/lang/ro-RO.rc b/reactos/dll/cpl/console/lang/ro-RO.rc index 7c33e3a6fbe..fda9e11e1e9 100644 --- a/reactos/dll/cpl/console/lang/ro-RO.rc +++ b/reactos/dll/cpl/console/lang/ro-RO.rc @@ -44,10 +44,10 @@ BEGIN LTEXT "Previzionare:", -1, 10, 10, 94, 10 LTEXT "&Mărime:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "F&ont:", -1, 10, 105, 33, 10 CHECKBOX "&Aldin", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Fiecare caracter are:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/ru-RU.rc b/reactos/dll/cpl/console/lang/ru-RU.rc index 7a71960c3c0..6abf4279b9f 100644 --- a/reactos/dll/cpl/console/lang/ru-RU.rc +++ b/reactos/dll/cpl/console/lang/ru-RU.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "Окно предпросмотра:", -1, 10, 10, 94, 10 LTEXT "Размер:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Шрифт:", -1, 10, 105, 33, 10 CHECKBOX "&Жирный", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Каждый символ:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/sk-SK.rc b/reactos/dll/cpl/console/lang/sk-SK.rc index 6392d83271b..67ab2a28315 100644 --- a/reactos/dll/cpl/console/lang/sk-SK.rc +++ b/reactos/dll/cpl/console/lang/sk-SK.rc @@ -39,10 +39,10 @@ BEGIN LTEXT "Ukážka okna:", -1, 10, 10, 94, 10 LTEXT "Veľkosť:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Písmo:", -1, 10, 105, 33, 10 CHECKBOX "&Tučné písma", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Každý znak je:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/sq-AL.rc b/reactos/dll/cpl/console/lang/sq-AL.rc index 8a2364e66d7..185759d3aea 100644 --- a/reactos/dll/cpl/console/lang/sq-AL.rc +++ b/reactos/dll/cpl/console/lang/sq-AL.rc @@ -39,10 +39,10 @@ BEGIN LTEXT "Dritare Preview:", -1, 10, 10, 94, 10 LTEXT "Masë:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Font:", -1, 10, 105, 33, 10 CHECKBOX "&Bold fonts", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Çdo krarakter është:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/tr-TR.rc b/reactos/dll/cpl/console/lang/tr-TR.rc index 7521b5bcce9..ead07ea068e 100644 --- a/reactos/dll/cpl/console/lang/tr-TR.rc +++ b/reactos/dll/cpl/console/lang/tr-TR.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "Pencere Ön İzlemesi:", -1, 10, 10, 94, 10 LTEXT "&Boyutlar:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Yazı Tipi:", -1, 10, 105, 33, 10 CHECKBOX "&Kalın Yazı Tipleri", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Tüm damgalar:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/uk-UA.rc b/reactos/dll/cpl/console/lang/uk-UA.rc index dbe92ecf144..f275427ebc2 100644 --- a/reactos/dll/cpl/console/lang/uk-UA.rc +++ b/reactos/dll/cpl/console/lang/uk-UA.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "Зразок вікна", -1, 10, 10, 94, 10 LTEXT "Size:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&Шрифт:", -1, 10, 105, 33, 10 CHECKBOX "&Жирні", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "Кожен символ:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/lang/zh-CN.rc b/reactos/dll/cpl/console/lang/zh-CN.rc index fa8d9bd0390..c36cea883ec 100644 --- a/reactos/dll/cpl/console/lang/zh-CN.rc +++ b/reactos/dll/cpl/console/lang/zh-CN.rc @@ -37,10 +37,10 @@ BEGIN LTEXT "窗口预览:", -1, 10, 10, 94, 10 LTEXT "大小:", -1, 180, 10, 36, 10 CONTROL "", IDC_STATIC_FONT_WINDOW_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 10, 20, 163, 74 - LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTSIZE, 181, 20, 55, 80, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL LTEXT "&字体(&F):", -1, 10, 105, 33, 10 CHECKBOX "粗体(&B)", IDC_CHECK_BOLD_FONTS, 56, 105, 60, 10 - LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + LISTBOX IDC_LBOX_FONTTYPE, 10, 120, 110, 40, LBS_SORT | LBS_HASSTRINGS | WS_VSCROLL GROUPBOX "", IDC_GROUPBOX_FONT_NAME, 6, 156, 241, 50 CONTROL "", IDC_STATIC_SELECT_FONT_PREVIEW, "Static", SS_OWNERDRAW | SS_SUNKEN, 16, 165, 95, 35 LTEXT "每个字符为:", -1, 124, 166, 75, 10 diff --git a/reactos/dll/cpl/console/layout.c b/reactos/dll/cpl/console/layout.c index 90926c821c2..1b99e400b9c 100644 --- a/reactos/dll/cpl/console/layout.c +++ b/reactos/dll/cpl/console/layout.c @@ -107,6 +107,8 @@ PaintText(LPDRAWITEMSTRUCT drawItem, HBRUSH hBrush; HFONT Font, OldFont; + COORD FontSize = GuiInfo->FontSize; + if (TextMode == Screen) CurrentAttrib = pConInfo->ci.ScreenAttrib; else if (TextMode == Popup) @@ -120,8 +122,11 @@ PaintText(LPDRAWITEMSTRUCT drawItem, hBrush = CreateSolidBrush(nbkColor); if (!hBrush) return FALSE; - Font = CreateFontW(GuiInfo->FontSize.Y, - GuiInfo->FontSize.X, + FontSize.Y = FontSize.Y > 0 ? -MulDiv(FontSize.Y, GetDeviceCaps(drawItem->hDC, LOGPIXELSY), 72) + : FontSize.Y; + + Font = CreateFontW(FontSize.Y, + FontSize.X, 0, TA_BASELINE, GuiInfo->FontWeight, @@ -131,7 +136,7 @@ PaintText(LPDRAWITEMSTRUCT drawItem, OEM_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, - DEFAULT_QUALITY, // NONANTIALIASED_QUALITY ; ANTIALIASED_QUALITY + DEFAULT_QUALITY, FIXED_PITCH | GuiInfo->FontFamily, GuiInfo->FaceName); if (Font == NULL) @@ -154,7 +159,7 @@ PaintText(LPDRAWITEMSTRUCT drawItem, DrawTextW(drawItem->hDC, szPreviewText, wcslen(szPreviewText), &drawItem->rcItem, 0); SetTextColor(drawItem->hDC, ptColor); SetBkColor(drawItem->hDC, pbkColor); - DeleteObject((HGDIOBJ)hBrush); + DeleteObject(hBrush); SelectObject(drawItem->hDC, OldFont); DeleteObject(Font); diff --git a/reactos/dll/win32/kernel32/client/console/console.c b/reactos/dll/win32/kernel32/client/console/console.c index 0a4059ac84a..ee630cbac3a 100644 --- a/reactos/dll/win32/kernel32/client/console/console.c +++ b/reactos/dll/win32/kernel32/client/console/console.c @@ -3,8 +3,8 @@ * PROJECT: ReactOS system libraries * FILE: dll/win32/kernel32/client/console/console.c * PURPOSE: Win32 server console functions - * PROGRAMMERS: James Tabor - * + * PROGRAMMERS: James Tabor + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *******************************************************************/ @@ -18,29 +18,37 @@ /* GLOBALS ********************************************************************/ extern RTL_CRITICAL_SECTION ConsoleLock; -extern BOOL ConsoleInitialized; -extern BOOL WINAPI IsDebuggerPresent(VOID); +extern BOOLEAN ConsoleInitialized; /* Console reserved "file" names */ static LPCWSTR BaseConFileName = CONSOLE_FILE_NAME; static LPCWSTR BaseConInputFileName = CONSOLE_INPUT_FILE_NAME; static LPCWSTR BaseConOutputFileName = CONSOLE_OUTPUT_FILE_NAME; -PHANDLER_ROUTINE InitialHandler[1]; -PHANDLER_ROUTINE* CtrlHandlers; -ULONG NrCtrlHandlers; -ULONG NrAllocatedHandlers; -BOOL LastCloseNotify = FALSE; +/* Console Control handling */ +static PHANDLER_ROUTINE InitialHandler[1]; +static PHANDLER_ROUTINE* CtrlHandlers; +static ULONG NrCtrlHandlers; +static ULONG NrAllocatedHandlers; +static BOOLEAN LastCloseNotify = FALSE; +extern BOOL WINAPI IsDebuggerPresent(VOID); + +/* Console Input facilities */ HANDLE InputWaitHandle = INVALID_HANDLE_VALUE; -#define INPUTEXENAME_BUFLEN 256 -static WCHAR InputExeName[INPUTEXENAME_BUFLEN]; +#define EXENAME_LENGTH 255 + 1 +static RTL_CRITICAL_SECTION ExeNameLock; +static BOOLEAN ExeNameInitialized; +static WCHAR ExeNameBuffer[EXENAME_LENGTH]; // NULL-terminated +static USHORT ExeNameLength; // Count in number of characters without NULL +static WCHAR StartDirBuffer[MAX_PATH + 1]; // NULL-terminated +static USHORT StartDirLength; // Count in number of characters without NULL /* Default Console Control Handler ********************************************/ -BOOL +static BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event) { @@ -193,8 +201,7 @@ ConsoleControlDispatcher(IN LPVOID lpThreadParameter) } VOID -WINAPI -InitConsoleCtrlHandling(VOID) +InitializeCtrlHandling(VOID) { /* Initialize Console Ctrl Handler */ NrAllocatedHandlers = NrCtrlHandlers = 1; @@ -203,6 +210,135 @@ InitConsoleCtrlHandling(VOID) } +/* Input EXE Name Support *****************************************************/ + +VOID +InitExeName(VOID) +{ + NTSTATUS Status; + PPEB Peb = NtCurrentPeb(); + PCURDIR CurrentDirectory = &Peb->ProcessParameters->CurrentDirectory; + PLDR_DATA_TABLE_ENTRY ImageEntry; + + if (ExeNameInitialized) return; + + /* Initialize the EXE name lock */ + Status = RtlInitializeCriticalSection(&ExeNameLock); + if (!NT_SUCCESS(Status)) return; + ExeNameInitialized = TRUE; + + ImageEntry = CONTAINING_RECORD(Peb->Ldr->InLoadOrderModuleList.Flink, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + /* Retrieve the EXE name, NULL-terminate it... */ + ExeNameLength = min(sizeof(ExeNameBuffer)/sizeof(ExeNameBuffer[0]), + ImageEntry->BaseDllName.Length / sizeof(WCHAR)); + RtlCopyMemory(ExeNameBuffer, + ImageEntry->BaseDllName.Buffer, + ImageEntry->BaseDllName.Length); + ExeNameBuffer[ExeNameLength] = UNICODE_NULL; + + /* ... and retrieve the current directory path and NULL-terminate it. */ + StartDirLength = min(sizeof(StartDirBuffer)/sizeof(StartDirBuffer[0]), + CurrentDirectory->DosPath.Length / sizeof(WCHAR)); + RtlCopyMemory(StartDirBuffer, + CurrentDirectory->DosPath.Buffer, + CurrentDirectory->DosPath.Length); + StartDirBuffer[StartDirLength] = UNICODE_NULL; +} + +/* + * NOTE: + * The "LPDWORD Length" parameters point on input to the maximum size of + * the buffers that can hold data (if != 0), and on output they hold the + * real size of the data. If "Length" are == 0 on input, then on output + * they receive the full size of the data. + * The "LPWSTR* String" parameters have a double meaning: + * - when "CaptureStrings" is TRUE, data is copied to the buffers pointed + * by the pointers (*String). + * - when "CaptureStrings" is FALSE, "*String" are set to the addresses of + * the source data. + */ +VOID +SetUpAppName(IN BOOLEAN CaptureStrings, + IN OUT LPDWORD CurDirLength, + IN OUT LPWSTR* CurDir, + IN OUT LPDWORD AppNameLength, + IN OUT LPWSTR* AppName) +{ + DWORD Length; + + /* Retrieve the needed buffer size */ + Length = (StartDirLength + 1) * sizeof(WCHAR); + if (*CurDirLength > 0) Length = min(Length, *CurDirLength); + *CurDirLength = Length; + + /* Capture the data if needed, or, return a pointer to it */ + if (CaptureStrings) + { + /* + * Length is always >= sizeof(WCHAR). Copy everything but the + * possible trailing NULL character, and then NULL-terminate. + */ + Length -= sizeof(WCHAR); + RtlCopyMemory(*CurDir, StartDirBuffer, Length); + (*CurDir)[Length / sizeof(WCHAR)] = UNICODE_NULL; + } + else + { + *CurDir = StartDirBuffer; + } + + /* Retrieve the needed buffer size */ + Length = (ExeNameLength + 1) * sizeof(WCHAR); + if (*AppNameLength > 0) Length = min(Length, *AppNameLength); + *AppNameLength = Length; + + /* Capture the data if needed, or, return a pointer to it */ + if (CaptureStrings) + { + /* + * Length is always >= sizeof(WCHAR). Copy everything but the + * possible trailing NULL character, and then NULL-terminate. + */ + Length -= sizeof(WCHAR); + RtlCopyMemory(*AppName, ExeNameBuffer, Length); + (*AppName)[Length / sizeof(WCHAR)] = UNICODE_NULL; + } + else + { + *AppName = ExeNameBuffer; + } +} + +USHORT +GetCurrentExeName(OUT PWCHAR ExeName, + IN USHORT BufferSize) +{ + USHORT ExeLength; + + if (ExeNameInitialized) + { + RtlEnterCriticalSection(&ExeNameLock); + + if (BufferSize > ExeNameLength * sizeof(WCHAR)) + BufferSize = ExeNameLength * sizeof(WCHAR); + + RtlCopyMemory(ExeName, ExeNameBuffer, BufferSize); + + RtlLeaveCriticalSection(&ExeNameLock); + ExeLength = BufferSize; + } + else + { + *ExeName = UNICODE_NULL; + ExeLength = 0; + } + + return ExeLength; +} + /* FUNCTIONS ******************************************************************/ LPCWSTR @@ -999,77 +1135,198 @@ SetStdHandle(DWORD nStdHandle, } -/*-------------------------------------------------------------- - * AllocConsole - * +/* * @implemented */ -BOOL -WINAPI -AllocConsole(VOID) +static BOOL +IntAllocConsole(LPWSTR Title, + DWORD TitleLength, + LPWSTR Desktop, + DWORD DesktopLength, + LPWSTR CurDir, + DWORD CurDirLength, + LPWSTR AppName, + DWORD AppNameLength, + LPTHREAD_START_ROUTINE CtrlRoutine, + LPTHREAD_START_ROUTINE PropRoutine, + PCONSOLE_START_INFO ConsoleStartInfo) { + BOOL Success = TRUE; +#ifdef USE_CONSOLE_INIT_HANDLES NTSTATUS Status; - PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; +#endif + CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest; PCSR_CAPTURE_BUFFER CaptureBuffer; - if (Parameters->ConsoleHandle) - { - DPRINT1("AllocConsole: Allocating a console to a process already having one\n"); - SetLastError(ERROR_ACCESS_DENIED); - return FALSE; - } + AllocConsoleRequest->CtrlRoutine = CtrlRoutine; + AllocConsoleRequest->PropRoutine = PropRoutine; - CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO)); + CaptureBuffer = CsrAllocateCaptureBuffer(5, TitleLength + + DesktopLength + + CurDirLength + + AppNameLength + + sizeof(CONSOLE_START_INFO)); if (CaptureBuffer == NULL) { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; + Success = FALSE; + goto Quit; } - CsrAllocateMessagePointer(CaptureBuffer, - sizeof(CONSOLE_START_INFO), - (PVOID*)&AllocConsoleRequest->ConsoleStartInfo); + CsrCaptureMessageBuffer(CaptureBuffer, + ConsoleStartInfo, + sizeof(CONSOLE_START_INFO), + (PVOID*)&AllocConsoleRequest->ConsoleStartInfo); - InitConsoleInfo(AllocConsoleRequest->ConsoleStartInfo, - &Parameters->ImagePathName); + AllocConsoleRequest->TitleLength = TitleLength; + CsrCaptureMessageBuffer(CaptureBuffer, + Title, + TitleLength, + (PVOID*)&AllocConsoleRequest->ConsoleTitle); - AllocConsoleRequest->ConsoleHandle = NULL; - AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher; - AllocConsoleRequest->PropDispatcher = PropDialogHandler; + AllocConsoleRequest->DesktopLength = DesktopLength; + CsrCaptureMessageBuffer(CaptureBuffer, + Desktop, + DesktopLength, + (PVOID*)&AllocConsoleRequest->Desktop); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc), - sizeof(CONSOLE_ALLOCCONSOLE)); + AllocConsoleRequest->CurDirLength = CurDirLength; + CsrCaptureMessageBuffer(CaptureBuffer, + CurDir, + CurDirLength, + (PVOID*)&AllocConsoleRequest->CurDir); - CsrFreeCaptureBuffer(CaptureBuffer); + AllocConsoleRequest->AppNameLength = AppNameLength; + CsrCaptureMessageBuffer(CaptureBuffer, + AppName, + AppNameLength, + (PVOID*)&AllocConsoleRequest->AppName); + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc), + sizeof(*AllocConsoleRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) + { + BaseSetLastNTError(ApiMessage.Status); + Success = FALSE; + goto Quit; + } + +#ifdef USE_CONSOLE_INIT_HANDLES + // Is AllocConsoleRequest->ConsoleStartInfo->Events aligned on handle boundary ???? + Status = NtWaitForMultipleObjects(2, AllocConsoleRequest->ConsoleStartInfo->Events, + WaitAny, FALSE, NULL); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); - return FALSE; + Success = FALSE; + goto Quit; } - Parameters->ConsoleHandle = AllocConsoleRequest->ConsoleHandle; - SetStdHandle(STD_INPUT_HANDLE , AllocConsoleRequest->InputHandle ); - SetStdHandle(STD_OUTPUT_HANDLE, AllocConsoleRequest->OutputHandle); - SetStdHandle(STD_ERROR_HANDLE , AllocConsoleRequest->ErrorHandle ); + NtClose(AllocConsoleRequest->ConsoleStartInfo->Events[0]); + NtClose(AllocConsoleRequest->ConsoleStartInfo->Events[1]); + if (Status != STATUS_SUCCESS) + { + NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; + Success = FALSE; + } + else +#endif + { + RtlCopyMemory(ConsoleStartInfo, + AllocConsoleRequest->ConsoleStartInfo, + sizeof(CONSOLE_START_INFO)); + Success = TRUE; + } - /* Initialize Console Ctrl Handler */ - InitConsoleCtrlHandling(); +Quit: + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + return Success; +} - InputWaitHandle = AllocConsoleRequest->InputWaitHandle; +BOOL +WINAPI +AllocConsole(VOID) +{ + BOOL Success; + CONSOLE_START_INFO ConsoleStartInfo; - return TRUE; + PWCHAR ConsoleTitle; + PWCHAR Desktop; + PWCHAR AppName; + PWCHAR CurDir; + + ULONG TitleLength = (MAX_PATH + 1) * sizeof(WCHAR); + ULONG DesktopLength = (MAX_PATH + 1) * sizeof(WCHAR); + ULONG AppNameLength = 128 * sizeof(WCHAR); + ULONG CurDirLength = (MAX_PATH + 1) * sizeof(WCHAR); + + LCID lcid; + + RtlEnterCriticalSection(&ConsoleLock); + + if (NtCurrentPeb()->ProcessParameters->ConsoleHandle) + { + DPRINT1("AllocConsole: Allocating a console to a process already having one\n"); + SetLastError(ERROR_ACCESS_DENIED); + Success = FALSE; + goto Quit; + } + + /* Set up the console properties */ + SetUpConsoleInfo(FALSE, + &TitleLength, + &ConsoleTitle, + &DesktopLength, + &Desktop, + &ConsoleStartInfo); + DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n", + ConsoleTitle, Desktop); + + /* Initialize the Input EXE name */ + InitExeName(); + SetUpAppName(FALSE, + &CurDirLength, + &CurDir, + &AppNameLength, + &AppName); + DPRINT("CurDir = '%S' - AppName = '%S'\n", + CurDir, AppName); + + Success = IntAllocConsole(ConsoleTitle, + TitleLength, + Desktop, + DesktopLength, + CurDir, + CurDirLength, + AppName, + AppNameLength, + ConsoleControlDispatcher, + PropDialogHandler, + &ConsoleStartInfo); + if (Success) + { + /* Set up the handles */ + SetUpHandles(&ConsoleStartInfo); + InputWaitHandle = ConsoleStartInfo.InputWaitHandle; + + /* Initialize Console Ctrl Handling */ + InitializeCtrlHandling(); + + /* Sets the current console locale for this thread */ + SetTEBLangID(lcid); + } + +Quit: + RtlLeaveCriticalSection(&ConsoleLock); + return Success; } -/*-------------------------------------------------------------- - * FreeConsole - * +/* * @implemented */ BOOL @@ -1114,9 +1371,7 @@ FreeConsole(VOID) } -/*-------------------------------------------------------------- - * GetConsoleScreenBufferInfo - * +/* * @implemented */ BOOL @@ -1159,9 +1414,7 @@ GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * SetConsoleCursorPosition - * +/* * @implemented */ BOOL @@ -1190,9 +1443,7 @@ SetConsoleCursorPosition(HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * GetConsoleMode - * +/* * @implemented */ BOOL @@ -1228,9 +1479,7 @@ GetConsoleMode(HANDLE hConsoleHandle, } -/*-------------------------------------------------------------- - * SetConsoleMode - * +/* * @implemented */ BOOL @@ -1259,9 +1508,7 @@ SetConsoleMode(HANDLE hConsoleHandle, } -/*-------------------------------------------------------------- - * GetNumberOfConsoleInputEvents - * +/* * @implemented */ BOOL @@ -1298,9 +1545,7 @@ GetNumberOfConsoleInputEvents(HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * GetLargestConsoleWindowSize - * +/* * @implemented */ COORD @@ -1329,9 +1574,7 @@ GetLargestConsoleWindowSize(HANDLE hConsoleOutput) } -/*-------------------------------------------------------------- - * GetConsoleCursorInfo - * +/* * @implemented */ BOOL @@ -1371,9 +1614,7 @@ GetConsoleCursorInfo(HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * SetConsoleCursorInfo - * +/* * @implemented */ BOOL @@ -1402,9 +1643,7 @@ SetConsoleCursorInfo(HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * GetNumberOfConsoleMouseButtons - * +/* * @implemented */ BOOL @@ -1431,9 +1670,7 @@ GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons) } -/*-------------------------------------------------------------- - * SetConsoleActiveScreenBuffer - * +/* * @implemented */ BOOL @@ -1460,9 +1697,7 @@ SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput) } -/*-------------------------------------------------------------- - * FlushConsoleInputBuffer - * +/* * @implemented */ BOOL @@ -1489,9 +1724,7 @@ FlushConsoleInputBuffer(HANDLE hConsoleInput) } -/*-------------------------------------------------------------- - * SetConsoleScreenBufferSize - * +/* * @implemented */ BOOL @@ -1564,9 +1797,7 @@ IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * ScrollConsoleScreenBufferA - * +/* * @implemented */ BOOL @@ -1586,9 +1817,7 @@ ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * ScrollConsoleScreenBufferW - * +/* * @implemented */ BOOL @@ -1608,9 +1837,7 @@ ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * SetConsoleWindowInfo - * +/* * @implemented */ BOOL @@ -1647,9 +1874,7 @@ SetConsoleWindowInfo(HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * SetConsoleTextAttribute - * +/* * @implemented */ BOOL @@ -1774,9 +1999,7 @@ SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, } -/*-------------------------------------------------------------- - * GenerateConsoleCtrlEvent - * +/* * @implemented */ BOOL @@ -1854,9 +2077,9 @@ IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode) memcpy(lpConsoleTitle, TitleRequest->Title, TitleRequest->Length); if (bUnicode) - ((LPWSTR)lpConsoleTitle)[dwNumChars] = L'\0'; + ((LPWSTR)lpConsoleTitle)[dwNumChars] = UNICODE_NULL; else - ((LPSTR)lpConsoleTitle)[dwNumChars] = '\0'; + ((LPSTR)lpConsoleTitle)[dwNumChars] = ANSI_NULL; } CsrFreeCaptureBuffer(CaptureBuffer); @@ -1865,9 +2088,7 @@ IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode) } -/*-------------------------------------------------------------- - * GetConsoleTitleW - * +/* * @implemented */ DWORD @@ -1879,9 +2100,7 @@ GetConsoleTitleW(LPWSTR lpConsoleTitle, } -/*-------------------------------------------------------------- - * GetConsoleTitleA - * +/* * @implemented */ DWORD @@ -1935,9 +2154,7 @@ IntSetConsoleTitle(CONST VOID *lpConsoleTitle, BOOLEAN bUnicode) return TRUE; } -/*-------------------------------------------------------------- - * SetConsoleTitleW - * +/* * @implemented */ BOOL @@ -1948,9 +2165,7 @@ SetConsoleTitleW(LPCWSTR lpConsoleTitle) } -/*-------------------------------------------------------------- - * SetConsoleTitleA - * +/* * @implemented */ BOOL @@ -1961,9 +2176,7 @@ SetConsoleTitleA(LPCSTR lpConsoleTitle) } -/*-------------------------------------------------------------- - * CreateConsoleScreenBuffer - * +/* * @implemented */ HANDLE @@ -2040,9 +2253,7 @@ CreateConsoleScreenBuffer(DWORD dwDesiredAccess, } -/*-------------------------------------------------------------- - * GetConsoleCP - * +/* * @implemented */ UINT @@ -2070,9 +2281,7 @@ GetConsoleCP(VOID) } -/*-------------------------------------------------------------- - * SetConsoleCP - * +/* * @implemented */ BOOL @@ -2102,9 +2311,7 @@ SetConsoleCP(UINT wCodePageID) } -/*-------------------------------------------------------------- - * GetConsoleOutputCP - * +/* * @implemented */ UINT @@ -2132,9 +2339,7 @@ GetConsoleOutputCP(VOID) } -/*-------------------------------------------------------------- - * SetConsoleOutputCP - * +/* * @implemented */ BOOL @@ -2164,9 +2369,7 @@ SetConsoleOutputCP(UINT wCodePageID) } -/*-------------------------------------------------------------- - * GetConsoleProcessList - * +/* * @implemented */ DWORD @@ -2222,9 +2425,7 @@ GetConsoleProcessList(LPDWORD lpdwProcessList, } -/*-------------------------------------------------------------- - * GetConsoleSelectionInfo - * +/* * @implemented */ BOOL @@ -2258,60 +2459,137 @@ GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo) } -/*-------------------------------------------------------------- - * AttachConsole - * +/* * @implemented - * * @note Strongly inspired by AllocConsole. */ +static BOOL +IntAttachConsole(DWORD ProcessId, + LPTHREAD_START_ROUTINE CtrlRoutine, + LPTHREAD_START_ROUTINE PropRoutine, + PCONSOLE_START_INFO ConsoleStartInfo) +{ + BOOL Success = TRUE; +#ifdef USE_CONSOLE_INIT_HANDLES + NTSTATUS Status; +#endif + + CONSOLE_API_MESSAGE ApiMessage; + PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + + AttachConsoleRequest->ProcessId = ProcessId; + AttachConsoleRequest->CtrlRoutine = CtrlRoutine; + AttachConsoleRequest->PropRoutine = PropRoutine; + + CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO)); + if (CaptureBuffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + Success = FALSE; + goto Quit; + } + + CsrCaptureMessageBuffer(CaptureBuffer, + ConsoleStartInfo, + sizeof(CONSOLE_START_INFO), + (PVOID*)&AttachConsoleRequest->ConsoleStartInfo); + + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach), + sizeof(*AttachConsoleRequest)); + if (!NT_SUCCESS(ApiMessage.Status)) + { + BaseSetLastNTError(ApiMessage.Status); + Success = FALSE; + goto Quit; + } + +#ifdef USE_CONSOLE_INIT_HANDLES + // Is AttachConsoleRequest->ConsoleStartInfo->Events aligned on handle boundary ???? + Status = NtWaitForMultipleObjects(2, AttachConsoleRequest->ConsoleStartInfo->Events, + WaitAny, FALSE, NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + Success = FALSE; + goto Quit; + } + + NtClose(AttachConsoleRequest->ConsoleStartInfo->Events[0]); + NtClose(AttachConsoleRequest->ConsoleStartInfo->Events[1]); + if (Status != STATUS_SUCCESS) + { + NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; + Success = FALSE; + } + else +#endif + { + RtlCopyMemory(ConsoleStartInfo, + AttachConsoleRequest->ConsoleStartInfo, + sizeof(CONSOLE_START_INFO)); + Success = TRUE; + } + +Quit: + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + return Success; +} + BOOL WINAPI AttachConsole(DWORD dwProcessId) { - NTSTATUS Status; - PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; - CONSOLE_API_MESSAGE ApiMessage; - PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest; + BOOL Success; + CONSOLE_START_INFO ConsoleStartInfo; - if (Parameters->ConsoleHandle) + DWORD dummy; + LCID lcid; + + RtlEnterCriticalSection(&ConsoleLock); + + if (NtCurrentPeb()->ProcessParameters->ConsoleHandle) { DPRINT1("AttachConsole: Attaching a console to a process already having one\n"); SetLastError(ERROR_ACCESS_DENIED); - return FALSE; + Success = FALSE; + goto Quit; } - AttachConsoleRequest->ProcessId = dwProcessId; - AttachConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher; - AttachConsoleRequest->PropDispatcher = PropDialogHandler; + /* Set up the console properties */ + SetUpConsoleInfo(FALSE, + &dummy, + NULL, + &dummy, + NULL, + &ConsoleStartInfo); - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach), - sizeof(CONSOLE_ATTACHCONSOLE)); - if (!NT_SUCCESS(Status)) + Success = IntAttachConsole(dwProcessId, + ConsoleControlDispatcher, + PropDialogHandler, + &ConsoleStartInfo); + if (Success) { - BaseSetLastNTError(Status); - return FALSE; + /* Set up the handles */ + SetUpHandles(&ConsoleStartInfo); + InputWaitHandle = ConsoleStartInfo.InputWaitHandle; + + /* Initialize Console Ctrl Handling */ + InitializeCtrlHandling(); + + /* Sets the current console locale for this thread */ + SetTEBLangID(lcid); } - Parameters->ConsoleHandle = AttachConsoleRequest->ConsoleHandle; - SetStdHandle(STD_INPUT_HANDLE , AttachConsoleRequest->InputHandle ); - SetStdHandle(STD_OUTPUT_HANDLE, AttachConsoleRequest->OutputHandle); - SetStdHandle(STD_ERROR_HANDLE , AttachConsoleRequest->ErrorHandle ); - - /* Initialize Console Ctrl Handler */ - InitConsoleCtrlHandling(); - - InputWaitHandle = AttachConsoleRequest->InputWaitHandle; - - return TRUE; +Quit: + RtlLeaveCriticalSection(&ConsoleLock); + return Success; } -/*-------------------------------------------------------------- - * GetConsoleWindow - * +/* * @implemented */ HWND @@ -2337,9 +2615,7 @@ GetConsoleWindow(VOID) } -/*-------------------------------------------------------------- - * SetConsoleIcon - * +/* * @implemented */ BOOL @@ -2369,35 +2645,35 @@ SetConsoleIcon(HICON hIcon) /****************************************************************************** * \name SetConsoleInputExeNameW * \brief Sets the console input file name from a unicode string. - * \param lpInputExeName Pointer to a unicode string with the name. + * \param lpExeName Pointer to a unicode string with the name. * \return TRUE if successful, FALSE if unsuccsedful. - * \remarks If lpInputExeName is 0 or the string length is 0 or greater than 255, + * \remarks If lpExeName is 0 or the string length is 0 or greater than 255, * the function fails and sets last error to ERROR_INVALID_PARAMETER. */ BOOL WINAPI -SetConsoleInputExeNameW(LPCWSTR lpInputExeName) +SetConsoleInputExeNameW(IN LPWSTR lpExeName) { - int lenName; + DWORD ExeLength; - if ( !lpInputExeName || - (lenName = lstrlenW(lpInputExeName)) == 0 || - lenName > INPUTEXENAME_BUFLEN - 1 ) + ExeLength = lstrlenW(lpExeName); + if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH)) { /* Fail if string is empty or too long */ SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - RtlEnterCriticalSection(&ConsoleLock); + RtlEnterCriticalSection(&ExeNameLock); _SEH2_TRY { - RtlCopyMemory(InputExeName, lpInputExeName, lenName * sizeof(WCHAR)); - InputExeName[lenName] = L'\0'; + /* Set the input EXE name, not NULL terminated */ + RtlCopyMemory(ExeNameBuffer, lpExeName, ExeLength * sizeof(WCHAR)); + ExeNameLength = (USHORT)ExeLength; } _SEH2_FINALLY { - RtlLeaveCriticalSection(&ConsoleLock); + RtlLeaveCriticalSection(&ExeNameLock); } _SEH2_END; @@ -2408,42 +2684,72 @@ SetConsoleInputExeNameW(LPCWSTR lpInputExeName) /****************************************************************************** * \name SetConsoleInputExeNameA * \brief Sets the console input file name from an ansi string. - * \param lpInputExeName Pointer to an ansi string with the name. + * \param lpExeName Pointer to an ansi string with the name. * \return TRUE if successful, FALSE if unsuccsedful. - * \remarks If lpInputExeName is 0 or the string length is 0 or greater than 255, + * \remarks If lpExeName is 0 or the string length is 0 or greater than 255, * the function fails and sets last error to ERROR_INVALID_PARAMETER. */ BOOL WINAPI -SetConsoleInputExeNameA(LPCSTR lpInputExeName) +SetConsoleInputExeNameA(IN LPSTR lpExeName) { - WCHAR Buffer[INPUTEXENAME_BUFLEN]; - ANSI_STRING InputExeNameA; - UNICODE_STRING InputExeNameU; NTSTATUS Status; +#ifdef USE_TEB_STATIC_USTR + PUNICODE_STRING ExeNameU; +#else + UNICODE_STRING ExeNameU; +#endif + ANSI_STRING ExeNameA; +#ifndef USE_TEB_STATIC_USTR + WCHAR Buffer[EXENAME_LENGTH]; +#endif - RtlInitAnsiString(&InputExeNameA, lpInputExeName); +#ifdef USE_TEB_STATIC_USTR + /* + * Use the TEB static UNICODE string for storage. It is already + * initialized at process creation time by the Memory Manager. + */ + ExeNameU = &NtCurrentTeb()->StaticUnicodeString; +#endif - if ( InputExeNameA.Length == 0 || - InputExeNameA.Length > INPUTEXENAME_BUFLEN - 1 ) + /* Initialize string for conversion */ + RtlInitAnsiString(&ExeNameA, lpExeName); + +#if 1 + if ((ExeNameA.Length == 0) || (ExeNameA.Length >= EXENAME_LENGTH)) { /* Fail if string is empty or too long */ SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } +#endif +#ifndef USE_TEB_STATIC_USTR + ExeNameU.Length = 0; + ExeNameU.MaximumLength = (USHORT)sizeof(Buffer); + ExeNameU.Buffer = Buffer; +#endif - InputExeNameU.Buffer = Buffer; - InputExeNameU.MaximumLength = sizeof(Buffer); - InputExeNameU.Length = 0; - - Status = RtlAnsiStringToUnicodeString(&InputExeNameU, &InputExeNameA, FALSE); +#ifdef USE_TEB_STATIC_USTR + Status = RtlAnsiStringToUnicodeString(ExeNameU, &ExeNameA, FALSE); +#else + Status = RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, FALSE); +#endif if (!NT_SUCCESS(Status)) { - BaseSetLastNTError(Status); + /* Fail if string is empty or too long */ + if (Status == STATUS_BUFFER_OVERFLOW) + SetLastError(ERROR_FILENAME_EXCED_RANGE); + else + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } - return SetConsoleInputExeNameW(InputExeNameU.Buffer); +#ifdef USE_TEB_STATIC_USTR + return SetConsoleInputExeNameW(ExeNameU->Buffer); +#else + return SetConsoleInputExeNameW(ExeNameU.Buffer); +#endif } @@ -2460,37 +2766,30 @@ SetConsoleInputExeNameA(LPCSTR lpInputExeName) */ DWORD WINAPI -GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer) +GetConsoleInputExeNameW(IN DWORD nBufferLength, + OUT LPWSTR lpExeName) { - ULONG lenName = lstrlenW(InputExeName); - - if (nBufferLength == 0) + if (nBufferLength <= ExeNameLength) { - /* Buffer size is requested, return it */ - return lenName + 1; - } - - if (lenName + 1 > nBufferLength) - { - /* Buffer is not large enough! */ + /* Buffer is not large enough! Return the correct size. */ SetLastError(ERROR_BUFFER_OVERFLOW); - return 2; + return ExeNameLength + 1; } - RtlEnterCriticalSection(&ConsoleLock); + RtlEnterCriticalSection(&ExeNameLock); _SEH2_TRY { - RtlCopyMemory(lpBuffer, InputExeName, lenName * sizeof(WCHAR)); - lpBuffer[lenName] = '\0'; + /* Copy the input EXE name and NULL-terminate it */ + RtlCopyMemory(lpExeName, ExeNameBuffer, ExeNameLength * sizeof(WCHAR)); + lpExeName[ExeNameLength] = UNICODE_NULL; } _SEH2_FINALLY { - RtlLeaveCriticalSection(&ConsoleLock); + RtlLeaveCriticalSection(&ExeNameLock); } _SEH2_END; - /* Success, return 1 */ - return 1; + return TRUE; } @@ -2505,33 +2804,40 @@ GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer) */ DWORD WINAPI -GetConsoleInputExeNameA(DWORD nBufferLength, LPSTR lpBuffer) +GetConsoleInputExeNameA(IN DWORD nBufferLength, + OUT LPSTR lpExeName) { - WCHAR Buffer[INPUTEXENAME_BUFLEN]; - DWORD Ret; + NTSTATUS Status; + DWORD ExeLength; UNICODE_STRING BufferU; ANSI_STRING BufferA; + WCHAR Buffer[EXENAME_LENGTH]; - /* Get the unicode name */ - Ret = GetConsoleInputExeNameW(sizeof(Buffer) / sizeof(Buffer[0]), Buffer); + /* Get the UNICODE name */ + ExeLength = GetConsoleInputExeNameW(EXENAME_LENGTH, Buffer); - /* Initialize strings for conversion */ + if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH)) + return ExeLength; + + /* Initialize the strings for conversion */ RtlInitUnicodeString(&BufferU, Buffer); BufferA.Length = 0; BufferA.MaximumLength = (USHORT)nBufferLength; - BufferA.Buffer = lpBuffer; + BufferA.Buffer = lpExeName; - /* Convert unicode name to ansi, copying as much chars as fit */ - RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE); - - /* Error handling */ - if (nBufferLength <= BufferU.Length / sizeof(WCHAR)) + /* Convert UNICODE name to ANSI, copying as much chars as it can fit */ + Status = RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE); + if (!NT_SUCCESS(Status)) { - SetLastError(ERROR_BUFFER_OVERFLOW); - return 2; + if (Status == STATUS_BUFFER_OVERFLOW) + { + SetLastError(ERROR_BUFFER_OVERFLOW); + return ExeLength + 1; + } + SetLastError(ERROR_INVALID_PARAMETER); } - return Ret; + return ExeLength; } BOOL diff --git a/reactos/dll/win32/kernel32/client/console/history.c b/reactos/dll/win32/kernel32/client/console/history.c index 2fc50245fb4..fdc582630a7 100644 --- a/reactos/dll/win32/kernel32/client/console/history.c +++ b/reactos/dll/win32/kernel32/client/console/history.c @@ -25,30 +25,6 @@ IntStringSize(LPCVOID String, ULONG Size = (Unicode ? wcslen(String) : strlen(String)) * sizeof(WCHAR); return (Size + 3) & ~3; } - - -/* Copy a string to a capture buffer */ -static VOID -IntCaptureMessageString(PCSR_CAPTURE_BUFFER CaptureBuffer, - LPCVOID String, - BOOL Unicode, - PUNICODE_STRING RequestString) -{ - ULONG Size; - if (Unicode) - { - Size = wcslen(String) * sizeof(WCHAR); - CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)String, Size, (PVOID *)&RequestString->Buffer); - } - else - { - Size = strlen(String); - CsrAllocateMessagePointer(CaptureBuffer, Size * sizeof(WCHAR), (PVOID *)&RequestString->Buffer); - Size = MultiByteToWideChar(CP_ACP, 0, String, Size, RequestString->Buffer, Size * sizeof(WCHAR)) - * sizeof(WCHAR); - } - RequestString->Length = RequestString->MaximumLength = (USHORT)Size; -} #endif static VOID @@ -80,8 +56,6 @@ IntExpungeConsoleCommandHistory(LPCVOID lpExeName, BOOLEAN bUnicode) return; } - // IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, - // &ExpungeCommandHistoryRequest->ExeName); CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)lpExeName, ExpungeCommandHistoryRequest->ExeLength, @@ -131,14 +105,11 @@ IntGetConsoleCommandHistory(LPVOID lpHistory, DWORD cbHistory, LPCVOID lpExeName return 0; } - // IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, - // &GetCommandHistoryRequest->ExeName); CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)lpExeName, GetCommandHistoryRequest->ExeLength, (PVOID)&GetCommandHistoryRequest->ExeName); - // CsrAllocateMessagePointer(CaptureBuffer, HistoryLength, CsrAllocateMessagePointer(CaptureBuffer, GetCommandHistoryRequest->HistoryLength, (PVOID*)&GetCommandHistoryRequest->History); @@ -192,8 +163,6 @@ IntGetConsoleCommandHistoryLength(LPCVOID lpExeName, BOOL bUnicode) return 0; } - // IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, - // &GetCommandHistoryLengthRequest->ExeName); CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)lpExeName, GetCommandHistoryLengthRequest->ExeLength, @@ -248,8 +217,6 @@ IntSetConsoleNumberOfCommands(DWORD dwNumCommands, return FALSE; } - // IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, - // &SetHistoryNumberCommandsRequest->ExeName); CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)lpExeName, SetHistoryNumberCommandsRequest->ExeLength, diff --git a/reactos/dll/win32/kernel32/client/console/init.c b/reactos/dll/win32/kernel32/client/console/init.c index 1313b77a232..5134028b9c5 100644 --- a/reactos/dll/win32/kernel32/client/console/init.c +++ b/reactos/dll/win32/kernel32/client/console/init.c @@ -22,15 +22,14 @@ /* GLOBALS ********************************************************************/ RTL_CRITICAL_SECTION ConsoleLock; -BOOL ConsoleInitialized = FALSE; +BOOLEAN ConsoleInitialized = FALSE; extern HANDLE InputWaitHandle; -static HMODULE ConsoleLibrary = NULL; +static HMODULE ConsoleApplet = NULL; static BOOL AlreadyDisplayingProps = FALSE; -#define WIN_OBJ_DIR L"\\Windows" -#define SESSION_DIR L"\\Sessions" +static const PWSTR DefaultConsoleTitle = L"ReactOS Console"; /* FUNCTIONS ******************************************************************/ @@ -41,6 +40,7 @@ PropDialogHandler(IN LPVOID lpThreadParameter) { // NOTE: lpThreadParameter corresponds to the client shared section handle. + NTSTATUS Status = STATUS_SUCCESS; APPLET_PROC CPLFunc; /* @@ -60,223 +60,242 @@ PropDialogHandler(IN LPVOID lpThreadParameter) AlreadyDisplayingProps = TRUE; /* Load the Control Applet if needed */ - if (ConsoleLibrary == NULL) + if (ConsoleApplet == NULL) { WCHAR szBuffer[MAX_PATH]; GetSystemDirectoryW(szBuffer, MAX_PATH); wcscat(szBuffer, L"\\console.dll"); - ConsoleLibrary = LoadLibraryW(szBuffer); - - if (ConsoleLibrary == NULL) + ConsoleApplet = LoadLibraryW(szBuffer); + if (ConsoleApplet == NULL) { DPRINT1("Failed to load console.dll\n"); - AlreadyDisplayingProps = FALSE; - return STATUS_UNSUCCESSFUL; + Status = STATUS_UNSUCCESSFUL; + goto Quit; } } /* Load its main function */ - CPLFunc = (APPLET_PROC)GetProcAddress(ConsoleLibrary, "CPlApplet"); + CPLFunc = (APPLET_PROC)GetProcAddress(ConsoleApplet, "CPlApplet"); if (CPLFunc == NULL) { - DPRINT("Error: Console.dll misses CPlApplet export\n"); - AlreadyDisplayingProps = FALSE; - return STATUS_UNSUCCESSFUL; + DPRINT1("Error: Console.dll misses CPlApplet export\n"); + Status = STATUS_UNSUCCESSFUL; + goto Quit; } if (CPLFunc(NULL, CPL_INIT, 0, 0) == FALSE) { - DPRINT("Error: failed to initialize console.dll\n"); - AlreadyDisplayingProps = FALSE; - return STATUS_UNSUCCESSFUL; + DPRINT1("Error: failed to initialize console.dll\n"); + Status = STATUS_UNSUCCESSFUL; + goto Quit; } if (CPLFunc(NULL, CPL_GETCOUNT, 0, 0) != 1) { - DPRINT("Error: console.dll returned unexpected CPL count\n"); - AlreadyDisplayingProps = FALSE; - return STATUS_UNSUCCESSFUL; + DPRINT1("Error: console.dll returned unexpected CPL count\n"); + Status = STATUS_UNSUCCESSFUL; + goto Quit; } CPLFunc(NULL, CPL_DBLCLK, (LPARAM)lpThreadParameter, 0); CPLFunc(NULL, CPL_EXIT , 0, 0); +Quit: AlreadyDisplayingProps = FALSE; - return STATUS_SUCCESS; + return Status; +} + + +static INT +ParseShellInfo(LPCWSTR lpszShellInfo, + LPCWSTR lpszKeyword) +{ + DPRINT1("ParseShellInfo is UNIMPLEMENTED\n"); + return 0; +} + + +/* + * NOTE: + * The "LPDWORD Length" parameters point on input to the maximum size of + * the buffers that can hold data (if != 0), and on output they hold the + * real size of the data. If "Length" are == 0 on input, then on output + * they receive the full size of the data. + * The "LPWSTR* lpTitle" parameter has a double meaning: + * - when "CaptureTitle" is TRUE, data is copied to the buffer pointed + * by the pointer (*lpTitle). + * - when "CaptureTitle" is FALSE, "*lpTitle" is set to the address of + * the source data. + */ +VOID +SetUpConsoleInfo(IN BOOLEAN CaptureTitle, + IN OUT LPDWORD pTitleLength, + IN OUT LPWSTR* lpTitle OPTIONAL, + IN OUT LPDWORD pDesktopLength, + IN OUT LPWSTR* lpDesktop OPTIONAL, + IN OUT PCONSOLE_START_INFO ConsoleStartInfo) +{ + PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; + DWORD Length; + + /* Initialize the fields */ + + ConsoleStartInfo->IconIndex = 0; + ConsoleStartInfo->hIcon = NULL; + ConsoleStartInfo->hIconSm = NULL; + ConsoleStartInfo->dwStartupFlags = Parameters->WindowFlags; + ConsoleStartInfo->nFont = 0; + ConsoleStartInfo->nInputBufferSize = 0; + ConsoleStartInfo->uCodePage = GetOEMCP(); + + if (lpTitle) + { + LPWSTR Title; + + /* If we don't have any title, use the default one */ + if (Parameters->WindowTitle.Buffer == NULL) + { + Title = DefaultConsoleTitle; + Length = lstrlenW(DefaultConsoleTitle) * sizeof(WCHAR); // sizeof(DefaultConsoleTitle); + } + else + { + Title = Parameters->WindowTitle.Buffer; + Length = Parameters->WindowTitle.Length; + } + + /* Retrieve the needed buffer size */ + Length += sizeof(WCHAR); + if (*pTitleLength > 0) Length = min(Length, *pTitleLength); + *pTitleLength = Length; + + /* Capture the data if needed, or, return a pointer to it */ + if (CaptureTitle) + { + /* + * Length is always >= sizeof(WCHAR). Copy everything but the + * possible trailing NULL character, and then NULL-terminate. + */ + Length -= sizeof(WCHAR); + RtlCopyMemory(*lpTitle, Title, Length); + (*lpTitle)[Length / sizeof(WCHAR)] = UNICODE_NULL; + } + else + { + *lpTitle = Title; + } + } + else + { + *pTitleLength = 0; + } + + if (lpDesktop && Parameters->DesktopInfo.Buffer && *Parameters->DesktopInfo.Buffer) + { + /* Retrieve the needed buffer size */ + Length = Parameters->DesktopInfo.Length + sizeof(WCHAR); + if (*pDesktopLength > 0) Length = min(Length, *pDesktopLength); + *pDesktopLength = Length; + + /* Return a pointer to the data */ + *lpDesktop = Parameters->DesktopInfo.Buffer; + } + else + { + *pDesktopLength = 0; + if (lpDesktop) *lpDesktop = NULL; + } + + if (Parameters->WindowFlags & STARTF_USEFILLATTRIBUTE) + { + ConsoleStartInfo->wFillAttribute = (WORD)Parameters->FillAttribute; + } + if (Parameters->WindowFlags & STARTF_USECOUNTCHARS) + { + ConsoleStartInfo->dwScreenBufferSize.X = (SHORT)Parameters->CountCharsX; + ConsoleStartInfo->dwScreenBufferSize.Y = (SHORT)Parameters->CountCharsY; + } + if (Parameters->WindowFlags & STARTF_USESHOWWINDOW) + { + ConsoleStartInfo->wShowWindow = (WORD)Parameters->ShowWindowFlags; + } + if (Parameters->WindowFlags & STARTF_USEPOSITION) + { + ConsoleStartInfo->dwWindowOrigin.X = (SHORT)Parameters->StartingX; + ConsoleStartInfo->dwWindowOrigin.Y = (SHORT)Parameters->StartingY; + } + if (Parameters->WindowFlags & STARTF_USESIZE) + { + ConsoleStartInfo->dwWindowSize.X = (SHORT)Parameters->CountX; + ConsoleStartInfo->dwWindowSize.Y = (SHORT)Parameters->CountY; + } + + /* Get shell information (ShellInfo.Buffer is NULL-terminated) */ + if (Parameters->ShellInfo.Buffer != NULL) + { + ConsoleStartInfo->IconIndex = ParseShellInfo(Parameters->ShellInfo.Buffer, L"dde."); + + if ((Parameters->WindowFlags & STARTF_USEHOTKEY) == 0) + ConsoleStartInfo->dwHotKey = ParseShellInfo(Parameters->ShellInfo.Buffer, L"hotkey."); + else + ConsoleStartInfo->dwHotKey = HandleToUlong(Parameters->StandardInput); + } } VOID -InitConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo, - IN PUNICODE_STRING ImagePathName) +SetUpHandles(IN PCONSOLE_START_INFO ConsoleStartInfo) { - STARTUPINFOW si; - SIZE_T Length; + PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; - /* Get the startup information */ - GetStartupInfoW(&si); - - /* Initialize the fields */ - ConsoleStartInfo->dwStartupFlags = si.dwFlags; - if (si.dwFlags & STARTF_USEFILLATTRIBUTE) + if (ConsoleStartInfo->dwStartupFlags & STARTF_USEHOTKEY) { - ConsoleStartInfo->wFillAttribute = (WORD)si.dwFillAttribute; + Parameters->WindowFlags &= ~STARTF_USEHOTKEY; } - if (si.dwFlags & STARTF_USECOUNTCHARS) + if (ConsoleStartInfo->dwStartupFlags & STARTF_SHELLPRIVATE) { - ConsoleStartInfo->dwScreenBufferSize.X = (SHORT)(si.dwXCountChars); - ConsoleStartInfo->dwScreenBufferSize.Y = (SHORT)(si.dwYCountChars); - } - if (si.dwFlags & STARTF_USESHOWWINDOW) - { - ConsoleStartInfo->wShowWindow = si.wShowWindow; - } - if (si.dwFlags & STARTF_USEPOSITION) - { - ConsoleStartInfo->dwWindowOrigin.X = (SHORT)(si.dwX); - ConsoleStartInfo->dwWindowOrigin.Y = (SHORT)(si.dwY); - } - if (si.dwFlags & STARTF_USESIZE) - { - ConsoleStartInfo->dwWindowSize.X = (SHORT)(si.dwXSize); - ConsoleStartInfo->dwWindowSize.Y = (SHORT)(si.dwYSize); + Parameters->WindowFlags &= ~STARTF_SHELLPRIVATE; } - /* Set up the title for the console */ - if (si.lpTitle) - { - wcsncpy(ConsoleStartInfo->ConsoleTitle, si.lpTitle, MAX_PATH + 1); - } - else - { - ConsoleStartInfo->ConsoleTitle[0] = L'\0'; - } + /* We got the handles, let's set them */ + Parameters->ConsoleHandle = ConsoleStartInfo->ConsoleHandle; - /* Retrieve the application path name */ - Length = min(sizeof(ConsoleStartInfo->AppPath) / sizeof(ConsoleStartInfo->AppPath[0]) - 1, - ImagePathName->Length / sizeof(WCHAR)); - wcsncpy(ConsoleStartInfo->AppPath, ImagePathName->Buffer, Length); - ConsoleStartInfo->AppPath[Length] = L'\0'; - - /* The Console Server will use these fields to set up the console icon */ - ConsoleStartInfo->IconPath[0] = L'\0'; - ConsoleStartInfo->IconIndex = 0; + if ((ConsoleStartInfo->dwStartupFlags & STARTF_USESTDHANDLES) == 0) + { + Parameters->StandardInput = ConsoleStartInfo->InputHandle; + Parameters->StandardOutput = ConsoleStartInfo->OutputHandle; + Parameters->StandardError = ConsoleStartInfo->ErrorHandle; + } } -BOOL -WINAPI -BasepInitConsole(VOID) +static BOOLEAN +IsConsoleApp(VOID) +{ + PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); + return (ImageNtHeader && (ImageNtHeader->OptionalHeader.Subsystem == + IMAGE_SUBSYSTEM_WINDOWS_CUI)); +} + + +static BOOLEAN +ConnectConsole(IN PWSTR SessionDir, + IN PCONSRV_API_CONNECTINFO ConnectInfo, + OUT PBOOLEAN IsServerProcess) { NTSTATUS Status; - PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; - WCHAR SessionDir[256]; - ULONG SessionId = NtCurrentPeb()->SessionId; - BOOLEAN InServer; + ULONG ConnectInfoSize = sizeof(*ConnectInfo); - CONSRV_API_CONNECTINFO ConnectInfo; - ULONG ConnectInfoSize = sizeof(ConnectInfo); - - DPRINT("BasepInitConsole for : %wZ\n", &Parameters->ImagePathName); - DPRINT("Our current console handles are: %p, %p, %p %p\n", - Parameters->ConsoleHandle, Parameters->StandardInput, - Parameters->StandardOutput, Parameters->StandardError); - - /* Initialize our global console DLL lock */ - Status = RtlInitializeCriticalSection(&ConsoleLock); - if (!NT_SUCCESS(Status)) return FALSE; - ConsoleInitialized = TRUE; - - /* Do nothing if this isn't a console app... */ - if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem != - IMAGE_SUBSYSTEM_WINDOWS_CUI) - { - DPRINT("Image is not a console application\n"); - Parameters->ConsoleHandle = NULL; - ConnectInfo.ConsoleStartInfo.ConsoleNeeded = FALSE; // ConsoleNeeded is used for knowing whether or not this is a CUI app. - - ConnectInfo.ConsoleStartInfo.ConsoleTitle[0] = L'\0'; - ConnectInfo.ConsoleStartInfo.AppPath[0] = L'\0'; - } - else - { - LPCWSTR ExeName; - - InitConsoleInfo(&ConnectInfo.ConsoleStartInfo, - &Parameters->ImagePathName); - - /* Initialize Input EXE name */ - ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\'); - if (ExeName) SetConsoleInputExeNameW(ExeName + 1); - - /* Assume one is needed */ - ConnectInfo.ConsoleStartInfo.ConsoleNeeded = TRUE; - - /* Handle the special flags given to us by BasePushProcessParameters */ - if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS) - { - /* No console to create */ - DPRINT("No console to create\n"); - Parameters->ConsoleHandle = NULL; - ConnectInfo.ConsoleStartInfo.ConsoleNeeded = FALSE; - } - else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE) - { - /* We'll get the real one soon */ - DPRINT("Creating new console\n"); - Parameters->ConsoleHandle = NULL; - } - else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW) - { - /* We'll get the real one soon */ - DPRINT("Creating new invisible console\n"); - Parameters->ConsoleHandle = NULL; - ConnectInfo.ConsoleStartInfo.wShowWindow = SW_HIDE; - } - else - { - if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE) - { - Parameters->ConsoleHandle = NULL; - } - DPRINT("Using existing console: %p\n", Parameters->ConsoleHandle); - } - } - - /* Now use the proper console handle */ - ConnectInfo.ConsoleHandle = Parameters->ConsoleHandle; - - /* Initialize the Console Ctrl Handler */ - InitConsoleCtrlHandling(); - ConnectInfo.ConsoleStartInfo.CtrlDispatcher = ConsoleControlDispatcher; - - /* Initialize the Property Dialog Handler */ - ConnectInfo.ConsoleStartInfo.PropDispatcher = PropDialogHandler; - - /* Setup the right Object Directory path */ - if (!SessionId) - { - /* Use the raw path */ - wcscpy(SessionDir, WIN_OBJ_DIR); - } - else - { - /* Use the session path */ - swprintf(SessionDir, - L"%ws\\%ld%ws", - SESSION_DIR, - SessionId, - WIN_OBJ_DIR); - } + ASSERT(SessionDir); /* Connect to the Console Server */ - DPRINT("Connecting to the Console Server in BasepInitConsole...\n"); + DPRINT("Connecting to the Console Server...\n"); Status = CsrClientConnectToServer(SessionDir, CONSRV_SERVERDLL_INDEX, - &ConnectInfo, + ConnectInfo, &ConnectInfoSize, - &InServer); + IsServerProcess); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status); @@ -284,52 +303,237 @@ BasepInitConsole(VOID) } /* Nothing to do for server-to-server */ - if (InServer) return TRUE; + if (*IsServerProcess) return TRUE; - /* Nothing to do if not a console app */ - if (!ConnectInfo.ConsoleStartInfo.ConsoleNeeded) return TRUE; + /* Nothing to do if this is not a console app */ + if (!ConnectInfo->IsConsoleApp) return TRUE; - /* We got the handles, let's set them */ - if ((Parameters->ConsoleHandle = ConnectInfo.ConsoleHandle)) +#ifdef USE_CONSOLE_INIT_HANDLES + /* Wait for the connection to finish */ + Status = NtWaitForMultipleObjects(2, ConnectInfo->ConsoleStartInfo.Events, + WaitAny, FALSE, NULL); + if (!NT_SUCCESS(Status)) { - /* If we already had some, don't use the new ones */ - if (!Parameters->StandardInput) - { - Parameters->StandardInput = ConnectInfo.InputHandle; - } - if (!Parameters->StandardOutput) - { - Parameters->StandardOutput = ConnectInfo.OutputHandle; - } - if (!Parameters->StandardError) - { - Parameters->StandardError = ConnectInfo.ErrorHandle; - } + BaseSetLastNTError(Status); + return FALSE; } - InputWaitHandle = ConnectInfo.InputWaitHandle; + NtClose(ConnectInfo->ConsoleStartInfo.Events[0]); + NtClose(ConnectInfo->ConsoleStartInfo.Events[1]); + + if (Status != STATUS_SUCCESS) + { + NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; + return FALSE; + } +#endif - DPRINT("Console setup: %p, %p, %p, %p\n", - Parameters->ConsoleHandle, - Parameters->StandardInput, - Parameters->StandardOutput, - Parameters->StandardError); return TRUE; } -VOID +BOOLEAN WINAPI -BasepUninitConsole(VOID) +ConDllInitialize(IN ULONG Reason, + IN PWSTR SessionDir) { - /* Delete our critical section if we were initialized */ - if (ConsoleInitialized == TRUE) - { - if (ConsoleLibrary) FreeLibrary(ConsoleLibrary); + NTSTATUS Status; + PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; + BOOLEAN IsServerProcess; + CONSRV_API_CONNECTINFO ConnectInfo; + LCID lcid; - ConsoleInitialized = FALSE; - RtlDeleteCriticalSection(&ConsoleLock); + if (Reason != DLL_PROCESS_ATTACH) + { + if ((Reason == DLL_THREAD_ATTACH) && IsConsoleApp()) + { + /* Sets the current console locale for the new thread */ + SetTEBLangID(lcid); + } + else if (Reason == DLL_PROCESS_DETACH) + { + /* Free our resources */ + if (ConsoleInitialized == TRUE) + { + if (ConsoleApplet) FreeLibrary(ConsoleApplet); + + ConsoleInitialized = FALSE; + RtlDeleteCriticalSection(&ConsoleLock); + } + } + + return TRUE; } + + DPRINT("ConDllInitialize for: %wZ\n" + "Our current console handles are: 0x%p, 0x%p, 0x%p 0x%p\n", + &Parameters->ImagePathName, + Parameters->ConsoleHandle, + Parameters->StandardInput, + Parameters->StandardOutput, + Parameters->StandardError); + + /* Initialize our global console DLL lock */ + Status = RtlInitializeCriticalSection(&ConsoleLock); + if (!NT_SUCCESS(Status)) return FALSE; + ConsoleInitialized = TRUE; + + /* Show by default the console window when applicable */ + ConnectInfo.IsWindowVisible = TRUE; + /* If this is a console app, a console will be created/opened */ + ConnectInfo.IsConsoleApp = IsConsoleApp(); + + /* Do nothing if this is not a console app... */ + if (!ConnectInfo.IsConsoleApp) + { + DPRINT("Image is not a console application\n"); + } + + /* + * Handle the special flags given to us by BasePushProcessParameters. + */ + if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS) + { + /* No console to create */ + DPRINT("No console to create\n"); + /* + * The new process does not inherit its parent's console and cannot + * attach to the console of its parent. The new process can call the + * AllocConsole function at a later time to create a console. + */ + Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console. + ConnectInfo.IsConsoleApp = FALSE; // Do not create any console. + } + else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE) + { + /* We'll get the real one soon */ + DPRINT("Creating a new separate console\n"); + /* + * The new process has a new console, instead of inheriting + * its parent's console. + */ + Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console. + } + else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW) + { + /* We'll get the real one soon */ + DPRINT("Creating a new invisible console\n"); + /* + * The process is a console application that is being run + * without a console window. Therefore, the console handle + * for the application is not set. + */ + Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console. + ConnectInfo.IsWindowVisible = FALSE; // A console is created but is not shown to the user. + } + else + { + DPRINT("Using existing console: 0x%p\n", Parameters->ConsoleHandle); + } + + /* Do nothing if this is not a console app... */ + if (!ConnectInfo.IsConsoleApp) + { + /* Do not inherit the parent's console if we are not a console app */ + Parameters->ConsoleHandle = NULL; + } + + /* Now use the proper console handle */ + ConnectInfo.ConsoleStartInfo.ConsoleHandle = Parameters->ConsoleHandle; + + /* Initialize the console dispatchers */ + ConnectInfo.CtrlRoutine = ConsoleControlDispatcher; + ConnectInfo.PropRoutine = PropDialogHandler; + // ConnectInfo.ImeRoutine = ImeRoutine; + + /* Set up the console properties */ + if (ConnectInfo.IsConsoleApp && Parameters->ConsoleHandle == NULL) + { + /* + * We can set up the console properties only if we create a new one + * (we do not inherit it from our parent). + */ + + LPWSTR ConsoleTitle = ConnectInfo.ConsoleTitle; + + ConnectInfo.TitleLength = sizeof(ConnectInfo.ConsoleTitle); + ConnectInfo.DesktopLength = 0; // SetUpConsoleInfo will give us the real length. + + SetUpConsoleInfo(TRUE, + &ConnectInfo.TitleLength, + &ConsoleTitle, + &ConnectInfo.DesktopLength, + &ConnectInfo.Desktop, + &ConnectInfo.ConsoleStartInfo); + DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n", + ConsoleTitle, ConnectInfo.Desktop); + } + else + { + ConnectInfo.TitleLength = 0; + ConnectInfo.DesktopLength = 0; + } + + /* Initialize the Input EXE name */ + if (ConnectInfo.IsConsoleApp) + { + LPWSTR CurDir = ConnectInfo.CurDir; + LPWSTR AppName = ConnectInfo.AppName; + + InitExeName(); + + ConnectInfo.CurDirLength = sizeof(ConnectInfo.CurDir); + ConnectInfo.AppNameLength = sizeof(ConnectInfo.AppName); + + SetUpAppName(TRUE, + &ConnectInfo.CurDirLength, + &CurDir, + &ConnectInfo.AppNameLength, + &AppName); + DPRINT("CurDir = '%S' - AppName = '%S'\n", + CurDir, AppName); + } + else + { + ConnectInfo.CurDirLength = 0; + ConnectInfo.AppNameLength = 0; + } + + /* + * Initialize Console Ctrl Handling, that needs to be supported by + * all applications, especially because it is used at shutdown. + */ + InitializeCtrlHandling(); + + /* Connect to the Console Server */ + if (!ConnectConsole(SessionDir, + &ConnectInfo, + &IsServerProcess)) + { + // DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status); + return FALSE; + } + + /* If we are not doing server-to-server init and if this is a console app... */ + if (!IsServerProcess && ConnectInfo.IsConsoleApp) + { + /* ... set the handles that we got */ + if (Parameters->ConsoleHandle == NULL) + SetUpHandles(&ConnectInfo.ConsoleStartInfo); + + InputWaitHandle = ConnectInfo.ConsoleStartInfo.InputWaitHandle; + + /* Sets the current console locale for this thread */ + SetTEBLangID(lcid); + } + + DPRINT("Console setup: 0x%p, 0x%p, 0x%p, 0x%p\n", + Parameters->ConsoleHandle, + Parameters->StandardInput, + Parameters->StandardOutput, + Parameters->StandardError); + + return TRUE; } /* EOF */ diff --git a/reactos/dll/win32/kernel32/client/console/readwrite.c b/reactos/dll/win32/kernel32/client/console/readwrite.c index f1818a0c8c8..e231b418984 100644 --- a/reactos/dll/win32/kernel32/client/console/readwrite.c +++ b/reactos/dll/win32/kernel32/client/console/readwrite.c @@ -31,10 +31,6 @@ * Read functions * ******************/ -DWORD -WINAPI -GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer); - static BOOL IntReadConsole(IN HANDLE hConsoleInput, @@ -58,26 +54,12 @@ IntReadConsole(IN HANDLE hConsoleInput, ReadConsoleRequest->Unicode = bUnicode; /* - * Retrieve the current console executable name string and length (always - * in UNICODE format). - * FIXME: Do not use GetConsoleInputExeNameW but use something else... + * Retrieve the (current) Input EXE name string and length, + * not NULL-terminated (always in UNICODE format). */ - // 1- Get the exe name length in characters, including NULL character. ReadConsoleRequest->ExeLength = - (USHORT)GetConsoleInputExeNameW(0, (PWCHAR)ReadConsoleRequest->StaticBuffer); - // 2- Get the exe name (GetConsoleInputExeNameW returns 1 in case of success). - if (GetConsoleInputExeNameW(ReadConsoleRequest->ExeLength, - (PWCHAR)ReadConsoleRequest->StaticBuffer) != 1) - { - // Nothing - ReadConsoleRequest->ExeLength = 0; - } - else - { - // Remove the NULL character, and convert in number of bytes. - ReadConsoleRequest->ExeLength--; - ReadConsoleRequest->ExeLength *= sizeof(WCHAR); - } + GetCurrentExeName((PWCHAR)ReadConsoleRequest->StaticBuffer, + sizeof(ReadConsoleRequest->StaticBuffer)); /*** For DEBUGGING purposes ***/ { @@ -181,7 +163,7 @@ IntReadConsole(IN HANDLE hConsoleInput, } _SEH2_END; - /* Check for sanity */ + /* FIXME: Check for sanity */ /* if (!NT_SUCCESS(Status) && pInputControl) { @@ -1185,9 +1167,7 @@ IntFillConsoleOutputCode(IN HANDLE hConsoleOutput, * Read functions * ******************/ -/*-------------------------------------------------------------- - * ReadConsoleW - * +/* * @implemented */ BOOL @@ -1207,9 +1187,7 @@ ReadConsoleW(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * ReadConsoleA - * +/* * @implemented */ BOOL @@ -1229,9 +1207,7 @@ ReadConsoleA(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * PeekConsoleInputW - * +/* * @implemented */ BOOL @@ -1250,9 +1226,7 @@ PeekConsoleInputW(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * PeekConsoleInputA - * +/* * @implemented */ BOOL @@ -1271,9 +1245,7 @@ PeekConsoleInputA(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * ReadConsoleInputW - * +/* * @implemented */ BOOL @@ -1292,9 +1264,7 @@ ReadConsoleInputW(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * ReadConsoleInputA - * +/* * @implemented */ BOOL @@ -1313,9 +1283,7 @@ ReadConsoleInputA(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * ReadConsoleInputExW - * +/* * @implemented */ BOOL @@ -1335,9 +1303,7 @@ ReadConsoleInputExW(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * ReadConsoleInputExA - * +/* * @implemented */ BOOL @@ -1357,9 +1323,7 @@ ReadConsoleInputExA(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * ReadConsoleOutputW - * +/* * @implemented */ BOOL @@ -1379,9 +1343,7 @@ ReadConsoleOutputW(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * ReadConsoleOutputA - * +/* * @implemented */ BOOL @@ -1401,9 +1363,7 @@ ReadConsoleOutputA(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * ReadConsoleOutputCharacterW - * +/* * @implemented */ BOOL @@ -1423,9 +1383,7 @@ ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * ReadConsoleOutputCharacterA - * +/* * @implemented */ BOOL @@ -1445,9 +1403,7 @@ ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * ReadConsoleOutputAttribute - * +/* * @implemented */ BOOL @@ -1471,9 +1427,7 @@ ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput, * Write functions * *******************/ -/*-------------------------------------------------------------- - * WriteConsoleW - * +/* * @implemented */ BOOL @@ -1493,9 +1447,7 @@ WriteConsoleW(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * WriteConsoleA - * +/* * @implemented */ BOOL @@ -1515,9 +1467,7 @@ WriteConsoleA(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * WriteConsoleInputW - * +/* * @implemented */ BOOL @@ -1536,9 +1486,7 @@ WriteConsoleInputW(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * WriteConsoleInputA - * +/* * @implemented */ BOOL @@ -1557,9 +1505,7 @@ WriteConsoleInputA(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * WriteConsoleInputVDMW - * +/* * @implemented */ BOOL @@ -1578,9 +1524,7 @@ WriteConsoleInputVDMW(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * WriteConsoleInputVDMA - * +/* * @implemented */ BOOL @@ -1599,9 +1543,7 @@ WriteConsoleInputVDMA(IN HANDLE hConsoleInput, } -/*-------------------------------------------------------------- - * WriteConsoleOutputW - * +/* * @implemented */ BOOL @@ -1621,9 +1563,7 @@ WriteConsoleOutputW(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * WriteConsoleOutputA - * +/* * @implemented */ BOOL @@ -1643,9 +1583,7 @@ WriteConsoleOutputA(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * WriteConsoleOutputCharacterW - * +/* * @implemented */ BOOL @@ -1665,9 +1603,7 @@ WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * WriteConsoleOutputCharacterA - * +/* * @implemented */ BOOL @@ -1687,9 +1623,7 @@ WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * WriteConsoleOutputAttribute - * +/* * @implemented */ BOOL @@ -1709,9 +1643,7 @@ WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * FillConsoleOutputCharacterW - * +/* * @implemented */ BOOL @@ -1733,9 +1665,7 @@ FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * FillConsoleOutputCharacterA - * +/* * @implemented */ BOOL @@ -1757,9 +1687,7 @@ FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * FillConsoleOutputAttribute - * +/* * @implemented */ BOOL diff --git a/reactos/dll/win32/kernel32/client/console/vista.c b/reactos/dll/win32/kernel32/client/console/vista.c index bd2721e126b..ca691dda2c8 100644 --- a/reactos/dll/win32/kernel32/client/console/vista.c +++ b/reactos/dll/win32/kernel32/client/console/vista.c @@ -18,9 +18,7 @@ #if _WIN32_WINNT >= 0x600 -/*-------------------------------------------------------------- - * GetConsoleHistoryInfo - * +/* * @implemented */ BOOL @@ -55,9 +53,7 @@ GetConsoleHistoryInfo(PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo) } -/*-------------------------------------------------------------- - * SetConsoleHistoryInfo - * +/* * @implemented */ BOOL @@ -92,9 +88,7 @@ SetConsoleHistoryInfo(IN PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo) } -/*-------------------------------------------------------------- - * GetConsoleOriginalTitleW - * +/* * @unimplemented */ DWORD @@ -108,9 +102,7 @@ GetConsoleOriginalTitleW(OUT LPWSTR lpConsoleTitle, } -/*-------------------------------------------------------------- - * GetConsoleOriginalTitleA - * +/* * @unimplemented */ DWORD @@ -124,9 +116,7 @@ GetConsoleOriginalTitleA(OUT LPSTR lpConsoleTitle, } -/*-------------------------------------------------------------- - * GetConsoleScreenBufferInfoEx - * +/* * @unimplemented */ BOOL @@ -140,9 +130,7 @@ GetConsoleScreenBufferInfoEx(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * SetConsoleScreenBufferInfoEx - * +/* * @unimplemented */ BOOL @@ -156,9 +144,7 @@ SetConsoleScreenBufferInfoEx(IN HANDLE hConsoleOutput, } -/*-------------------------------------------------------------- - * GetCurrentConsoleFontEx - * +/* * @unimplemented */ BOOL diff --git a/reactos/dll/win32/kernel32/client/dllmain.c b/reactos/dll/win32/kernel32/client/dllmain.c index 04421291ac4..26c24cf5d43 100644 --- a/reactos/dll/win32/kernel32/client/dllmain.c +++ b/reactos/dll/win32/kernel32/client/dllmain.c @@ -200,7 +200,7 @@ DllMain(HANDLE hDll, } /* Initialize Console Support */ - if (!BasepInitConsole()) + if (!ConDllInitialize(dwReason, SessionDir)) { DPRINT1("Failed to set up console\n"); return FALSE; @@ -219,18 +219,24 @@ DllMain(HANDLE hDll, { if (DllInitialized == TRUE) { + /* Uninitialize console support */ + ConDllInitialize(dwReason, NULL); + /* Insert more dll detach stuff here! */ NlsUninit(); - /* Uninitialize console support */ - BasepUninitConsole(); - /* Delete DLL critical section */ RtlDeleteCriticalSection(&BaseDllDirectoryLock); } break; } + case DLL_THREAD_ATTACH: + { + /* ConDllInitialize sets the current console locale for the new thread */ + return ConDllInitialize(dwReason, NULL); + } + default: break; } diff --git a/reactos/dll/win32/kernel32/client/proc.c b/reactos/dll/win32/kernel32/client/proc.c index 47bb1404509..e590f20ab2a 100644 --- a/reactos/dll/win32/kernel32/client/proc.c +++ b/reactos/dll/win32/kernel32/client/proc.c @@ -726,7 +726,7 @@ BasePushProcessParameters(IN ULONG ParameterFlags, ProcessParameters->StandardError = StartupInfo->hStdError; } - /* Use Special Flags for BasepInitConsole in Kernel32 */ + /* Use Special Flags for ConDllInitialize in Kernel32 */ if (CreationFlags & DETACHED_PROCESS) { ProcessParameters->ConsoleHandle = HANDLE_DETACHED_PROCESS; diff --git a/reactos/dll/win32/kernel32/include/console.h b/reactos/dll/win32/kernel32/include/console.h index 1886608e88e..79e1d9a8022 100644 --- a/reactos/dll/win32/kernel32/include/console.h +++ b/reactos/dll/win32/kernel32/include/console.h @@ -10,26 +10,31 @@ /* CONSTANTS ******************************************************************/ -#define HANDLE_DETACHED_PROCESS (HANDLE)-2 -#define HANDLE_CREATE_NEW_CONSOLE (HANDLE)-3 -#define HANDLE_CREATE_NO_WINDOW (HANDLE)-4 +#define HANDLE_DETACHED_PROCESS (HANDLE)-1 +#define HANDLE_CREATE_NEW_CONSOLE (HANDLE)-2 +#define HANDLE_CREATE_NO_WINDOW (HANDLE)-3 + +// Enable (and then get rid of) this define when support for +// console initialization handles is implemented in CONSRV. +// #define USE_CONSOLE_INIT_HANDLES /* FUNCTION PROTOTYPES ********************************************************/ -BOOL WINAPI -BasepInitConsole(VOID); +BOOLEAN +WINAPI +ConDllInitialize(IN ULONG Reason, + IN PWSTR SessionDir); -VOID WINAPI -BasepUninitConsole(VOID); +VOID +InitializeCtrlHandling(VOID); -VOID WINAPI -InitConsoleCtrlHandling(VOID); - -DWORD WINAPI +DWORD +WINAPI ConsoleControlDispatcher(IN LPVOID lpThreadParameter); -DWORD WINAPI +DWORD +WINAPI PropDialogHandler(IN LPVOID lpThreadParameter); HANDLE WINAPI @@ -59,9 +64,32 @@ GetConsoleInputWaitHandle(VOID); HANDLE TranslateStdHandle(HANDLE hHandle); +#define SetTEBLangID(p) (p) + VOID -InitConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo, - IN PUNICODE_STRING ImagePathName); +SetUpConsoleInfo(IN BOOLEAN CaptureTitle, + IN OUT LPDWORD pTitleLength, + IN OUT LPWSTR* lpTitle OPTIONAL, + IN OUT LPDWORD pDesktopLength, + IN OUT LPWSTR* lpDesktop OPTIONAL, + IN OUT PCONSOLE_START_INFO ConsoleStartInfo); + +VOID +SetUpHandles(IN PCONSOLE_START_INFO ConsoleStartInfo); + +VOID +InitExeName(VOID); + +VOID +SetUpAppName(IN BOOLEAN CaptureStrings, + IN OUT LPDWORD CurDirLength, + IN OUT LPWSTR* CurDir, + IN OUT LPDWORD AppNameLength, + IN OUT LPWSTR* AppName); + +USHORT +GetCurrentExeName(OUT PWCHAR ExeName, + IN USHORT BufferSize); LPCWSTR IntCheckForConsoleFileName(IN LPCWSTR pszName, @@ -73,7 +101,4 @@ OpenConsoleW(LPCWSTR wsName, BOOL bInheritHandle, DWORD dwShareMode); -BOOL WINAPI -SetConsoleInputExeNameW(LPCWSTR lpInputExeName); - /* EOF */ diff --git a/reactos/include/psdk/wincon.h b/reactos/include/psdk/wincon.h index 2df5ef345a0..e34a8f6f7ca 100644 --- a/reactos/include/psdk/wincon.h +++ b/reactos/include/psdk/wincon.h @@ -27,9 +27,6 @@ extern "C" { // These codes are answered by GetConsoleDisplayMode #define CONSOLE_WINDOWED 0 #define CONSOLE_FULLSCREEN 1 -#if (_WIN32_WINNT >= 0x0600) -#define CONSOLE_OVERSTRIKE 1 -#endif #define CONSOLE_FULLSCREEN_HARDWARE 2 // These codes should be given to SetConsoleDisplayMode @@ -103,12 +100,16 @@ extern "C" { #define CONSOLE_MOUSE_DOWN 0x0008 /* - * History duplicate flags + * History information and mode flags */ #if (_WIN32_WINNT >= 0x0600) +// For Get/SetConsoleHistoryInfo #define HISTORY_NO_DUP_FLAG 0x0001 +// For SetConsoleCommandHistoryMode +#define CONSOLE_OVERSTRIKE 0x0001 #endif + /* * Read input flags */ diff --git a/reactos/include/reactos/subsys/win/basemsg.h b/reactos/include/reactos/subsys/win/basemsg.h index 620c7bcb0d2..a7be6805593 100644 --- a/reactos/include/reactos/subsys/win/basemsg.h +++ b/reactos/include/reactos/subsys/win/basemsg.h @@ -86,7 +86,7 @@ typedef struct _BASE_SXS_CREATEPROCESS_MSG UNICODE_STRING AssemblyName; } BASE_SXS_CREATEPROCESS_MSG, *PBASE_SXS_CREATEPROCESS_MSG; -typedef struct +typedef struct _BASE_CREATE_PROCESS { // // NT-type structure (BASE_CREATEPROCESS_MSG) @@ -104,23 +104,23 @@ typedef struct USHORT ProcessorArchitecture; } BASE_CREATE_PROCESS, *PBASE_CREATE_PROCESS; -typedef struct +typedef struct _BASE_CREATE_THREAD { HANDLE ThreadHandle; CLIENT_ID ClientId; } BASE_CREATE_THREAD, *PBASE_CREATE_THREAD; -typedef struct +typedef struct _BASE_GET_TEMP_FILE { UINT UniqueID; } BASE_GET_TEMP_FILE, *PBASE_GET_TEMP_FILE; -typedef struct +typedef struct _BASE_EXIT_PROCESS { UINT uExitCode; } BASE_EXIT_PROCESS, *PBASE_EXIT_PROCESS; -typedef struct +typedef struct _BASE_CHECK_VDM { ULONG iTask; HANDLE ConsoleHandle; @@ -152,7 +152,7 @@ typedef struct USHORT VDMState; } BASE_CHECK_VDM, *PBASE_CHECK_VDM; -typedef struct +typedef struct _BASE_UPDATE_VDM_ENTRY { ULONG iTask; ULONG BinaryType; @@ -163,7 +163,7 @@ typedef struct USHORT VDMCreationState; } BASE_UPDATE_VDM_ENTRY, *PBASE_UPDATE_VDM_ENTRY; -typedef struct +typedef struct _BASE_GET_NEXT_VDM_COMMAND { ULONG iTask; HANDLE ConsoleHandle; @@ -196,80 +196,80 @@ typedef struct ULONG fComingFromBat; } BASE_GET_NEXT_VDM_COMMAND, *PBASE_GET_NEXT_VDM_COMMAND; -typedef struct +typedef struct _BASE_EXIT_VDM { HANDLE ConsoleHandle; ULONG iWowTask; HANDLE WaitObjectForVDM; } BASE_EXIT_VDM, *PBASE_EXIT_VDM; -typedef struct +typedef struct _BASE_IS_FIRST_VDM { ULONG FirstVDM; } BASE_IS_FIRST_VDM, *PBASE_IS_FIRST_VDM; -typedef struct +typedef struct _BASE_GET_VDM_EXIT_CODE { HANDLE ConsoleHandle; HANDLE hParent; ULONG ExitCode; } BASE_GET_VDM_EXIT_CODE, *PBASE_GET_VDM_EXIT_CODE; -typedef struct +typedef struct _BASE_SET_REENTER_COUNT { HANDLE ConsoleHandle; ULONG fIncDec; } BASE_SET_REENTER_COUNT, *PBASE_SET_REENTER_COUNT; -typedef struct +typedef struct _BASE_GETSET_PROCESS_SHUTDOWN_PARAMS { ULONG ShutdownLevel; ULONG ShutdownFlags; } BASE_GETSET_PROCESS_SHUTDOWN_PARAMS, *PBASE_GETSET_PROCESS_SHUTDOWN_PARAMS; -typedef struct +typedef struct _BASE_GETSET_VDM_CURDIRS { HANDLE ConsoleHandle; PCHAR lpszzCurDirs; ULONG cchCurDirs; } BASE_GETSET_VDM_CURDIRS, *PBASE_GETSET_VDM_CURDIRS; -typedef struct +typedef struct _BASE_BAT_NOTIFICATION { HANDLE ConsoleHandle; ULONG fBeginEnd; } BASE_BAT_NOTIFICATION, *PBASE_BAT_NOTIFICATION; -typedef struct +typedef struct _BASE_REGISTER_WOWEXEC { HANDLE hwndWowExec; } BASE_REGISTER_WOWEXEC, *PBASE_REGISTER_WOWEXEC; -typedef struct +typedef struct _BASE_SOUND_SENTRY { ULONG VideoMode; } BASE_SOUND_SENTRY, *PBASE_SOUND_SENTRY; -typedef struct +typedef struct _BASE_REFRESH_INIFILE_MAPPING { UNICODE_STRING IniFileName; } BASE_REFRESH_INIFILE_MAPPING, *PBASE_REFRESH_INIFILE_MAPPING; -typedef struct +typedef struct _BASE_DEFINE_DOS_DEVICE { ULONG Flags; UNICODE_STRING DeviceName; UNICODE_STRING TargetPath; } BASE_DEFINE_DOS_DEVICE, *PBASE_DEFINE_DOS_DEVICE; -typedef struct +typedef struct _BASE_NLS_CREATE_SECTION { HANDLE SectionHandle; ULONG Type; ULONG LocaleId; } BASE_NLS_CREATE_SECTION, *PBASE_NLS_CREATE_SECTION; -typedef struct +typedef struct _BASE_NLS_GET_USER_INFO { PVOID /*PNLS_USER_INFO*/ NlsUserInfo; ULONG Size; diff --git a/reactos/include/reactos/subsys/win/conmsg.h b/reactos/include/reactos/subsys/win/conmsg.h index 1f047226d3d..42d83987d7f 100644 --- a/reactos/include/reactos/subsys/win/conmsg.h +++ b/reactos/include/reactos/subsys/win/conmsg.h @@ -119,6 +119,13 @@ typedef enum _CONSRV_API_NUMBER // typedef struct _CONSOLE_PROPERTIES { + INT IconIndex; + HICON hIcon; + HICON hIconSm; + DWORD dwHotKey; + DWORD dwStartupFlags; + + // NT_CONSOLE_PROPS WORD wFillAttribute; WORD wPopupFillAttribute; @@ -134,90 +141,88 @@ typedef struct _CONSOLE_PROPERTIES DWORD nFont; DWORD nInputBufferSize; COORD dwFontSize; - UINT uFontFamily; - UINT uFontWeight; + UINT uFontFamily; + UINT uFontWeight; WCHAR FaceName[LF_FACESIZE]; - UINT uCursorSize; - BOOL bFullScreen; - BOOL bQuickEdit; - BOOL bInsertMode; - BOOL bAutoPosition; - UINT uHistoryBufferSize; - UINT uNumberOfHistoryBuffers; - BOOL bHistoryNoDup; + UINT uCursorSize; + BOOL bFullScreen; + BOOL bQuickEdit; + BOOL bInsertMode; + BOOL bAutoPosition; + UINT uHistoryBufferSize; + UINT uNumberOfHistoryBuffers; + BOOL bHistoryNoDup; COLORREF ColorTable[16]; - //NT_FE_CONSOLE_PROPS + // NT_FE_CONSOLE_PROPS UINT uCodePage; } CONSOLE_PROPERTIES; -// -// To minimize code changes, some fields were put here even though they really only belong in -// CONSRV_API_CONNECTINFO. Do not change the ordering however, as it's required for Windows -// compatibility. -// typedef struct _CONSOLE_START_INFO -{ - INT IconIndex; - HICON IconHandle1; - HICON IconHandle2; - DWORD dwHotKey; - DWORD dwStartupFlags; - CONSOLE_PROPERTIES; - - BOOLEAN ConsoleNeeded; // Used for GUI apps only. - LPTHREAD_START_ROUTINE CtrlDispatcher; - LPTHREAD_START_ROUTINE ImeDispatcher; - LPTHREAD_START_ROUTINE PropDispatcher; - ULONG TitleLength; - WCHAR ConsoleTitle[MAX_PATH + 1]; // Console title or full path to the startup shortcut - ULONG DesktopLength; - PWCHAR DesktopPath; - ULONG AppNameLength; - WCHAR AppPath[128]; // Full path of the launched app - ULONG IconPathLength; - WCHAR IconPath[MAX_PATH + 1]; // Path to the file containing the icon -} CONSOLE_START_INFO, *PCONSOLE_START_INFO; - -typedef struct _CONSRV_API_CONNECTINFO { HANDLE ConsoleHandle; HANDLE InputWaitHandle; HANDLE InputHandle; HANDLE OutputHandle; HANDLE ErrorHandle; - HANDLE Event1; - HANDLE Event2; - /* Adapted from CONSOLE_ALLOCCONSOLE */ + HANDLE Events[2]; + + CONSOLE_PROPERTIES; +} CONSOLE_START_INFO, *PCONSOLE_START_INFO; + +#if defined(_M_IX86) +C_ASSERT(sizeof(CONSOLE_START_INFO) == 0xFC); +#endif + +typedef struct _CONSRV_API_CONNECTINFO +{ CONSOLE_START_INFO ConsoleStartInfo; + + BOOLEAN IsConsoleApp; + BOOLEAN IsWindowVisible; + + // USHORT Padding; + + LPTHREAD_START_ROUTINE CtrlRoutine; + LPTHREAD_START_ROUTINE PropRoutine; + LPTHREAD_START_ROUTINE ImeRoutine; + + ULONG TitleLength; + WCHAR ConsoleTitle[MAX_PATH + 1]; // Console title or full path to the startup shortcut + ULONG DesktopLength; + PWCHAR Desktop; + ULONG AppNameLength; + WCHAR AppName[128]; // Full path of the launched app + ULONG CurDirLength; + WCHAR CurDir[MAX_PATH + 1]; } CONSRV_API_CONNECTINFO, *PCONSRV_API_CONNECTINFO; #if defined(_M_IX86) C_ASSERT(sizeof(CONSRV_API_CONNECTINFO) == 0x638); #endif -typedef struct +typedef struct _CONSOLE_GETPROCESSLIST { HANDLE ConsoleHandle; ULONG ProcessCount; PDWORD ProcessIdsList; } CONSOLE_GETPROCESSLIST, *PCONSOLE_GETPROCESSLIST; -typedef struct +typedef struct _CONSOLE_GENERATECTRLEVENT { HANDLE ConsoleHandle; DWORD CtrlEvent; DWORD ProcessGroupId; } CONSOLE_GENERATECTRLEVENT, *PCONSOLE_GENERATECTRLEVENT; -typedef struct +typedef struct _CONSOLE_NOTIFYLASTCLOSE { HANDLE ConsoleHandle; } CONSOLE_NOTIFYLASTCLOSE, *PCONSOLE_NOTIFYLASTCLOSE; -typedef struct +typedef struct _CONSOLE_WRITECONSOLE { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -236,7 +241,7 @@ typedef struct CHAR Reserved2[6]; } CONSOLE_WRITECONSOLE, *PCONSOLE_WRITECONSOLE; -typedef struct +typedef struct _CONSOLE_READCONSOLE { HANDLE ConsoleHandle; HANDLE InputHandle; @@ -255,37 +260,43 @@ typedef struct BOOLEAN Unicode; } CONSOLE_READCONSOLE, *PCONSOLE_READCONSOLE; -typedef struct +typedef struct _CONSOLE_ALLOCCONSOLE { PCONSOLE_START_INFO ConsoleStartInfo; - HANDLE ConsoleHandle; - HANDLE InputHandle; - HANDLE OutputHandle; - HANDLE ErrorHandle; - HANDLE InputWaitHandle; - LPTHREAD_START_ROUTINE CtrlDispatcher; - LPTHREAD_START_ROUTINE PropDispatcher; + ULONG TitleLength; + PWCHAR ConsoleTitle; // Console title or full path to the startup shortcut + ULONG DesktopLength; + PWCHAR Desktop; + ULONG AppNameLength; + PWCHAR AppName; // Full path of the launched app + ULONG CurDirLength; + PWCHAR CurDir; + + LPTHREAD_START_ROUTINE CtrlRoutine; + LPTHREAD_START_ROUTINE PropRoutine; } CONSOLE_ALLOCCONSOLE, *PCONSOLE_ALLOCCONSOLE; -typedef struct +typedef struct _CONSOLE_ATTACHCONSOLE { - DWORD ProcessId; // If ProcessId == ATTACH_PARENT_PROCESS == -1, then attach the current process to its parent process console. - HANDLE ConsoleHandle; - HANDLE InputHandle; - HANDLE OutputHandle; - HANDLE ErrorHandle; - HANDLE InputWaitHandle; - LPTHREAD_START_ROUTINE CtrlDispatcher; - LPTHREAD_START_ROUTINE PropDispatcher; + /* + * If ProcessId == ATTACH_PARENT_PROCESS == -1, then attach + * the current process to its parent process console. + */ + DWORD ProcessId; + + PCONSOLE_START_INFO ConsoleStartInfo; + + LPTHREAD_START_ROUTINE CtrlRoutine; + LPTHREAD_START_ROUTINE PropRoutine; } CONSOLE_ATTACHCONSOLE, *PCONSOLE_ATTACHCONSOLE; -typedef struct +typedef struct _CONSOLE_FREECONSOLE { HANDLE ConsoleHandle; } CONSOLE_FREECONSOLE, *PCONSOLE_FREECONSOLE; -typedef struct +typedef struct _CONSOLE_GETSCREENBUFFERINFO { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -297,14 +308,14 @@ typedef struct COORD MaximumViewSize; } CONSOLE_GETSCREENBUFFERINFO, *PCONSOLE_GETSCREENBUFFERINFO; -typedef struct +typedef struct _CONSOLE_SETCURSORPOSITION { HANDLE ConsoleHandle; HANDLE OutputHandle; COORD Position; } CONSOLE_SETCURSORPOSITION, *PCONSOLE_SETCURSORPOSITION; -typedef struct +typedef struct _CONSOLE_SHOWCURSOR { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -312,14 +323,14 @@ typedef struct INT RefCount; } CONSOLE_SHOWCURSOR, *PCONSOLE_SHOWCURSOR; -typedef struct +typedef struct _CONSOLE_SETCURSOR { HANDLE ConsoleHandle; HANDLE OutputHandle; HCURSOR CursorHandle; } CONSOLE_SETCURSOR, *PCONSOLE_SETCURSOR; -typedef struct +typedef struct _CONSOLE_GETSETCURSORINFO { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -330,33 +341,33 @@ typedef struct */ } CONSOLE_GETSETCURSORINFO, *PCONSOLE_GETSETCURSORINFO; -typedef struct +typedef struct _CONSOLE_GETMOUSEINFO { HANDLE ConsoleHandle; ULONG NumButtons; } CONSOLE_GETMOUSEINFO, *PCONSOLE_GETMOUSEINFO; -typedef struct +typedef struct _CONSOLE_SETTEXTATTRIB { HANDLE ConsoleHandle; HANDLE OutputHandle; WORD Attributes; } CONSOLE_SETTEXTATTRIB, *PCONSOLE_SETTEXTATTRIB; -typedef struct +typedef struct _CONSOLE_GETSETCONSOLEMODE { HANDLE ConsoleHandle; HANDLE Handle; DWORD Mode; } CONSOLE_GETSETCONSOLEMODE, *PCONSOLE_GETSETCONSOLEMODE; -typedef struct +typedef struct _CONSOLE_GETDISPLAYMODE { HANDLE ConsoleHandle; DWORD DisplayMode; // ModeFlags } CONSOLE_GETDISPLAYMODE, *PCONSOLE_GETDISPLAYMODE; -typedef struct +typedef struct _CONSOLE_SETDISPLAYMODE { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -371,7 +382,7 @@ typedef struct #define CONSOLE_HARDWARE_STATE_GDI_MANAGED 0 #define CONSOLE_HARDWARE_STATE_DIRECT 1 -typedef struct +typedef struct _CONSOLE_GETSETHWSTATE { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -381,7 +392,7 @@ typedef struct -typedef struct +typedef struct _CONSOLE_CREATESCREENBUFFER { HANDLE ConsoleHandle; DWORD DesiredAccess; @@ -399,20 +410,20 @@ typedef struct HANDLE OutputHandle; /* Handle to newly created screen buffer */ } CONSOLE_CREATESCREENBUFFER, *PCONSOLE_CREATESCREENBUFFER; -typedef struct +typedef struct _CONSOLE_SETACTIVESCREENBUFFER { HANDLE ConsoleHandle; HANDLE OutputHandle; /* Handle to screen buffer to switch to */ } CONSOLE_SETACTIVESCREENBUFFER, *PCONSOLE_SETACTIVESCREENBUFFER; -typedef struct +typedef struct _CONSOLE_INVALIDATEDIBITS { HANDLE ConsoleHandle; HANDLE OutputHandle; SMALL_RECT Region; } CONSOLE_INVALIDATEDIBITS, *PCONSOLE_INVALIDATEDIBITS; -typedef struct +typedef struct _CONSOLE_SETPALETTE { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -420,7 +431,7 @@ typedef struct UINT Usage; } CONSOLE_SETPALETTE, *PCONSOLE_SETPALETTE; -typedef struct +typedef struct _CONSOLE_GETSETCONSOLETITLE { HANDLE ConsoleHandle; ULONG Length; @@ -428,13 +439,13 @@ typedef struct BOOLEAN Unicode; } CONSOLE_GETSETCONSOLETITLE, *PCONSOLE_GETSETCONSOLETITLE; -typedef struct +typedef struct _CONSOLE_FLUSHINPUTBUFFER { HANDLE ConsoleHandle; HANDLE InputHandle; } CONSOLE_FLUSHINPUTBUFFER, *PCONSOLE_FLUSHINPUTBUFFER; -typedef struct +typedef struct _CONSOLE_SCROLLSCREENBUFFER { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -466,7 +477,7 @@ typedef union _CODE_ELEMENT WORD Attribute; } CODE_ELEMENT; -typedef struct +typedef struct _CONSOLE_OUTPUTCODE { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -487,7 +498,7 @@ typedef struct } CONSOLE_READOUTPUTCODE , *PCONSOLE_READOUTPUTCODE, CONSOLE_WRITEOUTPUTCODE, *PCONSOLE_WRITEOUTPUTCODE; -typedef struct +typedef struct _CONSOLE_FILLOUTPUTCODE { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -499,7 +510,7 @@ typedef struct ULONG NumCodes; } CONSOLE_FILLOUTPUTCODE, *PCONSOLE_FILLOUTPUTCODE; -typedef struct +typedef struct _CONSOLE_GETINPUT { HANDLE ConsoleHandle; HANDLE InputHandle; @@ -510,7 +521,7 @@ typedef struct BOOLEAN Unicode; } CONSOLE_GETINPUT, *PCONSOLE_GETINPUT; -typedef struct +typedef struct _CONSOLE_WRITEINPUT { HANDLE ConsoleHandle; HANDLE InputHandle; @@ -521,7 +532,7 @@ typedef struct BOOLEAN AppendToEnd; } CONSOLE_WRITEINPUT, *PCONSOLE_WRITEINPUT; -typedef struct +typedef struct _CONSOLE_READOUTPUT { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -533,7 +544,7 @@ typedef struct BOOLEAN Unicode; } CONSOLE_READOUTPUT, *PCONSOLE_READOUTPUT; -typedef struct +typedef struct _CONSOLE_WRITEOUTPUT { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -552,7 +563,7 @@ typedef struct BOOLEAN UseVirtualMemory; } CONSOLE_WRITEOUTPUT, *PCONSOLE_WRITEOUTPUT; -typedef struct +typedef struct _CONSOLE_GETNUMINPUTEVENTS { HANDLE ConsoleHandle; HANDLE InputHandle; @@ -561,20 +572,20 @@ typedef struct -typedef struct +typedef struct _CONSOLE_CLOSEHANDLE { HANDLE ConsoleHandle; HANDLE Handle; } CONSOLE_CLOSEHANDLE, *PCONSOLE_CLOSEHANDLE; -typedef struct +typedef struct _CONSOLE_VERIFYHANDLE { BOOL IsValid; HANDLE ConsoleHandle; HANDLE Handle; } CONSOLE_VERIFYHANDLE, *PCONSOLE_VERIFYHANDLE; -typedef struct +typedef struct _CONSOLE_DUPLICATEHANDLE { HANDLE ConsoleHandle; HANDLE SourceHandle; @@ -584,14 +595,14 @@ typedef struct HANDLE TargetHandle; } CONSOLE_DUPLICATEHANDLE, *PCONSOLE_DUPLICATEHANDLE; -typedef struct +typedef struct _CONSOLE_GETHANDLEINFO { HANDLE ConsoleHandle; HANDLE Handle; DWORD Flags; } CONSOLE_GETHANDLEINFO, *PCONSOLE_GETHANDLEINFO; -typedef struct +typedef struct _CONSOLE_SETHANDLEINFO { HANDLE ConsoleHandle; HANDLE Handle; @@ -608,7 +619,7 @@ typedef enum _CONSOLE_HANDLE_TYPE HANDLE_OUTPUT = 0x02 } CONSOLE_HANDLE_TYPE; -typedef struct +typedef struct _CONSOLE_OPENCONSOLE { HANDLE ConsoleHandle; CONSOLE_HANDLE_TYPE HandleType; @@ -620,14 +631,14 @@ typedef struct -typedef struct +typedef struct _CONSOLE_GETLARGESTWINDOWSIZE { HANDLE ConsoleHandle; HANDLE OutputHandle; COORD Size; } CONSOLE_GETLARGESTWINDOWSIZE, *PCONSOLE_GETLARGESTWINDOWSIZE; -typedef struct +typedef struct _CONSOLE_MENUCONTROL { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -636,13 +647,13 @@ typedef struct HMENU MenuHandle; } CONSOLE_MENUCONTROL, *PCONSOLE_MENUCONTROL; -typedef struct +typedef struct _CONSOLE_SETMENUCLOSE { HANDLE ConsoleHandle; BOOL Enable; } CONSOLE_SETMENUCLOSE, *PCONSOLE_SETMENUCLOSE; -typedef struct +typedef struct _CONSOLE_SETWINDOWINFO { HANDLE ConsoleHandle; HANDLE OutputHandle; @@ -651,13 +662,13 @@ typedef struct // or in the old window position frame (Absolute == FALSE). } CONSOLE_SETWINDOWINFO, *PCONSOLE_SETWINDOWINFO; -typedef struct +typedef struct _CONSOLE_GETWINDOW { HANDLE ConsoleHandle; HWND WindowHandle; } CONSOLE_GETWINDOW, *PCONSOLE_GETWINDOW; -typedef struct +typedef struct _CONSOLE_SETICON { HANDLE ConsoleHandle; HICON IconHandle; @@ -665,7 +676,7 @@ typedef struct -typedef struct +typedef struct _CONSOLE_ADDGETALIAS { HANDLE ConsoleHandle; USHORT SourceLength; @@ -678,7 +689,7 @@ typedef struct BOOLEAN Unicode2; } CONSOLE_ADDGETALIAS, *PCONSOLE_ADDGETALIAS; -typedef struct +typedef struct _CONSOLE_GETALLALIASES { HANDLE ConsoleHandle; USHORT ExeLength; @@ -689,7 +700,7 @@ typedef struct PVOID AliasesBuffer; } CONSOLE_GETALLALIASES, *PCONSOLE_GETALLALIASES; -typedef struct +typedef struct _CONSOLE_GETALLALIASESLENGTH { HANDLE ConsoleHandle; USHORT ExeLength; @@ -699,7 +710,7 @@ typedef struct BOOLEAN Unicode2; } CONSOLE_GETALLALIASESLENGTH, *PCONSOLE_GETALLALIASESLENGTH; -typedef struct +typedef struct _CONSOLE_GETALIASESEXES { HANDLE ConsoleHandle; ULONG Length ; // ExeLength; // ExesLength @@ -707,7 +718,7 @@ typedef struct BOOLEAN Unicode; } CONSOLE_GETALIASESEXES, *PCONSOLE_GETALIASESEXES; -typedef struct +typedef struct _CONSOLE_GETALIASESEXESLENGTH { HANDLE ConsoleHandle; ULONG Length; @@ -716,7 +727,7 @@ typedef struct -typedef struct +typedef struct _CONSOLE_GETCOMMANDHISTORY { HANDLE ConsoleHandle; ULONG HistoryLength; @@ -727,7 +738,7 @@ typedef struct BOOLEAN Unicode2; } CONSOLE_GETCOMMANDHISTORY, *PCONSOLE_GETCOMMANDHISTORY; -typedef struct +typedef struct _CONSOLE_GETCOMMANDHISTORYLENGTH { HANDLE ConsoleHandle; ULONG HistoryLength; @@ -737,7 +748,7 @@ typedef struct BOOLEAN Unicode2; } CONSOLE_GETCOMMANDHISTORYLENGTH, *PCONSOLE_GETCOMMANDHISTORYLENGTH; -typedef struct +typedef struct _CONSOLE_EXPUNGECOMMANDHISTORY { HANDLE ConsoleHandle; USHORT ExeLength; @@ -746,14 +757,14 @@ typedef struct BOOLEAN Unicode2; } CONSOLE_EXPUNGECOMMANDHISTORY, *PCONSOLE_EXPUNGECOMMANDHISTORY; -typedef struct +typedef struct _CONSOLE_GETSETHISTORYINFO { UINT HistoryBufferSize; UINT NumberOfHistoryBuffers; DWORD dwFlags; } CONSOLE_GETSETHISTORYINFO, *PCONSOLE_GETSETHISTORYINFO; -typedef struct +typedef struct _CONSOLE_SETHISTORYNUMBERCOMMANDS { HANDLE ConsoleHandle; ULONG NumCommands; @@ -763,7 +774,7 @@ typedef struct BOOLEAN Unicode2; } CONSOLE_SETHISTORYNUMBERCOMMANDS, *PCONSOLE_SETHISTORYNUMBERCOMMANDS; -typedef struct +typedef struct _CONSOLE_SETHISTORYMODE { HANDLE ConsoleHandle; ULONG Mode; @@ -771,27 +782,27 @@ typedef struct -typedef struct +typedef struct _CONSOLE_SETSCREENBUFFERSIZE { HANDLE ConsoleHandle; HANDLE OutputHandle; COORD Size; } CONSOLE_SETSCREENBUFFERSIZE, *PCONSOLE_SETSCREENBUFFERSIZE; -typedef struct +typedef struct _CONSOLE_GETSELECTIONINFO { HANDLE ConsoleHandle; CONSOLE_SELECTION_INFO Info; } CONSOLE_GETSELECTIONINFO, *PCONSOLE_GETSELECTIONINFO; -typedef struct +typedef struct _CONSOLE_GETINPUTOUTPUTCP { HANDLE ConsoleHandle; UINT CodePage; BOOL OutputCP; // TRUE : Output Code Page ; FALSE : Input Code Page } CONSOLE_GETINPUTOUTPUTCP, *PCONSOLE_GETINPUTOUTPUTCP; -typedef struct +typedef struct _CONSOLE_SETINPUTOUTPUTCP { HANDLE ConsoleHandle; UINT CodePage; @@ -799,14 +810,14 @@ typedef struct HANDLE EventHandle; } CONSOLE_SETINPUTOUTPUTCP, *PCONSOLE_SETINPUTOUTPUTCP; -typedef struct +typedef struct _CONSOLE_GETKBDLAYOUTNAME { HANDLE ConsoleHandle; CHAR LayoutBuffer[KL_NAMELENGTH * sizeof(WCHAR)]; // Can hold up to 9 wchars BOOL Ansi; } CONSOLE_GETKBDLAYOUTNAME, *PCONSOLE_GETKBDLAYOUTNAME; -typedef struct +typedef struct _CONSOLE_REGISTERVDM { HANDLE ConsoleHandle; ULONG RegisterFlags; diff --git a/reactos/win32ss/user/winsrv/consrv.cmake b/reactos/win32ss/user/winsrv/consrv.cmake index 63b6f574d7b..a60a546d356 100644 --- a/reactos/win32ss/user/winsrv/consrv.cmake +++ b/reactos/win32ss/user/winsrv/consrv.cmake @@ -11,8 +11,10 @@ list(APPEND CONSRV_SOURCE consrv/console.c consrv/frontendctl.c consrv/handle.c + consrv/history.c consrv/init.c consrv/lineinput.c + consrv/popup.c consrv/settings.c consrv/subsysreg.c consrv/condrv/coninput.c diff --git a/reactos/win32ss/user/winsrv/consrv/alias.c b/reactos/win32ss/user/winsrv/consrv/alias.c index a288f976b91..a3a39cae48c 100644 --- a/reactos/win32ss/user/winsrv/consrv/alias.c +++ b/reactos/win32ss/user/winsrv/consrv/alias.c @@ -18,23 +18,23 @@ typedef struct _ALIAS_ENTRY { + struct _ALIAS_ENTRY* Next; UNICODE_STRING Source; UNICODE_STRING Target; - struct _ALIAS_ENTRY* Next; } ALIAS_ENTRY, *PALIAS_ENTRY; typedef struct _ALIAS_HEADER { + struct _ALIAS_HEADER* Next; UNICODE_STRING ExeName; PALIAS_ENTRY Data; - struct _ALIAS_HEADER* Next; } ALIAS_HEADER, *PALIAS_HEADER; BOOLEAN -ConvertInputAnsiToUnicode(PCONSOLE Console, +ConvertInputAnsiToUnicode(PCONSRV_CONSOLE Console, PVOID Source, USHORT SourceLength, // BOOLEAN IsUnicode, @@ -61,7 +61,7 @@ ConvertInputAnsiToUnicode(PCONSOLE Console, } BOOLEAN -ConvertInputUnicodeToAnsi(PCONSOLE Console, +ConvertInputUnicodeToAnsi(PCONSRV_CONSOLE Console, PVOID Source, USHORT SourceLength, // BOOLEAN IsAnsi, @@ -474,7 +474,8 @@ CSR_API(SrvAddConsoleAlias) lpTarget = (ConsoleAliasRequest->TargetLength != 0 ? ConsoleAliasRequest->Target : NULL); - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = STATUS_SUCCESS; @@ -570,7 +571,8 @@ CSR_API(SrvGetConsoleAlias) return STATUS_INVALID_PARAMETER; } - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; Header = IntFindAliasHeader(Console, @@ -647,7 +649,8 @@ CSR_API(SrvGetConsoleAliases) return STATUS_INVALID_PARAMETER; } - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; Header = IntFindAliasHeader(Console, @@ -747,7 +750,8 @@ CSR_API(SrvGetConsoleAliasesLength) return STATUS_INVALID_PARAMETER; } - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; Header = IntFindAliasHeader(Console, @@ -787,7 +791,8 @@ CSR_API(SrvGetConsoleAliasExes) return STATUS_INVALID_PARAMETER; } - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; if (IntGetConsoleAliasesExesLength(Console->Aliases, GetAliasesExesRequest->Unicode) > GetAliasesExesRequest->Length) @@ -864,7 +869,8 @@ CSR_API(SrvGetConsoleAliasExesLength) DPRINT1("SrvGetConsoleAliasExesLength entered ApiMessage %p\n", ApiMessage); - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; GetAliasesExesLengthRequest->Length = diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c b/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c index 4c883eec8e6..800abb4052a 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c @@ -16,20 +16,6 @@ /* GLOBALS ********************************************************************/ -/* - * From MSDN: - * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. - * If they are the same, the function fails, and GetLastError returns - * ERROR_INVALID_PARAMETER." - */ -#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \ - ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ - WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) - -#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \ - ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ - MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1) - typedef struct ConsoleInput_t { LIST_ENTRY ListEntry; @@ -39,39 +25,13 @@ typedef struct ConsoleInput_t /* PRIVATE FUNCTIONS **********************************************************/ -static VOID -ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent) -{ - if (InputEvent->EventType == KEY_EVENT) - { - WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar; - InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0; - ConsoleInputUnicodeCharToAnsiChar(Console, - &InputEvent->Event.KeyEvent.uChar.AsciiChar, - &UnicodeChar); - } -} - -static VOID -ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent) -{ - if (InputEvent->EventType == KEY_EVENT) - { - CHAR AsciiChar = InputEvent->Event.KeyEvent.uChar.AsciiChar; - InputEvent->Event.KeyEvent.uChar.AsciiChar = 0; - ConsoleInputAnsiCharToUnicodeChar(Console, - &InputEvent->Event.KeyEvent.uChar.UnicodeChar, - &AsciiChar); - } -} - - -NTSTATUS -ConDrvAddInputEvents(PCONSOLE Console, - PINPUT_RECORD InputRecords, // InputEvent - ULONG NumEventsToWrite, - PULONG NumEventsWritten, - BOOLEAN AppendToEnd) +// ConDrvAddInputEvents +static NTSTATUS +AddInputEvents(PCONSOLE Console, + PINPUT_RECORD InputRecords, // InputEvent + ULONG NumEventsToWrite, + PULONG NumEventsWritten, + BOOLEAN AppendToEnd) { NTSTATUS Status = STATUS_SUCCESS; ULONG i = 0; @@ -218,61 +178,7 @@ Done: return Status; } - -ULONG -PreprocessInput(PCONSOLE Console, - PINPUT_RECORD InputEvent, - ULONG NumEventsToWrite); -VOID -PostprocessInput(PCONSOLE Console); - -NTSTATUS -ConioAddInputEvents(PCONSOLE Console, - PINPUT_RECORD InputRecords, // InputEvent - ULONG NumEventsToWrite, - PULONG NumEventsWritten, - BOOLEAN AppendToEnd) -{ - NTSTATUS Status = STATUS_SUCCESS; - - if (NumEventsWritten) *NumEventsWritten = 0; - - /* - * This pre-processing code MUST be IN consrv ONLY!! - */ - NumEventsToWrite = PreprocessInput(Console, InputRecords, NumEventsToWrite); - if (NumEventsToWrite == 0) return STATUS_SUCCESS; - - Status = ConDrvAddInputEvents(Console, - InputRecords, - NumEventsToWrite, - NumEventsWritten, - AppendToEnd); - - /* - * This post-processing code MUST be IN consrv ONLY!! - */ - // if (NT_SUCCESS(Status)) - if (Status == STATUS_SUCCESS) PostprocessInput(Console); - - return Status; -} - -/* Move elsewhere...*/ -NTSTATUS -ConioProcessInputEvent(PCONSOLE Console, - PINPUT_RECORD InputEvent) -{ - ULONG NumEventsWritten; - return ConioAddInputEvents(Console, - InputEvent, - 1, - &NumEventsWritten, - TRUE); -} - - -VOID +static VOID PurgeInputBuffer(PCONSOLE Console) { PLIST_ENTRY CurrentEntry; @@ -285,6 +191,36 @@ PurgeInputBuffer(PCONSOLE Console) ConsoleFreeHeap(Event); } + // CloseHandle(Console->InputBuffer.ActiveEvent); +} + +NTSTATUS NTAPI +ConDrvInitInputBuffer(IN PCONSOLE Console, + IN ULONG InputBufferSize) +{ + SECURITY_ATTRIBUTES SecurityAttributes; + + ConSrvInitObject(&Console->InputBuffer.Header, INPUT_BUFFER, Console); + + SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + SecurityAttributes.lpSecurityDescriptor = NULL; + SecurityAttributes.bInheritHandle = TRUE; + + Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL); + if (Console->InputBuffer.ActiveEvent == NULL) return STATUS_UNSUCCESSFUL; + + Console->InputBuffer.InputBufferSize = InputBufferSize; + InitializeListHead(&Console->InputBuffer.InputEvents); + Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | + ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT; + + return STATUS_SUCCESS; +} + +VOID NTAPI +ConDrvDeinitInputBuffer(IN PCONSOLE Console) +{ + PurgeInputBuffer(Console); CloseHandle(Console->InputBuffer.ActiveEvent); } @@ -302,10 +238,7 @@ ConDrvReadConsole(IN PCONSOLE Console, OUT PULONG NumCharsRead OPTIONAL) { // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait. - NTSTATUS Status = STATUS_PENDING; - PLIST_ENTRY CurrentEntry; - ConsoleInput *Input; - ULONG i; + // NTSTATUS Status; = STATUS_PENDING; if (Console == NULL || InputBuffer == NULL || /* Buffer == NULL || */ ReadControl == NULL || ReadControl->nLength != sizeof(CONSOLE_READCONSOLE_CONTROL)) @@ -317,128 +250,14 @@ ConDrvReadConsole(IN PCONSOLE Console, ASSERT(Console == InputBuffer->Header.Console); ASSERT((Buffer != NULL) || (Buffer == NULL && NumCharsToRead == 0)); - /* We haven't read anything (yet) */ - - i = ReadControl->nInitialChars; - - if (InputBuffer->Mode & ENABLE_LINE_INPUT) - { - if (Console->LineBuffer == NULL) - { - /* Starting a new line */ - Console->LineMaxSize = max(256, NumCharsToRead); - - Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR)); - if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY; - - Console->LinePos = Console->LineSize = ReadControl->nInitialChars; - Console->LineComplete = Console->LineUpPressed = FALSE; - Console->LineInsertToggle = Console->InsertMode; - Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask; - - /* - * Pre-filling the buffer is only allowed in the Unicode API, - * so we don't need to worry about ANSI <-> Unicode conversion. - */ - memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR)); - if (Console->LineSize == Console->LineMaxSize) - { - Console->LineComplete = TRUE; - Console->LinePos = 0; - } - } - - /* If we don't have a complete line yet, process the pending input */ - while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents)) - { - /* Remove input event from queue */ - CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); - if (IsListEmpty(&InputBuffer->InputEvents)) - { - ResetEvent(InputBuffer->ActiveEvent); - } - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - - /* Only pay attention to key down */ - if (Input->InputEvent.EventType == KEY_EVENT && - Input->InputEvent.Event.KeyEvent.bKeyDown) - { - LineInputKeyDown(Console, ExeName, - &Input->InputEvent.Event.KeyEvent); - ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; - } - ConsoleFreeHeap(Input); - } - - /* Check if we have a complete line to read from */ - if (Console->LineComplete) - { - while (i < NumCharsToRead && Console->LinePos != Console->LineSize) - { - WCHAR Char = Console->LineBuffer[Console->LinePos++]; - - if (Unicode) - { - ((PWCHAR)Buffer)[i] = Char; - } - else - { - ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); - } - ++i; - } - - if (Console->LinePos == Console->LineSize) - { - /* Entire line has been read */ - ConsoleFreeHeap(Console->LineBuffer); - Console->LineBuffer = NULL; - } - - Status = STATUS_SUCCESS; - } - } - else - { - /* Character input */ - while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents)) - { - /* Remove input event from queue */ - CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); - if (IsListEmpty(&InputBuffer->InputEvents)) - { - ResetEvent(InputBuffer->ActiveEvent); - } - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - - /* Only pay attention to valid ASCII chars, on key down */ - if (Input->InputEvent.EventType == KEY_EVENT && - Input->InputEvent.Event.KeyEvent.bKeyDown && - Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0') - { - WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar; - - if (Unicode) - { - ((PWCHAR)Buffer)[i] = Char; - } - else - { - ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); - } - ++i; - - /* Did read something */ - Status = STATUS_SUCCESS; - } - ConsoleFreeHeap(Input); - } - } - - // FIXME: Only set if Status == STATUS_SUCCESS ??? - if (NumCharsRead) *NumCharsRead = i; - - return Status; + /* Call the line-discipline */ + return TermReadStream(Console, + ExeName, + Unicode, + Buffer, + ReadControl, + NumCharsToRead, + NumCharsRead); } NTSTATUS NTAPI @@ -446,7 +265,6 @@ ConDrvGetConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, IN BOOLEAN KeepEvents, IN BOOLEAN WaitForMoreEvents, - IN BOOLEAN Unicode, OUT PINPUT_RECORD InputRecord, IN ULONG NumEventsToRead, OUT PULONG NumEventsRead OPTIONAL) @@ -496,20 +314,13 @@ ConDrvGetConsoleInput(IN PCONSOLE Console, if (NumEventsRead) *NumEventsRead = i; - /* Now translate everything to ANSI */ - if (!Unicode) - { - for (; i > 0; --i) - { - ConioInputEventToAnsi(InputBuffer->Header.Console, --InputRecord); - } - } - if (IsListEmpty(&InputBuffer->InputEvents)) { ResetEvent(InputBuffer->ActiveEvent); } + // FIXME: If we add back UNICODE support, it's here that we need to do the translation. + /* We read all the inputs available, we return success */ return STATUS_SUCCESS; } @@ -517,15 +328,11 @@ ConDrvGetConsoleInput(IN PCONSOLE Console, NTSTATUS NTAPI ConDrvWriteConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, - IN BOOLEAN Unicode, IN BOOLEAN AppendToEnd, IN PINPUT_RECORD InputRecord, IN ULONG NumEventsToWrite, OUT PULONG NumEventsWritten OPTIONAL) { - NTSTATUS Status = STATUS_SUCCESS; - ULONG i; - if (Console == NULL || InputBuffer == NULL /* || InputRecord == NULL */) return STATUS_INVALID_PARAMETER; @@ -533,26 +340,16 @@ ConDrvWriteConsoleInput(IN PCONSOLE Console, ASSERT(Console == InputBuffer->Header.Console); ASSERT((InputRecord != NULL) || (InputRecord == NULL && NumEventsToWrite == 0)); - /* First translate everything to UNICODE */ - if (!Unicode) - { - for (i = 0; i < NumEventsToWrite; ++i) - { - ConioInputEventToUnicode(Console, &InputRecord[i]); - } - } - /* Now, add the events */ - // if (NumEventsWritten) *NumEventsWritten = 0; - // ConDrvAddInputEvents - Status = ConioAddInputEvents(Console, - InputRecord, - NumEventsToWrite, - NumEventsWritten, - AppendToEnd); - // if (NumEventsWritten) *NumEventsWritten = i; + if (NumEventsWritten) *NumEventsWritten = 0; - return Status; + // FIXME: If we add back UNICODE support, it's here that we need to do the translation. + + return AddInputEvents(Console, + InputRecord, + NumEventsToWrite, + NumEventsWritten, + AppendToEnd); } NTSTATUS NTAPI diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/conoutput.c b/reactos/win32ss/user/winsrv/consrv/condrv/conoutput.c index 4fe657454f4..b6ce1bcb4bd 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/conoutput.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/conoutput.c @@ -115,7 +115,7 @@ static VOID ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer); VOID NTAPI -ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) +ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) { PCONSOLE Console = Buffer->Header.Console; PCONSOLE_SCREEN_BUFFER NewBuffer; @@ -190,7 +190,7 @@ ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console, /* If old buffer has no handles, it's now unreferenced */ if (Console->ActiveBuffer->Header.ReferenceCount == 0) { - ConioDeleteScreenBuffer(Console->ActiveBuffer); + ConDrvDeleteScreenBuffer(Console->ActiveBuffer); } /* Tie console to new buffer and signal the change to the frontend */ diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/console.c b/reactos/win32ss/user/winsrv/consrv/condrv/console.c index 4f60730212b..4075e76f3a2 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/console.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/console.c @@ -76,35 +76,6 @@ RemoveConsole(IN PCONSOLE Console) /* PRIVATE FUNCTIONS **********************************************************/ -// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180 -static BOOLEAN -ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest, - IN PCWSTR Source) -{ - SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR); - if (Size > MAXUSHORT) return FALSE; - - UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size); - if (UniDest->Buffer == NULL) return FALSE; - - RtlCopyMemory(UniDest->Buffer, Source, Size); - UniDest->MaximumLength = (USHORT)Size; - UniDest->Length = (USHORT)Size - sizeof(WCHAR); - - return TRUE; -} - -// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431 -static VOID -ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString) -{ - if (UnicodeString->Buffer) - { - ConsoleFreeHeap(UnicodeString->Buffer); - RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING)); - } -} - VOID NTAPI ConDrvPause(PCONSOLE Console) { @@ -190,14 +161,10 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole, IN PCONSOLE_INFO ConsoleInfo) { NTSTATUS Status; - SECURITY_ATTRIBUTES SecurityAttributes; // CONSOLE_INFO CapturedConsoleInfo; TEXTMODE_BUFFER_INFO ScreenBufferInfo; PCONSOLE Console; PCONSOLE_SCREEN_BUFFER NewBuffer; -#if 0 - WCHAR DefaultTitle[128]; -#endif if (NewConsole == NULL || ConsoleInfo == NULL) return STATUS_INVALID_PARAMETER; @@ -236,34 +203,16 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole, Console->ConsoleSize = ConsoleInfo->ConsoleSize; Console->FixedSize = FALSE; // Value by default; is reseted by the terminals if needed. - /* - * Initialize the input buffer - */ - ConSrvInitObject(&Console->InputBuffer.Header, INPUT_BUFFER, Console); - - SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); - SecurityAttributes.lpSecurityDescriptor = NULL; - SecurityAttributes.bInheritHandle = TRUE; - Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL); - if (NULL == Console->InputBuffer.ActiveEvent) + /* Initialize the input buffer */ + Status = ConDrvInitInputBuffer(Console, 0 /* ConsoleInfo->InputBufferSize */); + if (!NT_SUCCESS(Status)) { + DPRINT1("ConDrvInitInputBuffer: failed, Status = 0x%08lx\n", Status); DeleteCriticalSection(&Console->Lock); ConsoleFreeHeap(Console); - return STATUS_UNSUCCESSFUL; + return Status; } - Console->InputBuffer.InputBufferSize = 0; // FIXME! - InitializeListHead(&Console->InputBuffer.InputEvents); - Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | - ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT; - - Console->InsertMode = ConsoleInfo->InsertMode; - Console->LineBuffer = NULL; - Console->LinePos = Console->LineMaxSize = Console->LineSize = 0; - Console->LineComplete = Console->LineUpPressed = FALSE; - Console->LineInsertToggle = Console->InsertMode; - // LineWakeupMask - /* Set-up the code page */ Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage; @@ -282,7 +231,7 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole, if (!NT_SUCCESS(Status)) { DPRINT1("ConDrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status); - CloseHandle(Console->InputBuffer.ActiveEvent); + ConDrvDeinitInputBuffer(Console); DeleteCriticalSection(&Console->Lock); ConsoleFreeHeap(Console); return Status; @@ -291,28 +240,6 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole, Console->ActiveBuffer = NewBuffer; Console->UnpauseEvent = NULL; - /* Initialize the console title */ - ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo->ConsoleTitle); -#if 0 - if (ConsoleInfo.ConsoleTitle[0] == L'\0') - { - if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0]))) - { - ConsoleCreateUnicodeString(&Console->Title, DefaultTitle); - } - else - { - ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console"); - } - } - else - { -#endif - ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo->ConsoleTitle); -#if 0 - } -#endif - DPRINT("Console initialized\n"); /* All went right, so add the console to the list */ @@ -437,10 +364,10 @@ ConDrvDeleteConsole(IN PCONSOLE Console) /* FIXME: Send a terminate message to all the processes owning this console */ - /* Cleanup the UI-oriented part */ - DPRINT("Deregister console\n"); + /* Deregister the terminal */ + DPRINT("Deregister terminal\n"); ConDrvDeregisterTerminal(Console); - DPRINT("Console deregistered\n"); + DPRINT("Terminal deregistered\n"); /*** * Check that the console is in terminating state before continuing @@ -465,24 +392,19 @@ ConDrvDeleteConsole(IN PCONSOLE Console) /* Remove the console from the list */ RemoveConsole(Console); - /* Discard all entries in the input event queue */ - PurgeInputBuffer(Console); - if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer); - /* Delete the last screen buffer */ - ConioDeleteScreenBuffer(Console->ActiveBuffer); + ConDrvDeleteScreenBuffer(Console->ActiveBuffer); Console->ActiveBuffer = NULL; if (!IsListEmpty(&Console->BufferList)) { - DPRINT1("BUG: screen buffer list not empty\n"); - ASSERT(FALSE); + /***ConDrvUnlockConsoleList();***/ + ASSERTMSG("BUGBUGBUG!! screen buffer list not empty\n", FALSE); } - /**/ CloseHandle(Console->InputBuffer.ActiveEvent); /**/ - if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent); + /* Deinitialize the input buffer */ + ConDrvDeinitInputBuffer(Console); - ConsoleFreeUnicodeString(&Console->OriginalTitle); - ConsoleFreeUnicodeString(&Console->Title); + if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent); DPRINT("ConDrvDeleteConsole - Unlocking\n"); LeaveCriticalSection(&Console->Lock); @@ -518,17 +440,7 @@ ConDrvGetConsoleMode(IN PCONSOLE Console, if (INPUT_BUFFER == Object->Type) { PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object; - *ConsoleMode = InputBuffer->Mode; - - if (Console->QuickEdit || Console->InsertMode) - { - // Windows does this, even if it's not documented on MSDN - *ConsoleMode |= ENABLE_EXTENDED_FLAGS; - - if (Console->QuickEdit ) *ConsoleMode |= ENABLE_QUICK_EDIT_MODE; - if (Console->InsertMode) *ConsoleMode |= ENABLE_INSERT_MODE; - } } else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type) { @@ -548,8 +460,6 @@ ConDrvSetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, IN ULONG ConsoleMode) { -#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | \ - ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE ) #define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \ ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \ ENABLE_MOUSE_INPUT ) @@ -567,45 +477,21 @@ ConDrvSetConsoleMode(IN PCONSOLE Console, { PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object; - DPRINT("SetConsoleMode(Input, %d)\n", ConsoleMode); - - /* - * 1. Only the presence of valid mode flags is allowed. - */ - if (ConsoleMode & ~(CONSOLE_VALID_INPUT_MODES | CONSOLE_VALID_CONTROL_MODES)) + /* Only the presence of valid mode flags is allowed */ + if (ConsoleMode & ~CONSOLE_VALID_INPUT_MODES) { Status = STATUS_INVALID_PARAMETER; - goto Quit; } - - /* - * 2. If we use control mode flags without ENABLE_EXTENDED_FLAGS, - * then consider the flags invalid. - * - if ( (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) && - (ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0 ) + else { - Status = STATUS_INVALID_PARAMETER; - goto Quit; + InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES); } - */ - - /* - * 3. Now we can continue. - */ - if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) - { - Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE); - Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE); - } - InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES); } else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type) { PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object; - DPRINT("SetConsoleMode(Output, %d)\n", ConsoleMode); - + /* Only the presence of valid mode flags is allowed */ if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES) { Status = STATUS_INVALID_PARAMETER; @@ -620,115 +506,9 @@ ConDrvSetConsoleMode(IN PCONSOLE Console, Status = STATUS_INVALID_HANDLE; } -Quit: return Status; } -NTSTATUS NTAPI -ConDrvGetConsoleTitle(IN PCONSOLE Console, - IN BOOLEAN Unicode, - IN OUT PVOID TitleBuffer, - IN OUT PULONG BufLength) -{ - ULONG Length; - - if (Console == NULL || TitleBuffer == NULL || BufLength == NULL) - return STATUS_INVALID_PARAMETER; - - /* Copy title of the console to the user title buffer */ - if (Unicode) - { - if (*BufLength >= sizeof(WCHAR)) - { - Length = min(*BufLength - sizeof(WCHAR), Console->Title.Length); - RtlCopyMemory(TitleBuffer, Console->Title.Buffer, Length); - ((PWCHAR)TitleBuffer)[Length / sizeof(WCHAR)] = L'\0'; - *BufLength = Length; - } - else - { - *BufLength = Console->Title.Length; - } - } - else - { - if (*BufLength >= sizeof(CHAR)) - { - Length = min(*BufLength - sizeof(CHAR), Console->Title.Length / sizeof(WCHAR)); - Length = WideCharToMultiByte(Console->InputCodePage, 0, - Console->Title.Buffer, Length, - TitleBuffer, Length, - NULL, NULL); - ((PCHAR)TitleBuffer)[Length] = '\0'; - *BufLength = Length; - } - else - { - *BufLength = Console->Title.Length / sizeof(WCHAR); - } - } - - return STATUS_SUCCESS; -} - -NTSTATUS NTAPI -ConDrvSetConsoleTitle(IN PCONSOLE Console, - IN BOOLEAN Unicode, - IN PVOID TitleBuffer, - IN ULONG BufLength) -{ - PWCHAR Buffer; - ULONG Length; - - if (Console == NULL || TitleBuffer == NULL) - return STATUS_INVALID_PARAMETER; - - if (Unicode) - { - /* Length is in bytes */ - Length = BufLength; - } - else - { - /* Use the console input CP for the conversion */ - Length = MultiByteToWideChar(Console->InputCodePage, 0, - TitleBuffer, BufLength, - NULL, 0); - /* The returned Length was in number of wchars, convert it in bytes */ - Length *= sizeof(WCHAR); - } - - /* Allocate a new buffer to hold the new title (NULL-terminated) */ - Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Length + sizeof(WCHAR)); - if (!Buffer) return STATUS_NO_MEMORY; - - /* Free the old title */ - ConsoleFreeUnicodeString(&Console->Title); - - /* Copy title to console */ - Console->Title.Buffer = Buffer; - Console->Title.Length = Length; - Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR); - - if (Unicode) - { - RtlCopyMemory(Console->Title.Buffer, TitleBuffer, Console->Title.Length); - } - else - { - MultiByteToWideChar(Console->InputCodePage, 0, - TitleBuffer, BufLength, - Console->Title.Buffer, - Console->Title.Length / sizeof(WCHAR)); - } - - /* NULL-terminate */ - Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0'; - - // TermChangeTitle(Console); - return STATUS_SUCCESS; -} - NTSTATUS NTAPI ConDrvGetConsoleCP(IN PCONSOLE Console, OUT PUINT CodePage, diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/dummyterm.c b/reactos/win32ss/user/winsrv/consrv/condrv/dummyterm.c index 3b38329cfcd..2066cb54ee4 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/dummyterm.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/dummyterm.c @@ -25,23 +25,57 @@ DummyDeinitTerminal(IN OUT PTERMINAL This) { } + + +/************ Line discipline ***************/ + +static NTSTATUS NTAPI +DummyReadStream(IN OUT PTERMINAL This, + /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/ + IN BOOLEAN Unicode, + /**PWCHAR Buffer,**/ + OUT PVOID Buffer, + IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, + IN ULONG NumCharsToRead, + OUT PULONG NumCharsRead OPTIONAL) +{ + /* + * We were called because the console was in cooked mode. + * There is nothing to read, wait until a real terminal + * is plugged into the console. + */ + return STATUS_PENDING; +} + +static NTSTATUS NTAPI +DummyWriteStream(IN OUT PTERMINAL This, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib) +{ + /* + * We were called because the console was in cooked mode. + * There is nothing to write, wait until a real terminal + * is plugged into the console. + */ + + // /* Stop here if the console is paused */ + // if (Console->UnpauseEvent != NULL) return STATUS_PENDING; + + return STATUS_PENDING; +} + +/************ Line discipline ***************/ + + + static VOID NTAPI DummyDrawRegion(IN OUT PTERMINAL This, SMALL_RECT* Region) { } -static VOID NTAPI -DummyWriteStream(IN OUT PTERMINAL This, - SMALL_RECT* Region, - SHORT CursorStartX, - SHORT CursorStartY, - UINT ScrolledLines, - PWCHAR Buffer, - UINT Length) -{ -} - static BOOL NTAPI DummySetCursorInfo(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer) @@ -74,26 +108,12 @@ DummyReleaseScreenBuffer(IN OUT PTERMINAL This, { } -static VOID NTAPI -DummyChangeTitle(IN OUT PTERMINAL This) -{ -} - static VOID NTAPI DummyGetLargestConsoleWindowSize(IN OUT PTERMINAL This, PCOORD pSize) { } -/* -static BOOL NTAPI -DummyGetSelectionInfo(IN OUT PTERMINAL This, - PCONSOLE_SELECTION_INFO pSelectionInfo) -{ - return TRUE; -} -*/ - static BOOL NTAPI DummySetPalette(IN OUT PTERMINAL This, HPALETTE PaletteHandle, @@ -113,16 +133,17 @@ static TERMINAL_VTBL DummyVtbl = { DummyInitTerminal, DummyDeinitTerminal, - DummyDrawRegion, + + DummyReadStream, DummyWriteStream, + + DummyDrawRegion, DummySetCursorInfo, DummySetScreenInfo, DummyResizeTerminal, DummySetActiveScreenBuffer, DummyReleaseScreenBuffer, - DummyChangeTitle, DummyGetLargestConsoleWindowSize, - // DummyGetSelectionInfo, DummySetPalette, DummyShowMouseCursor, }; diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/text.c b/reactos/win32ss/user/winsrv/consrv/condrv/text.c index 6b8dbdcbc8a..72e62c121af 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/text.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/text.c @@ -16,7 +16,19 @@ /* GLOBALS ********************************************************************/ -#define TAB_WIDTH 8 +/* + * From MSDN: + * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. + * If they are the same, the function fails, and GetLastError returns + * ERROR_INVALID_PARAMETER." + */ +#define ConsoleOutputUnicodeToAnsiChar(Console, dChar, sWChar) \ + ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ + WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) + +#define ConsoleOutputAnsiToUnicodeChar(Console, dWChar, sChar) \ + ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ + MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1) /* PRIVATE FUNCTIONS **********************************************************/ @@ -33,7 +45,7 @@ static CONSOLE_SCREEN_BUFFER_VTBL TextVtbl = }; -static VOID +/*static*/ VOID ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff); @@ -127,7 +139,7 @@ ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y) return &Buff->Buffer[((Y + Buff->VirtualY) % Buff->ScreenBufferSize.Y) * Buff->ScreenBufferSize.X + X]; } -static VOID +/*static*/ VOID ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff) { PCHAR_INFO Ptr = ConioCoordToPointer(Buff, 0, Buff->CursorPosition.Y); @@ -235,6 +247,15 @@ ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer, } } +// FIXME! +NTSTATUS NTAPI +ConDrvWriteConsoleInput(IN PCONSOLE Console, + IN PCONSOLE_INPUT_BUFFER InputBuffer, + IN BOOLEAN AppendToEnd, + IN PINPUT_RECORD InputRecord, + IN ULONG NumEventsToWrite, + OUT PULONG NumEventsWritten OPTIONAL); + NTSTATUS ConioResizeBuffer(PCONSOLE Console, PTEXTMODE_SCREEN_BUFFER ScreenBuffer, @@ -343,175 +364,19 @@ ConioResizeBuffer(PCONSOLE Console, */ if (Console->InputBuffer.Mode & ENABLE_WINDOW_INPUT) { + ULONG NumEventsWritten; INPUT_RECORD er; er.EventType = WINDOW_BUFFER_SIZE_EVENT; er.Event.WindowBufferSizeEvent.dwSize = ScreenBuffer->ScreenBufferSize; - ConioProcessInputEvent(Console, &er); - } - - return STATUS_SUCCESS; -} - -static VOID -ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT ScrolledLines) -{ - /* If we hit bottom, slide the viewable screen */ - if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y) - { - Buff->CursorPosition.Y--; - if (++Buff->VirtualY == Buff->ScreenBufferSize.Y) - { - Buff->VirtualY = 0; - } - (*ScrolledLines)++; - ClearLineBuffer(Buff); - if (UpdateRect->Top != 0) - { - UpdateRect->Top--; - } - } - UpdateRect->Left = 0; - UpdateRect->Right = Buff->ScreenBufferSize.X - 1; - UpdateRect->Bottom = Buff->CursorPosition.Y; -} - -NTSTATUS -ConioWriteConsole(PCONSOLE Console, - PTEXTMODE_SCREEN_BUFFER Buff, - PWCHAR Buffer, - DWORD Length, - BOOL Attrib) -{ - UINT i; - PCHAR_INFO Ptr; - SMALL_RECT UpdateRect; - SHORT CursorStartX, CursorStartY; - UINT ScrolledLines; - - CursorStartX = Buff->CursorPosition.X; - CursorStartY = Buff->CursorPosition.Y; - UpdateRect.Left = Buff->ScreenBufferSize.X; - UpdateRect.Top = Buff->CursorPosition.Y; - UpdateRect.Right = -1; - UpdateRect.Bottom = Buff->CursorPosition.Y; - ScrolledLines = 0; - - for (i = 0; i < Length; i++) - { - /* - * If we are in processed mode, interpret special characters and - * display them correctly. Otherwise, just put them into the buffer. - */ - if (Buff->Mode & ENABLE_PROCESSED_OUTPUT) - { - /* --- CR --- */ - if (Buffer[i] == L'\r') - { - Buff->CursorPosition.X = 0; - UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); - UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); - continue; - } - /* --- LF --- */ - else if (Buffer[i] == L'\n') - { - Buff->CursorPosition.X = 0; - ConioNextLine(Buff, &UpdateRect, &ScrolledLines); - continue; - } - /* --- BS --- */ - else if (Buffer[i] == L'\b') - { - /* Only handle BS if we're not on the first pos of the first line */ - if (0 != Buff->CursorPosition.X || 0 != Buff->CursorPosition.Y) - { - if (0 == Buff->CursorPosition.X) - { - /* slide virtual position up */ - Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1; - Buff->CursorPosition.Y--; - UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y); - } - else - { - Buff->CursorPosition.X--; - } - Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); - Ptr->Char.UnicodeChar = L' '; - Ptr->Attributes = Buff->ScreenDefaultAttrib; - UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); - UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); - } - continue; - } - /* --- TAB --- */ - else if (Buffer[i] == L'\t') - { - UINT EndX; - - UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); - EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1); - EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X); - Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); - while (Buff->CursorPosition.X < EndX) - { - Ptr->Char.UnicodeChar = L' '; - Ptr->Attributes = Buff->ScreenDefaultAttrib; - ++Ptr; - Buff->CursorPosition.X++; - } - UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1); - if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) - { - if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) - { - Buff->CursorPosition.X = 0; - ConioNextLine(Buff, &UpdateRect, &ScrolledLines); - } - else - { - Buff->CursorPosition.X--; - } - } - continue; - } - // /* --- BEL ---*/ - // else if (Buffer[i] == L'\a') - // { - // // FIXME: This MUST BE moved to the terminal emulator frontend!! - // DPRINT1("Bell\n"); - // // SendNotifyMessage(Console->hWindow, PM_CONSOLE_BEEP, 0, 0); - // continue; - // } - } - UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); - UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); - - Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); - Ptr->Char.UnicodeChar = Buffer[i]; - if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib; - - Buff->CursorPosition.X++; - if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) - { - if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) - { - Buff->CursorPosition.X = 0; - ConioNextLine(Buff, &UpdateRect, &ScrolledLines); - } - else - { - Buff->CursorPosition.X = CursorStartX; - } - } - } - - if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer) - { - TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, - ScrolledLines, Buffer, Length); + // ConioProcessInputEvent(Console, &er); + ConDrvWriteConsoleInput(Console, + &Console->InputBuffer, + TRUE, + &er, + 1, + &NumEventsWritten); } return STATUS_SUCCESS; @@ -528,7 +393,7 @@ ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console, COORD TopLeft = {0}; ULONG NumCodesToWrite; - USHORT OldScreenAttrib; + USHORT OldScreenAttrib, OldPopupAttrib; if (Console == NULL || Buffer == NULL) { @@ -540,6 +405,7 @@ ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console, NumCodesToWrite = Buffer->ScreenBufferSize.X * Buffer->ScreenBufferSize.Y; OldScreenAttrib = Buffer->ScreenDefaultAttrib; + OldPopupAttrib = Buffer->PopupDefaultAttrib; X = TopLeft.X; Y = (TopLeft.Y + Buffer->VirtualY) % Buffer->ScreenBufferSize.Y; @@ -560,10 +426,14 @@ ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console, /* Foreground color */ if ((Ptr->Attributes & 0x0F) == (OldScreenAttrib & 0x0F)) Ptr->Attributes = (Ptr->Attributes & 0xFFF0) | (NewScreenAttrib & 0x0F); + if ((Ptr->Attributes & 0x0F) == (OldPopupAttrib & 0x0F)) + Ptr->Attributes = (Ptr->Attributes & 0xFFF0) | (NewPopupAttrib & 0x0F); /* Background color */ if ((Ptr->Attributes & 0xF0) == (OldScreenAttrib & 0xF0)) Ptr->Attributes = (Ptr->Attributes & 0xFF0F) | (NewScreenAttrib & 0xF0); + if ((Ptr->Attributes & 0xF0) == (OldPopupAttrib & 0xF0)) + Ptr->Attributes = (Ptr->Attributes & 0xFF0F) | (NewPopupAttrib & 0xF0); // ++Ptr; @@ -644,7 +514,7 @@ ConDrvReadConsoleOutput(IN PCONSOLE Console, } else { - // ConsoleUnicodeCharToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar); + // ConsoleOutputUnicodeToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar); WideCharToMultiByte(Console->OutputCodePage, 0, &Ptr->Char.UnicodeChar, 1, &CurCharInfo->Char.AsciiChar, 1, NULL, NULL); } @@ -707,7 +577,7 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console, } else { - ConsoleAnsiCharToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char.AsciiChar); + ConsoleOutputAnsiToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char.AsciiChar); } Ptr->Attributes = CurCharInfo->Attributes; ++Ptr; @@ -770,7 +640,7 @@ ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console, Ptr = ConioCoordToPointer(Buffer, CapturedWriteRegion.Left, Y); for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; ++X) { - ConsoleAnsiCharToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char); + ConsoleOutputAnsiToUnicodeChar(Console, &Ptr->Char.UnicodeChar, &CurCharInfo->Char); Ptr->Attributes = CurCharInfo->Attributes; ++Ptr; ++CurCharInfo; @@ -807,6 +677,7 @@ ConDrvWriteConsole(IN PCONSOLE Console, /* Stop here if the console is paused */ if (Console->UnpauseEvent != NULL) return STATUS_PENDING; + /* Convert the string to UNICODE */ if (Unicode) { Buffer = StringBuffer; @@ -831,15 +702,16 @@ ConDrvWriteConsole(IN PCONSOLE Console, } } + /* Send it */ if (Buffer) { if (NT_SUCCESS(Status)) { - Status = ConioWriteConsole(Console, - ScreenBuffer, - Buffer, - NumCharsToWrite, - TRUE); + Status = TermWriteStream(Console, + ScreenBuffer, + Buffer, + NumCharsToWrite, + TRUE); if (NT_SUCCESS(Status)) { Written = NumCharsToWrite; @@ -879,6 +751,10 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console, ASSERT(Console == Buffer->Header.Console); ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToRead == 0)); + // + // FIXME: Make overflow checks on ReadCoord !!!!!! + // + if (NumCodesRead) *NumCodesRead = 0; switch (CodeType) @@ -925,7 +801,7 @@ ConDrvReadConsoleOutputString(IN PCONSOLE Console, switch (CodeType) { case CODE_ASCII: - ConsoleUnicodeCharToAnsiChar(Console, (PCHAR)ReadBuffer, &Ptr->Char.UnicodeChar); + ConsoleOutputUnicodeToAnsiChar(Console, (PCHAR)ReadBuffer, &Ptr->Char.UnicodeChar); break; case CODE_UNICODE: @@ -989,6 +865,10 @@ ConDrvWriteConsoleOutputString(IN PCONSOLE Console, ASSERT(Console == Buffer->Header.Console); ASSERT((StringBuffer != NULL) || (StringBuffer == NULL && NumCodesToWrite == 0)); + // + // FIXME: Make overflow checks on WriteCoord !!!!!! + // + if (NumCodesWritten) *NumCodesWritten = 0; switch (CodeType) @@ -1117,13 +997,17 @@ ConDrvFillConsoleOutput(IN PCONSOLE Console, /* Validity check */ ASSERT(Console == Buffer->Header.Console); + // + // FIXME: Make overflow checks on WriteCoord !!!!!! + // + if (NumCodesWritten) *NumCodesWritten = 0; if (CodeType == CODE_ASCII) { /* Conversion from the ASCII char to the UNICODE char */ CODE_ELEMENT tmp; - ConsoleAnsiCharToUnicodeChar(Console, &tmp.UnicodeChar, &Code.AsciiChar); + ConsoleOutputAnsiToUnicodeChar(Console, &tmp.UnicodeChar, &Code.AsciiChar); Code = tmp; } @@ -1308,7 +1192,7 @@ ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console, if (!Unicode) { WCHAR tmp; - ConsoleAnsiCharToUnicodeChar(Console, &tmp, &FillChar.Char.AsciiChar); + ConsoleOutputAnsiToUnicodeChar(Console, &tmp, &FillChar.Char.AsciiChar); FillChar.Char.UnicodeChar = tmp; } diff --git a/reactos/win32ss/user/winsrv/consrv/coninput.c b/reactos/win32ss/user/winsrv/consrv/coninput.c index 953451e9f09..9faaf52f471 100644 --- a/reactos/win32ss/user/winsrv/consrv/coninput.c +++ b/reactos/win32ss/user/winsrv/consrv/coninput.c @@ -26,6 +26,21 @@ ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked)) +/* + * From MSDN: + * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. + * If they are the same, the function fails, and GetLastError returns + * ERROR_INVALID_PARAMETER." + */ +#define ConsoleInputUnicodeToAnsiChar(Console, dChar, sWChar) \ + ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ + WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) + +#define ConsoleInputAnsiToUnicodeChar(Console, dWChar, sChar) \ + ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ + MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1) + + typedef struct _GET_INPUT_INFO { PCSR_THREAD CallingThread; // The thread which called the input API. @@ -36,10 +51,33 @@ typedef struct _GET_INPUT_INFO /* PRIVATE FUNCTIONS **********************************************************/ -/* - * This pre-processing code MUST be IN consrv ONLY - */ -/* static */ ULONG +static VOID +ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent) +{ + if (InputEvent->EventType == KEY_EVENT) + { + WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar; + InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0; + ConsoleInputUnicodeToAnsiChar(Console, + &InputEvent->Event.KeyEvent.uChar.AsciiChar, + &UnicodeChar); + } +} + +static VOID +ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent) +{ + if (InputEvent->EventType == KEY_EVENT) + { + CHAR AsciiChar = InputEvent->Event.KeyEvent.uChar.AsciiChar; + InputEvent->Event.KeyEvent.uChar.AsciiChar = 0; + ConsoleInputAnsiToUnicodeChar(Console, + &InputEvent->Event.KeyEvent.uChar.UnicodeChar, + &AsciiChar); + } +} + +static ULONG PreprocessInput(PCONSRV_CONSOLE Console, PINPUT_RECORD InputEvent, ULONG NumEventsToWrite) @@ -98,10 +136,7 @@ PreprocessInput(PCONSRV_CONSOLE Console, return NumEventsToWrite; } -/* - * This post-processing code MUST be IN consrv ONLY - */ -/* static */ VOID +static VOID PostprocessInput(PCONSRV_CONSOLE Console) { CsrNotifyWait(&Console->ReadWaitQueue, @@ -115,7 +150,58 @@ PostprocessInput(PCONSRV_CONSOLE Console) } +NTSTATUS NTAPI +ConDrvWriteConsoleInput(IN PCONSOLE Console, + IN PCONSOLE_INPUT_BUFFER InputBuffer, + IN BOOLEAN AppendToEnd, + IN PINPUT_RECORD InputRecord, + IN ULONG NumEventsToWrite, + OUT PULONG NumEventsWritten OPTIONAL); +static NTSTATUS +ConioAddInputEvents(PCONSRV_CONSOLE Console, + PINPUT_RECORD InputRecords, // InputEvent + ULONG NumEventsToWrite, + PULONG NumEventsWritten, + BOOLEAN AppendToEnd) +{ + NTSTATUS Status = STATUS_SUCCESS; + if (NumEventsWritten) *NumEventsWritten = 0; + + NumEventsToWrite = PreprocessInput(Console, InputRecords, NumEventsToWrite); + if (NumEventsToWrite == 0) return STATUS_SUCCESS; + + // Status = ConDrvAddInputEvents(Console, + // InputRecords, + // NumEventsToWrite, + // NumEventsWritten, + // AppendToEnd); + + Status = ConDrvWriteConsoleInput((PCONSOLE)Console, + &Console->InputBuffer, + AppendToEnd, + InputRecords, + NumEventsToWrite, + NumEventsWritten); + + // if (NT_SUCCESS(Status)) + if (Status == STATUS_SUCCESS) PostprocessInput(Console); + + return Status; +} + +/* FIXME: This function can be called by CONDRV, in ConioResizeBuffer() in text.c */ +NTSTATUS +ConioProcessInputEvent(PCONSRV_CONSOLE Console, + PINPUT_RECORD InputEvent) +{ + ULONG NumEventsWritten; + return ConioAddInputEvents(Console, + InputEvent, + 1, + &NumEventsWritten, + TRUE); +} static NTSTATUS @@ -127,13 +213,14 @@ WaitBeforeReading(IN PGET_INPUT_INFO InputInfo, if (CreateWaitBlock) { PGET_INPUT_INFO CapturedInputInfo; + PCONSRV_CONSOLE Console = (PCONSRV_CONSOLE)InputInfo->InputBuffer->Header.Console; CapturedInputInfo = ConsoleAllocHeap(0, sizeof(GET_INPUT_INFO)); if (!CapturedInputInfo) return STATUS_NO_MEMORY; RtlMoveMemory(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO)); - if (!CsrCreateWait(&InputInfo->InputBuffer->Header.Console->ReadWaitQueue, + if (!CsrCreateWait(&Console->ReadWaitQueue, WaitFunction, InputInfo->CallingThread, ApiMessage, @@ -381,7 +468,6 @@ ConDrvGetConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, IN BOOLEAN KeepEvents, IN BOOLEAN WaitForMoreEvents, - IN BOOLEAN Unicode, OUT PINPUT_RECORD InputRecord, IN ULONG NumEventsToRead, OUT PULONG NumEventsRead OPTIONAL); @@ -422,7 +508,6 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, InputBuffer, (GetInputRequest->Flags & CONSOLE_READ_KEEPEVENT) != 0, (GetInputRequest->Flags & CONSOLE_READ_CONTINUE ) == 0, - GetInputRequest->Unicode, InputRecord, GetInputRequest->NumRecords, &NumEventsRead); @@ -443,6 +528,18 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, */ GetInputRequest->NumRecords = NumEventsRead; + if (NT_SUCCESS(Status)) + { + /* Now translate everything to ANSI */ + if (!GetInputRequest->Unicode) + { + for (; NumEventsRead > 0; --NumEventsRead) + { + ConioInputEventToAnsi(InputBuffer->Header.Console, --InputRecord); + } + } + } + return Status; // return STATUS_SUCCESS; } @@ -563,14 +660,15 @@ CSR_API(SrvGetConsoleInput) return Status; } +#if 0 NTSTATUS NTAPI ConDrvWriteConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, - IN BOOLEAN Unicode, IN BOOLEAN AppendToEnd, IN PINPUT_RECORD InputRecord, IN ULONG NumEventsToWrite, OUT PULONG NumEventsWritten OPTIONAL); +#endif CSR_API(SrvWriteConsoleInput) { NTSTATUS Status; @@ -619,14 +717,32 @@ CSR_API(SrvWriteConsoleInput) return Status; } + /* First translate everything to UNICODE */ + if (!WriteInputRequest->Unicode) + { + ULONG i; + for (i = 0; i < WriteInputRequest->NumRecords; ++i) + { + ConioInputEventToUnicode(InputBuffer->Header.Console, &InputRecord[i]); + } + } + + /* Now, add the events */ NumEventsWritten = 0; - Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console, - InputBuffer, - WriteInputRequest->Unicode, - WriteInputRequest->AppendToEnd, - InputRecord, - WriteInputRequest->NumRecords, - &NumEventsWritten); + Status = ConioAddInputEvents((PCONSRV_CONSOLE)InputBuffer->Header.Console, + // InputBuffer, + InputRecord, + WriteInputRequest->NumRecords, + &NumEventsWritten, + WriteInputRequest->AppendToEnd); + + // Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console, + // InputBuffer, + // WriteInputRequest->AppendToEnd, + // InputRecord, + // WriteInputRequest->NumRecords, + // &NumEventsWritten); + WriteInputRequest->NumRecords = NumEventsWritten; ConSrvReleaseInputBuffer(InputBuffer, TRUE); diff --git a/reactos/win32ss/user/winsrv/consrv/coninput.h b/reactos/win32ss/user/winsrv/consrv/coninput.h index 7ab46946777..ea186b0fcce 100644 --- a/reactos/win32ss/user/winsrv/consrv/coninput.h +++ b/reactos/win32ss/user/winsrv/consrv/coninput.h @@ -9,4 +9,8 @@ #pragma once -VOID PurgeInputBuffer(PCONSOLE Console); +NTSTATUS NTAPI +ConDrvInitInputBuffer(IN PCONSOLE Console, + IN ULONG InputBufferSize); +VOID NTAPI +ConDrvDeinitInputBuffer(IN PCONSOLE Console); diff --git a/reactos/win32ss/user/winsrv/consrv/conoutput.c b/reactos/win32ss/user/winsrv/consrv/conoutput.c index ab911f78a02..4c73eb1a41b 100644 --- a/reactos/win32ss/user/winsrv/consrv/conoutput.c +++ b/reactos/win32ss/user/winsrv/consrv/conoutput.c @@ -252,7 +252,7 @@ CSR_API(SrvCreateConsoleScreenBuffer) } Status = ConDrvCreateScreenBuffer(&Buff, - Console, + (PCONSOLE)Console, CreateScreenBufferRequest->ScreenBufferType, ScreenBufferInfo); if (!NT_SUCCESS(Status)) goto Quit; @@ -417,7 +417,9 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, { if (CreateWaitBlock) { - if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue, + PCONSRV_CONSOLE Console = (PCONSRV_CONSOLE)ScreenBuffer->Header.Console; + + if (!CsrCreateWait(&Console->WriteWaitQueue, WriteConsoleThread, ClientThread, ApiMessage, diff --git a/reactos/win32ss/user/winsrv/consrv/conoutput.h b/reactos/win32ss/user/winsrv/consrv/conoutput.h index 802b8c4742d..943fff007f0 100644 --- a/reactos/win32ss/user/winsrv/consrv/conoutput.h +++ b/reactos/win32ss/user/winsrv/consrv/conoutput.h @@ -37,7 +37,7 @@ NTSTATUS ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN OUT PCONSOLE Console, IN ULONG BufferType, IN PVOID ScreenBufferInfo); -VOID NTAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer); +VOID NTAPI ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer); // VOID ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer); PCONSOLE_SCREEN_BUFFER diff --git a/reactos/win32ss/user/winsrv/consrv/console.c b/reactos/win32ss/user/winsrv/consrv/console.c index a5d7c658330..fc0c8cdedf3 100644 --- a/reactos/win32ss/user/winsrv/consrv/console.c +++ b/reactos/win32ss/user/winsrv/consrv/console.c @@ -14,7 +14,13 @@ #include +/* This is for COM usage */ +#define COBJMACROS +#include + + #include +#include #include "procinit.h" #define NDEBUG @@ -25,8 +31,9 @@ NTSTATUS NTAPI RtlGetLastNtStatus(VOID); /* GLOBALS ********************************************************************/ +/* The list of the ConSrv consoles */ static ULONG ConsoleListSize; -static PCONSRV_CONSOLE* ConsoleList; /* The list of the ConSrv consoles */ +static PCONSRV_CONSOLE* ConsoleList; static RTL_RESOURCE ListLock; #define ConSrvLockConsoleListExclusive() \ @@ -155,9 +162,8 @@ RemoveConsoleByPointer(IN PCONSRV_CONSOLE Console) } } - /* Unlock the console list */ + /* Unlock the console list and return */ ConSrvUnlockConsoleList(); - return STATUS_SUCCESS; } @@ -187,9 +193,8 @@ ConSrvValidateConsole(OUT PCONSRV_CONSOLE* Console, if (Index >= ConsoleListSize || (ValidatedConsole = ConsoleList[Index]) == NULL) { - /* Unlock the console list */ + /* Unlock the console list and return */ ConSrvUnlockConsoleList(); - return FALSE; } @@ -198,7 +203,7 @@ ConSrvValidateConsole(OUT PCONSRV_CONSOLE* Console, /* Unlock the console list and return */ ConSrvUnlockConsoleList(); - RetVal = ConDrvValidateConsoleUnsafe(ValidatedConsole, + RetVal = ConDrvValidateConsoleUnsafe((PCONSOLE)ValidatedConsole, ExpectedState, LockConsole); if (RetVal) *Console = ValidatedConsole; @@ -209,11 +214,40 @@ ConSrvValidateConsole(OUT PCONSRV_CONSOLE* Console, /* PRIVATE FUNCTIONS **********************************************************/ +// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180 +static BOOLEAN +ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest, + IN PCWSTR Source) +{ + SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR); + if (Size > MAXUSHORT) return FALSE; + + UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size); + if (UniDest->Buffer == NULL) return FALSE; + + RtlCopyMemory(UniDest->Buffer, Source, Size); + UniDest->MaximumLength = (USHORT)Size; + UniDest->Length = (USHORT)Size - sizeof(WCHAR); + + return TRUE; +} + +// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431 +static VOID +ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString) +{ + if (UnicodeString->Buffer) + { + ConsoleFreeHeap(UnicodeString->Buffer); + RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING)); + } +} + VOID ConioPause(PCONSRV_CONSOLE Console, UINT Flags) { Console->PauseFlags |= Flags; - ConDrvPause(Console); + ConDrvPause((PCONSOLE)Console); } VOID @@ -224,7 +258,7 @@ ConioUnpause(PCONSRV_CONSOLE Console, UINT Flags) // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0) if (Console->PauseFlags == 0) { - ConDrvUnpause(Console); + ConDrvUnpause((PCONSOLE)Console); CsrNotifyWait(&Console->WriteWaitQueue, TRUE, @@ -317,10 +351,157 @@ ConSrvInitTerminal(IN OUT PTERMINAL Terminal, NTSTATUS NTAPI ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal); + +static BOOL +LoadShellLinkConsoleInfo(IN OUT PCONSOLE_INFO ConsoleInfo, + IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo) +{ +#define PATH_SEPARATOR L'\\' + + BOOL RetVal = FALSE; + HRESULT hRes = S_OK; + SIZE_T Length = 0; + LPWSTR LinkName = NULL; + LPWSTR IconPath = NULL; + WCHAR Buffer[MAX_PATH + 1]; + + ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0; + + if ((ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) + { + // return FALSE; // FIXME!! (for icon loading) + RetVal = TRUE; + goto Finish; + } + + /* 1- Find the last path separator if any */ + LinkName = wcsrchr(ConsoleInfo->ConsoleTitle, PATH_SEPARATOR); + if (LinkName == NULL) + LinkName = ConsoleInfo->ConsoleTitle; + else + ++LinkName; // Skip the path separator + + /* 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; + + /* 3- It may be a link. Try to retrieve some properties */ + hRes = CoInitialize(NULL); + if (SUCCEEDED(hRes)) + { + /* 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)) + { + /* Get a pointer to the IPersistFile interface */ + IPersistFile* ppf = NULL; + hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf); + if (SUCCEEDED(hRes)) + { + /* Load the shortcut */ + hRes = IPersistFile_Load(ppf, ConsoleInfo->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)) ConsoleInitInfo->ConsoleStartInfo->wShowWindow = (WORD)ShowCmd; + + /* Get the hotkey */ + // hRes = pshl->GetHotkey(&ShowCmd); + // if (SUCCEEDED(hRes)) ConsoleInitInfo->ConsoleStartInfo->HotKey = HotKey; + + /* Get the icon location, if any */ + hRes = IShellLinkW_GetIconLocation(pshl, + Buffer, + sizeof(Buffer)/sizeof(Buffer[0]) - 1, // == MAX_PATH + &ConsoleInitInfo->ConsoleStartInfo->IconIndex); + if (!SUCCEEDED(hRes)) + { + ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0; + } + else + { + IconPath = Buffer; + } + + // 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 = TRUE; // FALSE; + } + IPersistFile_Release(ppf); + } + IShellLinkW_Release(pshl); + } + } + CoUninitialize(); + +Finish: + + if (RetVal) + { + /* Get the associated icon, if any */ + if (IconPath == NULL) + { + // Question: How to retrieve the full path name + // of the app we are going to run?? + Length = RtlDosSearchPath_U(ConsoleInitInfo->CurDir, + ConsoleInitInfo->AppName, + NULL, + sizeof(Buffer), + Buffer, + NULL); + if (Length > 0 && Length < sizeof(Buffer)) + IconPath = Buffer; + else + IconPath = ConsoleInitInfo->AppName; + + // ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0; + } + DPRINT1("IconPath = '%S' ; IconIndex = %lu\n", + IconPath, ConsoleInitInfo->ConsoleStartInfo->IconIndex); + if (IconPath && *IconPath) + { + HICON hIcon = NULL, hIconSm = NULL; + PrivateExtractIconExW(IconPath, + ConsoleInitInfo->ConsoleStartInfo->IconIndex, + &hIcon, + &hIconSm, + 1); + DPRINT1("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm); + if (hIcon != NULL) ConsoleInitInfo->ConsoleStartInfo->hIcon = hIcon; + if (hIconSm != NULL) ConsoleInitInfo->ConsoleStartInfo->hIconSm = hIconSm; + } + } + + // FIXME: See the previous FIXME above. + RetVal = FALSE; + + return RetVal; +} + NTSTATUS NTAPI ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, OUT PCONSRV_CONSOLE* NewConsole, - IN OUT PCONSOLE_START_INFO ConsoleStartInfo, + IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN ULONG ConsoleLeaderProcessId) { NTSTATUS Status; @@ -331,7 +512,7 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, TERMINAL Terminal; /* The ConSrv terminal for this console */ - if (NewConsole == NULL || ConsoleStartInfo == NULL) + if (NewConsole == NULL || ConsoleInitInfo == NULL) return STATUS_INVALID_PARAMETER; *NewConsole = NULL; @@ -344,15 +525,15 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, ConSrvGetDefaultSettings(&ConsoleInfo, ConsoleLeaderProcessId); /* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */ - Length = min(wcslen(ConsoleStartInfo->ConsoleTitle), + Length = min(ConsoleInitInfo->TitleLength, sizeof(ConsoleInfo.ConsoleTitle) / sizeof(ConsoleInfo.ConsoleTitle[0]) - 1); - wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length); - ConsoleInfo.ConsoleTitle[Length] = L'\0'; + wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleInitInfo->ConsoleTitle, Length); + ConsoleInfo.ConsoleTitle[Length] = L'\0'; // NULL-terminate it. /* 3. Initialize the ConSrv terminal */ Status = ConSrvInitTerminal(&Terminal, &ConsoleInfo, - ConsoleStartInfo, + ConsoleInitInfo, ConsoleLeaderProcessId); if (!NT_SUCCESS(Status)) { @@ -361,10 +542,25 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, } DPRINT("CONSRV: Terminal initialized\n"); + /* + * 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 (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) // FIXME!! (for icon loading) + { + if (!LoadShellLinkConsoleInfo(&ConsoleInfo, ConsoleInitInfo)) + { + ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME; + } + } + /* * 4. Load the remaining console settings via the registry. */ - if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) + if ((ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) { /* * Either we weren't created by an app launched via a shell-link, @@ -379,17 +575,17 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, * (and which was transmitted via the ConsoleStartInfo structure). * We therefore overwrite the values read in the registry. */ - if (ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE) + if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE) { - ConsoleInfo.ScreenAttrib = (USHORT)ConsoleStartInfo->wFillAttribute; + ConsoleInfo.ScreenAttrib = (USHORT)ConsoleInitInfo->ConsoleStartInfo->wFillAttribute; } - if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS) + if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS) { - ConsoleInfo.ScreenBufferSize = ConsoleStartInfo->dwScreenBufferSize; + ConsoleInfo.ScreenBufferSize = ConsoleInitInfo->ConsoleStartInfo->dwScreenBufferSize; } - if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE) + if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE) { - ConsoleInfo.ConsoleSize = ConsoleStartInfo->dwWindowSize; + ConsoleInfo.ConsoleSize = ConsoleInitInfo->ConsoleStartInfo->dwWindowSize; } } @@ -410,6 +606,31 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, /*** Register ConSrv features ***/ + /* Initialize the console title */ +#if 0 + WCHAR DefaultTitle[128]; +#endif + ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo.ConsoleTitle); +#if 0 + if (ConsoleInfo.ConsoleTitle[0] == L'\0') + { + if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0]))) + { + ConsoleCreateUnicodeString(&Console->Title, DefaultTitle); + } + else + { + ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console"); + } + } + else + { +#endif + ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo.ConsoleTitle); +#if 0 + } +#endif + /* Initialize process support */ InitializeListHead(&Console->ProcessList); Console->NotifiedLastCloseProcess = NULL; @@ -427,12 +648,25 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, Console->NumberOfHistoryBuffers = ConsoleInfo.NumberOfHistoryBuffers; Console->HistoryNoDup = ConsoleInfo.HistoryNoDup; - Console->QuickEdit = ConsoleInfo.QuickEdit; + /* Initialize the Input Line Discipline */ + Console->LineBuffer = NULL; + Console->LinePos = Console->LineMaxSize = Console->LineSize = 0; + Console->LineComplete = Console->LineUpPressed = FALSE; + // LineWakeupMask + Console->LineInsertToggle = + Console->InsertMode = ConsoleInfo.InsertMode; + Console->QuickEdit = ConsoleInfo.QuickEdit; + + /* Popup windows */ + InitializeListHead(&Console->PopupWindows); /* Colour table */ memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors)); - /* Attach the ConSrv terminal to the console */ + /* + * Attach the ConSrv terminal to the console. + * This call makes a copy of our local Terminal variable. + */ Status = ConDrvRegisterTerminal(Console, &Terminal); if (!NT_SUCCESS(Status)) { @@ -462,12 +696,23 @@ ConSrvDeleteConsole(PCONSRV_CONSOLE Console) /* Remove the console from the list */ RemoveConsoleByPointer(Console); + /* Clean the Input Line Discipline */ + if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer); + /* Clean aliases and history */ IntDeleteAllAliases(Console); HistoryDeleteBuffers(Console); + /* Free the console title */ + ConsoleFreeUnicodeString(&Console->OriginalTitle); + ConsoleFreeUnicodeString(&Console->Title); + /* Now, call the driver. ConDrvDeregisterTerminal is called on-demand. */ - ConDrvDeleteConsole(Console); + ConDrvDeleteConsole((PCONSOLE)Console); + + /* Deinit the ConSrv terminal */ + // FIXME!! + // ConSrvDeinitTerminal(&Terminal); // &ConSrvConsole->Console->TermIFace } @@ -484,7 +729,7 @@ ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent, DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess); - if (ProcessData->CtrlDispatcher) + if (ProcessData->CtrlRoutine) { _SEH2_TRY { @@ -493,7 +738,7 @@ ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent, _SEH2_TRY { Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, - ProcessData->CtrlDispatcher, + ProcessData->CtrlRoutine, UlongToPtr(CtrlEvent), 0, NULL); if (NULL == Thread) { @@ -502,7 +747,8 @@ ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent, } else { - DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); + DPRINT("ProcessData->CtrlRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", + ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); WaitForSingleObject(Thread, Timeout); } } @@ -579,7 +825,7 @@ ConSrvConsoleProcessCtrlEvent(IN PCONSRV_CONSOLE Console, PCONSOLE_PROCESS_DATA current; /* If the console is already being destroyed, just return */ - if (!ConDrvValidateConsoleState(Console, CONSOLE_RUNNING)) + if (!ConDrvValidateConsoleState((PCONSOLE)Console, CONSOLE_RUNNING)) return STATUS_UNSUCCESSFUL; /* @@ -608,9 +854,6 @@ ConSrvConsoleProcessCtrlEvent(IN PCONSRV_CONSOLE Console, } - - - /* PUBLIC SERVER APIS *********************************************************/ CSR_API(SrvAllocConsole) @@ -619,6 +862,7 @@ CSR_API(SrvAllocConsole) PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest; PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process; PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess); + CONSOLE_INIT_INFO ConsoleInitInfo; if (ProcessData->ConsoleHandle != NULL) { @@ -626,33 +870,64 @@ CSR_API(SrvAllocConsole) return STATUS_ACCESS_DENIED; } - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&AllocConsoleRequest->ConsoleStartInfo, - 1, - sizeof(CONSOLE_START_INFO))) + if ( !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&AllocConsoleRequest->ConsoleStartInfo, + 1, + sizeof(CONSOLE_START_INFO)) || + !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&AllocConsoleRequest->ConsoleTitle, + AllocConsoleRequest->TitleLength, + sizeof(BYTE)) || + !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&AllocConsoleRequest->Desktop, + AllocConsoleRequest->DesktopLength, + sizeof(BYTE)) || + !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&AllocConsoleRequest->CurDir, + AllocConsoleRequest->CurDirLength, + sizeof(BYTE)) || + !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&AllocConsoleRequest->AppName, + AllocConsoleRequest->AppNameLength, + sizeof(BYTE)) ) { return STATUS_INVALID_PARAMETER; } + /* Initialize the console initialization info structure */ + ConsoleInitInfo.ConsoleStartInfo = AllocConsoleRequest->ConsoleStartInfo; + ConsoleInitInfo.TitleLength = AllocConsoleRequest->TitleLength; + ConsoleInitInfo.ConsoleTitle = AllocConsoleRequest->ConsoleTitle; + ConsoleInitInfo.DesktopLength = AllocConsoleRequest->DesktopLength; + ConsoleInitInfo.Desktop = AllocConsoleRequest->Desktop; + ConsoleInitInfo.AppNameLength = AllocConsoleRequest->AppNameLength; + ConsoleInitInfo.AppName = AllocConsoleRequest->AppName; + ConsoleInitInfo.CurDirLength = AllocConsoleRequest->CurDirLength; + ConsoleInitInfo.CurDir = AllocConsoleRequest->CurDir; + /* Initialize a new Console owned by the Console Leader Process */ Status = ConSrvAllocateConsole(ProcessData, - &AllocConsoleRequest->InputHandle, - &AllocConsoleRequest->OutputHandle, - &AllocConsoleRequest->ErrorHandle, - AllocConsoleRequest->ConsoleStartInfo); + &AllocConsoleRequest->ConsoleStartInfo->InputHandle, + &AllocConsoleRequest->ConsoleStartInfo->OutputHandle, + &AllocConsoleRequest->ConsoleStartInfo->ErrorHandle, + &ConsoleInitInfo); if (!NT_SUCCESS(Status)) { DPRINT1("Console allocation failed\n"); return Status; } + /* Mark the process as having a console */ + ProcessData->ConsoleApp = TRUE; + CsrProcess->Flags |= CsrProcessIsConsoleApp; + /* Return the console handle and the input wait handle to the caller */ - AllocConsoleRequest->ConsoleHandle = ProcessData->ConsoleHandle; - AllocConsoleRequest->InputWaitHandle = ProcessData->InputWaitHandle; + AllocConsoleRequest->ConsoleStartInfo->ConsoleHandle = ProcessData->ConsoleHandle; + AllocConsoleRequest->ConsoleStartInfo->InputWaitHandle = ProcessData->InputWaitHandle; /* Set the Property-Dialog and Control-Dispatcher handlers */ - ProcessData->PropDispatcher = AllocConsoleRequest->PropDispatcher; - ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher; + ProcessData->PropRoutine = AllocConsoleRequest->PropRoutine; + ProcessData->CtrlRoutine = AllocConsoleRequest->CtrlRoutine; return STATUS_SUCCESS; } @@ -674,6 +949,14 @@ CSR_API(SrvAttachConsole) return STATUS_ACCESS_DENIED; } + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&AttachConsoleRequest->ConsoleStartInfo, + 1, + sizeof(CONSOLE_START_INFO))) + { + return STATUS_INVALID_PARAMETER; + } + /* Check whether we try to attach to the parent's console */ if (ProcessId == ULongToHandle(ATTACH_PARENT_PROCESS)) { @@ -714,22 +997,26 @@ CSR_API(SrvAttachConsole) Status = ConSrvInheritConsole(TargetProcessData, SourceProcessData->ConsoleHandle, TRUE, - &AttachConsoleRequest->InputHandle, - &AttachConsoleRequest->OutputHandle, - &AttachConsoleRequest->ErrorHandle); + &AttachConsoleRequest->ConsoleStartInfo->InputHandle, + &AttachConsoleRequest->ConsoleStartInfo->OutputHandle, + &AttachConsoleRequest->ConsoleStartInfo->ErrorHandle); if (!NT_SUCCESS(Status)) { DPRINT1("Console inheritance failed\n"); goto Quit; } + /* Mark the process as having a console */ + TargetProcessData->ConsoleApp = TRUE; + TargetProcess->Flags |= CsrProcessIsConsoleApp; + /* Return the console handle and the input wait handle to the caller */ - AttachConsoleRequest->ConsoleHandle = TargetProcessData->ConsoleHandle; - AttachConsoleRequest->InputWaitHandle = TargetProcessData->InputWaitHandle; + AttachConsoleRequest->ConsoleStartInfo->ConsoleHandle = TargetProcessData->ConsoleHandle; + AttachConsoleRequest->ConsoleStartInfo->InputWaitHandle = TargetProcessData->InputWaitHandle; /* Set the Property-Dialog and Control-Dispatcher handlers */ - TargetProcessData->PropDispatcher = AttachConsoleRequest->PropDispatcher; - TargetProcessData->CtrlDispatcher = AttachConsoleRequest->CtrlDispatcher; + TargetProcessData->PropRoutine = AttachConsoleRequest->PropRoutine; + TargetProcessData->CtrlRoutine = AttachConsoleRequest->CtrlRoutine; Status = STATUS_SUCCESS; @@ -741,7 +1028,15 @@ Quit: CSR_API(SrvFreeConsole) { + PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process; + PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess); + ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process)); + + /* Mark the process as not having a console anymore */ + ProcessData->ConsoleApp = FALSE; + CsrProcess->Flags &= ~CsrProcessIsConsoleApp; + return STATUS_SUCCESS; } @@ -755,13 +1050,34 @@ CSR_API(SrvGetConsoleMode) PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest; PCONSOLE_IO_OBJECT Object; + PULONG ConsoleMode = &ConsoleModeRequest->Mode; + Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ConsoleModeRequest->Handle, &Object, NULL, GENERIC_READ, TRUE, 0); if (!NT_SUCCESS(Status)) return Status; + /* Get the standard console modes */ Status = ConDrvGetConsoleMode(Object->Console, Object, - &ConsoleModeRequest->Mode); + ConsoleMode); + if (NT_SUCCESS(Status)) + { + /* + * If getting the console modes succeeds, then retrieve + * the extended CONSRV-specific input modes. + */ + if (INPUT_BUFFER == Object->Type) + { + if (Object->Console->InsertMode || Object->Console->QuickEdit) + { + /* Windows also adds ENABLE_EXTENDED_FLAGS, even if it's not documented on MSDN */ + *ConsoleMode |= ENABLE_EXTENDED_FLAGS; + + if (Object->Console->InsertMode) *ConsoleMode |= ENABLE_INSERT_MODE; + if (Object->Console->QuickEdit ) *ConsoleMode |= ENABLE_QUICK_EDIT_MODE; + } + } + } ConSrvReleaseObject(Object, TRUE); return Status; @@ -773,32 +1089,63 @@ ConDrvSetConsoleMode(IN PCONSOLE Console, IN ULONG ConsoleMode); CSR_API(SrvSetConsoleMode) { +#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | \ + ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE ) + NTSTATUS Status; PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest; PCONSOLE_IO_OBJECT Object; + ULONG ConsoleMode = ConsoleModeRequest->Mode; + Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ConsoleModeRequest->Handle, &Object, NULL, GENERIC_WRITE, TRUE, 0); if (!NT_SUCCESS(Status)) return Status; + /* Set the standard console modes (without the CONSRV-specific input modes) */ + ConsoleMode &= ~CONSOLE_VALID_CONTROL_MODES; // Remove CONSRV-specific input modes. Status = ConDrvSetConsoleMode(Object->Console, Object, - ConsoleModeRequest->Mode); + ConsoleMode); + if (NT_SUCCESS(Status)) + { + /* + * If setting the console modes succeeds, then set + * the extended CONSRV-specific input modes. + */ + if (INPUT_BUFFER == Object->Type) + { + ConsoleMode = ConsoleModeRequest->Mode; + + if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) + { + /* + * If we use control mode flags without ENABLE_EXTENDED_FLAGS, + * then consider the flags invalid. + */ + if ((ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + Object->Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE); + Object->Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE); + } + } + } + } ConSrvReleaseObject(Object, TRUE); return Status; } -NTSTATUS NTAPI -ConDrvGetConsoleTitle(IN PCONSOLE Console, - IN BOOLEAN Unicode, - IN OUT PVOID TitleBuffer, - IN OUT PULONG BufLength); CSR_API(SrvGetConsoleTitle) { NTSTATUS Status; PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest; PCONSRV_CONSOLE Console; + ULONG Length; if (!CsrValidateMessageBuffer(ApiMessage, (PVOID)&TitleRequest->Title, @@ -815,26 +1162,52 @@ CSR_API(SrvGetConsoleTitle) return Status; } - Status = ConDrvGetConsoleTitle(Console, - TitleRequest->Unicode, - TitleRequest->Title, - &TitleRequest->Length); + /* Copy title of the console to the user title buffer */ + if (TitleRequest->Unicode) + { + if (TitleRequest->Length >= sizeof(WCHAR)) + { + Length = min(TitleRequest->Length - sizeof(WCHAR), Console->Title.Length); + RtlCopyMemory(TitleRequest->Title, Console->Title.Buffer, Length); + ((PWCHAR)TitleRequest->Title)[Length / sizeof(WCHAR)] = L'\0'; + TitleRequest->Length = Length; + } + else + { + TitleRequest->Length = Console->Title.Length; + } + } + else + { + if (TitleRequest->Length >= sizeof(CHAR)) + { + Length = min(TitleRequest->Length - sizeof(CHAR), Console->Title.Length / sizeof(WCHAR)); + Length = WideCharToMultiByte(Console->InputCodePage, 0, + Console->Title.Buffer, Length, + TitleRequest->Title, Length, + NULL, NULL); + ((PCHAR)TitleRequest->Title)[Length] = '\0'; + TitleRequest->Length = Length; + } + else + { + TitleRequest->Length = Console->Title.Length / sizeof(WCHAR); + } + } ConSrvReleaseConsole(Console, TRUE); return Status; } -NTSTATUS NTAPI -ConDrvSetConsoleTitle(IN PCONSOLE Console, - IN BOOLEAN Unicode, - IN PVOID TitleBuffer, - IN ULONG BufLength); CSR_API(SrvSetConsoleTitle) { NTSTATUS Status; PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest; PCONSRV_CONSOLE Console; + PWCHAR Buffer; + ULONG Length; + if (!CsrValidateMessageBuffer(ApiMessage, (PVOID)&TitleRequest->Title, TitleRequest->Length, @@ -850,12 +1223,56 @@ CSR_API(SrvSetConsoleTitle) return Status; } - Status = ConDrvSetConsoleTitle(Console, - TitleRequest->Unicode, - TitleRequest->Title, - TitleRequest->Length); - if (NT_SUCCESS(Status)) TermChangeTitle(Console); + if (TitleRequest->Unicode) + { + /* Length is in bytes */ + Length = TitleRequest->Length; + } + else + { + /* Use the console input CP for the conversion */ + Length = MultiByteToWideChar(Console->InputCodePage, 0, + TitleRequest->Title, TitleRequest->Length, + NULL, 0); + /* The returned Length was in number of wchars, convert it in bytes */ + Length *= sizeof(WCHAR); + } + /* Allocate a new buffer to hold the new title (NULL-terminated) */ + Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Length + sizeof(WCHAR)); + if (!Buffer) + { + Status = STATUS_NO_MEMORY; + goto Quit; + } + + /* Free the old title */ + ConsoleFreeUnicodeString(&Console->Title); + + /* Copy title to console */ + Console->Title.Buffer = Buffer; + Console->Title.Length = Length; + Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR); + + if (TitleRequest->Unicode) + { + RtlCopyMemory(Console->Title.Buffer, TitleRequest->Title, Console->Title.Length); + } + else + { + MultiByteToWideChar(Console->InputCodePage, 0, + TitleRequest->Title, TitleRequest->Length, + Console->Title.Buffer, + Console->Title.Length / sizeof(WCHAR)); + } + + /* NULL-terminate */ + Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0'; + + TermChangeTitle(Console); + Status = STATUS_SUCCESS; + +Quit: ConSrvReleaseConsole(Console, TRUE); return Status; } diff --git a/reactos/win32ss/user/winsrv/consrv/console.h b/reactos/win32ss/user/winsrv/consrv/console.h index a63754e4cbd..7118dffb327 100644 --- a/reactos/win32ss/user/winsrv/consrv/console.h +++ b/reactos/win32ss/user/winsrv/consrv/console.h @@ -8,27 +8,41 @@ #pragma once +typedef struct _CONSOLE_INIT_INFO +{ + PCONSOLE_START_INFO ConsoleStartInfo; + + ULONG TitleLength; + PWCHAR ConsoleTitle; + ULONG DesktopLength; + PWCHAR Desktop; + ULONG AppNameLength; + PWCHAR AppName; + ULONG CurDirLength; + PWCHAR CurDir; +} CONSOLE_INIT_INFO, *PCONSOLE_INIT_INFO; + VOID NTAPI ConSrvInitConsoleSupport(VOID); NTSTATUS NTAPI ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, - OUT struct _CONSOLE** /* PCONSOLE* */ NewConsole, - IN OUT PCONSOLE_START_INFO ConsoleStartInfo, + OUT struct _CONSRV_CONSOLE** /* PCONSRV_CONSOLE* */ NewConsole, + IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN ULONG ConsoleLeaderProcessId); -VOID NTAPI ConSrvDeleteConsole(struct _CONSOLE* /* PCONSOLE */ Console); +VOID NTAPI ConSrvDeleteConsole(struct _CONSRV_CONSOLE* /* PCONSRV_CONSOLE */ Console); NTSTATUS ConSrvGetConsole(IN PCONSOLE_PROCESS_DATA ProcessData, - OUT struct _CONSOLE** /* PCONSOLE* */ Console, + OUT struct _CONSRV_CONSOLE** /* PCONSRV_CONSOLE* */ Console, IN BOOLEAN LockConsole); VOID -ConSrvReleaseConsole(IN struct _CONSOLE* /* PCONSOLE */ Console, +ConSrvReleaseConsole(IN struct _CONSRV_CONSOLE* /* PCONSRV_CONSOLE */ Console, IN BOOLEAN WasConsoleLocked); BOOLEAN NTAPI -ConSrvValidateConsole(OUT struct _CONSOLE** /* PCONSOLE* */ Console, +ConSrvValidateConsole(OUT struct _CONSRV_CONSOLE** /* PCONSRV_CONSOLE* */ Console, IN HANDLE ConsoleHandle, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole); diff --git a/reactos/win32ss/user/winsrv/consrv/consrv.h b/reactos/win32ss/user/winsrv/consrv/consrv.h index 2c9c1e795f5..09b87fc81f5 100644 --- a/reactos/win32ss/user/winsrv/consrv/consrv.h +++ b/reactos/win32ss/user/winsrv/consrv/consrv.h @@ -51,10 +51,9 @@ typedef struct _CONSOLE_PROCESS_DATA { LIST_ENTRY ConsoleLink; PCSR_PROCESS Process; // Process owning this structure. - HANDLE InputWaitHandle; HANDLE ConsoleHandle; - HANDLE ParentConsoleHandle; + HANDLE InputWaitHandle; BOOLEAN ConsoleApp; // TRUE if it is a CUI app, FALSE otherwise. @@ -62,12 +61,21 @@ typedef struct _CONSOLE_PROCESS_DATA ULONG HandleTableSize; struct _CONSOLE_IO_HANDLE* /* PCONSOLE_IO_HANDLE */ HandleTable; // Length-varying table - LPTHREAD_START_ROUTINE CtrlDispatcher; - LPTHREAD_START_ROUTINE PropDispatcher; // We hold the property dialog handler there, till all the GUI thingie moves out from CSRSS. + LPTHREAD_START_ROUTINE CtrlRoutine; + LPTHREAD_START_ROUTINE PropRoutine; // We hold the property dialog handler there, till all the GUI thingie moves out from CSRSS. + // LPTHREAD_START_ROUTINE ImeRoutine; } CONSOLE_PROCESS_DATA, *PCONSOLE_PROCESS_DATA; + +// Helper for code refactoring +// #define USE_NEW_CONSOLE_WAY + +#ifndef USE_NEW_CONSOLE_WAY #include "include/conio.h" -// #include "include/conio_winsrv.h" +#else +#include "include/conio_winsrv.h" +#endif + #include "include/console.h" #include "include/settings.h" #include "include/term.h" diff --git a/reactos/win32ss/user/winsrv/consrv/frontendctl.c b/reactos/win32ss/user/winsrv/consrv/frontendctl.c index 24bef400a2e..865a98e0317 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontendctl.c +++ b/reactos/win32ss/user/winsrv/consrv/frontendctl.c @@ -143,7 +143,7 @@ CSR_API(SrvSetConsoleDisplayMode) TRUE); if (!NT_SUCCESS(Status)) return Status; - Console = Buff->Header.Console; + Console = (PCONSRV_CONSOLE)Buff->Header.Console; if (TermSetDisplayMode(Console, SetDisplayModeRequest->DisplayMode)) { @@ -163,14 +163,14 @@ CSR_API(SrvGetLargestConsoleWindowSize) { NTSTATUS Status; PCONSOLE_GETLARGESTWINDOWSIZE GetLargestWindowSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetLargestWindowSizeRequest; + PCONSOLE /*PCONSRV_CONSOLE*/ Console; PCONSOLE_SCREEN_BUFFER Buff; - PCONSRV_CONSOLE Console; Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), - GetLargestWindowSizeRequest->OutputHandle, - &Buff, - GENERIC_READ, - TRUE); + GetLargestWindowSizeRequest->OutputHandle, + &Buff, + GENERIC_READ, + TRUE); if (!NT_SUCCESS(Status)) return Status; Console = Buff->Header.Console; @@ -184,7 +184,7 @@ CSR_API(SrvShowConsoleCursor) { NTSTATUS Status; PCONSOLE_SHOWCURSOR ShowCursorRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ShowCursorRequest; - PCONSRV_CONSOLE Console; + PCONSOLE /*PCONSRV_CONSOLE*/ Console; PCONSOLE_SCREEN_BUFFER Buff; Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), @@ -220,7 +220,7 @@ CSR_API(SrvSetConsoleCursor) TRUE); if (!NT_SUCCESS(Status)) return Status; - Console = Buff->Header.Console; + Console = (PCONSRV_CONSOLE)Buff->Header.Console; Success = TermSetMouseCursor(Console, SetCursorRequest->CursorHandle); @@ -242,7 +242,7 @@ CSR_API(SrvConsoleMenuControl) TRUE); if (!NT_SUCCESS(Status)) return Status; - Console = Buff->Header.Console; + Console = (PCONSRV_CONSOLE)Buff->Header.Console; MenuControlRequest->MenuHandle = TermMenuControl(Console, MenuControlRequest->CmdIdLow, @@ -275,7 +275,8 @@ CSR_API(SrvGetConsoleWindow) PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest; PCONSRV_CONSOLE Console; - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; GetWindowRequest->WindowHandle = TermGetConsoleWindowHandle(Console); @@ -290,7 +291,8 @@ CSR_API(SrvSetConsoleIcon) PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest; PCONSRV_CONSOLE Console; - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = (TermChangeIcon(Console, SetIconRequest->IconHandle) @@ -307,7 +309,8 @@ CSR_API(SrvGetConsoleSelectionInfo) PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest; PCONSRV_CONSOLE Console; - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = (TermGetSelectionInfo(Console, &GetSelectionInfoRequest->Info) diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c index 84de1871b20..4a5102f2584 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c @@ -539,10 +539,15 @@ InitFonts(PGUI_CONSOLE_DATA GuiData, TEXTMETRICW Metrics; SIZE CharSize; + hDC = GetDC(GuiData->hWindow); + /* * Initialize a new NORMAL font and get its metrics. */ + FontSize.Y = FontSize.Y > 0 ? -MulDiv(FontSize.Y, GetDeviceCaps(hDC, LOGPIXELSY), 72) + : FontSize.Y; + NewFont = CreateFontW(FontSize.Y, FontSize.X, 0, @@ -554,20 +559,13 @@ InitFonts(PGUI_CONSOLE_DATA GuiData, OEM_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, - DEFAULT_QUALITY, // NONANTIALIASED_QUALITY ; ANTIALIASED_QUALITY + DEFAULT_QUALITY, FIXED_PITCH | FontFamily, FaceName); if (NewFont == NULL) { DPRINT1("InitFonts: CreateFontW failed\n"); - return FALSE; - } - - hDC = GetDC(GuiData->hWindow); - if (hDC == NULL) - { - DPRINT1("InitFonts: GetDC failed\n"); - DeleteObject(NewFont); + ReleaseDC(GuiData->hWindow, hDC); return FALSE; } @@ -591,7 +589,7 @@ InitFonts(PGUI_CONSOLE_DATA GuiData, GuiData->CharWidth = Metrics.tmMaxCharWidth; GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading; - /* Measure real char width more precisely if possible. */ + /* Measure real char width more precisely if possible */ if (GetTextExtentPoint32W(hDC, L"R", 1, &CharSize)) GuiData->CharWidth = CharSize.cx; @@ -2437,7 +2435,7 @@ ConWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) } case PM_CONSOLE_BEEP: - DPRINT1("Beep !!\n"); + DPRINT1("Beep\n"); Beep(800, 200); break; diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.h b/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.h index dee5c3254c2..456501b031c 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.h +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.h @@ -38,6 +38,7 @@ typedef struct _GUI_CONSOLE_DATA CRITICAL_SECTION Lock; BOOL WindowSizeLock; HANDLE hGuiInitEvent; + HANDLE hGuiTermEvent; POINT OldCursor; diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c index 12dce743a21..f7d67ef9cfc 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c @@ -296,7 +296,7 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup; pSharedInfo->ci.QuickEdit = Console->QuickEdit; pSharedInfo->ci.InsertMode = Console->InsertMode; - pSharedInfo->ci.InputBufferSize = 0; + /////////////pSharedInfo->ci.InputBufferSize = 0; pSharedInfo->ci.ScreenBufferSize = ActiveBuffer->ScreenBufferSize; pSharedInfo->ci.ConsoleSize = ActiveBuffer->ViewSize; pSharedInfo->ci.CursorBlinkOn; @@ -372,7 +372,7 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, } /* Start the properties dialog */ - if (ProcessData->PropDispatcher) + if (ProcessData->PropRoutine) { _SEH2_TRY { @@ -381,7 +381,7 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, _SEH2_TRY { Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, - ProcessData->PropDispatcher, + ProcessData->PropRoutine, (PVOID)hClientSection, 0, NULL); if (NULL == Thread) { @@ -389,7 +389,8 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, } else { - DPRINT("ProcessData->PropDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); + DPRINT("ProcessData->PropRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", + ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); /// WaitForSingleObject(Thread, INFINITE); } } @@ -643,7 +644,6 @@ GuiApplyWindowsConsoleSettings(PGUI_CONSOLE_DATA GuiData, Console->OriginalTitle.Length / sizeof(WCHAR)); wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length); #endif - // ULONG ConInfo.InputBufferSize = pConInfo-> // BOOLEAN ConInfo.CursorBlinkOn = pConInfo-> // BOOLEAN ConInfo.ForceCursorOff = pConInfo-> diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h index 593c14e5e2d..792fe1db81c 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h @@ -76,7 +76,7 @@ typedef struct _CONSOLE_STATE_INFO COLORREF ColorTable[16]; ULONG CodePage; - HWND HWnd; + HWND hWnd; WCHAR ConsoleTitle[256]; } CONSOLE_STATE_INFO, *PCONSOLE_STATE_INFO; diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c index 730d9a30c87..530b9ac7469 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c @@ -13,9 +13,6 @@ #include -#define COBJMACROS -#include - #define NDEBUG #include @@ -45,7 +42,8 @@ typedef struct _GUI_INIT_INFO } GUI_INIT_INFO, *PGUI_INIT_INFO; static BOOL ConsInitialized = FALSE; -static HWND NotifyWnd = NULL; +static HANDLE hInputThread = NULL; +static DWORD dwInputThreadId = 0; extern HICON ghDefaultIcon; extern HICON ghDefaultIconSm; @@ -142,48 +140,59 @@ VOID SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen); VOID CreateSysMenu(HWND hWnd); -static LRESULT CALLBACK -GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + +static DWORD NTAPI +GuiConsoleInputThread(PVOID Data) { - HWND NewWindow; - LONG WindowCount; - MSG Msg; + PHANDLE GraphicsStartupEvent = (PHANDLE)Data; + LONG WindowCount = 0; + MSG msg; - switch (msg) + /* + * This thread dispatches all the console notifications to the notify window. + * It is common for all the console windows. + */ + + /* The thread has been initialized, set the event */ + SetEvent(*GraphicsStartupEvent); + + while (GetMessageW(&msg, NULL, 0, 0)) { - case WM_CREATE: + switch (msg.message) { - SetWindowLongW(hWnd, GWL_USERDATA, 0); - return 0; - } - - case PM_CREATE_CONSOLE: - { - 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"); + + PrivateCsrssManualGuiCheck(-1); // co_AddGuiApp + + 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 (NewWindow == NULL) + { + DPRINT1("Failed to create a new console window\n"); + PrivateCsrssManualGuiCheck(+1); // RemoveGuiApp + 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() @@ -208,99 +217,60 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE); DPRINT("PM_CREATE_CONSOLE -- showing window\n"); - // ShowWindow(NewWindow, (int)wParam); - ShowWindowAsync(NewWindow, (int)wParam); + // ShowWindow(NewWindow, (int)GuiData->GuiInfo.ShowWindow); + ShowWindowAsync(NewWindow, (int)GuiData->GuiInfo.ShowWindow); 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; - if (GuiData->hWindow != NULL) /* && DestroyWindow(GuiData->hWindow) */ - { - DestroyWindow(GuiData->hWindow); + /* Exit the full screen mode if it was already set */ + // LeaveFullScreen(GuiData); - WindowCount = GetWindowLongW(hWnd, GWL_USERDATA); - WindowCount--; - SetWindowLongW(hWnd, GWL_USERDATA, WindowCount); - if (0 == WindowCount) + /* + * 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)) { - NotifyWnd = NULL; - DestroyWindow(hWnd); - DPRINT("CONSRV: Going to quit the Gui Thread!!\n"); - PostQuitMessage(0); - } - } + TranslateMessage(&TempMsg); + DispatchMessageW(&TempMsg); + }*/ + while (PeekMessageW(&TempMsg, NULL, 0, 0, PM_REMOVE)) ; - return 0; + if (GuiData->hWindow == NULL) continue; + + DestroyWindow(GuiData->hWindow); + PrivateCsrssManualGuiCheck(+1); // RemoveGuiApp + + SetEvent(GuiData->hGuiTermEvent); + + if (InterlockedDecrement(&WindowCount) == 0) + { + DPRINT("CONSRV: Going to quit the Input Thread!!\n"); + goto Quit; + } + + continue; + } } - default: - return DefWindowProcW(hWnd, msg, wParam, lParam); - } -} - -static DWORD NTAPI -GuiConsoleGuiThread(PVOID Data) -{ - MSG msg; - PHANDLE GraphicsStartupEvent = (PHANDLE)Data; - - /* - * This thread dispatches all the console notifications to the notify window. - * It is common for all the console windows. - */ - - PrivateCsrssManualGuiCheck(+1); - - NotifyWnd = CreateWindowW(L"ConSrvCreateNotify", - L"", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - NULL, - NULL, - ConSrvDllInstance, - NULL); - if (NULL == NotifyWnd) - { - PrivateCsrssManualGuiCheck(-1); - SetEvent(*GraphicsStartupEvent); - return 1; - } - - SetEvent(*GraphicsStartupEvent); - - while (GetMessageW(&msg, NULL, 0, 0)) - { TranslateMessage(&msg); DispatchMessageW(&msg); } - DPRINT("CONSRV: Quit the Gui Thread!!\n"); - PrivateCsrssManualGuiCheck(-1); +Quit: + DPRINT("CONSRV: Quit the Input Thread!!\n"); + + hInputThread = NULL; + dwInputThreadId = 0; return 1; } @@ -308,76 +278,43 @@ GuiConsoleGuiThread(PVOID Data) static BOOL GuiInit(VOID) { - WNDCLASSEXW wc; - /* Exit if we were already initialized */ // if (ConsInitialized) return TRUE; /* - * Initialize and register the different window classes, if needed. + * Initialize and register the console window class, if needed. */ if (!ConsInitialized) { - /* 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; - } - - /* Initialize the console window class */ - if (!RegisterConWndClass(ConSrvDllInstance)) - return FALSE; - + if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE; ConsInitialized = TRUE; } /* - * Set-up the notification window + * Set-up the console input thread */ - if (NULL == NotifyWnd) + if (hInputThread == NULL) { - HANDLE ThreadHandle; - HANDLE GraphicsStartupEvent; + HANDLE GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (GraphicsStartupEvent == NULL) return FALSE; - GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if (NULL == GraphicsStartupEvent) return FALSE; - - ThreadHandle = CreateThread(NULL, + hInputThread = CreateThread(NULL, 0, - GuiConsoleGuiThread, + GuiConsoleInputThread, (PVOID)&GraphicsStartupEvent, 0, - NULL); - if (NULL == ThreadHandle) + &dwInputThreadId); + if (hInputThread == NULL) { CloseHandle(GraphicsStartupEvent); - DPRINT1("CONSRV: Failed to create graphics console thread. Expect problems\n"); + DPRINT1("CONSRV: Failed to create graphics console thread.\n"); return FALSE; } - SetThreadPriority(ThreadHandle, THREAD_PRIORITY_HIGHEST); - CloseHandle(ThreadHandle); + SetThreadPriority(hInputThread, THREAD_PRIORITY_HIGHEST); + CloseHandle(hInputThread); WaitForSingleObject(GraphicsStartupEvent, INFINITE); CloseHandle(GraphicsStartupEvent); - - if (NULL == NotifyWnd) - { - DPRINT1("CONSRV: Failed to create notification window.\n"); - return FALSE; - } } // ConsInitialized = TRUE; @@ -386,7 +323,6 @@ GuiInit(VOID) } - /****************************************************************************** * GUI Console Driver * ******************************************************************************/ @@ -405,9 +341,7 @@ GuiInitFrontEnd(IN OUT PFRONTEND This, PGUI_CONSOLE_DATA GuiData; GUI_CONSOLE_INFO TermInfo; - SIZE_T Length = 0; - LPWSTR IconPath = NULL; - INT IconIndex = 0; + SIZE_T Length = 0; if (This == NULL || Console == NULL || This->OldData == NULL) return STATUS_INVALID_PARAMETER; @@ -422,10 +356,6 @@ GuiInitFrontEnd(IN OUT PFRONTEND This, ConsoleInfo = GuiInitInfo->ConsoleInfo; ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo; - IconPath = ConsoleStartInfo->IconPath; - IconIndex = ConsoleStartInfo->IconIndex; - - /* Terminal data allocation */ GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA)); if (!GuiData) @@ -451,10 +381,10 @@ GuiInitFrontEnd(IN OUT PFRONTEND This, /* 1. Load the default settings */ GuiConsoleGetDefaultSettings(&TermInfo, GuiInitInfo->ProcessId); - /* 3. Load the remaining console settings via the registry. */ + /* 3. Load the remaining console settings via the registry */ if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) { - /* Load the terminal infos from the registry. */ + /* Load the terminal infos from the registry */ GuiConsoleReadUserSettings(&TermInfo, ConsoleInfo->ConsoleTitle, GuiInitInfo->ProcessId); @@ -500,29 +430,17 @@ GuiInitFrontEnd(IN OUT PFRONTEND This, GuiData->GuiInfo.AutoPosition = TermInfo.AutoPosition; GuiData->GuiInfo.WindowOrigin = TermInfo.WindowOrigin; - /* Initialize the icon handles to their default values */ - GuiData->hIcon = ghDefaultIcon; - GuiData->hIconSm = ghDefaultIconSm; + /* Initialize the icon handles */ + if (ConsoleStartInfo->hIcon != NULL) + GuiData->hIcon = ConsoleStartInfo->hIcon; + else + GuiData->hIcon = ghDefaultIcon; + + if (ConsoleStartInfo->hIconSm != NULL) + GuiData->hIconSm = ConsoleStartInfo->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 */ @@ -545,6 +463,11 @@ GuiInitFrontEnd(IN OUT PFRONTEND This, GuiData->LineSelection = FALSE; // Default to block selection // TODO: Retrieve the selection mode via the registry. + /* Finally, finish to initialize the frontend structure */ + This->Data = GuiData; + if (This->OldData) ConsoleFreeHeap(This->OldData); + This->OldData = NULL; + /* * We need to wait until the GUI has been fully initialized * to retrieve custom settings i.e. WindowSize etc... @@ -552,11 +475,12 @@ GuiInitFrontEnd(IN OUT PFRONTEND This, * yet implemented. */ GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + GuiData->hGuiTermEvent = CreateEventW(NULL, FALSE, FALSE, NULL); DPRINT("GUI - Checkpoint\n"); /* Create the terminal window */ - PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, GuiData->GuiInfo.ShowWindow, (LPARAM)GuiData); + PostThreadMessageW(dwInputThreadId, PM_CREATE_CONSOLE, 0, (LPARAM)GuiData); /* Wait until initialization has finished */ WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE); @@ -572,11 +496,6 @@ GuiInitFrontEnd(IN OUT PFRONTEND This, 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; } @@ -585,7 +504,12 @@ GuiDeinitFrontEnd(IN OUT PFRONTEND This) { PGUI_CONSOLE_DATA GuiData = This->Data; - SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData); + DPRINT("Send PM_DESTROY_CONSOLE message and wait on hGuiTermEvent...\n"); + PostThreadMessageW(dwInputThreadId, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData); + WaitForSingleObject(GuiData->hGuiTermEvent, INFINITE); + DPRINT("hGuiTermEvent set\n"); + CloseHandle(GuiData->hGuiTermEvent); + GuiData->hGuiTermEvent = NULL; DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n", GuiData->hIcon, ghDefaultIcon, GuiData->hIconSm, ghDefaultIconSm); @@ -675,6 +599,15 @@ GuiWriteStream(IN OUT PFRONTEND This, SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL); } +/* static */ VOID NTAPI +GuiRingBell(IN OUT PFRONTEND This) +{ + PGUI_CONSOLE_DATA GuiData = This->Data; + + /* Emit an error beep sound */ + SendNotifyMessage(GuiData->hWindow, PM_CONSOLE_BEEP, 0, 0); +} + static BOOL NTAPI GuiSetCursorInfo(IN OUT PFRONTEND This, PCONSOLE_SCREEN_BUFFER Buff) @@ -1083,6 +1016,7 @@ static FRONTEND_VTBL GuiVtbl = GuiDeinitFrontEnd, GuiDrawRegion, GuiWriteStream, + GuiRingBell, GuiSetCursorInfo, GuiSetScreenInfo, GuiResizeTerminal, @@ -1104,139 +1038,21 @@ static FRONTEND_VTBL GuiVtbl = }; -static BOOL -LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo, - IN OUT PCONSOLE_INFO ConsoleInfo) -{ -#define PATH_SEPARATOR L'\\' - - BOOL RetVal = FALSE; - HRESULT hRes = S_OK; - LPWSTR LinkName = NULL; - SIZE_T Length = 0; - - if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) - return FALSE; - - ConsoleStartInfo->IconPath[0] = L'\0'; - ConsoleStartInfo->IconIndex = 0; - - /* 1- Find the last path separator if any */ - LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR); - if (LinkName == NULL) - { - LinkName = ConsoleStartInfo->ConsoleTitle; - } - else - { - /* Skip the path separator */ - ++LinkName; - } - - /* 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; - - /* 3- It may be a link. Try to retrieve some properties */ - hRes = CoInitialize(NULL); - if (SUCCEEDED(hRes)) - { - /* 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)) - { - /* Get a pointer to the IPersistFile interface */ - IPersistFile* ppf = NULL; - hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf); - if (SUCCEEDED(hRes)) - { - /* 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); - } - IShellLinkW_Release(pshl); - } - } - CoUninitialize(); - - return RetVal; -} - NTSTATUS NTAPI GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, IN OUT PCONSOLE_INFO ConsoleInfo, IN OUT PVOID ExtraConsoleInfo, IN ULONG ProcessId) { - PCONSOLE_START_INFO ConsoleStartInfo = ExtraConsoleInfo; + PCONSOLE_INIT_INFO ConsoleInitInfo = ExtraConsoleInfo; PGUI_INIT_INFO GuiInitInfo; - if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleStartInfo == NULL) + if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL) return STATUS_INVALID_PARAMETER; /* Initialize GUI terminal emulator common functionalities */ if (!GuiInit()) return STATUS_UNSUCCESSFUL; - /* - * 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; - } - } - /* * Initialize a private initialization info structure for later use. * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd. @@ -1245,8 +1061,9 @@ GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, if (GuiInitInfo == NULL) return STATUS_NO_MEMORY; // HACK: We suppose that the pointers will be valid in GuiInitFrontEnd... + // If not, then copy exactly what we need in GuiInitInfo. GuiInitInfo->ConsoleInfo = ConsoleInfo; - GuiInitInfo->ConsoleStartInfo = ConsoleStartInfo; + GuiInitInfo->ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo; GuiInitInfo->ProcessId = ProcessId; /* Finally, initialize the frontend structure */ diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h index 8755cdd9f24..3b252afdb37 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.h @@ -14,13 +14,6 @@ #include "guisettings.h" #include "conwnd.h" -NTSTATUS GuiInitConsole(PCONSOLE Console, - /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo, - PCONSOLE_INFO ConsoleInfo, - DWORD ProcessId, - LPCWSTR IconPath, - INT IconIndex); - VOID GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData); diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/lang/en-US.rc b/reactos/win32ss/user/winsrv/consrv/frontends/gui/lang/en-US.rc index 1a32b4882e7..9177466e193 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/lang/en-US.rc +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/lang/en-US.rc @@ -2,15 +2,15 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US STRINGTABLE BEGIN - IDS_EDIT "Edit" + IDS_EDIT "&Edit" IDS_MARK "Mark" IDS_COPY "Copy\tEnter" IDS_PASTE "Paste" IDS_SELECTALL "Select All" IDS_SCROLL "Scroll" IDS_FIND "Find..." - IDS_DEFAULTS "Defaults" - IDS_PROPERTIES "Properties" + IDS_DEFAULTS "&Defaults" + IDS_PROPERTIES "&Properties" /* IDS_SCROLLHERE "Scroll here" IDS_SCROLLTOP "Scroll top" diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/lang/fr-FR.rc b/reactos/win32ss/user/winsrv/consrv/frontends/gui/lang/fr-FR.rc index 0dde5099530..2c8955fc4ea 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/lang/fr-FR.rc +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/lang/fr-FR.rc @@ -1,18 +1,16 @@ LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL -/* Fixme : Translation could be really improved, with context - La traduction pourrait réellement être améliorée grâce au contexte */ STRINGTABLE BEGIN - IDS_EDIT "Éditer" - IDS_MARK "Marquer" - IDS_COPY "Copier\tEntrée" - IDS_PASTE "Coller" - IDS_SELECTALL "Tout sélectionner" - IDS_SCROLL "Défiler" - IDS_FIND "Trouver..." - IDS_DEFAULTS "Défauts" - IDS_PROPERTIES "Propriétés" + IDS_EDIT "Éd&ition" + IDS_MARK "&Marquer" + IDS_COPY "&Copier\tEntrée" + IDS_PASTE "C&oller" + IDS_SELECTALL "Sélectionner &tout" + IDS_SCROLL "&Défiler" + IDS_FIND "&Rechercher..." + IDS_DEFAULTS "&Défauts" + IDS_PROPERTIES "&Propriétés" /* IDS_SCROLLHERE "Défiler ici" IDS_SCROLLTOP "Défiler tout en haut" diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/input.c b/reactos/win32ss/user/winsrv/consrv/frontends/input.c index b2c17042eb1..33d420b6a8f 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/input.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/input.c @@ -10,7 +10,6 @@ /* INCLUDES *******************************************************************/ #include "consrv.h" -#include "include/conio.h" #include "include/term.h" #include "coninput.h" @@ -20,77 +19,6 @@ /* PRIVATE FUNCTIONS **********************************************************/ -static VOID -ConDrvProcessKey(IN PCONSOLE Console, - IN BOOLEAN Down, - IN UINT VirtualKeyCode, - IN UINT VirtualScanCode, - IN WCHAR UnicodeChar, - IN ULONG ShiftState, - IN BYTE KeyStateCtrl) -{ - INPUT_RECORD er; - - /* process Ctrl-C and Ctrl-Break */ - if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && - Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') && - (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyStateCtrl & 0x80) ) - { - DPRINT1("Console_Api Ctrl-C\n"); - ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT); - - if (Console->LineBuffer && !Console->LineComplete) - { - /* Line input is in progress; end it */ - Console->LinePos = Console->LineSize = 0; - Console->LineComplete = TRUE; - } - return; - } - - if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 && - (VK_UP == VirtualKeyCode || VK_DOWN == VirtualKeyCode) ) - { - if (!Down) return; - - /* scroll up or down */ - if (VK_UP == VirtualKeyCode) - { - /* only scroll up if there is room to scroll up into */ - if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1) - { - Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + - Console->ActiveBuffer->ScreenBufferSize.Y - 1) % - Console->ActiveBuffer->ScreenBufferSize.Y; - Console->ActiveBuffer->CursorPosition.Y++; - } - } - else - { - /* only scroll down if there is room to scroll down into */ - if (Console->ActiveBuffer->CursorPosition.Y != 0) - { - Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) % - Console->ActiveBuffer->ScreenBufferSize.Y; - Console->ActiveBuffer->CursorPosition.Y--; - } - } - - ConioDrawConsole(Console); - return; - } - - er.EventType = KEY_EVENT; - er.Event.KeyEvent.bKeyDown = Down; - er.Event.KeyEvent.wRepeatCount = 1; - er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode; - er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode; - er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar; - er.Event.KeyEvent.dwControlKeyState = ShiftState; - - ConioProcessInputEvent(Console, &er); -} - static DWORD ConioGetShiftState(PBYTE KeyState, LPARAM lParam) { @@ -138,8 +66,10 @@ ConioProcessKey(PCONSRV_CONSOLE Console, MSG* msg) UINT VirtualKeyCode; UINT VirtualScanCode; BOOL Down = FALSE; - BOOLEAN Fake; // synthesized, not a real event - BOOLEAN NotChar; // message should not be used to return a character + BOOLEAN Fake; // Synthesized, not a real event + BOOLEAN NotChar; // Message should not be used to return a character + + INPUT_RECORD er; if (NULL == Console) { @@ -172,7 +102,7 @@ ConioProcessKey(PCONSRV_CONSOLE Console, MSG* msg) 2, 0, NULL); - UnicodeChar = (1 == RetChars ? Chars[0] : 0); + UnicodeChar = (RetChars == 1 ? Chars[0] : 0); } Fake = UnicodeChar && @@ -194,14 +124,66 @@ ConioProcessKey(PCONSRV_CONSOLE Console, MSG* msg) if (Fake) return; + /* Process Ctrl-C and Ctrl-Break */ + if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && + Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') && + (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80) ) + { + DPRINT1("Console_Api Ctrl-C\n"); + ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT); + + if (Console->LineBuffer && !Console->LineComplete) + { + /* Line input is in progress; end it */ + Console->LinePos = Console->LineSize = 0; + Console->LineComplete = TRUE; + } + return; + } + + if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 && + (VirtualKeyCode == VK_UP || VirtualKeyCode == VK_DOWN) ) + { + if (!Down) return; + + /* Scroll up or down */ + if (VirtualKeyCode == VK_UP) + { + /* Only scroll up if there is room to scroll up into */ + if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1) + { + Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + + Console->ActiveBuffer->ScreenBufferSize.Y - 1) % + Console->ActiveBuffer->ScreenBufferSize.Y; + Console->ActiveBuffer->CursorPosition.Y++; + } + } + else + { + /* Only scroll down if there is room to scroll down into */ + if (Console->ActiveBuffer->CursorPosition.Y != 0) + { + Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) % + Console->ActiveBuffer->ScreenBufferSize.Y; + Console->ActiveBuffer->CursorPosition.Y--; + } + } + + ConioDrawConsole((PCONSOLE)Console); + return; + } + /* Send the key press to the console driver */ - ConDrvProcessKey(Console, - Down, - VirtualKeyCode, - VirtualScanCode, - UnicodeChar, - ShiftState, - KeyState[VK_CONTROL]); + + er.EventType = KEY_EVENT; + er.Event.KeyEvent.bKeyDown = Down; + er.Event.KeyEvent.wRepeatCount = 1; + er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode; + er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode; + er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar; + er.Event.KeyEvent.dwControlKeyState = ShiftState; + + ConioProcessInputEvent(Console, &er); } DWORD diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c b/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c index b2ba1a95885..668b4d6b3e6 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c @@ -18,6 +18,76 @@ #define NDEBUG #include + + + + +/********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/ + +/* GLOBALS ********************************************************************/ + +/* + * From MSDN: + * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. + * If they are the same, the function fails, and GetLastError returns + * ERROR_INVALID_PARAMETER." + */ +#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \ + ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ + WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) + +#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \ + ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ + MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1) + +typedef struct ConsoleInput_t +{ + LIST_ENTRY ListEntry; + INPUT_RECORD InputEvent; +} ConsoleInput; + + +/* PRIVATE FUNCTIONS **********************************************************/ + +#if 0 + +static VOID +ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent) +{ + if (InputEvent->EventType == KEY_EVENT) + { + WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar; + InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0; + ConsoleInputUnicodeCharToAnsiChar(Console, + &InputEvent->Event.KeyEvent.uChar.AsciiChar, + &UnicodeChar); + } +} + +static VOID +ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent) +{ + if (InputEvent->EventType == KEY_EVENT) + { + CHAR AsciiChar = InputEvent->Event.KeyEvent.uChar.AsciiChar; + InputEvent->Event.KeyEvent.uChar.AsciiChar = 0; + ConsoleInputAnsiCharToUnicodeChar(Console, + &InputEvent->Event.KeyEvent.uChar.UnicodeChar, + &AsciiChar); + } +} + +#endif + +/********** HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ************/ + + + + + + + + /* CONSRV TERMINAL FRONTENDS INTERFACE ****************************************/ /***************/ @@ -67,7 +137,7 @@ NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd); * NOTE: Each entry of the table should be retrieved when loading a front-end * (examples of the CSR servers which register some data for CSRSS). */ -struct +static struct { CHAR FrontEndName[80]; FRONTEND_LOAD FrontEndLoad; @@ -190,7 +260,7 @@ ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal) static NTSTATUS NTAPI ConSrvTermInitTerminal(IN OUT PTERMINAL This, - IN PCONSOLE Console) + IN PCONSOLE Console) { NTSTATUS Status; PFRONTEND FrontEnd = This->Data; @@ -203,6 +273,8 @@ ConSrvTermInitTerminal(IN OUT PTERMINAL This, Console->FrontEndIFace = *FrontEnd; Status = FrontEnd->Vtbl->InitFrontEnd(FrontEnd, FrontEnd->Console); + if (!NT_SUCCESS(Status)) + DPRINT1("InitFrontEnd failed, Status = 0x%08lx\n", Status); /** HACK HACK!! Be sure FrontEndIFace is correctly updated in the console!! **/ DPRINT1("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n"); @@ -218,6 +290,364 @@ ConSrvTermDeinitTerminal(IN OUT PTERMINAL This) FrontEnd->Vtbl->DeinitFrontEnd(FrontEnd); } + + +/************ Line discipline ***************/ + +static NTSTATUS NTAPI +ConSrvTermReadStream(IN OUT PTERMINAL This, + /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/ + IN BOOLEAN Unicode, + /**PWCHAR Buffer,**/ + OUT PVOID Buffer, + IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, + IN ULONG NumCharsToRead, + OUT PULONG NumCharsRead OPTIONAL) +{ + PFRONTEND FrontEnd = This->Data; + PCONSRV_CONSOLE Console = FrontEnd->Console; + PCONSOLE_INPUT_BUFFER InputBuffer = &Console->InputBuffer; + + // STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait. + NTSTATUS Status = STATUS_PENDING; + + PLIST_ENTRY CurrentEntry; + ConsoleInput *Input; + ULONG i; + + /* Validity checks */ + // ASSERT(Console == InputBuffer->Header.Console); + ASSERT((Buffer != NULL) || (Buffer == NULL && NumCharsToRead == 0)); + + /* We haven't read anything (yet) */ + i = ReadControl->nInitialChars; + + if (InputBuffer->Mode & ENABLE_LINE_INPUT) + { + /* COOKED mode, call the line discipline */ + + if (Console->LineBuffer == NULL) + { + /* Starting a new line */ + Console->LineMaxSize = max(256, NumCharsToRead); + + Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR)); + if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY; + + Console->LinePos = Console->LineSize = ReadControl->nInitialChars; + Console->LineComplete = Console->LineUpPressed = FALSE; + Console->LineInsertToggle = Console->InsertMode; + Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask; + + /* + * Pre-filling the buffer is only allowed in the Unicode API, + * so we don't need to worry about ANSI <-> Unicode conversion. + */ + memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR)); + if (Console->LineSize == Console->LineMaxSize) + { + Console->LineComplete = TRUE; + Console->LinePos = 0; + } + } + + /* If we don't have a complete line yet, process the pending input */ + while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents)) + { + /* Remove input event from queue */ + CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); + if (IsListEmpty(&InputBuffer->InputEvents)) + { + ResetEvent(InputBuffer->ActiveEvent); + } + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + + /* Only pay attention to key down */ + if (Input->InputEvent.EventType == KEY_EVENT && + Input->InputEvent.Event.KeyEvent.bKeyDown) + { + LineInputKeyDown(Console, ExeName, + &Input->InputEvent.Event.KeyEvent); + ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; + } + ConsoleFreeHeap(Input); + } + + /* Check if we have a complete line to read from */ + if (Console->LineComplete) + { + while (i < NumCharsToRead && Console->LinePos != Console->LineSize) + { + WCHAR Char = Console->LineBuffer[Console->LinePos++]; + + if (Unicode) + { + ((PWCHAR)Buffer)[i] = Char; + } + else + { + ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); + } + ++i; + } + + if (Console->LinePos == Console->LineSize) + { + /* Entire line has been read */ + ConsoleFreeHeap(Console->LineBuffer); + Console->LineBuffer = NULL; + } + + Status = STATUS_SUCCESS; + } + } + else + { + /* RAW mode */ + + /* Character input */ + while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents)) + { + /* Remove input event from queue */ + CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents); + if (IsListEmpty(&InputBuffer->InputEvents)) + { + ResetEvent(InputBuffer->ActiveEvent); + } + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + + /* Only pay attention to valid characters, on key down */ + if (Input->InputEvent.EventType == KEY_EVENT && + Input->InputEvent.Event.KeyEvent.bKeyDown && + Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0') + { + WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar; + + if (Unicode) + { + ((PWCHAR)Buffer)[i] = Char; + } + else + { + ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char); + } + ++i; + + /* Did read something */ + Status = STATUS_SUCCESS; + } + ConsoleFreeHeap(Input); + } + } + + // FIXME: Only set if Status == STATUS_SUCCESS ??? + if (NumCharsRead) *NumCharsRead = i; + + return Status; +} + + + + +/* GLOBALS ********************************************************************/ + +#define TAB_WIDTH 8 + +// See condrv/text.c +/*static*/ VOID +ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff); + +static VOID +ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff, PSMALL_RECT UpdateRect, PUINT ScrolledLines) +{ + /* If we hit bottom, slide the viewable screen */ + if (++Buff->CursorPosition.Y == Buff->ScreenBufferSize.Y) + { + Buff->CursorPosition.Y--; + if (++Buff->VirtualY == Buff->ScreenBufferSize.Y) + { + Buff->VirtualY = 0; + } + (*ScrolledLines)++; + ClearLineBuffer(Buff); + if (UpdateRect->Top != 0) + { + UpdateRect->Top--; + } + } + UpdateRect->Left = 0; + UpdateRect->Right = Buff->ScreenBufferSize.X - 1; + UpdateRect->Bottom = Buff->CursorPosition.Y; +} + +static NTSTATUS +ConioWriteConsole(PFRONTEND FrontEnd, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib) +{ + PCONSRV_CONSOLE Console = FrontEnd->Console; + + UINT i; + PCHAR_INFO Ptr; + SMALL_RECT UpdateRect; + SHORT CursorStartX, CursorStartY; + UINT ScrolledLines; + + CursorStartX = Buff->CursorPosition.X; + CursorStartY = Buff->CursorPosition.Y; + UpdateRect.Left = Buff->ScreenBufferSize.X; + UpdateRect.Top = Buff->CursorPosition.Y; + UpdateRect.Right = -1; + UpdateRect.Bottom = Buff->CursorPosition.Y; + ScrolledLines = 0; + + for (i = 0; i < Length; i++) + { + /* + * If we are in processed mode, interpret special characters and + * display them correctly. Otherwise, just put them into the buffer. + */ + if (Buff->Mode & ENABLE_PROCESSED_OUTPUT) + { + /* --- CR --- */ + if (Buffer[i] == L'\r') + { + Buff->CursorPosition.X = 0; + UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); + UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); + continue; + } + /* --- LF --- */ + else if (Buffer[i] == L'\n') + { + Buff->CursorPosition.X = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + continue; + } + /* --- BS --- */ + else if (Buffer[i] == L'\b') + { + /* Only handle BS if we're not on the first pos of the first line */ + if (0 != Buff->CursorPosition.X || 0 != Buff->CursorPosition.Y) + { + if (0 == Buff->CursorPosition.X) + { + /* slide virtual position up */ + Buff->CursorPosition.X = Buff->ScreenBufferSize.X - 1; + Buff->CursorPosition.Y--; + UpdateRect.Top = min(UpdateRect.Top, Buff->CursorPosition.Y); + } + else + { + Buff->CursorPosition.X--; + } + Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); + Ptr->Char.UnicodeChar = L' '; + Ptr->Attributes = Buff->ScreenDefaultAttrib; + UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); + UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); + } + continue; + } + /* --- TAB --- */ + else if (Buffer[i] == L'\t') + { + UINT EndX; + + UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); + EndX = (Buff->CursorPosition.X + TAB_WIDTH) & ~(TAB_WIDTH - 1); + EndX = min(EndX, (UINT)Buff->ScreenBufferSize.X); + Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); + while (Buff->CursorPosition.X < EndX) + { + Ptr->Char.UnicodeChar = L' '; + Ptr->Attributes = Buff->ScreenDefaultAttrib; + ++Ptr; + Buff->CursorPosition.X++; + } + UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X - 1); + if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) + { + if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) + { + Buff->CursorPosition.X = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + } + else + { + Buff->CursorPosition.X--; + } + } + continue; + } + /* --- BEL ---*/ + else if (Buffer[i] == L'\a') + { + FrontEnd->Vtbl->RingBell(FrontEnd); + continue; + } + } + UpdateRect.Left = min(UpdateRect.Left, Buff->CursorPosition.X); + UpdateRect.Right = max(UpdateRect.Right, Buff->CursorPosition.X); + + Ptr = ConioCoordToPointer(Buff, Buff->CursorPosition.X, Buff->CursorPosition.Y); + Ptr->Char.UnicodeChar = Buffer[i]; + if (Attrib) Ptr->Attributes = Buff->ScreenDefaultAttrib; + + Buff->CursorPosition.X++; + if (Buff->CursorPosition.X == Buff->ScreenBufferSize.X) + { + if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) + { + Buff->CursorPosition.X = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + } + else + { + Buff->CursorPosition.X = CursorStartX; + } + } + } + + if (!ConioIsRectEmpty(&UpdateRect) && (PCONSOLE_SCREEN_BUFFER)Buff == Console->ActiveBuffer) + { + // TermWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, + // ScrolledLines, Buffer, Length); + FrontEnd->Vtbl->WriteStream(FrontEnd, + &UpdateRect, + CursorStartX, + CursorStartY, + ScrolledLines, + Buffer, + Length); + } + + return STATUS_SUCCESS; +} + + + +static NTSTATUS NTAPI +ConSrvTermWriteStream(IN OUT PTERMINAL This, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib) +{ + PFRONTEND FrontEnd = This->Data; + return ConioWriteConsole(FrontEnd, + Buff, + Buffer, + Length, + Attrib); +} + +/************ Line discipline ***************/ + + + static VOID NTAPI ConSrvTermDrawRegion(IN OUT PTERMINAL This, SMALL_RECT* Region) @@ -226,25 +656,6 @@ ConSrvTermDrawRegion(IN OUT PTERMINAL This, FrontEnd->Vtbl->DrawRegion(FrontEnd, Region); } -static VOID NTAPI -ConSrvTermWriteStream(IN OUT PTERMINAL This, - SMALL_RECT* Region, - SHORT CursorStartX, - SHORT CursorStartY, - UINT ScrolledLines, - PWCHAR Buffer, - UINT Length) -{ - PFRONTEND FrontEnd = This->Data; - FrontEnd->Vtbl->WriteStream(FrontEnd, - Region, - CursorStartX, - CursorStartY, - ScrolledLines, - Buffer, - Length); -} - static BOOL NTAPI ConSrvTermSetCursorInfo(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer) @@ -288,13 +699,6 @@ ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This, FrontEnd->Vtbl->ReleaseScreenBuffer(FrontEnd, ScreenBuffer); } -static VOID NTAPI -ConSrvTermChangeTitle(IN OUT PTERMINAL This) -{ - PFRONTEND FrontEnd = This->Data; - FrontEnd->Vtbl->ChangeTitle(FrontEnd); -} - static VOID NTAPI ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This, PCOORD pSize) @@ -303,16 +707,6 @@ ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This, FrontEnd->Vtbl->GetLargestConsoleWindowSize(FrontEnd, pSize); } -/* -static BOOL NTAPI -ConSrvTermGetSelectionInfo(IN OUT PTERMINAL This, - PCONSOLE_SELECTION_INFO pSelectionInfo) -{ - PFRONTEND FrontEnd = This->Data; - return FrontEnd->Vtbl->GetSelectionInfo(FrontEnd, pSelectionInfo); -} -*/ - static BOOL NTAPI ConSrvTermSetPalette(IN OUT PTERMINAL This, HPALETTE PaletteHandle, @@ -334,16 +728,17 @@ static TERMINAL_VTBL ConSrvTermVtbl = { ConSrvTermInitTerminal, ConSrvTermDeinitTerminal, - ConSrvTermDrawRegion, + + ConSrvTermReadStream, ConSrvTermWriteStream, + + ConSrvTermDrawRegion, ConSrvTermSetCursorInfo, ConSrvTermSetScreenInfo, ConSrvTermResizeTerminal, ConSrvTermSetActiveScreenBuffer, ConSrvTermReleaseScreenBuffer, - ConSrvTermChangeTitle, ConSrvTermGetLargestConsoleWindowSize, - // ConSrvTermGetSelectionInfo, ConSrvTermSetPalette, ConSrvTermShowMouseCursor, }; diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c b/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c index 3e2bed71c3d..d03cf223d3d 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c @@ -12,7 +12,7 @@ #ifdef TUITERM_COMPILE #include "consrv.h" -#include "include/conio.h" +// #include "include/conio.h" #include "include/console.h" #include "include/settings.h" #include "tuiterm.h" diff --git a/reactos/win32ss/user/winsrv/consrv/handle.c b/reactos/win32ss/user/winsrv/consrv/handle.c index 4c74ab15a3e..f54a459f24e 100644 --- a/reactos/win32ss/user/winsrv/consrv/handle.c +++ b/reactos/win32ss/user/winsrv/consrv/handle.c @@ -96,7 +96,7 @@ ConSrvCloseHandle(IN PCONSOLE_IO_HANDLE Handle) * even of the last buffer, but having to deal with a lack of * any active buffer might be error-prone. */ if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink) - ConioDeleteScreenBuffer(Buffer); + ConDrvDeleteScreenBuffer(Buffer); } else if (Object->Type == INPUT_BUFFER) { @@ -470,15 +470,12 @@ ConSrvReleaseObject(IN PCONSOLE_IO_OBJECT Object, - - - NTSTATUS ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, PHANDLE pInputHandle, PHANDLE pOutputHandle, PHANDLE pErrorHandle, - PCONSOLE_START_INFO ConsoleStartInfo) + PCONSOLE_INIT_INFO ConsoleInitInfo) { NTSTATUS Status = STATUS_SUCCESS; HANDLE ConsoleHandle; @@ -499,7 +496,7 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, /* Initialize a new Console owned by this process */ Status = ConSrvInitConsole(&ConsoleHandle, &Console, - ConsoleStartInfo, + ConsoleInitInfo, HandleToUlong(ProcessData->Process->ClientId.UniqueProcess)); if (!NT_SUCCESS(Status)) { diff --git a/reactos/win32ss/user/winsrv/consrv/history.c b/reactos/win32ss/user/winsrv/consrv/history.c new file mode 100644 index 00000000000..a885d20ab3e --- /dev/null +++ b/reactos/win32ss/user/winsrv/consrv/history.c @@ -0,0 +1,603 @@ +/* + * LICENSE: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: win32ss/user/winsrv/consrv/history.c + * PURPOSE: Console line input functions + * PROGRAMMERS: Jeffrey Morlan + */ + +/* INCLUDES *******************************************************************/ + +#include "consrv.h" +#include "popup.h" + +#define NDEBUG +#include + +typedef struct _HISTORY_BUFFER +{ + LIST_ENTRY ListEntry; + ULONG Position; + ULONG MaxEntries; + ULONG NumEntries; + UNICODE_STRING ExeName; + PUNICODE_STRING Entries; +} HISTORY_BUFFER, *PHISTORY_BUFFER; + + +BOOLEAN +ConvertInputAnsiToUnicode(PCONSRV_CONSOLE Console, + PVOID Source, + USHORT SourceLength, + // BOOLEAN IsUnicode, + PWCHAR* Target, + PUSHORT TargetLength); +BOOLEAN +ConvertInputUnicodeToAnsi(PCONSRV_CONSOLE Console, + PVOID Source, + USHORT SourceLength, + // BOOLEAN IsAnsi, + PCHAR/* * */ Target, + /*P*/USHORT TargetLength); + + +/* PRIVATE FUNCTIONS **********************************************************/ + +static PHISTORY_BUFFER +HistoryCurrentBuffer(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName) +{ + PLIST_ENTRY Entry = Console->HistoryBuffers.Flink; + PHISTORY_BUFFER Hist; + + for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink) + { + Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry); + if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE)) + return Hist; + } + + /* Couldn't find the buffer, create a new one */ + Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length); + if (!Hist) return NULL; + Hist->MaxEntries = Console->HistoryBufferSize; + Hist->NumEntries = 0; + Hist->Entries = ConsoleAllocHeap(0, Hist->MaxEntries * sizeof(UNICODE_STRING)); + if (!Hist->Entries) + { + ConsoleFreeHeap(Hist); + return NULL; + } + Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length; + Hist->ExeName.Buffer = (PWCHAR)(Hist + 1); + memcpy(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length); + InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry); + return Hist; +} + +static PHISTORY_BUFFER +HistoryFindBuffer(PCONSRV_CONSOLE Console, + PVOID ExeName, + USHORT ExeLength, + BOOLEAN UnicodeExe) +{ + UNICODE_STRING ExeNameU; + + PLIST_ENTRY Entry; + PHISTORY_BUFFER Hist = NULL; + + if (ExeName == NULL) return NULL; + + if (UnicodeExe) + { + ExeNameU.Buffer = ExeName; + /* Length is in bytes */ + ExeNameU.MaximumLength = ExeLength; + } + else + { + if (!ConvertInputAnsiToUnicode(Console, + ExeName, ExeLength, + &ExeNameU.Buffer, &ExeNameU.MaximumLength)) + { + return NULL; + } + } + ExeNameU.Length = ExeNameU.MaximumLength; + + Entry = Console->HistoryBuffers.Flink; + while (Entry != &Console->HistoryBuffers) + { + Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry); + + /* For the history APIs, the caller is allowed to give only part of the name */ + if (RtlPrefixUnicodeString(&ExeNameU, &Hist->ExeName, TRUE)) + { + if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); + return Hist; + } + + Entry = Entry->Flink; + } + + if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); + return NULL; +} + +static VOID +HistoryDeleteBuffer(PHISTORY_BUFFER Hist) +{ + if (!Hist) return; + + while (Hist->NumEntries != 0) + RtlFreeUnicodeString(&Hist->Entries[--Hist->NumEntries]); + + ConsoleFreeHeap(Hist->Entries); + RemoveEntryList(&Hist->ListEntry); + ConsoleFreeHeap(Hist); +} + +VOID +HistoryAddEntry(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + PUNICODE_STRING Entry) +{ + // UNICODE_STRING NewEntry; + PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); + + if (!Hist) return; + + // NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR); + // NewEntry.Buffer = Console->LineBuffer; + + /* Don't add blank or duplicate entries */ + if (Entry->Length == 0 || Hist->MaxEntries == 0 || + (Hist->NumEntries > 0 && + RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], Entry, FALSE))) + { + return; + } + + if (Console->HistoryNoDup) + { + INT i; + + /* Check if this line has been entered before */ + for (i = Hist->NumEntries - 1; i >= 0; i--) + { + if (RtlEqualUnicodeString(&Hist->Entries[i], Entry, FALSE)) + { + UNICODE_STRING NewEntry; + + /* Just rotate the list to bring this entry to the end */ + NewEntry = Hist->Entries[i]; + memmove(&Hist->Entries[i], &Hist->Entries[i + 1], + (Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING)); + Hist->Entries[Hist->NumEntries - 1] = NewEntry; + Hist->Position = Hist->NumEntries - 1; + return; + } + } + } + + if (Hist->NumEntries == Hist->MaxEntries) + { + /* List is full, remove oldest entry */ + RtlFreeUnicodeString(&Hist->Entries[0]); + memmove(&Hist->Entries[0], &Hist->Entries[1], + --Hist->NumEntries * sizeof(UNICODE_STRING)); + } + + if (NT_SUCCESS(RtlDuplicateUnicodeString(0, Entry, &Hist->Entries[Hist->NumEntries]))) + Hist->NumEntries++; + Hist->Position = Hist->NumEntries - 1; +} + +VOID +HistoryGetCurrentEntry(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + PUNICODE_STRING Entry) +{ + PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); + + if (!Hist || Hist->NumEntries == 0) + Entry->Length = 0; + else + *Entry = Hist->Entries[Hist->Position]; +} + +BOOL +HistoryRecallHistory(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + INT Offset, + PUNICODE_STRING Entry) +{ + PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); + ULONG Position = 0; + + if (!Hist || Hist->NumEntries == 0) return FALSE; + + Position = Hist->Position + Offset; + Position = min(max(Position, 0), Hist->NumEntries - 1); + Hist->Position = Position; + + *Entry = Hist->Entries[Hist->Position]; + return TRUE; +} + +BOOL +HistoryFindEntryByPrefix(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + PUNICODE_STRING Prefix, + PUNICODE_STRING Entry) +{ + INT HistPos; + + /* Search for history entries starting with input. */ + PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); + if (!Hist || Hist->NumEntries == 0) return FALSE; + + /* + * Like Up/F5, on first time start from current (usually last) entry, + * but on subsequent times start at previous entry. + */ + if (Console->LineUpPressed) + Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1; + Console->LineUpPressed = TRUE; + + // Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR) + // Entry.Buffer = Console->LineBuffer; + + /* + * Keep going backwards, even wrapping around to the end, + * until we get back to starting point. + */ + HistPos = Hist->Position; + do + { + if (RtlPrefixUnicodeString(Prefix, &Hist->Entries[HistPos], FALSE)) + { + Hist->Position = HistPos; + *Entry = Hist->Entries[HistPos]; + return TRUE; + } + if (--HistPos < 0) HistPos += Hist->NumEntries; + } while (HistPos != Hist->Position); + + return FALSE; +} + +PPOPUP_WINDOW +HistoryDisplayCurrentHistory(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName) +{ + PTEXTMODE_SCREEN_BUFFER ActiveBuffer; + PPOPUP_WINDOW Popup; + + SHORT xLeft, yTop; + SHORT Width, Height; + + PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); + + if (!Hist) return NULL; + if (Hist->NumEntries == 0) return NULL; + + if (GetType(Console->ActiveBuffer) != TEXTMODE_BUFFER) return NULL; + ActiveBuffer = (PTEXTMODE_SCREEN_BUFFER)Console->ActiveBuffer; + + Width = 40; + Height = 10; + + /* Center the popup window on the screen */ + xLeft = ActiveBuffer->ViewOrigin.X + (ActiveBuffer->ViewSize.X - Width ) / 2; + yTop = ActiveBuffer->ViewOrigin.Y + (ActiveBuffer->ViewSize.Y - Height) / 2; + + /* Create the popup */ + Popup = CreatePopupWindow(Console, ActiveBuffer, + xLeft, yTop, Width, Height); + if (Popup == NULL) return NULL; + + Popup->PopupInputRoutine = NULL; + + return Popup; +} + +VOID +HistoryDeleteCurrentBuffer(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName) +{ + HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName)); +} + +VOID +HistoryDeleteBuffers(PCONSRV_CONSOLE Console) +{ + PLIST_ENTRY CurrentEntry; + PHISTORY_BUFFER HistoryBuffer; + + while (!IsListEmpty(&Console->HistoryBuffers)) + { + CurrentEntry = RemoveHeadList(&Console->HistoryBuffers); + HistoryBuffer = CONTAINING_RECORD(CurrentEntry, HISTORY_BUFFER, ListEntry); + HistoryDeleteBuffer(HistoryBuffer); + } +} + + +/* PUBLIC SERVER APIS *********************************************************/ + +CSR_API(SrvGetConsoleCommandHistory) +{ + NTSTATUS Status; + PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest; + PCONSRV_CONSOLE Console; + ULONG BytesWritten = 0; + PHISTORY_BUFFER Hist; + + DPRINT1("SrvGetConsoleCommandHistory entered\n"); + + if ( !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetCommandHistoryRequest->History, + GetCommandHistoryRequest->HistoryLength, + sizeof(BYTE)) || + !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetCommandHistoryRequest->ExeName, + GetCommandHistoryRequest->ExeLength, + sizeof(BYTE)) ) + { + return STATUS_INVALID_PARAMETER; + } + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Hist = HistoryFindBuffer(Console, + GetCommandHistoryRequest->ExeName, + GetCommandHistoryRequest->ExeLength, + GetCommandHistoryRequest->Unicode2); + if (Hist) + { + ULONG i; + + LPSTR TargetBufferA; + LPWSTR TargetBufferW; + ULONG BufferSize = GetCommandHistoryRequest->HistoryLength; + + ULONG Offset = 0; + ULONG SourceLength; + + if (GetCommandHistoryRequest->Unicode) + { + TargetBufferW = GetCommandHistoryRequest->History; + BufferSize /= sizeof(WCHAR); + } + else + { + TargetBufferA = GetCommandHistoryRequest->History; + } + + for (i = 0; i < Hist->NumEntries; i++) + { + SourceLength = Hist->Entries[i].Length / sizeof(WCHAR); + if (Offset + SourceLength + 1 > BufferSize) + { + Status = STATUS_BUFFER_OVERFLOW; + break; + } + + if (GetCommandHistoryRequest->Unicode) + { + RtlCopyMemory(&TargetBufferW[Offset], Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR)); + Offset += SourceLength; + TargetBufferW[Offset++] = L'\0'; + } + else + { + ConvertInputUnicodeToAnsi(Console, + Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR), + &TargetBufferA[Offset], SourceLength); + Offset += SourceLength; + TargetBufferA[Offset++] = '\0'; + } + } + + if (GetCommandHistoryRequest->Unicode) + BytesWritten = Offset * sizeof(WCHAR); + else + BytesWritten = Offset; + } + + // GetCommandHistoryRequest->HistoryLength = TargetBuffer - (PBYTE)GetCommandHistoryRequest->History; + GetCommandHistoryRequest->HistoryLength = BytesWritten; + + ConSrvReleaseConsole(Console, TRUE); + return Status; +} + +CSR_API(SrvGetConsoleCommandHistoryLength) +{ + NTSTATUS Status; + PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryLengthRequest; + PCONSRV_CONSOLE Console; + PHISTORY_BUFFER Hist; + ULONG Length = 0; + + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetCommandHistoryLengthRequest->ExeName, + GetCommandHistoryLengthRequest->ExeLength, + sizeof(BYTE))) + { + return STATUS_INVALID_PARAMETER; + } + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Hist = HistoryFindBuffer(Console, + GetCommandHistoryLengthRequest->ExeName, + GetCommandHistoryLengthRequest->ExeLength, + GetCommandHistoryLengthRequest->Unicode2); + if (Hist) + { + ULONG i; + for (i = 0; i < Hist->NumEntries; i++) + Length += Hist->Entries[i].Length + sizeof(WCHAR); // Each entry is returned NULL-terminated + } + /* + * Quick and dirty way of getting the number of bytes of the + * corresponding ANSI string from the one in UNICODE. + */ + if (!GetCommandHistoryLengthRequest->Unicode) + Length /= sizeof(WCHAR); + + GetCommandHistoryLengthRequest->HistoryLength = Length; + + ConSrvReleaseConsole(Console, TRUE); + return Status; +} + +CSR_API(SrvExpungeConsoleCommandHistory) +{ + NTSTATUS Status; + PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ExpungeCommandHistoryRequest; + PCONSRV_CONSOLE Console; + PHISTORY_BUFFER Hist; + + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&ExpungeCommandHistoryRequest->ExeName, + ExpungeCommandHistoryRequest->ExeLength, + sizeof(BYTE))) + { + return STATUS_INVALID_PARAMETER; + } + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Hist = HistoryFindBuffer(Console, + ExpungeCommandHistoryRequest->ExeName, + ExpungeCommandHistoryRequest->ExeLength, + ExpungeCommandHistoryRequest->Unicode2); + HistoryDeleteBuffer(Hist); + + ConSrvReleaseConsole(Console, TRUE); + return Status; +} + +CSR_API(SrvSetConsoleNumberOfCommands) +{ + NTSTATUS Status; + PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryNumberCommandsRequest; + PCONSRV_CONSOLE Console; + PHISTORY_BUFFER Hist; + + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&SetHistoryNumberCommandsRequest->ExeName, + SetHistoryNumberCommandsRequest->ExeLength, + sizeof(BYTE))) + { + return STATUS_INVALID_PARAMETER; + } + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Hist = HistoryFindBuffer(Console, + SetHistoryNumberCommandsRequest->ExeName, + SetHistoryNumberCommandsRequest->ExeLength, + SetHistoryNumberCommandsRequest->Unicode2); + if (Hist) + { + ULONG MaxEntries = SetHistoryNumberCommandsRequest->NumCommands; + PUNICODE_STRING OldEntryList = Hist->Entries; + PUNICODE_STRING NewEntryList = ConsoleAllocHeap(0, MaxEntries * sizeof(UNICODE_STRING)); + if (!NewEntryList) + { + Status = STATUS_NO_MEMORY; + } + else + { + /* If necessary, shrink by removing oldest entries */ + for (; Hist->NumEntries > MaxEntries; Hist->NumEntries--) + { + RtlFreeUnicodeString(Hist->Entries++); + Hist->Position += (Hist->Position == 0); + } + + Hist->MaxEntries = MaxEntries; + Hist->Entries = memcpy(NewEntryList, Hist->Entries, + Hist->NumEntries * sizeof(UNICODE_STRING)); + ConsoleFreeHeap(OldEntryList); + } + } + + ConSrvReleaseConsole(Console, TRUE); + return Status; +} + +CSR_API(SrvGetConsoleHistory) +{ +#if 0 // Vista+ + PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest; + PCONSRV_CONSOLE Console; + NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); + if (NT_SUCCESS(Status)) + { + HistoryInfoRequest->HistoryBufferSize = Console->HistoryBufferSize; + HistoryInfoRequest->NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; + HistoryInfoRequest->dwFlags = (Console->HistoryNoDup ? HISTORY_NO_DUP_FLAG : 0); + ConSrvReleaseConsole(Console, TRUE); + } + return Status; +#else + DPRINT1("%s not yet implemented\n", __FUNCTION__); + return STATUS_NOT_IMPLEMENTED; +#endif +} + +CSR_API(SrvSetConsoleHistory) +{ +#if 0 // Vista+ + PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest; + PCONSRV_CONSOLE Console; + NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); + if (NT_SUCCESS(Status)) + { + Console->HistoryBufferSize = HistoryInfoRequest->HistoryBufferSize; + Console->NumberOfHistoryBuffers = HistoryInfoRequest->NumberOfHistoryBuffers; + Console->HistoryNoDup = !!(HistoryInfoRequest->dwFlags & HISTORY_NO_DUP_FLAG); + ConSrvReleaseConsole(Console, TRUE); + } + return Status; +#else + DPRINT1("%s not yet implemented\n", __FUNCTION__); + return STATUS_NOT_IMPLEMENTED; +#endif +} + +CSR_API(SrvSetConsoleCommandHistoryMode) +{ + NTSTATUS Status; + PCONSOLE_SETHISTORYMODE SetHistoryModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryModeRequest; + PCONSRV_CONSOLE Console; + + DPRINT1("SrvSetConsoleCommandHistoryMode(Mode = %d) is not yet implemented\n", + SetHistoryModeRequest->Mode); + + Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), + &Console, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + Console->InsertMode = !!(SetHistoryModeRequest->Mode & CONSOLE_OVERSTRIKE); + + ConSrvReleaseConsole(Console, TRUE); + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/history.h b/reactos/win32ss/user/winsrv/consrv/history.h new file mode 100644 index 00000000000..1b3833f23c0 --- /dev/null +++ b/reactos/win32ss/user/winsrv/consrv/history.h @@ -0,0 +1,11 @@ +/* + * LICENSE: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: win32ss/user/winsrv/consrv/history.h + * PURPOSE: Console line input functions + * PROGRAMMERS: Jeffrey Morlan + */ + +#pragma once + +VOID HistoryDeleteBuffers(PCONSRV_CONSOLE Console); diff --git a/reactos/win32ss/user/winsrv/consrv/include/conio.h b/reactos/win32ss/user/winsrv/consrv/include/conio.h index fc9d4ebd9a2..a3728641c4d 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/conio.h +++ b/reactos/win32ss/user/winsrv/consrv/include/conio.h @@ -12,6 +12,22 @@ #include "rect.h" +// This is ALMOST a HACK!!!!!!! +// Helpers for code refactoring +#ifdef USE_NEW_CONSOLE_WAY + +#define _CONSRV_CONSOLE _WINSRV_CONSOLE +#define CONSRV_CONSOLE WINSRV_CONSOLE +#define PCONSRV_CONSOLE PWINSRV_CONSOLE + +#else + +#define _CONSRV_CONSOLE _CONSOLE +#define CONSRV_CONSOLE CONSOLE +#define PCONSRV_CONSOLE PCONSOLE + +#endif + /* Default attributes */ #define DEFAULT_SCREEN_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED) #define DEFAULT_POPUP_ATTRIB (FOREGROUND_BLUE | FOREGROUND_RED | \ @@ -175,7 +191,7 @@ typedef struct _CONSOLE_INPUT_BUFFER { CONSOLE_IO_OBJECT Header; /* Object header - MUST BE IN FIRST PLACE */ - ULONG InputBufferSize; /* Size of this input buffer */ + ULONG InputBufferSize; /* Size of this input buffer -- UNUSED!! */ LIST_ENTRY InputEvents; /* List head for input event queue */ HANDLE ActiveEvent; /* Event set when an input event is added in its queue */ @@ -194,17 +210,33 @@ typedef struct _TERMINAL_VTBL IN struct _CONSOLE* Console); VOID (NTAPI *DeinitTerminal)(IN OUT PTERMINAL This); + + +/************ Line discipline ***************/ + + /* Interface used only for text-mode screen buffers */ + + NTSTATUS (NTAPI *ReadStream)(IN OUT PTERMINAL This, + /**/IN PUNICODE_STRING ExeName /**/OPTIONAL/**/,/**/ + IN BOOLEAN Unicode, + /**PWCHAR Buffer,**/ + OUT PVOID Buffer, + IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, + IN ULONG NumCharsToRead, + OUT PULONG NumCharsRead OPTIONAL); + NTSTATUS (NTAPI *WriteStream)(IN OUT PTERMINAL This, + PTEXTMODE_SCREEN_BUFFER Buff, + PWCHAR Buffer, + DWORD Length, + BOOL Attrib); + +/************ Line discipline ***************/ + + + /* Interface used for both text-mode and graphics screen buffers */ VOID (NTAPI *DrawRegion)(IN OUT PTERMINAL This, SMALL_RECT* Region); - /* Interface used only for text-mode screen buffers */ - VOID (NTAPI *WriteStream)(IN OUT PTERMINAL This, - SMALL_RECT* Region, - SHORT CursorStartX, - SHORT CursorStartY, - UINT ScrolledLines, - PWCHAR Buffer, - UINT Length); BOOL (NTAPI *SetCursorInfo)(IN OUT PTERMINAL This, PCONSOLE_SCREEN_BUFFER ScreenBuffer); BOOL (NTAPI *SetScreenInfo)(IN OUT PTERMINAL This, @@ -219,11 +251,8 @@ typedef struct _TERMINAL_VTBL /* * External interface (functions corresponding to the Console API) */ - VOID (NTAPI *ChangeTitle)(IN OUT PTERMINAL This); VOID (NTAPI *GetLargestConsoleWindowSize)(IN OUT PTERMINAL This, PCOORD pSize); - // BOOL (NTAPI *GetSelectionInfo)(IN OUT PTERMINAL This, - // PCONSOLE_SELECTION_INFO pSelectionInfo); BOOL (NTAPI *SetPalette)(IN OUT PTERMINAL This, HPALETTE PaletteHandle, UINT PaletteUsage); @@ -263,51 +292,39 @@ typedef enum _CONSOLE_STATE // HACK!! struct _CONSOLE; /* HACK: */ typedef struct _CONSOLE *PCONSOLE; +#ifndef USE_NEW_CONSOLE_WAY #include "conio_winsrv.h" +#endif typedef struct _CONSOLE { /******************************* Console Set-up *******************************/ + +#ifndef USE_NEW_CONSOLE_WAY + WINSRV_CONSOLE; // HACK HACK!! +#endif + LONG ReferenceCount; /* Is incremented each time a handle to something in the console (a screen-buffer or the input buffer of this console) gets referenced */ CRITICAL_SECTION Lock; - /**/WINSRV_CONSOLE;/**/ // HACK HACK!! - CONSOLE_STATE State; /* State of the console */ TERMINAL TermIFace; /* Frontend-specific interface */ ULONG ConsoleID; /* The ID of the console */ LIST_ENTRY ListEntry; /* Entry in the list of consoles */ -/**************************** Input buffer and data ***************************/ + HANDLE UnpauseEvent; /* When != NULL, event for pausing the console */ + +/******************************** Input buffer ********************************/ CONSOLE_INPUT_BUFFER InputBuffer; /* Input buffer of the console */ UINT InputCodePage; - /** Put those things in CONSOLE_INPUT_BUFFER in PWINSRV_CONSOLE ?? **/ - PWCHAR LineBuffer; /* Current line being input, in line buffered mode */ - ULONG LineMaxSize; /* Maximum size of line in characters (including CR+LF) */ - ULONG LineSize; /* Current size of line */ - ULONG LinePos; /* Current position within line */ - BOOLEAN LineComplete; /* User pressed enter, ready to send back to client */ - BOOLEAN LineUpPressed; - BOOLEAN LineInsertToggle; /* Replace character over cursor instead of inserting */ - ULONG LineWakeupMask; /* Bitmap of which control characters will end line input */ - - /** In PWINSRV_CONSOLE ?? **/ - BOOLEAN InsertMode; - /*************************************************/ - /******************************* Screen buffers *******************************/ LIST_ENTRY BufferList; /* List of all screen buffers for this console */ PCONSOLE_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */ UINT OutputCodePage; /****************************** Other properties ******************************/ - UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */ - UNICODE_STRING Title; /* Title of console. Always NULL-terminated */ - - HANDLE UnpauseEvent; /* When != NULL, event for pausing the console */ - COORD ConsoleSize; /* The current size of the console, for text-mode only */ BOOLEAN FixedSize; /* TRUE if the console is of fixed size */ @@ -323,42 +340,16 @@ NTSTATUS ConSrvConsoleCtrlEvent(IN ULONG CtrlEvent, IN PCONSOLE_PROCESS_DATA ProcessData); -/* coninput.c */ -NTSTATUS -ConioAddInputEvents(PCONSOLE Console, - PINPUT_RECORD InputRecords, - ULONG NumEventsToWrite, - PULONG NumEventsWritten, - BOOLEAN AppendToEnd); -NTSTATUS -ConioProcessInputEvent(PCONSOLE Console, - PINPUT_RECORD InputEvent); + +#define GetConsoleInputBufferMode(Console) \ + (Console)->InputBuffer.Mode + /* conoutput.c */ - -/* - * From MSDN: - * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. - * If they are the same, the function fails, and GetLastError returns - * ERROR_INVALID_PARAMETER." - */ -#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \ - ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ - WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) - -#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \ - ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ - MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1) - PCHAR_INFO ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y); -VOID ConioDrawConsole(PCONSOLE Console); -NTSTATUS ConioResizeBuffer(PCONSOLE Console, +VOID ConioDrawConsole(PCONSOLE /*PCONSRV_CONSOLE*/ Console); +NTSTATUS ConioResizeBuffer(PCONSOLE /*PCONSRV_CONSOLE*/ Console, PTEXTMODE_SCREEN_BUFFER ScreenBuffer, COORD Size); -NTSTATUS ConioWriteConsole(PCONSOLE Console, - PTEXTMODE_SCREEN_BUFFER Buff, - PWCHAR Buffer, - DWORD Length, - BOOL Attrib); /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/include/conio_winsrv.h b/reactos/win32ss/user/winsrv/consrv/include/conio_winsrv.h index d7be50e4e75..135ccb54352 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/conio_winsrv.h +++ b/reactos/win32ss/user/winsrv/consrv/include/conio_winsrv.h @@ -14,14 +14,19 @@ // This is ALMOST a HACK!!!!!!! // Helpers for code refactoring +#ifdef USE_NEW_CONSOLE_WAY + +#define _CONSRV_CONSOLE _WINSRV_CONSOLE +#define CONSRV_CONSOLE WINSRV_CONSOLE +#define PCONSRV_CONSOLE PWINSRV_CONSOLE + +#else + #define _CONSRV_CONSOLE _CONSOLE #define CONSRV_CONSOLE CONSOLE #define PCONSRV_CONSOLE PCONSOLE -// #define _CONSRV_CONSOLE _WINSRV_CONSOLE -// #define CONSRV_CONSOLE WINSRV_CONSOLE -// #define PCONSRV_CONSOLE PWINSRV_CONSOLE - +#endif #define CSR_DEFAULT_CURSOR_SIZE 25 @@ -33,6 +38,12 @@ typedef struct _CHAR_CELL } CHAR_CELL, *PCHAR_CELL; C_ASSERT(sizeof(CHAR_CELL) == 2); +// HACK!! +struct _WINSRV_CONSOLE; +/* HACK: */ typedef struct _WINSRV_CONSOLE *PWINSRV_CONSOLE; +#ifdef USE_NEW_CONSOLE_WAY +#include "conio.h" +#endif typedef struct _FRONTEND FRONTEND, *PFRONTEND; /* HACK: */ typedef struct _CONSOLE_INFO *PCONSOLE_INFO; @@ -58,6 +69,7 @@ typedef struct _FRONTEND_VTBL UINT ScrolledLines, PWCHAR Buffer, UINT Length); + VOID (NTAPI *RingBell)(IN OUT PFRONTEND This); BOOL (NTAPI *SetCursorInfo)(IN OUT PFRONTEND This, PCONSOLE_SCREEN_BUFFER ScreenBuffer); BOOL (NTAPI *SetScreenInfo)(IN OUT PFRONTEND This, @@ -117,8 +129,11 @@ typedef struct _WINSRV_CONSOLE { /******************************* Console Set-up *******************************/ /* This **MUST** be FIRST!! */ - // CONSOLE; - // PCONSOLE Console; +#ifdef USE_NEW_CONSOLE_WAY + CONSOLE; + // CONSOLE Console; + // // PCONSOLE Console; +#endif // LONG ReferenceCount; /* Is incremented each time a handle to something in the console (a screen-buffer or the input buffer of this console) gets referenced */ // CRITICAL_SECTION Lock; @@ -131,8 +146,6 @@ typedef struct _WINSRV_CONSOLE PCONSOLE_PROCESS_DATA NotifiedLastCloseProcess; /* Pointer to the unique process that needs to be notified when the console leader process is killed */ BOOLEAN NotifyLastClose; /* TRUE if the console should send a control event when the console leader process is killed */ - BOOLEAN QuickEdit; - /******************************* Pausing support ******************************/ BYTE PauseFlags; LIST_ENTRY ReadWaitQueue; /* List head for the queue of unique input buffer read wait blocks */ @@ -145,6 +158,19 @@ typedef struct _WINSRV_CONSOLE ULONG NumberOfHistoryBuffers; /* Maximum number of history buffers allowed */ BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */ +/**************************** Input Line Discipline ***************************/ + PWCHAR LineBuffer; /* Current line being input, in line buffered mode */ + ULONG LineMaxSize; /* Maximum size of line in characters (including CR+LF) */ + ULONG LineSize; /* Current size of line */ + ULONG LinePos; /* Current position within line */ + BOOLEAN LineComplete; /* User pressed enter, ready to send back to client */ + BOOLEAN LineUpPressed; + BOOLEAN LineInsertToggle; /* Replace character over cursor instead of inserting */ + ULONG LineWakeupMask; /* Bitmap of which control characters will end line input */ + + BOOLEAN InsertMode; + BOOLEAN QuickEdit; + /************************ Virtual DOS Machine support *************************/ COORD VDMBufferSize; /* Real size of the VDM buffer, in units of ??? */ HANDLE VDMBufferSection; /* Handle to the memory shared section for the VDM buffer */ @@ -157,9 +183,12 @@ typedef struct _WINSRV_CONSOLE HANDLE ErrorHardwareEvent; /****************************** Other properties ******************************/ - COLORREF Colors[16]; /* Colour palette */ + LIST_ENTRY PopupWindows; /* List of popup windows */ + UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */ + UNICODE_STRING Title; /* Title of console. Always NULL-terminated */ + COLORREF Colors[16]; /* Colour palette */ -} WINSRV_CONSOLE, *PWINSRV_CONSOLE; +} WINSRV_CONSOLE; // , *PWINSRV_CONSOLE; /* console.c */ VOID ConioPause(PCONSRV_CONSOLE Console, UINT Flags); @@ -181,40 +210,14 @@ DWORD ConioEffectiveCursorSize(PCONSRV_CONSOLE Console, DWORD Scale); NTSTATUS -ConioAddInputEvents(PCONSRV_CONSOLE Console, - PINPUT_RECORD InputRecords, - ULONG NumEventsToWrite, - PULONG NumEventsWritten, - BOOLEAN AppendToEnd); -NTSTATUS ConioProcessInputEvent(PCONSRV_CONSOLE Console, PINPUT_RECORD InputEvent); /* conoutput.c */ - -/* - * From MSDN: - * "The lpMultiByteStr and lpWideCharStr pointers must not be the same. - * If they are the same, the function fails, and GetLastError returns - * ERROR_INVALID_PARAMETER." - */ -#define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \ - ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \ - WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) - -#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \ - ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \ - MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1) - PCHAR_INFO ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff, ULONG X, ULONG Y); -VOID ConioDrawConsole(PCONSRV_CONSOLE Console); -NTSTATUS ConioResizeBuffer(PCONSRV_CONSOLE Console, +VOID ConioDrawConsole(PCONSOLE /*PCONSRV_CONSOLE*/ Console); +NTSTATUS ConioResizeBuffer(PCONSOLE /*PCONSRV_CONSOLE*/ Console, PTEXTMODE_SCREEN_BUFFER ScreenBuffer, COORD Size); -NTSTATUS ConioWriteConsole(PCONSRV_CONSOLE Console, - PTEXTMODE_SCREEN_BUFFER Buff, - PWCHAR Buffer, - DWORD Length, - BOOL Attrib); /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/include/settings.h b/reactos/win32ss/user/winsrv/consrv/include/settings.h index fcef0f18b58..9edfc4ce9d9 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/settings.h +++ b/reactos/win32ss/user/winsrv/consrv/include/settings.h @@ -62,6 +62,9 @@ typedef struct _CONSOLE_INFO /* * Structure used to communicate with console.dll + * + * FIXME: It should overlap with the Windows' CONSOLE_STATE_INFO structure + * for GUI terminals!! */ typedef struct _CONSOLE_PROPS { diff --git a/reactos/win32ss/user/winsrv/consrv/include/term.h b/reactos/win32ss/user/winsrv/consrv/include/term.h index 037f6e8c314..ecea140aff1 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/term.h +++ b/reactos/win32ss/user/winsrv/consrv/include/term.h @@ -8,13 +8,19 @@ #pragma once -/* Macros used to call functions in the FRONTEND_VTBL virtual table */ +/* Macros used to call functions in the TERMINAL_VTBL virtual table */ + +#define TermReadStream(Console, ExeName, /**/ Unicode, /**/ Buffer, ReadControl, NumCharsToRead, NumCharsRead) \ + (Console)->TermIFace.Vtbl->ReadStream(&(Console)->TermIFace, (ExeName), /**/ (Unicode), /**/ \ + (Buffer), (ReadControl), (NumCharsToRead), (NumCharsRead)) + +#define TermWriteStream(Console, ScreenBuffer, Buffer, Length, Attrib) \ + (Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (ScreenBuffer), (Buffer), \ + (Length), (Attrib)) + #define TermDrawRegion(Console, Region) \ (Console)->TermIFace.Vtbl->DrawRegion(&(Console)->TermIFace, (Region)) -#define TermWriteStream(Console, Region, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \ - (Console)->TermIFace.Vtbl->WriteStream(&(Console)->TermIFace, (Region), (CurStartX), (CurStartY), \ - (ScrolledLines), (Buffer), (Length)) #define TermSetCursorInfo(Console, ScreenBuffer) \ (Console)->TermIFace.Vtbl->SetCursorInfo(&(Console)->TermIFace, (ScreenBuffer)) #define TermSetScreenInfo(Console, ScreenBuffer, OldCursorX, OldCursorY) \ @@ -25,27 +31,30 @@ (Console)->TermIFace.Vtbl->SetActiveScreenBuffer(&(Console)->TermIFace) #define TermReleaseScreenBuffer(Console, ScreenBuffer) \ (Console)->TermIFace.Vtbl->ReleaseScreenBuffer(&(Console)->TermIFace, (ScreenBuffer)) +#define TermGetLargestConsoleWindowSize(Console, pSize) \ + (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize(&(Console)->TermIFace, (pSize)) +#define TermSetPalette(Console, PaletteHandle, PaletteUsage) \ + (Console)->TermIFace.Vtbl->SetPalette(&(Console)->TermIFace, (PaletteHandle), (PaletteUsage)) +#define TermShowMouseCursor(Console, Show) \ + (Console)->TermIFace.Vtbl->ShowMouseCursor(&(Console)->TermIFace, (Show)) + + +/* Macros used to call functions in the FRONTEND_VTBL virtual table */ + #define TermRefreshInternalInfo(Console) \ (Console)->FrontEndIFace.Vtbl->RefreshInternalInfo(&(Console)->FrontEndIFace) - #define TermChangeTitle(Console) \ - (Console)->TermIFace.Vtbl->ChangeTitle(&(Console)->TermIFace) + (Console)->FrontEndIFace.Vtbl->ChangeTitle(&(Console)->FrontEndIFace) #define TermChangeIcon(Console, IconHandle) \ (Console)->FrontEndIFace.Vtbl->ChangeIcon(&(Console)->FrontEndIFace, (IconHandle)) #define TermGetConsoleWindowHandle(Console) \ (Console)->FrontEndIFace.Vtbl->GetConsoleWindowHandle(&(Console)->FrontEndIFace) -#define TermGetLargestConsoleWindowSize(Console, pSize) \ - (Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize(&(Console)->TermIFace, (pSize)) #define TermGetSelectionInfo(Console, pSelectionInfo) \ (Console)->FrontEndIFace.Vtbl->GetSelectionInfo(&(Console)->FrontEndIFace, (pSelectionInfo)) -#define TermSetPalette(Console, PaletteHandle, PaletteUsage) \ - (Console)->TermIFace.Vtbl->SetPalette(&(Console)->TermIFace, (PaletteHandle), (PaletteUsage)) #define TermGetDisplayMode(Console) \ (Console)->FrontEndIFace.Vtbl->GetDisplayMode(&(Console)->FrontEndIFace) #define TermSetDisplayMode(Console, NewMode) \ (Console)->FrontEndIFace.Vtbl->SetDisplayMode(&(Console)->FrontEndIFace, (NewMode)) -#define TermShowMouseCursor(Console, Show) \ - (Console)->TermIFace.Vtbl->ShowMouseCursor(&(Console)->TermIFace, (Show)) #define TermSetMouseCursor(Console, CursorHandle) \ (Console)->FrontEndIFace.Vtbl->SetMouseCursor(&(Console)->FrontEndIFace, (CursorHandle)) #define TermMenuControl(Console, CmdIdLow, CmdIdHigh) \ diff --git a/reactos/win32ss/user/winsrv/consrv/init.c b/reactos/win32ss/user/winsrv/consrv/init.c index 3f50c6b1ba9..743166dbcea 100644 --- a/reactos/win32ss/user/winsrv/consrv/init.c +++ b/reactos/win32ss/user/winsrv/consrv/init.c @@ -354,8 +354,8 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess, RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData)); TargetProcessData->Process = TargetProcess; TargetProcessData->InputWaitHandle = NULL; - TargetProcessData->ConsoleHandle = TargetProcessData->ParentConsoleHandle = NULL; - TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE); + TargetProcessData->ConsoleHandle = NULL; + TargetProcessData->ConsoleApp = FALSE; /* * The handles table gets initialized either when inheriting from @@ -377,10 +377,10 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess, * handles table: this can happen if it is a GUI application having called * AllocConsole), then try to inherit handles from the parent process. */ - if (TargetProcessData->ConsoleApp /* && SourceProcessData->ConsoleApp */) + if (TargetProcess->Flags & CsrProcessIsConsoleApp /* && SourceProcessData->ConsoleHandle != NULL */) { PCONSOLE_PROCESS_DATA SourceProcessData = ConsoleGetPerProcessData(SourceProcess); - PCONSOLE SourceConsole; + PCONSRV_CONSOLE SourceConsole; /* Validate and lock the parent's console */ if (ConSrvValidateConsole(&SourceConsole, @@ -389,10 +389,9 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess, { /* Inherit the parent's handles table */ Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData); - if (NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { - /* Temporary save the parent's console too */ - TargetProcessData->ParentConsoleHandle = SourceProcessData->ConsoleHandle; + DPRINT1("Inheriting handles table failed\n"); } /* Unlock the parent's console */ @@ -416,28 +415,37 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess, NTSTATUS Status = STATUS_SUCCESS; PCONSRV_API_CONNECTINFO ConnectInfo = (PCONSRV_API_CONNECTINFO)ConnectionInfo; PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess); + CONSOLE_INIT_INFO ConsoleInitInfo; if ( ConnectionInfo == NULL || ConnectionInfoLength == NULL || - *ConnectionInfoLength != sizeof(CONSRV_API_CONNECTINFO) ) + *ConnectionInfoLength != sizeof(*ConnectInfo) ) { DPRINT1("CONSRV: Connection failed - ConnectionInfo = 0x%p ; ConnectionInfoLength = 0x%p (%lu), wanted %lu\n", ConnectionInfo, ConnectionInfoLength, ConnectionInfoLength ? *ConnectionInfoLength : (ULONG)-1, - sizeof(CONSRV_API_CONNECTINFO)); + sizeof(*ConnectInfo)); return STATUS_UNSUCCESSFUL; } /* If we don't need a console, then get out of here */ - if (!ConnectInfo->ConsoleStartInfo.ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps. - { - return STATUS_SUCCESS; - } + DPRINT("ConnectInfo->IsConsoleApp = %s\n", ConnectInfo->IsConsoleApp ? "True" : "False"); + if (!ConnectInfo->IsConsoleApp) return STATUS_SUCCESS; - /* If we don't have a console, then create a new one... */ - if (!ConnectInfo->ConsoleHandle || - ConnectInfo->ConsoleHandle != ProcessData->ParentConsoleHandle) + /* Initialize the console initialization info structure */ + ConsoleInitInfo.ConsoleStartInfo = &ConnectInfo->ConsoleStartInfo; + ConsoleInitInfo.TitleLength = ConnectInfo->TitleLength; + ConsoleInitInfo.ConsoleTitle = ConnectInfo->ConsoleTitle; + ConsoleInitInfo.DesktopLength = ConnectInfo->DesktopLength; + ConsoleInitInfo.Desktop = ConnectInfo->Desktop; + ConsoleInitInfo.AppNameLength = ConnectInfo->AppNameLength; + ConsoleInitInfo.AppName = ConnectInfo->AppName; + ConsoleInitInfo.CurDirLength = ConnectInfo->CurDirLength; + ConsoleInitInfo.CurDir = ConnectInfo->CurDir; + + /* If we don't inherit from an existing console, then create a new one... */ + if (ConnectInfo->ConsoleStartInfo.ConsoleHandle == NULL) { DPRINT("ConSrvConnect - Allocate a new console\n"); @@ -454,10 +462,10 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess, /* Initialize a new Console owned by the Console Leader Process */ Status = ConSrvAllocateConsole(ProcessData, - &ConnectInfo->InputHandle, - &ConnectInfo->OutputHandle, - &ConnectInfo->ErrorHandle, - &ConnectInfo->ConsoleStartInfo); + &ConnectInfo->ConsoleStartInfo.InputHandle, + &ConnectInfo->ConsoleStartInfo.OutputHandle, + &ConnectInfo->ConsoleStartInfo.ErrorHandle, + &ConsoleInitInfo); if (!NT_SUCCESS(Status)) { DPRINT1("Console allocation failed\n"); @@ -470,11 +478,11 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess, /* Reuse our current console */ Status = ConSrvInheritConsole(ProcessData, - ConnectInfo->ConsoleHandle, + ConnectInfo->ConsoleStartInfo.ConsoleHandle, FALSE, - NULL, // &ConnectInfo->InputHandle, - NULL, // &ConnectInfo->OutputHandle, - NULL); // &ConnectInfo->ErrorHandle); + NULL, // &ConnectInfo->ConsoleStartInfo.InputHandle, + NULL, // &ConnectInfo->ConsoleStartInfo.OutputHandle, + NULL); // &ConnectInfo->ConsoleStartInfo.ErrorHandle); if (!NT_SUCCESS(Status)) { DPRINT1("Console inheritance failed\n"); @@ -482,13 +490,17 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess, } } + /* Mark the process as having a console */ + ProcessData->ConsoleApp = TRUE; + // ProcessData->Flags |= CsrProcessIsConsoleApp; + /* Return the console handle and the input wait handle to the caller */ - ConnectInfo->ConsoleHandle = ProcessData->ConsoleHandle; - ConnectInfo->InputWaitHandle = ProcessData->InputWaitHandle; + ConnectInfo->ConsoleStartInfo.ConsoleHandle = ProcessData->ConsoleHandle; + ConnectInfo->ConsoleStartInfo.InputWaitHandle = ProcessData->InputWaitHandle; /* Set the Property-Dialog and Control-Dispatcher handlers */ - ProcessData->PropDispatcher = ConnectInfo->ConsoleStartInfo.PropDispatcher; - ProcessData->CtrlDispatcher = ConnectInfo->ConsoleStartInfo.CtrlDispatcher; + ProcessData->PropRoutine = ConnectInfo->PropRoutine; + ProcessData->CtrlRoutine = ConnectInfo->CtrlRoutine; return STATUS_SUCCESS; } @@ -508,6 +520,10 @@ ConSrvDisconnect(PCSR_PROCESS Process) { DPRINT("ConSrvDisconnect - calling ConSrvRemoveConsole\n"); ConSrvRemoveConsole(ProcessData); + + /* Mark the process as not having a console anymore */ + ProcessData->ConsoleApp = FALSE; + Process->Flags &= ~CsrProcessIsConsoleApp; } RtlDeleteCriticalSection(&ProcessData->HandleTableLock); diff --git a/reactos/win32ss/user/winsrv/consrv/lineinput.c b/reactos/win32ss/user/winsrv/consrv/lineinput.c index e60ff4c1135..0a839d328f9 100644 --- a/reactos/win32ss/user/winsrv/consrv/lineinput.c +++ b/reactos/win32ss/user/winsrv/consrv/lineinput.c @@ -9,30 +9,21 @@ /* INCLUDES *******************************************************************/ #include "consrv.h" +#include "popup.h" #define NDEBUG #include -typedef struct _HISTORY_BUFFER -{ - LIST_ENTRY ListEntry; - UINT Position; - UINT MaxEntries; - UINT NumEntries; - UNICODE_STRING ExeName; - PUNICODE_STRING Entries; -} HISTORY_BUFFER, *PHISTORY_BUFFER; - BOOLEAN -ConvertInputAnsiToUnicode(PCONSOLE Console, +ConvertInputAnsiToUnicode(PCONSRV_CONSOLE Console, PVOID Source, USHORT SourceLength, // BOOLEAN IsUnicode, PWCHAR* Target, PUSHORT TargetLength); BOOLEAN -ConvertInputUnicodeToAnsi(PCONSOLE Console, +ConvertInputUnicodeToAnsi(PCONSRV_CONSOLE Console, PVOID Source, USHORT SourceLength, // BOOLEAN IsAnsi, @@ -40,185 +31,36 @@ ConvertInputUnicodeToAnsi(PCONSOLE Console, /*P*/USHORT TargetLength); -/* PRIVATE FUNCTIONS **********************************************************/ - -static PHISTORY_BUFFER -HistoryCurrentBuffer(PCONSRV_CONSOLE Console, - PUNICODE_STRING ExeName) -{ - PLIST_ENTRY Entry = Console->HistoryBuffers.Flink; - PHISTORY_BUFFER Hist; - - for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink) - { - Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry); - if (RtlEqualUnicodeString(ExeName, &Hist->ExeName, FALSE)) - return Hist; - } - - /* Couldn't find the buffer, create a new one */ - Hist = ConsoleAllocHeap(0, sizeof(HISTORY_BUFFER) + ExeName->Length); - if (!Hist) return NULL; - Hist->MaxEntries = Console->HistoryBufferSize; - Hist->NumEntries = 0; - Hist->Entries = ConsoleAllocHeap(0, Hist->MaxEntries * sizeof(UNICODE_STRING)); - if (!Hist->Entries) - { - ConsoleFreeHeap(Hist); - return NULL; - } - Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName->Length; - Hist->ExeName.Buffer = (PWCHAR)(Hist + 1); - memcpy(Hist->ExeName.Buffer, ExeName->Buffer, ExeName->Length); - InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry); - return Hist; -} - -static VOID +VOID HistoryAddEntry(PCONSRV_CONSOLE Console, - PUNICODE_STRING ExeName) -{ - UNICODE_STRING NewEntry; - PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); - INT i; - - if (!Hist) return; - - NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR); - NewEntry.Buffer = Console->LineBuffer; - - /* Don't add blank or duplicate entries */ - if (NewEntry.Length == 0 || Hist->MaxEntries == 0 || - (Hist->NumEntries > 0 && - RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], &NewEntry, FALSE))) - { - return; - } - - if (Console->HistoryNoDup) - { - /* Check if this line has been entered before */ - for (i = Hist->NumEntries - 1; i >= 0; i--) - { - if (RtlEqualUnicodeString(&Hist->Entries[i], &NewEntry, FALSE)) - { - /* Just rotate the list to bring this entry to the end */ - NewEntry = Hist->Entries[i]; - memmove(&Hist->Entries[i], &Hist->Entries[i + 1], - (Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING)); - Hist->Entries[Hist->NumEntries - 1] = NewEntry; - Hist->Position = Hist->NumEntries - 1; - return; - } - } - } - - if (Hist->NumEntries == Hist->MaxEntries) - { - /* List is full, remove oldest entry */ - RtlFreeUnicodeString(&Hist->Entries[0]); - memmove(&Hist->Entries[0], &Hist->Entries[1], - --Hist->NumEntries * sizeof(UNICODE_STRING)); - } - - if (NT_SUCCESS(RtlDuplicateUnicodeString(0, &NewEntry, &Hist->Entries[Hist->NumEntries]))) - Hist->NumEntries++; - Hist->Position = Hist->NumEntries - 1; -} - -static VOID + PUNICODE_STRING ExeName, + PUNICODE_STRING Entry); +BOOL +HistoryRecallHistory(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + INT Offset, + PUNICODE_STRING Entry); +VOID HistoryGetCurrentEntry(PCONSRV_CONSOLE Console, PUNICODE_STRING ExeName, - PUNICODE_STRING Entry) -{ - PHISTORY_BUFFER Hist = HistoryCurrentBuffer(Console, ExeName); - - if (!Hist || Hist->NumEntries == 0) - Entry->Length = 0; - else - *Entry = Hist->Entries[Hist->Position]; -} - -static PHISTORY_BUFFER -HistoryFindBuffer(PCONSRV_CONSOLE Console, - PVOID ExeName, - USHORT ExeLength, - BOOLEAN UnicodeExe) -{ - UNICODE_STRING ExeNameU; - - PLIST_ENTRY Entry; - PHISTORY_BUFFER Hist = NULL; - - if (ExeName == NULL) return NULL; - - if (UnicodeExe) - { - ExeNameU.Buffer = ExeName; - /* Length is in bytes */ - ExeNameU.MaximumLength = ExeLength; - } - else - { - if (!ConvertInputAnsiToUnicode(Console, - ExeName, ExeLength, - &ExeNameU.Buffer, &ExeNameU.MaximumLength)) - { - return NULL; - } - } - ExeNameU.Length = ExeNameU.MaximumLength; - - Entry = Console->HistoryBuffers.Flink; - while (Entry != &Console->HistoryBuffers) - { - Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry); - - /* For the history APIs, the caller is allowed to give only part of the name */ - if (RtlPrefixUnicodeString(&ExeNameU, &Hist->ExeName, TRUE)) - { - if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); - return Hist; - } - - Entry = Entry->Flink; - } - - if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer); - return NULL; -} - -static VOID -HistoryDeleteBuffer(PHISTORY_BUFFER Hist) -{ - if (!Hist) return; - - while (Hist->NumEntries != 0) - RtlFreeUnicodeString(&Hist->Entries[--Hist->NumEntries]); - - ConsoleFreeHeap(Hist->Entries); - RemoveEntryList(&Hist->ListEntry); - ConsoleFreeHeap(Hist); -} - + PUNICODE_STRING Entry); VOID -HistoryDeleteBuffers(PCONSRV_CONSOLE Console) -{ - PLIST_ENTRY CurrentEntry; - PHISTORY_BUFFER HistoryBuffer; +HistoryDeleteCurrentBuffer(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName); +BOOL +HistoryFindEntryByPrefix(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + PUNICODE_STRING Prefix, + PUNICODE_STRING Entry); - while (!IsListEmpty(&Console->HistoryBuffers)) - { - CurrentEntry = RemoveHeadList(&Console->HistoryBuffers); - HistoryBuffer = CONTAINING_RECORD(CurrentEntry, HISTORY_BUFFER, ListEntry); - HistoryDeleteBuffer(HistoryBuffer); - } -} + +/* PRIVATE FUNCTIONS **********************************************************/ static VOID -LineInputSetPos(PCONSRV_CONSOLE Console, UINT Pos) +LineInputSetPos(PCONSRV_CONSOLE Console, + UINT Pos) { - if (Pos != Console->LinePos && Console->InputBuffer.Mode & ENABLE_ECHO_INPUT) + if (Pos != Console->LinePos && GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT) { PCONSOLE_SCREEN_BUFFER Buffer = Console->ActiveBuffer; SHORT OldCursorX = Buffer->CursorPosition.X; @@ -240,7 +82,10 @@ LineInputSetPos(PCONSRV_CONSOLE Console, UINT Pos) } static VOID -LineInputEdit(PCONSRV_CONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHAR Insertion) +LineInputEdit(PCONSRV_CONSOLE Console, + UINT NumToDelete, + UINT NumToInsert, + PWCHAR Insertion) { PTEXTMODE_SCREEN_BUFFER ActiveBuffer; UINT Pos = Console->LinePos; @@ -259,15 +104,15 @@ LineInputEdit(PCONSRV_CONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHA (Console->LineSize - (Pos + NumToDelete)) * sizeof(WCHAR)); memcpy(&Console->LineBuffer[Pos], Insertion, NumToInsert * sizeof(WCHAR)); - if (Console->InputBuffer.Mode & ENABLE_ECHO_INPUT) + if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT) { for (i = Pos; i < NewSize; i++) { - ConioWriteConsole(Console, ActiveBuffer, &Console->LineBuffer[i], 1, TRUE); + TermWriteStream(Console, ActiveBuffer, &Console->LineBuffer[i], 1, TRUE); } for (; i < Console->LineSize; i++) { - ConioWriteConsole(Console, ActiveBuffer, L" ", 1, TRUE); + TermWriteStream(Console, ActiveBuffer, L" ", 1, TRUE); } Console->LinePos = i; } @@ -276,6 +121,7 @@ LineInputEdit(PCONSRV_CONSOLE Console, UINT NumToDelete, UINT NumToInsert, PWCHA LineInputSetPos(Console, Pos + NumToInsert); } +#if 0 static VOID LineInputRecallHistory(PCONSRV_CONSOLE Console, PUNICODE_STRING ExeName, @@ -295,6 +141,30 @@ LineInputRecallHistory(PCONSRV_CONSOLE Console, Hist->Entries[Hist->Position].Length / sizeof(WCHAR), Hist->Entries[Hist->Position].Buffer); } +#else +static VOID +LineInputRecallHistory(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName, + INT Offset) +{ + UNICODE_STRING Entry; + + if (!HistoryRecallHistory(Console, ExeName, Offset, &Entry)) return; + + LineInputSetPos(Console, 0); + LineInputEdit(Console, Console->LineSize, + Entry.Length / sizeof(WCHAR), + Entry.Buffer); +} +#endif + + +// TESTS!! +PPOPUP_WINDOW Popup = NULL; + +PPOPUP_WINDOW +HistoryDisplayCurrentHistory(PCONSRV_CONSOLE Console, + PUNICODE_STRING ExeName); VOID LineInputKeyDown(PCONSRV_CONSOLE Console, @@ -302,145 +172,238 @@ LineInputKeyDown(PCONSRV_CONSOLE Console, KEY_EVENT_RECORD *KeyEvent) { UINT Pos = Console->LinePos; - PHISTORY_BUFFER Hist; UNICODE_STRING Entry; - INT HistPos; + + /* + * First, deal with control keys... + */ switch (KeyEvent->wVirtualKeyCode) { - case VK_ESCAPE: - /* Clear entire line */ - LineInputSetPos(Console, 0); - LineInputEdit(Console, Console->LineSize, 0, NULL); - return; - case VK_HOME: - /* Move to start of line. With ctrl, erase everything left of cursor */ - LineInputSetPos(Console, 0); - if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) - LineInputEdit(Console, Pos, 0, NULL); - return; - case VK_END: - /* Move to end of line. With ctrl, erase everything right of cursor */ - if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) - LineInputEdit(Console, Console->LineSize - Pos, 0, NULL); - else - LineInputSetPos(Console, Console->LineSize); - return; - case VK_LEFT: - /* Move left. With ctrl, move to beginning of previous word */ - if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) + case VK_ESCAPE: { - while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--; - while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--; + /* Clear entire line */ + LineInputSetPos(Console, 0); + LineInputEdit(Console, Console->LineSize, 0, NULL); + + // TESTS!! + if (Popup) + { + DestroyPopupWindow(Popup); + Popup = NULL; + } + return; } - else + + case VK_HOME: { - Pos -= (Pos > 0); + /* Move to start of line. With CTRL, erase everything left of cursor */ + LineInputSetPos(Console, 0); + if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) + LineInputEdit(Console, Pos, 0, NULL); + return; } - LineInputSetPos(Console, Pos); - return; - case VK_RIGHT: - case VK_F1: - /* Move right. With ctrl, move to beginning of next word */ - if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) + + case VK_END: { - while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++; - while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++; + /* Move to end of line. With CTRL, erase everything right of cursor */ + if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) + LineInputEdit(Console, Console->LineSize - Pos, 0, NULL); + else + LineInputSetPos(Console, Console->LineSize); + return; + } + + case VK_LEFT: + { + /* Move left. With CTRL, move to beginning of previous word */ + if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) + { + while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--; + while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--; + } + else + { + Pos -= (Pos > 0); + } LineInputSetPos(Console, Pos); return; } - else - { - /* Recall one character (but don't overwrite current line) */ - HistoryGetCurrentEntry(Console, ExeName, &Entry); - if (Pos < Console->LineSize) - LineInputSetPos(Console, Pos + 1); - else if (Pos * sizeof(WCHAR) < Entry.Length) - LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]); - } - return; - case VK_INSERT: - /* Toggle between insert and overstrike */ - Console->LineInsertToggle = !Console->LineInsertToggle; - TermSetCursorInfo(Console, Console->ActiveBuffer); - return; - case VK_DELETE: - /* Remove character to right of cursor */ - if (Pos != Console->LineSize) - LineInputEdit(Console, 1, 0, NULL); - return; - case VK_PRIOR: - /* Recall first history entry */ - LineInputRecallHistory(Console, ExeName, -((WORD)-1)); - return; - case VK_NEXT: - /* Recall last history entry */ - LineInputRecallHistory(Console, ExeName, +((WORD)-1)); - return; - case VK_UP: - case VK_F5: - /* Recall previous history entry. On first time, actually recall the - * current (usually last) entry; on subsequent times go back. */ - LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0); - Console->LineUpPressed = TRUE; - return; - case VK_DOWN: - /* Recall next history entry */ - LineInputRecallHistory(Console, ExeName, +1); - return; - case VK_F3: - /* Recall remainder of current history entry */ - HistoryGetCurrentEntry(Console, ExeName, &Entry); - if (Pos * sizeof(WCHAR) < Entry.Length) - { - UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos); - UINT DeleteSize = min(Console->LineSize - Pos, InsertSize); - LineInputEdit(Console, DeleteSize, InsertSize, &Entry.Buffer[Pos]); - } - return; - case VK_F6: - /* Insert a ^Z character */ - KeyEvent->uChar.UnicodeChar = 26; - break; - case VK_F7: - if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) - HistoryDeleteBuffer(HistoryCurrentBuffer(Console, ExeName)); - return; - case VK_F8: - /* Search for history entries starting with input. */ - Hist = HistoryCurrentBuffer(Console, ExeName); - if (!Hist || Hist->NumEntries == 0) return; - /* Like Up/F5, on first time start from current (usually last) entry, - * but on subsequent times start at previous entry. */ - if (Console->LineUpPressed) - Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1; - Console->LineUpPressed = TRUE; - - Entry.Length = Console->LinePos * sizeof(WCHAR); - Entry.Buffer = Console->LineBuffer; - - /* Keep going backwards, even wrapping around to the end, - * until we get back to starting point */ - HistPos = Hist->Position; - do + case VK_RIGHT: + case VK_F1: { - if (RtlPrefixUnicodeString(&Entry, &Hist->Entries[HistPos], FALSE)) + /* Move right. With CTRL, move to beginning of next word */ + if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) + { + while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++; + while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++; + LineInputSetPos(Console, Pos); + } + else + { + /* Recall one character (but don't overwrite current line) */ + HistoryGetCurrentEntry(Console, ExeName, &Entry); + if (Pos < Console->LineSize) + LineInputSetPos(Console, Pos + 1); + else if (Pos * sizeof(WCHAR) < Entry.Length) + LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]); + } + return; + } + + case VK_INSERT: + { + /* Toggle between insert and overstrike */ + Console->LineInsertToggle = !Console->LineInsertToggle; + TermSetCursorInfo(Console, Console->ActiveBuffer); + return; + } + + case VK_DELETE: + { + /* Remove character to right of cursor */ + if (Pos != Console->LineSize) + LineInputEdit(Console, 1, 0, NULL); + return; + } + + case VK_PRIOR: + { + /* Recall first history entry */ + LineInputRecallHistory(Console, ExeName, -((WORD)-1)); + return; + } + + case VK_NEXT: + { + /* Recall last history entry */ + LineInputRecallHistory(Console, ExeName, +((WORD)-1)); + return; + } + + case VK_UP: + case VK_F5: + { + /* + * Recall previous history entry. On first time, actually recall the + * current (usually last) entry; on subsequent times go back. + */ + LineInputRecallHistory(Console, ExeName, Console->LineUpPressed ? -1 : 0); + Console->LineUpPressed = TRUE; + return; + } + + case VK_DOWN: + { + /* Recall next history entry */ + LineInputRecallHistory(Console, ExeName, +1); + return; + } + + case VK_F3: + { + /* Recall remainder of current history entry */ + HistoryGetCurrentEntry(Console, ExeName, &Entry); + if (Pos * sizeof(WCHAR) < Entry.Length) + { + UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos); + UINT DeleteSize = min(Console->LineSize - Pos, InsertSize); + LineInputEdit(Console, DeleteSize, InsertSize, &Entry.Buffer[Pos]); + } + return; + } + + case VK_F6: + { + /* Insert a ^Z character */ + KeyEvent->uChar.UnicodeChar = 26; + break; + } + + case VK_F7: + { + if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) + HistoryDeleteCurrentBuffer(Console, ExeName); + else + { + if (Popup) DestroyPopupWindow(Popup); + Popup = HistoryDisplayCurrentHistory(Console, ExeName); + } + return; + } + + case VK_F8: + { + UNICODE_STRING EntryFound; + + Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR) + Entry.Buffer = Console->LineBuffer; + + if (HistoryFindEntryByPrefix(Console, ExeName, &Entry, &EntryFound)) { - Hist->Position = HistPos; LineInputEdit(Console, Console->LineSize - Pos, - Hist->Entries[HistPos].Length / sizeof(WCHAR) - Pos, - &Hist->Entries[HistPos].Buffer[Pos]); + EntryFound.Length / sizeof(WCHAR) - Pos, + &EntryFound.Buffer[Pos]); /* Cursor stays where it was */ LineInputSetPos(Console, Pos); - return; } - if (--HistPos < 0) HistPos += Hist->NumEntries; - } while (HistPos != Hist->Position); + + return; + } +#if 0 + { + PHISTORY_BUFFER Hist; + INT HistPos; + + /* Search for history entries starting with input. */ + Hist = HistoryCurrentBuffer(Console, ExeName); + if (!Hist || Hist->NumEntries == 0) return; + + /* + * Like Up/F5, on first time start from current (usually last) entry, + * but on subsequent times start at previous entry. + */ + if (Console->LineUpPressed) + Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1; + Console->LineUpPressed = TRUE; + + Entry.Length = Console->LinePos * sizeof(WCHAR); // == Pos * sizeof(WCHAR) + Entry.Buffer = Console->LineBuffer; + + /* + * Keep going backwards, even wrapping around to the end, + * until we get back to starting point. + */ + HistPos = Hist->Position; + do + { + if (RtlPrefixUnicodeString(&Entry, &Hist->Entries[HistPos], FALSE)) + { + Hist->Position = HistPos; + LineInputEdit(Console, Console->LineSize - Pos, + Hist->Entries[HistPos].Length / sizeof(WCHAR) - Pos, + &Hist->Entries[HistPos].Buffer[Pos]); + /* Cursor stays where it was */ + LineInputSetPos(Console, Pos); + return; + } + if (--HistPos < 0) HistPos += Hist->NumEntries; + } while (HistPos != Hist->Position); + + return; + } +#endif + return; } - if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT) + + /* + * OK, we deal with normal keys, we can continue... + */ + + if (KeyEvent->uChar.UnicodeChar == L'\b' && GetConsoleInputBufferMode(Console) & ENABLE_PROCESSED_INPUT) { /* backspace handling - if processed input enabled then we handle it here * otherwise we treat it like a normal char. */ @@ -452,32 +415,37 @@ LineInputKeyDown(PCONSRV_CONSOLE Console, } else if (KeyEvent->uChar.UnicodeChar == L'\r') { - HistoryAddEntry(Console, ExeName); + Entry.Length = Entry.MaximumLength = Console->LineSize * sizeof(WCHAR); + Entry.Buffer = Console->LineBuffer; + HistoryAddEntry(Console, ExeName, &Entry); /* TODO: Expand aliases */ + DPRINT1("TODO: Expand aliases\n"); LineInputSetPos(Console, Console->LineSize); Console->LineBuffer[Console->LineSize++] = L'\r'; - if (Console->InputBuffer.Mode & ENABLE_ECHO_INPUT) + if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT) { if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) { - ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\r", 1, TRUE); + TermWriteStream(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\r", 1, TRUE); } } - /* Add \n if processed input. There should usually be room for it, + /* + * Add \n if processed input. There should usually be room for it, * but an exception to the rule exists: the buffer could have been - * pre-filled with LineMaxSize - 1 characters. */ - if (Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && + * pre-filled with LineMaxSize - 1 characters. + */ + if (GetConsoleInputBufferMode(Console) & ENABLE_PROCESSED_INPUT && Console->LineSize < Console->LineMaxSize) { Console->LineBuffer[Console->LineSize++] = L'\n'; - if (Console->InputBuffer.Mode & ENABLE_ECHO_INPUT) + if (GetConsoleInputBufferMode(Console) & ENABLE_ECHO_INPUT) { if (GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) { - ConioWriteConsole(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\n", 1, TRUE); + TermWriteStream(Console, (PTEXTMODE_SCREEN_BUFFER)(Console->ActiveBuffer), L"\n", 1, TRUE); } } } @@ -499,6 +467,7 @@ LineInputKeyDown(PCONSRV_CONSOLE Console, { /* Normal character */ BOOL Overstrike = !Console->LineInsertToggle && (Console->LinePos != Console->LineSize); + DPRINT("Overstrike = %s\n", Overstrike ? "true" : "false"); LineInputEdit(Console, (Overstrike ? 1 : 0), 1, &KeyEvent->uChar.UnicodeChar); } } @@ -507,272 +476,4 @@ LineInputKeyDown(PCONSRV_CONSOLE Console, /* PUBLIC SERVER APIS *********************************************************/ -CSR_API(SrvGetConsoleCommandHistory) -{ - NTSTATUS Status; - PCONSOLE_GETCOMMANDHISTORY GetCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryRequest; - PCONSRV_CONSOLE Console; - ULONG BytesWritten = 0; - PHISTORY_BUFFER Hist; - - DPRINT1("SrvGetConsoleCommandHistory entered\n"); - - if ( !CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&GetCommandHistoryRequest->History, - GetCommandHistoryRequest->HistoryLength, - sizeof(BYTE)) || - !CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&GetCommandHistoryRequest->ExeName, - GetCommandHistoryRequest->ExeLength, - sizeof(BYTE)) ) - { - return STATUS_INVALID_PARAMETER; - } - - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(Status)) return Status; - - Hist = HistoryFindBuffer(Console, - GetCommandHistoryRequest->ExeName, - GetCommandHistoryRequest->ExeLength, - GetCommandHistoryRequest->Unicode2); - if (Hist) - { - UINT i; - - LPSTR TargetBufferA; - LPWSTR TargetBufferW; - ULONG BufferSize = GetCommandHistoryRequest->HistoryLength; - - UINT Offset = 0; - UINT SourceLength; - - if (GetCommandHistoryRequest->Unicode) - { - TargetBufferW = GetCommandHistoryRequest->History; - BufferSize /= sizeof(WCHAR); - } - else - { - TargetBufferA = GetCommandHistoryRequest->History; - } - - for (i = 0; i < Hist->NumEntries; i++) - { - SourceLength = Hist->Entries[i].Length / sizeof(WCHAR); - if (Offset + SourceLength + 1 > BufferSize) - { - Status = STATUS_BUFFER_OVERFLOW; - break; - } - - if (GetCommandHistoryRequest->Unicode) - { - RtlCopyMemory(&TargetBufferW[Offset], Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR)); - Offset += SourceLength; - TargetBufferW[Offset++] = L'\0'; - } - else - { - ConvertInputUnicodeToAnsi(Console, - Hist->Entries[i].Buffer, SourceLength * sizeof(WCHAR), - &TargetBufferA[Offset], SourceLength); - Offset += SourceLength; - TargetBufferA[Offset++] = '\0'; - } - } - - if (GetCommandHistoryRequest->Unicode) - BytesWritten = Offset * sizeof(WCHAR); - else - BytesWritten = Offset; - } - - // GetCommandHistoryRequest->HistoryLength = TargetBuffer - (PBYTE)GetCommandHistoryRequest->History; - GetCommandHistoryRequest->HistoryLength = BytesWritten; - - ConSrvReleaseConsole(Console, TRUE); - return Status; -} - -CSR_API(SrvGetConsoleCommandHistoryLength) -{ - NTSTATUS Status; - PCONSOLE_GETCOMMANDHISTORYLENGTH GetCommandHistoryLengthRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetCommandHistoryLengthRequest; - PCONSRV_CONSOLE Console; - PHISTORY_BUFFER Hist; - ULONG Length = 0; - UINT i; - - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&GetCommandHistoryLengthRequest->ExeName, - GetCommandHistoryLengthRequest->ExeLength, - sizeof(BYTE))) - { - return STATUS_INVALID_PARAMETER; - } - - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(Status)) return Status; - - Hist = HistoryFindBuffer(Console, - GetCommandHistoryLengthRequest->ExeName, - GetCommandHistoryLengthRequest->ExeLength, - GetCommandHistoryLengthRequest->Unicode2); - if (Hist) - { - for (i = 0; i < Hist->NumEntries; i++) - Length += Hist->Entries[i].Length + sizeof(WCHAR); // Each entry is returned NULL-terminated - } - /* - * Quick and dirty way of getting the number of bytes of the - * corresponding ANSI string from the one in UNICODE. - */ - if (!GetCommandHistoryLengthRequest->Unicode) - Length /= sizeof(WCHAR); - - GetCommandHistoryLengthRequest->HistoryLength = Length; - - ConSrvReleaseConsole(Console, TRUE); - return Status; -} - -CSR_API(SrvExpungeConsoleCommandHistory) -{ - NTSTATUS Status; - PCONSOLE_EXPUNGECOMMANDHISTORY ExpungeCommandHistoryRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ExpungeCommandHistoryRequest; - PCONSRV_CONSOLE Console; - PHISTORY_BUFFER Hist; - - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&ExpungeCommandHistoryRequest->ExeName, - ExpungeCommandHistoryRequest->ExeLength, - sizeof(BYTE))) - { - return STATUS_INVALID_PARAMETER; - } - - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(Status)) return Status; - - Hist = HistoryFindBuffer(Console, - ExpungeCommandHistoryRequest->ExeName, - ExpungeCommandHistoryRequest->ExeLength, - ExpungeCommandHistoryRequest->Unicode2); - HistoryDeleteBuffer(Hist); - - ConSrvReleaseConsole(Console, TRUE); - return Status; -} - -CSR_API(SrvSetConsoleNumberOfCommands) -{ - NTSTATUS Status; - PCONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryNumberCommandsRequest; - PCONSRV_CONSOLE Console; - PHISTORY_BUFFER Hist; - - if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&SetHistoryNumberCommandsRequest->ExeName, - SetHistoryNumberCommandsRequest->ExeLength, - sizeof(BYTE))) - { - return STATUS_INVALID_PARAMETER; - } - - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(Status)) return Status; - - Hist = HistoryFindBuffer(Console, - SetHistoryNumberCommandsRequest->ExeName, - SetHistoryNumberCommandsRequest->ExeLength, - SetHistoryNumberCommandsRequest->Unicode2); - if (Hist) - { - UINT MaxEntries = SetHistoryNumberCommandsRequest->NumCommands; - PUNICODE_STRING OldEntryList = Hist->Entries; - PUNICODE_STRING NewEntryList = ConsoleAllocHeap(0, MaxEntries * sizeof(UNICODE_STRING)); - if (!NewEntryList) - { - Status = STATUS_NO_MEMORY; - } - else - { - /* If necessary, shrink by removing oldest entries */ - for (; Hist->NumEntries > MaxEntries; Hist->NumEntries--) - { - RtlFreeUnicodeString(Hist->Entries++); - Hist->Position += (Hist->Position == 0); - } - - Hist->MaxEntries = MaxEntries; - Hist->Entries = memcpy(NewEntryList, Hist->Entries, - Hist->NumEntries * sizeof(UNICODE_STRING)); - ConsoleFreeHeap(OldEntryList); - } - } - - ConSrvReleaseConsole(Console, TRUE); - return Status; -} - -CSR_API(SrvGetConsoleHistory) -{ -#if 0 // Vista+ - PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest; - PCONSRV_CONSOLE Console; - NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (NT_SUCCESS(Status)) - { - HistoryInfoRequest->HistoryBufferSize = Console->HistoryBufferSize; - HistoryInfoRequest->NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; - HistoryInfoRequest->dwFlags = Console->HistoryNoDup; - ConSrvReleaseConsole(Console, TRUE); - } - return Status; -#else - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; -#endif -} - -CSR_API(SrvSetConsoleHistory) -{ -#if 0 // Vista+ - PCONSOLE_GETSETHISTORYINFO HistoryInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HistoryInfoRequest; - PCONSRV_CONSOLE Console; - NTSTATUS Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (NT_SUCCESS(Status)) - { - Console->HistoryBufferSize = HistoryInfoRequest->HistoryBufferSize; - Console->NumberOfHistoryBuffers = HistoryInfoRequest->NumberOfHistoryBuffers; - Console->HistoryNoDup = HistoryInfoRequest->dwFlags & HISTORY_NO_DUP_FLAG; - ConSrvReleaseConsole(Console, TRUE); - } - return Status; -#else - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; -#endif -} - -CSR_API(SrvSetConsoleCommandHistoryMode) -{ - NTSTATUS Status; - PCONSOLE_SETHISTORYMODE SetHistoryModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHistoryModeRequest; - PCONSRV_CONSOLE Console; - - DPRINT1("SrvSetConsoleCommandHistoryMode(Mode = %d) is not yet implemented\n", - SetHistoryModeRequest->Mode); - - Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if (!NT_SUCCESS(Status)) return Status; - - /* This API is not yet implemented */ - Status = STATUS_NOT_IMPLEMENTED; - - ConSrvReleaseConsole(Console, TRUE); - return Status; -} - /* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/lineinput.h b/reactos/win32ss/user/winsrv/consrv/lineinput.h index 55511a0f758..c26a33a34ca 100644 --- a/reactos/win32ss/user/winsrv/consrv/lineinput.h +++ b/reactos/win32ss/user/winsrv/consrv/lineinput.h @@ -1,15 +1,13 @@ /* * LICENSE: GPL - See COPYING in the top level directory * PROJECT: ReactOS Console Server DLL - * FILE: win32ss/user/winsrv/consrv/lineinput.c + * FILE: win32ss/user/winsrv/consrv/lineinput.h * PURPOSE: Console line input functions * PROGRAMMERS: Jeffrey Morlan */ #pragma once -VOID HistoryDeleteBuffers(PCONSRV_CONSOLE Console); - VOID LineInputKeyDown(PCONSRV_CONSOLE Console, PUNICODE_STRING ExeName, diff --git a/reactos/win32ss/user/winsrv/consrv/popup.c b/reactos/win32ss/user/winsrv/consrv/popup.c new file mode 100644 index 00000000000..98751e5b391 --- /dev/null +++ b/reactos/win32ss/user/winsrv/consrv/popup.c @@ -0,0 +1,251 @@ +/* + * LICENSE: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: win32ss/user/winsrv/consrv/popup.c + * PURPOSE: Console popup windows + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + * + * NOTE: Strongly inspired by the DrawBox function + * from base/setup/usetup/interface/usetup.c, written by: + * Eric Kohl (revision 3753) + * Herv Poussineau (revision 24718) + * and *UiDisplayMenu from FreeLdr. + */ + +/* INCLUDES *******************************************************************/ + +#include "consrv.h" +#include "popup.h" + +#define NDEBUG +#include + + +/* PRIVATE FUNCTIONS **********************************************************/ + +NTSTATUS NTAPI +ConDrvFillConsoleOutput(IN PCONSOLE Console, + IN PTEXTMODE_SCREEN_BUFFER Buffer, + IN CODE_TYPE CodeType, + IN CODE_ELEMENT Code, + IN ULONG NumCodesToWrite, + IN PCOORD WriteCoord, + OUT PULONG NumCodesWritten OPTIONAL); +NTSTATUS NTAPI +ConDrvReadConsoleOutput(IN PCONSOLE Console, + IN PTEXTMODE_SCREEN_BUFFER Buffer, + IN BOOLEAN Unicode, + OUT PCHAR_INFO CharInfo/*Buffer*/, + IN OUT PSMALL_RECT ReadRegion); +NTSTATUS NTAPI +ConDrvWriteConsoleOutput(IN PCONSOLE Console, + IN PTEXTMODE_SCREEN_BUFFER Buffer, + IN BOOLEAN Unicode, + IN PCHAR_INFO CharInfo/*Buffer*/, + IN OUT PSMALL_RECT WriteRegion); + + +static VOID +DrawBox(PTEXTMODE_SCREEN_BUFFER Buffer, + IN SHORT xLeft, + IN SHORT yTop, + IN SHORT Width, + IN SHORT Height) +{ + COORD coPos; + DWORD Written; + + /* Set screen attributes */ + coPos.X = xLeft; + for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++) + { + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ATTRIBUTE, + (CODE_ELEMENT)(WORD)Buffer->PopupDefaultAttrib, + Width, + &coPos, + &Written); + } + + /* draw upper left corner */ + coPos.X = xLeft; + coPos.Y = yTop; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)0xDA, // '+', + 1, + &coPos, + &Written); + + /* draw upper edge */ + coPos.X = xLeft + 1; + coPos.Y = yTop; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)0xC4, // '-', + Width - 2, + &coPos, + &Written); + + /* draw upper right corner */ + coPos.X = xLeft + Width - 1; + coPos.Y = yTop; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)0xBF, // '+', + 1, + &coPos, + &Written); + + /* Draw right edge, inner space and left edge */ + for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++) + { + coPos.X = xLeft; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)0xB3, // '|', + 1, + &coPos, + &Written); + + coPos.X = xLeft + 1; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)' ', + Width - 2, + &coPos, + &Written); + + coPos.X = xLeft + Width - 1; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)0xB3, // '|', + 1, + &coPos, + &Written); + } + + /* draw lower left corner */ + coPos.X = xLeft; + coPos.Y = yTop + Height - 1; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)0xC0, // '+', + 1, + &coPos, + &Written); + + /* draw lower edge */ + coPos.X = xLeft + 1; + coPos.Y = yTop + Height - 1; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)0xC4, // '-', + Width - 2, + &coPos, + &Written); + + /* draw lower right corner */ + coPos.X = xLeft + Width - 1; + coPos.Y = yTop + Height - 1; + ConDrvFillConsoleOutput(Buffer->Header.Console, + Buffer, + CODE_ASCII, + (CODE_ELEMENT)(CHAR)0xD9, // '+', + 1, + &coPos, + &Written); +} + + +/* PUBLIC FUNCTIONS ***********************************************************/ + +PPOPUP_WINDOW +CreatePopupWindow(PCONSRV_CONSOLE Console, + PTEXTMODE_SCREEN_BUFFER Buffer, + SHORT xLeft, + SHORT yTop, + SHORT Width, + SHORT Height) +{ + PPOPUP_WINDOW Popup; + SMALL_RECT Region; + + ASSERT((PCONSOLE)Console == Buffer->Header.Console); + + /* Create the popup window */ + Popup = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*Popup)); + if (Popup == NULL) return NULL; + + Popup->ScreenBuffer = Buffer; + Popup->Origin.X = xLeft; + Popup->Origin.Y = yTop; + Popup->Size.X = Width; + Popup->Size.Y = Height; + + /* Save old contents */ + Popup->OldContents = ConsoleAllocHeap(HEAP_ZERO_MEMORY, + Popup->Size.X * Popup->Size.Y * + sizeof(*Popup->OldContents)); + if (Popup->OldContents == NULL) + { + ConsoleFreeHeap(Popup); + return NULL; + } + Region.Left = Popup->Origin.X; + Region.Top = Popup->Origin.Y; + Region.Right = Popup->Origin.X + Popup->Size.X - 1; + Region.Bottom = Popup->Origin.Y + Popup->Size.Y - 1; + ConDrvReadConsoleOutput(Buffer->Header.Console, + Buffer, + TRUE, + Popup->OldContents, + &Region); + + /* Draw it */ + DrawBox(Buffer, + xLeft, yTop, + Width, Height); + + /* Add it into the list of popups */ + InsertTailList(&Console->PopupWindows, &Popup->ListEntry); + + return Popup; +} + +VOID +DestroyPopupWindow(PPOPUP_WINDOW Popup) +{ + SMALL_RECT Region; + + if (Popup == NULL) return; + + /* Remove it from the list of popups */ + RemoveEntryList(&Popup->ListEntry); + + /* Restore the old screen-buffer contents */ + Region.Left = Popup->Origin.X; + Region.Top = Popup->Origin.Y; + Region.Right = Popup->Origin.X + Popup->Size.X - 1; + Region.Bottom = Popup->Origin.Y + Popup->Size.Y - 1; + ConDrvWriteConsoleOutput(Popup->ScreenBuffer->Header.Console, + Popup->ScreenBuffer, + TRUE, + Popup->OldContents, + &Region); + + /* Free memory */ + ConsoleFreeHeap(Popup->OldContents); + ConsoleFreeHeap(Popup); +} + +/* EOF */ diff --git a/reactos/win32ss/user/winsrv/consrv/popup.h b/reactos/win32ss/user/winsrv/consrv/popup.h new file mode 100644 index 00000000000..a103d158830 --- /dev/null +++ b/reactos/win32ss/user/winsrv/consrv/popup.h @@ -0,0 +1,37 @@ +/* + * LICENSE: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: win32ss/user/winsrv/consrv/popup.h + * PURPOSE: Console popup windows + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#pragma once + +typedef +VOID +(NTAPI *PPOPUP_INPUT_ROUTINE)(VOID); + +typedef struct _POPUP_WINDOW +{ + LIST_ENTRY ListEntry; /* Entry in console's list of popups */ + PTEXTMODE_SCREEN_BUFFER ScreenBuffer; /* Associated screen-buffer */ + + // SMALL_RECT Region; /* The region the popup occupies */ + COORD Origin; /* Origin of the popup window */ + COORD Size; /* Size of the popup window */ + + PCHAR_INFO OldContents; /* The data under the popup window */ + PPOPUP_INPUT_ROUTINE PopupInputRoutine; /* Routine called when input is received */ +} POPUP_WINDOW, *PPOPUP_WINDOW; + + +PPOPUP_WINDOW +CreatePopupWindow(PCONSRV_CONSOLE Console, + PTEXTMODE_SCREEN_BUFFER Buffer, + SHORT xLeft, + SHORT yTop, + SHORT Width, + SHORT Height); +VOID +DestroyPopupWindow(PPOPUP_WINDOW Popup); diff --git a/reactos/win32ss/user/winsrv/consrv/procinit.h b/reactos/win32ss/user/winsrv/consrv/procinit.h index 493415156eb..cbc0d6b002b 100644 --- a/reactos/win32ss/user/winsrv/consrv/procinit.h +++ b/reactos/win32ss/user/winsrv/consrv/procinit.h @@ -9,14 +9,14 @@ #pragma once NTSTATUS ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, - PHANDLE pInputHandle, - PHANDLE pOutputHandle, - PHANDLE pErrorHandle, - PCONSOLE_START_INFO ConsoleStartInfo); + PHANDLE pInputHandle, + PHANDLE pOutputHandle, + PHANDLE pErrorHandle, + PCONSOLE_INIT_INFO ConsoleInitInfo); NTSTATUS ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData, - HANDLE ConsoleHandle, - BOOLEAN CreateNewHandlesTable, - PHANDLE pInputHandle, - PHANDLE pOutputHandle, - PHANDLE pErrorHandle); + HANDLE ConsoleHandle, + BOOLEAN CreateNewHandlesTable, + PHANDLE pInputHandle, + PHANDLE pOutputHandle, + PHANDLE pErrorHandle); VOID ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData); diff --git a/reactos/win32ss/user/winsrv/consrv/settings.c b/reactos/win32ss/user/winsrv/consrv/settings.c index 7373f04401c..0e75955ab58 100644 --- a/reactos/win32ss/user/winsrv/consrv/settings.c +++ b/reactos/win32ss/user/winsrv/consrv/settings.c @@ -404,7 +404,7 @@ ConSrvGetDefaultSettings(IN OUT PCONSOLE_INFO ConsoleInfo, ConsoleInfo->QuickEdit = FALSE; ConsoleInfo->InsertMode = TRUE; - // ConsoleInfo->InputBufferSize; + // ConsoleInfo->InputBufferSize = 0; // Rule: ScreenBufferSize >= ConsoleSize ConsoleInfo->ScreenBufferSize.X = 80;