Coverage Report

Created: 2026-07-16 07:14

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