diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 64834723f..6ab187b23 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -757,10 +757,7 @@ fileio_stat(const char *path, struct _stat64 *buf) WIN32_FILE_ATTRIBUTE_DATA attributes = { 0 }; int ret = -1, len = 0; - if ((wpath = utf8_to_utf16(path)) == NULL) { - errno = ENOMEM; - return -1; - } + memset(buf, 0, sizeof(struct _stat64)); /* Detect root dir */ if (path && strcmp(path, "/") == 0) { @@ -770,7 +767,7 @@ fileio_stat(const char *path, struct _stat64 *buf) } if ((wpath = utf8_to_utf16(path)) == NULL) { - errno = errno_from_Win32LastError(); + errno = ENOMEM; debug3("utf8_to_utf16 failed for file:%s error:%d", path, GetLastError()); return -1; } @@ -781,7 +778,7 @@ fileio_stat(const char *path, struct _stat64 *buf) goto cleanup; } - len = wcslen(wpath); + len = (int)wcslen(wpath); buf->st_ino = 0; /* Has no meaning in the FAT, HPFS, or NTFS file systems*/ buf->st_gid = 0; /* UNIX - specific; has no meaning on windows */ diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index a5ce51858..f016eaaa8 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -482,10 +482,10 @@ strmode(mode_t mode, char *p) * As of now we are keeping "*" for everything. * TODO - figure out if there is a better option */ - const char *permissions = "********* "; - strncpy(p, permissions, strlen(permissions) + 1); - - p = p + strlen(p); + const char *permissions = "********* "; + for(int i = 0; i < strlen(permissions); i++) + *p++ = permissions[i]; + *p = '\0'; } @@ -535,11 +535,10 @@ static BOOL is_root_or_empty(wchar_t * path) { wchar_t * path_start; - BOOL has_drive_letter_and_colon; int len; if (!path) return FALSE; - len = wcslen(path); + len = (int)wcslen(path); if((len > 1) && __ascii_iswalpha(path[0]) && path[1] == L':') path_start = path + 2; else diff --git a/contrib/win32/win32compat/misc_internal.h b/contrib/win32/win32compat/misc_internal.h index 6f2d30570..abf818ab6 100644 --- a/contrib/win32/win32compat/misc_internal.h +++ b/contrib/win32/win32compat/misc_internal.h @@ -29,4 +29,5 @@ void convertToForwardslash(char *str); #define errno_from_Win32LastError() errno_from_Win32Error(GetLastError()) int errno_from_Win32Error(int); void unix_time_to_file_time(ULONG, LPFILETIME); -void file_time_unix_time(const LPFILETIME, time_t *); +void file_time_to_unix_time(const LPFILETIME, time_t *); +int file_attr_to_st_mode(wchar_t * path, DWORD attributes); \ No newline at end of file diff --git a/contrib/win32/win32compat/shell-host.c b/contrib/win32/win32compat/shell-host.c index f19a3c36f..f50443fff 100644 --- a/contrib/win32/win32compat/shell-host.c +++ b/contrib/win32/win32compat/shell-host.c @@ -86,39 +86,41 @@ typedef struct consoleEvent { } consoleEvent; struct key_translation { - char incoming[6]; + wchar_t in[6]; int vk; - char outgoing; + wchar_t out; + int in_key_len; } key_translation; +/* All the substrings (Ex- "\x1b") should be in the end, otherwise ProcessIncomingKeys() will not work as expected */ struct key_translation keys[] = { - { "\x1b", VK_ESCAPE, '\x1b' }, - { "\r", VK_RETURN, '\r' }, - { "\b", VK_BACK, '\b' }, - { "\x7f", VK_BACK, '\b' }, - { "\t", VK_TAB, '\t' }, - { "\x1b[A", VK_UP, 0 }, - { "\x1b[B", VK_DOWN, 0 }, - { "\x1b[C", VK_RIGHT, 0 }, - { "\x1b[D", VK_LEFT, 0 }, - { "\x1b[1~", VK_HOME, 0 }, - { "\x1b[2~", VK_INSERT, 0 }, - { "\x1b[3~", VK_DELETE, 0 }, - { "\x1b[4~", VK_END, 0 }, - { "\x1b[5~", VK_PRIOR, 0 }, - { "\x1b[6~", VK_NEXT, 0 }, - { "\x1b[11~", VK_F1, 0 }, - { "\x1b[12~", VK_F2, 0 }, - { "\x1b[13~", VK_F3, 0 }, - { "\x1b[14~", VK_F4, 0 }, - { "\x1b[15~", VK_F5, 0 }, - { "\x1b[17~", VK_F6, 0 }, - { "\x1b[18~", VK_F7, 0 }, - { "\x1b[19~", VK_F8, 0 }, - { "\x1b[20~", VK_F9, 0 }, - { "\x1b[21~", VK_F10, 0 }, - { "\x1b[23~", VK_F11, 0 }, - { "\x1b[24~", VK_F12, 0 } + { L"\r", VK_RETURN, L'\r' , 0}, + { L"\b", VK_BACK, L'\b' , 0}, + { L"\x7f", VK_BACK, L'\b' , 0}, + { L"\t", VK_TAB, L'\t' , 0}, + { L"\x1b[A", VK_UP, 0 , 0}, + { L"\x1b[B", VK_DOWN, 0 , 0}, + { L"\x1b[C", VK_RIGHT, 0 , 0}, + { L"\x1b[D", VK_LEFT, 0 , 0}, + { L"\x1b[1~", VK_HOME, 0 , 0}, + { L"\x1b[2~", VK_INSERT, 0 , 0}, + { L"\x1b[3~", VK_DELETE, 0 , 0}, + { L"\x1b[4~", VK_END, 0 , 0}, + { L"\x1b[5~", VK_PRIOR, 0 , 0}, + { L"\x1b[6~", VK_NEXT, 0 , 0}, + { L"\x1b[11~", VK_F1, 0 , 0}, + { L"\x1b[12~", VK_F2, 0 , 0}, + { L"\x1b[13~", VK_F3, 0 , 0}, + { L"\x1b[14~", VK_F4, 0 , 0}, + { L"\x1b[15~", VK_F5, 0 , 0}, + { L"\x1b[17~", VK_F6, 0 , 0}, + { L"\x1b[18~", VK_F7, 0 , 0}, + { L"\x1b[19~", VK_F8, 0 , 0}, + { L"\x1b[20~", VK_F9, 0 , 0}, + { L"\x1b[21~", VK_F10, 0 , 0}, + { L"\x1b[23~", VK_F11, 0 , 0}, + { L"\x1b[24~", VK_F12, 0 , 0}, + { L"\x1b", VK_ESCAPE, L'\x1b' , 0} }; static SHORT lastX = 0; @@ -130,7 +132,6 @@ consoleEvent* tail = NULL; BOOL bRet = FALSE; BOOL bNoScrollRegion = FALSE; BOOL bStartup = TRUE; -BOOL bAnsi = FALSE; BOOL bHookEvents = FALSE; BOOL bFullScreen = FALSE; BOOL bUseAnsiEmulation = TRUE; @@ -142,13 +143,12 @@ HANDLE pipe_in = INVALID_HANDLE_VALUE; HANDLE pipe_out = INVALID_HANDLE_VALUE; HANDLE pipe_err = INVALID_HANDLE_VALUE; HANDLE child = INVALID_HANDLE_VALUE; -DWORD child_exit_code = 0; HANDLE hConsoleBuffer = INVALID_HANDLE_VALUE; - HANDLE monitor_thread = INVALID_HANDLE_VALUE; HANDLE io_thread = INVALID_HANDLE_VALUE; HANDLE ux_thread = INVALID_HANDLE_VALUE; +DWORD child_exit_code = 0; DWORD hostProcessId = 0; DWORD hostThreadId = 0; DWORD childProcessId = 0; @@ -196,7 +196,7 @@ ConSRWidth() * This function will handle the console keystrokes. */ void -SendKeyStroke(HANDLE hInput, int keyStroke, char character) +SendKeyStroke(HANDLE hInput, int keyStroke, wchar_t character) { DWORD wr = 0; INPUT_RECORD ir; @@ -207,32 +207,48 @@ SendKeyStroke(HANDLE hInput, int keyStroke, char character) ir.Event.KeyEvent.wVirtualKeyCode = keyStroke; ir.Event.KeyEvent.wVirtualScanCode = 0; ir.Event.KeyEvent.dwControlKeyState = 0; - ir.Event.KeyEvent.uChar.UnicodeChar = 0; - ir.Event.KeyEvent.uChar.AsciiChar = character; + ir.Event.KeyEvent.uChar.UnicodeChar = character; - WriteConsoleInputA(hInput, &ir, 1, &wr); + WriteConsoleInputW(hInput, &ir, 1, &wr); ir.Event.KeyEvent.bKeyDown = FALSE; - WriteConsoleInputA(hInput, &ir, 1, &wr); + WriteConsoleInputW(hInput, &ir, 1, &wr); +} + +void +initialize_keylen() +{ + for(int i = 0; i < ARRAYSIZE(keys); i++) + keys[i].in_key_len = (int) wcslen(keys[i].in); } void ProcessIncomingKeys(char * ansikey) { - int keylen = (int) strlen(ansikey); - - if (!keylen) - return; - - for (int nKey=0; nKey < ARRAYSIZE(keys); nKey++) { - if (strcmp(ansikey, keys[nKey].incoming) == 0) { - SendKeyStroke(child_in, keys[nKey].vk, keys[nKey].outgoing); - return; - } + wchar_t *buf = utf8_to_utf16(ansikey); + + if (!buf) { + printf("\nFailed to deserialize the client data, error:%d\n", GetLastError()); + exit(255); } - for (int i=0; i < keylen; i++) - SendKeyStroke(child_in, 0, ansikey[i]); + loop: + while (buf && (wcslen(buf) > 0)) { + for (int j = 0; j < ARRAYSIZE(keys); j++) { + if ( (wcslen(buf) >= keys[j].in_key_len) && (wcsncmp(buf, keys[j].in, keys[j].in_key_len) == 0) ) { + SendKeyStroke(child_in, keys[j].vk, keys[j].out); + buf += keys[j].in_key_len; + goto loop; + } + } + + if (*buf == L'\x3') /*Ctrl+C - Raise Ctrl+C*/ + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + else + SendKeyStroke(child_in, 0, *buf); + + buf++; + } } /* @@ -458,8 +474,7 @@ SizeWindow(HANDLE hInput) matchingFont.dwFontSize.X = 0; matchingFont.dwFontSize.Y = 16; matchingFont.FontFamily = FF_DONTCARE; - matchingFont.FontWeight = FW_NORMAL; - //wcscpy(matchingFont.FaceName, L"Consolas"); + matchingFont.FontWeight = FW_NORMAL; wcscpy_s(matchingFont.FaceName, LF_FACESIZE, L"Consolas"); bSuccess = __SetCurrentConsoleFontEx(child_out, FALSE, &matchingFont); @@ -741,19 +756,6 @@ ProcessEvent(void *p) DWORD WINAPI ProcessEventQueue(LPVOID p) { - 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; - } - while (1) { while (head) { EnterCriticalSection(&criticalSection); @@ -853,32 +855,18 @@ DWORD WINAPI ProcessPipes(LPVOID p) { BOOL ret; - DWORD dwStatus; + DWORD dwStatus; char buf[128]; /* process data from pipe_in and route appropriately */ - while (1) { + while (1) { ZeroMemory(buf, sizeof(buf)); int rd = 0; GOTO_CLEANUP_ON_FALSE(ReadFile(pipe_in, buf, sizeof(buf) - 1, &rd, NULL)); /* read bufsize-1 */ bStartup = FALSE; - for (int i=0; i < rd; i++) { - if (buf[i] == 0) - break; - - if (buf[i] == 3) { /*Ctrl+C - Raise Ctrl+C*/ - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); - continue; - } - - if (bAnsi) - SendKeyStroke(child_in, 0, buf[i]); - else { - ProcessIncomingKeys(buf); - break; - } - } + if(rd > 0) + ProcessIncomingKeys(buf); } cleanup: @@ -964,8 +952,8 @@ start_with_pty(wchar_t *command) HMODULE hm_kernel32 = NULL, hm_user32 = NULL; if(cmd == NULL) { - printf("ssh-shellhost - out of memory"); - return -1; + printf("ssh-shellhost is out of memory"); + exit(255); } if ((hm_kernel32 = LoadLibraryW(L"kernel32.dll")) == NULL || @@ -1047,6 +1035,8 @@ start_with_pty(wchar_t *command) /* disable Ctrl+C hander in this process*/ SetConsoleCtrlHandler(NULL, TRUE); + + initialize_keylen(); io_thread = CreateThread(NULL, 0, ProcessPipes, NULL, 0, NULL); if (IS_INVALID_HANDLE(io_thread)) @@ -1118,6 +1108,11 @@ start_withno_pty(wchar_t *command) char buf[128]; DWORD rd = 0, wr = 0, i = 0; + if (cmd == NULL) { + printf("ssh-shellhost is out of memory"); + exit(255); + } + pipe_in = GetStdHandle(STD_INPUT_HANDLE); pipe_out = GetStdHandle(STD_OUTPUT_HANDLE); pipe_err = GetStdHandle(STD_ERROR_HANDLE); diff --git a/contrib/win32/win32compat/win32_dirent.c b/contrib/win32/win32compat/win32_dirent.c index 7c2d3eb3a..c6488f025 100644 --- a/contrib/win32/win32compat/win32_dirent.c +++ b/contrib/win32/win32compat/win32_dirent.c @@ -100,7 +100,6 @@ opendir(const char *name) DIR *pdir; wchar_t searchstr[PATH_MAX]; wchar_t* wname = NULL; - int needed; size_t len; /* Detect root dir */ diff --git a/session.c b/session.c index 03bed3b65..67720e797 100644 --- a/session.c +++ b/session.c @@ -367,9 +367,9 @@ int register_child(void* child, unsigned long pid); int do_exec_windows(Session *s, const char *command, int pty) { int pipein[2], pipeout[2], pipeerr[2], r; - char *exec_command = NULL, *progdir = w32_programdir(), *cmd = NULL, *shell_host = NULL, *command_b64 = NULL, *argp = NULL; + char *exec_command = NULL, *progdir = w32_programdir(), *cmd = NULL, *shell_host = NULL, *command_b64 = NULL; wchar_t *exec_command_w = NULL, *pw_dir_w; - const char *sftp_exe = "sftp-server.exe"; + const char *sftp_exe = "sftp-server.exe", *argp = NULL; size_t command_b64_len = 0; PROCESS_INFORMATION pi; STARTUPINFOW si;