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