Fixed variable parsed.
[platform/upstream/freerdp.git] / client / common / cmdline.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * FreeRDP Client Command-Line Interface
4  *
5  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
7  *
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
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <assert.h>
26
27 #include <winpr/crt.h>
28 #include <winpr/cmdline.h>
29
30 #include <freerdp/addin.h>
31 #include <freerdp/settings.h>
32 #include <freerdp/client/channels.h>
33 #include <freerdp/crypto/crypto.h>
34 #include <freerdp/locale/keyboard.h>
35
36
37 #include <freerdp/client/cmdline.h>
38 #include <freerdp/version.h>
39
40 #include "compatibility.h"
41
42 #include <freerdp/log.h>
43 #define TAG CLIENT_TAG("common.cmdline")
44
45 COMMAND_LINE_ARGUMENT_A args[] =
46 {
47         { "v", COMMAND_LINE_VALUE_REQUIRED, "<server>[:port]", NULL, NULL, -1, NULL, "Server hostname" },
48         { "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" },
49         { "w", COMMAND_LINE_VALUE_REQUIRED, "<width>", "1024", NULL, -1, NULL, "Width" },
50         { "h", COMMAND_LINE_VALUE_REQUIRED, "<height>", "768", NULL, -1, NULL, "Height" },
51         { "size", COMMAND_LINE_VALUE_REQUIRED, "<width>x<height> or <percent>%", "1024x768", NULL, -1, NULL, "Screen size" },
52         { "f", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Fullscreen mode" },
53         { "bpp", COMMAND_LINE_VALUE_REQUIRED, "<depth>", "16", NULL, -1, NULL, "Session bpp (color depth)" },
54         { "kbd", COMMAND_LINE_VALUE_REQUIRED, "0x<layout id> or <layout name>", NULL, NULL, -1, NULL, "Keyboard layout" },
55         { "kbd-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List keyboard layouts" },
56         { "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "<type id>", NULL, NULL, -1, NULL, "Keyboard type" },
57         { "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "<subtype id>", NULL, NULL, -1, NULL, "Keyboard subtype" },
58         { "kbd-fn-key", COMMAND_LINE_VALUE_REQUIRED, "<function key count>", NULL, NULL, -1, NULL, "Keyboard function key count" },
59         { "admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "console", "Admin (or console) session" },
60         { "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" },
61         { "pth", COMMAND_LINE_VALUE_REQUIRED, "<password hash>", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" },
62         { "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "Client Hostname to send to server" },
63         { "multimon", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Use multiple monitors" },
64         { "span", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Span screen over multiple monitors" },
65         { "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use available work area" },
66         { "monitors", COMMAND_LINE_VALUE_REQUIRED, "<0,1,2...>", NULL, NULL, -1, NULL, "Select monitors to use" },
67         { "monitor-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List detected monitors" },
68         { "t", COMMAND_LINE_VALUE_REQUIRED, "<title>", NULL, NULL, -1, "title", "Window title" },
69         { "decorations", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Window decorations" },
70         { "smart-sizing", COMMAND_LINE_VALUE_OPTIONAL, "<width>x<height>", NULL, NULL, -1, NULL, "Scale remote desktop to window size" },
71         { "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, "addin", "Addin" },
72         { "vc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Static virtual channel" },
73         { "dvc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Dynamic virtual channel" },
74         { "u", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Username" },
75         { "p", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Password" },
76         { "d", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Domain" },
77         { "g", COMMAND_LINE_VALUE_OPTIONAL, "<gateway>[:port]", NULL, NULL, -1, NULL, "Gateway Hostname" },
78         { "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" },
79         { "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" },
80         { "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" },
81         { "gt", COMMAND_LINE_VALUE_REQUIRED, "<rpc|http|auto>", NULL, NULL, -1, NULL, "Gateway transport type" },
82         { "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, "gum", "Gateway usage method" },
83         { "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info string>", NULL, NULL, -1, NULL, "Load balance info" },
84         { "app", COMMAND_LINE_VALUE_REQUIRED, "<executable path> or <||alias>", NULL, NULL, -1, NULL, "Remote application program" },
85         { "app-name", COMMAND_LINE_VALUE_REQUIRED, "<app name>", NULL, NULL, -1, NULL, "Remote application name for user interface" },
86         { "app-icon", COMMAND_LINE_VALUE_REQUIRED, "<icon path>", NULL, NULL, -1, NULL, "Remote application icon for user interface" },
87         { "app-cmd", COMMAND_LINE_VALUE_REQUIRED, "<parameters>", NULL, NULL, -1, NULL, "Remote application command-line parameters" },
88         { "app-file", COMMAND_LINE_VALUE_REQUIRED, "<file name>", NULL, NULL, -1, NULL, "File to open with remote application" },
89         { "app-guid", COMMAND_LINE_VALUE_REQUIRED, "<app guid>", NULL, NULL, -1, NULL, "Remote application GUID" },
90         { "compression", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, "z", "Compression" },
91         { "compression-level", COMMAND_LINE_VALUE_REQUIRED, "<level>", NULL, NULL, -1, NULL, "Compression level (0,1,2)" },
92         { "shell", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Alternate shell" },
93         { "shell-dir", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Shell working directory" },
94         { "sound", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "audio", "Audio output (sound)" },
95         { "microphone", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "mic", "Audio input (microphone)" },
96         { "audio-mode", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Audio output mode" },
97         { "multimedia", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "mmr", "Redirect multimedia (video)" },
98         { "network", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Network connection type" },
99         { "drive", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect drive" },
100         { "drives", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect all drives" },
101         { "home-drive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect home drive" },
102         { "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect clipboard" },
103         { "serial", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "tty", "Redirect serial device" },
104         { "parallel", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect parallel device" },
105         { "smartcard", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect smartcard device" },
106         { "printer", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect printer device" },
107         { "usb", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect USB device" },
108         { "multitouch", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect multitouch input" },
109         { "gestures", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Consume multitouch input locally" },
110         { "echo", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "echo", "Echo channel" },
111         { "disp", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Display control" },
112         { "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Smooth fonts (ClearType)" },
113         { "aero", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueFalse, -1, NULL, "Desktop composition" },
114         { "window-drag", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Full window drag" },
115         { "menu-anims", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Menu animations" },
116         { "themes", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Themes" },
117         { "wallpaper", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Wallpaper" },
118         { "gdi", COMMAND_LINE_VALUE_REQUIRED, "<sw|hw>", NULL, NULL, -1, NULL, "GDI rendering" },
119         { "gfx", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" },
120         { "gfx-thin-client", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline thin client mode" },
121         { "gfx-small-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline small cache mode" },
122         { "gfx-progressive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline progressive codec" },
123         { "gfx-h264", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8.1 graphics pipeline H264 codec" },
124         { "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" },
125         { "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "<image|video>", NULL, NULL, -1, NULL, "RemoteFX mode" },
126         { "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Frame acknowledgement" },
127         { "nsc", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "nscodec", "NSCodec" },
128         { "jpeg", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "JPEG codec" },
129         { "jpeg-quality", COMMAND_LINE_VALUE_REQUIRED, "<percentage>", NULL, NULL, -1, NULL, "JPEG quality" },
130         { "nego", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "protocol security negotiation" },
131         { "sec", COMMAND_LINE_VALUE_REQUIRED, "<rdp|tls|nla|ext>", NULL, NULL, -1, NULL, "force specific protocol security" },
132         { "sec-rdp", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "rdp protocol security" },
133         { "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "tls protocol security" },
134         { "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "nla protocol security" },
135         { "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" },
136         { "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, "<netmon|ma|ciphers>", NULL, NULL, -1, NULL, "Allowed TLS ciphers" },
137         { "cert-name", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "certificate name" },
138         { "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" },
139         { "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" },
140         { "pcid", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Preconnection Id" },
141         { "spn-class", COMMAND_LINE_VALUE_REQUIRED, "<service class>", NULL, NULL, -1, NULL, "SPN authentication service class" },
142         { "credentials-delegation", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Disable credentials delegation" },
143         { "vmconnect", COMMAND_LINE_VALUE_OPTIONAL, "<vmid>", NULL, NULL, -1, NULL, "Hyper-V console (use port 2179, disable negotiation)" },
144         { "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "authentication (hack!)" },
145         { "encryption", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "encryption (hack!)" },
146         { "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "grab keyboard" },
147         { "toggle-fullscreen", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Alt+Ctrl+Enter toggles fullscreen" },
148         { "mouse-motion", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "mouse-motion" },
149         { "parent-window", COMMAND_LINE_VALUE_REQUIRED, "<window id>", NULL, NULL, -1, NULL, "Parent window id" },
150         { "bitmap-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "bitmap cache" },
151         { "offscreen-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "offscreen bitmap cache" },
152         { "glyph-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "glyph cache" },
153         { "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "<rfx|nsc|jpeg>", NULL, NULL, -1, NULL, "bitmap codec cache" },
154         { "fast-path", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "fast-path input/output" },
155         { "max-fast-path-size", COMMAND_LINE_VALUE_OPTIONAL, "<size>", NULL, NULL, -1, NULL, "maximum fast-path update size" },
156         { "async-input", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous input" },
157         { "async-update", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous update" },
158         { "async-transport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous transport (unstable)" },
159         { "async-channels", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous channels (unstable)" },
160         { "wm-class", COMMAND_LINE_VALUE_REQUIRED, "<class name>", NULL, NULL, -1, NULL, "set the WM_CLASS hint for the window instance" },
161         { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "print version" },
162         { "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "print help" },
163         { "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "<pcap file>", NULL, NULL, -1, NULL, "Replay rfx pcap file" },
164         { "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only." },
165         { "auto-reconnect", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Automatic reconnection" },
166         { "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "<base64 cookie>", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" },
167         { "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" },
168         { "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" },
169         { "multitransport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support multitransport protocol" },
170         { "assistance", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Remote assistance password" },
171         { "encryption-methods", COMMAND_LINE_VALUE_REQUIRED, "<40,56,128,FIPS>", NULL, NULL, -1, NULL, "RDP standard security encryption methods" },
172         { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
173 };
174
175 int freerdp_client_print_version()
176 {
177         printf("This is FreeRDP version %s (git %s)\n", FREERDP_VERSION_FULL, GIT_REVISION);
178         return 1;
179 }
180
181 int freerdp_client_print_command_line_help(int argc, char** argv)
182 {
183         char* str;
184         int length;
185         COMMAND_LINE_ARGUMENT_A* arg;
186
187         printf("\n");
188         printf("FreeRDP - A Free Remote Desktop Protocol Implementation\n");
189         printf("See www.freerdp.com for more information\n");
190         printf("\n");
191
192         printf("Usage: %s [file] [options] [/v:<server>[:port]]\n", argv[0]);
193         printf("\n");
194
195         printf("Syntax:\n");
196         printf("    /flag (enables flag)\n");
197         printf("    /option:<value> (specifies option with value)\n");
198         printf("    +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')\n");
199         printf("\n");
200
201         arg = args;
202
203         do
204         {
205                 if (arg->Flags & COMMAND_LINE_VALUE_FLAG)
206                 {
207                         printf("    %s", "/");
208                         printf("%-20s", arg->Name);
209                         printf("\t%s\n", arg->Text);
210                 }
211                 else if ((arg->Flags & COMMAND_LINE_VALUE_REQUIRED) || (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL))
212                 {
213                         printf("    %s", "/");
214
215                         if (arg->Format)
216                         {
217                                 length = (int)(strlen(arg->Name) + strlen(arg->Format) + 2);
218                                 str = (char*) calloc(length + 1UL, sizeof(char));
219                                 sprintf_s(str, length + 1, "%s:%s", arg->Name, arg->Format);
220                                 printf("%-20s", str);
221                                 free(str);
222                         }
223                         else
224                         {
225                                 printf("%-20s", arg->Name);
226                         }
227
228                         printf("\t%s\n", arg->Text);
229                 }
230                 else if (arg->Flags & COMMAND_LINE_VALUE_BOOL)
231                 {
232                         length = (int) strlen(arg->Name) + 32;
233                         str = (char*) calloc(length + 1UL, sizeof(char));
234                         sprintf_s(str, length + 1, "%s (default:%s)", arg->Name,
235                                         arg->Default ? "on" : "off");
236
237                         printf("    %s", arg->Default ? "-" : "+");
238
239                         printf("%-20s", str);
240                         free(str);
241
242                         printf("\t%s\n", arg->Text);
243                 }
244         }
245         while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
246
247         printf("\n");
248
249         printf("Examples:\n");
250         printf("    xfreerdp connection.rdp /p:Pwd123! /f\n");
251         printf("    xfreerdp /u:CONTOSO\\JohnDoe /p:Pwd123! /v:rdp.contoso.com\n");
252         printf("    xfreerdp /u:JohnDoe /p:Pwd123! /w:1366 /h:768 /v:192.168.1.100:4489\n");
253         printf("    xfreerdp /u:JohnDoe /p:Pwd123! /vmconnect:C824F53E-95D2-46C6-9A18-23A5BB403532 /v:192.168.1.100\n");
254         printf("\n");
255
256         printf("Clipboard Redirection: +clipboard\n");
257         printf("\n");
258
259         printf("Drive Redirection: /drive:home,/home/user\n");
260         printf("Smartcard Redirection: /smartcard:<device>\n");
261         printf("Serial Port Redirection: /serial:<name>,<device>,[SerCx2|SerCx|Serial],[permissive]\n");
262         printf("Serial Port Redirection: /serial:COM1,/dev/ttyS0\n");
263         printf("Parallel Port Redirection: /parallel:<device>\n");
264         printf("Printer Redirection: /printer:<device>,<driver>\n");
265         printf("\n");
266
267         printf("Audio Output Redirection: /sound:sys:alsa\n");
268         printf("Audio Input Redirection: /microphone:sys:alsa\n");
269         printf("\n");
270
271         printf("Multimedia Redirection: /multimedia:sys:alsa\n");
272         printf("USB Device Redirection: /usb:id,dev:054c:0268\n");
273         printf("\n");
274
275         printf("More documentation is coming, in the meantime consult source files\n");
276         printf("\n");
277
278         return 1;
279 }
280
281 int freerdp_client_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv)
282 {
283         if (index == 1)
284         {
285                 int length;
286                 rdpSettings* settings;
287
288                 length = (int) strlen(argv[index]);
289
290                 if (length > 4)
291                 {
292                         if (_stricmp(&(argv[index])[length - 4], ".rdp") == 0)
293                         {
294                                 settings = (rdpSettings*) context;
295                                 settings->ConnectionFile = _strdup(argv[index]);
296
297                                 return 1;
298                         }
299                 }
300
301                 if (length > 13)
302                 {
303                         if (_stricmp(&(argv[index])[length - 13], ".msrcIncident") == 0)
304                         {
305                                 settings = (rdpSettings*) context;
306                                 settings->AssistanceFile = _strdup(argv[index]);
307
308                                 return 1;
309                         }
310                 }
311         }
312
313         return 0;
314 }
315
316 int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params)
317 {
318         if (strcmp(params[0], "drive") == 0)
319         {
320                 RDPDR_DRIVE* drive;
321
322                 if (count < 3)
323                         return -1;
324
325                 settings->DeviceRedirection = TRUE;
326
327                 drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE));
328
329                 if (!drive)
330                         return -1;
331
332                 drive->Type = RDPDR_DTYP_FILESYSTEM;
333
334                 if (count > 1)
335                         drive->Name = _strdup(params[1]);
336
337                 if (count > 2)
338                         drive->Path = _strdup(params[2]);
339
340                 freerdp_device_collection_add(settings, (RDPDR_DEVICE*) drive);
341
342                 return 1;
343         }
344         else if (strcmp(params[0], "printer") == 0)
345         {
346                 RDPDR_PRINTER* printer;
347
348                 if (count < 1)
349                         return -1;
350
351                 settings->RedirectPrinters = TRUE;
352                 settings->DeviceRedirection = TRUE;
353
354                 if (count > 1)
355                 {
356                         printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER));
357
358                         if (!printer)
359                                 return -1;
360
361                         printer->Type = RDPDR_DTYP_PRINT;
362
363                         if (count > 1)
364                                 printer->Name = _strdup(params[1]);
365
366                         if (count > 2)
367                                 printer->DriverName = _strdup(params[2]);
368
369                         freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer);
370                 }
371
372                 return 1;
373         }
374         else if (strcmp(params[0], "smartcard") == 0)
375         {
376                 RDPDR_SMARTCARD* smartcard;
377
378                 if (count < 1)
379                         return -1;
380
381                 settings->RedirectSmartCards = TRUE;
382                 settings->DeviceRedirection = TRUE;
383
384                 if (count > 1)
385                 {
386                         smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD));
387
388                         if (!smartcard)
389                                 return -1;
390
391                         smartcard->Type = RDPDR_DTYP_SMARTCARD;
392
393                         if (count > 1)
394                                 smartcard->Name = _strdup(params[1]);
395
396                         if (count > 2)
397                                 smartcard->Path = _strdup(params[2]);
398
399                         freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard);
400                 }
401
402                 return 1;
403         }
404         else if (strcmp(params[0], "serial") == 0)
405         {
406                 RDPDR_SERIAL* serial;
407
408                 if (count < 1)
409                         return -1;
410
411                 settings->RedirectSerialPorts = TRUE;
412                 settings->DeviceRedirection = TRUE;
413
414                 serial = (RDPDR_SERIAL*) calloc(1, sizeof(RDPDR_SERIAL));
415
416                 if (!serial)
417                         return -1;
418
419                 serial->Type = RDPDR_DTYP_SERIAL;
420
421                 if (count > 1)
422                         serial->Name = _strdup(params[1]);
423
424                 if (count > 2)
425                         serial->Path = _strdup(params[2]);
426
427                 if (count > 3)
428                         serial->Driver = _strdup(params[3]);
429
430                 if (count > 4)
431                         serial->Permissive = _strdup(params[4]);
432
433                 freerdp_device_collection_add(settings, (RDPDR_DEVICE*) serial);
434
435                 return 1;
436         }
437         else if (strcmp(params[0], "parallel") == 0)
438         {
439                 RDPDR_PARALLEL* parallel;
440
441                 if (count < 1)
442                         return -1;
443
444                 settings->RedirectParallelPorts = TRUE;
445                 settings->DeviceRedirection = TRUE;
446
447                 parallel = (RDPDR_PARALLEL*) calloc(1, sizeof(RDPDR_PARALLEL));
448
449                 if (!parallel)
450                         return -1;
451
452                 parallel->Type = RDPDR_DTYP_PARALLEL;
453
454                 if (count > 1)
455                         parallel->Name = _strdup(params[1]);
456
457                 if (count > 2)
458                         parallel->Path = _strdup(params[2]);
459
460                 freerdp_device_collection_add(settings, (RDPDR_DEVICE*) parallel);
461
462                 return 1;
463         }
464
465         return 0;
466 }
467
468 int freerdp_client_add_static_channel(rdpSettings* settings, int count, char** params)
469 {
470         int index;
471         ADDIN_ARGV* args;
472
473         args = (ADDIN_ARGV*) malloc(sizeof(ADDIN_ARGV));
474
475         args->argc = count;
476         args->argv = (char**) calloc(args->argc, sizeof(char*));
477
478         for (index = 0; index < args->argc; index++)
479                 args->argv[index] = _strdup(params[index]);
480
481         freerdp_static_channel_collection_add(settings, args);
482
483         return 0;
484 }
485
486 int freerdp_client_add_dynamic_channel(rdpSettings* settings, int count, char** params)
487 {
488         int index;
489         ADDIN_ARGV* args;
490
491         args = (ADDIN_ARGV*) malloc(sizeof(ADDIN_ARGV));
492
493         args->argc = count;
494         args->argv = (char**) calloc(args->argc, sizeof(char*));
495
496         for (index = 0; index < args->argc; index++)
497                 args->argv[index] = _strdup(params[index]);
498
499         freerdp_dynamic_channel_collection_add(settings, args);
500
501         return 0;
502 }
503
504 static char** freerdp_command_line_parse_comma_separated_values(char* list, int* count)
505 {
506         char** p;
507         char* str;
508         int nArgs;
509         int index;
510         int nCommas;
511
512         nCommas = 0;
513
514         assert(NULL != count);
515
516         *count = 0;
517         if (!list)
518                 return NULL;
519
520         for (index = 0; list[index]; index++)
521                 nCommas += (list[index] == ',') ? 1 : 0;
522
523         nArgs = nCommas + 1;
524         p = (char**) calloc((nArgs + 1UL), sizeof(char*));
525
526         str = (char*) list;
527
528         p[0] = str;
529
530         for (index = 1; index < nArgs; index++)
531         {
532                 p[index] = strchr(p[index - 1], ',');
533                 *p[index] = '\0';
534                 p[index]++;
535         }
536
537         p[index] = str + strlen(str);
538
539         *count = nArgs;
540
541         return p;
542 }
543
544 static char** freerdp_command_line_parse_comma_separated_values_offset(char* list, int* count)
545 {
546         char** p;
547         char** t;
548
549         p = freerdp_command_line_parse_comma_separated_values(list, count);
550
551         t = (char**) realloc(p, sizeof(char*) * (*count + 1));
552         if (!t)
553                 return NULL;
554         p = t;
555         if (count > 0)
556                 MoveMemory(&p[1], p, sizeof(char*) * *count);
557         (*count)++;
558
559         return p;
560 }
561
562 int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT_A* arg)
563 {
564         rdpSettings* settings = (rdpSettings*) context;
565
566         CommandLineSwitchStart(arg)
567
568         CommandLineSwitchCase(arg, "a")
569         {
570                 char** p;
571                 int count;
572
573                 p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
574
575                 if (freerdp_client_add_device_channel(settings, count, p) > 0)
576                 {
577                         settings->DeviceRedirection = TRUE;
578                 }
579
580                 free(p);
581         }
582         CommandLineSwitchCase(arg, "vc")
583         {
584                 char** p;
585                 int count;
586
587                 p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
588
589                 freerdp_client_add_static_channel(settings, count, p);
590
591                 free(p);
592         }
593         CommandLineSwitchCase(arg, "dvc")
594         {
595                 char** p;
596                 int count;
597
598                 p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
599
600                 freerdp_client_add_dynamic_channel(settings, count, p);
601
602                 free(p);
603         }
604         CommandLineSwitchCase(arg, "drive")
605         {
606                 char** p;
607                 int count;
608
609                 p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
610                 p[0] = "drive";
611
612                 freerdp_client_add_device_channel(settings, count, p);
613
614                 free(p);
615         }
616         CommandLineSwitchCase(arg, "serial")
617         {
618                 char** p;
619                 int count;
620
621                 p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
622                 p[0] = "serial";
623
624                 freerdp_client_add_device_channel(settings, count, p);
625
626                 free(p);
627         }
628         CommandLineSwitchCase(arg, "parallel")
629         {
630                 char** p;
631                 int count;
632
633                 p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
634                 p[0] = "parallel";
635
636                 freerdp_client_add_device_channel(settings, count, p);
637
638                 free(p);
639         }
640         CommandLineSwitchCase(arg, "smartcard")
641         {
642                 char** p;
643                 int count;
644
645                 p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
646                 p[0] = "smartcard";
647
648                 freerdp_client_add_device_channel(settings, count, p);
649
650                 free(p);
651         }
652         CommandLineSwitchCase(arg, "printer")
653         {
654                 if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
655                 {
656                         char** p;
657                         int count;
658
659                         p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
660                         p[0] = "printer";
661
662                         freerdp_client_add_device_channel(settings, count, p);
663
664                         free(p);
665                 }
666                 else
667                 {
668                         char* p[1];
669                         int count;
670
671                         count = 1;
672                         p[0] = "printer";
673
674                         freerdp_client_add_device_channel(settings, count, p);
675                 }
676         }
677         CommandLineSwitchCase(arg, "usb")
678         {
679                 char** p;
680                 int count;
681
682                 p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
683                 p[0] = "urbdrc";
684
685                 freerdp_client_add_dynamic_channel(settings, count, p);
686
687                 free(p);
688         }
689         CommandLineSwitchCase(arg, "multitouch")
690         {
691                 settings->MultiTouchInput = TRUE;
692         }
693         CommandLineSwitchCase(arg, "gestures")
694         {
695                 settings->MultiTouchGestures = TRUE;
696         }
697         CommandLineSwitchCase(arg, "echo")
698         {
699                 settings->SupportEchoChannel = TRUE;
700         }
701         CommandLineSwitchCase(arg, "disp")
702         {
703                 settings->SupportDisplayControl = TRUE;
704         }
705         CommandLineSwitchCase(arg, "sound")
706         {
707                 if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
708                 {
709                         char** p;
710                         int count;
711
712                         p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
713                         p[0] = "rdpsnd";
714
715                         freerdp_client_add_static_channel(settings, count, p);
716
717                         free(p);
718                 }
719                 else
720                 {
721                         char* p[1];
722                         int count;
723
724                         count = 1;
725                         p[0] = "rdpsnd";
726
727                         freerdp_client_add_static_channel(settings, count, p);
728                 }
729         }
730         CommandLineSwitchCase(arg, "microphone")
731         {
732                 if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
733                 {
734                         char** p;
735                         int count;
736
737                         p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
738                         p[0] = "audin";
739
740                         freerdp_client_add_dynamic_channel(settings, count, p);
741
742                         free(p);
743                 }
744                 else
745                 {
746                         char* p[1];
747                         int count;
748
749                         count = 1;
750                         p[0] = "audin";
751
752                         freerdp_client_add_dynamic_channel(settings, count, p);
753                 }
754         }
755         CommandLineSwitchCase(arg, "multimedia")
756         {
757                 if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
758                 {
759                         char** p;
760                         int count;
761
762                         p = freerdp_command_line_parse_comma_separated_values_offset(arg->Value, &count);
763                         p[0] = "tsmf";
764
765                         freerdp_client_add_dynamic_channel(settings, count, p);
766
767                         free(p);
768                 }
769                 else
770                 {
771                         char* p[1];
772                         int count;
773
774                         count = 1;
775                         p[0] = "tsmf";
776
777                         freerdp_client_add_dynamic_channel(settings, count, p);
778                 }
779         }
780         CommandLineSwitchCase(arg, "heartbeat")
781         {
782                 settings->SupportHeartbeatPdu = TRUE;
783         }
784         CommandLineSwitchCase(arg, "multitransport")
785         {
786                 settings->SupportMultitransport = TRUE;
787                 settings->MultitransportFlags = (TRANSPORT_TYPE_UDP_FECR | TRANSPORT_TYPE_UDP_FECL | TRANSPORT_TYPE_UDP_PREFERRED);
788         }
789
790         CommandLineSwitchEnd(arg)
791
792         return 0;
793 }
794
795 int freerdp_parse_username(char* username, char** user, char** domain)
796 {
797         char* p;
798         char* u;
799         int length = 0;
800
801         p = strchr(username, '\\');
802         u = strrchr(username, '@');
803
804         if (p)
805         {
806                 length = (int) (p - username);
807                 *user = _strdup(&p[1]);
808                 if (!*user)
809                         return -1;
810
811                 *domain = (char*) calloc(length + 1UL, sizeof(char));
812                 if (!*domain)
813                 {
814                         free (*user);
815                         *user = NULL;
816                         return -1;
817                 }
818
819                 strncpy(*domain, username, length);
820                 (*domain)[length] = '\0';
821         }
822         else if (u)
823         {
824                 length = (int) (u - username);
825                 *domain = _strdup(&u[1]);
826                 if (!*domain)
827                         return -1;
828
829                 *user = (char*) calloc(length + 1UL, sizeof(char));
830                 if (!*user)
831                 {
832                         free(*domain);
833                         *domain = NULL;
834                 }
835                 strncpy(*user, username, length);
836                 (*user)[length] = '\0';
837         }
838         else
839         {
840                 /* Do not break up the name for '@'; both credSSP and the
841                  * ClientInfo PDU expect 'user@corp.net' to be transmitted
842                  * as username 'user@corp.net', domain empty.
843                  */
844                 *user = _strdup(username);
845                 if (!*user)
846                         return -1;
847
848                 *domain = NULL;
849         }
850
851         return 0;
852 }
853
854 int freerdp_parse_hostname(char* hostname, char** host, int* port)
855 {
856         char* p;
857         int length;
858
859         p = strrchr(hostname, ':');
860
861         if (p)
862         {
863                 length = (p - hostname);
864                 *host = (char*) calloc(length + 1UL, sizeof(char));
865
866                 if (!(*host))
867                         return -1;
868
869                 CopyMemory(*host, hostname, length);
870                 (*host)[length] = '\0';
871                 *port = atoi(p + 1);
872         }
873         else
874         {
875                 *host = _strdup(hostname);
876
877                 if (!(*host))
878                         return -1;
879
880                 *port = -1;
881         }
882
883         return 0;
884 }
885
886 int freerdp_set_connection_type(rdpSettings* settings, int type)
887 {
888         settings->ConnectionType = type;
889
890         if (type == CONNECTION_TYPE_MODEM)
891         {
892                 settings->DisableWallpaper = TRUE;
893                 settings->AllowFontSmoothing = FALSE;
894                 settings->AllowDesktopComposition = FALSE;
895                 settings->DisableFullWindowDrag = TRUE;
896                 settings->DisableMenuAnims = TRUE;
897                 settings->DisableThemes = TRUE;
898         }
899         else if (type == CONNECTION_TYPE_BROADBAND_LOW)
900         {
901                 settings->DisableWallpaper = TRUE;
902                 settings->AllowFontSmoothing = FALSE;
903                 settings->AllowDesktopComposition = FALSE;
904                 settings->DisableFullWindowDrag = TRUE;
905                 settings->DisableMenuAnims = TRUE;
906                 settings->DisableThemes = FALSE;
907         }
908         else if (type == CONNECTION_TYPE_SATELLITE)
909         {
910                 settings->DisableWallpaper = TRUE;
911                 settings->AllowFontSmoothing = FALSE;
912                 settings->AllowDesktopComposition = TRUE;
913                 settings->DisableFullWindowDrag = TRUE;
914                 settings->DisableMenuAnims = TRUE;
915                 settings->DisableThemes = FALSE;
916         }
917         else if (type == CONNECTION_TYPE_BROADBAND_HIGH)
918         {
919                 settings->DisableWallpaper = TRUE;
920                 settings->AllowFontSmoothing = FALSE;
921                 settings->AllowDesktopComposition = TRUE;
922                 settings->DisableFullWindowDrag = TRUE;
923                 settings->DisableMenuAnims = TRUE;
924                 settings->DisableThemes = FALSE;
925         }
926         else if (type == CONNECTION_TYPE_WAN)
927         {
928                 settings->DisableWallpaper = FALSE;
929                 settings->AllowFontSmoothing = TRUE;
930                 settings->AllowDesktopComposition = TRUE;
931                 settings->DisableFullWindowDrag = FALSE;
932                 settings->DisableMenuAnims = FALSE;
933                 settings->DisableThemes = FALSE;
934         }
935         else if (type == CONNECTION_TYPE_LAN)
936         {
937                 settings->DisableWallpaper = FALSE;
938                 settings->AllowFontSmoothing = TRUE;
939                 settings->AllowDesktopComposition = TRUE;
940                 settings->DisableFullWindowDrag = FALSE;
941                 settings->DisableMenuAnims = FALSE;
942                 settings->DisableThemes = FALSE;
943         }
944         else if (type == CONNECTION_TYPE_AUTODETECT)
945         {
946                 settings->DisableWallpaper = FALSE;
947                 settings->AllowFontSmoothing = TRUE;
948                 settings->AllowDesktopComposition = TRUE;
949                 settings->DisableFullWindowDrag = FALSE;
950                 settings->DisableMenuAnims = FALSE;
951                 settings->DisableThemes = FALSE;
952
953                 settings->NetworkAutoDetect = TRUE;
954         }
955
956         return 0;
957 }
958
959 int freerdp_map_keyboard_layout_name_to_id(char* name)
960 {
961         int i;
962         int id = 0;
963         RDP_KEYBOARD_LAYOUT* layouts;
964
965         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD);
966
967         for (i = 0; layouts[i].code; i++)
968         {
969                 if (_stricmp(layouts[i].name, name) == 0)
970                         id = layouts[i].code;
971         }
972
973         free(layouts);
974
975         if (id)
976                 return id;
977
978         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT);
979
980         for (i = 0; layouts[i].code; i++)
981         {
982                 if (_stricmp(layouts[i].name, name) == 0)
983                         id = layouts[i].code;
984         }
985
986         free(layouts);
987
988         if (id)
989                 return id;
990
991         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_IME);
992
993         for (i = 0; layouts[i].code; i++)
994         {
995                 if (_stricmp(layouts[i].name, name) == 0)
996                         id = layouts[i].code;
997         }
998
999         free(layouts);
1000
1001         if (id)
1002                 return id;
1003
1004         return 0;
1005 }
1006
1007 int freerdp_detect_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv)
1008 {
1009         int length;
1010
1011         if (index == 1)
1012         {
1013                 length = (int) strlen(argv[index]);
1014
1015                 if (length > 4)
1016                 {
1017                         if (_stricmp(&(argv[index])[length - 4], ".rdp") == 0)
1018                         {
1019                                 return 1;
1020                         }
1021                 }
1022
1023                 if (length > 13)
1024                 {
1025                         if (_stricmp(&(argv[index])[length - 13], ".msrcIncident") == 0)
1026                         {
1027                                 return 1;
1028                         }
1029                 }
1030         }
1031
1032         return 0;
1033 }
1034
1035 int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv,
1036         int* count, BOOL ignoreUnknown)
1037 {
1038         int status;
1039         DWORD flags;
1040         int detect_status;
1041         COMMAND_LINE_ARGUMENT_A* arg;
1042
1043         flags = COMMAND_LINE_SEPARATOR_COLON;
1044         flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
1045
1046         if (ignoreUnknown)
1047         {
1048                 flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
1049         }
1050
1051         *count = 0;
1052         detect_status = 0;
1053         CommandLineClearArgumentsA(args);
1054
1055         status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags,
1056                         NULL, freerdp_detect_command_line_pre_filter, NULL);
1057
1058         if (status < 0)
1059                 return status;
1060
1061         arg = args;
1062
1063         do
1064         {
1065                 if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
1066                         continue;
1067
1068                 (*count)++;
1069         }
1070         while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
1071
1072         if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
1073                 detect_status = -1;
1074
1075         return detect_status;
1076 }
1077
1078 int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv,
1079         int* count, BOOL ignoreUnknown)
1080 {
1081         int status;
1082         DWORD flags;
1083         int detect_status;
1084         COMMAND_LINE_ARGUMENT_A* arg;
1085
1086         flags = COMMAND_LINE_SEPARATOR_SPACE;
1087         flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
1088         flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
1089
1090         if (ignoreUnknown)
1091         {
1092                 flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
1093         }
1094
1095         *count = 0;
1096         detect_status = 0;
1097         CommandLineClearArgumentsA(args);
1098
1099         status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags,
1100                         NULL, freerdp_detect_command_line_pre_filter, NULL);
1101
1102         if (status < 0)
1103                 return status;
1104
1105         arg = args;
1106
1107         do
1108         {
1109                 if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
1110                         continue;
1111
1112                 (*count)++;
1113         }
1114         while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
1115
1116         if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
1117                 detect_status = -1;
1118
1119         return detect_status;
1120 }
1121
1122 static BOOL freerdp_client_detect_command_line(int argc, char** argv,
1123         DWORD* flags, BOOL ignoreUnknown)
1124 {
1125         int old_cli_status;
1126         int old_cli_count;
1127         int posix_cli_status;
1128         int posix_cli_count;
1129         int windows_cli_status;
1130         int windows_cli_count;
1131         BOOL compatibility = FALSE;
1132
1133         windows_cli_status = freerdp_detect_windows_style_command_line_syntax(argc, argv, &windows_cli_count, ignoreUnknown);
1134         posix_cli_status = freerdp_detect_posix_style_command_line_syntax(argc, argv, &posix_cli_count, ignoreUnknown);
1135         old_cli_status = freerdp_detect_old_command_line_syntax(argc, argv, &old_cli_count);
1136
1137         /* Default is POSIX syntax */
1138         *flags = COMMAND_LINE_SEPARATOR_SPACE;
1139         *flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
1140         *flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
1141
1142         if (posix_cli_status <= COMMAND_LINE_STATUS_PRINT)
1143                 return compatibility;
1144
1145         /* Check, if this may be windows style syntax... */
1146         if ((windows_cli_count && (windows_cli_count >= posix_cli_count)) || (windows_cli_status <= COMMAND_LINE_STATUS_PRINT))
1147         {
1148                 windows_cli_count = 1;
1149                 *flags = COMMAND_LINE_SEPARATOR_COLON;
1150                 *flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
1151         }
1152         else if (old_cli_status >= 0)
1153         {
1154                 /* Ignore legacy parsing in case there is an error in the command line. */
1155
1156                 if ((old_cli_status == 1) || ((old_cli_count > posix_cli_count) && (old_cli_status != -1)))
1157                 {
1158                         *flags = COMMAND_LINE_SEPARATOR_SPACE;
1159                         *flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
1160
1161                         compatibility = TRUE;
1162                 }
1163         }
1164
1165         WLog_DBG(TAG, "windows: %d/%d posix: %d/%d compat: %d/%d", windows_cli_status, windows_cli_count,
1166                 posix_cli_status, posix_cli_count, old_cli_status, old_cli_count);
1167
1168         return compatibility;
1169 }
1170
1171 int freerdp_client_settings_command_line_status_print(rdpSettings* settings, int status, int argc, char** argv)
1172 {
1173         COMMAND_LINE_ARGUMENT_A* arg;
1174
1175         if (status == COMMAND_LINE_STATUS_PRINT_VERSION)
1176         {
1177                 freerdp_client_print_version();
1178                 return COMMAND_LINE_STATUS_PRINT_VERSION;
1179         }
1180         else if (status == COMMAND_LINE_STATUS_PRINT)
1181         {
1182                 arg = CommandLineFindArgumentA(args, "kbd-list");
1183
1184                 if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1185                 {
1186                         int i;
1187                         RDP_KEYBOARD_LAYOUT* layouts;
1188
1189                         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD);
1190                         printf("\nKeyboard Layouts\n");
1191                         for (i = 0; layouts[i].code; i++)
1192                                 printf("0x%08X\t%s\n", (int) layouts[i].code, layouts[i].name);
1193                         free(layouts);
1194
1195                         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT);
1196                         printf("\nKeyboard Layout Variants\n");
1197                         for (i = 0; layouts[i].code; i++)
1198                                 printf("0x%08X\t%s\n", (int) layouts[i].code, layouts[i].name);
1199                         free(layouts);
1200
1201                         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_IME);
1202                         printf("\nKeyboard Input Method Editors (IMEs)\n");
1203                         for (i = 0; layouts[i].code; i++)
1204                                 printf("0x%08X\t%s\n", (int) layouts[i].code, layouts[i].name);
1205                         free(layouts);
1206
1207                         printf("\n");
1208                 }
1209
1210                 arg = CommandLineFindArgumentA(args, "monitor-list");
1211
1212                 if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1213                 {
1214                         settings->ListMonitors = TRUE;
1215                 }
1216
1217                 return COMMAND_LINE_STATUS_PRINT;
1218         }
1219         else if (status < 0)
1220         {
1221                 freerdp_client_print_command_line_help(argc, argv);
1222                 return COMMAND_LINE_STATUS_PRINT_HELP;
1223         }
1224
1225         return 0;
1226 }
1227
1228 int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
1229         int argc, char** argv, BOOL allowUnknown)
1230 {
1231         char* p;
1232         char* user = NULL;
1233         char* gwUser = NULL;
1234         char* str;
1235         int length;
1236         int status;
1237         DWORD flags;
1238         BOOL compatibility;
1239         COMMAND_LINE_ARGUMENT_A* arg;
1240
1241         compatibility = freerdp_client_detect_command_line(argc, argv, &flags, allowUnknown);
1242
1243         if (compatibility)
1244         {
1245                 WLog_WARN(TAG, "Using deprecated command-line interface!");
1246                 return freerdp_client_parse_old_command_line_arguments(argc, argv, settings);
1247         }
1248         else
1249         {
1250                 CommandLineClearArgumentsA(args);
1251
1252                 if (allowUnknown)
1253                 {
1254                         flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
1255                 }
1256                 status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, settings,
1257                                 freerdp_client_command_line_pre_filter, freerdp_client_command_line_post_filter);
1258
1259                 if (status < 0)
1260                         return status;
1261         }
1262
1263         CommandLineFindArgumentA(args, "v");
1264
1265         arg = args;
1266
1267         do
1268         {
1269                 if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
1270                         continue;
1271
1272                 CommandLineSwitchStart(arg)
1273
1274                 CommandLineSwitchCase(arg, "v")
1275                 {
1276                         p = strchr(arg->Value, '[');
1277                         /* ipv4 */
1278                         if (!p)
1279                         {
1280                                 p = strchr(arg->Value, ':');
1281                                 if (p)
1282                                 {
1283                                         length = (int) (p - arg->Value);
1284                                         settings->ServerPort = atoi(&p[1]);
1285                                         settings->ServerHostname = (char*) calloc(length + 1UL, sizeof(char));
1286                                         strncpy(settings->ServerHostname, arg->Value, length);
1287                                         settings->ServerHostname[length] = '\0';
1288                                 }
1289                                 else
1290                                 {
1291                                         settings->ServerHostname = _strdup(arg->Value);
1292                                 }
1293                         }
1294                         else /* ipv6 */
1295                         {
1296                                 char *p2 = strchr(arg->Value, ']');
1297                                 /* not a valid [] ipv6 addr found */
1298                                 if (!p2)
1299                                         continue;
1300
1301                                 length = p2 - p;
1302                                 settings->ServerHostname = (char*) calloc(length, sizeof(char));
1303                                 strncpy(settings->ServerHostname, p+1, length-1);
1304                                 if (*(p2 + 1) == ':')
1305                                 {
1306                                         settings->ServerPort = atoi(&p2[2]);
1307                                 }
1308                                 printf("hostname %s port %d\n", settings->ServerHostname, settings->ServerPort);
1309                         }
1310                 }
1311                 CommandLineSwitchCase(arg, "spn-class")
1312                 {
1313                         settings->AuthenticationServiceClass = _strdup(arg->Value);
1314                 }
1315                 CommandLineSwitchCase(arg, "credentials-delegation")
1316                 {
1317                         settings->DisableCredentialsDelegation = arg->Value ? FALSE : TRUE;
1318                 }
1319                 CommandLineSwitchCase(arg, "vmconnect")
1320                 {
1321                         settings->ServerPort = 2179;
1322                         settings->NegotiateSecurityLayer = FALSE;
1323
1324                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1325                         {
1326                                 settings->SendPreconnectionPdu = TRUE;
1327                                 settings->PreconnectionBlob = _strdup(arg->Value);
1328                         }
1329                 }
1330                 CommandLineSwitchCase(arg, "w")
1331                 {
1332                         settings->DesktopWidth = atoi(arg->Value);
1333                 }
1334                 CommandLineSwitchCase(arg, "h")
1335                 {
1336                         settings->DesktopHeight = atoi(arg->Value);
1337                 }
1338                 CommandLineSwitchCase(arg, "size")
1339                 {
1340                         str = _strdup(arg->Value);
1341
1342                         p = strchr(str, 'x');
1343
1344                         if (p)
1345                         {
1346                                 *p = '\0';
1347                                 settings->DesktopWidth = atoi(str);
1348                                 settings->DesktopHeight = atoi(&p[1]);
1349                         }
1350                         else
1351                         {
1352                                 p = strchr(str, '%');
1353                                 if(p)
1354                                 {
1355                                         settings->PercentScreen = atoi(str);
1356                                 }
1357                         }
1358
1359                         free(str);
1360                 }
1361                 CommandLineSwitchCase(arg, "f")
1362                 {
1363                         settings->Fullscreen = TRUE;
1364                 }
1365                 CommandLineSwitchCase(arg, "multimon")
1366                 {
1367                         settings->UseMultimon = TRUE;
1368
1369                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1370                         {
1371                                 if (_stricmp(arg->Value, "force") == 0)
1372                                 {
1373                                         settings->ForceMultimon = TRUE;
1374                                 }
1375                         }
1376                 }
1377                 CommandLineSwitchCase(arg, "span")
1378                 {
1379                         settings->SpanMonitors = TRUE;
1380                 }
1381                 CommandLineSwitchCase(arg, "workarea")
1382                 {
1383                         settings->Workarea = TRUE;
1384                 }
1385                 CommandLineSwitchCase(arg, "monitors")
1386                 {
1387                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1388                         {
1389                                 UINT32 i;
1390                                 char** p;
1391                                 int count = 0;
1392
1393                                 p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
1394
1395                                 if (count > 16)
1396                                         count = 16;
1397
1398                                 settings->NumMonitorIds = (UINT32) count;
1399
1400                                 for (i = 0; i < settings->NumMonitorIds; i++)
1401                                 {
1402                                         settings->MonitorIds[i] = atoi(p[i]);
1403                                 }
1404
1405                                 free(p);
1406                         }
1407                 }
1408                 CommandLineSwitchCase(arg, "monitor-list")
1409                 {
1410                         settings->ListMonitors = TRUE;
1411                 }
1412                 CommandLineSwitchCase(arg, "t")
1413                 {
1414                         settings->WindowTitle = _strdup(arg->Value);
1415                 }
1416                 CommandLineSwitchCase(arg, "decorations")
1417                 {
1418                         settings->Decorations = arg->Value ? TRUE : FALSE;
1419                 }
1420                 CommandLineSwitchCase(arg, "smart-sizing")
1421                 {
1422                         settings->SmartSizing = TRUE;
1423
1424                         if (arg->Value)
1425                         {
1426                                 str = _strdup(arg->Value);
1427                                 if ((p = strchr(str, 'x')))
1428                                 {
1429                                         *p = '\0';
1430                                         settings->SmartSizingWidth = atoi(str);
1431                                         settings->SmartSizingHeight = atoi(&p[1]);
1432                                 }
1433                                 free(str);
1434                         }
1435                 }
1436                 CommandLineSwitchCase(arg, "bpp")
1437                 {
1438                         settings->ColorDepth = atoi(arg->Value);
1439                 }
1440                 CommandLineSwitchCase(arg, "admin")
1441                 {
1442                         settings->ConsoleSession = TRUE;
1443                 }
1444                 CommandLineSwitchCase(arg, "restricted-admin")
1445                 {
1446                         settings->ConsoleSession = TRUE;
1447                         settings->RestrictedAdminModeRequired = TRUE;
1448                 }
1449                 CommandLineSwitchCase(arg, "pth")
1450                 {
1451                         settings->ConsoleSession = TRUE;
1452                         settings->RestrictedAdminModeRequired = TRUE;
1453                         settings->PasswordHash = _strdup(arg->Value);
1454                 }
1455                 CommandLineSwitchCase(arg, "client-hostname")
1456                 {
1457                         settings->ClientHostname = _strdup(arg->Value);
1458                 }
1459                 CommandLineSwitchCase(arg, "kbd")
1460                 {
1461                         unsigned long int id;
1462                         char* pEnd;
1463
1464                         id = strtoul(arg->Value, &pEnd, 16);
1465
1466                         if (pEnd != (arg->Value + strlen(arg->Value)))
1467                                 id = 0;
1468
1469                         if (id == 0)
1470                         {
1471                                 id = (unsigned long int) freerdp_map_keyboard_layout_name_to_id(arg->Value);
1472
1473                                 if (!id)
1474                                 {
1475                                         WLog_ERR(TAG, "Could not identify keyboard layout: %s", arg->Value);
1476                                 }
1477                         }
1478
1479                         settings->KeyboardLayout = (UINT32) id;
1480                 }
1481                 CommandLineSwitchCase(arg, "kbd-type")
1482                 {
1483                         settings->KeyboardType = atoi(arg->Value);
1484                 }
1485                 CommandLineSwitchCase(arg, "kbd-subtype")
1486                 {
1487                         settings->KeyboardSubType = atoi(arg->Value);
1488                 }
1489                 CommandLineSwitchCase(arg, "kbd-fn-key")
1490                 {
1491                         settings->KeyboardFunctionKey = atoi(arg->Value);
1492                 }
1493                 CommandLineSwitchCase(arg, "u")
1494                 {
1495                         user = _strdup(arg->Value);
1496                 }
1497                 CommandLineSwitchCase(arg, "d")
1498                 {
1499                         settings->Domain = _strdup(arg->Value);
1500                 }
1501                 CommandLineSwitchCase(arg, "p")
1502                 {
1503                         settings->Password = _strdup(arg->Value);
1504                 }
1505                 CommandLineSwitchCase(arg, "g")
1506                 {
1507                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1508                         {
1509                                 p = strchr(arg->Value, ':');
1510
1511                                 if (p)
1512                                 {
1513                                         length = (int) (p - arg->Value);
1514                                         settings->GatewayPort = atoi(&p[1]);
1515                                         settings->GatewayHostname = (char*) calloc(length + 1UL, sizeof(char));
1516                                         strncpy(settings->GatewayHostname, arg->Value, length);
1517                                         settings->GatewayHostname[length] = '\0';
1518                                 }
1519                                 else
1520                                 {
1521                                         settings->GatewayHostname = _strdup(arg->Value);
1522                                 }
1523                         }
1524                         else
1525                         {
1526                                 settings->GatewayHostname = _strdup(settings->ServerHostname);
1527                         }
1528
1529                         settings->GatewayEnabled = TRUE;
1530                         settings->GatewayUseSameCredentials = TRUE;
1531
1532                         freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DIRECT);
1533                 }
1534                 CommandLineSwitchCase(arg, "gu")
1535                 {
1536                         gwUser = _strdup(arg->Value);
1537                         settings->GatewayUseSameCredentials = FALSE;
1538                 }
1539                 CommandLineSwitchCase(arg, "gd")
1540                 {
1541                         settings->GatewayDomain = _strdup(arg->Value);
1542                         settings->GatewayUseSameCredentials = FALSE;
1543                 }
1544                 CommandLineSwitchCase(arg, "gp")
1545                 {
1546                         settings->GatewayPassword = _strdup(arg->Value);
1547                         settings->GatewayUseSameCredentials = FALSE;
1548                 }
1549                 CommandLineSwitchCase(arg, "gt")
1550                 {
1551                         if (_stricmp(arg->Value, "rpc") == 0)
1552                         {
1553                                 settings->GatewayRpcTransport = TRUE;
1554                                 settings->GatewayHttpTransport = FALSE;
1555                         }
1556                         else if (_stricmp(arg->Value, "http") == 0)
1557                         {
1558                                 settings->GatewayRpcTransport = FALSE;
1559                                 settings->GatewayHttpTransport = TRUE;
1560                         }
1561                         else if (_stricmp(arg->Value, "auto") == 0)
1562                         {
1563                                 settings->GatewayRpcTransport = TRUE;
1564                                 settings->GatewayHttpTransport = TRUE;
1565                         }
1566                 }
1567                 CommandLineSwitchCase(arg, "gateway-usage-method")
1568                 {
1569                         int type;
1570                         char* pEnd;
1571
1572                         type = strtol(arg->Value, &pEnd, 10);
1573
1574                         if (type == 0)
1575                         {
1576                                 if (_stricmp(arg->Value, "none") == 0)
1577                                         type = TSC_PROXY_MODE_NONE_DIRECT;
1578                                 else if (_stricmp(arg->Value, "direct") == 0)
1579                                         type = TSC_PROXY_MODE_DIRECT;
1580                                 else if (_stricmp(arg->Value, "detect") == 0)
1581                                         type = TSC_PROXY_MODE_DETECT;
1582                                 else if (_stricmp(arg->Value, "default") == 0)
1583                                         type = TSC_PROXY_MODE_DEFAULT;
1584                         }
1585
1586                         freerdp_set_gateway_usage_method(settings, (UINT32) type);
1587                 }
1588                 CommandLineSwitchCase(arg, "app")
1589                 {
1590                         settings->RemoteApplicationProgram = _strdup(arg->Value);
1591
1592                         settings->RemoteApplicationMode = TRUE;
1593                         settings->RemoteAppLanguageBarSupported = TRUE;
1594                         settings->Workarea = TRUE;
1595                         settings->DisableWallpaper = TRUE;
1596                         settings->DisableFullWindowDrag = TRUE;
1597                 }
1598                 CommandLineSwitchCase(arg, "load-balance-info")
1599                 {
1600                         settings->LoadBalanceInfo = (BYTE*) _strdup(arg->Value);
1601                         settings->LoadBalanceInfoLength = (UINT32) strlen((char*) settings->LoadBalanceInfo);
1602                 }
1603                 CommandLineSwitchCase(arg, "app-name")
1604                 {
1605                         settings->RemoteApplicationName = _strdup(arg->Value);
1606                 }
1607                 CommandLineSwitchCase(arg, "app-icon")
1608                 {
1609                         settings->RemoteApplicationIcon = _strdup(arg->Value);
1610                 }
1611                 CommandLineSwitchCase(arg, "app-cmd")
1612                 {
1613                         settings->RemoteApplicationCmdLine = _strdup(arg->Value);
1614                 }
1615                 CommandLineSwitchCase(arg, "app-file")
1616                 {
1617                         settings->RemoteApplicationFile = _strdup(arg->Value);
1618                 }
1619                 CommandLineSwitchCase(arg, "app-guid")
1620                 {
1621                         settings->RemoteApplicationGuid = _strdup(arg->Value);
1622                 }
1623                 CommandLineSwitchCase(arg, "compression")
1624                 {
1625                         settings->CompressionEnabled = arg->Value ? TRUE : FALSE;
1626                 }
1627                 CommandLineSwitchCase(arg, "compression-level")
1628                 {
1629                         settings->CompressionLevel = atoi(arg->Value);
1630                 }
1631                 CommandLineSwitchCase(arg, "drives")
1632                 {
1633                         settings->RedirectDrives = arg->Value ? TRUE : FALSE;
1634                 }
1635                 CommandLineSwitchCase(arg, "home-drive")
1636                 {
1637                         settings->RedirectHomeDrive = arg->Value ? TRUE : FALSE;
1638                 }
1639                 CommandLineSwitchCase(arg, "clipboard")
1640                 {
1641                         settings->RedirectClipboard = arg->Value ? TRUE : FALSE;
1642                 }
1643                 CommandLineSwitchCase(arg, "shell")
1644                 {
1645                         settings->AlternateShell = _strdup(arg->Value);
1646                 }
1647                 CommandLineSwitchCase(arg, "shell-dir")
1648                 {
1649                         settings->ShellWorkingDirectory = _strdup(arg->Value);
1650                 }
1651                 CommandLineSwitchCase(arg, "audio-mode")
1652                 {
1653                         int mode;
1654
1655                         mode = atoi(arg->Value);
1656
1657                         if (mode == AUDIO_MODE_REDIRECT)
1658                         {
1659                                 settings->AudioPlayback = TRUE;
1660                         }
1661                         else if (mode == AUDIO_MODE_PLAY_ON_SERVER)
1662                         {
1663                                 settings->RemoteConsoleAudio = TRUE;
1664                         }
1665                         else if (mode == AUDIO_MODE_NONE)
1666                         {
1667                                 settings->AudioPlayback = FALSE;
1668                                 settings->RemoteConsoleAudio = FALSE;
1669                         }
1670                 }
1671                 CommandLineSwitchCase(arg, "network")
1672                 {
1673                         int type;
1674                         char* pEnd;
1675
1676                         type = strtol(arg->Value, &pEnd, 10);
1677
1678                         if (type == 0)
1679                         {
1680                                 if (_stricmp(arg->Value, "modem") == 0)
1681                                         type = CONNECTION_TYPE_MODEM;
1682                                 else if (_stricmp(arg->Value, "broadband") == 0)
1683                                         type = CONNECTION_TYPE_BROADBAND_HIGH;
1684                                 else if (_stricmp(arg->Value, "broadband-low") == 0)
1685                                         type = CONNECTION_TYPE_BROADBAND_LOW;
1686                                 else if (_stricmp(arg->Value, "broadband-high") == 0)
1687                                         type = CONNECTION_TYPE_BROADBAND_HIGH;
1688                                 else if (_stricmp(arg->Value, "wan") == 0)
1689                                         type = CONNECTION_TYPE_WAN;
1690                                 else if (_stricmp(arg->Value, "lan") == 0)
1691                                         type = CONNECTION_TYPE_LAN;
1692                                 else if ((_stricmp(arg->Value, "autodetect") == 0) ||
1693                                                 (_stricmp(arg->Value, "auto") == 0) ||
1694                                                 (_stricmp(arg->Value, "detect") == 0))
1695                                 {
1696                                         type = CONNECTION_TYPE_AUTODETECT;
1697                                 }
1698                         }
1699
1700                         freerdp_set_connection_type(settings, type);
1701                 }
1702                 CommandLineSwitchCase(arg, "fonts")
1703                 {
1704                         settings->AllowFontSmoothing = arg->Value ? TRUE : FALSE;
1705                 }
1706                 CommandLineSwitchCase(arg, "wallpaper")
1707                 {
1708                         settings->DisableWallpaper = arg->Value ? FALSE : TRUE;
1709                 }
1710                 CommandLineSwitchCase(arg, "window-drag")
1711                 {
1712                         settings->DisableFullWindowDrag = arg->Value ? FALSE : TRUE;
1713                 }
1714                 CommandLineSwitchCase(arg, "menu-anims")
1715                 {
1716                         settings->DisableMenuAnims = arg->Value ? FALSE : TRUE;
1717                 }
1718                 CommandLineSwitchCase(arg, "themes")
1719                 {
1720                         settings->DisableThemes = arg->Value ? FALSE : TRUE;
1721                 }
1722                 CommandLineSwitchCase(arg, "aero")
1723                 {
1724                         settings->AllowDesktopComposition = arg->Value ? TRUE : FALSE;
1725                 }
1726                 CommandLineSwitchCase(arg, "gdi")
1727                 {
1728                         if (_stricmp(arg->Value, "sw") == 0)
1729                                 settings->SoftwareGdi = TRUE;
1730                         else if (_stricmp(arg->Value, "hw") == 0)
1731                                 settings->SoftwareGdi = FALSE;
1732                 }
1733                 CommandLineSwitchCase(arg, "gfx")
1734                 {
1735                         settings->SupportGraphicsPipeline = TRUE;
1736                 }
1737                 CommandLineSwitchCase(arg, "gfx-thin-client")
1738                 {
1739                         settings->GfxThinClient = arg->Value ? TRUE : FALSE;
1740                         settings->SupportGraphicsPipeline = TRUE;
1741                 }
1742                 CommandLineSwitchCase(arg, "gfx-small-cache")
1743                 {
1744                         settings->GfxSmallCache = arg->Value ? TRUE : FALSE;
1745                         settings->SupportGraphicsPipeline = TRUE;
1746                 }
1747                 CommandLineSwitchCase(arg, "gfx-progressive")
1748                 {
1749                         settings->GfxProgressive = arg->Value ? TRUE : FALSE;
1750                         settings->GfxThinClient = settings->GfxProgressive ? FALSE : TRUE;
1751                         settings->SupportGraphicsPipeline = TRUE;
1752                 }
1753                 CommandLineSwitchCase(arg, "gfx-h264")
1754                 {
1755                         settings->GfxH264 = arg->Value ? TRUE : FALSE;
1756                         settings->SupportGraphicsPipeline = TRUE;
1757                 }
1758                 CommandLineSwitchCase(arg, "rfx")
1759                 {
1760                         settings->RemoteFxCodec = TRUE;
1761                         settings->FastPathOutput = TRUE;
1762                         settings->ColorDepth = 32;
1763                         settings->LargePointerFlag = TRUE;
1764                         settings->FrameMarkerCommandEnabled = TRUE;
1765                 }
1766                 CommandLineSwitchCase(arg, "rfx-mode")
1767                 {
1768                         if (strcmp(arg->Value, "video") == 0)
1769                                 settings->RemoteFxCodecMode = 0x00;
1770                         else if (strcmp(arg->Value, "image") == 0)
1771                                 settings->RemoteFxCodecMode = 0x02;
1772                 }
1773                 CommandLineSwitchCase(arg, "frame-ack")
1774                 {
1775                         settings->FrameAcknowledge = atoi(arg->Value);
1776                 }
1777                 CommandLineSwitchCase(arg, "nsc")
1778                 {
1779                         settings->NSCodec = TRUE;
1780                         settings->FastPathOutput = TRUE;
1781                         settings->ColorDepth = 32;
1782                         settings->LargePointerFlag = TRUE;
1783                         settings->FrameMarkerCommandEnabled = TRUE;
1784                 }
1785                 CommandLineSwitchCase(arg, "jpeg")
1786                 {
1787                         settings->JpegCodec = TRUE;
1788                         settings->JpegQuality = 75;
1789                 }
1790                 CommandLineSwitchCase(arg, "jpeg-quality")
1791                 {
1792                         settings->JpegQuality = atoi(arg->Value) % 100;
1793                 }
1794                 CommandLineSwitchCase(arg, "nego")
1795                 {
1796                         settings->NegotiateSecurityLayer = arg->Value ? TRUE : FALSE;
1797                 }
1798                 CommandLineSwitchCase(arg, "pcb")
1799                 {
1800                         settings->SendPreconnectionPdu = TRUE;
1801                         settings->PreconnectionBlob = _strdup(arg->Value);
1802                 }
1803                 CommandLineSwitchCase(arg, "pcid")
1804                 {
1805                         settings->SendPreconnectionPdu = TRUE;
1806                         settings->PreconnectionId = atoi(arg->Value);
1807                 }
1808                 CommandLineSwitchCase(arg, "sec")
1809                 {
1810                         if (strcmp("rdp", arg->Value) == 0) /* Standard RDP */
1811                         {
1812                                 settings->RdpSecurity = TRUE;
1813                                 settings->TlsSecurity = FALSE;
1814                                 settings->NlaSecurity = FALSE;
1815                                 settings->ExtSecurity = FALSE;
1816                                 settings->UseRdpSecurityLayer = TRUE;
1817                         }
1818                         else if (strcmp("tls", arg->Value) == 0) /* TLS */
1819                         {
1820                                 settings->RdpSecurity = FALSE;
1821                                 settings->TlsSecurity = TRUE;
1822                                 settings->NlaSecurity = FALSE;
1823                                 settings->ExtSecurity = FALSE;
1824                         }
1825                         else if (strcmp("nla", arg->Value) == 0) /* NLA */
1826                         {
1827                                 settings->RdpSecurity = FALSE;
1828                                 settings->TlsSecurity = FALSE;
1829                                 settings->NlaSecurity = TRUE;
1830                                 settings->ExtSecurity = FALSE;
1831                         }
1832                         else if (strcmp("ext", arg->Value) == 0) /* NLA Extended */
1833                         {
1834                                 settings->RdpSecurity = FALSE;
1835                                 settings->TlsSecurity = FALSE;
1836                                 settings->NlaSecurity = FALSE;
1837                                 settings->ExtSecurity = TRUE;
1838                         }
1839                         else
1840                         {
1841                                 WLog_ERR(TAG, "unknown protocol security: %s", arg->Value);
1842                         }
1843                 }
1844                 CommandLineSwitchCase(arg, "encryption-methods")
1845                 {
1846                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1847                         {
1848                                 UINT32 i;
1849                                 char** p;
1850                                 int count = 0;
1851
1852                                 p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
1853
1854                                 for (i = 0; i < count; i++)
1855                                 {
1856                                         if (!strcmp(p[i], "40"))
1857                                                 settings->EncryptionMethods |= ENCRYPTION_METHOD_40BIT;
1858                                         else if (!strcmp(p[i], "56"))
1859                                                 settings->EncryptionMethods |= ENCRYPTION_METHOD_56BIT;
1860                                         else if (!strcmp(p[i], "128"))
1861                                                 settings->EncryptionMethods |= ENCRYPTION_METHOD_128BIT;
1862                                         else if (!strcmp(p[i], "FIPS"))
1863                                                 settings->EncryptionMethods |= ENCRYPTION_METHOD_FIPS;
1864                                         else
1865                                                 WLog_ERR(TAG, "unknown encryption method '%s'", p[i]);
1866                                 }
1867
1868                                 free(p);
1869                         }
1870                 }
1871                 CommandLineSwitchCase(arg, "sec-rdp")
1872                 {
1873                         settings->RdpSecurity = arg->Value ? TRUE : FALSE;
1874                 }
1875                 CommandLineSwitchCase(arg, "sec-tls")
1876                 {
1877                         settings->TlsSecurity = arg->Value ? TRUE : FALSE;
1878                 }
1879                 CommandLineSwitchCase(arg, "sec-nla")
1880                 {
1881                         settings->NlaSecurity = arg->Value ? TRUE : FALSE;
1882                 }
1883                 CommandLineSwitchCase(arg, "sec-ext")
1884                 {
1885                         settings->ExtSecurity = arg->Value ? TRUE : FALSE;
1886                 }
1887                 CommandLineSwitchCase(arg, "tls-ciphers")
1888                 {
1889                         if (strcmp(arg->Value, "netmon") == 0)
1890                         {
1891                                 settings->AllowedTlsCiphers = _strdup("ALL:!ECDH");
1892                         }
1893                         else if (strcmp(arg->Value, "ma") == 0)
1894                         {
1895                                 settings->AllowedTlsCiphers = _strdup("AES128-SHA");
1896                         }
1897                         else
1898                         {
1899                                 settings->AllowedTlsCiphers = _strdup(arg->Value);
1900                         }
1901                 }
1902                 CommandLineSwitchCase(arg, "cert-name")
1903                 {
1904                         settings->CertificateName = _strdup(arg->Value);
1905                 }
1906                 CommandLineSwitchCase(arg, "cert-ignore")
1907                 {
1908                         settings->IgnoreCertificate = TRUE;
1909                 }
1910                 CommandLineSwitchCase(arg, "authentication")
1911                 {
1912                         settings->Authentication = arg->Value ? TRUE : FALSE;
1913                 }
1914                 CommandLineSwitchCase(arg, "encryption")
1915                 {
1916                         settings->UseRdpSecurityLayer = arg->Value ? FALSE : TRUE;
1917                 }
1918                 CommandLineSwitchCase(arg, "grab-keyboard")
1919                 {
1920                         settings->GrabKeyboard = arg->Value ? TRUE : FALSE;
1921                 }
1922                 CommandLineSwitchCase(arg, "toggle-fullscreen")
1923                 {
1924                         settings->ToggleFullscreen = arg->Value ? TRUE : FALSE;
1925                 }
1926                 CommandLineSwitchCase(arg, "mouse-motion")
1927                 {
1928                         settings->MouseMotion = arg->Value ? TRUE : FALSE;
1929                 }
1930                 CommandLineSwitchCase(arg, "parent-window")
1931                 {
1932                         settings->ParentWindowId = strtol(arg->Value, NULL, 0);
1933                 }
1934                 CommandLineSwitchCase(arg, "bitmap-cache")
1935                 {
1936                         settings->BitmapCacheEnabled = arg->Value ? TRUE : FALSE;
1937                 }
1938                 CommandLineSwitchCase(arg, "offscreen-cache")
1939                 {
1940                         settings->OffscreenSupportLevel = arg->Value ? TRUE : FALSE;
1941                 }
1942                 CommandLineSwitchCase(arg, "glyph-cache")
1943                 {
1944                         settings->GlyphSupportLevel = arg->Value ? GLYPH_SUPPORT_FULL : GLYPH_SUPPORT_NONE;
1945                 }
1946                 CommandLineSwitchCase(arg, "codec-cache")
1947                 {
1948                         settings->BitmapCacheV3Enabled = TRUE;
1949
1950                         if (strcmp(arg->Value, "rfx") == 0)
1951                         {
1952                                 settings->RemoteFxCodec = TRUE;
1953                         }
1954                         else if (strcmp(arg->Value, "nsc") == 0)
1955                         {
1956                                 settings->NSCodec = TRUE;
1957                         }
1958                         else if (strcmp(arg->Value, "jpeg") == 0)
1959                         {
1960                                 settings->JpegCodec = TRUE;
1961
1962                                 if (settings->JpegQuality == 0)
1963                                         settings->JpegQuality = 75;
1964                         }
1965                 }
1966                 CommandLineSwitchCase(arg, "fast-path")
1967                 {
1968                         settings->FastPathInput = arg->Value ? TRUE : FALSE;
1969                         settings->FastPathOutput = arg->Value ? TRUE : FALSE;
1970                 }
1971                 CommandLineSwitchCase(arg, "max-fast-path-size")
1972                 {
1973                         settings->MultifragMaxRequestSize = atoi(arg->Value);
1974                 }
1975                 CommandLineSwitchCase(arg, "async-input")
1976                 {
1977                         settings->AsyncInput = arg->Value ? TRUE : FALSE;
1978                 }
1979                 CommandLineSwitchCase(arg, "async-update")
1980                 {
1981                         settings->AsyncUpdate = arg->Value ? TRUE : FALSE;
1982                 }
1983                 CommandLineSwitchCase(arg, "async-channels")
1984                 {
1985                         settings->AsyncChannels = arg->Value ? TRUE : FALSE;
1986                 }
1987                 CommandLineSwitchCase(arg, "async-transport")
1988                 {
1989                         settings->AsyncTransport = arg->Value ? TRUE : FALSE;
1990                 }
1991                 CommandLineSwitchCase(arg, "wm-class")
1992                 {
1993                         settings->WmClass = _strdup(arg->Value);
1994                 }
1995                 CommandLineSwitchCase(arg, "play-rfx")
1996                 {
1997                         settings->PlayRemoteFxFile = _strdup(arg->Value);
1998                         settings->PlayRemoteFx = TRUE;
1999                 }
2000                 CommandLineSwitchCase(arg, "auth-only")
2001                 {
2002                         settings->AuthenticationOnly = arg->Value ? TRUE : FALSE;
2003                 }
2004                 CommandLineSwitchCase(arg, "auto-reconnect")
2005                 {
2006                         settings->AutoReconnectionEnabled = arg->Value ? TRUE : FALSE;
2007                 }
2008                 CommandLineSwitchCase(arg, "reconnect-cookie")
2009                 {
2010                         BYTE *base64;
2011                         int length;
2012                         crypto_base64_decode((const char *) (arg->Value), (int) strlen(arg->Value),
2013                                                                 &base64, &length);
2014                         if ((base64 != NULL) && (length == sizeof(ARC_SC_PRIVATE_PACKET)))
2015                         {
2016                                 memcpy(settings->ServerAutoReconnectCookie, base64, length);
2017                                 free(base64);
2018                         }
2019                         else
2020                         {
2021                                 WLog_ERR(TAG, "reconnect-cookie:  invalid base64 '%s'", arg->Value);
2022                         }
2023                 }
2024                 CommandLineSwitchCase(arg, "print-reconnect-cookie")
2025                 {
2026                         settings->PrintReconnectCookie = arg->Value ? TRUE : FALSE;
2027                 }
2028                 CommandLineSwitchCase(arg, "assistance")
2029                 {
2030                         settings->RemoteAssistanceMode = TRUE;
2031                         settings->RemoteAssistancePassword = _strdup(arg->Value);
2032                 }
2033                 CommandLineSwitchDefault(arg)
2034                 {
2035                 }
2036
2037                 CommandLineSwitchEnd(arg)
2038         }
2039         while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
2040
2041         if (!settings->Domain && user)
2042         {
2043                 freerdp_parse_username(user, &settings->Username, &settings->Domain);
2044                 free(user);
2045         }
2046
2047         if (!settings->GatewayDomain && gwUser)
2048         {
2049                 freerdp_parse_username(gwUser, &settings->GatewayUsername,
2050                                  &settings->GatewayDomain);
2051                 free(gwUser);
2052         }
2053
2054         freerdp_performance_flags_make(settings);
2055
2056         if (settings->SupportGraphicsPipeline)
2057         {
2058                 settings->FastPathOutput = TRUE;
2059                 settings->ColorDepth = 32;
2060                 settings->LargePointerFlag = TRUE;
2061                 settings->FrameMarkerCommandEnabled = TRUE;
2062         }
2063
2064         arg = CommandLineFindArgumentA(args, "port");
2065
2066         if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
2067         {
2068                 settings->ServerPort = atoi(arg->Value);
2069         }
2070
2071         arg = CommandLineFindArgumentA(args, "p");
2072
2073         if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
2074         {
2075                 FillMemory(arg->Value, strlen(arg->Value), '*');
2076         }
2077
2078         arg = CommandLineFindArgumentA(args, "gp");
2079
2080         if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
2081         {
2082                 FillMemory(arg->Value, strlen(arg->Value), '*');
2083         }
2084
2085         return status;
2086 }
2087
2088 int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings* settings, char* name, void* data)
2089 {
2090         void* entry;
2091
2092         entry = freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
2093
2094         if (entry)
2095         {
2096                 if (freerdp_channels_client_load(channels, settings, entry, data) == 0)
2097                 {
2098                         WLog_INFO(TAG, "loading channel %s", name);
2099                         return 0;
2100                 }
2101         }
2102
2103         return -1;
2104 }
2105
2106 int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
2107 {
2108         UINT32 index;
2109         ADDIN_ARGV* args;
2110
2111         if ((freerdp_static_channel_collection_find(settings, "rdpsnd")) ||
2112                         (freerdp_dynamic_channel_collection_find(settings, "tsmf")))
2113         {
2114                 settings->DeviceRedirection = TRUE; /* rdpsnd requires rdpdr to be registered */
2115                 settings->AudioPlayback = TRUE; /* Both rdpsnd and tsmf require this flag to be set */
2116         }
2117
2118         if (freerdp_dynamic_channel_collection_find(settings, "audin"))
2119         {
2120                 settings->AudioCapture = TRUE;
2121         }
2122
2123         if (settings->NetworkAutoDetect ||
2124                 settings->SupportHeartbeatPdu ||
2125                 settings->SupportMultitransport)
2126         {
2127                 settings->DeviceRedirection = TRUE; /* these RDP8 features require rdpdr to be registered */
2128         }
2129
2130         if (settings->RedirectDrives || settings->RedirectHomeDrive || settings->RedirectSerialPorts
2131                         || settings->RedirectSmartCards || settings->RedirectPrinters)
2132         {
2133                 settings->DeviceRedirection = TRUE; /* All of these features require rdpdr */
2134         }
2135
2136         if (settings->RedirectDrives)
2137         {
2138                 if (!freerdp_device_collection_find(settings, "drive"))
2139                 {
2140                         char* params[3];
2141
2142                         params[0] = "drive";
2143                         params[1] = "media";
2144                         params[2] = "*";
2145
2146                         freerdp_client_add_device_channel(settings, 3, (char**) params);
2147                 }
2148         }
2149
2150         if (settings->RedirectHomeDrive)
2151         {
2152                 if (!freerdp_device_collection_find(settings, "drive"))
2153                 {
2154                         char* params[3];
2155
2156                         params[0] = "drive";
2157                         params[1] = "home";
2158                         params[2] = "%";
2159
2160                         freerdp_client_add_device_channel(settings, 3, (char**) params);
2161                 }
2162         }
2163
2164         if (settings->DeviceRedirection)
2165         {
2166                 freerdp_client_load_static_channel_addin(channels, settings, "rdpdr", settings);
2167
2168                 if (!freerdp_static_channel_collection_find(settings, "rdpsnd"))
2169                 {
2170                         char* params[2];
2171
2172                         params[0] = "rdpsnd";
2173                         params[1] = "sys:fake";
2174
2175                         freerdp_client_add_static_channel(settings, 2, (char**) params);
2176                 }
2177         }
2178
2179         if (settings->RedirectSmartCards)
2180         {
2181                 RDPDR_SMARTCARD* smartcard;
2182
2183                 smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD));
2184
2185                 if (!smartcard)
2186                         return -1;
2187
2188                 smartcard->Type = RDPDR_DTYP_SMARTCARD;
2189                 freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard);
2190         }
2191
2192         if (settings->RedirectPrinters)
2193         {
2194                 RDPDR_PRINTER* printer;
2195
2196                 printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER));
2197
2198                 if (!printer)
2199                         return -1;
2200
2201                 printer->Type = RDPDR_DTYP_PRINT;
2202                 freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer);
2203         }
2204
2205         if (settings->RedirectClipboard)
2206         {
2207                 if (!freerdp_static_channel_collection_find(settings, "cliprdr"))
2208                 {
2209                         char* params[1];
2210
2211                         params[0] = "cliprdr";
2212
2213                         freerdp_client_add_static_channel(settings, 1, (char**) params);
2214                 }
2215         }
2216
2217         if (settings->LyncRdpMode)
2218         {
2219                 settings->EncomspVirtualChannel = TRUE;
2220                 settings->RemdeskVirtualChannel = TRUE;
2221                 settings->CompressionEnabled = FALSE;
2222         }
2223
2224         if (settings->RemoteAssistanceMode)
2225         {
2226                 settings->EncomspVirtualChannel = TRUE;
2227                 settings->RemdeskVirtualChannel = TRUE;
2228         }
2229
2230         if (settings->EncomspVirtualChannel)
2231                 freerdp_client_load_static_channel_addin(channels, settings, "encomsp", settings);
2232
2233         if (settings->RemdeskVirtualChannel)
2234                 freerdp_client_load_static_channel_addin(channels, settings, "remdesk", settings);
2235
2236         for (index = 0; index < settings->StaticChannelCount; index++)
2237         {
2238                 args = settings->StaticChannelArray[index];
2239                 freerdp_client_load_static_channel_addin(channels, settings, args->argv[0], args);
2240         }
2241
2242         if (settings->RemoteApplicationMode)
2243         {
2244                 freerdp_client_load_static_channel_addin(channels, settings, "rail", settings);
2245         }
2246
2247         if (settings->MultiTouchInput)
2248         {
2249                 char* p[1];
2250                 int count;
2251
2252                 count = 1;
2253                 p[0] = "rdpei";
2254
2255                 freerdp_client_add_dynamic_channel(settings, count, p);
2256         }
2257
2258         if (settings->SupportGraphicsPipeline)
2259         {
2260                 char* p[1];
2261                 int count;
2262
2263                 count = 1;
2264                 p[0] = "rdpgfx";
2265
2266                 freerdp_client_add_dynamic_channel(settings, count, p);
2267         }
2268
2269         if (settings->SupportEchoChannel)
2270         {
2271                 char* p[1];
2272                 int count;
2273
2274                 count = 1;
2275                 p[0] = "echo";
2276
2277                 freerdp_client_add_dynamic_channel(settings, count, p);
2278         }
2279
2280         if (settings->SupportDisplayControl)
2281         {
2282                 char* p[1];
2283                 int count;
2284
2285                 count = 1;
2286                 p[0] = "disp";
2287
2288                 freerdp_client_add_dynamic_channel(settings, count, p);
2289         }
2290
2291         if (settings->DynamicChannelCount)
2292                 settings->SupportDynamicChannels = TRUE;
2293
2294         if (settings->SupportDynamicChannels)
2295         {
2296                 freerdp_client_load_static_channel_addin(channels, settings, "drdynvc", settings);
2297         }
2298
2299         return 1;
2300 }