add optional support for win32 console

* add option to build as console by using WITH_WIN_CONSOLE
* add passphrase read from stdin for Win32
* fix windows authentication with stdin password
* allow redirected stdin to be used for stdin input
* flush stdout to help with automation
* use stdin when /from-stdin is present
* add error log for stdin flag but stdin redirected
This commit is contained in:
Alexandru Bagu 2021-10-11 16:00:52 -04:00 committed by akallabeth
parent 0e991a1078
commit 07ea60e960
5 changed files with 132 additions and 39 deletions

View File

@ -58,6 +58,12 @@ if (WIN32 AND BUILD_SHARED_LIBS)
set ( ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
endif()
if(WITH_WIN_CONSOLE)
add_definitions("-DWITH_WIN_CONSOLE")
set(WIN32_GUI_FLAG "")
else()
set(WIN32_GUI_FLAG "WIN32")
endif()
if(WITH_CLIENT_INTERFACE)
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_API_VERSION})
@ -72,7 +78,7 @@ if(WITH_CLIENT_INTERFACE)
else()
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} cli/wfreerdp.c cli/wfreerdp.h)
add_executable(${MODULE_NAME} WIN32 ${${MODULE_PREFIX}_SRCS})
add_executable(${MODULE_NAME} ${WIN32_GUI_FLAG} ${${MODULE_PREFIX}_SRCS})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "wfreerdp")
endif()

View File

@ -25,6 +25,14 @@ set(${MODULE_PREFIX}_SRCS
wfreerdp.h
../wfreerdp.rc)
if(WITH_WIN_CONSOLE)
add_definitions("-DWITH_WIN_CONSOLE")
set(WIN32_GUI_FLAG "")
else()
set(WIN32_GUI_FLAG "WIN32")
endif()
# On windows create dll version information.
# Vendor, product and year are already set in top level CMakeLists.txt
if (WIN32)
@ -40,7 +48,7 @@ if (WIN32)
set ( ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
endif()
add_executable(${MODULE_NAME} WIN32 ${${MODULE_PREFIX}_SRCS})
add_executable(${MODULE_NAME} ${WIN32_GUI_FLAG} ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} wfreerdp-client)

View File

@ -142,3 +142,10 @@ out:
LocalFree(args);
return ret;
}
#ifdef WITH_WIN_CONSOLE
int main()
{
return WinMain(NULL, NULL, NULL, 0);
}
#endif

View File

@ -35,6 +35,7 @@
#include <tchar.h>
#include <winpr/assert.h>
#include <sys/types.h>
#include <io.h>
#include <freerdp/log.h>
#include <freerdp/event.h>
@ -59,28 +60,9 @@
#define TAG CLIENT_TAG("windows")
static BOOL wf_create_console(void)
static BOOL wf_has_console(void)
{
#if defined(WITH_WIN_CONSOLE)
if (!AttachConsole(ATTACH_PARENT_PROCESS))
return FALSE;
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
clearerr(stdout);
clearerr(stderr);
fflush(stdout);
fflush(stderr);
freopen("CONIN$", "r", stdin);
clearerr(stdin);
WLog_INFO(TAG, "Debug console created.");
return TRUE;
#else
return FALSE;
#endif
return _isatty(_fileno(stdin));
}
static BOOL wf_end_paint(rdpContext* context)
@ -446,24 +428,49 @@ static BOOL wf_authenticate_raw(freerdp* instance, const char* title, char** use
dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES;
if (username && *username)
strncpy(UserName, *username, CREDUI_MAX_USERNAME_LENGTH);
if (wfc->isConsole)
status = CredUICmdLinePromptForCredentialsA(
title, NULL, 0, UserName, CREDUI_MAX_USERNAME_LENGTH + 1, Password,
CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
else
status = CredUIPromptForCredentialsA(&wfUiInfo, title, NULL, 0, UserName,
CREDUI_MAX_USERNAME_LENGTH + 1, Password,
CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
if (status != NO_ERROR)
{
WLog_ERR(TAG, "CredUIPromptForCredentials unexpected status: 0x%08lX", status);
return FALSE;
strncpy(UserName, *username, CREDUI_MAX_USERNAME_LENGTH);
strncpy(User, UserName, CREDUI_MAX_USERNAME_LENGTH);
}
status = CredUIParseUserNameA(UserName, User, sizeof(User), Domain, sizeof(Domain));
// WLog_ERR(TAG, "User: %s Domain: %s Password: %s", User, Domain, Password);
if (password && *password)
{
strncpy(Password, *password, CREDUI_MAX_PASSWORD_LENGTH);
}
if (domain && *domain)
{
strncpy(Domain, *domain, CREDUI_MAX_DOMAIN_TARGET_LENGTH);
}
if (!(username && *username && password && *password))
{
if (!wfc->isConsole && wfc->context.settings->CredentialsFromStdin)
WLog_ERR(TAG, "Flag for stdin read present but stdin is redirected; using GUI");
if (wfc->isConsole && wfc->context.settings->CredentialsFromStdin)
status = CredUICmdLinePromptForCredentialsA(
title, NULL, 0, UserName, CREDUI_MAX_USERNAME_LENGTH + 1, Password,
CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
else
status = CredUIPromptForCredentialsA(&wfUiInfo, title, NULL, 0, UserName,
CREDUI_MAX_USERNAME_LENGTH + 1, Password,
CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
if (status != NO_ERROR)
{
WLog_ERR(TAG, "CredUIPromptForCredentials unexpected status: 0x%08lX", status);
return FALSE;
}
status = CredUIParseUserNameA(UserName, User, CREDUI_MAX_USERNAME_LENGTH, Domain,
CREDUI_MAX_DOMAIN_TARGET_LENGTH);
if (status != NO_ERROR)
{
WLog_ERR(TAG, "Failed to parse UserName: %s into User: %s Domain: %s", UserName, User,
Domain);
return FALSE;
}
}
*username = _strdup(User);
if (!(*username))
@ -1031,7 +1038,7 @@ static BOOL wfreerdp_client_new(freerdp* instance, rdpContext* context)
// AttachConsole and stdin do not work well.
// Use GUI input dialogs instead of command line ones.
wfc->isConsole = wf_create_console();
wfc->isConsole = wf_has_console();
if (!(wfreerdp_client_global_init()))
return FALSE;

View File

@ -26,8 +26,73 @@
#ifdef _WIN32
#include <stdio.h>
#include <io.h>
char read_chr(int isTty)
{
if (isTty)
return _getch();
char chr;
if (scanf_s("%c", &chr, (UINT32)sizeof(char)) && !feof(stdin))
return chr;
return 0;
}
char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz, int from_stdin)
{
const char CTRLC = 3;
const char BACKSPACE = '\b';
const char NEWLINE = '\n';
const char CARRIAGERETURN = '\r';
const char SHOW_ASTERISK = TRUE;
if (from_stdin)
{
printf("%s ", prompt);
fflush(stdout);
size_t read_cnt = 0, chr;
char isTty = _isatty(_fileno(stdin));
while (read_cnt < bufsiz - 1 && (chr = read_chr(isTty)) && chr != NEWLINE &&
chr != CARRIAGERETURN)
{
if (chr == BACKSPACE)
{
if (read_cnt > 0)
{
if (SHOW_ASTERISK)
printf("\b \b");
read_cnt--;
}
}
else if (chr == CTRLC)
{
if (read_cnt != 0)
{
while (read_cnt > 0)
{
if (SHOW_ASTERISK)
printf("\b \b");
read_cnt--;
}
}
else
goto fail;
}
else
{
*(buf + read_cnt) = chr;
read_cnt++;
if (SHOW_ASTERISK)
printf("*");
}
}
*(buf + read_cnt) = '\0';
printf("\n");
fflush(stdout);
return buf;
}
fail:
errno = ENOSYS;
return NULL;
}