FreeRDP
Loading...
Searching...
No Matches
client/common/file.c
1
20#include <freerdp/config.h>
21
22#include <errno.h>
23#include <ctype.h>
24#include <stdlib.h>
25
26#include <winpr/string.h>
27#include <winpr/file.h>
28#include <winpr/cast.h>
29
30#include <freerdp/utils/warnings.h>
31
32#include <freerdp/client.h>
33#include <freerdp/client/file.h>
34#include <freerdp/client/cmdline.h>
35
36#include <freerdp/channels/urbdrc.h>
37#include <freerdp/channels/rdpecam.h>
38#include <freerdp/channels/location.h>
39
50#include <stdio.h>
51#include <string.h>
52
53#include <winpr/wtypes.h>
54#include <winpr/crt.h>
55#include <winpr/path.h>
56#include <freerdp/log.h>
57#define TAG CLIENT_TAG("common")
58
59/*#define DEBUG_CLIENT_FILE 1*/
60
61static const BYTE BOM_UTF16_LE[2] = { 0xFF, 0xFE };
62
63// #define INVALID_INTEGER_VALUE 0xFFFFFFFF
64
65#define RDP_FILE_LINE_FLAG_FORMATTED 0x00000001
66// #define RDP_FILE_LINE_FLAG_STANDARD 0x00000002
67#define RDP_FILE_LINE_FLAG_TYPE_STRING 0x00000010
68#define RDP_FILE_LINE_FLAG_TYPE_INTEGER 0x00000020
69// #define RDP_FILE_LINE_FLAG_TYPE_BINARY 0x00000040
70
71struct rdp_file_line
72{
73 char* name;
74 LPSTR sValue;
75 PBYTE bValue;
76
77 size_t index;
78
79 long iValue;
80 DWORD flags;
81 int valueLength;
82};
83typedef struct rdp_file_line rdpFileLine;
84
85struct rdp_file
86{
87 DWORD UseMultiMon; /* use multimon */
88 LPSTR SelectedMonitors; /* selectedmonitors */
89 DWORD MaximizeToCurrentDisplays; /* maximizetocurrentdisplays */
90 DWORD SingleMonInWindowedMode; /* singlemoninwindowedmode */
91 DWORD ScreenModeId; /* screen mode id */
92 DWORD SpanMonitors; /* span monitors */
93 DWORD SmartSizing; /* smartsizing */
94 DWORD DynamicResolution; /* dynamic resolution */
95 DWORD EnableSuperSpan; /* enablesuperpan */
96 DWORD SuperSpanAccelerationFactor; /* superpanaccelerationfactor */
97
98 DWORD DesktopWidth; /* desktopwidth */
99 DWORD DesktopHeight; /* desktopheight */
100 DWORD DesktopSizeId; /* desktop size id */
101 DWORD SessionBpp; /* session bpp */
102 DWORD DesktopScaleFactor; /* desktopscalefactor */
103
104 DWORD Compression; /* compression */
105 DWORD KeyboardHook; /* keyboardhook */
106 DWORD DisableCtrlAltDel; /* disable ctrl+alt+del */
107
108 DWORD AudioMode; /* audiomode */
109 DWORD AudioQualityMode; /* audioqualitymode */
110 DWORD AudioCaptureMode; /* audiocapturemode */
111 DWORD EncodeRedirectedVideoCapture; /* encode redirected video capture */
112 DWORD RedirectedVideoCaptureEncodingQuality; /* redirected video capture encoding quality */
113 DWORD VideoPlaybackMode; /* videoplaybackmode */
114
115 DWORD ConnectionType; /* connection type */
116
117 DWORD NetworkAutoDetect; /* networkautodetect */
118 DWORD BandwidthAutoDetect; /* bandwidthautodetect */
119
120 DWORD PinConnectionBar; /* pinconnectionbar */
121 DWORD DisplayConnectionBar; /* displayconnectionbar */
122
123 DWORD WorkspaceId; /* workspaceid */
124 DWORD EnableWorkspaceReconnect; /* enableworkspacereconnect */
125
126 DWORD DisableWallpaper; /* disable wallpaper */
127 DWORD AllowFontSmoothing; /* allow font smoothing */
128 DWORD AllowDesktopComposition; /* allow desktop composition */
129 DWORD DisableFullWindowDrag; /* disable full window drag */
130 DWORD DisableMenuAnims; /* disable menu anims */
131 DWORD DisableThemes; /* disable themes */
132 DWORD DisableCursorSetting; /* disable cursor setting */
133
134 DWORD BitmapCacheSize; /* bitmapcachesize */
135 DWORD BitmapCachePersistEnable; /* bitmapcachepersistenable */
136
137 DWORD ServerPort; /* server port */
138
139 LPSTR Username; /* username */
140 LPSTR Domain; /* domain */
141 LPSTR Password; /*password*/
142 PBYTE Password51; /* password 51 */
143
144 LPSTR FullAddress; /* full address */
145 LPSTR AlternateFullAddress; /* alternate full address */
146
147 LPSTR UsbDevicesToRedirect; /* usbdevicestoredirect */
148 DWORD RedirectDrives; /* redirectdrives */
149 DWORD RedirectPrinters; /* redirectprinters */
150 DWORD RedirectComPorts; /* redirectcomports */
151 DWORD RedirectLocation; /* redirectlocation */
152 DWORD RedirectSmartCards; /* redirectsmartcards */
153 DWORD RedirectWebauthN; /* redirectwebauthn */
154 LPSTR RedirectCameras; /* camerastoredirect */
155 DWORD RedirectClipboard; /* redirectclipboard */
156 DWORD RedirectPosDevices; /* redirectposdevices */
157 DWORD RedirectDirectX; /* redirectdirectx */
158 DWORD DisablePrinterRedirection; /* disableprinterredirection */
159 DWORD DisableClipboardRedirection; /* disableclipboardredirection */
160
161 DWORD ConnectToConsole; /* connect to console */
162 DWORD AdministrativeSession; /* administrative session */
163 DWORD AutoReconnectionEnabled; /* autoreconnection enabled */
164 DWORD AutoReconnectMaxRetries; /* autoreconnect max retries */
165
166 DWORD PublicMode; /* public mode */
167 DWORD AuthenticationLevel; /* authentication level */
168 DWORD PromptCredentialOnce; /* promptcredentialonce */
169 DWORD PromptForCredentials; /* prompt for credentials */
170 DWORD NegotiateSecurityLayer; /* negotiate security layer */
171 DWORD EnableCredSSPSupport; /* enablecredsspsupport */
172 DWORD EnableRdsAadAuth; /* enablerdsaadauth */
173
174 DWORD RemoteApplicationMode; /* remoteapplicationmode */
175 LPSTR LoadBalanceInfo; /* loadbalanceinfo */
176
177 LPSTR RemoteApplicationName; /* remoteapplicationname */
178 LPSTR RemoteApplicationIcon; /* remoteapplicationicon */
179 LPSTR RemoteApplicationProgram; /* remoteapplicationprogram */
180 LPSTR RemoteApplicationFile; /* remoteapplicationfile */
181 LPSTR RemoteApplicationGuid; /* remoteapplicationguid */
182 LPSTR RemoteApplicationCmdLine; /* remoteapplicationcmdline */
183 DWORD RemoteApplicationExpandCmdLine; /* remoteapplicationexpandcmdline */
184 DWORD RemoteApplicationExpandWorkingDir; /* remoteapplicationexpandworkingdir */
185 DWORD DisableConnectionSharing; /* disableconnectionsharing */
186 DWORD DisableRemoteAppCapsCheck; /* disableremoteappcapscheck */
187
188 LPSTR AlternateShell; /* alternate shell */
189 LPSTR ShellWorkingDirectory; /* shell working directory */
190
191 LPSTR GatewayHostname; /* gatewayhostname */
192 DWORD GatewayUsageMethod; /* gatewayusagemethod */
193 DWORD GatewayProfileUsageMethod; /* gatewayprofileusagemethod */
194 DWORD GatewayCredentialsSource; /* gatewaycredentialssource */
195
196 LPSTR ResourceProvider; /* resourceprovider */
197
198 LPSTR WvdEndpointPool; /* wvd endpoint pool */
199 LPSTR geo; /* geo */
200 LPSTR armpath; /* armpath */
201 LPSTR aadtenantid; /* aadtenantid" */
202 LPSTR diagnosticserviceurl; /* diagnosticserviceurl */
203 LPSTR hubdiscoverygeourl; /* hubdiscoverygeourl" */
204 LPSTR activityhint; /* activityhint */
205
206 DWORD UseRedirectionServerName; /* use redirection server name */
207
208 LPSTR GatewayAccessToken; /* gatewayaccesstoken */
209
210 LPSTR EndpointFedAuthToken; /* endpointfedauth */
211
212 LPSTR DrivesToRedirect; /* drivestoredirect */
213 LPSTR DevicesToRedirect; /* devicestoredirect */
214 LPSTR WinPosStr; /* winposstr */
215
216 LPSTR PreconnectionBlob; /* pcb */
217
218 LPSTR KdcProxyName; /* kdcproxyname */
219 DWORD RdgIsKdcProxy; /* rdgiskdcproxy */
220
221 DWORD align1;
222
223 size_t lineCount;
224 size_t lineSize;
225 rdpFileLine* lines;
226
227 ADDIN_ARGV* args;
228 void* context;
229
230 DWORD flags;
231};
232
233static const char key_str_username[] = "username";
234static const char key_str_domain[] = "domain";
235static const char key_str_password[] = "password";
236static const char key_str_full_address[] = "full address";
237static const char key_str_alternate_full_address[] = "alternate full address";
238static const char key_str_usbdevicestoredirect[] = "usbdevicestoredirect";
239static const char key_str_camerastoredirect[] = "camerastoredirect";
240static const char key_str_loadbalanceinfo[] = "loadbalanceinfo";
241static const char key_str_remoteapplicationname[] = "remoteapplicationname";
242static const char key_str_remoteapplicationicon[] = "remoteapplicationicon";
243static const char key_str_remoteapplicationprogram[] = "remoteapplicationprogram";
244static const char key_str_remoteapplicationfile[] = "remoteapplicationfile";
245static const char key_str_remoteapplicationguid[] = "remoteapplicationguid";
246static const char key_str_remoteapplicationcmdline[] = "remoteapplicationcmdline";
247static const char key_str_alternate_shell[] = "alternate shell";
248static const char key_str_shell_working_directory[] = "shell working directory";
249static const char key_str_gatewayhostname[] = "gatewayhostname";
250static const char key_str_gatewayaccesstoken[] = "gatewayaccesstoken";
251static const char key_str_endpointfedauth[] = "endpointfedauth";
252static const char key_str_resourceprovider[] = "resourceprovider";
253static const char str_resourceprovider_arm[] = "arm";
254static const char key_str_kdcproxyname[] = "kdcproxyname";
255static const char key_str_drivestoredirect[] = "drivestoredirect";
256static const char key_str_devicestoredirect[] = "devicestoredirect";
257static const char key_str_winposstr[] = "winposstr";
258static const char key_str_pcb[] = "pcb";
259static const char key_str_selectedmonitors[] = "selectedmonitors";
260
261static const char key_str_wvd[] = "wvd endpoint pool";
262static const char key_str_geo[] = "geo";
263static const char key_str_armpath[] = "armpath";
264static const char key_str_aadtenantid[] = "aadtenantid";
265
266static const char key_str_diagnosticserviceurl[] = "diagnosticserviceurl";
267static const char key_str_hubdiscoverygeourl[] = "hubdiscoverygeourl";
268
269static const char key_str_activityhint[] = "activityhint";
270
271static const char key_int_rdgiskdcproxy[] = "rdgiskdcproxy";
272static const char key_int_use_redirection_server_name[] = "use redirection server name";
273static const char key_int_gatewaycredentialssource[] = "gatewaycredentialssource";
274static const char key_int_gatewayprofileusagemethod[] = "gatewayprofileusagemethod";
275static const char key_int_gatewayusagemethod[] = "gatewayusagemethod";
276static const char key_int_disableremoteappcapscheck[] = "disableremoteappcapscheck";
277static const char key_int_disableconnectionsharing[] = "disableconnectionsharing";
278static const char key_int_remoteapplicationexpandworkingdir[] = "remoteapplicationexpandworkingdir";
279static const char key_int_remoteapplicationexpandcmdline[] = "remoteapplicationexpandcmdline";
280static const char key_int_remoteapplicationmode[] = "remoteapplicationmode";
281static const char key_int_enablecredsspsupport[] = "enablecredsspsupport";
282static const char key_int_enablerdsaadauth[] = "enablerdsaadauth";
283static const char key_int_negotiate_security_layer[] = "negotiate security layer";
284static const char key_int_prompt_for_credentials[] = "prompt for credentials";
285static const char key_int_promptcredentialonce[] = "promptcredentialonce";
286static const char key_int_authentication_level[] = "authentication level";
287static const char key_int_public_mode[] = "public mode";
288static const char key_int_autoreconnect_max_retries[] = "autoreconnect max retries";
289static const char key_int_autoreconnection_enabled[] = "autoreconnection enabled";
290static const char key_int_administrative_session[] = "administrative session";
291static const char key_int_connect_to_console[] = "connect to console";
292static const char key_int_disableclipboardredirection[] = "disableclipboardredirection";
293static const char key_int_disableprinterredirection[] = "disableprinterredirection";
294static const char key_int_redirectdirectx[] = "redirectdirectx";
295static const char key_int_redirectposdevices[] = "redirectposdevices";
296static const char key_int_redirectclipboard[] = "redirectclipboard";
297static const char key_int_redirectsmartcards[] = "redirectsmartcards";
298static const char key_int_redirectcomports[] = "redirectcomports";
299static const char key_int_redirectlocation[] = "redirectlocation";
300static const char key_int_redirectprinters[] = "redirectprinters";
301static const char key_int_redirectdrives[] = "redirectdrives";
302static const char key_int_server_port[] = "server port";
303static const char key_int_bitmapcachepersistenable[] = "bitmapcachepersistenable";
304static const char key_int_bitmapcachesize[] = "bitmapcachesize";
305static const char key_int_disable_cursor_setting[] = "disable cursor setting";
306static const char key_int_disable_themes[] = "disable themes";
307static const char key_int_disable_menu_anims[] = "disable menu anims";
308static const char key_int_disable_full_window_drag[] = "disable full window drag";
309static const char key_int_allow_desktop_composition[] = "allow desktop composition";
310static const char key_int_allow_font_smoothing[] = "allow font smoothing";
311static const char key_int_disable_wallpaper[] = "disable wallpaper";
312static const char key_int_enableworkspacereconnect[] = "enableworkspacereconnect";
313static const char key_int_workspaceid[] = "workspaceid";
314static const char key_int_displayconnectionbar[] = "displayconnectionbar";
315static const char key_int_pinconnectionbar[] = "pinconnectionbar";
316static const char key_int_bandwidthautodetect[] = "bandwidthautodetect";
317static const char key_int_networkautodetect[] = "networkautodetect";
318static const char key_int_connection_type[] = "connection type";
319static const char key_int_videoplaybackmode[] = "videoplaybackmode";
320static const char key_int_redirected_video_capture_encoding_quality[] =
321 "redirected video capture encoding quality";
322static const char key_int_encode_redirected_video_capture[] = "encode redirected video capture";
323static const char key_int_audiocapturemode[] = "audiocapturemode";
324static const char key_int_audioqualitymode[] = "audioqualitymode";
325static const char key_int_audiomode[] = "audiomode";
326static const char key_int_disable_ctrl_alt_del[] = "disable ctrl+alt+del";
327static const char key_int_keyboardhook[] = "keyboardhook";
328static const char key_int_compression[] = "compression";
329static const char key_int_desktopscalefactor[] = "desktopscalefactor";
330static const char key_int_session_bpp[] = "session bpp";
331static const char key_int_desktop_size_id[] = "desktop size id";
332static const char key_int_desktopheight[] = "desktopheight";
333static const char key_int_desktopwidth[] = "desktopwidth";
334static const char key_int_superpanaccelerationfactor[] = "superpanaccelerationfactor";
335static const char key_int_enablesuperpan[] = "enablesuperpan";
336static const char key_int_dynamic_resolution[] = "dynamic resolution";
337static const char key_int_smart_sizing[] = "smart sizing";
338static const char key_int_span_monitors[] = "span monitors";
339static const char key_int_screen_mode_id[] = "screen mode id";
340static const char key_int_singlemoninwindowedmode[] = "singlemoninwindowedmode";
341static const char key_int_maximizetocurrentdisplays[] = "maximizetocurrentdisplays";
342static const char key_int_use_multimon[] = "use multimon";
343static const char key_int_redirectwebauthn[] = "redirectwebauthn";
344
345static BOOL utils_str_is_empty(const char* str)
346{
347 if (!str)
348 return TRUE;
349 if (strlen(str) == 0)
350 return TRUE;
351 return FALSE;
352}
353
354static SSIZE_T freerdp_client_rdp_file_add_line(rdpFile* file);
355static rdpFileLine* freerdp_client_rdp_file_find_line_by_name(const rdpFile* file,
356 const char* name);
357static void freerdp_client_file_string_check_free(LPSTR str);
358
359static BOOL freerdp_client_rdp_file_find_integer_entry(rdpFile* file, const char* name,
360 DWORD** outValue, rdpFileLine** outLine)
361{
362 WINPR_ASSERT(file);
363 WINPR_ASSERT(name);
364 WINPR_ASSERT(outValue);
365 WINPR_ASSERT(outLine);
366
367 *outValue = nullptr;
368 *outLine = nullptr;
369
370 if (_stricmp(name, key_int_use_multimon) == 0)
371 *outValue = &file->UseMultiMon;
372 else if (_stricmp(name, key_int_maximizetocurrentdisplays) == 0)
373 *outValue = &file->MaximizeToCurrentDisplays;
374 else if (_stricmp(name, key_int_singlemoninwindowedmode) == 0)
375 *outValue = &file->SingleMonInWindowedMode;
376 else if (_stricmp(name, key_int_screen_mode_id) == 0)
377 *outValue = &file->ScreenModeId;
378 else if (_stricmp(name, key_int_span_monitors) == 0)
379 *outValue = &file->SpanMonitors;
380 else if (_stricmp(name, key_int_smart_sizing) == 0)
381 *outValue = &file->SmartSizing;
382 else if (_stricmp(name, key_int_dynamic_resolution) == 0)
383 *outValue = &file->DynamicResolution;
384 else if (_stricmp(name, key_int_enablesuperpan) == 0)
385 *outValue = &file->EnableSuperSpan;
386 else if (_stricmp(name, key_int_superpanaccelerationfactor) == 0)
387 *outValue = &file->SuperSpanAccelerationFactor;
388 else if (_stricmp(name, key_int_desktopwidth) == 0)
389 *outValue = &file->DesktopWidth;
390 else if (_stricmp(name, key_int_desktopheight) == 0)
391 *outValue = &file->DesktopHeight;
392 else if (_stricmp(name, key_int_desktop_size_id) == 0)
393 *outValue = &file->DesktopSizeId;
394 else if (_stricmp(name, key_int_session_bpp) == 0)
395 *outValue = &file->SessionBpp;
396 else if (_stricmp(name, key_int_desktopscalefactor) == 0)
397 *outValue = &file->DesktopScaleFactor;
398 else if (_stricmp(name, key_int_compression) == 0)
399 *outValue = &file->Compression;
400 else if (_stricmp(name, key_int_keyboardhook) == 0)
401 *outValue = &file->KeyboardHook;
402 else if (_stricmp(name, key_int_disable_ctrl_alt_del) == 0)
403 *outValue = &file->DisableCtrlAltDel;
404 else if (_stricmp(name, key_int_audiomode) == 0)
405 *outValue = &file->AudioMode;
406 else if (_stricmp(name, key_int_audioqualitymode) == 0)
407 *outValue = &file->AudioQualityMode;
408 else if (_stricmp(name, key_int_audiocapturemode) == 0)
409 *outValue = &file->AudioCaptureMode;
410 else if (_stricmp(name, key_int_encode_redirected_video_capture) == 0)
411 *outValue = &file->EncodeRedirectedVideoCapture;
412 else if (_stricmp(name, key_int_redirected_video_capture_encoding_quality) == 0)
413 *outValue = &file->RedirectedVideoCaptureEncodingQuality;
414 else if (_stricmp(name, key_int_videoplaybackmode) == 0)
415 *outValue = &file->VideoPlaybackMode;
416 else if (_stricmp(name, key_int_connection_type) == 0)
417 *outValue = &file->ConnectionType;
418 else if (_stricmp(name, key_int_networkautodetect) == 0)
419 *outValue = &file->NetworkAutoDetect;
420 else if (_stricmp(name, key_int_bandwidthautodetect) == 0)
421 *outValue = &file->BandwidthAutoDetect;
422 else if (_stricmp(name, key_int_pinconnectionbar) == 0)
423 *outValue = &file->PinConnectionBar;
424 else if (_stricmp(name, key_int_displayconnectionbar) == 0)
425 *outValue = &file->DisplayConnectionBar;
426 else if (_stricmp(name, key_int_workspaceid) == 0)
427 *outValue = &file->WorkspaceId;
428 else if (_stricmp(name, key_int_enableworkspacereconnect) == 0)
429 *outValue = &file->EnableWorkspaceReconnect;
430 else if (_stricmp(name, key_int_disable_wallpaper) == 0)
431 *outValue = &file->DisableWallpaper;
432 else if (_stricmp(name, key_int_allow_font_smoothing) == 0)
433 *outValue = &file->AllowFontSmoothing;
434 else if (_stricmp(name, key_int_allow_desktop_composition) == 0)
435 *outValue = &file->AllowDesktopComposition;
436 else if (_stricmp(name, key_int_disable_full_window_drag) == 0)
437 *outValue = &file->DisableFullWindowDrag;
438 else if (_stricmp(name, key_int_disable_menu_anims) == 0)
439 *outValue = &file->DisableMenuAnims;
440 else if (_stricmp(name, key_int_disable_themes) == 0)
441 *outValue = &file->DisableThemes;
442 else if (_stricmp(name, key_int_disable_cursor_setting) == 0)
443 *outValue = &file->DisableCursorSetting;
444 else if (_stricmp(name, key_int_bitmapcachesize) == 0)
445 *outValue = &file->BitmapCacheSize;
446 else if (_stricmp(name, key_int_bitmapcachepersistenable) == 0)
447 *outValue = &file->BitmapCachePersistEnable;
448 else if (_stricmp(name, key_int_server_port) == 0)
449 *outValue = &file->ServerPort;
450 else if (_stricmp(name, key_int_redirectdrives) == 0)
451 *outValue = &file->RedirectDrives;
452 else if (_stricmp(name, key_int_redirectprinters) == 0)
453 *outValue = &file->RedirectPrinters;
454 else if (_stricmp(name, key_int_redirectcomports) == 0)
455 *outValue = &file->RedirectComPorts;
456 else if (_stricmp(name, key_int_redirectlocation) == 0)
457 *outValue = &file->RedirectLocation;
458 else if (_stricmp(name, key_int_redirectsmartcards) == 0)
459 *outValue = &file->RedirectSmartCards;
460 else if (_stricmp(name, key_int_redirectclipboard) == 0)
461 *outValue = &file->RedirectClipboard;
462 else if (_stricmp(name, key_int_redirectposdevices) == 0)
463 *outValue = &file->RedirectPosDevices;
464 else if (_stricmp(name, key_int_redirectdirectx) == 0)
465 *outValue = &file->RedirectDirectX;
466 else if (_stricmp(name, key_int_disableprinterredirection) == 0)
467 *outValue = &file->DisablePrinterRedirection;
468 else if (_stricmp(name, key_int_disableclipboardredirection) == 0)
469 *outValue = &file->DisableClipboardRedirection;
470 else if (_stricmp(name, key_int_connect_to_console) == 0)
471 *outValue = &file->ConnectToConsole;
472 else if (_stricmp(name, key_int_administrative_session) == 0)
473 *outValue = &file->AdministrativeSession;
474 else if (_stricmp(name, key_int_autoreconnection_enabled) == 0)
475 *outValue = &file->AutoReconnectionEnabled;
476 else if (_stricmp(name, key_int_autoreconnect_max_retries) == 0)
477 *outValue = &file->AutoReconnectMaxRetries;
478 else if (_stricmp(name, key_int_public_mode) == 0)
479 *outValue = &file->PublicMode;
480 else if (_stricmp(name, key_int_authentication_level) == 0)
481 *outValue = &file->AuthenticationLevel;
482 else if (_stricmp(name, key_int_promptcredentialonce) == 0)
483 *outValue = &file->PromptCredentialOnce;
484 else if ((_stricmp(name, key_int_prompt_for_credentials) == 0))
485 *outValue = &file->PromptForCredentials;
486 else if (_stricmp(name, key_int_negotiate_security_layer) == 0)
487 *outValue = &file->NegotiateSecurityLayer;
488 else if (_stricmp(name, key_int_enablecredsspsupport) == 0)
489 *outValue = &file->EnableCredSSPSupport;
490 else if (_stricmp(name, key_int_enablerdsaadauth) == 0)
491 *outValue = &file->EnableRdsAadAuth;
492 else if (_stricmp(name, key_int_remoteapplicationmode) == 0)
493 *outValue = &file->RemoteApplicationMode;
494 else if (_stricmp(name, key_int_remoteapplicationexpandcmdline) == 0)
495 *outValue = &file->RemoteApplicationExpandCmdLine;
496 else if (_stricmp(name, key_int_remoteapplicationexpandworkingdir) == 0)
497 *outValue = &file->RemoteApplicationExpandWorkingDir;
498 else if (_stricmp(name, key_int_disableconnectionsharing) == 0)
499 *outValue = &file->DisableConnectionSharing;
500 else if (_stricmp(name, key_int_disableremoteappcapscheck) == 0)
501 *outValue = &file->DisableRemoteAppCapsCheck;
502 else if (_stricmp(name, key_int_gatewayusagemethod) == 0)
503 *outValue = &file->GatewayUsageMethod;
504 else if (_stricmp(name, key_int_gatewayprofileusagemethod) == 0)
505 *outValue = &file->GatewayProfileUsageMethod;
506 else if (_stricmp(name, key_int_gatewaycredentialssource) == 0)
507 *outValue = &file->GatewayCredentialsSource;
508 else if (_stricmp(name, key_int_use_redirection_server_name) == 0)
509 *outValue = &file->UseRedirectionServerName;
510 else if (_stricmp(name, key_int_rdgiskdcproxy) == 0)
511 *outValue = &file->RdgIsKdcProxy;
512 else if (_stricmp(name, key_int_redirectwebauthn) == 0)
513 *outValue = &file->RedirectWebauthN;
514 else
515 {
516 rdpFileLine* line = freerdp_client_rdp_file_find_line_by_name(file, name);
517 if (!line)
518 return FALSE;
519 if (!(line->flags & RDP_FILE_LINE_FLAG_TYPE_INTEGER))
520 return FALSE;
521
522 *outLine = line;
523 }
524
525 return TRUE;
526}
527
528static BOOL freerdp_client_rdp_file_find_string_entry(rdpFile* file, const char* name,
529 LPSTR** outValue, rdpFileLine** outLine)
530{
531 WINPR_ASSERT(file);
532 WINPR_ASSERT(name);
533 WINPR_ASSERT(outValue);
534 WINPR_ASSERT(outLine);
535
536 *outValue = nullptr;
537 *outLine = nullptr;
538
539 if (_stricmp(name, key_str_username) == 0)
540 *outValue = &file->Username;
541 else if (_stricmp(name, key_str_domain) == 0)
542 *outValue = &file->Domain;
543 else if (_stricmp(name, key_str_password) == 0)
544 *outValue = &file->Password;
545 else if (_stricmp(name, key_str_full_address) == 0)
546 *outValue = &file->FullAddress;
547 else if (_stricmp(name, key_str_alternate_full_address) == 0)
548 *outValue = &file->AlternateFullAddress;
549 else if (_stricmp(name, key_str_usbdevicestoredirect) == 0)
550 *outValue = &file->UsbDevicesToRedirect;
551 else if (_stricmp(name, key_str_camerastoredirect) == 0)
552 *outValue = &file->RedirectCameras;
553 else if (_stricmp(name, key_str_loadbalanceinfo) == 0)
554 *outValue = &file->LoadBalanceInfo;
555 else if (_stricmp(name, key_str_remoteapplicationname) == 0)
556 *outValue = &file->RemoteApplicationName;
557 else if (_stricmp(name, key_str_remoteapplicationicon) == 0)
558 *outValue = &file->RemoteApplicationIcon;
559 else if (_stricmp(name, key_str_remoteapplicationprogram) == 0)
560 *outValue = &file->RemoteApplicationProgram;
561 else if (_stricmp(name, key_str_remoteapplicationfile) == 0)
562 *outValue = &file->RemoteApplicationFile;
563 else if (_stricmp(name, key_str_remoteapplicationguid) == 0)
564 *outValue = &file->RemoteApplicationGuid;
565 else if (_stricmp(name, key_str_remoteapplicationcmdline) == 0)
566 *outValue = &file->RemoteApplicationCmdLine;
567 else if (_stricmp(name, key_str_alternate_shell) == 0)
568 *outValue = &file->AlternateShell;
569 else if (_stricmp(name, key_str_shell_working_directory) == 0)
570 *outValue = &file->ShellWorkingDirectory;
571 else if (_stricmp(name, key_str_gatewayhostname) == 0)
572 *outValue = &file->GatewayHostname;
573 else if (_stricmp(name, key_str_resourceprovider) == 0)
574 *outValue = &file->ResourceProvider;
575 else if (_stricmp(name, key_str_wvd) == 0)
576 *outValue = &file->WvdEndpointPool;
577 else if (_stricmp(name, key_str_geo) == 0)
578 *outValue = &file->geo;
579 else if (_stricmp(name, key_str_armpath) == 0)
580 *outValue = &file->armpath;
581 else if (_stricmp(name, key_str_aadtenantid) == 0)
582 *outValue = &file->aadtenantid;
583 else if (_stricmp(name, key_str_diagnosticserviceurl) == 0)
584 *outValue = &file->diagnosticserviceurl;
585 else if (_stricmp(name, key_str_hubdiscoverygeourl) == 0)
586 *outValue = &file->hubdiscoverygeourl;
587 else if (_stricmp(name, key_str_activityhint) == 0)
588 *outValue = &file->activityhint;
589 else if (_stricmp(name, key_str_gatewayaccesstoken) == 0)
590 *outValue = &file->GatewayAccessToken;
591 else if (_stricmp(name, key_str_endpointfedauth) == 0)
592 *outValue = &file->EndpointFedAuthToken;
593 else if (_stricmp(name, key_str_kdcproxyname) == 0)
594 *outValue = &file->KdcProxyName;
595 else if (_stricmp(name, key_str_drivestoredirect) == 0)
596 *outValue = &file->DrivesToRedirect;
597 else if (_stricmp(name, key_str_devicestoredirect) == 0)
598 *outValue = &file->DevicesToRedirect;
599 else if (_stricmp(name, key_str_winposstr) == 0)
600 *outValue = &file->WinPosStr;
601 else if (_stricmp(name, key_str_pcb) == 0)
602 *outValue = &file->PreconnectionBlob;
603 else if (_stricmp(name, key_str_selectedmonitors) == 0)
604 *outValue = &file->SelectedMonitors;
605 else
606 {
607 rdpFileLine* line = freerdp_client_rdp_file_find_line_by_name(file, name);
608 if (!line)
609 return FALSE;
610 if (!(line->flags & RDP_FILE_LINE_FLAG_TYPE_STRING))
611 return FALSE;
612
613 *outLine = line;
614 }
615
616 return TRUE;
617}
618
619/*
620 * Set an integer in a rdpFile
621 *
622 * @return FALSE if a standard name was set, TRUE for a non-standard name, FALSE on error
623 *
624 */
625static BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, long value)
626{
627 DWORD* targetValue = nullptr;
628 rdpFileLine* line = nullptr;
629#ifdef DEBUG_CLIENT_FILE
630 WLog_DBG(TAG, "%s:i:%ld", name, value);
631#endif
632
633 if (value < 0)
634 return FALSE;
635
636 if (!freerdp_client_rdp_file_find_integer_entry(file, name, &targetValue, &line))
637 {
638 SSIZE_T index = freerdp_client_rdp_file_add_line(file);
639 if (index == -1)
640 return FALSE;
641 line = &file->lines[index];
642 }
643
644 if (targetValue)
645 {
646 *targetValue = (DWORD)value;
647 return TRUE;
648 }
649
650 if (line)
651 {
652 free(line->name);
653 line->name = _strdup(name);
654 if (!line->name)
655 {
656 free(line->name);
657 line->name = nullptr;
658 return FALSE;
659 }
660
661 line->iValue = value;
662 line->flags = RDP_FILE_LINE_FLAG_FORMATTED;
663 line->flags |= RDP_FILE_LINE_FLAG_TYPE_INTEGER;
664 line->valueLength = 0;
665 return TRUE;
666 }
667
668 return FALSE;
669}
670
671static BOOL freerdp_client_parse_rdp_file_integer(rdpFile* file, const char* name,
672 const char* value)
673{
674 char* endptr = nullptr;
675 long ivalue = 0;
676 errno = 0;
677 ivalue = strtol(value, &endptr, 0);
678
679 if ((endptr == nullptr) || (errno != 0) || (endptr == value) || (ivalue > INT32_MAX) ||
680 (ivalue < INT32_MIN))
681 {
682 if (file->flags & RDP_FILE_FLAG_PARSE_INT_RELAXED)
683 {
684 WLog_WARN(TAG, "Integer option %s has invalid value %s, using default", name, value);
685 return TRUE;
686 }
687 else
688 {
689 WLog_ERR(TAG, "Failed to convert RDP file integer option %s [value=%s]", name, value);
690 return FALSE;
691 }
692 }
693
694 return freerdp_client_rdp_file_set_integer(file, name, ivalue);
695}
696
705static BOOL freerdp_client_rdp_file_set_string(rdpFile* file, const char* name, const char* value)
706{
707 LPSTR* targetValue = nullptr;
708 rdpFileLine* line = nullptr;
709#ifdef DEBUG_CLIENT_FILE
710 WLog_DBG(TAG, "%s:s:%s", name, value);
711#endif
712
713 if (!name || !value)
714 return FALSE;
715
716 if (!freerdp_client_rdp_file_find_string_entry(file, name, &targetValue, &line))
717 {
718 SSIZE_T index = freerdp_client_rdp_file_add_line(file);
719 if (index == -1)
720 return FALSE;
721 line = &file->lines[index];
722 }
723
724 if (targetValue)
725 {
726 if ((uintptr_t)(*targetValue) != UINTPTR_MAX)
727 free(*targetValue);
728
729 *targetValue = _strdup(value);
730 return ((*targetValue) != nullptr);
731 }
732
733 if (line)
734 {
735 free(line->name);
736 free(line->sValue);
737 line->name = _strdup(name);
738 line->sValue = _strdup(value);
739 if (!line->name || !line->sValue)
740 {
741 free(line->name);
742 free(line->sValue);
743 line->name = nullptr;
744 line->sValue = nullptr;
745 return FALSE;
746 }
747
748 line->flags = RDP_FILE_LINE_FLAG_FORMATTED;
749 line->flags |= RDP_FILE_LINE_FLAG_TYPE_STRING;
750 line->valueLength = 0;
751 return TRUE;
752 }
753
754 return FALSE;
755}
756
757static BOOL freerdp_client_add_option(rdpFile* file, const char* option)
758{
759 return freerdp_addin_argv_add_argument(file->args, option);
760}
761
762static SSIZE_T freerdp_client_rdp_file_add_line(rdpFile* file)
763{
764 SSIZE_T index = (SSIZE_T)file->lineCount;
765
766 while ((file->lineCount + 1) > file->lineSize)
767 {
768 size_t new_size = file->lineCount + 2048;
769 rdpFileLine* new_line = (rdpFileLine*)realloc(file->lines, new_size * sizeof(rdpFileLine));
770
771 if (!new_line)
772 return -1;
773
774 file->lines = new_line;
775 file->lineSize = new_size;
776 }
777
778 ZeroMemory(&(file->lines[file->lineCount]), sizeof(rdpFileLine));
779 file->lines[file->lineCount].index = (size_t)index;
780 (file->lineCount)++;
781 return index;
782}
783
784BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, const BYTE* buffer, size_t size)
785{
786 return freerdp_client_parse_rdp_file_buffer_ex(file, buffer, size, nullptr);
787}
788
789static BOOL trim(char** strptr)
790{
791 char* start = nullptr;
792 char* str = nullptr;
793 char* end = nullptr;
794
795 start = str = *strptr;
796 if (!str)
797 return TRUE;
798 if (!(~((size_t)str)))
799 return TRUE;
800 end = str + strlen(str) - 1;
801
802 while (isspace(*str))
803 str++;
804
805 while ((end > str) && isspace(*end))
806 end--;
807 end[1] = '\0';
808 if (start == str)
809 *strptr = str;
810 else
811 {
812 *strptr = _strdup(str);
813 free(start);
814 return *strptr != nullptr;
815 }
816
817 return TRUE;
818}
819
820static BOOL trim_strings(rdpFile* file)
821{
822 if (!trim(&file->Username))
823 return FALSE;
824 if (!trim(&file->Domain))
825 return FALSE;
826 if (!trim(&file->AlternateFullAddress))
827 return FALSE;
828 if (!trim(&file->FullAddress))
829 return FALSE;
830 if (!trim(&file->UsbDevicesToRedirect))
831 return FALSE;
832 if (!trim(&file->RedirectCameras))
833 return FALSE;
834 if (!trim(&file->LoadBalanceInfo))
835 return FALSE;
836 if (!trim(&file->GatewayHostname))
837 return FALSE;
838 if (!trim(&file->GatewayAccessToken))
839 return FALSE;
840 if (!trim(&file->EndpointFedAuthToken))
841 return FALSE;
842 if (!trim(&file->RemoteApplicationName))
843 return FALSE;
844 if (!trim(&file->RemoteApplicationIcon))
845 return FALSE;
846 if (!trim(&file->RemoteApplicationProgram))
847 return FALSE;
848 if (!trim(&file->RemoteApplicationFile))
849 return FALSE;
850 if (!trim(&file->RemoteApplicationGuid))
851 return FALSE;
852 if (!trim(&file->RemoteApplicationCmdLine))
853 return FALSE;
854 if (!trim(&file->AlternateShell))
855 return FALSE;
856 if (!trim(&file->ShellWorkingDirectory))
857 return FALSE;
858 if (!trim(&file->DrivesToRedirect))
859 return FALSE;
860 if (!trim(&file->DevicesToRedirect))
861 return FALSE;
862 if (!trim(&file->WinPosStr))
863 return FALSE;
864 if (!trim(&file->PreconnectionBlob))
865 return FALSE;
866 if (!trim(&file->KdcProxyName))
867 return FALSE;
868 if (!trim(&file->SelectedMonitors))
869 return FALSE;
870
871 for (size_t i = 0; i < file->lineCount; ++i)
872 {
873 rdpFileLine* curLine = &file->lines[i];
874 if (curLine->flags & RDP_FILE_LINE_FLAG_TYPE_STRING)
875 {
876 if (!trim(&curLine->sValue))
877 return FALSE;
878 }
879 }
880
881 return TRUE;
882}
883
884static BOOL parse_line(rdpFile* file, char* line, size_t length, rdp_file_fkt_parse parse)
885{
886 if (length <= 1)
887 return TRUE;
888
889 const char* beg = line;
890#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
891#if defined(WITH_EMBEDDED_CLI_IN_RDP_FILES)
892 if (beg[0] == '/')
893 {
894 freerdp_warn_deprecated(WLog_Get(TAG), "Parsing CLI options within an RDP file",
895 "Will be removed in FreeRDP 4.0");
896 if (!freerdp_client_add_option(file, line))
897 return FALSE;
898
899 return TRUE; /* FreeRDP option */
900 }
901#endif
902#endif
903
904 char* d1 = strchr(line, ':');
905
906 if (!d1)
907 return TRUE; /* not first delimiter */
908
909 const char* type = &d1[1];
910 char* d2 = strchr(type, ':');
911
912 if (!d2)
913 return TRUE; /* no second delimiter */
914
915 if ((d2 - d1) != 2)
916 return TRUE; /* improper type length */
917
918 *d1 = 0;
919 *d2 = 0;
920 const char* name = beg;
921 const char* value = &d2[1];
922
923 if (parse && parse(file->context, name, *type, value))
924 return TRUE;
925
926 if (*type == 'i')
927 {
928 /* integer type */
929 return freerdp_client_parse_rdp_file_integer(file, name, value);
930 }
931 if (*type == 's')
932 {
933 /* string type */
934 return freerdp_client_rdp_file_set_string(file, name, value);
935 }
936 if (*type == 'b')
937 {
938 /* binary type */
939 WLog_ERR(TAG, "Unsupported RDP file binary option %s [value=%s]", name, value);
940 }
941
942 return TRUE;
943}
944
945BOOL freerdp_client_parse_rdp_file_buffer_ex(rdpFile* file, const BYTE* buffer, size_t size,
946 rdp_file_fkt_parse parse)
947{
948 BOOL rc = FALSE;
949 char* copy = nullptr;
950
951 if (!file)
952 return FALSE;
953 if (size < 2)
954 return FALSE;
955
956 if ((buffer[0] == BOM_UTF16_LE[0]) && (buffer[1] == BOM_UTF16_LE[1]))
957 {
958 LPCWSTR uc = (LPCWSTR)(&buffer[2]);
959 const size_t charlen = size / sizeof(WCHAR) - 1;
960 copy = ConvertWCharNToUtf8Alloc(uc, charlen, &size);
961 if (!copy)
962 {
963 WLog_ERR(TAG, "Failed to convert RDP file from UCS2 to UTF8");
964 return FALSE;
965 }
966 }
967 else
968 {
969 copy = calloc(1, size + sizeof(BYTE));
970
971 if (!copy)
972 return FALSE;
973
974 memcpy(copy, buffer, size);
975 }
976
977 char* context = nullptr;
978 char* line = strtok_s(copy, "\r\n", &context);
979
980 while (line)
981 {
982 const size_t length = strnlen(line, size);
983
984 if (!parse_line(file, line, length, parse))
985 goto fail;
986
987 line = strtok_s(nullptr, "\r\n", &context);
988 }
989
990 rc = trim_strings(file);
991fail:
992 free(copy);
993 return rc;
994}
995
996BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
997{
998 return freerdp_client_parse_rdp_file_ex(file, name, nullptr);
999}
1000
1001BOOL freerdp_client_parse_rdp_file_ex(rdpFile* file, const char* name, rdp_file_fkt_parse parse)
1002{
1003 BOOL status = 0;
1004 BYTE* buffer = nullptr;
1005 FILE* fp = nullptr;
1006 size_t read_size = 0;
1007 INT64 file_size = 0;
1008 const char* fname = name;
1009
1010 if (!file || !name)
1011 return FALSE;
1012
1013 if (_strnicmp(fname, "file://", 7) == 0)
1014 fname = &name[7];
1015
1016 fp = winpr_fopen(fname, "r");
1017 if (!fp)
1018 {
1019 WLog_ERR(TAG, "Failed to open RDP file %s", name);
1020 return FALSE;
1021 }
1022
1023 if (_fseeki64(fp, 0, SEEK_END) < 0)
1024 goto fail;
1025 file_size = _ftelli64(fp);
1026 if (_fseeki64(fp, 0, SEEK_SET) < 0)
1027 goto fail;
1028
1029 if (file_size < 1)
1030 {
1031 WLog_ERR(TAG, "RDP file %s is empty", name);
1032 goto fail;
1033 }
1034
1035 buffer = (BYTE*)malloc((size_t)file_size + 2);
1036
1037 if (!buffer)
1038 goto fail;
1039
1040 read_size = fread(buffer, (size_t)file_size, 1, fp);
1041
1042 if (!read_size)
1043 {
1044 if (!ferror(fp))
1045 read_size = (size_t)file_size;
1046 }
1047
1048 if (read_size < 1)
1049 {
1050 WLog_ERR(TAG, "Could not read from RDP file %s", name);
1051 goto fail;
1052 }
1053
1054 buffer[file_size] = '\0';
1055 buffer[file_size + 1] = '\0';
1056 status = freerdp_client_parse_rdp_file_buffer_ex(file, buffer, (size_t)file_size, parse);
1057
1058fail:
1059 (void)fclose(fp);
1060 free(buffer);
1061 return status;
1062}
1063
1064static inline void freerdp_client_file_string_reset(char** target)
1065{
1066 WINPR_ASSERT(target);
1067 freerdp_client_file_string_check_free(*target);
1068 *target = (char*)UINTPTR_MAX;
1069}
1070
1071static inline BOOL FILE_POPULATE_STRING(char** _target, const rdpSettings* _settings,
1072 FreeRDP_Settings_Keys_String _option)
1073{
1074 WINPR_ASSERT(_target);
1075 WINPR_ASSERT(_settings);
1076
1077 const char* str = freerdp_settings_get_string(_settings, _option);
1078 freerdp_client_file_string_reset(_target);
1079 if (str)
1080 {
1081 char* copy = _strdup(str);
1082 if (!copy)
1083 return FALSE;
1084 *_target = copy;
1085 }
1086 return TRUE;
1087}
1088
1089static char* freerdp_client_channel_args_to_string(const rdpSettings* settings, const char* channel,
1090 const char* option)
1091{
1092 ADDIN_ARGV* args = freerdp_dynamic_channel_collection_find(settings, channel);
1093 const char* filters[] = { option };
1094 if (!args || (args->argc < 2))
1095 return nullptr;
1096
1097 return CommandLineToCommaSeparatedValuesEx(args->argc - 1, args->argv + 1, filters,
1098 ARRAYSIZE(filters));
1099}
1100
1101static BOOL rdp_opt_duplicate(const rdpSettings* _settings, FreeRDP_Settings_Keys_String _id,
1102 char** _key)
1103{
1104 WINPR_ASSERT(_settings);
1105 WINPR_ASSERT(_key);
1106 const char* tmp = freerdp_settings_get_string(_settings, _id);
1107
1108 if (tmp)
1109 {
1110 *_key = _strdup(tmp);
1111 if (!*_key)
1112 return FALSE;
1113 }
1114
1115 return TRUE;
1116}
1117
1118BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSettings* settings)
1119{
1120 FreeRDP_Settings_Keys_String index = FreeRDP_STRING_UNUSED;
1121 UINT32 LoadBalanceInfoLength = 0;
1122 const char* GatewayHostname = nullptr;
1123 char* redirectCameras = nullptr;
1124
1125 if (!file || !settings)
1126 return FALSE;
1127
1128 if (!FILE_POPULATE_STRING(&file->Domain, settings, FreeRDP_Domain) ||
1129 !FILE_POPULATE_STRING(&file->Username, settings, FreeRDP_Username) ||
1130 !FILE_POPULATE_STRING(&file->Password, settings, FreeRDP_Password) ||
1131 !FILE_POPULATE_STRING(&file->FullAddress, settings, FreeRDP_ServerHostname) ||
1132 !FILE_POPULATE_STRING(&file->AlternateFullAddress, settings, FreeRDP_ServerHostname) ||
1133 !FILE_POPULATE_STRING(&file->AlternateShell, settings, FreeRDP_AlternateShell) ||
1134 !FILE_POPULATE_STRING(&file->DrivesToRedirect, settings, FreeRDP_DrivesToRedirect))
1135
1136 return FALSE;
1137 file->ServerPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
1138
1139 file->DesktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
1140 file->DesktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
1141 file->SessionBpp = freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
1142 file->DesktopScaleFactor = freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor);
1143 file->DynamicResolution = WINPR_ASSERTING_INT_CAST(
1144 UINT32, freerdp_settings_get_bool(settings, FreeRDP_SupportDisplayControl));
1145 file->VideoPlaybackMode = WINPR_ASSERTING_INT_CAST(
1146 UINT32, freerdp_settings_get_bool(settings, FreeRDP_SupportVideoOptimized));
1147
1148 // TODO file->MaximizeToCurrentDisplays;
1149 // TODO file->SingleMonInWindowedMode;
1150 // TODO file->EncodeRedirectedVideoCapture;
1151 // TODO file->RedirectedVideoCaptureEncodingQuality;
1152 file->ConnectToConsole = WINPR_ASSERTING_INT_CAST(
1153 UINT32, freerdp_settings_get_bool(settings, FreeRDP_ConsoleSession));
1154 file->NegotiateSecurityLayer = WINPR_ASSERTING_INT_CAST(
1155 UINT32, freerdp_settings_get_bool(settings, FreeRDP_NegotiateSecurityLayer));
1156 file->EnableCredSSPSupport =
1157 WINPR_ASSERTING_INT_CAST(UINT32, freerdp_settings_get_bool(settings, FreeRDP_NlaSecurity));
1158 file->EnableRdsAadAuth =
1159 WINPR_ASSERTING_INT_CAST(UINT32, freerdp_settings_get_bool(settings, FreeRDP_AadSecurity));
1160
1161 if (freerdp_settings_get_bool(settings, FreeRDP_RemoteApplicationMode))
1162 index = FreeRDP_RemoteApplicationWorkingDir;
1163 else
1164 index = FreeRDP_ShellWorkingDirectory;
1165 if (!FILE_POPULATE_STRING(&file->ShellWorkingDirectory, settings, index))
1166 return FALSE;
1167 file->ConnectionType = freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType);
1168
1169 file->ScreenModeId = freerdp_settings_get_bool(settings, FreeRDP_Fullscreen) ? 2 : 1;
1170
1171 LoadBalanceInfoLength = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
1172 if (LoadBalanceInfoLength > 0)
1173 {
1174 const BYTE* LoadBalanceInfo =
1175 freerdp_settings_get_pointer(settings, FreeRDP_LoadBalanceInfo);
1176 file->LoadBalanceInfo = calloc(LoadBalanceInfoLength + 1, 1);
1177 if (!file->LoadBalanceInfo)
1178 return FALSE;
1179 memcpy(file->LoadBalanceInfo, LoadBalanceInfo, LoadBalanceInfoLength);
1180 }
1181
1182 if (freerdp_settings_get_bool(settings, FreeRDP_AudioPlayback))
1183 file->AudioMode = AUDIO_MODE_REDIRECT;
1184 else if (freerdp_settings_get_bool(settings, FreeRDP_RemoteConsoleAudio))
1185 file->AudioMode = AUDIO_MODE_PLAY_ON_SERVER;
1186 else
1187 file->AudioMode = AUDIO_MODE_NONE;
1188
1189 /* The gateway hostname should also contain a port specifier unless it is the default port 443
1190 */
1191 GatewayHostname = freerdp_settings_get_string(settings, FreeRDP_GatewayHostname);
1192 if (GatewayHostname)
1193 {
1194 const UINT32 GatewayPort = freerdp_settings_get_uint32(settings, FreeRDP_GatewayPort);
1195 freerdp_client_file_string_check_free(file->GatewayHostname);
1196 if (GatewayPort == 443)
1197 file->GatewayHostname = _strdup(GatewayHostname);
1198 else
1199 {
1200 int length = _scprintf("%s:%" PRIu32, GatewayHostname, GatewayPort);
1201 if (length < 0)
1202 return FALSE;
1203
1204 file->GatewayHostname = (char*)malloc((size_t)length + 1);
1205 if (!file->GatewayHostname)
1206 return FALSE;
1207
1208 if (sprintf_s(file->GatewayHostname, (size_t)length + 1, "%s:%" PRIu32, GatewayHostname,
1209 GatewayPort) < 0)
1210 return FALSE;
1211 }
1212 if (!file->GatewayHostname)
1213 return FALSE;
1214 }
1215
1216 if (freerdp_settings_get_bool(settings, FreeRDP_GatewayArmTransport))
1217 file->ResourceProvider = _strdup(str_resourceprovider_arm);
1218
1219 if (!rdp_opt_duplicate(settings, FreeRDP_GatewayAvdWvdEndpointPool, &file->WvdEndpointPool))
1220 return FALSE;
1221 if (!rdp_opt_duplicate(settings, FreeRDP_GatewayAvdGeo, &file->geo))
1222 return FALSE;
1223 if (!rdp_opt_duplicate(settings, FreeRDP_GatewayAvdArmpath, &file->armpath))
1224 return FALSE;
1225 if (!rdp_opt_duplicate(settings, FreeRDP_GatewayAvdAadtenantid, &file->aadtenantid))
1226 return FALSE;
1227 if (!rdp_opt_duplicate(settings, FreeRDP_GatewayAvdDiagnosticserviceurl,
1228 &file->diagnosticserviceurl))
1229 return FALSE;
1230 if (!rdp_opt_duplicate(settings, FreeRDP_GatewayAvdHubdiscoverygeourl,
1231 &file->hubdiscoverygeourl))
1232 return FALSE;
1233 if (!rdp_opt_duplicate(settings, FreeRDP_GatewayAvdActivityhint, &file->activityhint))
1234 return FALSE;
1235
1236 file->AudioCaptureMode =
1237 WINPR_ASSERTING_INT_CAST(UINT32, freerdp_settings_get_bool(settings, FreeRDP_AudioCapture));
1238 file->BitmapCachePersistEnable = WINPR_ASSERTING_INT_CAST(
1239 UINT32, freerdp_settings_get_bool(settings, FreeRDP_BitmapCachePersistEnabled));
1240 file->Compression = WINPR_ASSERTING_INT_CAST(
1241 UINT32, freerdp_settings_get_bool(settings, FreeRDP_CompressionEnabled));
1242 file->AuthenticationLevel = freerdp_settings_get_uint32(settings, FreeRDP_AuthenticationLevel);
1243 file->GatewayUsageMethod = freerdp_get_gateway_usage_method(settings);
1244 file->GatewayCredentialsSource =
1245 freerdp_settings_get_uint32(settings, FreeRDP_GatewayCredentialsSource);
1246 file->PromptCredentialOnce = WINPR_ASSERTING_INT_CAST(
1247 UINT32, freerdp_settings_get_bool(settings, FreeRDP_GatewayUseSameCredentials));
1248 file->PromptForCredentials = WINPR_ASSERTING_INT_CAST(
1249 UINT32, freerdp_settings_get_bool(settings, FreeRDP_PromptForCredentials));
1250 file->RemoteApplicationMode = WINPR_ASSERTING_INT_CAST(
1251 UINT32, freerdp_settings_get_bool(settings, FreeRDP_RemoteApplicationMode));
1252 if (!FILE_POPULATE_STRING(&file->GatewayAccessToken, settings, FreeRDP_GatewayAccessToken) ||
1253 !FILE_POPULATE_STRING(&file->EndpointFedAuthToken, settings,
1254 FreeRDP_EndpointFedAuthToken) ||
1255 !FILE_POPULATE_STRING(&file->RemoteApplicationProgram, settings,
1256 FreeRDP_RemoteApplicationProgram) ||
1257 !FILE_POPULATE_STRING(&file->RemoteApplicationName, settings,
1258 FreeRDP_RemoteApplicationName) ||
1259 !FILE_POPULATE_STRING(&file->RemoteApplicationIcon, settings,
1260 FreeRDP_RemoteApplicationIcon) ||
1261 !FILE_POPULATE_STRING(&file->RemoteApplicationFile, settings,
1262 FreeRDP_RemoteApplicationFile) ||
1263 !FILE_POPULATE_STRING(&file->RemoteApplicationGuid, settings,
1264 FreeRDP_RemoteApplicationGuid) ||
1265 !FILE_POPULATE_STRING(&file->RemoteApplicationCmdLine, settings,
1266 FreeRDP_RemoteApplicationCmdLine))
1267 return FALSE;
1268 file->SpanMonitors =
1269 WINPR_ASSERTING_INT_CAST(UINT32, freerdp_settings_get_bool(settings, FreeRDP_SpanMonitors));
1270 file->UseMultiMon =
1271 WINPR_ASSERTING_INT_CAST(UINT32, freerdp_settings_get_bool(settings, FreeRDP_UseMultimon));
1272 file->AllowDesktopComposition = WINPR_ASSERTING_INT_CAST(
1273 UINT32, freerdp_settings_get_bool(settings, FreeRDP_AllowDesktopComposition));
1274 file->AllowFontSmoothing = WINPR_ASSERTING_INT_CAST(
1275 UINT32, freerdp_settings_get_bool(settings, FreeRDP_AllowFontSmoothing));
1276 file->DisableWallpaper = WINPR_ASSERTING_INT_CAST(
1277 UINT32, freerdp_settings_get_bool(settings, FreeRDP_DisableWallpaper));
1278 file->DisableFullWindowDrag = WINPR_ASSERTING_INT_CAST(
1279 UINT32, freerdp_settings_get_bool(settings, FreeRDP_DisableFullWindowDrag));
1280 file->DisableMenuAnims = WINPR_ASSERTING_INT_CAST(
1281 UINT32, freerdp_settings_get_bool(settings, FreeRDP_DisableMenuAnims));
1282 file->DisableThemes = WINPR_ASSERTING_INT_CAST(
1283 UINT32, freerdp_settings_get_bool(settings, FreeRDP_DisableThemes));
1284 file->BandwidthAutoDetect = (freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType) >=
1285 CONNECTION_TYPE_AUTODETECT);
1286 file->NetworkAutoDetect =
1287 freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect) ? 1 : 0;
1288 file->AutoReconnectionEnabled = WINPR_ASSERTING_INT_CAST(
1289 UINT32, freerdp_settings_get_bool(settings, FreeRDP_AutoReconnectionEnabled));
1290 file->RedirectSmartCards = WINPR_ASSERTING_INT_CAST(
1291 UINT32, freerdp_settings_get_bool(settings, FreeRDP_RedirectSmartCards));
1292 file->RedirectWebauthN = WINPR_ASSERTING_INT_CAST(
1293 UINT32, freerdp_settings_get_bool(settings, FreeRDP_RedirectWebAuthN));
1294
1295 redirectCameras =
1296 freerdp_client_channel_args_to_string(settings, RDPECAM_DVC_CHANNEL_NAME, "device:");
1297 if (redirectCameras)
1298 {
1299 char* str =
1300 freerdp_client_channel_args_to_string(settings, RDPECAM_DVC_CHANNEL_NAME, "encode:");
1301 file->EncodeRedirectedVideoCapture = 0;
1302 if (str)
1303 {
1304 unsigned long val = 0;
1305 errno = 0;
1306 val = strtoul(str, nullptr, 0);
1307 if ((val < UINT32_MAX) && (errno == 0))
1308 file->EncodeRedirectedVideoCapture = (UINT32)val;
1309 }
1310 free(str);
1311
1312 str = freerdp_client_channel_args_to_string(settings, RDPECAM_DVC_CHANNEL_NAME, "quality:");
1313 file->RedirectedVideoCaptureEncodingQuality = 0;
1314 if (str)
1315 {
1316 unsigned long val = 0;
1317 errno = 0;
1318 val = strtoul(str, nullptr, 0);
1319 if ((val <= 2) && (errno == 0))
1320 {
1321 file->RedirectedVideoCaptureEncodingQuality = (UINT32)val;
1322 }
1323 }
1324 free(str);
1325
1326 file->RedirectCameras = redirectCameras;
1327 }
1328 else
1329 freerdp_client_file_string_reset(&file->RedirectCameras);
1330
1331#ifdef CHANNEL_URBDRC_CLIENT
1332 char* redirectUsb =
1333 freerdp_client_channel_args_to_string(settings, URBDRC_CHANNEL_NAME, "device:");
1334 if (redirectUsb)
1335 file->UsbDevicesToRedirect = redirectUsb;
1336 else
1337 freerdp_client_file_string_reset(&file->UsbDevicesToRedirect);
1338#endif
1339
1340 file->RedirectClipboard =
1341 freerdp_settings_get_bool(settings, FreeRDP_RedirectClipboard) ? 1 : 0;
1342 file->RedirectPrinters = freerdp_settings_get_bool(settings, FreeRDP_RedirectPrinters) ? 1 : 0;
1343 file->RedirectDrives = freerdp_settings_get_bool(settings, FreeRDP_RedirectDrives) ? 1 : 0;
1344 file->RdgIsKdcProxy = freerdp_settings_get_bool(settings, FreeRDP_KerberosRdgIsProxy) ? 1 : 0;
1345 file->RedirectComPorts = (freerdp_settings_get_bool(settings, FreeRDP_RedirectSerialPorts) ||
1346 freerdp_settings_get_bool(settings, FreeRDP_RedirectParallelPorts));
1347 file->RedirectLocation =
1348 (freerdp_dynamic_channel_collection_find(settings, LOCATION_CHANNEL_NAME) != nullptr);
1349 if (!FILE_POPULATE_STRING(&file->DrivesToRedirect, settings, FreeRDP_DrivesToRedirect) ||
1350 !FILE_POPULATE_STRING(&file->PreconnectionBlob, settings, FreeRDP_PreconnectionBlob) ||
1351 !FILE_POPULATE_STRING(&file->KdcProxyName, settings, FreeRDP_KerberosKdcUrl))
1352 return FALSE;
1353
1354 {
1355 size_t offset = 0;
1356 UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
1357 const UINT32* MonitorIds = freerdp_settings_get_pointer(settings, FreeRDP_MonitorIds);
1358 /* String size: 10 char UINT32 max string length, 1 char separator, one element nullptr */
1359 size_t size = count * (10 + 1) + 1;
1360
1361 char* str = calloc(size, sizeof(char));
1362 for (UINT32 x = 0; x < count; x++)
1363 {
1364 int rc = _snprintf(&str[offset], size - offset, "%" PRIu32 ",", MonitorIds[x]);
1365 if (rc <= 0)
1366 {
1367 free(str);
1368 return FALSE;
1369 }
1370 offset += (size_t)rc;
1371 }
1372 if (offset > 0)
1373 str[offset - 1] = '\0';
1374 freerdp_client_file_string_check_free(file->SelectedMonitors);
1375 file->SelectedMonitors = str;
1376 }
1377
1378 file->KeyboardHook = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardHook);
1379
1380 return TRUE;
1381}
1382
1383BOOL freerdp_client_write_rdp_file(const rdpFile* file, const char* name, BOOL unicode)
1384{
1385 int status = 0;
1386 WCHAR* unicodestr = nullptr;
1387
1388 if (!file || !name)
1389 return FALSE;
1390
1391 const size_t size = freerdp_client_write_rdp_file_buffer(file, nullptr, 0);
1392 if (size == 0)
1393 return FALSE;
1394 char* buffer = calloc(size + 1ULL, sizeof(char));
1395 if (!buffer)
1396 return FALSE;
1397
1398 if (freerdp_client_write_rdp_file_buffer(file, buffer, size + 1) != size)
1399 {
1400 WLog_ERR(TAG, "freerdp_client_write_rdp_file: error writing to output buffer");
1401 free(buffer);
1402 return FALSE;
1403 }
1404
1405 FILE* fp = winpr_fopen(name, "w+b");
1406
1407 if (fp)
1408 {
1409 if (unicode)
1410 {
1411 size_t len = 0;
1412 unicodestr = ConvertUtf8NToWCharAlloc(buffer, size, &len);
1413
1414 if (!unicodestr)
1415 {
1416 free(buffer);
1417 (void)fclose(fp);
1418 return FALSE;
1419 }
1420
1421 /* Write multi-byte header */
1422 if ((fwrite(BOM_UTF16_LE, sizeof(BYTE), 2, fp) != 2) ||
1423 (fwrite(unicodestr, sizeof(WCHAR), len, fp) != len))
1424 {
1425 free(buffer);
1426 free(unicodestr);
1427 (void)fclose(fp);
1428 return FALSE;
1429 }
1430
1431 free(unicodestr);
1432 }
1433 else
1434 {
1435 if (fwrite(buffer, 1, size, fp) != size)
1436 {
1437 free(buffer);
1438 (void)fclose(fp);
1439 return FALSE;
1440 }
1441 }
1442
1443 (void)fflush(fp);
1444 status = fclose(fp);
1445 }
1446
1447 free(buffer);
1448 return (status == 0);
1449}
1450
1451WINPR_ATTR_FORMAT_ARG(3, 4)
1452static SSIZE_T freerdp_client_write_setting_to_buffer(char** buffer, size_t* bufferSize,
1453 WINPR_FORMAT_ARG const char* fmt, ...)
1454{
1455 va_list ap = WINPR_C_ARRAY_INIT;
1456 SSIZE_T len = 0;
1457 char* buf = nullptr;
1458 size_t bufSize = 0;
1459
1460 if (!buffer || !bufferSize || !fmt)
1461 return -1;
1462
1463 buf = *buffer;
1464 bufSize = *bufferSize;
1465
1466 va_start(ap, fmt);
1467 len = vsnprintf(buf, bufSize, fmt, ap);
1468 va_end(ap);
1469 if (len < 0)
1470 return -1;
1471
1472 /* _snprintf doesn't add the ending \0 to its return value */
1473 ++len;
1474
1475 /* we just want to know the size - return it */
1476 if (!buf && !bufSize)
1477 return len;
1478
1479 if (!buf)
1480 return -1;
1481
1482 /* update buffer size and buffer position and replace \0 with \n */
1483 if (bufSize >= (size_t)len)
1484 {
1485 *bufferSize -= (size_t)len;
1486 buf[len - 1] = '\n';
1487 *buffer = buf + len;
1488 }
1489 else
1490 return -1;
1491
1492 return len;
1493}
1494
1495static SSIZE_T write_int_parameters(const rdpFile* file, char* buffer, size_t size)
1496{
1497 WINPR_ASSERT(file);
1498
1499 struct intentry_t
1500 {
1501 const char* key;
1502 DWORD val;
1503 };
1504 const struct intentry_t settings[] = {
1505 { key_int_use_multimon, file->UseMultiMon },
1506 { key_int_maximizetocurrentdisplays, file->MaximizeToCurrentDisplays },
1507 { key_int_singlemoninwindowedmode, file->SingleMonInWindowedMode },
1508 { key_int_screen_mode_id, file->ScreenModeId },
1509 { key_int_span_monitors, file->SpanMonitors },
1510 { key_int_smart_sizing, file->SmartSizing },
1511 { key_int_dynamic_resolution, file->DynamicResolution },
1512 { key_int_enablesuperpan, file->EnableSuperSpan },
1513 { key_int_superpanaccelerationfactor, file->SuperSpanAccelerationFactor },
1514 { key_int_desktopwidth, file->DesktopWidth },
1515 { key_int_desktopheight, file->DesktopHeight },
1516 { key_int_desktop_size_id, file->DesktopSizeId },
1517 { key_int_session_bpp, file->SessionBpp },
1518 { key_int_desktopscalefactor, file->DesktopScaleFactor },
1519 { key_int_compression, file->Compression },
1520 { key_int_keyboardhook, file->KeyboardHook },
1521 { key_int_disable_ctrl_alt_del, file->DisableCtrlAltDel },
1522 { key_int_audiomode, file->AudioMode },
1523 { key_int_audioqualitymode, file->AudioQualityMode },
1524 { key_int_audiocapturemode, file->AudioCaptureMode },
1525 { key_int_encode_redirected_video_capture, file->EncodeRedirectedVideoCapture },
1526 { key_int_redirected_video_capture_encoding_quality,
1527 file->RedirectedVideoCaptureEncodingQuality },
1528 { key_int_videoplaybackmode, file->VideoPlaybackMode },
1529 { key_int_connection_type, file->ConnectionType },
1530 { key_int_networkautodetect, file->NetworkAutoDetect },
1531 { key_int_bandwidthautodetect, file->BandwidthAutoDetect },
1532 { key_int_pinconnectionbar, file->PinConnectionBar },
1533 { key_int_displayconnectionbar, file->DisplayConnectionBar },
1534 { key_int_workspaceid, file->WorkspaceId },
1535 { key_int_enableworkspacereconnect, file->EnableWorkspaceReconnect },
1536 { key_int_disable_wallpaper, file->DisableWallpaper },
1537 { key_int_allow_font_smoothing, file->AllowFontSmoothing },
1538 { key_int_allow_desktop_composition, file->AllowDesktopComposition },
1539 { key_int_disable_full_window_drag, file->DisableFullWindowDrag },
1540 { key_int_disable_menu_anims, file->DisableMenuAnims },
1541 { key_int_disable_themes, file->DisableThemes },
1542 { key_int_disable_cursor_setting, file->DisableCursorSetting },
1543 { key_int_bitmapcachesize, file->BitmapCacheSize },
1544 { key_int_bitmapcachepersistenable, file->BitmapCachePersistEnable },
1545 { key_int_server_port, file->ServerPort },
1546 { key_int_redirectdrives, file->RedirectDrives },
1547 { key_int_redirectprinters, file->RedirectPrinters },
1548 { key_int_redirectcomports, file->RedirectComPorts },
1549 { key_int_redirectlocation, file->RedirectLocation },
1550 { key_int_redirectsmartcards, file->RedirectSmartCards },
1551 { key_int_redirectclipboard, file->RedirectClipboard },
1552 { key_int_redirectposdevices, file->RedirectPosDevices },
1553 { key_int_redirectdirectx, file->RedirectDirectX },
1554 { key_int_disableprinterredirection, file->DisablePrinterRedirection },
1555 { key_int_disableclipboardredirection, file->DisableClipboardRedirection },
1556 { key_int_connect_to_console, file->ConnectToConsole },
1557 { key_int_administrative_session, file->AdministrativeSession },
1558 { key_int_autoreconnection_enabled, file->AutoReconnectionEnabled },
1559 { key_int_autoreconnect_max_retries, file->AutoReconnectMaxRetries },
1560 { key_int_public_mode, file->PublicMode },
1561 { key_int_authentication_level, file->AuthenticationLevel },
1562 { key_int_promptcredentialonce, file->PromptCredentialOnce },
1563 { key_int_prompt_for_credentials, file->PromptForCredentials },
1564 { key_int_negotiate_security_layer, file->NegotiateSecurityLayer },
1565 { key_int_enablecredsspsupport, file->EnableCredSSPSupport },
1566 { key_int_enablerdsaadauth, file->EnableRdsAadAuth },
1567 { key_int_remoteapplicationmode, file->RemoteApplicationMode },
1568 { key_int_remoteapplicationexpandcmdline, file->RemoteApplicationExpandCmdLine },
1569 { key_int_remoteapplicationexpandworkingdir, file->RemoteApplicationExpandWorkingDir },
1570 { key_int_disableconnectionsharing, file->DisableConnectionSharing },
1571 { key_int_disableremoteappcapscheck, file->DisableRemoteAppCapsCheck },
1572 { key_int_gatewayusagemethod, file->GatewayUsageMethod },
1573 { key_int_gatewayprofileusagemethod, file->GatewayProfileUsageMethod },
1574 { key_int_gatewaycredentialssource, file->GatewayCredentialsSource },
1575 { key_int_use_redirection_server_name, file->UseRedirectionServerName },
1576 { key_int_rdgiskdcproxy, file->RdgIsKdcProxy },
1577 { key_int_redirectwebauthn, file->RedirectWebauthN }
1578 };
1579
1580 SSIZE_T totalSize = 0;
1581 for (size_t x = 0; x < ARRAYSIZE(settings); x++)
1582 {
1583 const struct intentry_t* cur = &settings[x];
1584 if (~cur->val)
1585 {
1586 const SSIZE_T res = freerdp_client_write_setting_to_buffer(
1587 &buffer, &size, "%s:i:%" PRIu32, cur->key, cur->val);
1588 if (res < 0)
1589 return res;
1590 totalSize += res;
1591 }
1592 }
1593
1594 return totalSize;
1595}
1596
1597static SSIZE_T write_string_parameters(const rdpFile* file, char* buffer, size_t size)
1598{
1599 WINPR_ASSERT(file);
1600
1601 struct strentry_t
1602 {
1603 const char* key;
1604 const char* val;
1605 };
1606 const struct strentry_t settings[] = {
1607 { key_str_username, file->Username },
1608 { key_str_domain, file->Domain },
1609 { key_str_password, file->Password },
1610 { key_str_full_address, file->FullAddress },
1611 { key_str_alternate_full_address, file->AlternateFullAddress },
1612 { key_str_usbdevicestoredirect, file->UsbDevicesToRedirect },
1613 { key_str_camerastoredirect, file->RedirectCameras },
1614 { key_str_loadbalanceinfo, file->LoadBalanceInfo },
1615 { key_str_remoteapplicationname, file->RemoteApplicationName },
1616 { key_str_remoteapplicationicon, file->RemoteApplicationIcon },
1617 { key_str_remoteapplicationprogram, file->RemoteApplicationProgram },
1618 { key_str_remoteapplicationfile, file->RemoteApplicationFile },
1619 { key_str_remoteapplicationguid, file->RemoteApplicationGuid },
1620 { key_str_remoteapplicationcmdline, file->RemoteApplicationCmdLine },
1621 { key_str_alternate_shell, file->AlternateShell },
1622 { key_str_shell_working_directory, file->ShellWorkingDirectory },
1623 { key_str_gatewayhostname, file->GatewayHostname },
1624 { key_str_resourceprovider, file->ResourceProvider },
1625 { key_str_wvd, file->WvdEndpointPool },
1626 { key_str_geo, file->geo },
1627 { key_str_armpath, file->armpath },
1628 { key_str_aadtenantid, file->aadtenantid },
1629 { key_str_diagnosticserviceurl, file->diagnosticserviceurl },
1630 { key_str_hubdiscoverygeourl, file->hubdiscoverygeourl },
1631 { key_str_activityhint, file->activityhint },
1632 { key_str_gatewayaccesstoken, file->GatewayAccessToken },
1633 { key_str_endpointfedauth, file->EndpointFedAuthToken },
1634 { key_str_kdcproxyname, file->KdcProxyName },
1635 { key_str_drivestoredirect, file->DrivesToRedirect },
1636 { key_str_devicestoredirect, file->DevicesToRedirect },
1637 { key_str_winposstr, file->WinPosStr },
1638 { key_str_pcb, file->PreconnectionBlob },
1639 { key_str_selectedmonitors, file->SelectedMonitors }
1640 };
1641
1642 SSIZE_T totalSize = 0;
1643 for (size_t x = 0; x < ARRAYSIZE(settings); x++)
1644 {
1645 const struct strentry_t* cur = &settings[x];
1646 if (~(size_t)(cur->val))
1647 {
1648 const SSIZE_T res = freerdp_client_write_setting_to_buffer(&buffer, &size, "%s:s:%s",
1649 cur->key, cur->val);
1650 if (res < 0)
1651 return res;
1652 totalSize += res;
1653 }
1654 }
1655
1656 return totalSize;
1657}
1658
1659static SSIZE_T write_custom_parameters(const rdpFile* file, char* buffer, size_t size)
1660{
1661 WINPR_ASSERT(file);
1662
1663 SSIZE_T totalSize = 0;
1664 /* custom parameters */
1665 for (size_t i = 0; i < file->lineCount; ++i)
1666 {
1667 SSIZE_T res = -1;
1668 const rdpFileLine* curLine = &file->lines[i];
1669
1670 if (curLine->flags & RDP_FILE_LINE_FLAG_TYPE_INTEGER)
1671 res = freerdp_client_write_setting_to_buffer(&buffer, &size, "%s:i:%" PRIu32,
1672 curLine->name, (UINT32)curLine->iValue);
1673 else if (curLine->flags & RDP_FILE_LINE_FLAG_TYPE_STRING)
1674 res = freerdp_client_write_setting_to_buffer(&buffer, &size, "%s:s:%s", curLine->name,
1675 curLine->sValue);
1676 if (res < 0)
1677 return res;
1678
1679 totalSize += res;
1680 }
1681 return totalSize;
1682}
1683
1684size_t freerdp_client_write_rdp_file_buffer(const rdpFile* file, char* buffer, size_t size)
1685{
1686 size_t totalSize = 0;
1687
1688 if (!file)
1689 return 0;
1690
1691 /* either buffer and size are null or non-null */
1692 if ((!buffer || !size) && (buffer || size))
1693 return 0;
1694
1695 /* integer parameters */
1696 const SSIZE_T intsize = write_int_parameters(file, buffer, size);
1697 if (intsize < 0)
1698 return 0;
1699 totalSize += (size_t)intsize;
1700 if (buffer)
1701 buffer += intsize;
1702
1703 /* string parameters */
1704 const SSIZE_T stringsize = write_string_parameters(file, buffer, size);
1705 if (stringsize < 0)
1706 return 0;
1707 totalSize += (size_t)stringsize;
1708 if (buffer)
1709 buffer += stringsize;
1710
1711 /* custom parameters */
1712 const SSIZE_T customsize = write_custom_parameters(file, buffer, size);
1713 if (customsize < 0)
1714 return 0;
1715 totalSize += (size_t)customsize;
1716 return totalSize;
1717}
1718
1719static ADDIN_ARGV* rdp_file_to_args(const char* channel, const char* values)
1720{
1721 size_t count = 0;
1722 char** p = nullptr;
1723 ADDIN_ARGV* args = freerdp_addin_argv_new(0, nullptr);
1724 if (!args)
1725 return nullptr;
1726 if (!freerdp_addin_argv_add_argument(args, channel))
1727 goto fail;
1728
1729 p = CommandLineParseCommaSeparatedValues(values, &count);
1730 for (size_t x = 0; x < count; x++)
1731 {
1732 BOOL rc = 0;
1733 const char* val = p[x];
1734 const size_t len = strlen(val) + 8;
1735 char* str = calloc(len, sizeof(char));
1736 if (!str)
1737 goto fail;
1738
1739 (void)_snprintf(str, len, "device:%s", val);
1740 rc = freerdp_addin_argv_add_argument(args, str);
1741 free(str);
1742 if (!rc)
1743 goto fail;
1744 }
1745 CommandLineParserFree(p);
1746 return args;
1747
1748fail:
1749 CommandLineParserFree(p);
1750 freerdp_addin_argv_free(args);
1751 return nullptr;
1752}
1753
1754BOOL freerdp_client_populate_settings_from_rdp_file_unchecked(const rdpFile* file,
1755 rdpSettings* settings)
1756{
1757 if (!file || !settings)
1758 return FALSE;
1759
1760 /* Start with connection type.
1761 * This setting initializes certain defaults which might be overridden by later options.
1762 */
1763 if (~file->BandwidthAutoDetect)
1764 {
1765 if (file->BandwidthAutoDetect != 0)
1766 {
1767 if ((~file->NetworkAutoDetect) && (file->NetworkAutoDetect == 0))
1768 {
1769 WLog_WARN(TAG,
1770 "Got networkautodetect:i:%" PRIu32 " and bandwidthautodetect:i:%" PRIu32
1771 ". Correcting to networkautodetect:i:1",
1772 file->NetworkAutoDetect, file->BandwidthAutoDetect);
1773 WLog_WARN(TAG,
1774 "Add networkautodetect:i:1 to your RDP file to eliminate this warning.");
1775 }
1776 }
1777 if (!freerdp_settings_set_bool(settings, FreeRDP_NetworkAutoDetect,
1778 (file->BandwidthAutoDetect != 0) ||
1779 (file->NetworkAutoDetect != 0)))
1780 return FALSE;
1781 }
1782
1783 if (~file->NetworkAutoDetect)
1784 {
1785 if (file->NetworkAutoDetect != 0)
1786 {
1787 if ((~file->BandwidthAutoDetect) && (file->BandwidthAutoDetect == 0))
1788 {
1789 WLog_WARN(TAG,
1790 "Got networkautodetect:i:%" PRIu32 " and bandwidthautodetect:i:%" PRIu32
1791 ". Correcting to bandwidthautodetect:i:1",
1792 file->NetworkAutoDetect, file->BandwidthAutoDetect);
1793 WLog_WARN(
1794 TAG, "Add bandwidthautodetect:i:1 to your RDP file to eliminate this warning.");
1795 }
1796 }
1797 if (!freerdp_settings_set_bool(settings, FreeRDP_NetworkAutoDetect,
1798 (file->BandwidthAutoDetect != 0) ||
1799 (file->NetworkAutoDetect != 0)))
1800 return FALSE;
1801 }
1802
1803 if (~((size_t)file->Domain))
1804 {
1805 if (!freerdp_settings_set_string(settings, FreeRDP_Domain, file->Domain))
1806 return FALSE;
1807 }
1808
1809 if (~((size_t)file->Username))
1810 {
1811 char* user = nullptr;
1812 char* domain = nullptr;
1813
1814 if (!freerdp_parse_username(file->Username, &user, &domain))
1815 return FALSE;
1816
1817 if (!freerdp_settings_set_string(settings, FreeRDP_Username, user))
1818 return FALSE;
1819
1820 if (!(~((size_t)file->Domain)) && domain)
1821 {
1822 if (!freerdp_settings_set_string(settings, FreeRDP_Domain, domain))
1823 return FALSE;
1824 }
1825
1826 free(user);
1827 free(domain);
1828 }
1829
1830 if (~((size_t)file->Password))
1831 {
1832 if (!freerdp_settings_set_string(settings, FreeRDP_Password, file->Password))
1833 return FALSE;
1834 }
1835
1836 {
1837 const char* address = nullptr;
1838
1839 /* With MSTSC alternate full address always wins,
1840 * so mimic this. */
1841 if (~((size_t)file->AlternateFullAddress))
1842 address = file->AlternateFullAddress;
1843 else if (~((size_t)file->FullAddress))
1844 address = file->FullAddress;
1845
1846 if (address)
1847 {
1848 int port = -1;
1849 char* host = nullptr;
1850
1851 if (!freerdp_parse_hostname(address, &host, &port))
1852 return FALSE;
1853
1854 const BOOL rc = freerdp_settings_set_string(settings, FreeRDP_ServerHostname, host);
1855 free(host);
1856 if (!rc)
1857 return FALSE;
1858
1859 if (port > 0)
1860 {
1861 if (!freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, (UINT32)port))
1862 return FALSE;
1863 }
1864 }
1865 }
1866
1867 if (~file->ServerPort)
1868 {
1869 if (!freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, file->ServerPort))
1870 return FALSE;
1871 }
1872
1873 if (~file->DesktopSizeId)
1874 {
1875 switch (file->DesktopSizeId)
1876 {
1877 case 0:
1878 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, 640))
1879 return FALSE;
1880 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, 480))
1881 return FALSE;
1882 break;
1883 case 1:
1884 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, 800))
1885 return FALSE;
1886 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, 600))
1887 return FALSE;
1888 break;
1889 case 2:
1890 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, 1024))
1891 return FALSE;
1892 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, 768))
1893 return FALSE;
1894 break;
1895 case 3:
1896 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, 1280))
1897 return FALSE;
1898 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, 1024))
1899 return FALSE;
1900 break;
1901 case 4:
1902 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, 1600))
1903 return FALSE;
1904 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, 1200))
1905 return FALSE;
1906 break;
1907 default:
1908 WLog_WARN(TAG, "Unsupported 'desktop size id' value %" PRIu32, file->DesktopSizeId);
1909 break;
1910 }
1911 }
1912
1913 if (~file->DesktopWidth)
1914 {
1915 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, file->DesktopWidth))
1916 return FALSE;
1917 }
1918
1919 if (~file->DesktopHeight)
1920 {
1921 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, file->DesktopHeight))
1922 return FALSE;
1923 }
1924
1925 if (~file->SessionBpp)
1926 {
1927 if (!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, file->SessionBpp))
1928 return FALSE;
1929 }
1930
1931 if (~file->ConnectToConsole)
1932 {
1933 if (!freerdp_settings_set_bool(settings, FreeRDP_ConsoleSession,
1934 file->ConnectToConsole != 0))
1935 return FALSE;
1936 }
1937
1938 if (~file->AdministrativeSession)
1939 {
1940 if (!freerdp_settings_set_bool(settings, FreeRDP_ConsoleSession,
1941 file->AdministrativeSession != 0))
1942 return FALSE;
1943 }
1944
1945 if (~file->NegotiateSecurityLayer)
1946 {
1947 if (!freerdp_settings_set_bool(settings, FreeRDP_NegotiateSecurityLayer,
1948 file->NegotiateSecurityLayer != 0))
1949 return FALSE;
1950 }
1951
1952 if (~file->EnableCredSSPSupport)
1953 {
1954 if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity,
1955 file->EnableCredSSPSupport != 0))
1956 return FALSE;
1957 }
1958
1959 if (~file->EnableRdsAadAuth)
1960 {
1961 const BOOL val = file->EnableRdsAadAuth != 0;
1962 if (!freerdp_settings_set_bool(settings, FreeRDP_AadSecurity, val))
1963 return FALSE;
1964 }
1965
1966 if (~((size_t)file->AlternateShell))
1967 {
1968 if (!freerdp_settings_set_string(settings, FreeRDP_AlternateShell, file->AlternateShell))
1969 return FALSE;
1970 }
1971
1972 if (~((size_t)file->ShellWorkingDirectory))
1973 {
1974 /* ShellWorkingDir is used for either, shell working dir or remote app working dir */
1975 FreeRDP_Settings_Keys_String targetId =
1976 (~file->RemoteApplicationMode && file->RemoteApplicationMode != 0)
1977 ? FreeRDP_RemoteApplicationWorkingDir
1978 : FreeRDP_ShellWorkingDirectory;
1979
1980 if (!freerdp_settings_set_string(settings, targetId, file->ShellWorkingDirectory))
1981 return FALSE;
1982 }
1983
1984 if (~file->ScreenModeId)
1985 {
1998 if (!freerdp_settings_set_bool(settings, FreeRDP_Fullscreen, (file->ScreenModeId == 2)))
1999 return FALSE;
2000 }
2001
2002 if (~(file->SmartSizing))
2003 {
2004 if (!freerdp_settings_set_bool(settings, FreeRDP_SmartSizing, (file->SmartSizing == 1)))
2005 return FALSE;
2015 if (((~(file->DesktopWidth) && ~(file->DesktopHeight)) || ~(file->DesktopSizeId)) &&
2016 (file->SmartSizing == 1))
2017 {
2018 if (!freerdp_settings_set_uint32(settings, FreeRDP_SmartSizingWidth,
2019 file->DesktopWidth))
2020 return FALSE;
2021 if (!freerdp_settings_set_uint32(settings, FreeRDP_SmartSizingHeight,
2022 file->DesktopHeight))
2023 return FALSE;
2024 }
2025 }
2026
2027 if (~((size_t)file->LoadBalanceInfo))
2028 {
2029 const size_t len = strlen(file->LoadBalanceInfo);
2030 if (!freerdp_settings_set_pointer_len(settings, FreeRDP_LoadBalanceInfo,
2031 file->LoadBalanceInfo, len))
2032 return FALSE;
2033 }
2034
2035 if (~file->AuthenticationLevel)
2036 {
2051 if (!freerdp_settings_set_uint32(settings, FreeRDP_AuthenticationLevel,
2052 file->AuthenticationLevel))
2053 return FALSE;
2054 }
2055
2056 if (~file->ConnectionType)
2057 {
2058 if (!freerdp_settings_set_uint32(settings, FreeRDP_ConnectionType, file->ConnectionType))
2059 return FALSE;
2060 }
2061
2062 if (~file->AudioMode)
2063 {
2064 switch (file->AudioMode)
2065 {
2066 case AUDIO_MODE_REDIRECT:
2067 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE))
2068 return FALSE;
2069 if (!freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, TRUE))
2070 return FALSE;
2071 break;
2072 case AUDIO_MODE_PLAY_ON_SERVER:
2073 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, TRUE))
2074 return FALSE;
2075 if (!freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE))
2076 return FALSE;
2077 break;
2078 case AUDIO_MODE_NONE:
2079 default:
2080 if (!freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE))
2081 return FALSE;
2082 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE))
2083 return FALSE;
2084 break;
2085 }
2086 }
2087
2088 if (~file->AudioCaptureMode)
2089 {
2090 if (!freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, file->AudioCaptureMode != 0))
2091 return FALSE;
2092 }
2093
2094 if (~file->Compression)
2095 {
2096 if (!freerdp_settings_set_bool(settings, FreeRDP_CompressionEnabled,
2097 file->Compression != 0))
2098 return FALSE;
2099 }
2100
2101 if (~((size_t)file->GatewayHostname))
2102 {
2103 int port = -1;
2104 char* host = nullptr;
2105
2106 if (!freerdp_parse_hostname(file->GatewayHostname, &host, &port))
2107 return FALSE;
2108
2109 const BOOL rc = freerdp_settings_set_string(settings, FreeRDP_GatewayHostname, host);
2110 free(host);
2111 if (!rc)
2112 return FALSE;
2113
2114 if (port > 0)
2115 {
2116 if (!freerdp_settings_set_uint32(settings, FreeRDP_GatewayPort, (UINT32)port))
2117 return FALSE;
2118 }
2119 }
2120
2121 if (~((size_t)file->ResourceProvider))
2122 {
2123 if (_stricmp(file->ResourceProvider, str_resourceprovider_arm) == 0)
2124 {
2125 if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayArmTransport, TRUE))
2126 return FALSE;
2127 }
2128 }
2129
2130 if (~((size_t)file->WvdEndpointPool))
2131 {
2132 if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdWvdEndpointPool,
2133 file->WvdEndpointPool))
2134 return FALSE;
2135 }
2136
2137 if (~((size_t)file->geo))
2138 {
2139 if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdGeo, file->geo))
2140 return FALSE;
2141 }
2142
2143 if (~((size_t)file->armpath))
2144 {
2145 if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdArmpath, file->armpath))
2146 return FALSE;
2147 }
2148
2149 if (~((size_t)file->aadtenantid))
2150 {
2151 if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdAadtenantid,
2152 file->aadtenantid))
2153 return FALSE;
2154 }
2155
2156 if (~((size_t)file->diagnosticserviceurl))
2157 {
2158 if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdDiagnosticserviceurl,
2159 file->diagnosticserviceurl))
2160 return FALSE;
2161 }
2162
2163 if (~((size_t)file->hubdiscoverygeourl))
2164 {
2165 if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdHubdiscoverygeourl,
2166 file->hubdiscoverygeourl))
2167 return FALSE;
2168 }
2169
2170 if (~((size_t)file->activityhint))
2171 {
2172 if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdActivityhint,
2173 file->activityhint))
2174 return FALSE;
2175 }
2176
2177 if (~((size_t)file->GatewayAccessToken))
2178 {
2179 if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAccessToken,
2180 file->GatewayAccessToken))
2181 return FALSE;
2182 }
2183
2184 if (~((size_t)file->EndpointFedAuthToken))
2185 {
2186 if (!freerdp_settings_set_string(settings, FreeRDP_EndpointFedAuthToken,
2187 file->EndpointFedAuthToken))
2188 return FALSE;
2189 }
2190
2191 if (~file->GatewayUsageMethod)
2192 {
2193 if (!freerdp_set_gateway_usage_method(settings, file->GatewayUsageMethod))
2194 return FALSE;
2195 }
2196
2197 if (~file->PromptCredentialOnce)
2198 {
2199 if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayUseSameCredentials,
2200 file->PromptCredentialOnce != 0))
2201 return FALSE;
2202 }
2203
2204 if (~file->PromptForCredentials)
2205 {
2206 if (!freerdp_settings_set_bool(settings, FreeRDP_PromptForCredentials,
2207 file->PromptForCredentials != 0))
2208 return FALSE;
2209 }
2210
2211 if (~file->RemoteApplicationMode)
2212 {
2213 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteApplicationMode,
2214 file->RemoteApplicationMode != 0))
2215 return FALSE;
2216 }
2217
2218 if (~((size_t)file->RemoteApplicationProgram))
2219 {
2220 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteApplicationProgram,
2221 file->RemoteApplicationProgram))
2222 return FALSE;
2223 }
2224
2225 if (~((size_t)file->RemoteApplicationName))
2226 {
2227 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteApplicationName,
2228 file->RemoteApplicationName))
2229 return FALSE;
2230 }
2231
2232 if (~((size_t)file->RemoteApplicationIcon))
2233 {
2234 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteApplicationIcon,
2235 file->RemoteApplicationIcon))
2236 return FALSE;
2237 }
2238
2239 if (~((size_t)file->RemoteApplicationFile))
2240 {
2241 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteApplicationFile,
2242 file->RemoteApplicationFile))
2243 return FALSE;
2244 }
2245
2246 if (~((size_t)file->RemoteApplicationGuid))
2247 {
2248 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteApplicationGuid,
2249 file->RemoteApplicationGuid))
2250 return FALSE;
2251 }
2252
2253 if (~((size_t)file->RemoteApplicationCmdLine))
2254 {
2255 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteApplicationCmdLine,
2256 file->RemoteApplicationCmdLine))
2257 return FALSE;
2258 }
2259
2260 if (~file->SpanMonitors)
2261 {
2262 if (!freerdp_settings_set_bool(settings, FreeRDP_SpanMonitors, file->SpanMonitors != 0))
2263 return FALSE;
2264 }
2265
2266 if (~file->UseMultiMon)
2267 {
2268 if (!freerdp_settings_set_bool(settings, FreeRDP_UseMultimon, file->UseMultiMon != 0))
2269 return FALSE;
2270 }
2271
2272 if (~file->AllowFontSmoothing)
2273 {
2274 if (!freerdp_settings_set_bool(settings, FreeRDP_AllowFontSmoothing,
2275 file->AllowFontSmoothing != 0))
2276 return FALSE;
2277 }
2278
2279 if (~file->DisableWallpaper)
2280 {
2281 if (!freerdp_settings_set_bool(settings, FreeRDP_DisableWallpaper,
2282 file->DisableWallpaper != 0))
2283 return FALSE;
2284 }
2285
2286 if (~file->DisableFullWindowDrag)
2287 {
2288 if (!freerdp_settings_set_bool(settings, FreeRDP_DisableFullWindowDrag,
2289 file->DisableFullWindowDrag != 0))
2290 return FALSE;
2291 }
2292
2293 if (~file->DisableMenuAnims)
2294 {
2295 if (!freerdp_settings_set_bool(settings, FreeRDP_DisableMenuAnims,
2296 file->DisableMenuAnims != 0))
2297 return FALSE;
2298 }
2299
2300 if (~file->DisableThemes)
2301 {
2302 if (!freerdp_settings_set_bool(settings, FreeRDP_DisableThemes, file->DisableThemes != 0))
2303 return FALSE;
2304 }
2305
2306 if (~file->AllowDesktopComposition)
2307 {
2308 if (!freerdp_settings_set_bool(settings, FreeRDP_AllowDesktopComposition,
2309 file->AllowDesktopComposition != 0))
2310 return FALSE;
2311 }
2312
2313 if (~file->BitmapCachePersistEnable)
2314 {
2315 if (!freerdp_settings_set_bool(settings, FreeRDP_BitmapCachePersistEnabled,
2316 file->BitmapCachePersistEnable != 0))
2317 return FALSE;
2318 }
2319
2320 if (~file->DisableRemoteAppCapsCheck)
2321 {
2322 if (!freerdp_settings_set_bool(settings, FreeRDP_DisableRemoteAppCapsCheck,
2323 file->DisableRemoteAppCapsCheck != 0))
2324 return FALSE;
2325 }
2326
2327 if (~file->AutoReconnectionEnabled)
2328 {
2329 if (!freerdp_settings_set_bool(settings, FreeRDP_AutoReconnectionEnabled,
2330 file->AutoReconnectionEnabled != 0))
2331 return FALSE;
2332 }
2333
2334 if (~file->AutoReconnectMaxRetries)
2335 {
2336 if (!freerdp_settings_set_uint32(settings, FreeRDP_AutoReconnectMaxRetries,
2337 file->AutoReconnectMaxRetries))
2338 return FALSE;
2339 }
2340
2341 if (~file->RedirectSmartCards)
2342 {
2343 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectSmartCards,
2344 file->RedirectSmartCards != 0))
2345 return FALSE;
2346 }
2347
2348 if (~file->RedirectWebauthN)
2349 {
2350 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectWebAuthN,
2351 file->RedirectWebauthN != 0))
2352 return FALSE;
2353 }
2354
2355 if (~file->RedirectClipboard)
2356 {
2357 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard,
2358 file->RedirectClipboard != 0))
2359 return FALSE;
2360 }
2361
2362 if (~file->RedirectPrinters)
2363 {
2364 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectPrinters,
2365 file->RedirectPrinters != 0))
2366 return FALSE;
2367 }
2368
2369 if (~file->RedirectDrives)
2370 {
2371 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectDrives, file->RedirectDrives != 0))
2372 return FALSE;
2373 }
2374
2375 if (~file->RedirectPosDevices)
2376 {
2377 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectSerialPorts,
2378 file->RedirectComPorts != 0) ||
2379 !freerdp_settings_set_bool(settings, FreeRDP_RedirectParallelPorts,
2380 file->RedirectComPorts != 0))
2381 return FALSE;
2382 }
2383
2384 if (~file->RedirectComPorts)
2385 {
2386 if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectSerialPorts,
2387 file->RedirectComPorts != 0) ||
2388 !freerdp_settings_set_bool(settings, FreeRDP_RedirectParallelPorts,
2389 file->RedirectComPorts != 0))
2390 return FALSE;
2391 }
2392
2393 if (~file->RedirectLocation && (file->RedirectLocation != 0))
2394 {
2395 size_t count = 0;
2396
2397 char** ptr = CommandLineParseCommaSeparatedValuesEx(LOCATION_CHANNEL_NAME, nullptr, &count);
2398 const BOOL rc =
2399 freerdp_client_add_dynamic_channel(settings, count, (const char* const*)ptr);
2400 CommandLineParserFree(ptr);
2401 if (!rc)
2402 return FALSE;
2403 }
2404
2405 if (~file->RedirectDirectX)
2406 {
2407 /* What is this?! */
2408 }
2409
2410 if ((~((size_t)file->DevicesToRedirect)) && !utils_str_is_empty(file->DevicesToRedirect))
2411 {
2436 if (!freerdp_settings_set_bool(settings, FreeRDP_DeviceRedirection, TRUE))
2437 return FALSE;
2438 }
2439
2440 if ((~((size_t)file->DrivesToRedirect)) && !utils_str_is_empty(file->DrivesToRedirect))
2441 {
2442 if (!freerdp_settings_set_string(settings, FreeRDP_DrivesToRedirect,
2443 file->DrivesToRedirect))
2444 return FALSE;
2445 }
2446
2447 if ((~((size_t)file->RedirectCameras)) && !utils_str_is_empty(file->RedirectCameras))
2448 {
2449#if defined(CHANNEL_RDPECAM_CLIENT)
2450 union
2451 {
2452 char** c;
2453 const char* const* cc;
2454 } cnv;
2455 ADDIN_ARGV* args = rdp_file_to_args(RDPECAM_DVC_CHANNEL_NAME, file->RedirectCameras);
2456 if (!args)
2457 return FALSE;
2458
2459 BOOL status = TRUE;
2460 if (~file->EncodeRedirectedVideoCapture)
2461 {
2462 char encode[64] = WINPR_C_ARRAY_INIT;
2463 (void)_snprintf(encode, sizeof(encode), "encode:%" PRIu32,
2464 file->EncodeRedirectedVideoCapture);
2465 if (!freerdp_addin_argv_add_argument(args, encode))
2466 status = FALSE;
2467 }
2468 if (~file->RedirectedVideoCaptureEncodingQuality)
2469 {
2470 char quality[64] = WINPR_C_ARRAY_INIT;
2471 (void)_snprintf(quality, sizeof(quality), "quality:%" PRIu32,
2472 file->RedirectedVideoCaptureEncodingQuality);
2473 if (!freerdp_addin_argv_add_argument(args, quality))
2474 status = FALSE;
2475 }
2476
2477 cnv.c = args->argv;
2478 if (status)
2479 status = freerdp_client_add_dynamic_channel(
2480 settings, WINPR_ASSERTING_INT_CAST(size_t, args->argc), cnv.cc);
2481 freerdp_addin_argv_free(args);
2482 if (!status)
2483 return FALSE;
2484#else
2485 WLog_WARN(
2486 TAG,
2487 "This build does not support [MS-RDPECAM] camera redirection channel. Ignoring '%s'",
2488 key_str_camerastoredirect);
2489#endif
2490 }
2491
2492 if ((~((size_t)file->UsbDevicesToRedirect)) && !utils_str_is_empty(file->UsbDevicesToRedirect))
2493 {
2494#ifdef CHANNEL_URBDRC_CLIENT
2495 union
2496 {
2497 char** c;
2498 const char* const* cc;
2499 } cnv;
2500 ADDIN_ARGV* args = rdp_file_to_args(URBDRC_CHANNEL_NAME, file->UsbDevicesToRedirect);
2501 if (!args)
2502 return FALSE;
2503 cnv.c = args->argv;
2504 const BOOL status = freerdp_client_add_dynamic_channel(
2505 settings, WINPR_ASSERTING_INT_CAST(size_t, args->argc), cnv.cc);
2506 freerdp_addin_argv_free(args);
2507 if (!status)
2508 return FALSE;
2509#else
2510 WLog_WARN(TAG,
2511 "This build does not support [MS-RDPEUSB] usb redirection channel. Ignoring '%s'",
2512 key_str_usbdevicestoredirect);
2513#endif
2514 }
2515
2516 if (~file->KeyboardHook)
2517 {
2518 if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardHook, file->KeyboardHook))
2519 return FALSE;
2520 }
2521
2522 if (~(size_t)file->SelectedMonitors)
2523 {
2524 size_t count = 0;
2525 char** ptr = CommandLineParseCommaSeparatedValues(file->SelectedMonitors, &count);
2526 UINT32* list = nullptr;
2527
2528 if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, nullptr, count))
2529 {
2530 CommandLineParserFree(ptr);
2531 return FALSE;
2532 }
2533 list = freerdp_settings_get_pointer_writable(settings, FreeRDP_MonitorIds);
2534 if (!list && (count > 0))
2535 {
2536 CommandLineParserFree(ptr);
2537 return FALSE;
2538 }
2539 for (size_t x = 0; x < count; x++)
2540 {
2541 unsigned long val = 0;
2542 errno = 0;
2543 val = strtoul(ptr[x], nullptr, 0);
2544 if ((val >= UINT32_MAX) && (errno != 0))
2545 {
2546 CommandLineParserFree(ptr);
2547 return FALSE;
2548 }
2549 list[x] = (UINT32)val;
2550 }
2551 CommandLineParserFree(ptr);
2552 }
2553
2554 if (~file->DynamicResolution)
2555 {
2556 const BOOL val = file->DynamicResolution != 0;
2557 if (!freerdp_settings_set_bool(settings, FreeRDP_SupportDisplayControl, val))
2558 return FALSE;
2559 if (!freerdp_settings_set_bool(settings, FreeRDP_DynamicResolutionUpdate, val))
2560 return FALSE;
2561 }
2562
2563 if (~file->DesktopScaleFactor)
2564 {
2565 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopScaleFactor,
2566 file->DesktopScaleFactor))
2567 return FALSE;
2568 }
2569
2570 if (~file->VideoPlaybackMode)
2571 {
2572 if (file->VideoPlaybackMode != 0)
2573 {
2574 if (!freerdp_settings_set_bool(settings, FreeRDP_SupportGeometryTracking, TRUE) ||
2575 !freerdp_settings_set_bool(settings, FreeRDP_SupportVideoOptimized, TRUE))
2576 return FALSE;
2577 }
2578 else
2579 {
2580 if (!freerdp_settings_set_bool(settings, FreeRDP_SupportVideoOptimized, FALSE))
2581 return FALSE;
2582 }
2583 }
2584 // TODO file->MaximizeToCurrentDisplays;
2585 // TODO file->SingleMonInWindowedMode;
2586 // TODO file->EncodeRedirectedVideoCapture;
2587 // TODO file->RedirectedVideoCaptureEncodingQuality;
2588
2589 if (~((size_t)file->PreconnectionBlob))
2590 {
2591 if (!freerdp_settings_set_string(settings, FreeRDP_PreconnectionBlob,
2592 file->PreconnectionBlob) ||
2593 !freerdp_settings_set_bool(settings, FreeRDP_SendPreconnectionPdu, TRUE))
2594 return FALSE;
2595 }
2596
2597 if (~((size_t)file->KdcProxyName))
2598 {
2599 if (!freerdp_settings_set_string(settings, FreeRDP_KerberosKdcUrl, file->KdcProxyName))
2600 return FALSE;
2601 }
2602
2603 if (~file->RdgIsKdcProxy)
2604 {
2605 if (!freerdp_settings_set_bool(settings, FreeRDP_KerberosRdgIsProxy,
2606 file->RdgIsKdcProxy != 0))
2607 return FALSE;
2608 }
2609
2610 if (file->args->argc > 1)
2611 {
2612 WCHAR* ConnectionFile =
2613 freerdp_settings_get_string_as_utf16(settings, FreeRDP_ConnectionFile, nullptr);
2614
2615 if (freerdp_client_settings_parse_command_line(settings, file->args->argc, file->args->argv,
2616 FALSE) < 0)
2617 {
2618 free(ConnectionFile);
2619 return FALSE;
2620 }
2621
2622 BOOL rc = freerdp_settings_set_string_from_utf16(settings, FreeRDP_ConnectionFile,
2623 ConnectionFile);
2624 free(ConnectionFile);
2625 if (!rc)
2626 return FALSE;
2627 }
2628
2629 return TRUE;
2630}
2631
2632static BOOL freerdp_apply_connection_type_from_file(const rdpFile* file, rdpSettings* settings,
2633 UINT32 type)
2634{
2635 struct network_settings
2636 {
2637 FreeRDP_Settings_Keys_Bool id;
2638 BOOL apply;
2639 BOOL value[7];
2640 };
2641 WINPR_ASSERT(file);
2642
2643 const struct network_settings config[] = { { FreeRDP_DisableWallpaper,
2644 (~file->DisableWallpaper) == 0,
2645 { TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE } },
2646 { FreeRDP_AllowFontSmoothing,
2647 (~file->AllowFontSmoothing) == 0,
2648 { FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE } },
2649 { FreeRDP_AllowDesktopComposition,
2650 (~file->AllowDesktopComposition) == 0,
2651 { FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE } },
2652 { FreeRDP_DisableFullWindowDrag,
2653 (~file->DisableFullWindowDrag) == 0,
2654 { TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE } },
2655 { FreeRDP_DisableMenuAnims,
2656 (~file->DisableMenuAnims) == 0,
2657 { TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE } },
2658 { FreeRDP_DisableThemes,
2659 (~file->DisableThemes) == 0,
2660 { TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
2661 FALSE } } };
2662
2663 switch (type)
2664 {
2665 case CONNECTION_TYPE_INVALID:
2666 return TRUE;
2667
2668 case CONNECTION_TYPE_MODEM:
2669 case CONNECTION_TYPE_BROADBAND_LOW:
2670 case CONNECTION_TYPE_BROADBAND_HIGH:
2671 case CONNECTION_TYPE_SATELLITE:
2672 case CONNECTION_TYPE_WAN:
2673 case CONNECTION_TYPE_LAN:
2674 case CONNECTION_TYPE_AUTODETECT:
2675 break;
2676 default:
2677 WLog_WARN(TAG, "Unknown ConnectionType %" PRIu32 ", aborting", type);
2678 return FALSE;
2679 }
2680
2681 for (size_t x = 0; x < ARRAYSIZE(config); x++)
2682 {
2683 const struct network_settings* cur = &config[x];
2684 if (!cur->apply)
2685 continue;
2686
2687 if (!freerdp_settings_set_bool(settings, cur->id, cur->value[type - 1]))
2688 return FALSE;
2689 }
2690 return TRUE;
2691}
2692
2693static BOOL freerdp_set_connection_type_from_file(const rdpFile* file, rdpSettings* settings,
2694 UINT32 type)
2695{
2696 WINPR_ASSERT(file);
2697 if (!freerdp_settings_set_uint32(settings, FreeRDP_ConnectionType, type))
2698 return FALSE;
2699
2700 switch (type)
2701 {
2702 case CONNECTION_TYPE_INVALID:
2703 case CONNECTION_TYPE_MODEM:
2704 case CONNECTION_TYPE_BROADBAND_LOW:
2705 case CONNECTION_TYPE_SATELLITE:
2706 case CONNECTION_TYPE_BROADBAND_HIGH:
2707 case CONNECTION_TYPE_WAN:
2708 case CONNECTION_TYPE_LAN:
2709 if (!freerdp_apply_connection_type_from_file(file, settings, type))
2710 return FALSE;
2711 break;
2712 case CONNECTION_TYPE_AUTODETECT:
2713 if (!freerdp_apply_connection_type_from_file(file, settings, type))
2714 return FALSE;
2715 /* Automatically activate GFX and RFX codec support */
2716#ifdef WITH_GFX_H264
2717 if (!freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444v2, TRUE) ||
2718 !freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444, TRUE) ||
2719 !freerdp_settings_set_bool(settings, FreeRDP_GfxH264, TRUE))
2720 return FALSE;
2721#endif
2722 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, TRUE) ||
2723 !freerdp_settings_set_bool(settings, FreeRDP_SupportGraphicsPipeline, TRUE))
2724 return FALSE;
2725 break;
2726 default:
2727 WLog_WARN(TAG, "Unknown ConnectionType %" PRIu32 ", aborting", type);
2728 return FALSE;
2729 }
2730
2731 return TRUE;
2732}
2733
2734BOOL freerdp_client_populate_settings_from_rdp_file(const rdpFile* file, rdpSettings* settings)
2735{
2736 if (!freerdp_client_populate_settings_from_rdp_file_unchecked(file, settings))
2737 return FALSE;
2738
2739 DWORD type = freerdp_settings_get_uint32(settings, FreeRDP_ConnectionType);
2740 if ((~file->ConnectionType) == 0)
2741 {
2742 if (freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect))
2743 type = CONNECTION_TYPE_AUTODETECT;
2744 }
2745 return freerdp_set_connection_type_from_file(file, settings, type);
2746}
2747
2748static rdpFileLine* freerdp_client_rdp_file_find_line_by_name(const rdpFile* file, const char* name)
2749{
2750 BOOL bFound = FALSE;
2751 rdpFileLine* line = nullptr;
2752
2753 for (size_t index = 0; index < file->lineCount; index++)
2754 {
2755 line = &(file->lines[index]);
2756
2757 if (line->flags & RDP_FILE_LINE_FLAG_FORMATTED)
2758 {
2759 if (_stricmp(name, line->name) == 0)
2760 {
2761 bFound = TRUE;
2762 break;
2763 }
2764 }
2765 }
2766
2767 return (bFound) ? line : nullptr;
2768}
2776int freerdp_client_rdp_file_set_string_option(rdpFile* file, const char* name, const char* value)
2777{
2778 return freerdp_client_rdp_file_set_string(file, name, value);
2779}
2780
2781const char* freerdp_client_rdp_file_get_string_option(const rdpFile* file, const char* name)
2782{
2783 LPSTR* value = nullptr;
2784 rdpFileLine* line = nullptr;
2785
2786 rdpFile* wfile = WINPR_CAST_CONST_PTR_AWAY(file, rdpFile*);
2787 if (freerdp_client_rdp_file_find_string_entry(wfile, name, &value, &line))
2788 {
2789 if (value && ~(size_t)(*value))
2790 return *value;
2791 if (line)
2792 return line->sValue;
2793 }
2794
2795 return nullptr;
2796}
2797
2798int freerdp_client_rdp_file_set_integer_option(rdpFile* file, const char* name, int value)
2799{
2800 return freerdp_client_rdp_file_set_integer(file, name, value);
2801}
2802
2803int freerdp_client_rdp_file_get_integer_option(const rdpFile* file, const char* name)
2804{
2805 DWORD* value = nullptr;
2806 rdpFileLine* line = nullptr;
2807
2808 rdpFile* wfile = WINPR_CAST_CONST_PTR_AWAY(file, rdpFile*);
2809 if (freerdp_client_rdp_file_find_integer_entry(wfile, name, &value, &line))
2810 {
2811 if (value && ~(*value))
2812 return WINPR_ASSERTING_INT_CAST(int, *value);
2813 if (line)
2814 return (int)line->iValue;
2815 }
2816
2817 return -1;
2818}
2819
2820static void freerdp_client_file_string_check_free(LPSTR str)
2821{
2822 if (~((size_t)str))
2823 free(str);
2824}
2825
2826rdpFile* freerdp_client_rdp_file_new(void)
2827{
2828 return freerdp_client_rdp_file_new_ex(0);
2829}
2830
2831rdpFile* freerdp_client_rdp_file_new_ex(DWORD flags)
2832{
2833 rdpFile* file = (rdpFile*)calloc(1, sizeof(rdpFile));
2834
2835 if (!file)
2836 return nullptr;
2837
2838 file->flags = flags;
2839
2840 FillMemory(file, sizeof(rdpFile), 0xFF);
2841 file->lines = nullptr;
2842 file->lineCount = 0;
2843 file->lineSize = 32;
2844 file->GatewayProfileUsageMethod = 1;
2845 file->lines = (rdpFileLine*)calloc(file->lineSize, sizeof(rdpFileLine));
2846
2847 file->args = freerdp_addin_argv_new(0, nullptr);
2848 if (!file->lines || !file->args)
2849 goto fail;
2850
2851 if (!freerdp_client_add_option(file, "freerdp"))
2852 goto fail;
2853
2854 return file;
2855fail:
2856 WINPR_PRAGMA_DIAG_PUSH
2857 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2858 freerdp_client_rdp_file_free(file);
2859 WINPR_PRAGMA_DIAG_POP
2860 return nullptr;
2861}
2862void freerdp_client_rdp_file_free(rdpFile* file)
2863{
2864 if (file)
2865 {
2866 if (file->lineCount)
2867 {
2868 for (size_t i = 0; i < file->lineCount; i++)
2869 {
2870 free(file->lines[i].name);
2871 free(file->lines[i].sValue);
2872 }
2873 }
2874 free(file->lines);
2875
2876 freerdp_addin_argv_free(file->args);
2877
2878 freerdp_client_file_string_check_free(file->Username);
2879 freerdp_client_file_string_check_free(file->Domain);
2880 freerdp_client_file_string_check_free(file->Password);
2881 freerdp_client_file_string_check_free(file->FullAddress);
2882 freerdp_client_file_string_check_free(file->AlternateFullAddress);
2883 freerdp_client_file_string_check_free(file->UsbDevicesToRedirect);
2884 freerdp_client_file_string_check_free(file->RedirectCameras);
2885 freerdp_client_file_string_check_free(file->SelectedMonitors);
2886 freerdp_client_file_string_check_free(file->LoadBalanceInfo);
2887 freerdp_client_file_string_check_free(file->RemoteApplicationName);
2888 freerdp_client_file_string_check_free(file->RemoteApplicationIcon);
2889 freerdp_client_file_string_check_free(file->RemoteApplicationProgram);
2890 freerdp_client_file_string_check_free(file->RemoteApplicationFile);
2891 freerdp_client_file_string_check_free(file->RemoteApplicationGuid);
2892 freerdp_client_file_string_check_free(file->RemoteApplicationCmdLine);
2893 freerdp_client_file_string_check_free(file->AlternateShell);
2894 freerdp_client_file_string_check_free(file->ShellWorkingDirectory);
2895 freerdp_client_file_string_check_free(file->GatewayHostname);
2896 freerdp_client_file_string_check_free(file->GatewayAccessToken);
2897 freerdp_client_file_string_check_free(file->KdcProxyName);
2898 freerdp_client_file_string_check_free(file->DrivesToRedirect);
2899 freerdp_client_file_string_check_free(file->DevicesToRedirect);
2900 freerdp_client_file_string_check_free(file->WinPosStr);
2901 freerdp_client_file_string_check_free(file->ResourceProvider);
2902 freerdp_client_file_string_check_free(file->WvdEndpointPool);
2903 freerdp_client_file_string_check_free(file->geo);
2904 freerdp_client_file_string_check_free(file->armpath);
2905 freerdp_client_file_string_check_free(file->aadtenantid);
2906 freerdp_client_file_string_check_free(file->diagnosticserviceurl);
2907 freerdp_client_file_string_check_free(file->hubdiscoverygeourl);
2908 freerdp_client_file_string_check_free(file->activityhint);
2909 free(file);
2910 }
2911}
2912
2913void freerdp_client_rdp_file_set_callback_context(rdpFile* file, void* context)
2914{
2915 file->context = context;
2916}
#define LOCATION_CHANNEL_NAME
WINPR_ATTR_NODISCARD FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string_from_utf16(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const WCHAR *param)
Sets a string settings value. The param is converted to UTF-8 and the copy stored.
WINPR_ATTR_NODISCARD FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API WCHAR * freerdp_settings_get_string_as_utf16(const rdpSettings *settings, FreeRDP_Settings_Keys_String id, size_t *pCharLen)
Return an allocated UTF16 string.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_set_gateway_usage_method(rdpSettings *settings, UINT32 GatewayUsageMethod)
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.