Fix changelog email address
[freerdp-ubuntu-pcb-backport.git] / channels / rail / rail_orders.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol client.
3  * Remote Applications Integrated Locally (RAIL) Orders
4  *
5  * Copyright 2009 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2011 Roman Barabanov <romanbarabanov@gmail.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <freerdp/utils/rail.h>
22 #include <freerdp/utils/memory.h>
23
24 #include "rail_orders.h"
25
26 #define RAIL_ORDER_TYPE_EXEC                    0x0001
27 #define RAIL_ORDER_TYPE_ACTIVATE                0x0002
28 #define RAIL_ORDER_TYPE_SYSPARAM                0x0003
29 #define RAIL_ORDER_TYPE_SYSCOMMAND              0x0004
30 #define RAIL_ORDER_TYPE_HANDSHAKE               0x0005
31 #define RAIL_ORDER_TYPE_NOTIFY_EVENT            0x0006
32 #define RAIL_ORDER_TYPE_WINDOW_MOVE             0x0008
33 #define RAIL_ORDER_TYPE_LOCALMOVESIZE           0x0009
34 #define RAIL_ORDER_TYPE_MINMAXINFO              0x000A
35 #define RAIL_ORDER_TYPE_CLIENT_STATUS           0x000B
36 #define RAIL_ORDER_TYPE_SYSMENU                 0x000C
37 #define RAIL_ORDER_TYPE_LANGBAR_INFO            0x000D
38 #define RAIL_ORDER_TYPE_EXEC_RESULT             0x0080
39 #define RAIL_ORDER_TYPE_GET_APPID_REQ           0x000E
40 #define RAIL_ORDER_TYPE_GET_APPID_RESP          0x000F
41
42 static const char* const RAIL_ORDER_TYPE_STRINGS[] =
43 {
44         "",
45         "Execute",
46         "Activate",
47         "System Parameters Update",
48         "System Command",
49         "Handshake",
50         "Notify Event",
51         "",
52         "Window Move",
53         "Local Move/Size",
54         "Min Max Info",
55         "Client Status",
56         "System Menu",
57         "Language Bar Info",
58         "Get Application ID Request",
59         "Get Application ID Response",
60         "Execute Result"
61 };
62
63 void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, UNICODE_STRING* unicode_string)
64 {
65         char* buffer;
66         size_t length = 0;
67
68         if (unicode_string->string != NULL)
69                 xfree(unicode_string->string);
70
71         unicode_string->string = NULL;
72         unicode_string->length = 0;
73
74         if (string == NULL || strlen(string) < 1)
75                 return;
76
77         buffer = freerdp_uniconv_out(rail_order->uniconv, string, &length);
78
79         unicode_string->string = (uint8*) buffer;
80         unicode_string->length = (uint16) length;
81 }
82
83 void rail_read_pdu_header(STREAM* s, uint16* orderType, uint16* orderLength)
84 {
85         stream_read_uint16(s, *orderType); /* orderType (2 bytes) */
86         stream_read_uint16(s, *orderLength); /* orderLength (2 bytes) */
87 }
88
89 void rail_write_pdu_header(STREAM* s, uint16 orderType, uint16 orderLength)
90 {
91         stream_write_uint16(s, orderType); /* orderType (2 bytes) */
92         stream_write_uint16(s, orderLength); /* orderLength (2 bytes) */
93 }
94
95 STREAM* rail_pdu_init(int length)
96 {
97         STREAM* s;
98         s = stream_new(length + RAIL_PDU_HEADER_LENGTH);
99         stream_seek(s, RAIL_PDU_HEADER_LENGTH);
100         return s;
101 }
102
103 void rail_send_pdu(rdpRailOrder* rail_order, STREAM* s, uint16 orderType)
104 {
105         uint16 orderLength;
106
107         orderLength = stream_get_length(s);
108         stream_set_pos(s, 0);
109
110         rail_write_pdu_header(s, orderType, orderLength);
111         stream_set_pos(s, orderLength);
112
113         /* send */
114         DEBUG_RAIL("Sending %s PDU, length:%d",
115                         RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
116
117         rail_send_channel_data(rail_order->plugin, s->data, orderLength);
118 }
119
120 void rail_write_high_contrast(STREAM* s, HIGH_CONTRAST* high_contrast)
121 {
122         high_contrast->colorSchemeLength = high_contrast->colorScheme.length + 2;
123         stream_write_uint32(s, high_contrast->flags); /* flags (4 bytes) */
124         stream_write_uint32(s, high_contrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */
125         rail_write_unicode_string(s, &high_contrast->colorScheme); /* colorScheme */
126 }
127
128 void rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake)
129 {
130         stream_read_uint32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
131 }
132
133 void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result)
134 {
135         stream_read_uint16(s, exec_result->flags); /* flags (2 bytes) */
136         stream_read_uint16(s, exec_result->execResult); /* execResult (2 bytes) */
137         stream_read_uint32(s, exec_result->rawResult); /* rawResult (4 bytes) */
138         stream_seek_uint16(s); /* padding (2 bytes) */
139         rail_read_unicode_string(s, &exec_result->exeOrFile); /* exeOrFile */
140 }
141
142 void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam)
143 {
144         uint8 body;
145         stream_read_uint32(s, sysparam->param); /* systemParam (4 bytes) */
146         stream_read_uint8(s, body); /* body (1 byte) */
147
148         switch (sysparam->param)
149         {
150                 case SPI_SET_SCREEN_SAVE_ACTIVE:
151                         sysparam->setScreenSaveActive = (body != 0) ? true : false;
152                         break;
153
154                 case SPI_SET_SCREEN_SAVE_SECURE:
155                         sysparam->setScreenSaveSecure = (body != 0) ? true : false;
156                         break;
157
158                 default:
159                         break;
160         }
161 }
162
163 void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo)
164 {
165         stream_read_uint32(s, minmaxinfo->windowId); /* windowId (4 bytes) */
166         stream_read_uint16(s, minmaxinfo->maxWidth); /* maxWidth (2 bytes) */
167         stream_read_uint16(s, minmaxinfo->maxHeight); /* maxHeight (2 bytes) */
168         stream_read_uint16(s, minmaxinfo->maxPosX); /* maxPosX (2 bytes) */
169         stream_read_uint16(s, minmaxinfo->maxPosY); /* maxPosY (2 bytes) */
170         stream_read_uint16(s, minmaxinfo->minTrackWidth); /* minTrackWidth (2 bytes) */
171         stream_read_uint16(s, minmaxinfo->minTrackHeight); /* minTrackHeight (2 bytes) */
172         stream_read_uint16(s, minmaxinfo->maxTrackWidth); /* maxTrackWidth (2 bytes) */
173         stream_read_uint16(s, minmaxinfo->maxTrackHeight); /* maxTrackHeight (2 bytes) */
174 }
175
176 void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize)
177 {
178         uint16 isMoveSizeStart;
179         stream_read_uint32(s, localmovesize->windowId); /* windowId (4 bytes) */
180
181         stream_read_uint16(s, isMoveSizeStart); /* isMoveSizeStart (2 bytes) */
182         localmovesize->isMoveSizeStart = (isMoveSizeStart != 0) ? true : false;
183
184         stream_read_uint16(s, localmovesize->moveSizeType); /* moveSizeType (2 bytes) */
185         stream_read_uint16(s, localmovesize->posX); /* posX (2 bytes) */
186         stream_read_uint16(s, localmovesize->posY); /* posY (2 bytes) */
187 }
188
189 void rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp)
190 {
191         stream_read_uint32(s, get_appid_resp->windowId); /* windowId (4 bytes) */
192         stream_read(s, &get_appid_resp->applicationIdBuffer[0], 512); /* applicationId (256 UNICODE chars) */
193
194         get_appid_resp->applicationId.length = 512;
195         get_appid_resp->applicationId.string = &get_appid_resp->applicationIdBuffer[0];
196 }
197
198 void rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info)
199 {
200         stream_read_uint32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
201 }
202
203 void rail_write_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake)
204 {
205         stream_write_uint32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
206 }
207
208 void rail_write_client_status_order(STREAM* s, RAIL_CLIENT_STATUS_ORDER* client_status)
209 {
210         stream_write_uint32(s, client_status->flags); /* flags (4 bytes) */
211 }
212
213 void rail_write_client_exec_order(STREAM* s, RAIL_EXEC_ORDER* exec)
214 {
215         stream_write_uint16(s, exec->flags); /* flags (2 bytes) */
216         stream_write_uint16(s, exec->exeOrFile.length); /* exeOrFileLength (2 bytes) */
217         stream_write_uint16(s, exec->workingDir.length); /* workingDirLength (2 bytes) */
218         stream_write_uint16(s, exec->arguments.length); /* argumentsLength (2 bytes) */
219         rail_write_unicode_string_value(s, &exec->exeOrFile); /* exeOrFile */
220         rail_write_unicode_string_value(s, &exec->workingDir); /* workingDir */
221         rail_write_unicode_string_value(s, &exec->arguments); /* arguments */
222 }
223
224 void rail_write_client_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam)
225 {
226         uint8 body;
227         stream_write_uint32(s, sysparam->param); /* systemParam (4 bytes) */
228
229         switch (sysparam->param)
230         {
231                 case SPI_SET_DRAG_FULL_WINDOWS:
232                         body = sysparam->dragFullWindows;
233                         stream_write_uint8(s, body);
234                         break;
235
236                 case SPI_SET_KEYBOARD_CUES:
237                         body = sysparam->keyboardCues;
238                         stream_write_uint8(s, body);
239                         break;
240
241                 case SPI_SET_KEYBOARD_PREF:
242                         body = sysparam->keyboardPref;
243                         stream_write_uint8(s, body);
244                         break;
245
246                 case SPI_SET_MOUSE_BUTTON_SWAP:
247                         body = sysparam->mouseButtonSwap;
248                         stream_write_uint8(s, body);
249                         break;
250
251                 case SPI_SET_WORK_AREA:
252                         freerdp_write_rectangle_16(s, &sysparam->workArea);
253                         break;
254
255                 case SPI_DISPLAY_CHANGE:
256                         freerdp_write_rectangle_16(s, &sysparam->displayChange);
257                         break;
258
259                 case SPI_TASKBAR_POS:
260                         freerdp_write_rectangle_16(s, &sysparam->taskbarPos);
261                         break;
262
263                 case SPI_SET_HIGH_CONTRAST:
264                         rail_write_high_contrast(s, &sysparam->highContrast);
265                         break;
266         }
267 }
268
269 void rail_write_client_activate_order(STREAM* s, RAIL_ACTIVATE_ORDER* activate)
270 {
271         uint8 enabled;
272
273         stream_write_uint32(s, activate->windowId); /* windowId (4 bytes) */
274
275         enabled = activate->enabled;
276         stream_write_uint8(s, enabled); /* enabled (1 byte) */
277 }
278
279 void rail_write_client_sysmenu_order(STREAM* s, RAIL_SYSMENU_ORDER* sysmenu)
280 {
281         stream_write_uint32(s, sysmenu->windowId); /* windowId (4 bytes) */
282         stream_write_uint16(s, sysmenu->left); /* left (2 bytes) */
283         stream_write_uint16(s, sysmenu->top); /* top (2 bytes) */
284 }
285
286 void rail_write_client_syscommand_order(STREAM* s, RAIL_SYSCOMMAND_ORDER* syscommand)
287 {
288         stream_write_uint32(s, syscommand->windowId); /* windowId (4 bytes) */
289         stream_write_uint16(s, syscommand->command); /* command (2 bytes) */
290 }
291
292 void rail_write_client_notify_event_order(STREAM* s, RAIL_NOTIFY_EVENT_ORDER* notify_event)
293 {
294         stream_write_uint32(s, notify_event->windowId); /* windowId (4 bytes) */
295         stream_write_uint32(s, notify_event->notifyIconId); /* notifyIconId (4 bytes) */
296         stream_write_uint32(s, notify_event->message); /* notifyIconId (4 bytes) */
297 }
298
299 void rail_write_client_window_move_order(STREAM* s, RAIL_WINDOW_MOVE_ORDER* window_move)
300 {
301         stream_write_uint32(s, window_move->windowId); /* windowId (4 bytes) */
302         stream_write_uint16(s, window_move->left); /* left (2 bytes) */
303         stream_write_uint16(s, window_move->top); /* top (2 bytes) */
304         stream_write_uint16(s, window_move->right); /* right (2 bytes) */
305         stream_write_uint16(s, window_move->bottom); /* bottom (2 bytes) */
306 }
307
308 void rail_write_client_get_appid_req_order(STREAM* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req)
309 {
310         stream_write_uint32(s, get_appid_req->windowId); /* windowId (4 bytes) */
311 }
312
313 void rail_write_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info)
314 {
315         stream_write_uint32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
316 }
317
318 void rail_recv_handshake_order(rdpRailOrder* rail_order, STREAM* s)
319 {
320         rail_read_handshake_order(s, &rail_order->handshake);
321
322         rail_order->handshake.buildNumber = 0x00001DB0;
323         rail_send_handshake_order(rail_order);
324
325         rail_order->client_status.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
326         rail_send_client_status_order(rail_order);
327
328         /* sysparam update */
329
330         rail_order->sysparam.params = 0;
331
332         rail_order->sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST;
333         rail_order->sysparam.highContrast.colorScheme.string = NULL;
334         rail_order->sysparam.highContrast.colorScheme.length = 0;
335         rail_order->sysparam.highContrast.flags = 0x7E;
336
337         rail_order->sysparam.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP;
338         rail_order->sysparam.mouseButtonSwap = false;
339
340         rail_order->sysparam.params |= SPI_MASK_SET_KEYBOARD_PREF;
341         rail_order->sysparam.keyboardPref = false;
342
343         rail_order->sysparam.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS;
344         rail_order->sysparam.dragFullWindows = false;
345
346         rail_order->sysparam.params |= SPI_MASK_SET_KEYBOARD_CUES;
347         rail_order->sysparam.keyboardCues = false;
348
349         rail_order->sysparam.params |= SPI_MASK_SET_WORK_AREA;
350         rail_order->sysparam.workArea.left = 0;
351         rail_order->sysparam.workArea.top = 0;
352         rail_order->sysparam.workArea.right = 1024;
353         rail_order->sysparam.workArea.bottom = 768;
354
355         rail_send_channel_event(rail_order->plugin,
356                 RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS, &rail_order->sysparam);
357 }
358
359 void rail_recv_exec_result_order(rdpRailOrder* rail_order, STREAM* s)
360 {
361         rail_read_server_exec_result_order(s, &rail_order->exec_result);
362         rail_send_channel_event(rail_order->plugin,
363                 RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS, &rail_order->exec_result);
364 }
365
366 void rail_recv_server_sysparam_order(rdpRailOrder* rail_order, STREAM* s)
367 {
368         rail_read_server_sysparam_order(s, &rail_order->sysparam);
369         rail_send_channel_event(rail_order->plugin,
370                 RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM, &rail_order->sysparam);
371 }
372
373 void rail_recv_server_minmaxinfo_order(rdpRailOrder* rail_order, STREAM* s)
374 {
375         rail_read_server_minmaxinfo_order(s, &rail_order->minmaxinfo);
376         rail_send_channel_event(rail_order->plugin,
377                 RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO, &rail_order->minmaxinfo);
378 }
379
380 void rail_recv_server_localmovesize_order(rdpRailOrder* rail_order, STREAM* s)
381 {
382         rail_read_server_localmovesize_order(s, &rail_order->localmovesize);
383         rail_send_channel_event(rail_order->plugin,
384                 RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE, &rail_order->localmovesize);
385 }
386
387 void rail_recv_server_get_appid_resp_order(rdpRailOrder* rail_order, STREAM* s)
388 {
389         rail_read_server_get_appid_resp_order(s, &rail_order->get_appid_resp);
390         rail_send_channel_event(rail_order->plugin,
391                 RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP, &rail_order->get_appid_resp);
392 }
393
394 void rail_recv_langbar_info_order(rdpRailOrder* rail_order, STREAM* s)
395 {
396         rail_read_langbar_info_order(s, &rail_order->langbar_info);
397         rail_send_channel_event(rail_order->plugin,
398                 RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO, &rail_order->langbar_info);
399 }
400
401 void rail_order_recv(rdpRailOrder* rail_order, STREAM* s)
402 {
403         uint16 orderType;
404         uint16 orderLength;
405
406         rail_read_pdu_header(s, &orderType, &orderLength);
407
408         DEBUG_RAIL("Received %s PDU, length:%d",
409                         RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
410
411         switch (orderType)
412         {
413                 case RDP_RAIL_ORDER_HANDSHAKE:
414                         rail_recv_handshake_order(rail_order, s);
415                         break;
416
417                 case RDP_RAIL_ORDER_EXEC_RESULT:
418                         rail_recv_exec_result_order(rail_order, s);
419                         break;
420
421                 case RDP_RAIL_ORDER_SYSPARAM:
422                         rail_recv_server_sysparam_order(rail_order, s);
423                         break;
424
425                 case RDP_RAIL_ORDER_MINMAXINFO:
426                         rail_recv_server_minmaxinfo_order(rail_order, s);
427                         break;
428
429                 case RDP_RAIL_ORDER_LOCALMOVESIZE:
430                         rail_recv_server_localmovesize_order(rail_order, s);
431                         break;
432
433                 case RDP_RAIL_ORDER_GET_APPID_RESP:
434                         rail_recv_server_get_appid_resp_order(rail_order, s);
435                         break;
436
437                 case RDP_RAIL_ORDER_LANGBARINFO:
438                         rail_recv_langbar_info_order(rail_order, s);
439                         break;
440
441                 default:
442                         printf("Unknown RAIL PDU order reveived.");
443                         break;
444         }
445 }
446
447 void rail_send_handshake_order(rdpRailOrder* rail_order)
448 {
449         STREAM* s;
450         s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
451         rail_write_handshake_order(s, &rail_order->handshake);
452         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_HANDSHAKE);
453 }
454
455 void rail_send_client_status_order(rdpRailOrder* rail_order)
456 {
457         STREAM* s;
458         s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH);
459         rail_write_client_status_order(s, &rail_order->client_status);
460         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_CLIENT_STATUS);
461 }
462
463 void rail_send_client_exec_order(rdpRailOrder* rail_order)
464 {
465         STREAM* s;
466         int length;
467
468         length = RAIL_EXEC_ORDER_LENGTH +
469                         rail_order->exec.exeOrFile.length +
470                         rail_order->exec.workingDir.length +
471                         rail_order->exec.arguments.length;
472
473         s = rail_pdu_init(RAIL_EXEC_ORDER_LENGTH);
474         rail_write_client_exec_order(s, &rail_order->exec);
475         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_EXEC);
476 }
477
478 void rail_send_client_sysparam_order(rdpRailOrder* rail_order)
479 {
480         STREAM* s;
481         int length;
482
483         length = RAIL_SYSPARAM_ORDER_LENGTH;
484
485         switch (rail_order->sysparam.param)
486         {
487                 case SPI_SET_DRAG_FULL_WINDOWS:
488                 case SPI_SET_KEYBOARD_CUES:
489                 case SPI_SET_KEYBOARD_PREF:
490                 case SPI_SET_MOUSE_BUTTON_SWAP:
491                         length += 1;
492                         break;
493
494                 case SPI_SET_WORK_AREA:
495                 case SPI_DISPLAY_CHANGE:
496                 case SPI_TASKBAR_POS:
497                         length += 8;
498                         break;
499
500                 case SPI_SET_HIGH_CONTRAST:
501                         length += rail_order->sysparam.highContrast.colorSchemeLength + 10;
502                         break;
503         }
504
505         s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH + 8);
506         rail_write_client_sysparam_order(s, &rail_order->sysparam);
507         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSPARAM);
508 }
509
510 void rail_send_client_sysparams_order(rdpRailOrder* rail_order)
511 {
512         if (rail_order->sysparam.params & SPI_MASK_SET_HIGH_CONTRAST)
513         {
514                 rail_order->sysparam.param = SPI_SET_HIGH_CONTRAST;
515                 rail_send_client_sysparam_order(rail_order);
516         }
517
518         if (rail_order->sysparam.params & SPI_MASK_TASKBAR_POS)
519         {
520                 rail_order->sysparam.param = SPI_TASKBAR_POS;
521                 rail_send_client_sysparam_order(rail_order);
522         }
523
524         if (rail_order->sysparam.params & SPI_MASK_SET_MOUSE_BUTTON_SWAP)
525         {
526                 rail_order->sysparam.param = SPI_SET_MOUSE_BUTTON_SWAP;
527                 rail_send_client_sysparam_order(rail_order);
528         }
529
530         if (rail_order->sysparam.params & SPI_MASK_SET_KEYBOARD_PREF)
531         {
532                 rail_order->sysparam.param = SPI_SET_KEYBOARD_PREF;
533                 rail_send_client_sysparam_order(rail_order);
534         }
535
536         if (rail_order->sysparam.params & SPI_MASK_SET_DRAG_FULL_WINDOWS)
537         {
538                 rail_order->sysparam.param = SPI_SET_DRAG_FULL_WINDOWS;
539                 rail_send_client_sysparam_order(rail_order);
540         }
541
542         if (rail_order->sysparam.params & SPI_MASK_SET_KEYBOARD_CUES)
543         {
544                 rail_order->sysparam.param = SPI_SET_KEYBOARD_CUES;
545                 rail_send_client_sysparam_order(rail_order);
546         }
547
548         if (rail_order->sysparam.params & SPI_MASK_SET_WORK_AREA)
549         {
550                 rail_order->sysparam.param = SPI_SET_WORK_AREA;
551                 rail_send_client_sysparam_order(rail_order);
552         }
553 }
554
555 void rail_send_client_activate_order(rdpRailOrder* rail_order)
556 {
557         STREAM* s;
558         s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
559         rail_write_client_activate_order(s, &rail_order->activate);
560         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_ACTIVATE);
561 }
562
563 void rail_send_client_sysmenu_order(rdpRailOrder* rail_order)
564 {
565         STREAM* s;
566         s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH);
567         rail_write_client_sysmenu_order(s, &rail_order->sysmenu);
568         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSMENU);
569 }
570
571 void rail_send_client_syscommand_order(rdpRailOrder* rail_order)
572 {
573         STREAM* s;
574         s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH);
575         rail_write_client_syscommand_order(s, &rail_order->syscommand);
576         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_SYSCOMMAND);
577 }
578
579 void rail_send_client_notify_event_order(rdpRailOrder* rail_order)
580 {
581         STREAM* s;
582         s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH);
583         rail_write_client_notify_event_order(s, &rail_order->notify_event);
584         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_NOTIFY_EVENT);
585 }
586
587 void rail_send_client_window_move_order(rdpRailOrder* rail_order)
588 {
589         STREAM* s;
590         s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH);
591         rail_write_client_window_move_order(s, &rail_order->window_move);
592         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_WINDOW_MOVE);
593 }
594
595 void rail_send_client_get_appid_req_order(rdpRailOrder* rail_order)
596 {
597         STREAM* s;
598         s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH);
599         rail_write_client_get_appid_req_order(s, &rail_order->get_appid_req);
600         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_GET_APPID_REQ);
601 }
602
603 void rail_send_client_langbar_info_order(rdpRailOrder* rail_order)
604 {
605         STREAM* s;
606         s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
607         rail_write_langbar_info_order(s, &rail_order->langbar_info);
608         rail_send_pdu(rail_order, s, RAIL_ORDER_TYPE_LANGBAR_INFO);
609 }
610
611 rdpRailOrder* rail_order_new()
612 {
613         rdpRailOrder* rail_order;
614
615         rail_order = xnew(rdpRailOrder);
616
617         if (rail_order != NULL)
618         {
619                 rail_order->uniconv = freerdp_uniconv_new();
620         }
621
622         return rail_order;
623 }
624
625 void rail_order_free(rdpRailOrder* rail_order)
626 {
627         if (rail_order != NULL)
628         {
629                 freerdp_uniconv_free(rail_order->uniconv);
630                 xfree(rail_order);
631         }
632 }
633