/src/FreeRDP/channels/rail/rail_common.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * FreeRDP: A Remote Desktop Protocol Implementation |
3 | | * RAIL common functions |
4 | | * |
5 | | * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com> |
6 | | * Copyright 2011 Roman Barabanov <romanbarabanov@gmail.com> |
7 | | * Copyright 2011 Vic Lee |
8 | | * Copyright 2015 Thincast Technologies GmbH |
9 | | * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com> |
10 | | * |
11 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
12 | | * you may not use this file except in compliance with the License. |
13 | | * You may obtain a copy of the License at |
14 | | * |
15 | | * http://www.apache.org/licenses/LICENSE-2.0 |
16 | | * |
17 | | * Unless required by applicable law or agreed to in writing, software |
18 | | * distributed under the License is distributed on an "AS IS" BASIS, |
19 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
20 | | * See the License for the specific language governing permissions and |
21 | | * limitations under the License. |
22 | | */ |
23 | | #include "rail_common.h" |
24 | | |
25 | | #include <winpr/crt.h> |
26 | | #include <freerdp/channels/log.h> |
27 | | |
28 | | #define TAG CHANNELS_TAG("rail.common") |
29 | | |
30 | | const char* rail_get_order_type_string(UINT16 orderType) |
31 | 0 | { |
32 | 0 | switch (orderType) |
33 | 0 | { |
34 | 0 | case TS_RAIL_ORDER_EXEC: |
35 | 0 | return "TS_RAIL_ORDER_EXEC"; |
36 | 0 | case TS_RAIL_ORDER_ACTIVATE: |
37 | 0 | return "TS_RAIL_ORDER_ACTIVATE"; |
38 | 0 | case TS_RAIL_ORDER_SYSPARAM: |
39 | 0 | return "TS_RAIL_ORDER_SYSPARAM"; |
40 | 0 | case TS_RAIL_ORDER_SYSCOMMAND: |
41 | 0 | return "TS_RAIL_ORDER_SYSCOMMAND"; |
42 | 0 | case TS_RAIL_ORDER_HANDSHAKE: |
43 | 0 | return "TS_RAIL_ORDER_HANDSHAKE"; |
44 | 0 | case TS_RAIL_ORDER_NOTIFY_EVENT: |
45 | 0 | return "TS_RAIL_ORDER_NOTIFY_EVENT"; |
46 | 0 | case TS_RAIL_ORDER_WINDOWMOVE: |
47 | 0 | return "TS_RAIL_ORDER_WINDOWMOVE"; |
48 | 0 | case TS_RAIL_ORDER_LOCALMOVESIZE: |
49 | 0 | return "TS_RAIL_ORDER_LOCALMOVESIZE"; |
50 | 0 | case TS_RAIL_ORDER_MINMAXINFO: |
51 | 0 | return "TS_RAIL_ORDER_MINMAXINFO"; |
52 | 0 | case TS_RAIL_ORDER_CLIENTSTATUS: |
53 | 0 | return "TS_RAIL_ORDER_CLIENTSTATUS"; |
54 | 0 | case TS_RAIL_ORDER_SYSMENU: |
55 | 0 | return "TS_RAIL_ORDER_SYSMENU"; |
56 | 0 | case TS_RAIL_ORDER_LANGBARINFO: |
57 | 0 | return "TS_RAIL_ORDER_LANGBARINFO"; |
58 | 0 | case TS_RAIL_ORDER_GET_APPID_REQ: |
59 | 0 | return "TS_RAIL_ORDER_GET_APPID_REQ"; |
60 | 0 | case TS_RAIL_ORDER_GET_APPID_RESP: |
61 | 0 | return "TS_RAIL_ORDER_GET_APPID_RESP"; |
62 | 0 | case TS_RAIL_ORDER_TASKBARINFO: |
63 | 0 | return "TS_RAIL_ORDER_TASKBARINFO"; |
64 | 0 | case TS_RAIL_ORDER_LANGUAGEIMEINFO: |
65 | 0 | return "TS_RAIL_ORDER_LANGUAGEIMEINFO"; |
66 | 0 | case TS_RAIL_ORDER_COMPARTMENTINFO: |
67 | 0 | return "TS_RAIL_ORDER_COMPARTMENTINFO"; |
68 | 0 | case TS_RAIL_ORDER_HANDSHAKE_EX: |
69 | 0 | return "TS_RAIL_ORDER_HANDSHAKE_EX"; |
70 | 0 | case TS_RAIL_ORDER_ZORDER_SYNC: |
71 | 0 | return "TS_RAIL_ORDER_ZORDER_SYNC"; |
72 | 0 | case TS_RAIL_ORDER_CLOAK: |
73 | 0 | return "TS_RAIL_ORDER_CLOAK"; |
74 | 0 | case TS_RAIL_ORDER_POWER_DISPLAY_REQUEST: |
75 | 0 | return "TS_RAIL_ORDER_POWER_DISPLAY_REQUEST"; |
76 | 0 | case TS_RAIL_ORDER_SNAP_ARRANGE: |
77 | 0 | return "TS_RAIL_ORDER_SNAP_ARRANGE"; |
78 | 0 | case TS_RAIL_ORDER_GET_APPID_RESP_EX: |
79 | 0 | return "TS_RAIL_ORDER_GET_APPID_RESP_EX"; |
80 | 0 | case TS_RAIL_ORDER_EXEC_RESULT: |
81 | 0 | return "TS_RAIL_ORDER_EXEC_RESULT"; |
82 | 0 | case TS_RAIL_ORDER_TEXTSCALEINFO: |
83 | 0 | return "TS_RAIL_ORDER_TEXTSCALEINFO"; |
84 | 0 | case TS_RAIL_ORDER_CARETBLINKINFO: |
85 | 0 | return "TS_RAIL_ORDER_CARETBLINKINFO"; |
86 | 0 | default: |
87 | 0 | return "TS_RAIL_ORDER_UNKNOWN"; |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | | const char* rail_get_order_type_string_full(UINT16 orderType, char* buffer, size_t length) |
92 | 0 | { |
93 | 0 | _snprintf(buffer, length, "%s[0x%04" PRIx16 "]", rail_get_order_type_string(orderType), |
94 | 0 | orderType); |
95 | 0 | return buffer; |
96 | 0 | } |
97 | | |
98 | | /** |
99 | | * Function description |
100 | | * |
101 | | * @return 0 on success, otherwise a Win32 error code |
102 | | */ |
103 | | UINT rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength) |
104 | 0 | { |
105 | 0 | if (!s || !orderType || !orderLength) |
106 | 0 | return ERROR_INVALID_PARAMETER; |
107 | | |
108 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) |
109 | 0 | return ERROR_INVALID_DATA; |
110 | | |
111 | 0 | Stream_Read_UINT16(s, *orderType); /* orderType (2 bytes) */ |
112 | 0 | Stream_Read_UINT16(s, *orderLength); /* orderLength (2 bytes) */ |
113 | 0 | return CHANNEL_RC_OK; |
114 | 0 | } |
115 | | |
116 | | void rail_write_pdu_header(wStream* s, UINT16 orderType, UINT16 orderLength) |
117 | 0 | { |
118 | 0 | Stream_Write_UINT16(s, orderType); /* orderType (2 bytes) */ |
119 | 0 | Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */ |
120 | 0 | } |
121 | | |
122 | | wStream* rail_pdu_init(size_t length) |
123 | 0 | { |
124 | 0 | wStream* s = NULL; |
125 | 0 | s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH); |
126 | |
|
127 | 0 | if (!s) |
128 | 0 | return NULL; |
129 | | |
130 | 0 | Stream_Seek(s, RAIL_PDU_HEADER_LENGTH); |
131 | 0 | return s; |
132 | 0 | } |
133 | | |
134 | | /** |
135 | | * Function description |
136 | | * |
137 | | * @return 0 on success, otherwise a Win32 error code |
138 | | */ |
139 | | UINT rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake) |
140 | 0 | { |
141 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) |
142 | 0 | return ERROR_INVALID_DATA; |
143 | | |
144 | 0 | Stream_Read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ |
145 | 0 | return CHANNEL_RC_OK; |
146 | 0 | } |
147 | | |
148 | | void rail_write_handshake_order(wStream* s, const RAIL_HANDSHAKE_ORDER* handshake) |
149 | 0 | { |
150 | 0 | Stream_Write_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */ |
151 | 0 | } |
152 | | |
153 | | /** |
154 | | * Function description |
155 | | * |
156 | | * @return 0 on success, otherwise a Win32 error code |
157 | | */ |
158 | | UINT rail_read_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshakeEx) |
159 | 0 | { |
160 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 8)) |
161 | 0 | return ERROR_INVALID_DATA; |
162 | | |
163 | 0 | Stream_Read_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */ |
164 | 0 | Stream_Read_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */ |
165 | 0 | return CHANNEL_RC_OK; |
166 | 0 | } |
167 | | |
168 | | void rail_write_handshake_ex_order(wStream* s, const RAIL_HANDSHAKE_EX_ORDER* handshakeEx) |
169 | 0 | { |
170 | 0 | Stream_Write_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */ |
171 | 0 | Stream_Write_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */ |
172 | 0 | } |
173 | | |
174 | | /** |
175 | | * Function description |
176 | | * |
177 | | * @return 0 on success, otherwise a Win32 error code |
178 | | */ |
179 | | UINT rail_write_unicode_string(wStream* s, const RAIL_UNICODE_STRING* unicode_string) |
180 | 0 | { |
181 | 0 | if (!s || !unicode_string) |
182 | 0 | return ERROR_INVALID_PARAMETER; |
183 | | |
184 | 0 | if (!Stream_EnsureRemainingCapacity(s, 2 + unicode_string->length)) |
185 | 0 | { |
186 | 0 | WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); |
187 | 0 | return CHANNEL_RC_NO_MEMORY; |
188 | 0 | } |
189 | | |
190 | 0 | Stream_Write_UINT16(s, unicode_string->length); /* cbString (2 bytes) */ |
191 | 0 | Stream_Write(s, unicode_string->string, unicode_string->length); /* string */ |
192 | 0 | return CHANNEL_RC_OK; |
193 | 0 | } |
194 | | |
195 | | /** |
196 | | * Function description |
197 | | * |
198 | | * @return 0 on success, otherwise a Win32 error code |
199 | | */ |
200 | | UINT rail_write_unicode_string_value(wStream* s, const RAIL_UNICODE_STRING* unicode_string) |
201 | 0 | { |
202 | 0 | size_t length = 0; |
203 | |
|
204 | 0 | if (!s || !unicode_string) |
205 | 0 | return ERROR_INVALID_PARAMETER; |
206 | | |
207 | 0 | length = unicode_string->length; |
208 | |
|
209 | 0 | if (length > 0) |
210 | 0 | { |
211 | 0 | if (!Stream_EnsureRemainingCapacity(s, length)) |
212 | 0 | { |
213 | 0 | WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); |
214 | 0 | return CHANNEL_RC_NO_MEMORY; |
215 | 0 | } |
216 | | |
217 | 0 | Stream_Write(s, unicode_string->string, length); /* string */ |
218 | 0 | } |
219 | | |
220 | 0 | return CHANNEL_RC_OK; |
221 | 0 | } |
222 | | |
223 | | /** |
224 | | * Function description |
225 | | * |
226 | | * @return 0 on success, otherwise a Win32 error code |
227 | | */ |
228 | | static UINT rail_read_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast) |
229 | 0 | { |
230 | 0 | if (!s || !highContrast) |
231 | 0 | return ERROR_INVALID_PARAMETER; |
232 | | |
233 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 8)) |
234 | 0 | return ERROR_INVALID_DATA; |
235 | | |
236 | 0 | Stream_Read_UINT32(s, highContrast->flags); /* flags (4 bytes) */ |
237 | 0 | Stream_Read_UINT32(s, highContrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */ |
238 | |
|
239 | 0 | if (!rail_read_unicode_string(s, &highContrast->colorScheme)) /* colorScheme */ |
240 | 0 | return ERROR_INTERNAL_ERROR; |
241 | 0 | return CHANNEL_RC_OK; |
242 | 0 | } |
243 | | |
244 | | /** |
245 | | * Function description |
246 | | * |
247 | | * @return 0 on success, otherwise a Win32 error code |
248 | | */ |
249 | | static UINT rail_write_high_contrast(wStream* s, const RAIL_HIGH_CONTRAST* highContrast) |
250 | 0 | { |
251 | 0 | UINT32 colorSchemeLength = 0; |
252 | |
|
253 | 0 | if (!s || !highContrast) |
254 | 0 | return ERROR_INVALID_PARAMETER; |
255 | | |
256 | 0 | if (!Stream_EnsureRemainingCapacity(s, 8)) |
257 | 0 | return CHANNEL_RC_NO_MEMORY; |
258 | | |
259 | 0 | colorSchemeLength = highContrast->colorScheme.length + 2; |
260 | 0 | Stream_Write_UINT32(s, highContrast->flags); /* flags (4 bytes) */ |
261 | 0 | Stream_Write_UINT32(s, colorSchemeLength); /* colorSchemeLength (4 bytes) */ |
262 | 0 | return rail_write_unicode_string(s, &highContrast->colorScheme); /* colorScheme */ |
263 | 0 | } |
264 | | |
265 | | /** |
266 | | * Function description |
267 | | * |
268 | | * @return 0 on success, otherwise a Win32 error code |
269 | | */ |
270 | | static UINT rail_read_filterkeys(wStream* s, TS_FILTERKEYS* filterKeys) |
271 | 0 | { |
272 | 0 | if (!s || !filterKeys) |
273 | 0 | return ERROR_INVALID_PARAMETER; |
274 | | |
275 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 20)) |
276 | 0 | return ERROR_INVALID_DATA; |
277 | | |
278 | 0 | Stream_Read_UINT32(s, filterKeys->Flags); |
279 | 0 | Stream_Read_UINT32(s, filterKeys->WaitTime); |
280 | 0 | Stream_Read_UINT32(s, filterKeys->DelayTime); |
281 | 0 | Stream_Read_UINT32(s, filterKeys->RepeatTime); |
282 | 0 | Stream_Read_UINT32(s, filterKeys->BounceTime); |
283 | 0 | return CHANNEL_RC_OK; |
284 | 0 | } |
285 | | |
286 | | /** |
287 | | * Function description |
288 | | * |
289 | | * @return 0 on success, otherwise a Win32 error code |
290 | | */ |
291 | | static UINT rail_write_filterkeys(wStream* s, const TS_FILTERKEYS* filterKeys) |
292 | 0 | { |
293 | 0 | if (!s || !filterKeys) |
294 | 0 | return ERROR_INVALID_PARAMETER; |
295 | | |
296 | 0 | if (!Stream_EnsureRemainingCapacity(s, 20)) |
297 | 0 | return CHANNEL_RC_NO_MEMORY; |
298 | | |
299 | 0 | Stream_Write_UINT32(s, filterKeys->Flags); |
300 | 0 | Stream_Write_UINT32(s, filterKeys->WaitTime); |
301 | 0 | Stream_Write_UINT32(s, filterKeys->DelayTime); |
302 | 0 | Stream_Write_UINT32(s, filterKeys->RepeatTime); |
303 | 0 | Stream_Write_UINT32(s, filterKeys->BounceTime); |
304 | 0 | return CHANNEL_RC_OK; |
305 | 0 | } |
306 | | |
307 | | /** |
308 | | * Function description |
309 | | * |
310 | | * @return 0 on success, otherwise a Win32 error code |
311 | | */ |
312 | | UINT rail_read_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam, BOOL extendedSpiSupported) |
313 | 0 | { |
314 | 0 | BYTE body = 0; |
315 | 0 | UINT error = CHANNEL_RC_OK; |
316 | |
|
317 | 0 | if (!s || !sysparam) |
318 | 0 | return ERROR_INVALID_PARAMETER; |
319 | | |
320 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 5)) |
321 | 0 | return ERROR_INVALID_DATA; |
322 | | |
323 | 0 | Stream_Read_UINT32(s, sysparam->param); /* systemParam (4 bytes) */ |
324 | |
|
325 | 0 | sysparam->params = 0; /* bitflags of received params */ |
326 | |
|
327 | 0 | switch (sysparam->param) |
328 | 0 | { |
329 | | /* Client sysparams */ |
330 | 0 | case SPI_SET_DRAG_FULL_WINDOWS: |
331 | 0 | sysparam->params |= SPI_MASK_SET_DRAG_FULL_WINDOWS; |
332 | 0 | Stream_Read_UINT8(s, body); /* body (1 byte) */ |
333 | 0 | sysparam->dragFullWindows = body != 0; |
334 | 0 | break; |
335 | | |
336 | 0 | case SPI_SET_KEYBOARD_CUES: |
337 | 0 | sysparam->params |= SPI_MASK_SET_KEYBOARD_CUES; |
338 | 0 | Stream_Read_UINT8(s, body); /* body (1 byte) */ |
339 | 0 | sysparam->keyboardCues = body != 0; |
340 | 0 | break; |
341 | | |
342 | 0 | case SPI_SET_KEYBOARD_PREF: |
343 | 0 | sysparam->params |= SPI_MASK_SET_KEYBOARD_PREF; |
344 | 0 | Stream_Read_UINT8(s, body); /* body (1 byte) */ |
345 | 0 | sysparam->keyboardPref = body != 0; |
346 | 0 | break; |
347 | | |
348 | 0 | case SPI_SET_MOUSE_BUTTON_SWAP: |
349 | 0 | sysparam->params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP; |
350 | 0 | Stream_Read_UINT8(s, body); /* body (1 byte) */ |
351 | 0 | sysparam->mouseButtonSwap = body != 0; |
352 | 0 | break; |
353 | | |
354 | 0 | case SPI_SET_WORK_AREA: |
355 | 0 | sysparam->params |= SPI_MASK_SET_WORK_AREA; |
356 | |
|
357 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 8)) |
358 | 0 | return ERROR_INVALID_DATA; |
359 | | |
360 | 0 | Stream_Read_UINT16(s, sysparam->workArea.left); /* left (2 bytes) */ |
361 | 0 | Stream_Read_UINT16(s, sysparam->workArea.top); /* top (2 bytes) */ |
362 | 0 | Stream_Read_UINT16(s, sysparam->workArea.right); /* right (2 bytes) */ |
363 | 0 | Stream_Read_UINT16(s, sysparam->workArea.bottom); /* bottom (2 bytes) */ |
364 | 0 | break; |
365 | | |
366 | 0 | case SPI_DISPLAY_CHANGE: |
367 | 0 | sysparam->params |= SPI_MASK_DISPLAY_CHANGE; |
368 | |
|
369 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 8)) |
370 | 0 | return ERROR_INVALID_DATA; |
371 | | |
372 | 0 | Stream_Read_UINT16(s, sysparam->displayChange.left); /* left (2 bytes) */ |
373 | 0 | Stream_Read_UINT16(s, sysparam->displayChange.top); /* top (2 bytes) */ |
374 | 0 | Stream_Read_UINT16(s, sysparam->displayChange.right); /* right (2 bytes) */ |
375 | 0 | Stream_Read_UINT16(s, sysparam->displayChange.bottom); /* bottom (2 bytes) */ |
376 | 0 | break; |
377 | | |
378 | 0 | case SPI_TASKBAR_POS: |
379 | 0 | sysparam->params |= SPI_MASK_TASKBAR_POS; |
380 | |
|
381 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 8)) |
382 | 0 | return ERROR_INVALID_DATA; |
383 | | |
384 | 0 | Stream_Read_UINT16(s, sysparam->taskbarPos.left); /* left (2 bytes) */ |
385 | 0 | Stream_Read_UINT16(s, sysparam->taskbarPos.top); /* top (2 bytes) */ |
386 | 0 | Stream_Read_UINT16(s, sysparam->taskbarPos.right); /* right (2 bytes) */ |
387 | 0 | Stream_Read_UINT16(s, sysparam->taskbarPos.bottom); /* bottom (2 bytes) */ |
388 | 0 | break; |
389 | | |
390 | 0 | case SPI_SET_HIGH_CONTRAST: |
391 | 0 | sysparam->params |= SPI_MASK_SET_HIGH_CONTRAST; |
392 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 8)) |
393 | 0 | return ERROR_INVALID_DATA; |
394 | | |
395 | 0 | error = rail_read_high_contrast(s, &sysparam->highContrast); |
396 | 0 | break; |
397 | | |
398 | 0 | case SPI_SETCARETWIDTH: |
399 | 0 | sysparam->params |= SPI_MASK_SET_CARET_WIDTH; |
400 | |
|
401 | 0 | if (!extendedSpiSupported) |
402 | 0 | return ERROR_INVALID_DATA; |
403 | | |
404 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) |
405 | 0 | return ERROR_INVALID_DATA; |
406 | | |
407 | 0 | Stream_Read_UINT32(s, sysparam->caretWidth); |
408 | |
|
409 | 0 | if (sysparam->caretWidth < 0x0001) |
410 | 0 | return ERROR_INVALID_DATA; |
411 | | |
412 | 0 | break; |
413 | | |
414 | 0 | case SPI_SETSTICKYKEYS: |
415 | 0 | sysparam->params |= SPI_MASK_SET_STICKY_KEYS; |
416 | |
|
417 | 0 | if (!extendedSpiSupported) |
418 | 0 | return ERROR_INVALID_DATA; |
419 | | |
420 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) |
421 | 0 | return ERROR_INVALID_DATA; |
422 | | |
423 | 0 | Stream_Read_UINT32(s, sysparam->stickyKeys); |
424 | 0 | break; |
425 | | |
426 | 0 | case SPI_SETTOGGLEKEYS: |
427 | 0 | sysparam->params |= SPI_MASK_SET_TOGGLE_KEYS; |
428 | |
|
429 | 0 | if (!extendedSpiSupported) |
430 | 0 | return ERROR_INVALID_DATA; |
431 | | |
432 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) |
433 | 0 | return ERROR_INVALID_DATA; |
434 | | |
435 | 0 | Stream_Read_UINT32(s, sysparam->toggleKeys); |
436 | 0 | break; |
437 | | |
438 | 0 | case SPI_SETFILTERKEYS: |
439 | 0 | sysparam->params |= SPI_MASK_SET_FILTER_KEYS; |
440 | |
|
441 | 0 | if (!extendedSpiSupported) |
442 | 0 | return ERROR_INVALID_DATA; |
443 | | |
444 | 0 | if (!Stream_CheckAndLogRequiredLength(TAG, s, 20)) |
445 | 0 | return ERROR_INVALID_DATA; |
446 | | |
447 | 0 | error = rail_read_filterkeys(s, &sysparam->filterKeys); |
448 | 0 | break; |
449 | | |
450 | | /* Server sysparams */ |
451 | 0 | case SPI_SETSCREENSAVEACTIVE: |
452 | 0 | sysparam->params |= SPI_MASK_SET_SCREEN_SAVE_ACTIVE; |
453 | |
|
454 | 0 | Stream_Read_UINT8(s, body); /* body (1 byte) */ |
455 | 0 | sysparam->setScreenSaveActive = body != 0; |
456 | 0 | break; |
457 | | |
458 | 0 | case SPI_SETSCREENSAVESECURE: |
459 | 0 | sysparam->params |= SPI_MASK_SET_SET_SCREEN_SAVE_SECURE; |
460 | |
|
461 | 0 | Stream_Read_UINT8(s, body); /* body (1 byte) */ |
462 | 0 | sysparam->setScreenSaveSecure = body != 0; |
463 | 0 | break; |
464 | | |
465 | 0 | default: |
466 | 0 | break; |
467 | 0 | } |
468 | | |
469 | 0 | return error; |
470 | 0 | } |
471 | | |
472 | | /** |
473 | | * Function description |
474 | | * |
475 | | * @return 0 on success, otherwise a Win32 err2or code |
476 | | */ |
477 | | UINT rail_write_sysparam_order(wStream* s, const RAIL_SYSPARAM_ORDER* sysparam, |
478 | | BOOL extendedSpiSupported) |
479 | 0 | { |
480 | 0 | BYTE body = 0; |
481 | 0 | UINT error = CHANNEL_RC_OK; |
482 | |
|
483 | 0 | if (!s || !sysparam) |
484 | 0 | return ERROR_INVALID_PARAMETER; |
485 | | |
486 | 0 | if (!Stream_EnsureRemainingCapacity(s, 12)) |
487 | 0 | return CHANNEL_RC_NO_MEMORY; |
488 | | |
489 | 0 | Stream_Write_UINT32(s, sysparam->param); /* systemParam (4 bytes) */ |
490 | |
|
491 | 0 | switch (sysparam->param) |
492 | 0 | { |
493 | | /* Client sysparams */ |
494 | 0 | case SPI_SET_DRAG_FULL_WINDOWS: |
495 | 0 | body = sysparam->dragFullWindows ? 1 : 0; |
496 | 0 | Stream_Write_UINT8(s, body); |
497 | 0 | break; |
498 | | |
499 | 0 | case SPI_SET_KEYBOARD_CUES: |
500 | 0 | body = sysparam->keyboardCues ? 1 : 0; |
501 | 0 | Stream_Write_UINT8(s, body); |
502 | 0 | break; |
503 | | |
504 | 0 | case SPI_SET_KEYBOARD_PREF: |
505 | 0 | body = sysparam->keyboardPref ? 1 : 0; |
506 | 0 | Stream_Write_UINT8(s, body); |
507 | 0 | break; |
508 | | |
509 | 0 | case SPI_SET_MOUSE_BUTTON_SWAP: |
510 | 0 | body = sysparam->mouseButtonSwap ? 1 : 0; |
511 | 0 | Stream_Write_UINT8(s, body); |
512 | 0 | break; |
513 | | |
514 | 0 | case SPI_SET_WORK_AREA: |
515 | 0 | Stream_Write_UINT16(s, sysparam->workArea.left); /* left (2 bytes) */ |
516 | 0 | Stream_Write_UINT16(s, sysparam->workArea.top); /* top (2 bytes) */ |
517 | 0 | Stream_Write_UINT16(s, sysparam->workArea.right); /* right (2 bytes) */ |
518 | 0 | Stream_Write_UINT16(s, sysparam->workArea.bottom); /* bottom (2 bytes) */ |
519 | 0 | break; |
520 | | |
521 | 0 | case SPI_DISPLAY_CHANGE: |
522 | 0 | Stream_Write_UINT16(s, sysparam->displayChange.left); /* left (2 bytes) */ |
523 | 0 | Stream_Write_UINT16(s, sysparam->displayChange.top); /* top (2 bytes) */ |
524 | 0 | Stream_Write_UINT16(s, sysparam->displayChange.right); /* right (2 bytes) */ |
525 | 0 | Stream_Write_UINT16(s, sysparam->displayChange.bottom); /* bottom (2 bytes) */ |
526 | 0 | break; |
527 | | |
528 | 0 | case SPI_TASKBAR_POS: |
529 | 0 | Stream_Write_UINT16(s, sysparam->taskbarPos.left); /* left (2 bytes) */ |
530 | 0 | Stream_Write_UINT16(s, sysparam->taskbarPos.top); /* top (2 bytes) */ |
531 | 0 | Stream_Write_UINT16(s, sysparam->taskbarPos.right); /* right (2 bytes) */ |
532 | 0 | Stream_Write_UINT16(s, sysparam->taskbarPos.bottom); /* bottom (2 bytes) */ |
533 | 0 | break; |
534 | | |
535 | 0 | case SPI_SET_HIGH_CONTRAST: |
536 | 0 | error = rail_write_high_contrast(s, &sysparam->highContrast); |
537 | 0 | break; |
538 | | |
539 | 0 | case SPI_SETCARETWIDTH: |
540 | 0 | if (!extendedSpiSupported) |
541 | 0 | return ERROR_INVALID_DATA; |
542 | | |
543 | 0 | if (sysparam->caretWidth < 0x0001) |
544 | 0 | return ERROR_INVALID_DATA; |
545 | | |
546 | 0 | Stream_Write_UINT32(s, sysparam->caretWidth); |
547 | 0 | break; |
548 | | |
549 | 0 | case SPI_SETSTICKYKEYS: |
550 | 0 | if (!extendedSpiSupported) |
551 | 0 | return ERROR_INVALID_DATA; |
552 | | |
553 | 0 | Stream_Write_UINT32(s, sysparam->stickyKeys); |
554 | 0 | break; |
555 | | |
556 | 0 | case SPI_SETTOGGLEKEYS: |
557 | 0 | if (!extendedSpiSupported) |
558 | 0 | return ERROR_INVALID_DATA; |
559 | | |
560 | 0 | Stream_Write_UINT32(s, sysparam->toggleKeys); |
561 | 0 | break; |
562 | | |
563 | 0 | case SPI_SETFILTERKEYS: |
564 | 0 | if (!extendedSpiSupported) |
565 | 0 | return ERROR_INVALID_DATA; |
566 | | |
567 | 0 | error = rail_write_filterkeys(s, &sysparam->filterKeys); |
568 | 0 | break; |
569 | | |
570 | | /* Server sysparams */ |
571 | 0 | case SPI_SETSCREENSAVEACTIVE: |
572 | 0 | body = sysparam->setScreenSaveActive ? 1 : 0; |
573 | 0 | Stream_Write_UINT8(s, body); |
574 | 0 | break; |
575 | | |
576 | 0 | case SPI_SETSCREENSAVESECURE: |
577 | 0 | body = sysparam->setScreenSaveSecure ? 1 : 0; |
578 | 0 | Stream_Write_UINT8(s, body); |
579 | 0 | break; |
580 | | |
581 | 0 | default: |
582 | 0 | return ERROR_INVALID_PARAMETER; |
583 | 0 | } |
584 | | |
585 | 0 | return error; |
586 | 0 | } |
587 | | |
588 | | BOOL rail_is_extended_spi_supported(UINT32 channelFlags) |
589 | 0 | { |
590 | 0 | return (channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED) ? TRUE : FALSE; |
591 | 0 | } |
592 | | |
593 | | const char* rail_handshake_ex_flags_to_string(UINT32 flags, char* buffer, size_t len) |
594 | 0 | { |
595 | 0 | if (len < 1) |
596 | 0 | return NULL; |
597 | | |
598 | 0 | _snprintf(buffer, len, "{"); |
599 | 0 | char* fbuffer = &buffer[1]; |
600 | 0 | len--; |
601 | |
|
602 | 0 | if (flags & TS_RAIL_ORDER_HANDSHAKEEX_FLAGS_HIDEF) |
603 | 0 | winpr_str_append("HIDEF", fbuffer, len, "|"); |
604 | 0 | if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED) |
605 | 0 | winpr_str_append("EXTENDED_SPI_SUPPORTED", fbuffer, len, "|"); |
606 | 0 | if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED) |
607 | 0 | winpr_str_append("SNAP_ARRANGE_SUPPORTED", fbuffer, len, "|"); |
608 | 0 | if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_TEXT_SCALE_SUPPORTED) |
609 | 0 | winpr_str_append("TEXT_SCALE_SUPPORTED", fbuffer, len, "|"); |
610 | 0 | if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_CARET_BLINK_SUPPORTED) |
611 | 0 | winpr_str_append("CARET_BLINK_SUPPORTED", fbuffer, len, "|"); |
612 | 0 | if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_2_SUPPORTED) |
613 | 0 | winpr_str_append("EXTENDED_SPI_2_SUPPORTED", fbuffer, len, "|"); |
614 | |
|
615 | 0 | char number[16] = { 0 }; |
616 | 0 | _snprintf(number, sizeof(number), "[0x%08" PRIx32 "]", flags); |
617 | 0 | winpr_str_append(number, buffer, len, "}"); |
618 | 0 | return buffer; |
619 | 0 | } |