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