diff --git a/contrib/win32/win32compat/shell-host.c b/contrib/win32/win32compat/shell-host.c index 7e184afa1..cd4de126a 100644 --- a/contrib/win32/win32compat/shell-host.c +++ b/contrib/win32/win32compat/shell-host.c @@ -1,36 +1,37 @@ /* -* Author: Manoj Ampalam -* Primitive shell-host to support parsing of cmd.exe input and async IO redirection -* -* Author: Ray Heyes -* PTY with ANSI emulation wrapper -* -* Copyright (c) 2015 Microsoft Corp. -* All rights reserved -* -* Microsoft openssh win32 port -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Author: Manoj Ampalam + * Primitive shell-host to support parsing of cmd.exe input and async IO redirection + * + * Author: Ray Heyes + * PTY with ANSI emulation wrapper + * + * Copyright (c) 2017 Microsoft Corp. + * All rights reserved + * + * Shell-host is responsible for handling all the interactive and non-interactive cmds. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include #include @@ -51,47 +52,45 @@ #define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 #endif -typedef BOOL (WINAPI *__t_SetCurrentConsoleFontEx)( - _In_ HANDLE hConsoleOutput, - _In_ BOOL bMaximumWindow, - _In_ PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx - ); +typedef BOOL(WINAPI *__t_SetCurrentConsoleFontEx)( + _In_ HANDLE hConsoleOutput, + _In_ BOOL bMaximumWindow, + _In_ PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx + ); __t_SetCurrentConsoleFontEx __SetCurrentConsoleFontEx; -typedef BOOL (WINAPI *__t_UnhookWinEvent)( - _In_ HWINEVENTHOOK hWinEventHook - ); +typedef BOOL(WINAPI *__t_UnhookWinEvent)( + _In_ HWINEVENTHOOK hWinEventHook + ); __t_UnhookWinEvent __UnhookWinEvent; -typedef HWINEVENTHOOK (WINAPI *__t_SetWinEventHook)( - _In_ UINT eventMin, - _In_ UINT eventMax, - _In_ HMODULE hmodWinEventProc, - _In_ WINEVENTPROC lpfnWinEventProc, - _In_ DWORD idProcess, - _In_ DWORD idThread, - _In_ UINT dwflags - ); +typedef HWINEVENTHOOK(WINAPI *__t_SetWinEventHook)( + _In_ UINT eventMin, + _In_ UINT eventMax, + _In_ HMODULE hmodWinEventProc, + _In_ WINEVENTPROC lpfnWinEventProc, + _In_ DWORD idProcess, + _In_ DWORD idThread, + _In_ UINT dwflags + ); __t_SetWinEventHook __SetWinEventHook; - typedef struct consoleEvent { - DWORD event; - HWND hwnd; - LONG idObject; - LONG idChild; - void* prior; - void* next; + DWORD event; + HWND hwnd; + LONG idObject; + LONG idChild; + void* prior; + void* next; } consoleEvent; -struct key_translation -{ - char incoming[5]; - int vk; - char outgoing[1]; +struct key_translation { + char incoming[5]; + int vk; + char outgoing[1]; } key_translation; -struct key_translation keys[] = { +struct key_translation keys[] = { { "\x1b", VK_ESCAPE, "\x1b" }, { "\r", VK_RETURN, "\r" }, { "\b", VK_BACK, "\b" }, @@ -171,1143 +170,1005 @@ CONSOLE_SCREEN_BUFFER_INFOEX consoleInfo; CONSOLE_SCREEN_BUFFER_INFOEX nextConsoleInfo; STARTUPINFO inputSi; -#define GOTO_CLEANUP_ON_FALSE(exp) do { \ - ret = (exp); \ - if (ret == FALSE) \ - goto cleanup; \ -} while(0) \ +#define GOTO_CLEANUP_ON_FALSE(exp) do { \ + ret = (exp); \ + if (ret == FALSE) \ + goto cleanup; \ +} while(0) -#define GOTO_CLEANUP_ON_ERR(exp) do { \ - if ((exp) != 0) \ - goto cleanup; \ -} while(0) \ +#define GOTO_CLEANUP_ON_ERR(exp) do { \ + if ((exp) != 0) \ + goto cleanup; \ +} while(0) -// Console keystroke handling -void SendKeyStroke(HANDLE hInput, int keyStroke, char character) +/* + * This function will handle the console keystrokes. + */ +void +SendKeyStroke(HANDLE hInput, int keyStroke, char character) { - DWORD wr = 0; - INPUT_RECORD ir; + DWORD wr = 0; + INPUT_RECORD ir; - ir.EventType = KEY_EVENT; - ir.Event.KeyEvent.bKeyDown = TRUE; - ir.Event.KeyEvent.wRepeatCount = 1; - ir.Event.KeyEvent.wVirtualKeyCode = keyStroke; - ir.Event.KeyEvent.wVirtualScanCode = 0; - ir.Event.KeyEvent.dwControlKeyState = 0; - ir.Event.KeyEvent.uChar.UnicodeChar = 0; - if(character != 0) - ir.Event.KeyEvent.uChar.AsciiChar = character; + ir.EventType = KEY_EVENT; + ir.Event.KeyEvent.bKeyDown = TRUE; + ir.Event.KeyEvent.wRepeatCount = 1; + ir.Event.KeyEvent.wVirtualKeyCode = keyStroke; + ir.Event.KeyEvent.wVirtualScanCode = 0; + ir.Event.KeyEvent.dwControlKeyState = 0; + ir.Event.KeyEvent.uChar.UnicodeChar = 0; + if (character != 0) + ir.Event.KeyEvent.uChar.AsciiChar = character; - WriteConsoleInputA(hInput, &ir, 1, &wr); + WriteConsoleInputA(hInput, &ir, 1, &wr); - ir.Event.KeyEvent.bKeyDown = FALSE; - WriteConsoleInputA(hInput, &ir, 1, &wr); + ir.Event.KeyEvent.bKeyDown = FALSE; + WriteConsoleInputA(hInput, &ir, 1, &wr); } -void ProcessIncomingKeys(char * ansikey) { - int nKey = 0; - int index = ARRAYSIZE(keys); +void +ProcessIncomingKeys(char * ansikey) { + int nKey = 0; + int index = ARRAYSIZE(keys); - while (nKey < index) { - if (strcmp(ansikey, keys[nKey].incoming) == 0) { - SendKeyStroke(child_in, keys[nKey].vk, keys[nKey].outgoing[0]); - break; - } - else - nKey++; - } + while (nKey < index) { + if (strcmp(ansikey, keys[nKey].incoming) == 0) { + SendKeyStroke(child_in, keys[nKey].vk, keys[nKey].outgoing[0]); + break; + } + else + nKey++; + } - if (nKey == index) { - SendKeyStroke(child_in, 0, ansikey[0]); - } + if (nKey == index) + SendKeyStroke(child_in, 0, ansikey[0]); } -// VT output routines -void SendLF(HANDLE hInput) { - DWORD wr = 0; +/* + * VT output routines + */ +void +SendLF(HANDLE hInput) { + DWORD wr = 0; - if (bUseAnsiEmulation) - WriteFile(hInput, "\n", 1, &wr, NULL); + if (bUseAnsiEmulation) + WriteFile(hInput, "\n", 1, &wr, NULL); } -void SendClearScreen(HANDLE hInput) { - DWORD wr = 0; +void +SendClearScreen(HANDLE hInput) { + DWORD wr = 0; - if (bUseAnsiEmulation) - WriteFile(hInput, "\033[2J", 4, &wr, NULL); + if (bUseAnsiEmulation) + WriteFile(hInput, "\033[2J", 4, &wr, NULL); } -void SendClearScreenFromCursor(HANDLE hInput) { - DWORD wr = 0; +void +SendClearScreenFromCursor(HANDLE hInput) { + DWORD wr = 0; - if (bUseAnsiEmulation) - WriteFile(hInput, "\033[1J", 4, &wr, NULL); + if (bUseAnsiEmulation) + WriteFile(hInput, "\033[1J", 4, &wr, NULL); } -void SendHideCursor(HANDLE hInput) { - DWORD wr = 0; +void +SendHideCursor(HANDLE hInput) { + DWORD wr = 0; - if (bUseAnsiEmulation) - WriteFile(hInput, "\033[?25l", 6, &wr, NULL); + if (bUseAnsiEmulation) + WriteFile(hInput, "\033[?25l", 6, &wr, NULL); } -void SendShowCursor(HANDLE hInput) { - DWORD wr = 0; +void +SendShowCursor(HANDLE hInput) { + DWORD wr = 0; - if (bUseAnsiEmulation) - WriteFile(hInput, "\033[?25h", 6, &wr, NULL); + if (bUseAnsiEmulation) + WriteFile(hInput, "\033[?25h", 6, &wr, NULL); } -void SendCursorPositionRequest(HANDLE hInput) { - DWORD wr = 0; +void +SendCursorPositionRequest(HANDLE hInput) { + DWORD wr = 0; - if (bUseAnsiEmulation) - WriteFile(hInput, "\033[6n", 4, &wr, NULL); + if (bUseAnsiEmulation) + WriteFile(hInput, "\033[6n", 4, &wr, NULL); } -void SendSetCursor(HANDLE hInput, int X, int Y) { +void +SendSetCursor(HANDLE hInput, int X, int Y) { + DWORD wr = 0; + DWORD out = 0; + char formatted_output[255]; - DWORD wr = 0; - DWORD out = 0; - - char formatted_output[255]; - - out = _snprintf_s(formatted_output, sizeof(formatted_output), _TRUNCATE, "\033[%d;%dH", Y, X); - if (bUseAnsiEmulation) - WriteFile(hInput, formatted_output, out, &wr, NULL); + out = _snprintf_s(formatted_output, sizeof(formatted_output), _TRUNCATE, "\033[%d;%dH", Y, X); + if (bUseAnsiEmulation) + WriteFile(hInput, formatted_output, out, &wr, NULL); } -void SendVerticalScroll(HANDLE hInput, int lines) { +void +SendVerticalScroll(HANDLE hInput, int lines) { + DWORD wr = 0; + DWORD out = 0; + char formatted_output[255]; - DWORD wr = 0; - DWORD out = 0; - char formatted_output[255]; + LONG vn = abs(lines); + /* Not supporting the [S at the moment. */ + if (lines > 0) { + out = snprintf(formatted_output, sizeof(formatted_output), "\033[%dT", vn); - LONG vn = abs(lines); - - if (lines > 0) { - - out = snprintf(formatted_output, sizeof(formatted_output), "\033[%dT", vn); - - if (bUseAnsiEmulation) - WriteFile(hInput, formatted_output, out, &wr, NULL); - } - // Not supporting the [S at the moment. + if (bUseAnsiEmulation) + WriteFile(hInput, formatted_output, out, &wr, NULL); + } } -void SendHorizontalScroll(HANDLE hInput, int cells) { +void +SendHorizontalScroll(HANDLE hInput, int cells) { + DWORD wr = 0; + DWORD out = 0; + char formatted_output[255]; - DWORD wr = 0; - DWORD out = 0; - char formatted_output[255]; + out = snprintf(formatted_output, sizeof(formatted_output), "\033[%dG", cells); - out = snprintf(formatted_output, sizeof(formatted_output), "\033[%dG", cells); - - if (bUseAnsiEmulation) - WriteFile(hInput, formatted_output, out, &wr, NULL); + if (bUseAnsiEmulation) + WriteFile(hInput, formatted_output, out, &wr, NULL); } -void SendCharacter(HANDLE hInput, WORD attributes, wchar_t character) { - - DWORD wr = 0; - DWORD out = 0; - DWORD current = 0; - - char formatted_output[2048]; - - static WORD pattributes = 0; - - USHORT Color = 0; +void +SendCharacter(HANDLE hInput, WORD attributes, wchar_t character) { + DWORD wr = 0; + DWORD out = 0; + DWORD current = 0; + char formatted_output[2048]; + static WORD pattributes = 0; + USHORT Color = 0; ULONG Status = 0; - PSTR Next; - size_t SizeLeft; + size_t SizeLeft; - if (!character) - return; + if (!character) + return; - Next = formatted_output; - SizeLeft = sizeof formatted_output; + Next = formatted_output; + SizeLeft = sizeof formatted_output; - // - // Handle the foreground intensity - // - if ((attributes & FOREGROUND_INTENSITY) != 0) { + /* Handle the foreground intensity */ + if ((attributes & FOREGROUND_INTENSITY) != 0) Color = 1; - } - else { + else Color = 0; - } StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, "\033[%u", Color); - // - // Handle the background intensity - // - if ((attributes & BACKGROUND_INTENSITY) != 0) { - Color = 1; - } - else { - Color = 39; - } - - StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color); - - // - // Handle the underline - // - if ((attributes & COMMON_LVB_UNDERSCORE) != 0) { - Color = 4; - } - else { - Color = 24; - } - - StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color); - - // - // Handle reverse video - // - if ((attributes & COMMON_LVB_REVERSE_VIDEO) != 0) { - Color = 7; - } - else { - Color = 27; - } - - StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color); - - // - // Add background and foreground colors to buffer. - // - Color = 30 + - 4 * ((attributes & FOREGROUND_BLUE) != 0) + - 2 * ((attributes & FOREGROUND_GREEN) != 0) + - 1 * ((attributes & FOREGROUND_RED) != 0); + /* Handle the background intensity */ + if ((attributes & BACKGROUND_INTENSITY) != 0) + Color = 1; + else + Color = 39; StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color); - Color = 40 + - 4 * ((attributes & BACKGROUND_BLUE) != 0) + - 2 * ((attributes & BACKGROUND_GREEN) != 0) + - 1 * ((attributes & BACKGROUND_RED) != 0); + /* Handle the underline */ + if ((attributes & COMMON_LVB_UNDERSCORE) != 0) + Color = 4; + else + Color = 24; + + StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color); + + /* Handle reverse video */ + if ((attributes & COMMON_LVB_REVERSE_VIDEO) != 0) + Color = 7; + else + Color = 27; + + StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color); + + /* Add background and foreground colors to buffer. */ + Color = 30 + + 4 * ((attributes & FOREGROUND_BLUE) != 0) + + 2 * ((attributes & FOREGROUND_GREEN) != 0) + + 1 * ((attributes & FOREGROUND_RED) != 0); + + StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color); + + Color = 40 + + 4 * ((attributes & BACKGROUND_BLUE) != 0) + + 2 * ((attributes & BACKGROUND_GREEN) != 0) + + 1 * ((attributes & BACKGROUND_RED) != 0); StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color); StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, "m", Color); - if (bUseAnsiEmulation && attributes != pattributes) - WriteFile(hInput, formatted_output, (Next - formatted_output), &wr, NULL); + if (bUseAnsiEmulation && attributes != pattributes) + WriteFile(hInput, formatted_output, (Next - formatted_output), &wr, NULL); - // East asian languages have 2 bytes for each character, only use the first - if (!(attributes & COMMON_LVB_TRAILING_BYTE)) - { - int nSize = WideCharToMultiByte(CP_UTF8, - 0, - &character, - 1, - Next, - 10, - NULL, - NULL); + /* East asian languages have 2 bytes for each character, only use the first */ + if (!(attributes & COMMON_LVB_TRAILING_BYTE)) { + int nSize = WideCharToMultiByte(CP_UTF8, + 0, + &character, + 1, + Next, + 10, + NULL, + NULL); - if(nSize > 0) - WriteFile(hInput, Next, nSize, &wr, NULL); - } + if (nSize > 0) + WriteFile(hInput, Next, nSize, &wr, NULL); + } - pattributes = attributes; + pattributes = attributes; } -void SendBuffer(HANDLE hInput, CHAR_INFO *buffer, DWORD bufferSize) { - - if (bufferSize <= 0) - return; +void +SendBuffer(HANDLE hInput, CHAR_INFO *buffer, DWORD bufferSize) { + if (bufferSize <= 0) + return; - for (DWORD i = 0; i < bufferSize; i++) - { - SendCharacter(hInput, buffer[i].Attributes, buffer[i].Char.UnicodeChar); - } + for (DWORD i = 0; i < bufferSize; i++) + SendCharacter(hInput, buffer[i].Attributes, buffer[i].Char.UnicodeChar); } -void CalculateAndSetCursor(HANDLE hInput, UINT aboveTopLine, UINT viewPortHeight, UINT x, UINT y) { +void +CalculateAndSetCursor(HANDLE hInput, UINT aboveTopLine, UINT viewPortHeight, UINT x, UINT y) { - SendSetCursor(pipe_out, x + 1, y + 1); - currentLine = y; + SendSetCursor(pipe_out, x + 1, y + 1); + currentLine = y; } -void SizeWindow(HANDLE hInput) { +void +SizeWindow(HANDLE hInput) { + SMALL_RECT srWindowRect; + COORD coordScreen; + BOOL bSuccess = FALSE; + /* The input window does not scroll currently to ease calculations on the paint/draw */ + bNoScrollRegion = TRUE; - SMALL_RECT srWindowRect; - COORD coordScreen; - BOOL bSuccess = FALSE; + /* Set the default font to Consolas */ + CONSOLE_FONT_INFOEX matchingFont; + matchingFont.cbSize = sizeof(matchingFont); + matchingFont.nFont = 0; + matchingFont.dwFontSize.X = 0; + matchingFont.dwFontSize.Y = 16; + matchingFont.FontFamily = FF_DONTCARE; + matchingFont.FontWeight = FW_NORMAL; + wcscpy(matchingFont.FaceName, L"Consolas"); - // The input window does not scroll currently to ease calculations - // on the paint/draw. - bNoScrollRegion = TRUE; + bSuccess = __SetCurrentConsoleFontEx(child_out, FALSE, &matchingFont); - // Set the default font to Consolas - CONSOLE_FONT_INFOEX matchingFont; - matchingFont.cbSize = sizeof(matchingFont); - matchingFont.nFont = 0; - matchingFont.dwFontSize.X = 0; - matchingFont.dwFontSize.Y = 16; - matchingFont.FontFamily = FF_DONTCARE; - matchingFont.FontWeight = FW_NORMAL; - wcscpy(matchingFont.FaceName, L"Consolas"); + /* This information is the live screen */ + ZeroMemory(&consoleInfo, sizeof(consoleInfo)); + consoleInfo.cbSize = sizeof(consoleInfo); - bSuccess = __SetCurrentConsoleFontEx(child_out, FALSE, &matchingFont); + bSuccess = GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); - // This information is the live screen - ZeroMemory(&consoleInfo, sizeof(consoleInfo)); - consoleInfo.cbSize = sizeof(consoleInfo); + /* Get the largest size we can size the console window to */ + coordScreen = GetLargestConsoleWindowSize(child_out); - bSuccess = GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); + /* Define the new console window size and scroll position */ + if (inputSi.dwXCountChars == 0 || inputSi.dwYCountChars == 0) { + inputSi.dwXCountChars = 80; + inputSi.dwYCountChars = 25; + } - // Get the largest size we can size the console window to. - coordScreen = GetLargestConsoleWindowSize(child_out); + srWindowRect.Right = (SHORT)(min(inputSi.dwXCountChars, coordScreen.X) - 1); + srWindowRect.Bottom = (SHORT)(min(inputSi.dwYCountChars, coordScreen.Y) - 1); + srWindowRect.Left = srWindowRect.Top = (SHORT)0; - // Define the new console window size and scroll position. - if (inputSi.dwXCountChars == 0 || inputSi.dwYCountChars == 0) { - inputSi.dwXCountChars = 80; - inputSi.dwYCountChars = 25; - } + /* Define the new console buffer size to be the maximum possible */ + coordScreen.X = 100; + coordScreen.Y = 9999; - srWindowRect.Right = (SHORT)(min(inputSi.dwXCountChars, coordScreen.X) - 1); - srWindowRect.Bottom = (SHORT)(min(inputSi.dwYCountChars, coordScreen.Y) - 1); - srWindowRect.Left = srWindowRect.Top = (SHORT)0; + if (SetConsoleWindowInfo(child_out, TRUE, &srWindowRect)) + bSuccess = SetConsoleScreenBufferSize(child_out, coordScreen); + else { + if (SetConsoleScreenBufferSize(child_out, coordScreen)) + bSuccess = SetConsoleWindowInfo(child_out, TRUE, &srWindowRect); + } - /// Define the new console buffer size to be the maximum possible. - coordScreen.X = 100; - coordScreen.Y = 9999; - - if (SetConsoleWindowInfo(child_out, TRUE, &srWindowRect)) { - - bSuccess = SetConsoleScreenBufferSize(child_out, coordScreen); - } - else { - if (SetConsoleScreenBufferSize(child_out, coordScreen)) { - - bSuccess = SetConsoleWindowInfo(child_out, TRUE, &srWindowRect); - } - - } - - bSuccess = GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); + bSuccess = GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); } -// End of VT output routines - -DWORD WINAPI MonitorChild(_In_ LPVOID lpParameter) { - WaitForSingleObject(child, INFINITE); - GetExitCodeProcess(child, &child_exit_code); - PostThreadMessage(hostThreadId, WM_APPEXIT, 0, 0); - return 0; +DWORD WINAPI +MonitorChild(_In_ LPVOID lpParameter) { + WaitForSingleObject(child, INFINITE); + GetExitCodeProcess(child, &child_exit_code); + PostThreadMessage(hostThreadId, WM_APPEXIT, 0, 0); + return 0; } -DWORD ProcessEvent(void *p) { +DWORD +ProcessEvent(void *p) { + char f[255]; + wchar_t chUpdate; + WORD wAttributes; + WORD wX; + WORD wY; + DWORD dwProcessId; + DWORD wr = 0; + DWORD dwMode; + DWORD event; + HWND hwnd; + LONG idObject; + LONG idChild; - char f[255]; - wchar_t chUpdate; + if (!p) + return ERROR_INVALID_PARAMETER; - WORD wAttributes; - WORD wX; - WORD wY; + consoleEvent* current = (consoleEvent *)p; - DWORD dwProcessId; - DWORD wr = 0; - DWORD dwMode; + if (current) { + event = current->event; + hwnd = current->hwnd; + idObject = current->idObject; + idChild = current->idChild; + } else + return ERROR_INVALID_PARAMETER; - DWORD event; - HWND hwnd; - LONG idObject; - LONG idChild; + if (event < EVENT_CONSOLE_CARET || event > EVENT_CONSOLE_LAYOUT) + return ERROR_INVALID_PARAMETER; - if (!p) - { - return ERROR_INVALID_PARAMETER; - } + if (child_out == INVALID_HANDLE_VALUE || child_out == NULL) + return ERROR_INVALID_PARAMETER; - consoleEvent* current = (consoleEvent *)p; + GetWindowThreadProcessId(hwnd, &dwProcessId); - if(current) { - event = current->event; - hwnd = current->hwnd; - idObject = current->idObject; - idChild = current->idChild; - } - else { - return ERROR_INVALID_PARAMETER; - } + if (childProcessId != dwProcessId) + return ERROR_SUCCESS; - if (event < EVENT_CONSOLE_CARET || event > EVENT_CONSOLE_LAYOUT) - { - return ERROR_INVALID_PARAMETER; - } + ZeroMemory(&consoleInfo, sizeof(consoleInfo)); + consoleInfo.cbSize = sizeof(consoleInfo); - if (child_out == INVALID_HANDLE_VALUE || child_out == NULL) - { - return ERROR_INVALID_PARAMETER; - } + GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); - GetWindowThreadProcessId(hwnd, &dwProcessId); + UINT viewPortHeight = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1; + UINT viewPortWidth = consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1; - if (childProcessId != dwProcessId) - { - return ERROR_SUCCESS; - } + switch (event) { + case EVENT_CONSOLE_CARET: + { + COORD co; + + if (idObject == CONSOLE_CARET_SELECTION) { + co.X = HIWORD(idChild); + co.Y = LOWORD(idChild); + } else { + co.X = HIWORD(idChild); + co.Y = LOWORD(idChild); + } - ZeroMemory(&consoleInfo, sizeof(consoleInfo)); - consoleInfo.cbSize = sizeof(consoleInfo); + break; + } + case EVENT_CONSOLE_UPDATE_REGION: + { + SMALL_RECT readRect; - GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); + readRect.Top = HIWORD(idObject); + readRect.Left = LOWORD(idObject); + readRect.Bottom = HIWORD(idChild); + readRect.Right = LOWORD(idChild); - UINT viewPortHeight = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1; - UINT viewPortWidth = consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1; + /* Detect a "cls" (Windows) */ + if (!bStartup && + (readRect.Top == consoleInfo.srWindow.Top || readRect.Top == nextConsoleInfo.srWindow.Top)) { + BOOL isClearCommand = FALSE; + isClearCommand = (consoleInfo.dwSize.X == readRect.Right + 1) && (consoleInfo.dwSize.Y == readRect.Bottom + 1); - switch (event) { - case EVENT_CONSOLE_CARET: - { - COORD co; + /* If cls then inform app to clear its buffers and return */ + if (isClearCommand) { + SendClearScreen(pipe_out); + ViewPortY = 0; + lastViewPortY = 0; - if (idObject == CONSOLE_CARET_SELECTION) { - co.X = HIWORD(idChild); - co.Y = LOWORD(idChild); - } - else { - co.X = HIWORD(idChild); - co.Y = LOWORD(idChild); - } + return ERROR_SUCCESS; + } + } - break; - } - case EVENT_CONSOLE_UPDATE_REGION: - { - SMALL_RECT readRect; + /* Figure out the buffer size */ + COORD coordBufSize; + coordBufSize.Y = readRect.Bottom - readRect.Top + 1; + coordBufSize.X = readRect.Right - readRect.Left + 1; - readRect.Top = HIWORD(idObject); - readRect.Left = LOWORD(idObject); - readRect.Bottom = HIWORD(idChild); - readRect.Right = LOWORD(idChild); + /* + * Security check: the maximum screen buffer size is 9999 columns x 9999 lines so check + * the computed buffer size for overflow. since the X and Y in the COORD structure + * are shorts they could be negative. + */ + if (coordBufSize.X < 0 || coordBufSize.X > MAX_CONSOLE_COLUMNS || + coordBufSize.Y < 0 || coordBufSize.Y > MAX_CONSOLE_ROWS) + return ERROR_INVALID_PARAMETER; - // Detect a "cls" (Windows). - if (!bStartup && - (readRect.Top == consoleInfo.srWindow.Top || readRect.Top == nextConsoleInfo.srWindow.Top)) - { - BOOL isClearCommand = FALSE; - isClearCommand = (consoleInfo.dwSize.X == readRect.Right + 1) && (consoleInfo.dwSize.Y == readRect.Bottom + 1); + /* Compute buffer size */ + DWORD bufferSize = coordBufSize.X * coordBufSize.Y; + if (bufferSize > MAX_EXPECTED_BUFFER_SIZE) { + if (!bStartup) { + SendClearScreen(pipe_out); + ViewPortY = 0; + lastViewPortY = 0; + } + return ERROR_SUCCESS; + } - // If cls then inform app to clear its buffers and return. - if (isClearCommand) - { - SendClearScreen(pipe_out); - ViewPortY = 0; - lastViewPortY = 0; + /* Create the screen scrape buffer */ + CHAR_INFO *pBuffer = (PCHAR_INFO)malloc(sizeof(CHAR_INFO) * bufferSize); + if (!pBuffer) + return ERROR_INSUFFICIENT_BUFFER; - return ERROR_SUCCESS; - } - } + /* The top left destination cell of the temporary buffer is row 0, col 0 */ + COORD coordBufCoord; + coordBufCoord.X = 0; + coordBufCoord.Y = 0; - // Figure out the buffer size - COORD coordBufSize; - coordBufSize.Y = readRect.Bottom - readRect.Top + 1; - coordBufSize.X = readRect.Right - readRect.Left + 1; + /* Copy the block from the screen buffer to the temp. buffer */ + if (!ReadConsoleOutput(child_out, pBuffer, coordBufSize, coordBufCoord, &readRect)) { + DWORD dwError = GetLastError(); + + free(pBuffer); + return dwError; + } - // Security check: the maximum screen buffer size is 9999 columns x 9999 lines so check - // the computed buffer size for overflow. since the X and Y in the COORD structure - // are shorts they could be negative. - if (coordBufSize.X < 0 || coordBufSize.X > MAX_CONSOLE_COLUMNS || - coordBufSize.Y < 0 || coordBufSize.Y > MAX_CONSOLE_ROWS) - { - return ERROR_INVALID_PARAMETER; - } + if (readRect.Top > currentLine) + for (SHORT n = currentLine; n < readRect.Top; n++) + SendLF(pipe_out); - // Compute buffer size - DWORD bufferSize = coordBufSize.X * coordBufSize.Y; + /* Set cursor location based on the reported location from the message */ + CalculateAndSetCursor(pipe_out, ViewPortY, viewPortHeight, readRect.Left, readRect.Top); - if (bufferSize > MAX_EXPECTED_BUFFER_SIZE) { + /* Send the entire block */ + SendBuffer(pipe_out, pBuffer, bufferSize); + lastViewPortY = ViewPortY; + lastLineLength = readRect.Left; + + free(pBuffer); + + break; + } + case EVENT_CONSOLE_UPDATE_SIMPLE: + { + chUpdate = LOWORD(idChild); + wAttributes = HIWORD(idChild); + wX = LOWORD(idObject); + wY = HIWORD(idObject); - if (!bStartup) { - SendClearScreen(pipe_out); - ViewPortY = 0; - lastViewPortY = 0; - } + /* Set cursor location based on the reported location from the message */ + CalculateAndSetCursor(pipe_out, ViewPortY, viewPortHeight, wX, wY); - return ERROR_SUCCESS; - } + /* Send the one character. Note that a CR doesn't end up here */ + SendCharacter(pipe_out, wAttributes, chUpdate); - // Create the screen scrape buffer - CHAR_INFO *pBuffer = (PCHAR_INFO)malloc(sizeof(CHAR_INFO) * bufferSize); + break; + } + case EVENT_CONSOLE_UPDATE_SCROLL: + { + DWORD out = 0; + LONG vd = idChild; + LONG hd = idObject; + LONG vn = abs(vd); - if (!pBuffer) - { - return ERROR_INSUFFICIENT_BUFFER; - } + if (vd > 0) { + if (ViewPortY > 0) + ViewPortY -= vn; + } else { + ViewPortY += vn; + } - // The top left destination cell of the temporary buffer is row 0, col 0. - COORD coordBufCoord; - coordBufCoord.X = 0; - coordBufCoord.Y = 0; + break; + } + case EVENT_CONSOLE_LAYOUT: + { + if (consoleInfo.dwMaximumWindowSize.X == consoleInfo.dwSize.X && + consoleInfo.dwMaximumWindowSize.Y == consoleInfo.dwSize.Y && + (consoleInfo.dwCursorPosition.X == 0 && consoleInfo.dwCursorPosition.Y == 0)) { + /* Screen has switched to fullscreen mode */ + SendClearScreen(pipe_out); + savedViewPortY = ViewPortY; + savedLastViewPortY = lastViewPortY; + ViewPortY = 0; + lastViewPortY = 0;; + bFullScreen = TRUE; + } else { + /* Leave full screen mode if applicable */ + if (bFullScreen) { + SendClearScreen(pipe_out); + ViewPortY = savedViewPortY; + lastViewPortY = savedLastViewPortY; + bFullScreen = FALSE; + } + } + break; + } + } - // Copy the block from the screen buffer to the temp. buffer. - if (!ReadConsoleOutput(child_out, pBuffer, coordBufSize, coordBufCoord, &readRect)) - { - DWORD dwError = GetLastError(); + ZeroMemory(&consoleInfo, sizeof(consoleInfo)); + consoleInfo.cbSize = sizeof(consoleInfo); + GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); - free(pBuffer); - return dwError; - } - - if (readRect.Top > currentLine) - for(SHORT n = currentLine; n < readRect.Top; n++) - SendLF(pipe_out); - - // Set cursor location based on the reported location from the message. - CalculateAndSetCursor(pipe_out, ViewPortY, viewPortHeight, readRect.Left, - readRect.Top); - - // Send the entire block. - SendBuffer(pipe_out, pBuffer, bufferSize); - - lastViewPortY = ViewPortY; - lastLineLength = readRect.Left; - - free(pBuffer); - - break; - } - case EVENT_CONSOLE_UPDATE_SIMPLE: - { - chUpdate = LOWORD(idChild); - wAttributes = HIWORD(idChild); - wX = LOWORD(idObject); - wY = HIWORD(idObject); - - // Set cursor location based on the reported location from the message. - CalculateAndSetCursor(pipe_out, ViewPortY, viewPortHeight, wX, wY); - - // Send the one character. Note that a CR doesn't end up here. - SendCharacter(pipe_out, wAttributes, chUpdate); - - break; - } - case EVENT_CONSOLE_UPDATE_SCROLL: - { - DWORD out = 0; - LONG vd = idChild; - LONG hd = idObject; - - LONG vn = abs(vd); - - if (vd > 0) { - if(ViewPortY > 0) - ViewPortY -= vn; - } - else { - ViewPortY += vn; - } - - break; - } - case EVENT_CONSOLE_LAYOUT: - { - if (consoleInfo.dwMaximumWindowSize.X == consoleInfo.dwSize.X && - consoleInfo.dwMaximumWindowSize.Y == consoleInfo.dwSize.Y && - (consoleInfo.dwCursorPosition.X == 0 && consoleInfo.dwCursorPosition.Y == 0)) - { - // Screen has switched to fullscreen mode - SendClearScreen(pipe_out); - - savedViewPortY = ViewPortY; - savedLastViewPortY = lastViewPortY; - - ViewPortY = 0; - lastViewPortY = 0;; - - bFullScreen = TRUE; - } - else - { - // Leave full screen mode if applicable - if (bFullScreen) { - SendClearScreen(pipe_out); - - ViewPortY = savedViewPortY; - lastViewPortY = savedLastViewPortY; - bFullScreen = FALSE; - } - } - - break; - } - } - - ZeroMemory(&consoleInfo, sizeof(consoleInfo)); - consoleInfo.cbSize = sizeof(consoleInfo); - - GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); - - return ERROR_SUCCESS; + return ERROR_SUCCESS; } -DWORD WINAPI ProcessEventQueue(LPVOID p) { +DWORD WINAPI +ProcessEventQueue(LPVOID p) { + static SHORT lastX = 0; + static SHORT lastY = 0; - static SHORT lastX = 0; - static SHORT lastY = 0; + while (1) { + while (head) { + EnterCriticalSection(&criticalSection); + consoleEvent* current = head; + if (current) { + if (current->next) { + head = current->next; + head->prior = NULL; + } else { + head = NULL; + tail = NULL; + } + } - while (1) { + LeaveCriticalSection(&criticalSection); + if (current) { + ProcessEvent(current); + free(current); + } + } - while (head) { + if (child_in != INVALID_HANDLE_VALUE && child_in != NULL && + child_out != INVALID_HANDLE_VALUE && child_out != NULL) { + DWORD dwInputMode; + DWORD dwOutputMode; - EnterCriticalSection(&criticalSection); + if (GetConsoleMode(child_in, &dwInputMode) && GetConsoleMode(child_out, &dwOutputMode)) { + if (((dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING) && + ((dwInputMode & ENABLE_VIRTUAL_TERMINAL_INPUT) == ENABLE_VIRTUAL_TERMINAL_INPUT)) + bAnsi = TRUE; + else + bAnsi = FALSE; + } - consoleEvent* current = head; + ZeroMemory(&consoleInfo, sizeof(consoleInfo)); + consoleInfo.cbSize = sizeof(consoleInfo); - if (current) { - if (current->next) - { - head = current->next; - head->prior = NULL; - } - else - { - head = NULL; - tail = NULL; - } - } + /* This information is the live buffer that's currently in use */ + GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); - LeaveCriticalSection(&criticalSection); + /* Set the cursor to the last known good location according to the live buffer */ + if (lastX != consoleInfo.dwCursorPosition.X || + lastY != consoleInfo.dwCursorPosition.Y) + SendSetCursor(pipe_out, consoleInfo.dwCursorPosition.X + 1, consoleInfo.dwCursorPosition.Y + 1); - if (current) - { - ProcessEvent(current); - free(current); - } - } - - if (child_in != INVALID_HANDLE_VALUE && child_in != NULL && - child_out != INVALID_HANDLE_VALUE && child_out != NULL) - { - DWORD dwInputMode; - DWORD dwOutputMode; - - if (GetConsoleMode(child_in, &dwInputMode) && GetConsoleMode(child_out, &dwOutputMode)) { - if (((dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING) && - ((dwInputMode & ENABLE_VIRTUAL_TERMINAL_INPUT) == ENABLE_VIRTUAL_TERMINAL_INPUT)) - { - bAnsi = TRUE; - } - else { - bAnsi = FALSE; - } - } - - ZeroMemory(&consoleInfo, sizeof(consoleInfo)); - consoleInfo.cbSize = sizeof(consoleInfo); - - // This information is the live buffer that's currently in use. - GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); - - // Set the cursor to the last known good location according to the live buffer. - if (lastX != consoleInfo.dwCursorPosition.X || - lastY != consoleInfo.dwCursorPosition.Y) { - - SendSetCursor(pipe_out, consoleInfo.dwCursorPosition.X + 1, - consoleInfo.dwCursorPosition.Y + 1); - } - - lastX = consoleInfo.dwCursorPosition.X; - lastY = consoleInfo.dwCursorPosition.Y; - } - - Sleep(100); - } - - return 0; + lastX = consoleInfo.dwCursorPosition.X; + lastY = consoleInfo.dwCursorPosition.Y; + } + Sleep(100); + } + return 0; } -void QueueEvent( - DWORD event, - HWND hwnd, - LONG idObject, - LONG idChild) { +void +QueueEvent(DWORD event, HWND hwnd, LONG idObject, LONG idChild) { + consoleEvent* current = NULL; - consoleEvent* current = NULL; + EnterCriticalSection(&criticalSection); + current = malloc(sizeof(consoleEvent)); + if (current) { + if (!head) { + current->event = event; + current->hwnd = hwnd; + current->idChild = idChild; + current->idObject = idObject; - EnterCriticalSection(&criticalSection); + /* No links head == tail */ + current->next = NULL; + current->prior = NULL; - current = malloc(sizeof(consoleEvent)); + head = current; + tail = current; + } else { + current->event = event; + current->hwnd = hwnd; + current->idChild = idChild; + current->idObject = idObject; - if (current) { - if (!head) { - current->event = event; - current->hwnd = hwnd; - current->idChild = idChild; - current->idObject = idObject; + /* Current tail points to new tail */ + tail->next = current; - // No links head == tail - current->next = NULL; - current->prior = NULL; + /* New tail points to old tail */ + current->prior = tail; + current->next = NULL; - head = current; - tail = current; - } - else { - current->event = event; - current->hwnd = hwnd; - current->idChild = idChild; - current->idObject = idObject; - - // Current tail points to new tail - tail->next = current; - - // New tail points to old tail - current->prior = tail; - current->next = NULL; - - // Update the tail pointer to the new - // last event - tail = current; - } - } - - LeaveCriticalSection(&criticalSection); - - return; + /* Update the tail pointer to the new last event */ + tail = current; + } + } + LeaveCriticalSection(&criticalSection); } -DWORD WINAPI ProcessPipes(LPVOID p) { +DWORD WINAPI +ProcessPipes(LPVOID p) { + BOOL ret; + DWORD dwStatus; - BOOL ret; - DWORD dwStatus; + /* process data from pipe_in and route appropriately */ + while (1) { + char buf[128]; + ZeroMemory(buf, 128); + DWORD rd = 0, wr = 0, i = -1; - /* process data from pipe_in and route appropriately */ - while (1) { - char buf[128]; - ZeroMemory(buf, 128); + GOTO_CLEANUP_ON_FALSE(ReadFile(pipe_in, buf, 128, &rd, NULL)); + bStartup = FALSE; + while (++i < rd) { + INPUT_RECORD ir; + if (buf[i] == 3) { /*Ctrl+C - Raise Ctrl+C*/ + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + continue; + } - DWORD rd = 0, wr = 0, i = -1; + if (bAnsi) { + ir.EventType = KEY_EVENT; + ir.Event.KeyEvent.bKeyDown = TRUE; + ir.Event.KeyEvent.wRepeatCount = 1; + ir.Event.KeyEvent.wVirtualKeyCode = 0; + ir.Event.KeyEvent.wVirtualScanCode = 0; + ir.Event.KeyEvent.uChar.AsciiChar = buf[i]; + ir.Event.KeyEvent.dwControlKeyState = 0; + WriteConsoleInputA(child_in, &ir, 1, &wr); - GOTO_CLEANUP_ON_FALSE(ReadFile(pipe_in, buf, 128, &rd, NULL)); - - bStartup = FALSE; - - while (++i < rd) { - - INPUT_RECORD ir; - - if (buf[i] == 3) {/*Ctrl+C - Raise Ctrl+C*/ - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); - continue; - } - - if (bAnsi) { - ir.EventType = KEY_EVENT; - ir.Event.KeyEvent.bKeyDown = TRUE; - ir.Event.KeyEvent.wRepeatCount = 1; - ir.Event.KeyEvent.wVirtualKeyCode = 0; - ir.Event.KeyEvent.wVirtualScanCode = 0; - ir.Event.KeyEvent.uChar.AsciiChar = buf[i]; - ir.Event.KeyEvent.dwControlKeyState = 0; - WriteConsoleInputA(child_in, &ir, 1, &wr); - - ir.Event.KeyEvent.bKeyDown = FALSE; - WriteConsoleInputA(child_in, &ir, 1, &wr); - } - else { - ProcessIncomingKeys(buf); - break; - } - } - } + ir.Event.KeyEvent.bKeyDown = FALSE; + WriteConsoleInputA(child_in, &ir, 1, &wr); + } else { + ProcessIncomingKeys(buf); + break; + } + } + } cleanup: - /* pipe_in has ended */ - PostThreadMessage(hostThreadId, WM_APPEXIT, 0, 0); - - dwStatus = GetLastError(); - - return 0; + /* pipe_in has ended */ + PostThreadMessage(hostThreadId, WM_APPEXIT, 0, 0); + dwStatus = GetLastError(); + return 0; } -void CALLBACK ConsoleEventProc(HWINEVENTHOOK hWinEventHook, +void CALLBACK +ConsoleEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, - DWORD dwmsEventTime) -{ - QueueEvent(event, hwnd, idObject, idChild); + DWORD dwmsEventTime) { + QueueEvent(event, hwnd, idObject, idChild); } -DWORD ProcessMessages(void* p) -{ - BOOL ret; - DWORD dwMode; - DWORD dwStatus; - SECURITY_ATTRIBUTES sa; - MSG msg; +DWORD +ProcessMessages(void* p) { + BOOL ret; + DWORD dwMode; + DWORD dwStatus; + SECURITY_ATTRIBUTES sa; + MSG msg; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; - while (child_in == (HANDLE)-1) - { - child_in = CreateFile(TEXT("CONIN$"), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_WRITE | FILE_SHARE_READ, - &sa, OPEN_EXISTING, 0, NULL); - } - - if (child_in == (HANDLE)-1) - goto cleanup; - - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - while (child_out == (HANDLE)-1) - { - child_out = CreateFile(TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_WRITE | FILE_SHARE_READ, - &sa, OPEN_EXISTING, 0, NULL); - } - - if (child_out == (HANDLE)-1) - goto cleanup; - - child_err = child_out; - - SizeWindow(child_out); - - // Get the current buffer information after all the adjustments. - GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); - - // Loop for the console output events - while (GetMessage(&msg, NULL, 0, 0)) - { - if (msg.message == WM_APPEXIT) - { - break; - } - else - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } + while (child_in == (HANDLE)-1) { + child_in = CreateFile(TEXT("CONIN$"), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE | FILE_SHARE_READ, + &sa, OPEN_EXISTING, 0, NULL); + } + if (child_in == (HANDLE)-1) + goto cleanup; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + while (child_out == (HANDLE)-1) { + child_out = CreateFile(TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE | FILE_SHARE_READ, + &sa, OPEN_EXISTING, 0, NULL); + } + if (child_out == (HANDLE)-1) + goto cleanup; + child_err = child_out; + SizeWindow(child_out); + /* Get the current buffer information after all the adjustments */ + GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); + /* Loop for the console output events */ + while (GetMessage(&msg, NULL, 0, 0)) { + if (msg.message == WM_APPEXIT) + break; + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } cleanup: - dwStatus = GetLastError(); - - if (child_in != INVALID_HANDLE_VALUE) - CloseHandle(child_in); - if (child_out != INVALID_HANDLE_VALUE) - CloseHandle(child_out); - return 0; + dwStatus = GetLastError(); + if (child_in != INVALID_HANDLE_VALUE) + CloseHandle(child_in); + if (child_out != INVALID_HANDLE_VALUE) + CloseHandle(child_out); + return 0; } -int start_with_pty(int ac, wchar_t **av) { - STARTUPINFO si; - PROCESS_INFORMATION pi; - wchar_t cmd[MAX_CMD_LEN]; - SECURITY_ATTRIBUTES sa; - BOOL ret; - DWORD dwThreadId; - DWORD dwMode; - DWORD dwStatus; - HANDLE hEventHook = NULL; - HMODULE hm_kernel32 = NULL, hm_user32 = NULL; +int +start_with_pty(int ac, wchar_t **av) { + STARTUPINFO si; + PROCESS_INFORMATION pi; + wchar_t cmd[MAX_CMD_LEN]; + SECURITY_ATTRIBUTES sa; + BOOL ret; + DWORD dwThreadId; + DWORD dwMode; + DWORD dwStatus; + HANDLE hEventHook = NULL; + HMODULE hm_kernel32 = NULL, hm_user32 = NULL; - if ((hm_kernel32 = LoadLibraryW(L"kernel32.dll")) == NULL || - (hm_user32 = LoadLibraryW(L"user32.dll")) == NULL || - (__SetCurrentConsoleFontEx = (__t_SetCurrentConsoleFontEx)GetProcAddress(hm_kernel32, "SetCurrentConsoleFontEx")) == NULL || - (__UnhookWinEvent = (__t_UnhookWinEvent)GetProcAddress(hm_user32, "UnhookWinEvent")) == NULL || - (__SetWinEventHook = (__t_SetWinEventHook)GetProcAddress(hm_user32, "SetWinEventHook")) == NULL) { - printf("cannot support a pseudo terminal. \n"); - return -1; - } + if ((hm_kernel32 = LoadLibraryW(L"kernel32.dll")) == NULL || + (hm_user32 = LoadLibraryW(L"user32.dll")) == NULL || + (__SetCurrentConsoleFontEx = (__t_SetCurrentConsoleFontEx)GetProcAddress(hm_kernel32, "SetCurrentConsoleFontEx")) == NULL || + (__UnhookWinEvent = (__t_UnhookWinEvent)GetProcAddress(hm_user32, "UnhookWinEvent")) == NULL || + (__SetWinEventHook = (__t_SetWinEventHook)GetProcAddress(hm_user32, "SetWinEventHook")) == NULL) { + printf("cannot support a pseudo terminal. \n"); + return -1; + } - pipe_in = GetStdHandle(STD_INPUT_HANDLE); - pipe_out = GetStdHandle(STD_OUTPUT_HANDLE); - pipe_err = GetStdHandle(STD_ERROR_HANDLE); + pipe_in = GetStdHandle(STD_INPUT_HANDLE); + pipe_out = GetStdHandle(STD_OUTPUT_HANDLE); + pipe_err = GetStdHandle(STD_ERROR_HANDLE); - /* copy pipe handles passed through std io*/ - if ((pipe_in == INVALID_HANDLE_VALUE) - || (pipe_out == INVALID_HANDLE_VALUE) - || (pipe_err == INVALID_HANDLE_VALUE)) - return -1; + /* copy pipe handles passed through std io*/ + if ((pipe_in == INVALID_HANDLE_VALUE) || (pipe_out == INVALID_HANDLE_VALUE) || (pipe_err == INVALID_HANDLE_VALUE)) + return -1; - cp = GetConsoleCP(); + cp = GetConsoleCP(); - /* Windows PTY sends cursor positions in absolute coordinates starting from <0,0> - * We send a clear screen upfront to simplify client */ - SendClearScreen(pipe_out); + /* + * Windows PTY sends cursor positions in absolute coordinates starting from <0,0> + * We send a clear screen upfront to simplify client + */ + SendClearScreen(pipe_out); + ZeroMemory(&inputSi, sizeof(STARTUPINFO)); + GetStartupInfo(&inputSi); + memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); + sa.bInheritHandle = TRUE; + /* WM_APPEXIT */ + hostThreadId = GetCurrentThreadId(); + hostProcessId = GetCurrentProcessId(); + InitializeCriticalSection(&criticalSection); + hEventHook = __SetWinEventHook(EVENT_CONSOLE_CARET, EVENT_CONSOLE_LAYOUT, NULL, + ConsoleEventProc, 0, 0, WINEVENT_OUTOFCONTEXT); + memset(&si, 0, sizeof(STARTUPINFO)); + memset(&pi, 0, sizeof(PROCESS_INFORMATION)); + /* Copy our parent buffer sizes */ + si.cb = sizeof(STARTUPINFO); + si.dwFlags = 0; + /* disable inheritance on pipe_in*/ + GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0)); + + /*TODO - pick this up from system32*/ + cmd[0] = L'\0'; + if (ac) + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe")); + ac--; + av++; + if (ac) + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c")); + while (ac) { + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" ")); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, *av)); + ac--; + av++; + } - ZeroMemory(&inputSi, sizeof(STARTUPINFO)); - GetStartupInfo(&inputSi); + SetConsoleCtrlHandler(NULL, FALSE); + GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, + NULL, NULL, &si, &pi)); + childProcessId = pi.dwProcessId; - memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); - sa.bInheritHandle = TRUE; + FreeConsole(); + Sleep(20); + while (!AttachConsole(pi.dwProcessId)) { + if (GetExitCodeProcess(pi.hProcess, &child_exit_code) && child_exit_code != STILL_ACTIVE) + break; + Sleep(100); + } - /* WM_APPEXIT */ - hostThreadId = GetCurrentThreadId(); - hostProcessId = GetCurrentProcessId(); + /* monitor child exist */ + child = pi.hProcess; + monitor_thread = CreateThread(NULL, 0, MonitorChild, NULL, 0, NULL); + if (monitor_thread == INVALID_HANDLE_VALUE) + goto cleanup; - InitializeCriticalSection(&criticalSection); + /* disable Ctrl+C hander in this process*/ + SetConsoleCtrlHandler(NULL, TRUE); - hEventHook = __SetWinEventHook(EVENT_CONSOLE_CARET, EVENT_CONSOLE_LAYOUT, NULL, - ConsoleEventProc, 0, 0, WINEVENT_OUTOFCONTEXT); + io_thread = CreateThread(NULL, 0, ProcessPipes, NULL, 0, NULL); + if (io_thread == INVALID_HANDLE_VALUE) + goto cleanup; - memset(&si, 0, sizeof(STARTUPINFO)); - memset(&pi, 0, sizeof(PROCESS_INFORMATION)); - - // Copy our parent buffer sizes - si.cb = sizeof(STARTUPINFO); - si.dwFlags = 0; - - /* disable inheritance on pipe_in*/ - GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0)); - - /*TODO - pick this up from system32*/ - cmd[0] = L'\0'; - if (ac) - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe")); - - ac--; - av++; - if (ac) - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c")); - while (ac) { - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" ")); - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, *av)); - ac--; - av++; - } - - SetConsoleCtrlHandler(NULL, FALSE); - GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, - NULL, NULL, &si, &pi)); - childProcessId = pi.dwProcessId; - - FreeConsole(); - Sleep(20); - while (!AttachConsole(pi.dwProcessId)) - { - if (GetExitCodeProcess(pi.hProcess, &child_exit_code) && child_exit_code != STILL_ACTIVE) - break; - Sleep(100); - } - - /* monitor child exist */ - child = pi.hProcess; - monitor_thread = CreateThread(NULL, 0, MonitorChild, NULL, 0, NULL); - if (monitor_thread == INVALID_HANDLE_VALUE) - goto cleanup; - - /* disable Ctrl+C hander in this process*/ - SetConsoleCtrlHandler(NULL, TRUE); - - io_thread = CreateThread(NULL, 0, ProcessPipes, NULL, 0, NULL); - if (io_thread == INVALID_HANDLE_VALUE) - goto cleanup; - - ux_thread = CreateThread(NULL, 0, ProcessEventQueue, NULL, 0, NULL); - if (ux_thread == INVALID_HANDLE_VALUE) - goto cleanup; - - ProcessMessages(NULL); + ux_thread = CreateThread(NULL, 0, ProcessEventQueue, NULL, 0, NULL); + if (ux_thread == INVALID_HANDLE_VALUE) + goto cleanup; + ProcessMessages(NULL); cleanup: - dwStatus = GetLastError(); + dwStatus = GetLastError(); + DeleteCriticalSection(&criticalSection); + if (child != INVALID_HANDLE_VALUE) + TerminateProcess(child, 0); + if (monitor_thread != INVALID_HANDLE_VALUE) + WaitForSingleObject(monitor_thread, INFINITE); + if (ux_thread != INVALID_HANDLE_VALUE) + TerminateThread(ux_thread, S_OK); + if (hEventHook) + __UnhookWinEvent(hEventHook); + FreeConsole(); - DeleteCriticalSection(&criticalSection); - - if (child != INVALID_HANDLE_VALUE) - TerminateProcess(child, 0); - if (monitor_thread != INVALID_HANDLE_VALUE) - WaitForSingleObject(monitor_thread, INFINITE); - if (ux_thread != INVALID_HANDLE_VALUE) - TerminateThread(ux_thread, S_OK); - if (hEventHook) - __UnhookWinEvent(hEventHook); - - FreeConsole(); - - return child_exit_code; + return child_exit_code; } HANDLE child_pipe_read; HANDLE child_pipe_write; -DWORD WINAPI MonitorChild_nopty( - _In_ LPVOID lpParameter - ) { - WaitForSingleObject(child, INFINITE); + +DWORD WINAPI +MonitorChild_nopty( _In_ LPVOID lpParameter) { + WaitForSingleObject(child, INFINITE); GetExitCodeProcess(child, &child_exit_code); - CloseHandle(pipe_in); - //printf("XXXX CHILD PROCESS DEAD XXXXX"); - return 0; + CloseHandle(pipe_in); + return 0; } -int start_withno_pty(int ac, wchar_t **av) { - STARTUPINFO si; - PROCESS_INFORMATION pi; - wchar_t cmd[MAX_CMD_LEN]; - SECURITY_ATTRIBUTES sa; - BOOL ret; +int +start_withno_pty(int ac, wchar_t **av) { + STARTUPINFO si; + PROCESS_INFORMATION pi; + wchar_t cmd[MAX_CMD_LEN]; + SECURITY_ATTRIBUTES sa; + BOOL ret; - pipe_in = GetStdHandle(STD_INPUT_HANDLE); - pipe_out = GetStdHandle(STD_OUTPUT_HANDLE); - pipe_err = GetStdHandle(STD_ERROR_HANDLE); + pipe_in = GetStdHandle(STD_INPUT_HANDLE); + pipe_out = GetStdHandle(STD_OUTPUT_HANDLE); + pipe_err = GetStdHandle(STD_ERROR_HANDLE); - /* copy pipe handles passed through std io*/ - if ((pipe_in == INVALID_HANDLE_VALUE) - || (pipe_out == INVALID_HANDLE_VALUE) - || (pipe_err == INVALID_HANDLE_VALUE)) - return -1; + /* copy pipe handles passed through std io*/ + if ((pipe_in == INVALID_HANDLE_VALUE) || (pipe_out == INVALID_HANDLE_VALUE) || (pipe_err == INVALID_HANDLE_VALUE)) + return -1; - memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); - sa.bInheritHandle = TRUE; - if (!CreatePipe(&child_pipe_read, &child_pipe_write, &sa, 128)) - return -1; + memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); + sa.bInheritHandle = TRUE; + if (!CreatePipe(&child_pipe_read, &child_pipe_write, &sa, 128)) + return -1; - memset(&si, 0, sizeof(STARTUPINFO)); - memset(&pi, 0, sizeof(PROCESS_INFORMATION)); + memset(&si, 0, sizeof(STARTUPINFO)); + memset(&pi, 0, sizeof(PROCESS_INFORMATION)); + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = child_pipe_read; + si.hStdOutput = pipe_out; + si.hStdError = pipe_err; - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = child_pipe_read; - si.hStdOutput = pipe_out; - si.hStdError = pipe_err; + /* disable inheritance on child_pipe_write and pipe_in*/ + GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0)); + GOTO_CLEANUP_ON_FALSE(SetHandleInformation(child_pipe_write, HANDLE_FLAG_INHERIT, 0)); - /* disable inheritance on child_pipe_write and pipe_in*/ - GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0)); - GOTO_CLEANUP_ON_FALSE(SetHandleInformation(child_pipe_write, HANDLE_FLAG_INHERIT, 0)); + /*TODO - pick this up from system32*/ + cmd[0] = L'\0'; + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe")); + ac -= 2; + av += 2; + if (ac) + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c")); + while (ac) { + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" ")); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, *av)); + ac--; + av++; + } - /*TODO - pick this up from system32*/ - cmd[0] = L'\0'; - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe")); - ac -= 2; - av += 2; - if (ac) - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c")); - while (ac) { - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" ")); - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, *av)); - ac--; - av++; - } + GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)); - GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)); + /* close unwanted handles*/ + CloseHandle(child_pipe_read); + child_pipe_read = INVALID_HANDLE_VALUE; + child = pi.hProcess; + /* monitor child exist */ + monitor_thread = CreateThread(NULL, 0, MonitorChild_nopty, NULL, 0, NULL); + if (monitor_thread == INVALID_HANDLE_VALUE) + goto cleanup; - /* close unwanted handles*/ - CloseHandle(child_pipe_read); - child_pipe_read = INVALID_HANDLE_VALUE; + /* disable Ctrl+C hander in this process*/ + SetConsoleCtrlHandler(NULL, TRUE); - child = pi.hProcess; - /* monitor child exist */ - monitor_thread = CreateThread(NULL, 0, MonitorChild_nopty, NULL, 0, NULL); - if (monitor_thread == INVALID_HANDLE_VALUE) - goto cleanup; + /* process data from pipe_in and route appropriately */ + while (1) { + char buf[128]; + DWORD rd = 0, wr = 0, i = 0; + GOTO_CLEANUP_ON_FALSE(ReadFile(pipe_in, buf, 128, &rd, NULL)); - /* disable Ctrl+C hander in this process*/ - SetConsoleCtrlHandler(NULL, TRUE); + while (i < rd) { + /* skip arrow keys */ + if ((rd - i >= 3) && (buf[i] == '\033') && (buf[i + 1] == '[') && + (buf[i + 2] >= 'A') && (buf[i + 2] <= 'D')) { + i += 3; + continue; + } - /* process data from pipe_in and route appropriately */ - while (1) { - char buf[128]; - DWORD rd = 0, wr = 0, i = 0; - GOTO_CLEANUP_ON_FALSE(ReadFile(pipe_in, buf, 128, &rd, NULL)); + /* skip tab */ + if (buf[i] == '\t') { + i++; + continue; + } - while (i < rd) { + /* Ctrl +C */ + if (buf[i] == '\003') { + GOTO_CLEANUP_ON_FALSE(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)); + in_cmd_len = 0; + i++; + continue; + } - /* skip arrow keys */ - if ((rd - i >= 3) && (buf[i] == '\033') && (buf[i + 1] == '[') - && (buf[i + 2] >= 'A') && (buf[i + 2] <= 'D')) { - i += 3; - continue; - } + /* for backspace, we need to send space and another backspace for visual erase */ + if (buf[i] == '\b') { + if (in_cmd_len > 0) { + GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, "\b \b", 3, &wr, NULL)); + in_cmd_len--; + } + i++; + continue; + } - /* skip tab */ - if (buf[i] == '\t') { - i++; - continue; - } - - // Ctrl +C - if (buf[i] == '\003') { - GOTO_CLEANUP_ON_FALSE(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)); - in_cmd_len = 0; - i++; - continue; - } - - // for backspace, we need to send space and another backspace for visual erase - if (buf[i] == '\b') { - if (in_cmd_len > 0) { - GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, "\b \b", 3, &wr, NULL)); - in_cmd_len--; - } - i++; - continue; - } - - //for CR and LF - if ((buf[i] == '\r') || (buf[i] == '\n')) { - - /* TODO - do a much accurate mapping */ - GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL)); - if ((buf[i] == '\r') && ((i == rd - 1) || (buf[i + 1] != '\n'))) { - buf[i] = '\n'; - GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL)); - } - in_cmd[in_cmd_len] = buf[i]; - in_cmd_len++; - GOTO_CLEANUP_ON_FALSE(WriteFile(child_pipe_write, in_cmd, in_cmd_len, &wr, NULL)); - in_cmd_len = 0; - i++; - continue; - } - - - GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL)); - in_cmd[in_cmd_len] = buf[i]; - in_cmd_len++; - if (in_cmd_len == MAX_CMD_LEN - 1) { - GOTO_CLEANUP_ON_FALSE(WriteFile(child_pipe_write, in_cmd, in_cmd_len, &wr, NULL)); - in_cmd_len = 0; - } - - i++; - } - } + /* For CR and LF */ + if ((buf[i] == '\r') || (buf[i] == '\n')) { + /* TODO - do a much accurate mapping */ + GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL)); + if ((buf[i] == '\r') && ((i == rd - 1) || (buf[i + 1] != '\n'))) { + buf[i] = '\n'; + GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL)); + } + in_cmd[in_cmd_len] = buf[i]; + in_cmd_len++; + GOTO_CLEANUP_ON_FALSE(WriteFile(child_pipe_write, in_cmd, in_cmd_len, &wr, NULL)); + in_cmd_len = 0; + i++; + continue; + } + GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL)); + in_cmd[in_cmd_len] = buf[i]; + in_cmd_len++; + if (in_cmd_len == MAX_CMD_LEN - 1) { + GOTO_CLEANUP_ON_FALSE(WriteFile(child_pipe_write, in_cmd, in_cmd_len, &wr, NULL)); + in_cmd_len = 0; + } + i++; + } + } cleanup: - - if (child != INVALID_HANDLE_VALUE) - TerminateProcess(child, 0); - if (monitor_thread != INVALID_HANDLE_VALUE) - WaitForSingleObject(monitor_thread, INFINITE); - return child_exit_code; + if (child != INVALID_HANDLE_VALUE) + TerminateProcess(child, 0); + if (monitor_thread != INVALID_HANDLE_VALUE) + WaitForSingleObject(monitor_thread, INFINITE); + + return child_exit_code; } -int wmain(int ac, wchar_t **av) { +int +wmain(int ac, wchar_t **av) { + /* create job to hold all child processes */ + HANDLE job = CreateJobObject(NULL, NULL); + JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info; + memset(&job_info, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); + job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info))) + return -1; + CloseHandle(job); - - /* create job to hold all child processes */ - { - /* TODO - this does not work as expected*/ - HANDLE job = CreateJobObject(NULL, NULL); - JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info; - memset(&job_info, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); - job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info))) - return -1; - CloseHandle(job); - } - - if ((ac == 1) || wcscmp(av[1], L"-nopty")) - return start_with_pty(ac, av); - else - return start_withno_pty(ac, av); + if ((ac == 1) || wcscmp(av[1], L"-nopty")) + return start_with_pty(ac, av); + else + return start_withno_pty(ac, av); } \ No newline at end of file diff --git a/contrib/win32/win32compat/termio.c b/contrib/win32/win32compat/termio.c index 4e554257d..4708fdc2a 100644 --- a/contrib/win32/win32compat/termio.c +++ b/contrib/win32/win32compat/termio.c @@ -1,3 +1,40 @@ +/* + * Author: Manoj Ampalam + * read() and write() on tty using worker threads to handle + * synchronous Windows Console IO + * + * Author: Ray Hayes + * TTY/PTY support added by capturing all terminal input events + * + * Author: Balu + * Misc fixes and code cleanup + * + * Copyright (c) 2017 Microsoft Corp. + * All rights reserved + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include "w32fd.h" #include "tncon.h" @@ -12,12 +49,11 @@ struct io_status { DWORD transferred; DWORD error; }; - static struct io_status read_status, write_status; -static VOID CALLBACK ReadAPCProc( - _In_ ULONG_PTR dwParam - ) { +/* APC that gets queued on main thread when a sync Read completes on worker thread */ +static VOID CALLBACK +ReadAPCProc(_In_ ULONG_PTR dwParam) { struct w32_io* pio = (struct w32_io*)dwParam; debug3("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, read_status.transferred, pio->read_details.pending, read_status.error); @@ -30,39 +66,35 @@ static VOID CALLBACK ReadAPCProc( pio->read_overlapped.hEvent = 0; } -static DWORD WINAPI ReadConsoleThread( - _In_ LPVOID lpParameter -) { - int nBytesReturned = 0; +/* Read worker thread */ +static DWORD WINAPI +ReadConsoleThread(_In_ LPVOID lpParameter) { + int nBytesReturned = 0; + struct w32_io* pio = (struct w32_io*)lpParameter; - struct w32_io* pio = (struct w32_io*)lpParameter; + debug3("TermRead thread, io:%p", pio); + memset(&read_status, 0, sizeof(read_status)); + while (nBytesReturned == 0) { + nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio), + pio->read_details.buf, pio->read_details.buf_size); + } + read_status.transferred = nBytesReturned; + if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) { + debug("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio); + pio->read_details.pending = FALSE; + pio->read_details.error = GetLastError(); + DebugBreak(); + } - debug3("TermRead thread, io:%p", pio); - memset(&read_status, 0, sizeof(read_status)); - - while (nBytesReturned == 0) { - nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio), - pio->read_details.buf, pio->read_details.buf_size); - } - - read_status.transferred = nBytesReturned; - - if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) { - debug("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio); - pio->read_details.pending = FALSE; - pio->read_details.error = GetLastError(); - DebugBreak(); - } - - return 0; + return 0; } +/* Initiates read on tty */ int termio_initiate_read(struct w32_io* pio) { HANDLE read_thread; debug3("TermRead initiate io:%p", pio); - if (pio->read_details.buf_size == 0) { pio->read_details.buf = malloc(TERM_IO_BUF_SIZE); if (pio->read_details.buf == NULL) { @@ -72,7 +104,7 @@ termio_initiate_read(struct w32_io* pio) { pio->read_details.buf_size = TERM_IO_BUF_SIZE; } - read_thread = CreateThread(NULL, 0, ReadConsoleThread, pio, 0, NULL); + read_thread = CreateThread(NULL, 0, ReadConsoleThread, pio, 0, NULL); if (read_thread == NULL) { errno = errno_from_Win32Error(GetLastError()); debug("TermRead initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio); @@ -84,15 +116,15 @@ termio_initiate_read(struct w32_io* pio) { return 0; } -static VOID CALLBACK WriteAPCProc( - _In_ ULONG_PTR dwParam - ) { +/* APC that gets queued on main thread when a sync Write completes on worker thread */ +static VOID CALLBACK +WriteAPCProc(_In_ ULONG_PTR dwParam) { struct w32_io* pio = (struct w32_io*)dwParam; debug3("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, write_status.transferred, pio->write_details.pending, write_status.error); pio->write_details.error = write_status.error; pio->write_details.remaining -= write_status.transferred; - /*TODO- assert that reamining is 0 by now*/ + /* TODO- assert that reamining is 0 by now */ pio->write_details.completed = 0; pio->write_details.pending = FALSE; WaitForSingleObject(pio->write_overlapped.hEvent, INFINITE); @@ -100,28 +132,28 @@ static VOID CALLBACK WriteAPCProc( pio->write_overlapped.hEvent = 0; } -static DWORD WINAPI WriteThread( - _In_ LPVOID lpParameter - ) { +/* Write worker thread */ +static DWORD WINAPI +WriteThread(_In_ LPVOID lpParameter) { struct w32_io* pio = (struct w32_io*)lpParameter; - char *respbuf = NULL; - size_t resplen = 0; - DWORD dwSavedAttributes = ENABLE_PROCESSED_INPUT; + char *respbuf = NULL; + size_t resplen = 0; + DWORD dwSavedAttributes = ENABLE_PROCESSED_INPUT; debug3("TermWrite thread, io:%p", pio); - - if (in_raw_mode == 0) { + + if (in_raw_mode == 0) { /* convert stream to utf16 and dump on console */ pio->write_details.buf[write_status.to_transfer] = '\0'; wchar_t* t = utf8_to_utf16(pio->write_details.buf); WriteConsoleW(WINHANDLE(pio), t, wcslen(t), 0, 0); free(t); write_status.transferred = write_status.to_transfer; - } else { - /* console mode */ - telProcessNetwork(pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen); - /*TODO - respbuf is not null in some cases, this needs to be returned back via read stream*/ - write_status.transferred = write_status.to_transfer; - } + } else { + /* console mode */ + telProcessNetwork(pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen); + /* TODO - respbuf is not null in some cases, this needs to be returned back via read stream */ + write_status.transferred = write_status.to_transfer; + } if (0 == QueueUserAPC(WriteAPCProc, main_thread, (ULONG_PTR)pio)) { debug("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio); @@ -132,10 +164,10 @@ static DWORD WINAPI WriteThread( return 0; } +/* Initiates write on tty */ int termio_initiate_write(struct w32_io* pio, DWORD num_bytes) { HANDLE write_thread; - debug3("TermWrite initiate io:%p", pio); memset(&write_status, 0, sizeof(write_status)); write_status.to_transfer = num_bytes; @@ -151,28 +183,26 @@ termio_initiate_write(struct w32_io* pio, DWORD num_bytes) { return 0; } - -int termio_close(struct w32_io* pio) { +/* tty close */ +int +termio_close(struct w32_io* pio) { debug2("termio_close - pio:%p", pio); HANDLE h; - CancelIoEx(WINHANDLE(pio), NULL); /* If io is pending, let write worker threads exit. The read thread is blocked so terminate it.*/ - if (pio->read_details.pending) - TerminateThread(pio->read_overlapped.hEvent, 0); + if (pio->read_details.pending) + TerminateThread(pio->read_overlapped.hEvent, 0); if (pio->write_details.pending) WaitForSingleObject(pio->write_overlapped.hEvent, INFINITE); /* drain queued APCs */ SleepEx(0, TRUE); - if (pio->type != STD_IO_FD) {//STD handles are never explicitly closed + if (pio->type != STD_IO_FD) { + /* STD handles are never explicitly closed */ CloseHandle(WINHANDLE(pio)); - if (pio->read_details.buf) free(pio->read_details.buf); - if (pio->write_details.buf) free(pio->write_details.buf); - free(pio); } return 0; diff --git a/contrib/win32/win32compat/tncon.c b/contrib/win32/win32compat/tncon.c index 7df7eb24c..3dac83f61 100644 --- a/contrib/win32/win32compat/tncon.c +++ b/contrib/win32/win32compat/tncon.c @@ -1,10 +1,15 @@ /* - * Author: Microsoft Corp. + * Author: Ray Hayes + * ANSI TTY Reader - Maps Windows console input events to ANSI stream + * + * Author: Balu + * Misc fixes and code cleanup * - * Copyright (c) 2015 Microsoft Corp. + * Copyright (c) 2017 Microsoft Corp. * All rights reserved * - * Microsoft openssh win32 port + * This file is responsible for console reading calls for building an emulator + * over Windows Console. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,600 +32,549 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* tncon.c - * - * Console reading calls for building an emulator over Windows Console. MS win32 port of ssh.exe client uses it. - * -*/ #include #include #include #include - - #include - #include "ansiprsr.h" #include "tncon.h" #include "tnnet.h" extern bool gbVTAppMode; - -char *glob_out = NULL ; -int glob_outlen = 0; -int glob_space = 0; - +char *glob_out = NULL; +int glob_outlen = 0; +int glob_space = 0; unsigned char NAWSSTR[] = { "\xff\xfa\x1f\x00\x00\x00\x00\xff\xf0" }; - extern int ScreenY; extern int ScreenX; - extern int ScrollTop; extern int ScrollBottom; /* terminal global switches*/ TelParams Parameters = { - 0, // int fLogging; - NULL, //FILE *fplogfile; - NULL, //char *pInputFile; - NULL, // char *szDebugInputFile; - FALSE, //BOOL fDebugWait; - 0, //int timeOut; - 0, //int fLocalEcho; - 0, //int fTreatLFasCRLF; - 0, //int fSendCROnly; - ENUM_LF, //int nReceiveCRLF; - '`', //char sleepChar; - '\035', //char menuChar; // CTRL-] - 0, //SOCKET Socket; - FALSE, //BOOL bVT100Mode; - "\x01", //char *pAltKey; + 0, /* int fLogging */ + NULL, /* FILE *fplogfile */ + NULL, /* char *pInputFile */ + NULL, /* char *szDebugInputFile */ + FALSE, /* BOOL fDebugWait */ + 0, /* int timeOut */ + 0, /* int fLocalEcho */ + 0, /* int fTreatLFasCRLF */ + 0, /* int fSendCROnly */ + ENUM_LF, /* int nReceiveCRLF */ + '`', /* char sleepChar */ + '\035', /* char menuChar; // CTRL-] */ + 0, /* SOCKET Socket */ + FALSE, /* BOOL bVT100Mode */ + "\x01", /* char *pAltKey */ }; + TelParams* pParams = &Parameters; -// For our case, in NetWriteString2(), we do not use socket, but write the out going data to -// a global buffer setup by ReadConsoleForTermEmul() function below -int NetWriteString2(SOCKET sock, char* source, size_t len, int options) -{ +void queue_terminal_window_change_event(); + +/* + * For our case, in NetWriteString2(), we do not use socket, but write the out going data to + * a global buffer setup by ReadConsoleForTermEmul(). + */ +int +NetWriteString2(SOCKET sock, char* source, size_t len, int options) { while (len > 0) { if (glob_outlen >= glob_space) return glob_outlen; - *glob_out++ = *source++ ; + *glob_out++ = *source++; len--; glob_outlen++; } + return glob_outlen; +} + +BOOL +DataAvailable(HANDLE h) { + DWORD dwRet = WaitForSingleObject(h, INFINITE); + if (dwRet == WAIT_OBJECT_0) + return TRUE; + if (dwRet == WAIT_FAILED) + return FALSE; + return FALSE; +} + +int +ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) { + HANDLE hHandle[] = { hInput, NULL }; + DWORD nHandle = 1; + DWORD dwInput = 0; + DWORD dwControlKeyState = 0; + DWORD rc = 0; + unsigned char szResponse[50]; + unsigned char octets[20]; + char aChar = 0; + INPUT_RECORD InputRecord; + BOOL bCapsOn = FALSE; + BOOL bShift = FALSE; + + glob_out = destin; + glob_space = destinlen; + glob_outlen = 0; + while (DataAvailable(hInput)) { + if (glob_outlen >= destinlen) + return glob_outlen; + ReadConsoleInput(hInput, &InputRecord, 1, &dwInput); + switch (InputRecord.EventType) { + case WINDOW_BUFFER_SIZE_EVENT: + queue_terminal_window_change_event(); + break; + + case FOCUS_EVENT: + /* FALLTHROUGH */ + case MENU_EVENT: + break; + + case KEY_EVENT: + bCapsOn = (InputRecord.Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON); + bShift = (InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED); + dwControlKeyState = InputRecord.Event.KeyEvent.dwControlKeyState & + ~(CAPSLOCK_ON | ENHANCED_KEY | NUMLOCK_ON | SCROLLLOCK_ON); + if (InputRecord.Event.KeyEvent.bKeyDown) { + int n = WideCharToMultiByte( + CP_UTF8, + 0, + &(InputRecord.Event.KeyEvent.uChar.UnicodeChar), + 1, + (LPSTR)octets, + 20, + NULL, + NULL); + + if (pParams->fLocalEcho) + ConWriteString((char *)octets, n); + + switch (InputRecord.Event.KeyEvent.uChar.UnicodeChar) { + case 0xd: + if (pParams->nReceiveCRLF == ENUM_LF) + NetWriteString2(pParams->Socket, "\r", 1, 0); + else + NetWriteString2(pParams->Socket, "\r\n", 2, 0); + break; + + case VK_ESCAPE: + NetWriteString2(pParams->Socket, (char *)ESCAPE_KEY, 1, 0); + break; + + default: + switch (InputRecord.Event.KeyEvent.wVirtualKeyCode) { + case VK_UP: + NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_UP_ARROW : UP_ARROW), 3, 0); + break; + case VK_DOWN: + NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_DOWN_ARROW : DOWN_ARROW), 3, 0); + break; + case VK_RIGHT: + NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_RIGHT_ARROW : RIGHT_ARROW), 3, 0); + break; + case VK_LEFT: + NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_LEFT_ARROW : LEFT_ARROW), 3, 0); + break; + case VK_END: + NetWriteString2(pParams->Socket, (char *)SELECT_KEY, 4, 0); + break; + case VK_HOME: + NetWriteString2(pParams->Socket, (char *)FIND_KEY, 4, 0); + break; + case VK_INSERT: + NetWriteString2(pParams->Socket, (char *)INSERT_KEY, 4, 0); + break; + case VK_DELETE: + NetWriteString2(pParams->Socket, (char *)REMOVE_KEY, 4, 0); + break; + case VK_BACK: + NetWriteString2(pParams->Socket, (char *)BACKSPACE_KEY, 1, 0); + break; + case VK_TAB: + if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_TAB_KEY, 3, 0); + else + NetWriteString2(pParams->Socket, (char *)octets, n, 0); + break; + case VK_ESCAPE: + NetWriteString2(pParams->Socket, (char *)ESCAPE_KEY, 1, 0); + break; + case VK_SHIFT: + case VK_CONTROL: + case VK_CAPITAL: + break; /* NOP on these */ + case VK_F1: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF1_KEY, strlen(PF1_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF1_KEY, strlen(SHIFT_PF1_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF1_KEY, strlen(CTRL_PF1_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF1_KEY, strlen(ALT_PF1_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF1_KEY, strlen(SHIFT_ALT_CTRL_PF1_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF1_KEY, strlen(ALT_CTRL_PF1_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF1_KEY, strlen(SHIFT_ALT_PF1_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF1_KEY, strlen(SHIFT_CTRL_PF1_KEY), 0); + + break; + case VK_F2: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF2_KEY, strlen(PF2_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF2_KEY, strlen(SHIFT_PF2_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF2_KEY, strlen(CTRL_PF2_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF2_KEY, strlen(ALT_PF2_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF2_KEY, strlen(SHIFT_ALT_CTRL_PF2_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF2_KEY, strlen(ALT_CTRL_PF2_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF2_KEY, strlen(SHIFT_ALT_PF2_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF2_KEY, strlen(SHIFT_CTRL_PF2_KEY), 0); + break; + case VK_F3: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF3_KEY, strlen(PF3_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF3_KEY, strlen(SHIFT_PF3_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF3_KEY, strlen(CTRL_PF3_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF3_KEY, strlen(ALT_PF3_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF3_KEY, strlen(SHIFT_ALT_CTRL_PF3_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF3_KEY, strlen(ALT_CTRL_PF3_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF3_KEY, strlen(SHIFT_ALT_PF3_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF3_KEY, strlen(SHIFT_CTRL_PF3_KEY), 0); + break; + case VK_F4: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF4_KEY, strlen(PF4_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF4_KEY, strlen(SHIFT_PF4_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF4_KEY, strlen(CTRL_PF4_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF4_KEY, strlen(ALT_PF4_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF4_KEY, strlen(SHIFT_ALT_CTRL_PF4_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF4_KEY, strlen(ALT_CTRL_PF4_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF4_KEY, strlen(SHIFT_ALT_PF4_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF4_KEY, strlen(SHIFT_CTRL_PF4_KEY), 0); + break; + case VK_F5: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF5_KEY, strlen(PF5_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF5_KEY, strlen(SHIFT_PF5_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF5_KEY, strlen(CTRL_PF5_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF5_KEY, strlen(ALT_PF5_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF5_KEY, strlen(SHIFT_ALT_CTRL_PF5_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF5_KEY, strlen(ALT_CTRL_PF5_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF5_KEY, strlen(SHIFT_ALT_PF5_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF5_KEY, strlen(SHIFT_CTRL_PF5_KEY), 0); + break; + case VK_F6: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF6_KEY, strlen(PF6_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF6_KEY, strlen(SHIFT_PF6_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF6_KEY, strlen(CTRL_PF6_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF6_KEY, strlen(ALT_PF6_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF6_KEY, strlen(SHIFT_ALT_CTRL_PF6_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF6_KEY, strlen(ALT_CTRL_PF6_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF6_KEY, strlen(SHIFT_ALT_PF6_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF6_KEY, strlen(SHIFT_CTRL_PF6_KEY), 0); + break; + case VK_F7: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF7_KEY, strlen(PF7_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF7_KEY, strlen(SHIFT_PF7_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF7_KEY, strlen(CTRL_PF7_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF7_KEY, strlen(ALT_PF7_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF7_KEY, strlen(SHIFT_ALT_CTRL_PF7_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF7_KEY, strlen(ALT_CTRL_PF7_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF7_KEY, strlen(SHIFT_ALT_PF7_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF7_KEY, strlen(SHIFT_CTRL_PF7_KEY), 0); + break; + case VK_F8: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF8_KEY, strlen(PF8_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF8_KEY, strlen(SHIFT_PF8_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF8_KEY, strlen(CTRL_PF8_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF8_KEY, strlen(ALT_PF8_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF8_KEY, strlen(SHIFT_ALT_CTRL_PF8_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF8_KEY, strlen(ALT_CTRL_PF8_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF8_KEY, strlen(SHIFT_ALT_PF8_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF8_KEY, strlen(SHIFT_CTRL_PF8_KEY), 0); + break; + case VK_F9: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF9_KEY, strlen(PF9_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF9_KEY, strlen(SHIFT_PF9_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF9_KEY, strlen(CTRL_PF9_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF9_KEY, strlen(ALT_PF9_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF9_KEY, strlen(SHIFT_ALT_CTRL_PF9_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF9_KEY, strlen(ALT_CTRL_PF9_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF9_KEY, strlen(SHIFT_ALT_PF9_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF9_KEY, strlen(SHIFT_CTRL_PF9_KEY), 0); + break; + case VK_F10: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF10_KEY, strlen(PF10_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF10_KEY, strlen(SHIFT_PF10_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF10_KEY, strlen(CTRL_PF10_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF10_KEY, strlen(ALT_PF10_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) &&((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF10_KEY, strlen(SHIFT_ALT_CTRL_PF10_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF10_KEY, strlen(ALT_CTRL_PF10_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF10_KEY, strlen(SHIFT_ALT_PF10_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF10_KEY, strlen(SHIFT_CTRL_PF10_KEY), 0); + break; + case VK_F11: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF11_KEY, strlen(PF11_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF11_KEY, strlen(SHIFT_PF11_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF11_KEY, strlen(CTRL_PF11_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF11_KEY, strlen(ALT_PF11_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) &&((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF11_KEY, strlen(SHIFT_ALT_CTRL_PF11_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF11_KEY, strlen(ALT_CTRL_PF11_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF11_KEY, strlen(SHIFT_ALT_PF11_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF11_KEY, strlen(SHIFT_CTRL_PF11_KEY), 0); + break; + case VK_F12: + if (dwControlKeyState == 0) + NetWriteString2(pParams->Socket, (char *)PF12_KEY, strlen(PF12_KEY), 0); + + else if (dwControlKeyState == SHIFT_PRESSED) + NetWriteString2(pParams->Socket, (char *)SHIFT_PF12_KEY, strlen(SHIFT_PF12_KEY), 0); + + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) + NetWriteString2(pParams->Socket, (char *)CTRL_PF12_KEY, strlen(CTRL_PF12_KEY), 0); + + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) + NetWriteString2(pParams->Socket, (char *)ALT_PF12_KEY, strlen(ALT_PF12_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF12_KEY, strlen(SHIFT_ALT_CTRL_PF12_KEY), 0); + + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && + ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF12_KEY, strlen(ALT_CTRL_PF12_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF12_KEY, strlen(SHIFT_ALT_PF12_KEY), 0); + + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & RIGHT_CTRL_PRESSED))) + NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF12_KEY, strlen(SHIFT_CTRL_PF12_KEY), 0); + break; + default: + NetWriteString2(pParams->Socket, (char *)octets, n, 0); + break; + } + } + } + break; + } + break; + } return glob_outlen; } - -BOOL DataAvailable(HANDLE h) -{ - DWORD dwRet = WaitForSingleObject(h, INFINITE); - if(dwRet == WAIT_OBJECT_0) - return TRUE; - - if(dwRet == WAIT_FAILED) - return FALSE; - - return FALSE; -} - -void queue_terminal_window_change_event(); - -int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) -{ - HANDLE hHandle[] = { hInput, NULL }; - DWORD nHandle = 1; - DWORD dwInput = 0; - DWORD dwControlKeyState = 0; - DWORD rc = 0; - - unsigned char szResponse[50]; - unsigned char octets[20]; - - char aChar = 0; - - INPUT_RECORD InputRecord; - - BOOL bCapsOn = FALSE; - BOOL bShift = FALSE; - - glob_out = destin; - glob_space = destinlen; - glob_outlen = 0; - - while (DataAvailable(hInput)) - { - if (glob_outlen >= destinlen) - return glob_outlen; - - ReadConsoleInput(hInput, &InputRecord, 1, &dwInput); - - switch (InputRecord.EventType) - { - case WINDOW_BUFFER_SIZE_EVENT: - queue_terminal_window_change_event(); - break; - - case FOCUS_EVENT: - case MENU_EVENT: - break; - - case KEY_EVENT: - bCapsOn = (InputRecord.Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON); - bShift = (InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED); - dwControlKeyState = InputRecord.Event.KeyEvent.dwControlKeyState & - ~(CAPSLOCK_ON | ENHANCED_KEY | NUMLOCK_ON | SCROLLLOCK_ON); - - if (InputRecord.Event.KeyEvent.bKeyDown) - { - int n = WideCharToMultiByte( - CP_UTF8, - 0, - &(InputRecord.Event.KeyEvent.uChar.UnicodeChar), - 1, - (LPSTR)octets, - 20, - NULL, - NULL); - - if (pParams->fLocalEcho) { - ConWriteString((char *)octets, n); - } - - switch (InputRecord.Event.KeyEvent.uChar.UnicodeChar) - { - case 0xd: - if (pParams->nReceiveCRLF == ENUM_LF) - NetWriteString2(pParams->Socket, "\r", 1, 0); - else - NetWriteString2(pParams->Socket, "\r\n", 2, 0); - break; - - case VK_ESCAPE: - NetWriteString2(pParams->Socket, (char *)ESCAPE_KEY, 1, 0); - break; - - default: - switch (InputRecord.Event.KeyEvent.wVirtualKeyCode) - { - case VK_UP: - NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_UP_ARROW : UP_ARROW), 3, 0); - break; - case VK_DOWN: - NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_DOWN_ARROW : DOWN_ARROW), 3, 0); - break; - case VK_RIGHT: - NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_RIGHT_ARROW : RIGHT_ARROW), 3, 0); - break; - case VK_LEFT: - NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_LEFT_ARROW : LEFT_ARROW), 3, 0); - break; - case VK_END: - NetWriteString2(pParams->Socket, (char *)SELECT_KEY, 4, 0); - break; - case VK_HOME: - NetWriteString2(pParams->Socket, (char *)FIND_KEY, 4, 0); - break; - case VK_INSERT: - NetWriteString2(pParams->Socket, (char *)INSERT_KEY, 4, 0); - break; - case VK_DELETE: - NetWriteString2(pParams->Socket, (char *)REMOVE_KEY, 4, 0); - break; - case VK_BACK: - NetWriteString2(pParams->Socket, (char *)BACKSPACE_KEY, 1, 0); - break; - case VK_TAB: - if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_TAB_KEY, 3, 0); - else - NetWriteString2(pParams->Socket, (char *)octets, n, 0); - break; - case VK_ESCAPE: - NetWriteString2(pParams->Socket, (char *)ESCAPE_KEY, 1, 0); - break; - case VK_SHIFT: - case VK_CONTROL: - case VK_CAPITAL: - // NOP on these - break; - case VK_F1: - if (dwControlKeyState == 0) - { - NetWriteString2(pParams->Socket, (char *)PF1_KEY, strlen(PF1_KEY), 0); - } - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF1_KEY, strlen(SHIFT_PF1_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF1_KEY, strlen(CTRL_PF1_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF1_KEY, strlen(ALT_PF1_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF1_KEY, strlen(SHIFT_ALT_CTRL_PF1_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF1_KEY, strlen(ALT_CTRL_PF1_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF1_KEY, strlen(SHIFT_ALT_PF1_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF1_KEY, strlen(SHIFT_CTRL_PF1_KEY), 0); - break; - case VK_F2: - if (dwControlKeyState == 0) - { - NetWriteString2(pParams->Socket, (char *)PF2_KEY, strlen(PF2_KEY), 0); - } - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF2_KEY, strlen(SHIFT_PF2_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF2_KEY, strlen(CTRL_PF2_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF2_KEY, strlen(ALT_PF2_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF2_KEY, strlen(SHIFT_ALT_CTRL_PF2_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF2_KEY, strlen(ALT_CTRL_PF2_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF2_KEY, strlen(SHIFT_ALT_PF2_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF2_KEY, strlen(SHIFT_CTRL_PF2_KEY), 0); - break; - case VK_F3: - if (dwControlKeyState == 0) - { - NetWriteString2(pParams->Socket, (char *)PF3_KEY, strlen(PF3_KEY), 0); - } - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF3_KEY, strlen(SHIFT_PF3_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF3_KEY, strlen(CTRL_PF3_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF3_KEY, strlen(ALT_PF3_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF3_KEY, strlen(SHIFT_ALT_CTRL_PF3_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF3_KEY, strlen(ALT_CTRL_PF3_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF3_KEY, strlen(SHIFT_ALT_PF3_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF3_KEY, strlen(SHIFT_CTRL_PF3_KEY), 0); - break; - case VK_F4: - if (dwControlKeyState == 0) - { - NetWriteString2(pParams->Socket, (char *)PF4_KEY, strlen(PF4_KEY), 0); - } - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF4_KEY, strlen(SHIFT_PF4_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF4_KEY, strlen(CTRL_PF4_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF4_KEY, strlen(ALT_PF4_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF4_KEY, strlen(SHIFT_ALT_CTRL_PF4_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF4_KEY, strlen(ALT_CTRL_PF4_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF4_KEY, strlen(SHIFT_ALT_PF4_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF4_KEY, strlen(SHIFT_CTRL_PF4_KEY), 0); - break; - case VK_F5: - if (dwControlKeyState == 0) - { - NetWriteString2(pParams->Socket, (char *)PF5_KEY, strlen(PF5_KEY), 0); - } - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF5_KEY, strlen(SHIFT_PF5_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF5_KEY, strlen(CTRL_PF5_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF5_KEY, strlen(ALT_PF5_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF5_KEY, strlen(SHIFT_ALT_CTRL_PF5_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF5_KEY, strlen(ALT_CTRL_PF5_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF5_KEY, strlen(SHIFT_ALT_PF5_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF5_KEY, strlen(SHIFT_CTRL_PF5_KEY), 0); - break; - case VK_F6: - if (dwControlKeyState == 0) - NetWriteString2(pParams->Socket, (char *)PF6_KEY, strlen(PF6_KEY), 0); - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF6_KEY, strlen(SHIFT_PF6_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF6_KEY, strlen(CTRL_PF6_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF6_KEY, strlen(ALT_PF6_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF6_KEY, strlen(SHIFT_ALT_CTRL_PF6_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF6_KEY, strlen(ALT_CTRL_PF6_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF6_KEY, strlen(SHIFT_ALT_PF6_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF6_KEY, strlen(SHIFT_CTRL_PF6_KEY), 0); - break; - case VK_F7: - if (dwControlKeyState == 0) - NetWriteString2(pParams->Socket, (char *)PF7_KEY, strlen(PF7_KEY), 0); - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF7_KEY, strlen(SHIFT_PF7_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF7_KEY, strlen(CTRL_PF7_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF7_KEY, strlen(ALT_PF7_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF7_KEY, strlen(SHIFT_ALT_CTRL_PF7_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF7_KEY, strlen(ALT_CTRL_PF7_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF7_KEY, strlen(SHIFT_ALT_PF7_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF7_KEY, strlen(SHIFT_CTRL_PF7_KEY), 0); - break; - case VK_F8: - if (dwControlKeyState == 0) - NetWriteString2(pParams->Socket, (char *)PF8_KEY, strlen(PF8_KEY), 0); - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF8_KEY, strlen(SHIFT_PF8_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF8_KEY, strlen(CTRL_PF8_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF8_KEY, strlen(ALT_PF8_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF8_KEY, strlen(SHIFT_ALT_CTRL_PF8_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF8_KEY, strlen(ALT_CTRL_PF8_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF8_KEY, strlen(SHIFT_ALT_PF8_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF8_KEY, strlen(SHIFT_CTRL_PF8_KEY), 0); - break; - case VK_F9: - if (dwControlKeyState == 0) - NetWriteString2(pParams->Socket, (char *)PF9_KEY, strlen(PF9_KEY), 0); - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF9_KEY, strlen(SHIFT_PF9_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF9_KEY, strlen(CTRL_PF9_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF9_KEY, strlen(ALT_PF9_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF9_KEY, strlen(SHIFT_ALT_CTRL_PF9_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF9_KEY, strlen(ALT_CTRL_PF9_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF9_KEY, strlen(SHIFT_ALT_PF9_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF9_KEY, strlen(SHIFT_CTRL_PF9_KEY), 0); - break; - case VK_F10: - if (dwControlKeyState == 0) - NetWriteString2(pParams->Socket, (char *)PF10_KEY, strlen(PF10_KEY), 0); - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF10_KEY, strlen(SHIFT_PF10_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF10_KEY, strlen(CTRL_PF10_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF10_KEY, strlen(ALT_PF10_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF10_KEY, strlen(SHIFT_ALT_CTRL_PF10_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF10_KEY, strlen(ALT_CTRL_PF10_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF10_KEY, strlen(SHIFT_ALT_PF10_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF10_KEY, strlen(SHIFT_CTRL_PF10_KEY), 0); - break; - case VK_F11: - if (dwControlKeyState == 0) - NetWriteString2(pParams->Socket, (char *)PF11_KEY, strlen(PF11_KEY), 0); - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF11_KEY, strlen(SHIFT_PF11_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF11_KEY, strlen(CTRL_PF11_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF11_KEY, strlen(ALT_PF11_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF11_KEY, strlen(SHIFT_ALT_CTRL_PF11_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF11_KEY, strlen(ALT_CTRL_PF11_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF11_KEY, strlen(SHIFT_ALT_PF11_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF11_KEY, strlen(SHIFT_CTRL_PF11_KEY), 0); - break; - case VK_F12: - if (dwControlKeyState == 0) - NetWriteString2(pParams->Socket, (char *)PF12_KEY, strlen(PF12_KEY), 0); - else if (dwControlKeyState == SHIFT_PRESSED) - NetWriteString2(pParams->Socket, (char *)SHIFT_PF12_KEY, strlen(SHIFT_PF12_KEY), 0); - else if (dwControlKeyState == LEFT_CTRL_PRESSED || - dwControlKeyState == RIGHT_CTRL_PRESSED) - NetWriteString2(pParams->Socket, (char *)CTRL_PF12_KEY, strlen(CTRL_PF12_KEY), 0); - else if (dwControlKeyState == LEFT_ALT_PRESSED || - dwControlKeyState == RIGHT_ALT_PRESSED) - NetWriteString2(pParams->Socket, (char *)ALT_PF12_KEY, strlen(ALT_PF12_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF12_KEY, strlen(SHIFT_ALT_CTRL_PF12_KEY), 0); - else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF12_KEY, strlen(ALT_CTRL_PF12_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF12_KEY, strlen(SHIFT_ALT_PF12_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) && - ((dwControlKeyState & LEFT_CTRL_PRESSED) || - (dwControlKeyState & RIGHT_CTRL_PRESSED))) - NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF12_KEY, strlen(SHIFT_CTRL_PF12_KEY), 0); - break; - default: - { - NetWriteString2(pParams->Socket, (char *)octets, n, 0); - break; - } - } - } - } - break; - } - break; - } - - return glob_outlen ; -} - - diff --git a/contrib/win32/win32compat/tnnet.c b/contrib/win32/win32compat/tnnet.c index c047414e7..11955d061 100644 --- a/contrib/win32/win32compat/tnnet.c +++ b/contrib/win32/win32compat/tnnet.c @@ -1,10 +1,11 @@ /* * Author: Microsoft Corp. * - * Copyright (c) 2015 Microsoft Corp. + * Copyright (c) 2017 Microsoft Corp. * All rights reserved * - * Microsoft openssh win32 port + * This file is responsible for terminal emulation related network calls to + * invoke ANSI parsing engine. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,61 +28,51 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* tnnet.c - * - * Contains terminal emulation related network calls to invoke ANSI parsing engine - * - */ - + #include #include #include #include #include - #include "ansiprsr.h" #define dwBuffer 4096 -// Server will always be returning a sequence of ANSI control characters which the client -// protocol can either passthru directly to the console or transform based on an output terminal -// type. We're not using termcap so we're only supporting the ANSI (vt100) sequences that -// are hardcoded in the server and will be transformed to Windows Console commands. - -size_t telProcessNetwork(char *buf, size_t len, unsigned char **respbuf, size_t *resplen) -{ +/* + * Server will always be returning a sequence of ANSI control characters which the client + * protocol can either passthru directly to the console or transform based on an output terminal + * type. We're not using termcap so we're only supporting the ANSI (vt100) sequences that + * are hardcoded in the server and will be transformed to Windows Console commands. + */ +size_t +telProcessNetwork(char *buf, size_t len, unsigned char **respbuf, size_t *resplen) { unsigned char szBuffer[dwBuffer + 8]; - unsigned char* pszNewHead = NULL; + unsigned char* pszHead = NULL; + unsigned char* pszTail = NULL; - unsigned char* pszHead = NULL; - unsigned char* pszTail = NULL; + if (len == 0) + return len; - if (len == 0) - return len; - - // Transform a single carriage return into a single linefeed before - // continuing. + /* Transform a single carriage return into a single linefeed before continuing */ if ((len == 1) && (buf[0] == 13)) buf[0] = 10; pszTail = (unsigned char *)buf; pszHead = (unsigned char *)buf; - pszTail += len; - pszNewHead = pszHead; - // Loop through the network buffer transforming characters as necessary. - // The buffer will be empty after the transformation - // process since the buffer will contain only commands that are handled by the console API. + /* + * Loop through the network buffer transforming characters as necessary. + * The buffer will be empty after the transformation + * process since the buffer will contain only commands that are handled by the console API. + */ do { pszHead = pszNewHead; pszNewHead = ParseBuffer(pszHead, pszTail, respbuf, resplen); } while ((pszNewHead != pszHead) && (pszNewHead < pszTail) && (resplen == NULL || (resplen != NULL && *resplen == 0))); - - len = 0; - + len = 0; return len; }