@@ -38,6 +38,9 @@ typedef struct {
3838 HANDLE stdOut ;
3939
4040 HANDLE events [2 ];
41+ HANDLE inputHandler ;
42+ DWORD originalConsoleMode ;
43+ HPCON hpcon ;
4144} Context ;
4245
4346static void ParseArgs (int argc , const wchar_t * * wargv , char * * argv , Context * ctx );
@@ -47,6 +50,8 @@ static HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEXW* star
4750 HPCON hpcon );
4851static void __cdecl PipeListener (LPVOID );
4952static void __cdecl InputHandlerThread (LPVOID );
53+ static void __cdecl ResizeHandlerThread (LPVOID );
54+ static void CloseInputHandler (Context * ctx );
5055
5156static wchar_t * ToUtf16 (const char * utf8 ) {
5257 if (utf8 == NULL ) {
@@ -127,11 +132,15 @@ int wmain(int argc, const wchar_t* argv[]) {
127132 ctx .pipeIn = INVALID_HANDLE_VALUE ;
128133 ctx .pipeOut = INVALID_HANDLE_VALUE ;
129134 ctx .stdOut = GetStdHandle (STD_OUTPUT_HANDLE );
135+ ctx .inputHandler = INVALID_HANDLE_VALUE ;
130136 ctx .events [0 ] = CreateEvent (NULL , FALSE, FALSE, NULL );
131137 if (ctx .events [0 ] == NULL ) {
132138 return EXIT_FAILURE ;
133139 }
134140
141+ HANDLE hStdin = GetStdHandle (STD_INPUT_HANDLE );
142+ GetConsoleMode (hStdin , & ctx .originalConsoleMode );
143+
135144 DWORD consoleMode = 0 ;
136145 GetConsoleMode (ctx .stdOut , & consoleMode );
137146 SetConsoleMode (ctx .stdOut , consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING );
@@ -140,6 +149,7 @@ int wmain(int argc, const wchar_t* argv[]) {
140149
141150 hr = CreatePseudoConsoleAndPipes (& hpcon , & ctx );
142151 if (S_OK == hr ) {
152+ ctx .hpcon = hpcon ;
143153 HANDLE pipeListener = (HANDLE ) _beginthread (PipeListener , 0 , & ctx );
144154
145155 STARTUPINFOEXW startupInfo = {0 };
@@ -154,11 +164,14 @@ int wmain(int argc, const wchar_t* argv[]) {
154164 if (S_OK == hr ) {
155165 ctx .events [1 ] = cmdProc .hThread ;
156166
157- HANDLE inputHandler = (HANDLE ) _beginthread (InputHandlerThread , 0 , & ctx );
167+ ctx .inputHandler = (HANDLE ) _beginthread (InputHandlerThread , 0 , & ctx );
168+ _beginthread (ResizeHandlerThread , 0 , & ctx );
158169
159170 WaitForMultipleObjects (sizeof (ctx .events ) / sizeof (HANDLE ), ctx .events , FALSE,
160171 INFINITE );
161172
173+ CloseInputHandler (& ctx );
174+
162175 GetExitCodeProcess (cmdProc .hProcess , & childExitCode );
163176 }
164177
@@ -335,6 +348,7 @@ typedef enum { INIT, VERIFY, EXEC, END } State;
335348
336349static State ProcessOutput (Context * ctx , const char * buffer , DWORD len , State state ) {
337350 State nextState ;
351+ DWORD written ;
338352 switch (state ) {
339353 case INIT : {
340354 if (!IsWaitInputPass (ctx , buffer , len )) {
@@ -349,12 +363,12 @@ static State ProcessOutput(Context* ctx, const char* buffer, DWORD len, State st
349363 fprintf (stderr , "Password is error!" );
350364 nextState = END ;
351365 } else {
352- fprintf ( stdout , "%s" , buffer );
366+ WriteFile ( ctx -> stdOut , buffer , len , & written , NULL );
353367 nextState = EXEC ;
354368 }
355369 } break ;
356370 case EXEC : {
357- fprintf ( stdout , "%s" , buffer );
371+ WriteFile ( ctx -> stdOut , buffer , len , & written , NULL );
358372 nextState = EXEC ;
359373 } break ;
360374 case END : {
@@ -443,22 +457,65 @@ static void __cdecl InputHandlerThread(LPVOID arg) {
443457 DWORD mode ;
444458
445459 GetConsoleMode (hStdin , & mode );
446- mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT );
460+ mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT );
447461 mode |= ENABLE_VIRTUAL_TERMINAL_INPUT ;
448462 SetConsoleMode (hStdin , mode );
449463
450- char buffer ;
451- DWORD bytesRead , bytesWritten ;
464+ wchar_t buffer [ 64 ] ;
465+ DWORD charsRead , bytesWritten ;
452466
453467 while (1 ) {
454- if (!ReadFile (hStdin , & buffer , 1 , & bytesRead , NULL ) || bytesRead == 0 ) {
468+ if (!ReadConsoleW (hStdin , buffer , sizeof ( buffer ) / sizeof ( wchar_t ) , & charsRead , NULL ) || charsRead == 0 ) {
455469 break ;
456470 }
457471
458- if (!WriteFile (ctx -> pipeOut , & buffer , 1 , & bytesWritten , NULL )) {
459- break ;
472+ char utf8Buffer [256 ];
473+ int utf8Len = WideCharToMultiByte (CP_UTF8 , 0 , buffer , charsRead , utf8Buffer , sizeof (utf8Buffer ), NULL , NULL );
474+ if (utf8Len > 0 ) {
475+ if (!WriteFile (ctx -> pipeOut , utf8Buffer , utf8Len , & bytesWritten , NULL )) {
476+ break ;
477+ }
460478 }
461479 }
480+ }
462481
463- SetConsoleMode (hStdin , mode );
482+ static void CloseInputHandler (Context * ctx ) {
483+ HANDLE hStdin = GetStdHandle (STD_INPUT_HANDLE );
484+
485+ if (ctx -> pipeOut != INVALID_HANDLE_VALUE ) {
486+ CloseHandle (ctx -> pipeOut );
487+ ctx -> pipeOut = INVALID_HANDLE_VALUE ;
488+ }
489+
490+ if (ctx -> inputHandler != INVALID_HANDLE_VALUE ) {
491+ WaitForSingleObject (ctx -> inputHandler , 1000 );
492+ }
493+
494+ SetConsoleMode (hStdin , ctx -> originalConsoleMode );
495+ }
496+
497+ static void __cdecl ResizeHandlerThread (LPVOID arg ) {
498+ Context * ctx = arg ;
499+ HANDLE hConsole = GetStdHandle (STD_OUTPUT_HANDLE );
500+ COORD currentSize = {0 , 0 };
501+ CONSOLE_SCREEN_BUFFER_INFO csbi ;
502+
503+ if (GetConsoleScreenBufferInfo (hConsole , & csbi )) {
504+ currentSize .X = csbi .srWindow .Right - csbi .srWindow .Left + 1 ;
505+ currentSize .Y = csbi .srWindow .Bottom - csbi .srWindow .Top + 1 ;
506+ }
507+
508+ while (WaitForMultipleObjects (sizeof (ctx -> events ) / sizeof (HANDLE ), ctx -> events , FALSE, 100 ) ==
509+ WAIT_TIMEOUT ) {
510+ if (GetConsoleScreenBufferInfo (hConsole , & csbi )) {
511+ COORD newSize ;
512+ newSize .X = csbi .srWindow .Right - csbi .srWindow .Left + 1 ;
513+ newSize .Y = csbi .srWindow .Bottom - csbi .srWindow .Top + 1 ;
514+
515+ if (newSize .X != currentSize .X || newSize .Y != currentSize .Y ) {
516+ currentSize = newSize ;
517+ ResizePseudoConsole (ctx -> hpcon , currentSize );
518+ }
519+ }
520+ }
464521}
0 commit comments