From ab496941011efc4c8d8df9c0a78ee96e8855be47 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 12 Apr 2021 11:06:45 +0200 Subject: [PATCH] Added new RDP file options --- channels/client/addin.c | 3 +- .../urbdrc/client/libusb/libusb_udevman.c | 79 +-- channels/urbdrc/client/urbdrc_main.c | 4 + client/common/cmdline.c | 17 +- client/common/file.c | 473 ++++++++++++++---- client/common/test/TestClientRdpFile.c | 255 ++++++++-- libfreerdp/common/settings.c | 34 +- libfreerdp/primitives/test/measure.h | 3 +- winpr/include/winpr/cmdline.h | 2 + winpr/libwinpr/utils/cmdline.c | 27 +- 10 files changed, 691 insertions(+), 206 deletions(-) diff --git a/channels/client/addin.c b/channels/client/addin.c index 2ffa214f2..c82b57ad3 100644 --- a/channels/client/addin.c +++ b/channels/client/addin.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -498,7 +499,7 @@ void* channel_client_create_handler(rdpContext* ctx, LPVOID userdata, MsgHandler } internals->msg_handler = msg_handler; internals->userdata = userdata; - internals->channel_name = strdup(channel_name); + internals->channel_name = _strdup(channel_name); internals->ctx = ctx; if (!(ctx->settings->ThreadingFlags & THREADING_FLAGS_DISABLE_THREADS)) { diff --git a/channels/urbdrc/client/libusb/libusb_udevman.c b/channels/urbdrc/client/libusb/libusb_udevman.c index ff901b80a..8e51041b2 100644 --- a/channels/urbdrc/client/libusb/libusb_udevman.c +++ b/channels/urbdrc/client/libusb/libusb_udevman.c @@ -716,66 +716,67 @@ static BOOL urbdrc_udevman_register_devices(UDEVMAN* udevman, const char* device static UINT urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, const ADDIN_ARGV* args) { - int status; + int x; LPSTR devices = NULL; - COMMAND_LINE_ARGUMENT_A* arg; - COMMAND_LINE_ARGUMENT_A urbdrc_udevman_args[] = { - { "dbg", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "debug" }, - { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "device list" }, - { "id", COMMAND_LINE_VALUE_OPTIONAL, "", NULL, BoolValueFalse, -1, NULL, - "FLAG_ADD_BY_VID_PID" }, - { "addr", COMMAND_LINE_VALUE_OPTIONAL, "", NULL, BoolValueFalse, -1, NULL, - "FLAG_ADD_BY_ADDR" }, - { "auto", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_AUTO" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } - }; - status = CommandLineParseArgumentsA(args->argc, args->argv, urbdrc_udevman_args, - COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON, - udevman, NULL, NULL); - - if (status != CHANNEL_RC_OK) - return status; - - arg = urbdrc_udevman_args; - - do + for (x = 0; x < args->argc; x++) { - if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)) - continue; - - CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dbg") + const char* arg = args->argv[x]; + if (strcmp(arg, "dbg") == 0) { WLog_SetLogLevel(WLog_Get(TAG), WLOG_TRACE); } - CommandLineSwitchCase(arg, "dev") + else if (_strnicmp(arg, "device:", 7) == 0) { - devices = arg->Value; + /* Redirect all local devices */ + const char* val = &arg[7]; + const size_t len = strlen(val); + if (strcmp(val, "*") == 0) + { + udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO; + } + else if (_strnicmp(arg, "USBInstanceID:", 14) == 0) + { + // TODO: Usb instance ID + } + else if ((val[0] == '{') && (val[len - 1] == '}')) + { + // TODO: Usb device class + } } - CommandLineSwitchCase(arg, "id") + else if (_strnicmp(arg, "dev:", 4) == 0) { - if (arg->Value) - udevman->devices_vid_pid = arg->Value; + devices = &arg[4]; + } + else if (_strnicmp(arg, "id", 2) == 0) + { + const char* p = strchr(arg, ':'); + if (p) + udevman->devices_vid_pid = p + 1; else udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID; } - CommandLineSwitchCase(arg, "addr") + else if (_strnicmp(arg, "addr", 4) == 0) { - if (arg->Value) - udevman->devices_addr = arg->Value; + const char* p = strchr(arg, ':'); + if (p) + udevman->devices_addr = p + 1; else udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR; } - CommandLineSwitchCase(arg, "auto") + else if (strcmp(arg, "auto") == 0) { udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO; } - CommandLineSwitchDefault(arg) + else { + const size_t len = strlen(arg); + if ((arg[0] == '{') && (arg[len - 1] == '}')) + { + // TODO: Check for {Device Setup Class GUID}: + } } - CommandLineSwitchEnd(arg) - } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); - + } if (devices) { if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID) diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c index 17480eb38..9a475ee9e 100644 --- a/channels/urbdrc/client/urbdrc_main.c +++ b/channels/urbdrc/client/urbdrc_main.c @@ -804,6 +804,10 @@ static UINT urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, const ADDIN_ARGV* a COMMAND_LINE_ARGUMENT_A urbdrc_args[] = { { "dbg", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "debug" }, { "sys", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "subsystem" }, + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "devices" }, + { "encode", COMMAND_LINE_VALUE_FLAG, "", NULL, NULL, -1, NULL, "encode" }, + { "quality", COMMAND_LINE_VALUE_REQUIRED, "<[0-2] -> [high-medium-low]>", NULL, NULL, -1, + NULL, "quality" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 2f96ae087..5aca273db 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1831,6 +1831,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, UINT32 i; char** p; size_t count = 0; + UINT32* MonitorIds; p = CommandLineParseCommaSeparatedValues(arg->Value, &count); if (!p) @@ -1839,16 +1840,22 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (count > 16) count = 16; - settings->NumMonitorIds = (UINT32)count; + if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, NULL, count)) + { + free(p); + return FALSE; + } - for (i = 0; i < settings->NumMonitorIds; i++) + MonitorIds = + freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorIds, 0); + for (i = 0; i < count; i++) { LONGLONG val; if (!value_to_int(p[i], &val, 0, UINT16_MAX)) return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; - settings->MonitorIds[i] = (UINT32)val; + MonitorIds[i] = (UINT32)val; } free(p); @@ -3773,7 +3780,7 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) return FALSE; } - if (settings->SupportGeometryTracking) + if (freerdp_settings_get_bool(settings, FreeRDP_SupportGeometryTracking)) { char* p[1]; size_t count; @@ -3784,7 +3791,7 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) return FALSE; } - if (settings->SupportVideoOptimized) + if (freerdp_settings_get_bool(settings, FreeRDP_SupportVideoOptimized)) { char* p[1]; size_t count; diff --git a/client/common/file.c b/client/common/file.c index 6fb976f46..8f09643d3 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -23,16 +23,23 @@ #include #include +#include + +#include #include #include +#include + /** * Remote Desktop Plus - Overview of .rdp file settings: * http://www.donkz.nl/files/rdpsettings.html * * RDP Settings for Remote Desktop Services in Windows Server 2008 R2: * http://technet.microsoft.com/en-us/library/ff393699/ + * + * https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/rdp-files */ #include @@ -79,9 +86,13 @@ typedef struct rdp_file_line rdpFileLine; struct rdp_file { DWORD UseMultiMon; /* use multimon */ + LPSTR SelectedMonitors; /* selectedmonitors */ + DWORD MaximizeToCurrentDisplays; /* maximizetocurrentdisplays */ + DWORD SingleMonInWindowedMode; /* singlemoninwindowedmode */ DWORD ScreenModeId; /* screen mode id */ DWORD SpanMonitors; /* span monitors */ DWORD SmartSizing; /* smartsizing */ + DWORD DynamicResolution; /* dynamic resolution */ DWORD EnableSuperSpan; /* enablesuperpan */ DWORD SuperSpanAccelerationFactor; /* superpanaccelerationfactor */ @@ -89,6 +100,7 @@ struct rdp_file DWORD DesktopHeight; /* desktopheight */ DWORD DesktopSizeId; /* desktop size id */ DWORD SessionBpp; /* session bpp */ + DWORD DesktopScaleFactor; /* desktopscalefactor */ DWORD Compression; /* compression */ DWORD KeyboardHook; /* keyboardhook */ @@ -97,6 +109,8 @@ struct rdp_file DWORD AudioMode; /* audiomode */ DWORD AudioQualityMode; /* audioqualitymode */ DWORD AudioCaptureMode; /* audiocapturemode */ + DWORD EncodeRedirectedVideoCapture; /* encode redirected video capture */ + DWORD RedirectedVideoCaptureEncodingQuality; /* redirected video capture encoding quality */ DWORD VideoPlaybackMode; /* videoplaybackmode */ DWORD ConnectionType; /* connection type */ @@ -223,12 +237,18 @@ static BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, if (_stricmp(name, "use multimon") == 0) file->UseMultiMon = (UINT32)value; + else if (_stricmp(name, "maximizetocurrentdisplays") == 0) + file->MaximizeToCurrentDisplays = (UINT32)value; + else if (_stricmp(name, "singlemoninwindowedmode") == 0) + file->SingleMonInWindowedMode = (UINT32)value; else if (_stricmp(name, "screen mode id") == 0) file->ScreenModeId = (UINT32)value; else if (_stricmp(name, "span monitors") == 0) file->SpanMonitors = (UINT32)value; else if (_stricmp(name, "smart sizing") == 0) file->SmartSizing = (UINT32)value; + else if (_stricmp(name, "dynamic resolution") == 0) + file->DynamicResolution = (UINT32)value; else if (_stricmp(name, "enablesuperpan") == 0) file->EnableSuperSpan = (UINT32)value; else if (_stricmp(name, "superpanaccelerationfactor") == 0) @@ -241,6 +261,8 @@ static BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, file->DesktopSizeId = (UINT32)value; else if (_stricmp(name, "session bpp") == 0) file->SessionBpp = (UINT32)value; + else if (_stricmp(name, "desktopscalefactor") == 0) + file->DesktopScaleFactor = (UINT32)value; else if (_stricmp(name, "compression") == 0) file->Compression = (UINT32)value; else if (_stricmp(name, "keyboardhook") == 0) @@ -253,6 +275,10 @@ static BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, file->AudioQualityMode = (UINT32)value; else if (_stricmp(name, "audiocapturemode") == 0) file->AudioCaptureMode = (UINT32)value; + else if (_stricmp(name, "encode redirected video capture") == 0) + file->EncodeRedirectedVideoCapture = (UINT32)value; + else if (_stricmp(name, "redirected video capture encoding quality") == 0) + file->RedirectedVideoCaptureEncodingQuality = (UINT32)value; else if (_stricmp(name, "videoplaybackmode") == 0) file->VideoPlaybackMode = (UINT32)value; else if (_stricmp(name, "connection type") == 0) @@ -464,6 +490,8 @@ static int freerdp_client_rdp_file_set_string(rdpFile* file, const char* name, c tmp = &file->WinPosStr; else if (_stricmp(name, "pcb") == 0) tmp = &file->PreconnectionBlob; + else if (_stricmp(name, "selectedmonitors") == 0) + tmp = &file->SelectedMonitors; else standard = 1; @@ -642,6 +670,8 @@ static BOOL trim_strings(rdpFile* file) return FALSE; if (!trim(&file->KdcProxyName)) return FALSE; + if (!trim(&file->SelectedMonitors)) + return FALSE; return TRUE; } @@ -829,75 +859,110 @@ BOOL freerdp_client_parse_rdp_file_ex(rdpFile* file, const char* name, rdp_file_ return status; } -#define FILE_POPULATE_STRING(_target, _setting) \ - do \ - { \ - if (_setting) \ - { \ - freerdp_client_file_string_check_free(_target); \ - _target = _strdup(_setting); \ - if (!_target) \ - return FALSE; \ - } \ - } while (0) +static INLINE BOOL FILE_POPULATE_STRING(char** _target, const rdpSettings* _settings, + size_t _option) +{ + const char* str; + if (!_target || !_settings) + return FALSE; -static char* freerdp_client_channel_args_to_string(const rdpSettings* settings, const char* channel) + str = freerdp_settings_get_string(_settings, _option); + freerdp_client_file_string_check_free(*_target); + *_target = NULL; + if (str) + { + *_target = _strdup(str); + if (!_target) + return FALSE; + } + return TRUE; +} + +static char* freerdp_client_channel_args_to_string(const rdpSettings* settings, const char* channel, + const char* option) { ADDIN_ARGV* args = freerdp_dynamic_channel_collection_find(settings, channel); + const char* filters[] = { option }; if (!args || (args->argc < 2)) return NULL; - return CommandLineToCommaSeparatedValues(args->argc - 1, args->argv + 1); + return CommandLineToCommaSeparatedValuesEx(args->argc - 1, args->argv + 1, filters, + ARRAYSIZE(filters)); } BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSettings* settings) { - FILE_POPULATE_STRING(file->Domain, settings->Domain); - FILE_POPULATE_STRING(file->Username, settings->Username); - FILE_POPULATE_STRING(file->Password, settings->Password); - file->ServerPort = settings->ServerPort; - FILE_POPULATE_STRING(file->FullAddress, settings->ServerHostname); - FILE_POPULATE_STRING(file->AlternateFullAddress, settings->ServerHostname); - file->DesktopWidth = settings->DesktopWidth; - file->DesktopHeight = settings->DesktopHeight; - file->SessionBpp = settings->ColorDepth; - file->ConnectToConsole = settings->ConsoleSession; - file->NegotiateSecurityLayer = settings->NegotiateSecurityLayer; - file->EnableCredSSPSupport = settings->NlaSecurity; - FILE_POPULATE_STRING(file->AlternateShell, settings->AlternateShell); - if (settings->RemoteApplicationMode) - FILE_POPULATE_STRING(file->ShellWorkingDirectory, settings->RemoteApplicationWorkingDir); - else - FILE_POPULATE_STRING(file->ShellWorkingDirectory, settings->ShellWorkingDirectory); - file->ConnectionType = settings->ConnectionType; - FILE_POPULATE_STRING(file->DrivesToRedirect, settings->DrivesToRedirect); - file->ScreenModeId = settings->Fullscreen ? 2 : 1; + size_t index; + UINT32 LoadBalanceInfoLength; + const char* GatewayHostname = NULL; - if (settings->LoadBalanceInfoLength) + if (!FILE_POPULATE_STRING(&file->Domain, settings, FreeRDP_Domain) || + !FILE_POPULATE_STRING(&file->Username, settings, FreeRDP_Username) || + !FILE_POPULATE_STRING(&file->Password, settings, FreeRDP_Password) || + !FILE_POPULATE_STRING(&file->FullAddress, settings, FreeRDP_ServerHostname) || + !FILE_POPULATE_STRING(&file->AlternateFullAddress, settings, FreeRDP_ServerHostname) || + !FILE_POPULATE_STRING(&file->AlternateShell, settings, FreeRDP_AlternateShell) || + !FILE_POPULATE_STRING(&file->DrivesToRedirect, settings, FreeRDP_DrivesToRedirect)) + + return FALSE; + file->ServerPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort); + + file->DesktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth); + file->DesktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight); + file->SessionBpp = freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth); + file->DesktopScaleFactor = freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor); + file->DynamicResolution = freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate); + file->VideoPlaybackMode = freerdp_settings_get_bool(settings, FreeRDP_SupportVideoOptimized); + + // TODO file->MaximizeToCurrentDisplays; + // TODO file->SingleMonInWindowedMode; + // TODO file->EncodeRedirectedVideoCapture; + // TODO file->RedirectedVideoCaptureEncodingQuality; + file->ConnectToConsole = freerdp_settings_get_bool(settings, FreeRDP_ConsoleSession); + file->NegotiateSecurityLayer = + freerdp_settings_get_bool(settings, FreeRDP_NegotiateSecurityLayer); + file->EnableCredSSPSupport = freerdp_settings_get_bool(settings, FreeRDP_NlaSecurity); + + if (freerdp_settings_get_bool(settings, FreeRDP_RemoteApplicationMode)) + index = FreeRDP_RemoteApplicationWorkingDir; + else + index = FreeRDP_ShellWorkingDirectory; + if (!FILE_POPULATE_STRING(&file->ShellWorkingDirectory, settings, index)) + return FALSE; + file->ConnectionType = freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType); + + file->ScreenModeId = freerdp_settings_get_bool(settings, FreeRDP_Fullscreen) ? 2 : 1; + + LoadBalanceInfoLength = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength); + if (LoadBalanceInfoLength > 0) { - file->LoadBalanceInfo = calloc(settings->LoadBalanceInfoLength + 1, 1); + const BYTE* LoadBalanceInfo = + freerdp_settings_get_pointer(settings, FreeRDP_LoadBalanceInfo); + file->LoadBalanceInfo = calloc(LoadBalanceInfoLength + 1, 1); if (!file->LoadBalanceInfo) return FALSE; - memcpy(file->LoadBalanceInfo, settings->LoadBalanceInfo, settings->LoadBalanceInfoLength); + memcpy(file->LoadBalanceInfo, LoadBalanceInfo, LoadBalanceInfoLength); } - if (settings->AudioPlayback) + if (freerdp_settings_get_bool(settings, FreeRDP_AudioPlayback)) file->AudioMode = AUDIO_MODE_REDIRECT; - else if (settings->RemoteConsoleAudio) + else if (freerdp_settings_get_bool(settings, FreeRDP_RemoteConsoleAudio)) file->AudioMode = AUDIO_MODE_PLAY_ON_SERVER; else file->AudioMode = AUDIO_MODE_NONE; /* The gateway hostname should also contain a port specifier unless it is the default port 443 */ - if (settings->GatewayHostname) + GatewayHostname = freerdp_settings_get_string(settings, FreeRDP_GatewayHostname); + if (GatewayHostname) { + const UINT32 GatewayPort = freerdp_settings_get_uint32(settings, FreeRDP_GatewayPort); freerdp_client_file_string_check_free(file->GatewayHostname); - if (settings->GatewayPort == 443) - file->GatewayHostname = _strdup(settings->GatewayHostname); + if (GatewayPort == 443) + file->GatewayHostname = _strdup(GatewayHostname); else { - int length = _scprintf("%s:%" PRIu32, settings->GatewayHostname, settings->GatewayPort); + int length = _scprintf("%s:%" PRIu32, GatewayHostname, GatewayPort); if (length < 0) return FALSE; @@ -905,49 +970,124 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett if (!file->GatewayHostname) return FALSE; - if (sprintf_s(file->GatewayHostname, (size_t)length + 1, "%s:%" PRIu32, - settings->GatewayHostname, settings->GatewayPort) < 0) + if (sprintf_s(file->GatewayHostname, (size_t)length + 1, "%s:%" PRIu32, GatewayHostname, + GatewayPort) < 0) return FALSE; } if (!file->GatewayHostname) return FALSE; } - file->AudioCaptureMode = settings->AudioCapture; - file->BitmapCachePersistEnable = settings->BitmapCachePersistEnabled; - file->Compression = settings->CompressionEnabled; - file->AuthenticationLevel = settings->AuthenticationLevel; - FILE_POPULATE_STRING(file->GatewayAccessToken, settings->GatewayAccessToken); - file->GatewayUsageMethod = settings->GatewayUsageMethod; - file->PromptCredentialOnce = settings->GatewayUseSameCredentials; - file->PromptForCredentials = settings->PromptForCredentials; - file->RemoteApplicationMode = settings->RemoteApplicationMode; - FILE_POPULATE_STRING(file->RemoteApplicationProgram, settings->RemoteApplicationProgram); - FILE_POPULATE_STRING(file->RemoteApplicationName, settings->RemoteApplicationName); - FILE_POPULATE_STRING(file->RemoteApplicationIcon, settings->RemoteApplicationIcon); - FILE_POPULATE_STRING(file->RemoteApplicationFile, settings->RemoteApplicationFile); - FILE_POPULATE_STRING(file->RemoteApplicationGuid, settings->RemoteApplicationGuid); - FILE_POPULATE_STRING(file->RemoteApplicationCmdLine, settings->RemoteApplicationCmdLine); - file->SpanMonitors = settings->SpanMonitors; - file->UseMultiMon = settings->UseMultimon; - file->AllowDesktopComposition = settings->AllowDesktopComposition; - file->AllowFontSmoothing = settings->AllowFontSmoothing; - file->DisableWallpaper = settings->DisableWallpaper; - file->DisableFullWindowDrag = settings->DisableFullWindowDrag; - file->DisableMenuAnims = settings->DisableMenuAnims; - file->DisableThemes = settings->DisableThemes; - file->BandwidthAutoDetect = (settings->ConnectionType >= 7) ? TRUE : FALSE; - file->NetworkAutoDetect = settings->NetworkAutoDetect ? 0 : 1; - file->AutoReconnectionEnabled = settings->AutoReconnectionEnabled; - file->RedirectSmartCards = settings->RedirectSmartCards; - file->RedirectCameras = freerdp_client_channel_args_to_string(settings, "rdpecam"); - file->RedirectClipboard = settings->RedirectClipboard; - file->RedirectPrinters = settings->RedirectPrinters; - file->RedirectDrives = settings->RedirectDrives; - file->RedirectComPorts = (settings->RedirectSerialPorts || settings->RedirectParallelPorts); - FILE_POPULATE_STRING(file->DrivesToRedirect, settings->DrivesToRedirect); - file->KeyboardHook = settings->KeyboardHook; - FILE_POPULATE_STRING(file->PreconnectionBlob, settings->PreconnectionBlob); + file->AudioCaptureMode = freerdp_settings_get_bool(settings, FreeRDP_AudioCapture); + file->BitmapCachePersistEnable = + freerdp_settings_get_bool(settings, FreeRDP_BitmapCachePersistEnabled); + file->Compression = freerdp_settings_get_bool(settings, FreeRDP_CompressionEnabled); + file->AuthenticationLevel = freerdp_settings_get_uint32(settings, FreeRDP_AuthenticationLevel); + file->GatewayUsageMethod = freerdp_settings_get_uint32(settings, FreeRDP_GatewayUsageMethod); + file->PromptCredentialOnce = + freerdp_settings_get_bool(settings, FreeRDP_GatewayUseSameCredentials); + file->PromptForCredentials = freerdp_settings_get_bool(settings, FreeRDP_PromptForCredentials); + file->RemoteApplicationMode = + freerdp_settings_get_bool(settings, FreeRDP_RemoteApplicationMode); + if (!FILE_POPULATE_STRING(&file->GatewayAccessToken, settings, FreeRDP_GatewayAccessToken) || + !FILE_POPULATE_STRING(&file->RemoteApplicationProgram, settings, + FreeRDP_RemoteApplicationProgram) || + !FILE_POPULATE_STRING(&file->RemoteApplicationName, settings, + FreeRDP_RemoteApplicationName) || + !FILE_POPULATE_STRING(&file->RemoteApplicationIcon, settings, + FreeRDP_RemoteApplicationIcon) || + !FILE_POPULATE_STRING(&file->RemoteApplicationFile, settings, + FreeRDP_RemoteApplicationFile) || + !FILE_POPULATE_STRING(&file->RemoteApplicationGuid, settings, + FreeRDP_RemoteApplicationGuid) || + !FILE_POPULATE_STRING(&file->RemoteApplicationCmdLine, settings, + FreeRDP_RemoteApplicationCmdLine)) + return FALSE; + file->SpanMonitors = freerdp_settings_get_bool(settings, FreeRDP_SpanMonitors); + file->UseMultiMon = freerdp_settings_get_bool(settings, FreeRDP_UseMultimon); + file->AllowDesktopComposition = + freerdp_settings_get_bool(settings, FreeRDP_AllowDesktopComposition); + file->AllowFontSmoothing = freerdp_settings_get_bool(settings, FreeRDP_AllowFontSmoothing); + file->DisableWallpaper = freerdp_settings_get_bool(settings, FreeRDP_DisableWallpaper); + file->DisableFullWindowDrag = + freerdp_settings_get_bool(settings, FreeRDP_DisableFullWindowDrag); + file->DisableMenuAnims = freerdp_settings_get_bool(settings, FreeRDP_DisableMenuAnims); + file->DisableThemes = freerdp_settings_get_bool(settings, FreeRDP_DisableThemes); + file->BandwidthAutoDetect = + (freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType) >= 7) ? TRUE : FALSE; + file->NetworkAutoDetect = + freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect) ? 0 : 1; + file->AutoReconnectionEnabled = + freerdp_settings_get_bool(settings, FreeRDP_AutoReconnectionEnabled); + file->RedirectSmartCards = freerdp_settings_get_bool(settings, FreeRDP_RedirectSmartCards); + file->RedirectCameras = freerdp_client_channel_args_to_string(settings, "rdpecam", "device:"); + { + char* str = freerdp_client_channel_args_to_string(settings, "rdpecam", "encode:"); + file->EncodeRedirectedVideoCapture = 0; + if (str) + { + unsigned long val; + errno = 0; + val = strtoul(str, NULL, 0); + if ((val < UINT32_MAX) && (errno == 0)) + file->EncodeRedirectedVideoCapture = val; + } + free(str); + } + { + char* str = freerdp_client_channel_args_to_string(settings, "rdpecam", "quality:"); + + file->RedirectedVideoCaptureEncodingQuality = 0; + if (str) + { + unsigned long val; + errno = 0; + val = strtoul(str, NULL, 0); + if ((val <= 2) && (errno == 0)) + { + file->RedirectedVideoCaptureEncodingQuality = val; + } + } + free(str); + } +#ifdef CHANNEL_URBDRC_CLIENT + file->UsbDevicesToRedirect = + freerdp_client_channel_args_to_string(settings, URBDRC_CHANNEL_NAME, "device:"); +#endif + file->RedirectClipboard = freerdp_settings_get_bool(settings, FreeRDP_RedirectClipboard); + file->RedirectPrinters = freerdp_settings_get_bool(settings, FreeRDP_RedirectPrinters); + file->RedirectDrives = freerdp_settings_get_bool(settings, FreeRDP_RedirectDrives); + file->RedirectComPorts = (freerdp_settings_get_bool(settings, FreeRDP_RedirectSerialPorts) || + freerdp_settings_get_bool(settings, FreeRDP_RedirectParallelPorts)); + if (!FILE_POPULATE_STRING(&file->DrivesToRedirect, settings, FreeRDP_DrivesToRedirect) || + !FILE_POPULATE_STRING(&file->PreconnectionBlob, settings, FreeRDP_PreconnectionBlob)) + return FALSE; + + { + size_t offset = 0; + UINT32 x, count = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds); + const UINT32* MonitorIds = freerdp_settings_get_pointer(settings, FreeRDP_MonitorIds); + /* String size: 10 char UINT32 max string length, 1 char separator, one element NULL */ + size_t size = count * (10 + 1) + 1; + + char* str = calloc(size, sizeof(char)); + for (x = 0; x < count; x++) + { + int rc = _snprintf(&str[offset], size - offset, "%" PRIu32 ",", MonitorIds[x]); + if (rc <= 0) + { + free(str); + return FALSE; + } + offset += (size_t)rc; + } + if (offset > 0) + str[offset - 1] = '\0'; + freerdp_client_file_string_check_free(file->SelectedMonitors); + file->SelectedMonitors = str; + } + + file->KeyboardHook = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardHook); return TRUE; } @@ -1092,21 +1232,29 @@ size_t freerdp_client_write_rdp_file_buffer(const rdpFile* file, char* buffer, s /* integer parameters */ WRITE_SETTING_INT("use multimon:i:%" PRIu32, file->UseMultiMon); + WRITE_SETTING_INT("maximizetocurrentdisplays:i:%" PRIu32, file->MaximizeToCurrentDisplays); + WRITE_SETTING_INT("singlemoninwindowedmode:i:%" PRIu32, file->SingleMonInWindowedMode); WRITE_SETTING_INT("screen mode id:i:%" PRIu32, file->ScreenModeId); WRITE_SETTING_INT("span monitors:i:%" PRIu32, file->SpanMonitors); WRITE_SETTING_INT("smart sizing:i:%" PRIu32, file->SmartSizing); + WRITE_SETTING_INT("dynamic resolution:i:%" PRIu32, file->DynamicResolution); WRITE_SETTING_INT("enablesuperpan:i:%" PRIu32, file->EnableSuperSpan); WRITE_SETTING_INT("superpanaccelerationfactor:i:%" PRIu32, file->SuperSpanAccelerationFactor); WRITE_SETTING_INT("desktopwidth:i:%" PRIu32, file->DesktopWidth); WRITE_SETTING_INT("desktopheight:i:%" PRIu32, file->DesktopHeight); WRITE_SETTING_INT("desktop size id:i:%" PRIu32, file->DesktopSizeId); WRITE_SETTING_INT("session bpp:i:%" PRIu32, file->SessionBpp); + WRITE_SETTING_INT("desktopscalefactor:i:%" PRIu32, file->DesktopScaleFactor); WRITE_SETTING_INT("compression:i:%" PRIu32, file->Compression); WRITE_SETTING_INT("keyboardhook:i:%" PRIu32, file->KeyboardHook); WRITE_SETTING_INT("disable ctrl+alt+del:i:%" PRIu32, file->DisableCtrlAltDel); WRITE_SETTING_INT("audiomode:i:%" PRIu32, file->AudioMode); WRITE_SETTING_INT("audioqualitymode:i:%" PRIu32, file->AudioQualityMode); WRITE_SETTING_INT("audiocapturemode:i:%" PRIu32, file->AudioCaptureMode); + WRITE_SETTING_INT("encode redirected video capture:i:%" PRIu32, + file->EncodeRedirectedVideoCapture); + WRITE_SETTING_INT("redirected video capture encoding quality:i:%" PRIu32, + file->RedirectedVideoCaptureEncodingQuality); WRITE_SETTING_INT("videoplaybackmode:i:%" PRIu32, file->VideoPlaybackMode); WRITE_SETTING_INT("connection type:i:%" PRIu32, file->ConnectionType); WRITE_SETTING_INT("networkautodetect:i:%" PRIu32, file->NetworkAutoDetect); @@ -1181,10 +1329,45 @@ size_t freerdp_client_write_rdp_file_buffer(const rdpFile* file, char* buffer, s WRITE_SETTING_STR("devicestoredirect:s:%s", file->DevicesToRedirect); WRITE_SETTING_STR("winposstr:s:%s", file->WinPosStr); WRITE_SETTING_STR("pcb:s:%s", file->PreconnectionBlob); + WRITE_SETTING_STR("selectedmonitors:s:%s", file->SelectedMonitors); return totalSize; } +static ADDIN_ARGV* rdp_file_to_args(const char* channel, const char* values) +{ + size_t count, x; + char** p = NULL; + ADDIN_ARGV* args = freerdp_addin_argv_new(0, NULL); + if (!args) + return NULL; + if (!freerdp_addin_argv_add_argument(args, channel)) + goto fail; + + p = CommandLineParseCommaSeparatedValues(values, &count); + for (x = 0; x < count; x++) + { + BOOL rc; + const char* val = p[x]; + const size_t len = strlen(val) + 8; + char* str = calloc(len, sizeof(char)); + if (!str) + goto fail; + + _snprintf(str, len, "device:%s", val); + rc = freerdp_addin_argv_add_argument(args, str); + free(str); + if (!rc) + goto fail; + } + free(p); + return args; + +fail: + free(p); + freerdp_addin_argv_free(args); + return NULL; +} BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings) { BOOL setDefaultConnectionType = TRUE; @@ -1408,12 +1591,10 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~((size_t)file->LoadBalanceInfo)) { - settings->LoadBalanceInfo = (BYTE*)_strdup(file->LoadBalanceInfo); - - if (!settings->LoadBalanceInfo) + const size_t len = strlen(file->LoadBalanceInfo); + if (!freerdp_settings_set_pointer_len(settings, FreeRDP_LoadBalanceInfo, + file->LoadBalanceInfo, len)) return FALSE; - - settings->LoadBalanceInfoLength = (UINT32)strlen((char*)settings->LoadBalanceInfo); } if (~file->AuthenticationLevel) @@ -1432,7 +1613,9 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* * connect). 2: If server authentication fails, show a warning and allow me to connect or * refuse the connection (Warn me). 3: No authentication requirement is specified. */ - settings->AuthenticationLevel = file->AuthenticationLevel; + if (!freerdp_settings_set_uint32(settings, FreeRDP_AuthenticationLevel, + file->AuthenticationLevel)) + return FALSE; } if (~file->ConnectionType) @@ -1797,20 +1980,120 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~((size_t)file->RedirectCameras)) { BOOL status; - char** p; - size_t count; - p = CommandLineParseCommaSeparatedValuesEx("rdpecam", file->RedirectCameras, &count); - status = freerdp_client_add_dynamic_channel(settings, count, p); - free(p); + ADDIN_ARGV* args = rdp_file_to_args("rdpecam", file->RedirectCameras); + if (!args) + return FALSE; + + if (~file->EncodeRedirectedVideoCapture) + { + char encode[64]; + _snprintf(encode, sizeof(encode), "encode:%" PRIu32, + file->EncodeRedirectedVideoCapture); + freerdp_addin_argv_add_argument(args, encode); + } + if (~file->RedirectedVideoCaptureEncodingQuality) + { + char quality[64]; + _snprintf(quality, sizeof(quality), "quality:%" PRIu32, + file->RedirectedVideoCaptureEncodingQuality); + freerdp_addin_argv_add_argument(args, quality); + } + + status = freerdp_client_add_dynamic_channel(settings, args->argc, args->argv); + freerdp_addin_argv_free(args); /* Ignore return */ WINPR_UNUSED(status); } +#ifdef CHANNEL_URBDRC_CLIENT + if (~((size_t)file->UsbDevicesToRedirect)) + { + BOOL status; + ADDIN_ARGV* args = rdp_file_to_args(URBDRC_CHANNEL_NAME, file->UsbDevicesToRedirect); + if (!args) + return FALSE; + status = freerdp_client_add_dynamic_channel(settings, args->argc, args->argv); + freerdp_addin_argv_free(args); + /* Ignore return */ WINPR_UNUSED(status); + } +#endif + if (~file->KeyboardHook) { if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardHook, file->KeyboardHook)) return FALSE; } + if (~(size_t)file->SelectedMonitors) + { + size_t count = 0, x; + char** args = CommandLineParseCommaSeparatedValues(file->SelectedMonitors, &count); + UINT32* list; + + if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, NULL, count)) + { + free(args); + return FALSE; + } + list = freerdp_settings_get_pointer(settings, FreeRDP_MonitorIds); + if (!list && (count > 0)) + { + free(args); + return FALSE; + } + for (x = 0; x < count; x++) + { + UINT32 val; + errno = 0; + val = strtoul(args[x], NULL, 0); + if ((val == ULONG_MAX) && (errno != 0)) + { + free(args); + free(list); + return FALSE; + } + list[x] = val; + } + free(args); + } + + if (~file->DynamicResolution) + { + const BOOL val = file->DynamicResolution != 0; + if (val) + { + if (!freerdp_settings_set_bool(settings, FreeRDP_SupportDisplayControl, TRUE)) + return FALSE; + } + if (!freerdp_settings_set_bool(settings, FreeRDP_DynamicResolutionUpdate, val)) + return FALSE; + } + + if (~file->DesktopScaleFactor) + { + if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopScaleFactor, + file->DesktopScaleFactor)) + return FALSE; + } + + if (~file->VideoPlaybackMode) + { + if (file->VideoPlaybackMode != 0) + { + if (!freerdp_settings_set_bool(settings, FreeRDP_SupportGeometryTracking, TRUE) || + !freerdp_settings_set_bool(settings, FreeRDP_SupportVideoOptimized, TRUE)) + return FALSE; + } + else + { + if (!freerdp_settings_set_bool(settings, FreeRDP_SupportVideoOptimized, FALSE)) + return FALSE; + } + } + // TODO file->MaximizeToCurrentDisplays; + // TODO file->SingleMonInWindowedMode; + // TODO file->EncodeRedirectedVideoCapture; + // TODO file->RedirectedVideoCaptureEncodingQuality; + if (~((size_t)file->PreconnectionBlob)) { if (!freerdp_settings_set_string(settings, FreeRDP_PreconnectionBlob, @@ -1821,14 +2104,15 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (file->args->argc > 1) { - char* ConnectionFile = settings->ConnectionFile; + const char* ConnectionFile = freerdp_settings_get_string(settings, FreeRDP_ConnectionFile); settings->ConnectionFile = NULL; - if (freerdp_client_settings_parse_command_line(settings, (int)file->args->argc, - file->args->argv, FALSE) < 0) + if (freerdp_client_settings_parse_command_line(settings, file->args->argc, file->args->argv, + FALSE) < 0) return FALSE; - settings->ConnectionFile = ConnectionFile; + if (!freerdp_settings_set_string(settings, FreeRDP_ConnectionFile, ConnectionFile)) + return FALSE; } if (setDefaultConnectionType) @@ -2068,6 +2352,7 @@ void freerdp_client_rdp_file_free(rdpFile* file) freerdp_client_file_string_check_free(file->AlternateFullAddress); freerdp_client_file_string_check_free(file->UsbDevicesToRedirect); freerdp_client_file_string_check_free(file->RedirectCameras); + freerdp_client_file_string_check_free(file->SelectedMonitors); freerdp_client_file_string_check_free(file->LoadBalanceInfo); freerdp_client_file_string_check_free(file->RemoteApplicationName); freerdp_client_file_string_check_free(file->RemoteApplicationIcon); diff --git a/client/common/test/TestClientRdpFile.c b/client/common/test/TestClientRdpFile.c index ca4a79499..f15c69a70 100644 --- a/client/common/test/TestClientRdpFile.c +++ b/client/common/test/TestClientRdpFile.c @@ -1,4 +1,6 @@ - +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include #include @@ -160,56 +162,76 @@ static const BYTE testRdpFileUTF16[] = { 0x65, 0x00, 0x0d, 0x00, 0x0a, 0x00 }; -static char testRdpFileUTF8[] = "screen mode id:i:2\n" - "use multimon:i:0\n" - "desktopwidth:i:1920\n" - "desktopheight:i:1080\n" - "session bpp:i:32\n" - "winposstr:s:0,1,553,211,1353,811\n" - "compression:i:1\n" - "keyboardhook:i:2\n" - "audiocapturemode:i:0\n" - "videoplaybackmode:i:1\n" - "connection type:i:7\n" - "networkautodetect:i:1\n" - "bandwidthautodetect:i:1\n" - "displayconnectionbar:i:1\n" - "enableworkspacereconnect:i:0\n" - "disable wallpaper:i:0\n" - "allow font smoothing:i:0\n" - "allow desktop composition:i:0\n" - "disable full window drag:i:1\n" - "disable menu anims:i:1\n" - "disable themes:i:0\n" - "disable cursor setting:i:0\n" - "bitmapcachepersistenable:i:1\n" - "full address:s:LAB1-W7-DM-01.lab1.awake.local\n" - "alternate full address:s:LAB1-W7-DM-01.lab1.awake.global\n" - "audiomode:i:0\n" - "redirectprinters:i:1\n" - "redirectcomports:i:0\n" - "redirectsmartcards:i:1\n" - "redirectclipboard:i:1\n" - "redirectposdevices:i:0\n" - "autoreconnection enabled:i:1\n" - "authentication level:i:2\n" - "prompt for credentials:i:0\n" - "negotiate security layer:i:1\n" - "remoteapplicationmode:i:0\n" - "alternate shell:s:\n" - "shell working directory:s:\n" - "gatewayhostname:s:LAB1-W2K8R2-GW.lab1.awake.local\n" - "gatewayusagemethod:i:1\n" - "gatewaycredentialssource:i:0\n" - "gatewayprofileusagemethod:i:1\n" - "promptcredentialonce:i:1\n" - "use redirection server name:i:0\n" - "rdgiskdcproxy:i:0\n" - "kdcproxyname:s:\n" - "drivestoredirect:s:*\n" - "username:s:LAB1\\JohnDoe\n" - "vendor integer:i:123\n" - "vendor string:s:microsoft\n"; +const static char* camera_args[] = { "rdpecam", + "device:*", + "device:\\?\\usb#vid_0bda&pid_58b0&mi", + "device:-\\?\\usb#vid_0bdc&pid_58b1&mi", + "encode:1", + "quality:2" }; + +#if defined(CHANNEL_URBDRC_CLIENT) +const static char* urbdrc_args[] = { "urbdrc", "device:*", "device:USBInstanceID:someid", + "device:{72631e54-78a4-11d0-bcf7-00aa00b7b32a}" }; +#endif + +static char testRdpFileUTF8[] = + "screen mode id:i:2\n" + "use multimon:i:0\n" + "desktopwidth:i:1920\n" + "desktopheight:i:1080\n" + "dynamic resolution:i:1080\n" + "desktopscalefactor:i:1080\n" + "redirected video capture encoding quality:i:2\n" + "encode redirected video capture:i:1\n" + "camerastoredirect:s:*,\\?\\usb#vid_0bda&pid_58b0&mi,-\\?\\usb#vid_0bdc&pid_58b1&mi\n" + "usbdevicestoredirect:s:*,USBInstanceID:someid,{72631e54-78a4-11d0-bcf7-00aa00b7b32a}\n" + "selectedmonitors:s:3,2,42,23" + "session bpp:i:32\n" + "winposstr:s:0,1,553,211,1353,811\n" + "compression:i:1\n" + "keyboardhook:i:2\n" + "audiocapturemode:i:0\n" + "videoplaybackmode:i:2\n" + "connection type:i:7\n" + "networkautodetect:i:1\n" + "bandwidthautodetect:i:1\n" + "displayconnectionbar:i:1\n" + "enableworkspacereconnect:i:0\n" + "disable wallpaper:i:0\n" + "allow font smoothing:i:0\n" + "allow desktop composition:i:0\n" + "disable full window drag:i:1\n" + "disable menu anims:i:1\n" + "disable themes:i:0\n" + "disable cursor setting:i:0\n" + "bitmapcachepersistenable:i:1\n" + "full address:s:LAB1-W7-DM-01.lab1.awake.local\n" + "alternate full address:s:LAB1-W7-DM-01.lab1.awake.global\n" + "audiomode:i:0\n" + "redirectprinters:i:1\n" + "redirectcomports:i:0\n" + "redirectsmartcards:i:1\n" + "redirectclipboard:i:1\n" + "redirectposdevices:i:0\n" + "autoreconnection enabled:i:1\n" + "authentication level:i:2\n" + "prompt for credentials:i:0\n" + "negotiate security layer:i:1\n" + "remoteapplicationmode:i:0\n" + "alternate shell:s:\n" + "shell working directory:s:\n" + "gatewayhostname:s:LAB1-W2K8R2-GW.lab1.awake.local\n" + "gatewayusagemethod:i:1\n" + "gatewaycredentialssource:i:0\n" + "gatewayprofileusagemethod:i:1\n" + "promptcredentialonce:i:1\n" + "use redirection server name:i:0\n" + "rdgiskdcproxy:i:0\n" + "kdcproxyname:s:\n" + "drivestoredirect:s:*\n" + "username:s:LAB1\\JohnDoe\n" + "vendor integer:i:123\n" + "vendor string:s:microsoft\n"; static char* append(const char* fmt, ...) { @@ -241,6 +263,8 @@ int TestClientRdpFile(int argc, char* argv[]) { int rc = -1; int iValue; + UINT32 uValue; + const UINT32* puValue; const char* sValue; char* utfname = NULL; char* uniname = NULL; @@ -360,6 +384,135 @@ int TestClientRdpFile(int argc, char* argv[]) goto fail; } + iValue = freerdp_client_rdp_file_get_integer_option(file, "dynamic resolution"); + if (iValue != 1080) + { + printf("dynamic resolution uses invalid default value %d", iValue); + goto fail; + } + if (!freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate)) + { + printf("FreeRDP_DynamicResolutionUpdate has invalid value"); + goto fail; + } + iValue = freerdp_client_rdp_file_get_integer_option(file, "desktopscalefactor"); + if (iValue != 1080) + { + printf("desktopscalefactor uses invalid default value %d", iValue); + goto fail; + } + if (freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor) != iValue) + { + printf("FreeRDP_DesktopScaleFactor has invalid value"); + goto fail; + } + + /* Check [MS-RDPECAM] related options */ + { + int x; + ADDIN_ARGV* args; + iValue = + freerdp_client_rdp_file_get_integer_option(file, "encode redirected video capture"); + if (iValue != 1) + { + printf("encode redirected video capture uses invalid default value %d", iValue); + goto fail; + } + iValue = freerdp_client_rdp_file_get_integer_option( + file, "redirected video capture encoding quality"); + if (iValue != 2) + { + printf("redirected video capture encoding quality uses invalid default value %d", + iValue); + goto fail; + } + args = freerdp_dynamic_channel_collection_find(settings, "rdpecam"); + if (!args) + { + printf("rdpecam channel was not loaded"); + goto fail; + } + if (args->argc != 6) + { + printf("rdpecam channel was not loaded"); + goto fail; + } + + for (x = 0; x < args->argc; x++) + { + if (strcmp(args->argv[x], camera_args[x]) != 0) + { + printf("rdpecam invalid argument argv[%d]: %s", x, args->argv[x]); + goto fail; + } + } + } + + /* Check [URBDRC] related options */ +#if defined(CHANNEL_URBDRC_CLIENT) + { + int x; + ADDIN_ARGV* args = freerdp_dynamic_channel_collection_find(settings, "urbdrc"); + if (!args) + { + printf("urbdrc channel was not loaded"); + goto fail; + } + if (args->argc != 4) + { + printf("urbdrc channel was not loaded"); + goto fail; + } + + for (x = 0; x < args->argc; x++) + { + if (strcmp(args->argv[x], urbdrc_args[x]) != 0) + { + printf("urbdrc invalid argument argv[%d]: %s", x, args->argv[x]); + goto fail; + } + } + } +#endif + + /* Validate selectedmonitors:s:3,2,42,23 */ + uValue = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds); + if (uValue != 4) + { + printf("FreeRDP_NumMonitorIds has invalid value %" PRIu32, uValue); + goto fail; + } + puValue = (const UINT32*)freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, 0); + if (!puValue) + { + printf("FreeRDP_MonitorIds has invalid value %p", puValue); + goto fail; + } + if ((puValue[0] != 3) || (puValue[1] != 2) || (puValue[2] != 42) || (puValue[3] != 23)) + { + printf("FreeRDP_MonitorIds has invalid values: [%" PRIu32 ",%" PRIu32 ",%" PRIu32 + ",%" PRIu32 "]", + puValue[0], puValue[1], puValue[2], puValue[3]); + goto fail; + } + + iValue = freerdp_client_rdp_file_get_integer_option(file, "videoplaybackmode"); + if (iValue != 2) + { + printf("videoplaybackmode uses invalid default value %d", iValue); + goto fail; + } + if (!freerdp_settings_get_bool(settings, FreeRDP_SupportVideoOptimized)) + { + printf("FreeRDP_SupportVideoOptimized has invalid value"); + goto fail; + } + if (!freerdp_settings_get_bool(settings, FreeRDP_SupportGeometryTracking)) + { + printf("FreeRDP_SupportGeometryTracking has invalid value"); + goto fail; + } + iValue = freerdp_client_rdp_file_get_integer_option(file, "vendor integer"); if (iValue != 123) goto fail; diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index 4d391ceea..a1c00e80b 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -1008,7 +1008,7 @@ BOOL freerdp_settings_set_value_for_name(rdpSettings* settings, const char* name } static BOOL freerdp_settings_set_pointer_len_(rdpSettings* settings, size_t id, SSIZE_T lenId, - const void* data, size_t len) + const void* data, size_t len, size_t size) { BOOL rc; void* copy; @@ -1024,11 +1024,11 @@ static BOOL freerdp_settings_set_pointer_len_(rdpSettings* settings, size_t id, if (len == 0) return TRUE; - copy = calloc(len, 1); + copy = calloc(len, size); if (!copy) return FALSE; if (data) - memcpy(copy, data, len); + memcpy(copy, data, len * size); rc = freerdp_settings_set_pointer(settings, id, copy); if (!rc) { @@ -1062,23 +1062,23 @@ BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, size_t id, const vo settings->RdpServerRsaKey = (rdpRsaKey*)data; return TRUE; case FreeRDP_RedirectionPassword: - return freerdp_settings_set_pointer_len_(settings, id, - FreeRDP_RedirectionPasswordLength, data, len); + return freerdp_settings_set_pointer_len_( + settings, id, FreeRDP_RedirectionPasswordLength, data, len, sizeof(char)); case FreeRDP_RedirectionTsvUrl: return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionTsvUrlLength, - data, len); + data, len, sizeof(char)); case FreeRDP_LoadBalanceInfo: return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_LoadBalanceInfoLength, - data, len); + data, len, sizeof(char)); case FreeRDP_ServerRandom: return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerRandomLength, data, - len); + len, sizeof(char)); case FreeRDP_ClientRandom: return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ClientRandomLength, data, - len); + len, sizeof(char)); case FreeRDP_ServerCertificate: return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerCertificateLength, - data, len); + data, len, sizeof(char)); case FreeRDP_TargetNetAddresses: if (data == NULL) { @@ -1087,7 +1087,8 @@ BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, size_t id, const vo return FALSE; } return freerdp_settings_set_pointer_len_(settings, FreeRDP_TargetNetAddresses, - FreeRDP_TargetNetAddressCount, data, len); + FreeRDP_TargetNetAddressCount, data, len, + sizeof(char)); case FreeRDP_TargetNetPorts: if (data == NULL) @@ -1097,19 +1098,24 @@ BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, size_t id, const vo return FALSE; } return freerdp_settings_set_pointer_len_(settings, FreeRDP_TargetNetPorts, - FreeRDP_TargetNetAddressCount, data, len); + FreeRDP_TargetNetAddressCount, data, len, + sizeof(char)); case FreeRDP_ClientAutoReconnectCookie: case FreeRDP_ServerAutoReconnectCookie: case FreeRDP_ChannelDefArray: case FreeRDP_MonitorDefArray: - case FreeRDP_MonitorIds: case FreeRDP_ReceivedCapabilities: case FreeRDP_OrderSupport: case FreeRDP_ClientTimeZone: case FreeRDP_BitmapCacheV2CellInfo: case FreeRDP_GlyphCache: case FreeRDP_FragCache: - return freerdp_settings_set_pointer_len_(settings, id, -1, data, len); + return freerdp_settings_set_pointer_len_(settings, id, -1, data, len, sizeof(char)); + + case FreeRDP_MonitorIds: + return freerdp_settings_set_pointer_len_( + settings, FreeRDP_MonitorIds, FreeRDP_NumMonitorIds, data, len, sizeof(UINT32)); + default: if ((data == NULL) && (len == 0)) { diff --git a/libfreerdp/primitives/test/measure.h b/libfreerdp/primitives/test/measure.h index a54003084..5af588932 100644 --- a/libfreerdp/primitives/test/measure.h +++ b/libfreerdp/primitives/test/measure.h @@ -30,6 +30,7 @@ #endif #include +#include #ifndef _WIN32 #include @@ -85,7 +86,7 @@ extern void _floatprint(float t, char* output); int _loop; \ float _delta; \ char _str1[32], _str2[32]; \ - _prefix = strdup(_prefix_); \ + _prefix = _strdup(_prefix_); \ _str1[0] = '\0'; \ _str2[0] = '\0'; \ clock_gettime(CLOCK_MONOTONIC_RAW, &_start); \ diff --git a/winpr/include/winpr/cmdline.h b/winpr/include/winpr/cmdline.h index 332fe94c3..f1e30d08b 100644 --- a/winpr/include/winpr/cmdline.h +++ b/winpr/include/winpr/cmdline.h @@ -166,6 +166,8 @@ extern "C" size_t* count); WINPR_API char* CommandLineToCommaSeparatedValues(int argc, char* argv[]); + WINPR_API char* CommandLineToCommaSeparatedValuesEx(int argc, char* argv[], + const char* filters[], size_t number); #ifdef __cplusplus } diff --git a/winpr/libwinpr/utils/cmdline.c b/winpr/libwinpr/utils/cmdline.c index 7153b0dfd..3b1d6dfb9 100644 --- a/winpr/libwinpr/utils/cmdline.c +++ b/winpr/libwinpr/utils/cmdline.c @@ -560,6 +560,27 @@ char** CommandLineParseCommaSeparatedValues(const char* list, size_t* count) } char* CommandLineToCommaSeparatedValues(int argc, char* argv[]) +{ + return CommandLineToCommaSeparatedValuesEx(argc, argv, NULL, 0); +} + +static const char* filtered(const char* arg, const char* filters[], size_t number) +{ + size_t x; + if (number == 0) + return arg; + for (x = 0; x < number; x++) + { + const char* filter = filters[x]; + size_t len = strlen(filter); + if (_strnicmp(arg, filter, len) == 0) + return &arg[len]; + } + return NULL; +} + +char* CommandLineToCommaSeparatedValuesEx(int argc, char* argv[], const char* filters[], + size_t number) { int x; char* str = NULL; @@ -576,7 +597,11 @@ char* CommandLineToCommaSeparatedValues(int argc, char* argv[]) return NULL; for (x = 0; x < argc; x++) { - int rc = _snprintf(&str[offset], size - offset, "%s,", argv[x]); + int rc; + const char* arg = filtered(argv[x], filters, number); + if (!arg) + continue; + rc = _snprintf(&str[offset], size - offset, "%s,", arg); if (rc <= 0) { free(str);