UPN syntax fix: domain must be empty, not NULL.
[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         p = strrchr(username, '@');
803
804         *user = NULL;
805         *domain = NULL;
806
807         if (p)
808         {
809                 length = (int) (p - username);
810                 *user = _strdup(&p[1]);
811                 if (!*user)
812                         return -1;
813
814                 *domain = (char*) calloc(length + 1UL, sizeof(char));
815                 if (!*domain)
816                 {
817                         free (*user);
818                         *user = NULL;
819                         return -1;
820                 }
821
822                 strncpy(*domain, username, length);
823                 (*domain)[length] = '\0';
824         }
825         else if (username)
826         {
827                 /* Do not break up the name for '@'; both credSSP and the
828                  * ClientInfo PDU expect 'user@corp.net' to be transmitted
829                  * as username 'user@corp.net', domain empty (not NULL!).
830                  */
831                 *user = _strdup(username);
832                 if (!*user)
833                         return -1;
834
835                 /* If only username is given, prefix that with 'TARGET'
836                  * otherwise set the domain to an empty string.
837                  * NOTE: Domain NULL will result in undefined behavior.
838                  */
839                 if (!u)
840                         *domain = _strdup("TARGET");
841                 else
842                         *domain = _strdup("\0");
843
844                 if (!*domain)
845                 {
846                         free(*user);
847                         *user = NULL;
848                         return -1;
849                 }
850         }
851         else
852                         return -1;
853
854         return 0;
855 }
856
857 int freerdp_parse_hostname(char* hostname, char** host, int* port)
858 {
859         char* p;
860         int length;
861
862         p = strrchr(hostname, ':');
863
864         if (p)
865         {
866                 length = (p - hostname);
867                 *host = (char*) calloc(length + 1UL, sizeof(char));
868
869                 if (!(*host))
870                         return -1;
871
872                 CopyMemory(*host, hostname, length);
873                 (*host)[length] = '\0';
874                 *port = atoi(p + 1);
875         }
876         else
877         {
878                 *host = _strdup(hostname);
879
880                 if (!(*host))
881                         return -1;
882
883                 *port = -1;
884         }
885
886         return 0;
887 }
888
889 int freerdp_set_connection_type(rdpSettings* settings, int type)
890 {
891         settings->ConnectionType = type;
892
893         if (type == CONNECTION_TYPE_MODEM)
894         {
895                 settings->DisableWallpaper = TRUE;
896                 settings->AllowFontSmoothing = FALSE;
897                 settings->AllowDesktopComposition = FALSE;
898                 settings->DisableFullWindowDrag = TRUE;
899                 settings->DisableMenuAnims = TRUE;
900                 settings->DisableThemes = TRUE;
901         }
902         else if (type == CONNECTION_TYPE_BROADBAND_LOW)
903         {
904                 settings->DisableWallpaper = TRUE;
905                 settings->AllowFontSmoothing = FALSE;
906                 settings->AllowDesktopComposition = FALSE;
907                 settings->DisableFullWindowDrag = TRUE;
908                 settings->DisableMenuAnims = TRUE;
909                 settings->DisableThemes = FALSE;
910         }
911         else if (type == CONNECTION_TYPE_SATELLITE)
912         {
913                 settings->DisableWallpaper = TRUE;
914                 settings->AllowFontSmoothing = FALSE;
915                 settings->AllowDesktopComposition = TRUE;
916                 settings->DisableFullWindowDrag = TRUE;
917                 settings->DisableMenuAnims = TRUE;
918                 settings->DisableThemes = FALSE;
919         }
920         else if (type == CONNECTION_TYPE_BROADBAND_HIGH)
921         {
922                 settings->DisableWallpaper = TRUE;
923                 settings->AllowFontSmoothing = FALSE;
924                 settings->AllowDesktopComposition = TRUE;
925                 settings->DisableFullWindowDrag = TRUE;
926                 settings->DisableMenuAnims = TRUE;
927                 settings->DisableThemes = FALSE;
928         }
929         else if (type == CONNECTION_TYPE_WAN)
930         {
931                 settings->DisableWallpaper = FALSE;
932                 settings->AllowFontSmoothing = TRUE;
933                 settings->AllowDesktopComposition = TRUE;
934                 settings->DisableFullWindowDrag = FALSE;
935                 settings->DisableMenuAnims = FALSE;
936                 settings->DisableThemes = FALSE;
937         }
938         else if (type == CONNECTION_TYPE_LAN)
939         {
940                 settings->DisableWallpaper = FALSE;
941                 settings->AllowFontSmoothing = TRUE;
942                 settings->AllowDesktopComposition = TRUE;
943                 settings->DisableFullWindowDrag = FALSE;
944                 settings->DisableMenuAnims = FALSE;
945                 settings->DisableThemes = FALSE;
946         }
947         else if (type == CONNECTION_TYPE_AUTODETECT)
948         {
949                 settings->DisableWallpaper = FALSE;
950                 settings->AllowFontSmoothing = TRUE;
951                 settings->AllowDesktopComposition = TRUE;
952                 settings->DisableFullWindowDrag = FALSE;
953                 settings->DisableMenuAnims = FALSE;
954                 settings->DisableThemes = FALSE;
955
956                 settings->NetworkAutoDetect = TRUE;
957         }
958
959         return 0;
960 }
961
962 int freerdp_map_keyboard_layout_name_to_id(char* name)
963 {
964         int i;
965         int id = 0;
966         RDP_KEYBOARD_LAYOUT* layouts;
967
968         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD);
969
970         for (i = 0; layouts[i].code; i++)
971         {
972                 if (_stricmp(layouts[i].name, name) == 0)
973                         id = layouts[i].code;
974         }
975
976         free(layouts);
977
978         if (id)
979                 return id;
980
981         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT);
982
983         for (i = 0; layouts[i].code; i++)
984         {
985                 if (_stricmp(layouts[i].name, name) == 0)
986                         id = layouts[i].code;
987         }
988
989         free(layouts);
990
991         if (id)
992                 return id;
993
994         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_IME);
995
996         for (i = 0; layouts[i].code; i++)
997         {
998                 if (_stricmp(layouts[i].name, name) == 0)
999                         id = layouts[i].code;
1000         }
1001
1002         free(layouts);
1003
1004         if (id)
1005                 return id;
1006
1007         return 0;
1008 }
1009
1010 int freerdp_detect_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv)
1011 {
1012         int length;
1013
1014         if (index == 1)
1015         {
1016                 length = (int) strlen(argv[index]);
1017
1018                 if (length > 4)
1019                 {
1020                         if (_stricmp(&(argv[index])[length - 4], ".rdp") == 0)
1021                         {
1022                                 return 1;
1023                         }
1024                 }
1025
1026                 if (length > 13)
1027                 {
1028                         if (_stricmp(&(argv[index])[length - 13], ".msrcIncident") == 0)
1029                         {
1030                                 return 1;
1031                         }
1032                 }
1033         }
1034
1035         return 0;
1036 }
1037
1038 int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv,
1039         int* count, BOOL ignoreUnknown)
1040 {
1041         int status;
1042         DWORD flags;
1043         int detect_status;
1044         COMMAND_LINE_ARGUMENT_A* arg;
1045
1046         flags = COMMAND_LINE_SEPARATOR_COLON;
1047         flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
1048
1049         if (ignoreUnknown)
1050         {
1051                 flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
1052         }
1053
1054         *count = 0;
1055         detect_status = 0;
1056         CommandLineClearArgumentsA(args);
1057
1058         status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags,
1059                         NULL, freerdp_detect_command_line_pre_filter, NULL);
1060
1061         if (status < 0)
1062                 return status;
1063
1064         arg = args;
1065
1066         do
1067         {
1068                 if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
1069                         continue;
1070
1071                 (*count)++;
1072         }
1073         while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
1074
1075         if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
1076                 detect_status = -1;
1077
1078         return detect_status;
1079 }
1080
1081 int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv,
1082         int* count, BOOL ignoreUnknown)
1083 {
1084         int status;
1085         DWORD flags;
1086         int detect_status;
1087         COMMAND_LINE_ARGUMENT_A* arg;
1088
1089         flags = COMMAND_LINE_SEPARATOR_SPACE;
1090         flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
1091         flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
1092
1093         if (ignoreUnknown)
1094         {
1095                 flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
1096         }
1097
1098         *count = 0;
1099         detect_status = 0;
1100         CommandLineClearArgumentsA(args);
1101
1102         status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags,
1103                         NULL, freerdp_detect_command_line_pre_filter, NULL);
1104
1105         if (status < 0)
1106                 return status;
1107
1108         arg = args;
1109
1110         do
1111         {
1112                 if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
1113                         continue;
1114
1115                 (*count)++;
1116         }
1117         while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
1118
1119         if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
1120                 detect_status = -1;
1121
1122         return detect_status;
1123 }
1124
1125 static BOOL freerdp_client_detect_command_line(int argc, char** argv,
1126         DWORD* flags, BOOL ignoreUnknown)
1127 {
1128         int old_cli_status;
1129         int old_cli_count;
1130         int posix_cli_status;
1131         int posix_cli_count;
1132         int windows_cli_status;
1133         int windows_cli_count;
1134         BOOL compatibility = FALSE;
1135
1136         windows_cli_status = freerdp_detect_windows_style_command_line_syntax(argc, argv, &windows_cli_count, ignoreUnknown);
1137         posix_cli_status = freerdp_detect_posix_style_command_line_syntax(argc, argv, &posix_cli_count, ignoreUnknown);
1138         old_cli_status = freerdp_detect_old_command_line_syntax(argc, argv, &old_cli_count);
1139
1140         /* Default is POSIX syntax */
1141         *flags = COMMAND_LINE_SEPARATOR_SPACE;
1142         *flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
1143         *flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
1144
1145         if (posix_cli_status <= COMMAND_LINE_STATUS_PRINT)
1146                 return compatibility;
1147
1148         /* Check, if this may be windows style syntax... */
1149         if ((windows_cli_count && (windows_cli_count >= posix_cli_count)) || (windows_cli_status <= COMMAND_LINE_STATUS_PRINT))
1150         {
1151                 windows_cli_count = 1;
1152                 *flags = COMMAND_LINE_SEPARATOR_COLON;
1153                 *flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
1154         }
1155         else if (old_cli_status >= 0)
1156         {
1157                 /* Ignore legacy parsing in case there is an error in the command line. */
1158
1159                 if ((old_cli_status == 1) || ((old_cli_count > posix_cli_count) && (old_cli_status != -1)))
1160                 {
1161                         *flags = COMMAND_LINE_SEPARATOR_SPACE;
1162                         *flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
1163
1164                         compatibility = TRUE;
1165                 }
1166         }
1167
1168         WLog_DBG(TAG, "windows: %d/%d posix: %d/%d compat: %d/%d", windows_cli_status, windows_cli_count,
1169                 posix_cli_status, posix_cli_count, old_cli_status, old_cli_count);
1170
1171         return compatibility;
1172 }
1173
1174 int freerdp_client_settings_command_line_status_print(rdpSettings* settings, int status, int argc, char** argv)
1175 {
1176         COMMAND_LINE_ARGUMENT_A* arg;
1177
1178         if (status == COMMAND_LINE_STATUS_PRINT_VERSION)
1179         {
1180                 freerdp_client_print_version();
1181                 return COMMAND_LINE_STATUS_PRINT_VERSION;
1182         }
1183         else if (status == COMMAND_LINE_STATUS_PRINT)
1184         {
1185                 arg = CommandLineFindArgumentA(args, "kbd-list");
1186
1187                 if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1188                 {
1189                         int i;
1190                         RDP_KEYBOARD_LAYOUT* layouts;
1191
1192                         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD);
1193                         printf("\nKeyboard Layouts\n");
1194                         for (i = 0; layouts[i].code; i++)
1195                                 printf("0x%08X\t%s\n", (int) layouts[i].code, layouts[i].name);
1196                         free(layouts);
1197
1198                         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT);
1199                         printf("\nKeyboard Layout Variants\n");
1200                         for (i = 0; layouts[i].code; i++)
1201                                 printf("0x%08X\t%s\n", (int) layouts[i].code, layouts[i].name);
1202                         free(layouts);
1203
1204                         layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_IME);
1205                         printf("\nKeyboard Input Method Editors (IMEs)\n");
1206                         for (i = 0; layouts[i].code; i++)
1207                                 printf("0x%08X\t%s\n", (int) layouts[i].code, layouts[i].name);
1208                         free(layouts);
1209
1210                         printf("\n");
1211                 }
1212
1213                 arg = CommandLineFindArgumentA(args, "monitor-list");
1214
1215                 if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1216                 {
1217                         settings->ListMonitors = TRUE;
1218                 }
1219
1220                 return COMMAND_LINE_STATUS_PRINT;
1221         }
1222         else if (status < 0)
1223         {
1224                 freerdp_client_print_command_line_help(argc, argv);
1225                 return COMMAND_LINE_STATUS_PRINT_HELP;
1226         }
1227
1228         return 0;
1229 }
1230
1231 int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
1232         int argc, char** argv, BOOL allowUnknown)
1233 {
1234         char* p;
1235         char* user = NULL;
1236         char* gwUser = NULL;
1237         char* str;
1238         int length;
1239         int status;
1240         DWORD flags;
1241         BOOL compatibility;
1242         COMMAND_LINE_ARGUMENT_A* arg;
1243
1244         compatibility = freerdp_client_detect_command_line(argc, argv, &flags, allowUnknown);
1245
1246         if (compatibility)
1247         {
1248                 WLog_WARN(TAG, "Using deprecated command-line interface!");
1249                 return freerdp_client_parse_old_command_line_arguments(argc, argv, settings);
1250         }
1251         else
1252         {
1253                 CommandLineClearArgumentsA(args);
1254
1255                 if (allowUnknown)
1256                 {
1257                         flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
1258                 }
1259                 status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, settings,
1260                                 freerdp_client_command_line_pre_filter, freerdp_client_command_line_post_filter);
1261
1262                 if (status < 0)
1263                         return status;
1264         }
1265
1266         CommandLineFindArgumentA(args, "v");
1267
1268         arg = args;
1269
1270         do
1271         {
1272                 if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
1273                         continue;
1274
1275                 CommandLineSwitchStart(arg)
1276
1277                 CommandLineSwitchCase(arg, "v")
1278                 {
1279                         p = strchr(arg->Value, '[');
1280                         /* ipv4 */
1281                         if (!p)
1282                         {
1283                                 p = strchr(arg->Value, ':');
1284                                 if (p)
1285                                 {
1286                                         length = (int) (p - arg->Value);
1287                                         settings->ServerPort = atoi(&p[1]);
1288                                         settings->ServerHostname = (char*) calloc(length + 1UL, sizeof(char));
1289                                         strncpy(settings->ServerHostname, arg->Value, length);
1290                                         settings->ServerHostname[length] = '\0';
1291                                 }
1292                                 else
1293                                 {
1294                                         settings->ServerHostname = _strdup(arg->Value);
1295                                 }
1296                         }
1297                         else /* ipv6 */
1298                         {
1299                                 char *p2 = strchr(arg->Value, ']');
1300                                 /* not a valid [] ipv6 addr found */
1301                                 if (!p2)
1302                                         continue;
1303
1304                                 length = p2 - p;
1305                                 settings->ServerHostname = (char*) calloc(length, sizeof(char));
1306                                 strncpy(settings->ServerHostname, p+1, length-1);
1307                                 if (*(p2 + 1) == ':')
1308                                 {
1309                                         settings->ServerPort = atoi(&p2[2]);
1310                                 }
1311                                 printf("hostname %s port %d\n", settings->ServerHostname, settings->ServerPort);
1312                         }
1313                 }
1314                 CommandLineSwitchCase(arg, "spn-class")
1315                 {
1316                         settings->AuthenticationServiceClass = _strdup(arg->Value);
1317                 }
1318                 CommandLineSwitchCase(arg, "credentials-delegation")
1319                 {
1320                         settings->DisableCredentialsDelegation = arg->Value ? FALSE : TRUE;
1321                 }
1322                 CommandLineSwitchCase(arg, "vmconnect")
1323                 {
1324                         settings->ServerPort = 2179;
1325                         settings->NegotiateSecurityLayer = FALSE;
1326
1327                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1328                         {
1329                                 settings->SendPreconnectionPdu = TRUE;
1330                                 settings->PreconnectionBlob = _strdup(arg->Value);
1331                         }
1332                 }
1333                 CommandLineSwitchCase(arg, "w")
1334                 {
1335                         settings->DesktopWidth = atoi(arg->Value);
1336                 }
1337                 CommandLineSwitchCase(arg, "h")
1338                 {
1339                         settings->DesktopHeight = atoi(arg->Value);
1340                 }
1341                 CommandLineSwitchCase(arg, "size")
1342                 {
1343                         str = _strdup(arg->Value);
1344
1345                         p = strchr(str, 'x');
1346
1347                         if (p)
1348                         {
1349                                 *p = '\0';
1350                                 settings->DesktopWidth = atoi(str);
1351                                 settings->DesktopHeight = atoi(&p[1]);
1352                         }
1353                         else
1354                         {
1355                                 p = strchr(str, '%');
1356                                 if(p)
1357                                 {
1358                                         settings->PercentScreen = atoi(str);
1359                                 }
1360                         }
1361
1362                         free(str);
1363                 }
1364                 CommandLineSwitchCase(arg, "f")
1365                 {
1366                         settings->Fullscreen = TRUE;
1367                 }
1368                 CommandLineSwitchCase(arg, "multimon")
1369                 {
1370                         settings->UseMultimon = TRUE;
1371
1372                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1373                         {
1374                                 if (_stricmp(arg->Value, "force") == 0)
1375                                 {
1376                                         settings->ForceMultimon = TRUE;
1377                                 }
1378                         }
1379                 }
1380                 CommandLineSwitchCase(arg, "span")
1381                 {
1382                         settings->SpanMonitors = TRUE;
1383                 }
1384                 CommandLineSwitchCase(arg, "workarea")
1385                 {
1386                         settings->Workarea = TRUE;
1387                 }
1388                 CommandLineSwitchCase(arg, "monitors")
1389                 {
1390                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1391                         {
1392                                 UINT32 i;
1393                                 char** p;
1394                                 int count = 0;
1395
1396                                 p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
1397
1398                                 if (count > 16)
1399                                         count = 16;
1400
1401                                 settings->NumMonitorIds = (UINT32) count;
1402
1403                                 for (i = 0; i < settings->NumMonitorIds; i++)
1404                                 {
1405                                         settings->MonitorIds[i] = atoi(p[i]);
1406                                 }
1407
1408                                 free(p);
1409                         }
1410                 }
1411                 CommandLineSwitchCase(arg, "monitor-list")
1412                 {
1413                         settings->ListMonitors = TRUE;
1414                 }
1415                 CommandLineSwitchCase(arg, "t")
1416                 {
1417                         settings->WindowTitle = _strdup(arg->Value);
1418                 }
1419                 CommandLineSwitchCase(arg, "decorations")
1420                 {
1421                         settings->Decorations = arg->Value ? TRUE : FALSE;
1422                 }
1423                 CommandLineSwitchCase(arg, "smart-sizing")
1424                 {
1425                         settings->SmartSizing = TRUE;
1426
1427                         if (arg->Value)
1428                         {
1429                                 str = _strdup(arg->Value);
1430                                 if ((p = strchr(str, 'x')))
1431                                 {
1432                                         *p = '\0';
1433                                         settings->SmartSizingWidth = atoi(str);
1434                                         settings->SmartSizingHeight = atoi(&p[1]);
1435                                 }
1436                                 free(str);
1437                         }
1438                 }
1439                 CommandLineSwitchCase(arg, "bpp")
1440                 {
1441                         settings->ColorDepth = atoi(arg->Value);
1442                 }
1443                 CommandLineSwitchCase(arg, "admin")
1444                 {
1445                         settings->ConsoleSession = TRUE;
1446                 }
1447                 CommandLineSwitchCase(arg, "restricted-admin")
1448                 {
1449                         settings->ConsoleSession = TRUE;
1450                         settings->RestrictedAdminModeRequired = TRUE;
1451                 }
1452                 CommandLineSwitchCase(arg, "pth")
1453                 {
1454                         settings->ConsoleSession = TRUE;
1455                         settings->RestrictedAdminModeRequired = TRUE;
1456                         settings->PasswordHash = _strdup(arg->Value);
1457                 }
1458                 CommandLineSwitchCase(arg, "client-hostname")
1459                 {
1460                         settings->ClientHostname = _strdup(arg->Value);
1461                 }
1462                 CommandLineSwitchCase(arg, "kbd")
1463                 {
1464                         unsigned long int id;
1465                         char* pEnd;
1466
1467                         id = strtoul(arg->Value, &pEnd, 16);
1468
1469                         if (pEnd != (arg->Value + strlen(arg->Value)))
1470                                 id = 0;
1471
1472                         if (id == 0)
1473                         {
1474                                 id = (unsigned long int) freerdp_map_keyboard_layout_name_to_id(arg->Value);
1475
1476                                 if (!id)
1477                                 {
1478                                         WLog_ERR(TAG, "Could not identify keyboard layout: %s", arg->Value);
1479                                 }
1480                         }
1481
1482                         settings->KeyboardLayout = (UINT32) id;
1483                 }
1484                 CommandLineSwitchCase(arg, "kbd-type")
1485                 {
1486                         settings->KeyboardType = atoi(arg->Value);
1487                 }
1488                 CommandLineSwitchCase(arg, "kbd-subtype")
1489                 {
1490                         settings->KeyboardSubType = atoi(arg->Value);
1491                 }
1492                 CommandLineSwitchCase(arg, "kbd-fn-key")
1493                 {
1494                         settings->KeyboardFunctionKey = atoi(arg->Value);
1495                 }
1496                 CommandLineSwitchCase(arg, "u")
1497                 {
1498                         user = _strdup(arg->Value);
1499                 }
1500                 CommandLineSwitchCase(arg, "d")
1501                 {
1502                         settings->Domain = _strdup(arg->Value);
1503                 }
1504                 CommandLineSwitchCase(arg, "p")
1505                 {
1506                         settings->Password = _strdup(arg->Value);
1507                 }
1508                 CommandLineSwitchCase(arg, "g")
1509                 {
1510                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1511                         {
1512                                 p = strchr(arg->Value, ':');
1513
1514                                 if (p)
1515                                 {
1516                                         length = (int) (p - arg->Value);
1517                                         settings->GatewayPort = atoi(&p[1]);
1518                                         settings->GatewayHostname = (char*) calloc(length + 1UL, sizeof(char));
1519                                         strncpy(settings->GatewayHostname, arg->Value, length);
1520                                         settings->GatewayHostname[length] = '\0';
1521                                 }
1522                                 else
1523                                 {
1524                                         settings->GatewayHostname = _strdup(arg->Value);
1525                                 }
1526                         }
1527                         else
1528                         {
1529                                 settings->GatewayHostname = _strdup(settings->ServerHostname);
1530                         }
1531
1532                         settings->GatewayEnabled = TRUE;
1533                         settings->GatewayUseSameCredentials = TRUE;
1534
1535                         freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DIRECT);
1536                 }
1537                 CommandLineSwitchCase(arg, "gu")
1538                 {
1539                         gwUser = _strdup(arg->Value);
1540                         settings->GatewayUseSameCredentials = FALSE;
1541                 }
1542                 CommandLineSwitchCase(arg, "gd")
1543                 {
1544                         settings->GatewayDomain = _strdup(arg->Value);
1545                         settings->GatewayUseSameCredentials = FALSE;
1546                 }
1547                 CommandLineSwitchCase(arg, "gp")
1548                 {
1549                         settings->GatewayPassword = _strdup(arg->Value);
1550                         settings->GatewayUseSameCredentials = FALSE;
1551                 }
1552                 CommandLineSwitchCase(arg, "gt")
1553                 {
1554                         if (_stricmp(arg->Value, "rpc") == 0)
1555                         {
1556                                 settings->GatewayRpcTransport = TRUE;
1557                                 settings->GatewayHttpTransport = FALSE;
1558                         }
1559                         else if (_stricmp(arg->Value, "http") == 0)
1560                         {
1561                                 settings->GatewayRpcTransport = FALSE;
1562                                 settings->GatewayHttpTransport = TRUE;
1563                         }
1564                         else if (_stricmp(arg->Value, "auto") == 0)
1565                         {
1566                                 settings->GatewayRpcTransport = TRUE;
1567                                 settings->GatewayHttpTransport = TRUE;
1568                         }
1569                 }
1570                 CommandLineSwitchCase(arg, "gateway-usage-method")
1571                 {
1572                         int type;
1573                         char* pEnd;
1574
1575                         type = strtol(arg->Value, &pEnd, 10);
1576
1577                         if (type == 0)
1578                         {
1579                                 if (_stricmp(arg->Value, "none") == 0)
1580                                         type = TSC_PROXY_MODE_NONE_DIRECT;
1581                                 else if (_stricmp(arg->Value, "direct") == 0)
1582                                         type = TSC_PROXY_MODE_DIRECT;
1583                                 else if (_stricmp(arg->Value, "detect") == 0)
1584                                         type = TSC_PROXY_MODE_DETECT;
1585                                 else if (_stricmp(arg->Value, "default") == 0)
1586                                         type = TSC_PROXY_MODE_DEFAULT;
1587                         }
1588
1589                         freerdp_set_gateway_usage_method(settings, (UINT32) type);
1590                 }
1591                 CommandLineSwitchCase(arg, "app")
1592                 {
1593                         settings->RemoteApplicationProgram = _strdup(arg->Value);
1594
1595                         settings->RemoteApplicationMode = TRUE;
1596                         settings->RemoteAppLanguageBarSupported = TRUE;
1597                         settings->Workarea = TRUE;
1598                         settings->DisableWallpaper = TRUE;
1599                         settings->DisableFullWindowDrag = TRUE;
1600                 }
1601                 CommandLineSwitchCase(arg, "load-balance-info")
1602                 {
1603                         settings->LoadBalanceInfo = (BYTE*) _strdup(arg->Value);
1604                         settings->LoadBalanceInfoLength = (UINT32) strlen((char*) settings->LoadBalanceInfo);
1605                 }
1606                 CommandLineSwitchCase(arg, "app-name")
1607                 {
1608                         settings->RemoteApplicationName = _strdup(arg->Value);
1609                 }
1610                 CommandLineSwitchCase(arg, "app-icon")
1611                 {
1612                         settings->RemoteApplicationIcon = _strdup(arg->Value);
1613                 }
1614                 CommandLineSwitchCase(arg, "app-cmd")
1615                 {
1616                         settings->RemoteApplicationCmdLine = _strdup(arg->Value);
1617                 }
1618                 CommandLineSwitchCase(arg, "app-file")
1619                 {
1620                         settings->RemoteApplicationFile = _strdup(arg->Value);
1621                 }
1622                 CommandLineSwitchCase(arg, "app-guid")
1623                 {
1624                         settings->RemoteApplicationGuid = _strdup(arg->Value);
1625                 }
1626                 CommandLineSwitchCase(arg, "compression")
1627                 {
1628                         settings->CompressionEnabled = arg->Value ? TRUE : FALSE;
1629                 }
1630                 CommandLineSwitchCase(arg, "compression-level")
1631                 {
1632                         settings->CompressionLevel = atoi(arg->Value);
1633                 }
1634                 CommandLineSwitchCase(arg, "drives")
1635                 {
1636                         settings->RedirectDrives = arg->Value ? TRUE : FALSE;
1637                 }
1638                 CommandLineSwitchCase(arg, "home-drive")
1639                 {
1640                         settings->RedirectHomeDrive = arg->Value ? TRUE : FALSE;
1641                 }
1642                 CommandLineSwitchCase(arg, "clipboard")
1643                 {
1644                         settings->RedirectClipboard = arg->Value ? TRUE : FALSE;
1645                 }
1646                 CommandLineSwitchCase(arg, "shell")
1647                 {
1648                         settings->AlternateShell = _strdup(arg->Value);
1649                 }
1650                 CommandLineSwitchCase(arg, "shell-dir")
1651                 {
1652                         settings->ShellWorkingDirectory = _strdup(arg->Value);
1653                 }
1654                 CommandLineSwitchCase(arg, "audio-mode")
1655                 {
1656                         int mode;
1657
1658                         mode = atoi(arg->Value);
1659
1660                         if (mode == AUDIO_MODE_REDIRECT)
1661                         {
1662                                 settings->AudioPlayback = TRUE;
1663                         }
1664                         else if (mode == AUDIO_MODE_PLAY_ON_SERVER)
1665                         {
1666                                 settings->RemoteConsoleAudio = TRUE;
1667                         }
1668                         else if (mode == AUDIO_MODE_NONE)
1669                         {
1670                                 settings->AudioPlayback = FALSE;
1671                                 settings->RemoteConsoleAudio = FALSE;
1672                         }
1673                 }
1674                 CommandLineSwitchCase(arg, "network")
1675                 {
1676                         int type;
1677                         char* pEnd;
1678
1679                         type = strtol(arg->Value, &pEnd, 10);
1680
1681                         if (type == 0)
1682                         {
1683                                 if (_stricmp(arg->Value, "modem") == 0)
1684                                         type = CONNECTION_TYPE_MODEM;
1685                                 else if (_stricmp(arg->Value, "broadband") == 0)
1686                                         type = CONNECTION_TYPE_BROADBAND_HIGH;
1687                                 else if (_stricmp(arg->Value, "broadband-low") == 0)
1688                                         type = CONNECTION_TYPE_BROADBAND_LOW;
1689                                 else if (_stricmp(arg->Value, "broadband-high") == 0)
1690                                         type = CONNECTION_TYPE_BROADBAND_HIGH;
1691                                 else if (_stricmp(arg->Value, "wan") == 0)
1692                                         type = CONNECTION_TYPE_WAN;
1693                                 else if (_stricmp(arg->Value, "lan") == 0)
1694                                         type = CONNECTION_TYPE_LAN;
1695                                 else if ((_stricmp(arg->Value, "autodetect") == 0) ||
1696                                                 (_stricmp(arg->Value, "auto") == 0) ||
1697                                                 (_stricmp(arg->Value, "detect") == 0))
1698                                 {
1699                                         type = CONNECTION_TYPE_AUTODETECT;
1700                                 }
1701                         }
1702
1703                         freerdp_set_connection_type(settings, type);
1704                 }
1705                 CommandLineSwitchCase(arg, "fonts")
1706                 {
1707                         settings->AllowFontSmoothing = arg->Value ? TRUE : FALSE;
1708                 }
1709                 CommandLineSwitchCase(arg, "wallpaper")
1710                 {
1711                         settings->DisableWallpaper = arg->Value ? FALSE : TRUE;
1712                 }
1713                 CommandLineSwitchCase(arg, "window-drag")
1714                 {
1715                         settings->DisableFullWindowDrag = arg->Value ? FALSE : TRUE;
1716                 }
1717                 CommandLineSwitchCase(arg, "menu-anims")
1718                 {
1719                         settings->DisableMenuAnims = arg->Value ? FALSE : TRUE;
1720                 }
1721                 CommandLineSwitchCase(arg, "themes")
1722                 {
1723                         settings->DisableThemes = arg->Value ? FALSE : TRUE;
1724                 }
1725                 CommandLineSwitchCase(arg, "aero")
1726                 {
1727                         settings->AllowDesktopComposition = arg->Value ? TRUE : FALSE;
1728                 }
1729                 CommandLineSwitchCase(arg, "gdi")
1730                 {
1731                         if (_stricmp(arg->Value, "sw") == 0)
1732                                 settings->SoftwareGdi = TRUE;
1733                         else if (_stricmp(arg->Value, "hw") == 0)
1734                                 settings->SoftwareGdi = FALSE;
1735                 }
1736                 CommandLineSwitchCase(arg, "gfx")
1737                 {
1738                         settings->SupportGraphicsPipeline = TRUE;
1739                 }
1740                 CommandLineSwitchCase(arg, "gfx-thin-client")
1741                 {
1742                         settings->GfxThinClient = arg->Value ? TRUE : FALSE;
1743                         settings->SupportGraphicsPipeline = TRUE;
1744                 }
1745                 CommandLineSwitchCase(arg, "gfx-small-cache")
1746                 {
1747                         settings->GfxSmallCache = arg->Value ? TRUE : FALSE;
1748                         settings->SupportGraphicsPipeline = TRUE;
1749                 }
1750                 CommandLineSwitchCase(arg, "gfx-progressive")
1751                 {
1752                         settings->GfxProgressive = arg->Value ? TRUE : FALSE;
1753                         settings->GfxThinClient = settings->GfxProgressive ? FALSE : TRUE;
1754                         settings->SupportGraphicsPipeline = TRUE;
1755                 }
1756                 CommandLineSwitchCase(arg, "gfx-h264")
1757                 {
1758                         settings->GfxH264 = arg->Value ? TRUE : FALSE;
1759                         settings->SupportGraphicsPipeline = TRUE;
1760                 }
1761                 CommandLineSwitchCase(arg, "rfx")
1762                 {
1763                         settings->RemoteFxCodec = TRUE;
1764                         settings->FastPathOutput = TRUE;
1765                         settings->ColorDepth = 32;
1766                         settings->LargePointerFlag = TRUE;
1767                         settings->FrameMarkerCommandEnabled = TRUE;
1768                 }
1769                 CommandLineSwitchCase(arg, "rfx-mode")
1770                 {
1771                         if (strcmp(arg->Value, "video") == 0)
1772                                 settings->RemoteFxCodecMode = 0x00;
1773                         else if (strcmp(arg->Value, "image") == 0)
1774                                 settings->RemoteFxCodecMode = 0x02;
1775                 }
1776                 CommandLineSwitchCase(arg, "frame-ack")
1777                 {
1778                         settings->FrameAcknowledge = atoi(arg->Value);
1779                 }
1780                 CommandLineSwitchCase(arg, "nsc")
1781                 {
1782                         settings->NSCodec = TRUE;
1783                         settings->FastPathOutput = TRUE;
1784                         settings->ColorDepth = 32;
1785                         settings->LargePointerFlag = TRUE;
1786                         settings->FrameMarkerCommandEnabled = TRUE;
1787                 }
1788                 CommandLineSwitchCase(arg, "jpeg")
1789                 {
1790                         settings->JpegCodec = TRUE;
1791                         settings->JpegQuality = 75;
1792                 }
1793                 CommandLineSwitchCase(arg, "jpeg-quality")
1794                 {
1795                         settings->JpegQuality = atoi(arg->Value) % 100;
1796                 }
1797                 CommandLineSwitchCase(arg, "nego")
1798                 {
1799                         settings->NegotiateSecurityLayer = arg->Value ? TRUE : FALSE;
1800                 }
1801                 CommandLineSwitchCase(arg, "pcb")
1802                 {
1803                         settings->SendPreconnectionPdu = TRUE;
1804                         settings->PreconnectionBlob = _strdup(arg->Value);
1805                 }
1806                 CommandLineSwitchCase(arg, "pcid")
1807                 {
1808                         settings->SendPreconnectionPdu = TRUE;
1809                         settings->PreconnectionId = atoi(arg->Value);
1810                 }
1811                 CommandLineSwitchCase(arg, "sec")
1812                 {
1813                         if (strcmp("rdp", arg->Value) == 0) /* Standard RDP */
1814                         {
1815                                 settings->RdpSecurity = TRUE;
1816                                 settings->TlsSecurity = FALSE;
1817                                 settings->NlaSecurity = FALSE;
1818                                 settings->ExtSecurity = FALSE;
1819                                 settings->UseRdpSecurityLayer = TRUE;
1820                         }
1821                         else if (strcmp("tls", arg->Value) == 0) /* TLS */
1822                         {
1823                                 settings->RdpSecurity = FALSE;
1824                                 settings->TlsSecurity = TRUE;
1825                                 settings->NlaSecurity = FALSE;
1826                                 settings->ExtSecurity = FALSE;
1827                         }
1828                         else if (strcmp("nla", arg->Value) == 0) /* NLA */
1829                         {
1830                                 settings->RdpSecurity = FALSE;
1831                                 settings->TlsSecurity = FALSE;
1832                                 settings->NlaSecurity = TRUE;
1833                                 settings->ExtSecurity = FALSE;
1834                         }
1835                         else if (strcmp("ext", arg->Value) == 0) /* NLA Extended */
1836                         {
1837                                 settings->RdpSecurity = FALSE;
1838                                 settings->TlsSecurity = FALSE;
1839                                 settings->NlaSecurity = FALSE;
1840                                 settings->ExtSecurity = TRUE;
1841                         }
1842                         else
1843                         {
1844                                 WLog_ERR(TAG, "unknown protocol security: %s", arg->Value);
1845                         }
1846                 }
1847                 CommandLineSwitchCase(arg, "encryption-methods")
1848                 {
1849                         if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
1850                         {
1851                                 UINT32 i;
1852                                 char** p;
1853                                 int count = 0;
1854
1855                                 p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
1856
1857                                 for (i = 0; i < count; i++)
1858                                 {
1859                                         if (!strcmp(p[i], "40"))
1860                                                 settings->EncryptionMethods |= ENCRYPTION_METHOD_40BIT;
1861                                         else if (!strcmp(p[i], "56"))
1862                                                 settings->EncryptionMethods |= ENCRYPTION_METHOD_56BIT;
1863                                         else if (!strcmp(p[i], "128"))
1864                                                 settings->EncryptionMethods |= ENCRYPTION_METHOD_128BIT;
1865                                         else if (!strcmp(p[i], "FIPS"))
1866                                                 settings->EncryptionMethods |= ENCRYPTION_METHOD_FIPS;
1867                                         else
1868                                                 WLog_ERR(TAG, "unknown encryption method '%s'", p[i]);
1869                                 }
1870
1871                                 free(p);
1872                         }
1873                 }
1874                 CommandLineSwitchCase(arg, "sec-rdp")
1875                 {
1876                         settings->RdpSecurity = arg->Value ? TRUE : FALSE;
1877                 }
1878                 CommandLineSwitchCase(arg, "sec-tls")
1879                 {
1880                         settings->TlsSecurity = arg->Value ? TRUE : FALSE;
1881                 }
1882                 CommandLineSwitchCase(arg, "sec-nla")
1883                 {
1884                         settings->NlaSecurity = arg->Value ? TRUE : FALSE;
1885                 }
1886                 CommandLineSwitchCase(arg, "sec-ext")
1887                 {
1888                         settings->ExtSecurity = arg->Value ? TRUE : FALSE;
1889                 }
1890                 CommandLineSwitchCase(arg, "tls-ciphers")
1891                 {
1892                         if (strcmp(arg->Value, "netmon") == 0)
1893                         {
1894                                 settings->AllowedTlsCiphers = _strdup("ALL:!ECDH");
1895                         }
1896                         else if (strcmp(arg->Value, "ma") == 0)
1897                         {
1898                                 settings->AllowedTlsCiphers = _strdup("AES128-SHA");
1899                         }
1900                         else
1901                         {
1902                                 settings->AllowedTlsCiphers = _strdup(arg->Value);
1903                         }
1904                 }
1905                 CommandLineSwitchCase(arg, "cert-name")
1906                 {
1907                         settings->CertificateName = _strdup(arg->Value);
1908                 }
1909                 CommandLineSwitchCase(arg, "cert-ignore")
1910                 {
1911                         settings->IgnoreCertificate = TRUE;
1912                 }
1913                 CommandLineSwitchCase(arg, "authentication")
1914                 {
1915                         settings->Authentication = arg->Value ? TRUE : FALSE;
1916                 }
1917                 CommandLineSwitchCase(arg, "encryption")
1918                 {
1919                         settings->UseRdpSecurityLayer = arg->Value ? FALSE : TRUE;
1920                 }
1921                 CommandLineSwitchCase(arg, "grab-keyboard")
1922                 {
1923                         settings->GrabKeyboard = arg->Value ? TRUE : FALSE;
1924                 }
1925                 CommandLineSwitchCase(arg, "toggle-fullscreen")
1926                 {
1927                         settings->ToggleFullscreen = arg->Value ? TRUE : FALSE;
1928                 }
1929                 CommandLineSwitchCase(arg, "mouse-motion")
1930                 {
1931                         settings->MouseMotion = arg->Value ? TRUE : FALSE;
1932                 }
1933                 CommandLineSwitchCase(arg, "parent-window")
1934                 {
1935                         settings->ParentWindowId = strtol(arg->Value, NULL, 0);
1936                 }
1937                 CommandLineSwitchCase(arg, "bitmap-cache")
1938                 {
1939                         settings->BitmapCacheEnabled = arg->Value ? TRUE : FALSE;
1940                 }
1941                 CommandLineSwitchCase(arg, "offscreen-cache")
1942                 {
1943                         settings->OffscreenSupportLevel = arg->Value ? TRUE : FALSE;
1944                 }
1945                 CommandLineSwitchCase(arg, "glyph-cache")
1946                 {
1947                         settings->GlyphSupportLevel = arg->Value ? GLYPH_SUPPORT_FULL : GLYPH_SUPPORT_NONE;
1948                 }
1949                 CommandLineSwitchCase(arg, "codec-cache")
1950                 {
1951                         settings->BitmapCacheV3Enabled = TRUE;
1952
1953                         if (strcmp(arg->Value, "rfx") == 0)
1954                         {
1955                                 settings->RemoteFxCodec = TRUE;
1956                         }
1957                         else if (strcmp(arg->Value, "nsc") == 0)
1958                         {
1959                                 settings->NSCodec = TRUE;
1960                         }
1961                         else if (strcmp(arg->Value, "jpeg") == 0)
1962                         {
1963                                 settings->JpegCodec = TRUE;
1964
1965                                 if (settings->JpegQuality == 0)
1966                                         settings->JpegQuality = 75;
1967                         }
1968                 }
1969                 CommandLineSwitchCase(arg, "fast-path")
1970                 {
1971                         settings->FastPathInput = arg->Value ? TRUE : FALSE;
1972                         settings->FastPathOutput = arg->Value ? TRUE : FALSE;
1973                 }
1974                 CommandLineSwitchCase(arg, "max-fast-path-size")
1975                 {
1976                         settings->MultifragMaxRequestSize = atoi(arg->Value);
1977                 }
1978                 CommandLineSwitchCase(arg, "async-input")
1979                 {
1980                         settings->AsyncInput = arg->Value ? TRUE : FALSE;
1981                 }
1982                 CommandLineSwitchCase(arg, "async-update")
1983                 {
1984                         settings->AsyncUpdate = arg->Value ? TRUE : FALSE;
1985                 }
1986                 CommandLineSwitchCase(arg, "async-channels")
1987                 {
1988                         settings->AsyncChannels = arg->Value ? TRUE : FALSE;
1989                 }
1990                 CommandLineSwitchCase(arg, "async-transport")
1991                 {
1992                         settings->AsyncTransport = arg->Value ? TRUE : FALSE;
1993                 }
1994                 CommandLineSwitchCase(arg, "wm-class")
1995                 {
1996                         settings->WmClass = _strdup(arg->Value);
1997                 }
1998                 CommandLineSwitchCase(arg, "play-rfx")
1999                 {
2000                         settings->PlayRemoteFxFile = _strdup(arg->Value);
2001                         settings->PlayRemoteFx = TRUE;
2002                 }
2003                 CommandLineSwitchCase(arg, "auth-only")
2004                 {
2005                         settings->AuthenticationOnly = arg->Value ? TRUE : FALSE;
2006                 }
2007                 CommandLineSwitchCase(arg, "auto-reconnect")
2008                 {
2009                         settings->AutoReconnectionEnabled = arg->Value ? TRUE : FALSE;
2010                 }
2011                 CommandLineSwitchCase(arg, "reconnect-cookie")
2012                 {
2013                         BYTE *base64;
2014                         int length;
2015                         crypto_base64_decode((const char *) (arg->Value), (int) strlen(arg->Value),
2016                                                                 &base64, &length);
2017                         if ((base64 != NULL) && (length == sizeof(ARC_SC_PRIVATE_PACKET)))
2018                         {
2019                                 memcpy(settings->ServerAutoReconnectCookie, base64, length);
2020                                 free(base64);
2021                         }
2022                         else
2023                         {
2024                                 WLog_ERR(TAG, "reconnect-cookie:  invalid base64 '%s'", arg->Value);
2025                         }
2026                 }
2027                 CommandLineSwitchCase(arg, "print-reconnect-cookie")
2028                 {
2029                         settings->PrintReconnectCookie = arg->Value ? TRUE : FALSE;
2030                 }
2031                 CommandLineSwitchCase(arg, "assistance")
2032                 {
2033                         settings->RemoteAssistanceMode = TRUE;
2034                         settings->RemoteAssistancePassword = _strdup(arg->Value);
2035                 }
2036                 CommandLineSwitchDefault(arg)
2037                 {
2038                 }
2039
2040                 CommandLineSwitchEnd(arg)
2041         }
2042         while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
2043
2044         if (!settings->Domain && user)
2045         {
2046                 freerdp_parse_username(user, &settings->Username, &settings->Domain);
2047                 free(user);
2048         }
2049         else
2050                 settings->Username = user;
2051
2052         if (!settings->GatewayDomain && gwUser)
2053         {
2054                 freerdp_parse_username(gwUser, &settings->GatewayUsername,
2055                                  &settings->GatewayDomain);
2056                 free(gwUser);
2057         }
2058         else
2059                 settings->GatewayUsername = gwUser;
2060
2061         freerdp_performance_flags_make(settings);
2062
2063         if (settings->SupportGraphicsPipeline)
2064         {
2065                 settings->FastPathOutput = TRUE;
2066                 settings->ColorDepth = 32;
2067                 settings->LargePointerFlag = TRUE;
2068                 settings->FrameMarkerCommandEnabled = TRUE;
2069         }
2070
2071         arg = CommandLineFindArgumentA(args, "port");
2072
2073         if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
2074         {
2075                 settings->ServerPort = atoi(arg->Value);
2076         }
2077
2078         arg = CommandLineFindArgumentA(args, "p");
2079
2080         if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
2081         {
2082                 FillMemory(arg->Value, strlen(arg->Value), '*');
2083         }
2084
2085         arg = CommandLineFindArgumentA(args, "gp");
2086
2087         if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
2088         {
2089                 FillMemory(arg->Value, strlen(arg->Value), '*');
2090         }
2091
2092         return status;
2093 }
2094
2095 int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings* settings, char* name, void* data)
2096 {
2097         void* entry;
2098
2099         entry = freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
2100
2101         if (entry)
2102         {
2103                 if (freerdp_channels_client_load(channels, settings, entry, data) == 0)
2104                 {
2105                         WLog_INFO(TAG, "loading channel %s", name);
2106                         return 0;
2107                 }
2108         }
2109
2110         return -1;
2111 }
2112
2113 int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
2114 {
2115         UINT32 index;
2116         ADDIN_ARGV* args;
2117
2118         if ((freerdp_static_channel_collection_find(settings, "rdpsnd")) ||
2119                         (freerdp_dynamic_channel_collection_find(settings, "tsmf")))
2120         {
2121                 settings->DeviceRedirection = TRUE; /* rdpsnd requires rdpdr to be registered */
2122                 settings->AudioPlayback = TRUE; /* Both rdpsnd and tsmf require this flag to be set */
2123         }
2124
2125         if (freerdp_dynamic_channel_collection_find(settings, "audin"))
2126         {
2127                 settings->AudioCapture = TRUE;
2128         }
2129
2130         if (settings->NetworkAutoDetect ||
2131                 settings->SupportHeartbeatPdu ||
2132                 settings->SupportMultitransport)
2133         {
2134                 settings->DeviceRedirection = TRUE; /* these RDP8 features require rdpdr to be registered */
2135         }
2136
2137         if (settings->RedirectDrives || settings->RedirectHomeDrive || settings->RedirectSerialPorts
2138                         || settings->RedirectSmartCards || settings->RedirectPrinters)
2139         {
2140                 settings->DeviceRedirection = TRUE; /* All of these features require rdpdr */
2141         }
2142
2143         if (settings->RedirectDrives)
2144         {
2145                 if (!freerdp_device_collection_find(settings, "drive"))
2146                 {
2147                         char* params[3];
2148
2149                         params[0] = "drive";
2150                         params[1] = "media";
2151                         params[2] = "*";
2152
2153                         freerdp_client_add_device_channel(settings, 3, (char**) params);
2154                 }
2155         }
2156
2157         if (settings->RedirectHomeDrive)
2158         {
2159                 if (!freerdp_device_collection_find(settings, "drive"))
2160                 {
2161                         char* params[3];
2162
2163                         params[0] = "drive";
2164                         params[1] = "home";
2165                         params[2] = "%";
2166
2167                         freerdp_client_add_device_channel(settings, 3, (char**) params);
2168                 }
2169         }
2170
2171         if (settings->DeviceRedirection)
2172         {
2173                 freerdp_client_load_static_channel_addin(channels, settings, "rdpdr", settings);
2174
2175                 if (!freerdp_static_channel_collection_find(settings, "rdpsnd"))
2176                 {
2177                         char* params[2];
2178
2179                         params[0] = "rdpsnd";
2180                         params[1] = "sys:fake";
2181
2182                         freerdp_client_add_static_channel(settings, 2, (char**) params);
2183                 }
2184         }
2185
2186         if (settings->RedirectSmartCards)
2187         {
2188                 RDPDR_SMARTCARD* smartcard;
2189
2190                 smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD));
2191
2192                 if (!smartcard)
2193                         return -1;
2194
2195                 smartcard->Type = RDPDR_DTYP_SMARTCARD;
2196                 freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard);
2197         }
2198
2199         if (settings->RedirectPrinters)
2200         {
2201                 RDPDR_PRINTER* printer;
2202
2203                 printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER));
2204
2205                 if (!printer)
2206                         return -1;
2207
2208                 printer->Type = RDPDR_DTYP_PRINT;
2209                 freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer);
2210         }
2211
2212         if (settings->RedirectClipboard)
2213         {
2214                 if (!freerdp_static_channel_collection_find(settings, "cliprdr"))
2215                 {
2216                         char* params[1];
2217
2218                         params[0] = "cliprdr";
2219
2220                         freerdp_client_add_static_channel(settings, 1, (char**) params);
2221                 }
2222         }
2223
2224         if (settings->LyncRdpMode)
2225         {
2226                 settings->EncomspVirtualChannel = TRUE;
2227                 settings->RemdeskVirtualChannel = TRUE;
2228                 settings->CompressionEnabled = FALSE;
2229         }
2230
2231         if (settings->RemoteAssistanceMode)
2232         {
2233                 settings->EncomspVirtualChannel = TRUE;
2234                 settings->RemdeskVirtualChannel = TRUE;
2235         }
2236
2237         if (settings->EncomspVirtualChannel)
2238                 freerdp_client_load_static_channel_addin(channels, settings, "encomsp", settings);
2239
2240         if (settings->RemdeskVirtualChannel)
2241                 freerdp_client_load_static_channel_addin(channels, settings, "remdesk", settings);
2242
2243         for (index = 0; index < settings->StaticChannelCount; index++)
2244         {
2245                 args = settings->StaticChannelArray[index];
2246                 freerdp_client_load_static_channel_addin(channels, settings, args->argv[0], args);
2247         }
2248
2249         if (settings->RemoteApplicationMode)
2250         {
2251                 freerdp_client_load_static_channel_addin(channels, settings, "rail", settings);
2252         }
2253
2254         if (settings->MultiTouchInput)
2255         {
2256                 char* p[1];
2257                 int count;
2258
2259                 count = 1;
2260                 p[0] = "rdpei";
2261
2262                 freerdp_client_add_dynamic_channel(settings, count, p);
2263         }
2264
2265         if (settings->SupportGraphicsPipeline)
2266         {
2267                 char* p[1];
2268                 int count;
2269
2270                 count = 1;
2271                 p[0] = "rdpgfx";
2272
2273                 freerdp_client_add_dynamic_channel(settings, count, p);
2274         }
2275
2276         if (settings->SupportEchoChannel)
2277         {
2278                 char* p[1];
2279                 int count;
2280
2281                 count = 1;
2282                 p[0] = "echo";
2283
2284                 freerdp_client_add_dynamic_channel(settings, count, p);
2285         }
2286
2287         if (settings->SupportDisplayControl)
2288         {
2289                 char* p[1];
2290                 int count;
2291
2292                 count = 1;
2293                 p[0] = "disp";
2294
2295                 freerdp_client_add_dynamic_channel(settings, count, p);
2296         }
2297
2298         if (settings->DynamicChannelCount)
2299                 settings->SupportDynamicChannels = TRUE;
2300
2301         if (settings->SupportDynamicChannels)
2302         {
2303                 freerdp_client_load_static_channel_addin(channels, settings, "drdynvc", settings);
2304         }
2305
2306         return 1;
2307 }