2 * FreeRDP: A Remote Desktop Protocol client.
5 * Copyright 2009-2011 Jay Sorg
6 * Copyright 2011 Vic Lee
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
25 #include <freerdp/settings.h>
26 #include <freerdp/utils/print.h>
27 #include <freerdp/utils/memory.h>
28 #include <freerdp/utils/args.h>
31 * Parse command-line arguments and update rdpSettings members accordingly.
32 * @param settings pointer to rdpSettings struct to be updated.
33 * @param argc number of arguments available.
34 * @param argv string array of the arguments.
35 * @param plugin_callback function to be called when a plugin needs to be loaded.
36 * @param plugin_user_data pointer to be passed to the plugin_callback function.
37 * @param ui_callback function to be called when a UI-specific argument is being processed.
38 * @param ui_user_data pointer to be passed to the ui_callback function.
39 * @return number of arguments that were parsed, or FREERDP_ARGS_PARSE_RESULT on failure or --version/--help
41 int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
42 ProcessPluginArgs plugin_callback, void* plugin_user_data,
43 ProcessUIArgs ui_callback, void* ui_user_data)
49 int num_extensions = 0;
50 RDP_PLUGIN_DATA* plugin_data;
54 if ((strcmp("-h", argv[index]) == 0 ) || (strcmp("--help", argv[index]) == 0 ))
57 "FreeRDP - A Free Remote Desktop Protocol Client\n"
58 "See http://www.freerdp.com for more information\n"
60 "Usage: %s [options] server:port\n"
61 " -0: connect to console session\n"
62 " -a: set color depth in bit, default is 16\n"
63 " -c: initial working directory\n"
64 " -D: hide window decorations\n"
67 " -f: fullscreen mode\n"
68 " -g: set geometry, using format WxH or X%% or 'workarea', default is 1024x768\n"
69 " -h: print this help\n"
70 " -k: set keyboard layout ID\n"
71 " -K: do not interfere with window manager bindings\n"
72 " -m: don't send mouse motion events\n"
74 " -o: console audio\n"
76 " -s: set startup-shell\n"
77 " -t: alternative port number, default is 3389\n"
79 " -x: performance flags (m[odem], b[roadband] or l[an])\n"
80 " -X: embed into another window with a given XID.\n"
81 " -z: enable compression\n"
82 " --app: RemoteApp connection. This implies -g workarea\n"
83 " --ext: load an extension\n"
84 " --no-auth: disable authentication\n"
85 " --no-fastpath: disable fast-path\n"
86 " --gdi: graphics rendering (hw, sw)\n"
87 " --no-osb: disable offscreen bitmaps\n"
88 " --no-bmp-cache: disable bitmap cache\n"
89 " --plugin: load a virtual channel plugin\n"
90 " --rfx: enable RemoteFX\n"
91 " --rfx-mode: RemoteFX operational flags (v[ideo], i[mage]), default is video\n"
92 " --nsc: enable NSCodec (experimental)\n"
93 " --disable-wallpaper: disables wallpaper\n"
94 " --composition: enable desktop composition\n"
95 " --disable-full-window-drag: disables full window drag\n"
96 " --disable-menu-animations: disables menu animations\n"
97 " --disable-theming: disables theming\n"
98 " --no-nego: disable negotiation of security layer and enforce highest enabled security protocol\n"
99 " --no-rdp: disable Standard RDP encryption\n"
100 " --no-tls: disable TLS encryption\n"
101 " --no-nla: disable network level authentication\n"
102 " --ntlm: force NTLM authentication protocol version (1 or 2)\n"
103 " --ignore-certificate: ignore verification of logon certificate\n"
104 " --sec: force protocol security (rdp, tls or nla)\n"
105 " --secure-checksum: use salted checksums with Standard RDP encryption\n"
106 " --pcid: preconnection id\n"
107 " --pcb: preconnection blob\n"
108 " --version: print version information\n"
110 return FREERDP_ARGS_PARSE_HELP; //TODO: What is the correct return
112 else if (strcmp("-a", argv[index]) == 0)
117 printf("missing color depth\n");
118 return FREERDP_ARGS_PARSE_FAILURE;
120 settings->color_depth = atoi(argv[index]);
122 else if (strcmp("-u", argv[index]) == 0)
127 printf("missing username\n");
128 return FREERDP_ARGS_PARSE_FAILURE;
130 settings->username = xstrdup(argv[index]);
132 else if (strcmp("-p", argv[index]) == 0)
137 printf("missing password\n");
138 return FREERDP_ARGS_PARSE_FAILURE;
140 settings->password = xstrdup(argv[index]);
141 settings->autologon = 1;
144 * Overwrite original password which could be revealed by a simple "ps aux" command.
145 * This approach won't hide the password length, but it is better than nothing.
148 memset(argv[index], '*', strlen(argv[index]));
150 else if (strcmp("-d", argv[index]) == 0)
155 printf("missing domain\n");
156 return FREERDP_ARGS_PARSE_FAILURE;
158 settings->domain = xstrdup(argv[index]);
160 else if (strcmp("-s", argv[index]) == 0)
165 printf("missing shell\n");
166 return FREERDP_ARGS_PARSE_FAILURE;
168 settings->shell = xstrdup(argv[index]);
170 else if (strcmp("-c", argv[index]) == 0)
175 printf("missing directory\n");
176 return FREERDP_ARGS_PARSE_FAILURE;
178 settings->directory = xstrdup(argv[index]);
180 else if (strcmp("-g", argv[index]) == 0)
185 printf("missing dimensions\n");
186 return FREERDP_ARGS_PARSE_FAILURE;
189 if (strncmp("workarea", argv[index], 1) == 0)
191 settings->workarea = true;
195 settings->width = (uint16) strtol(argv[index], &p, 10);
199 settings->height = (uint16) strtol(p + 1, &p, 10);
203 settings->percent_screen = settings->width;
204 if (settings->percent_screen <= 0 || settings->percent_screen > 100)
206 printf("invalid geometry percentage\n");
207 return FREERDP_ARGS_PARSE_FAILURE;
212 if (ui_callback != NULL)
213 ui_callback(settings, "-g", p, ui_user_data);
217 else if (strcmp("-f", argv[index]) == 0)
219 settings->fullscreen = true;
221 else if (strcmp("-D", argv[index]) == 0)
223 settings->decorations = false;
225 else if (strcmp("-T", argv[index]) == 0)
230 printf("missing window title\n");
231 return FREERDP_ARGS_PARSE_FAILURE;
234 settings->window_title = xstrdup(argv[index]);
236 else if (strcmp("-t", argv[index]) == 0)
241 printf("missing port number\n");
242 return FREERDP_ARGS_PARSE_FAILURE;
244 settings->port = atoi(argv[index]);
246 else if (strcmp("-k", argv[index]) == 0)
251 printf("missing keyboard layout id\n");
252 return FREERDP_ARGS_PARSE_FAILURE;
254 sscanf(argv[index], "%X", &(settings->kbd_layout));
256 else if (strcmp("-K", argv[index]) == 0)
258 settings->grab_keyboard = false;
260 else if (strcmp("-n", argv[index]) == 0)
265 printf("missing client hostname\n");
266 return FREERDP_ARGS_PARSE_FAILURE;
268 strncpy(settings->client_hostname, argv[index], sizeof(settings->client_hostname) - 1);
269 settings->client_hostname[sizeof(settings->client_hostname) - 1] = 0;
271 else if (strcmp("-o", argv[index]) == 0)
273 settings->console_audio = true;
275 else if (strcmp("-0", argv[index]) == 0)
277 settings->console_session = true;
279 else if (strcmp("-z", argv[index]) == 0)
281 settings->compression = true;
283 else if (strcmp("--ntlm", argv[index]) == 0)
287 settings->ntlm_version = atoi(argv[index]);
289 if (settings->ntlm_version != 2)
290 settings->ntlm_version = 1;
292 else if (strcmp("--no-glyph-cache", argv[index]) == 0)
294 settings->glyph_cache = false;
296 else if (strcmp("--no-osb", argv[index]) == 0)
298 settings->offscreen_bitmap_cache = false;
300 else if (strcmp("--no-bmp-cache", argv[index]) == 0)
302 settings->bitmap_cache = false;
304 else if (strcmp("--no-auth", argv[index]) == 0)
306 settings->authentication = false;
308 else if (strcmp("--ignore-certificate", argv[index]) == 0)
310 settings->ignore_certificate = true;
312 else if (strcmp("--certificate-name", argv[index]) == 0)
317 printf("missing certificate name\n");
318 return FREERDP_ARGS_PARSE_FAILURE;
321 settings->certificate_name = xstrdup(argv[index]);
323 else if (strcmp("--no-fastpath", argv[index]) == 0)
325 settings->fastpath_input = false;
326 settings->fastpath_output = false;
328 else if (strcmp("--gdi", argv[index]) == 0)
333 printf("missing GDI backend\n");
334 return FREERDP_ARGS_PARSE_FAILURE;
336 if (strncmp("sw", argv[index], 1) == 0) /* software */
338 settings->sw_gdi = true;
340 else if (strncmp("hw", argv[index], 1) == 0) /* hardware */
342 settings->sw_gdi = false;
346 printf("unknown GDI backend\n");
347 return FREERDP_ARGS_PARSE_FAILURE;
350 else if (strcmp("--rfx", argv[index]) == 0)
352 settings->rfx_codec = true;
353 settings->fastpath_output = true;
354 settings->color_depth = 32;
355 settings->frame_acknowledge = false;
356 settings->performance_flags = PERF_FLAG_NONE;
357 settings->large_pointer = true;
359 else if (strcmp("--rfx-mode", argv[index]) == 0)
364 printf("missing RemoteFX mode flag\n");
365 return FREERDP_ARGS_PARSE_FAILURE;
367 if (argv[index][0] == 'v') /* video */
369 settings->rfx_codec_mode = 0x00;
371 else if (argv[index][0] == 'i') /* image */
373 settings->rfx_codec_mode = 0x02;
377 printf("unknown RemoteFX mode flag\n");
378 return FREERDP_ARGS_PARSE_FAILURE;
381 else if (strcmp("--nsc", argv[index]) == 0)
383 settings->ns_codec = true;
385 else if (strcmp("--dump-rfx", argv[index]) == 0)
390 printf("missing file name\n");
391 return FREERDP_ARGS_PARSE_FAILURE;
393 settings->dump_rfx_file = xstrdup(argv[index]);
394 settings->dump_rfx = true;
396 else if (strcmp("--play-rfx", argv[index]) == 0)
401 printf("missing file name\n");
402 return FREERDP_ARGS_PARSE_FAILURE;
404 settings->play_rfx_file = xstrdup(argv[index]);
405 settings->play_rfx = true;
407 else if (strcmp("--fonts", argv[index]) == 0)
409 settings->smooth_fonts = true;
411 else if (strcmp("--disable-wallpaper", argv[index]) == 0)
413 settings->disable_wallpaper = true;
415 else if (strcmp("--disable-full-window-drag", argv[index]) == 0)
417 settings->disable_full_window_drag = true;
419 else if (strcmp("--disable-menu-animations", argv[index]) == 0)
421 settings->disable_menu_animations = true;
423 else if (strcmp("--disable-theming", argv[index]) == 0)
425 settings->disable_theming = true;
427 else if (strcmp("--composition", argv[index]) == 0)
429 settings->desktop_composition = true;
431 else if (strcmp("--no-motion", argv[index]) == 0)
433 settings->mouse_motion = false;
435 else if (strcmp("--app", argv[index]) == 0)
437 settings->remote_app = true;
438 settings->rail_langbar_supported = true;
439 settings->workarea = true;
440 settings->performance_flags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG;
442 else if (strcmp("-x", argv[index]) == 0)
447 printf("missing performance flag\n");
448 return FREERDP_ARGS_PARSE_FAILURE;
450 if (argv[index][0] == 'm') /* modem */
452 settings->performance_flags = PERF_DISABLE_WALLPAPER |
453 PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS |
454 PERF_DISABLE_THEMING;
456 settings->connection_type = CONNECTION_TYPE_MODEM;
458 else if (argv[index][0] == 'b') /* broadband */
460 settings->performance_flags = PERF_DISABLE_WALLPAPER;
461 settings->connection_type = CONNECTION_TYPE_BROADBAND_HIGH;
463 else if (argv[index][0] == 'l') /* lan */
465 settings->performance_flags = PERF_FLAG_NONE;
466 settings->connection_type = CONNECTION_TYPE_LAN;
470 settings->performance_flags = strtol(argv[index], 0, 16);
473 else if (strcmp("-X", argv[index]) == 0)
479 printf("missing parent window XID\n");
480 return FREERDP_ARGS_PARSE_FAILURE;
483 settings->parent_window_xid = strtoul(argv[index], NULL, 16);
485 if (settings->parent_window_xid == 0)
487 printf("invalid parent window XID\n");
488 return FREERDP_ARGS_PARSE_FAILURE;
491 else if (strcmp("--no-rdp", argv[index]) == 0)
493 settings->rdp_security = false;
495 else if (strcmp("--no-tls", argv[index]) == 0)
497 settings->tls_security = false;
499 else if (strcmp("--no-nla", argv[index]) == 0)
501 settings->nla_security = false;
503 else if (strcmp("--sec", argv[index]) == 0)
508 printf("missing protocol security\n");
509 return FREERDP_ARGS_PARSE_FAILURE;
511 if (strncmp("rdp", argv[index], 1) == 0) /* Standard RDP */
513 settings->rdp_security = true;
514 settings->tls_security = false;
515 settings->nla_security = false;
516 settings->encryption = true;
517 settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
518 settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
520 else if (strncmp("tls", argv[index], 1) == 0) /* TLS */
522 settings->rdp_security = false;
523 settings->tls_security = true;
524 settings->nla_security = false;
526 else if (strncmp("nla", argv[index], 1) == 0) /* NLA */
528 settings->rdp_security = false;
529 settings->tls_security = false;
530 settings->nla_security = true;
534 printf("unknown protocol security\n");
535 return FREERDP_ARGS_PARSE_FAILURE;
538 else if (strcmp("--no-nego", argv[index]) == 0)
540 settings->security_layer_negotiation = false;
542 else if (strcmp("--plugin", argv[index]) == 0)
548 printf("missing plugin name\n");
549 return FREERDP_ARGS_PARSE_FAILURE;
552 if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0)
556 while (index < argc && strcmp("--", argv[index]) != 0)
558 if (plugin_data == NULL)
559 plugin_data = (RDP_PLUGIN_DATA*) xmalloc(sizeof(RDP_PLUGIN_DATA) * (i + 2));
561 plugin_data = (RDP_PLUGIN_DATA*) xrealloc(plugin_data, sizeof(RDP_PLUGIN_DATA) * (i + 2));
563 plugin_data[i].size = sizeof(RDP_PLUGIN_DATA);
564 plugin_data[i].data[0] = NULL;
565 plugin_data[i].data[1] = NULL;
566 plugin_data[i].data[2] = NULL;
567 plugin_data[i].data[3] = NULL;
568 plugin_data[i + 1].size = 0;
570 for (j = 0, p = argv[index]; j < 4 && p != NULL; j++)
574 plugin_data[i].data[j] = p + 1;
575 p = strchr(p + 1, '\'');
580 plugin_data[i].data[j] = p;
591 if (plugin_callback != NULL)
593 if (!plugin_callback(settings, argv[t], plugin_data, plugin_user_data))
594 return FREERDP_ARGS_PARSE_FAILURE;
597 else if (strcmp("--ext", argv[index]) == 0)
602 printf("missing extension name\n");
603 return FREERDP_ARGS_PARSE_FAILURE;
605 if (num_extensions >= sizeof(settings->extensions) / sizeof(struct rdp_ext_set))
607 printf("maximum extensions reached\n");
608 return FREERDP_ARGS_PARSE_FAILURE;
610 snprintf(settings->extensions[num_extensions].name,
611 sizeof(settings->extensions[num_extensions].name),
613 settings->extensions[num_extensions].data = NULL;
614 if (index < argc - 1 && strcmp("--data", argv[index + 1]) == 0)
617 settings->extensions[num_extensions].data = argv[index];
619 while (index < argc && strcmp("--", argv[index]) != 0)
627 else if (strcmp("--secure-checksum", argv[index]) == 0)
629 settings->secure_checksum = true;
631 else if (strcmp("--pcid", argv[index]) == 0)
636 printf("missing preconnection id value\n");
639 settings->send_preconnection_pdu = true;
640 settings->preconnection_id = atoi(argv[index]);
642 else if (strcmp("--pcb", argv[index]) == 0)
647 printf("missing preconnection blob value\n");
650 settings->send_preconnection_pdu = true;
651 settings->preconnection_blob = xstrdup(argv[index]);
653 else if (strcmp("--version", argv[index]) == 0)
655 printf("This is FreeRDP version %s\n", FREERDP_VERSION_FULL);
656 return FREERDP_ARGS_PARSE_VERSION;
658 else if (argv[index][0] != '-')
660 if (argv[index][0] == '[' && (p = strchr(argv[index], ']'))
661 && (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':'))))
663 /* Either "[...]" or "[...]:..." with at most one : after the brackets */
664 settings->hostname = xstrdup(argv[index] + 1);
665 if ((p = strchr((char*)settings->hostname, ']')))
669 settings->port = atoi(p + 2);
674 /* Port number is cut off and used if exactly one : in the string */
675 settings->hostname = xstrdup(argv[index]);
676 if ((p = strchr((char*)settings->hostname, ':')) && !strchr(p + 1, ':'))
679 settings->port = atoi(p + 1);
682 /* server is the last argument for the current session. arguments
683 followed will be parsed for the next session. */
686 if (settings->smooth_fonts)
687 settings->performance_flags |= PERF_ENABLE_FONT_SMOOTHING;
689 if (settings->desktop_composition)
690 settings->performance_flags |= PERF_ENABLE_DESKTOP_COMPOSITION;
692 if (settings->disable_wallpaper)
693 settings->performance_flags |= PERF_DISABLE_WALLPAPER;
695 if (settings->disable_full_window_drag)
696 settings->performance_flags |= PERF_DISABLE_FULLWINDOWDRAG;
698 if (settings->disable_menu_animations)
699 settings->performance_flags |= PERF_DISABLE_MENUANIMATIONS;
701 if (settings->disable_theming)
702 settings->performance_flags |= PERF_DISABLE_THEMING;
708 if (ui_callback != NULL)
710 t = ui_callback(settings, argv[index], (index + 1 < argc && argv[index + 1][0] != '-' ?
711 argv[index + 1] : NULL), ui_user_data);
714 printf("invalid option: %s\n", argv[index]);
715 return FREERDP_ARGS_PARSE_FAILURE;
722 printf("missing server name\n");
723 return FREERDP_ARGS_PARSE_FAILURE;