1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * RDP Capability Sets
4 *
5 * Copyright 2011 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 "capabilities.h"
25 #include "fastpath.h"
26
27 #include <winpr/crt.h>
28 #include <winpr/rpc.h>
29
30 #include <freerdp/log.h>
31
32 #define TAG FREERDP_TAG("core.capabilities")
33
34 static const char* const CAPSET_TYPE_STRINGS[] = { "Unknown",
35 "General",
36 "Bitmap",
37 "Order",
38 "Bitmap Cache",
39 "Control",
40 "Unknown",
41 "Window Activation",
42 "Pointer",
43 "Share",
44 "Color Cache",
45 "Unknown",
46 "Sound",
47 "Input",
48 "Font",
49 "Brush",
50 "Glyph Cache",
51 "Offscreen Bitmap Cache",
52 "Bitmap Cache Host Support",
53 "Bitmap Cache v2",
54 "Virtual Channel",
55 "DrawNineGrid Cache",
56 "Draw GDI+ Cache",
57 "Remote Programs",
58 "Window List",
59 "Desktop Composition",
60 "Multifragment Update",
61 "Large Pointer",
62 "Surface Commands",
63 "Bitmap Codecs",
64 "Frame Acknowledge" };
65
get_capability_name(UINT16 type)66 static const char* get_capability_name(UINT16 type)
67 {
68 if (type > CAPSET_TYPE_FRAME_ACKNOWLEDGE)
69 return "<unknown>";
70
71 return CAPSET_TYPE_STRINGS[type];
72 }
73
74 #ifdef WITH_DEBUG_CAPABILITIES
75 static BOOL rdp_print_capability_sets(wStream* s, UINT16 numberCapabilities, BOOL receiving);
76 #endif
77
78 /* CODEC_GUID_REMOTEFX: 0x76772F12BD724463AFB3B73C9C6F7886 */
79
80 static const GUID CODEC_GUID_REMOTEFX = {
81 0x76772F12, 0xBD72, 0x4463, { 0xAF, 0xB3, 0xB7, 0x3C, 0x9C, 0x6F, 0x78, 0x86 }
82 };
83
84 /* CODEC_GUID_NSCODEC 0xCA8D1BB9000F154F589FAE2D1A87E2D6 */
85
86 static const GUID CODEC_GUID_NSCODEC = {
87 0xCA8D1BB9, 0x000F, 0x154F, { 0x58, 0x9F, 0xAE, 0x2D, 0x1A, 0x87, 0xE2, 0xD6 }
88 };
89
90 /* CODEC_GUID_IGNORE 0x9C4351A6353542AE910CCDFCE5760B58 */
91
92 static const GUID CODEC_GUID_IGNORE = {
93 0x9C4351A6, 0x3535, 0x42AE, { 0x91, 0x0C, 0xCD, 0xFC, 0xE5, 0x76, 0x0B, 0x58 }
94 };
95
96 /* CODEC_GUID_IMAGE_REMOTEFX 0x2744CCD49D8A4E74803C0ECBEEA19C54 */
97
98 static const GUID CODEC_GUID_IMAGE_REMOTEFX = {
99 0x2744CCD4, 0x9D8A, 0x4E74, { 0x80, 0x3C, 0x0E, 0xCB, 0xEE, 0xA1, 0x9C, 0x54 }
100 };
101
102 #if defined(WITH_JPEG)
103 /* CODEC_GUID_JPEG 0x430C9EED1BAF4CE6869ACB8B37B66237 */
104
105 static const GUID CODEC_GUID_JPEG = {
106 0x430C9EED, 0x1BAF, 0x4CE6, { 0x86, 0x9A, 0xCB, 0x8B, 0x37, 0xB6, 0x62, 0x37 }
107 };
108 #endif
109
rdp_read_capability_set_header(wStream * s,UINT16 * length,UINT16 * type)110 static BOOL rdp_read_capability_set_header(wStream* s, UINT16* length, UINT16* type)
111 {
112 if (Stream_GetRemainingLength(s) < 4)
113 return FALSE;
114 Stream_Read_UINT16(s, *type); /* capabilitySetType */
115 Stream_Read_UINT16(s, *length); /* lengthCapability */
116 if (*length < 4)
117 return FALSE;
118 return TRUE;
119 }
120
rdp_write_capability_set_header(wStream * s,UINT16 length,UINT16 type)121 static void rdp_write_capability_set_header(wStream* s, UINT16 length, UINT16 type)
122 {
123 Stream_Write_UINT16(s, type); /* capabilitySetType */
124 Stream_Write_UINT16(s, length); /* lengthCapability */
125 }
126
rdp_capability_set_start(wStream * s)127 static size_t rdp_capability_set_start(wStream* s)
128 {
129 size_t header = Stream_GetPosition(s);
130 if (Stream_GetRemainingCapacity(s) < CAPSET_HEADER_LENGTH)
131 return SIZE_MAX;
132 Stream_Zero(s, CAPSET_HEADER_LENGTH);
133 return header;
134 }
135
rdp_capability_set_finish(wStream * s,UINT16 header,UINT16 type)136 static BOOL rdp_capability_set_finish(wStream* s, UINT16 header, UINT16 type)
137 {
138 const size_t footer = Stream_GetPosition(s);
139 const size_t length = footer - header;
140 if ((Stream_Capacity(s) < header + 4ULL) || (length > UINT16_MAX))
141 return FALSE;
142 Stream_SetPosition(s, header);
143 rdp_write_capability_set_header(s, (UINT16)length, type);
144 Stream_SetPosition(s, footer);
145 return TRUE;
146 }
147
148 /**
149 * Read general capability set.\n
150 * @msdn{cc240549}
151 * @param s stream
152 * @param settings settings
153 * @return if the operation completed successfully
154 */
155
rdp_read_general_capability_set(wStream * s,rdpSettings * settings)156 static BOOL rdp_read_general_capability_set(wStream* s, rdpSettings* settings)
157 {
158 UINT16 extraFlags;
159 BYTE refreshRectSupport;
160 BYTE suppressOutputSupport;
161
162 if (Stream_GetRemainingLength(s) < 20)
163 return FALSE;
164
165 if (settings->ServerMode)
166 {
167 Stream_Read_UINT16(s, settings->OsMajorType); /* osMajorType (2 bytes) */
168 Stream_Read_UINT16(s, settings->OsMinorType); /* osMinorType (2 bytes) */
169 }
170 else
171 {
172 Stream_Seek_UINT16(s); /* osMajorType (2 bytes) */
173 Stream_Seek_UINT16(s); /* osMinorType (2 bytes) */
174 }
175
176 Stream_Seek_UINT16(s); /* protocolVersion (2 bytes) */
177 Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */
178 Stream_Seek_UINT16(s); /* generalCompressionTypes (2 bytes) */
179 Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
180 Stream_Seek_UINT16(s); /* updateCapabilityFlag (2 bytes) */
181 Stream_Seek_UINT16(s); /* remoteUnshareFlag (2 bytes) */
182 Stream_Seek_UINT16(s); /* generalCompressionLevel (2 bytes) */
183 Stream_Read_UINT8(s, refreshRectSupport); /* refreshRectSupport (1 byte) */
184 Stream_Read_UINT8(s, suppressOutputSupport); /* suppressOutputSupport (1 byte) */
185 settings->NoBitmapCompressionHeader = (extraFlags & NO_BITMAP_COMPRESSION_HDR) ? TRUE : FALSE;
186 settings->LongCredentialsSupported = (extraFlags & LONG_CREDENTIALS_SUPPORTED) ? TRUE : FALSE;
187
188 if (!(extraFlags & FASTPATH_OUTPUT_SUPPORTED))
189 settings->FastPathOutput = FALSE;
190
191 if (!(extraFlags & ENC_SALTED_CHECKSUM))
192 settings->SaltedChecksum = FALSE;
193
194 if (!settings->ServerMode)
195 {
196 /**
197 * Note: refreshRectSupport and suppressOutputSupport are
198 * server-only flags indicating to the client weather the
199 * respective PDUs are supported. See MS-RDPBCGR 2.2.7.1.1
200 */
201 if (!refreshRectSupport)
202 settings->RefreshRect = FALSE;
203
204 if (!suppressOutputSupport)
205 settings->SuppressOutput = FALSE;
206 }
207
208 return TRUE;
209 }
210
211 /**
212 * Write general capability set.\n
213 * @msdn{cc240549}
214 * @param s stream
215 * @param settings settings
216 */
217
rdp_write_general_capability_set(wStream * s,const rdpSettings * settings)218 static BOOL rdp_write_general_capability_set(wStream* s, const rdpSettings* settings)
219 {
220 size_t header;
221 UINT16 extraFlags;
222
223 if (!Stream_EnsureRemainingCapacity(s, 64))
224 return FALSE;
225
226 header = rdp_capability_set_start(s);
227 if (header > UINT16_MAX)
228 return FALSE;
229 extraFlags = 0;
230
231 if (settings->LongCredentialsSupported)
232 extraFlags |= LONG_CREDENTIALS_SUPPORTED;
233
234 if (settings->NoBitmapCompressionHeader)
235 extraFlags |= NO_BITMAP_COMPRESSION_HDR;
236
237 if (settings->AutoReconnectionEnabled)
238 extraFlags |= AUTORECONNECT_SUPPORTED;
239
240 if (settings->FastPathOutput)
241 extraFlags |= FASTPATH_OUTPUT_SUPPORTED;
242
243 if (settings->SaltedChecksum)
244 extraFlags |= ENC_SALTED_CHECKSUM;
245
246 if ((settings->OsMajorType > UINT16_MAX) || (settings->OsMinorType > UINT16_MAX))
247 {
248 WLog_ERR(TAG,
249 "OsMajorType=%08" PRIx32 ", OsMinorType=%08" PRIx32
250 " they need to be smaller %04" PRIx16,
251 settings->OsMajorType, settings->OsMinorType, UINT16_MAX);
252 return FALSE;
253 }
254 Stream_Write_UINT16(s, (UINT16)settings->OsMajorType); /* osMajorType (2 bytes) */
255 Stream_Write_UINT16(s, (UINT16)settings->OsMinorType); /* osMinorType (2 bytes) */
256 Stream_Write_UINT16(s, CAPS_PROTOCOL_VERSION); /* protocolVersion (2 bytes) */
257 Stream_Write_UINT16(s, 0); /* pad2OctetsA (2 bytes) */
258 Stream_Write_UINT16(s, 0); /* generalCompressionTypes (2 bytes) */
259 Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
260 Stream_Write_UINT16(s, 0); /* updateCapabilityFlag (2 bytes) */
261 Stream_Write_UINT16(s, 0); /* remoteUnshareFlag (2 bytes) */
262 Stream_Write_UINT16(s, 0); /* generalCompressionLevel (2 bytes) */
263 Stream_Write_UINT8(s, settings->RefreshRect ? 1 : 0); /* refreshRectSupport (1 byte) */
264 Stream_Write_UINT8(s, settings->SuppressOutput ? 1 : 0); /* suppressOutputSupport (1 byte) */
265 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_GENERAL);
266 }
267
268 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_general_capability_set(wStream * s)269 static BOOL rdp_print_general_capability_set(wStream* s)
270 {
271 UINT16 osMajorType;
272 UINT16 osMinorType;
273 UINT16 protocolVersion;
274 UINT16 pad2OctetsA;
275 UINT16 generalCompressionTypes;
276 UINT16 extraFlags;
277 UINT16 updateCapabilityFlag;
278 UINT16 remoteUnshareFlag;
279 UINT16 generalCompressionLevel;
280 BYTE refreshRectSupport;
281 BYTE suppressOutputSupport;
282
283 if (Stream_GetRemainingLength(s) < 20)
284 return FALSE;
285
286 WLog_INFO(TAG, "GeneralCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
287 Stream_Read_UINT16(s, osMajorType); /* osMajorType (2 bytes) */
288 Stream_Read_UINT16(s, osMinorType); /* osMinorType (2 bytes) */
289 Stream_Read_UINT16(s, protocolVersion); /* protocolVersion (2 bytes) */
290 Stream_Read_UINT16(s, pad2OctetsA); /* pad2OctetsA (2 bytes) */
291 Stream_Read_UINT16(s, generalCompressionTypes); /* generalCompressionTypes (2 bytes) */
292 Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
293 Stream_Read_UINT16(s, updateCapabilityFlag); /* updateCapabilityFlag (2 bytes) */
294 Stream_Read_UINT16(s, remoteUnshareFlag); /* remoteUnshareFlag (2 bytes) */
295 Stream_Read_UINT16(s, generalCompressionLevel); /* generalCompressionLevel (2 bytes) */
296 Stream_Read_UINT8(s, refreshRectSupport); /* refreshRectSupport (1 byte) */
297 Stream_Read_UINT8(s, suppressOutputSupport); /* suppressOutputSupport (1 byte) */
298 WLog_INFO(TAG, "\tosMajorType: 0x%04" PRIX16 "", osMajorType);
299 WLog_INFO(TAG, "\tosMinorType: 0x%04" PRIX16 "", osMinorType);
300 WLog_INFO(TAG, "\tprotocolVersion: 0x%04" PRIX16 "", protocolVersion);
301 WLog_INFO(TAG, "\tpad2OctetsA: 0x%04" PRIX16 "", pad2OctetsA);
302 WLog_INFO(TAG, "\tgeneralCompressionTypes: 0x%04" PRIX16 "", generalCompressionTypes);
303 WLog_INFO(TAG, "\textraFlags: 0x%04" PRIX16 "", extraFlags);
304 WLog_INFO(TAG, "\tupdateCapabilityFlag: 0x%04" PRIX16 "", updateCapabilityFlag);
305 WLog_INFO(TAG, "\tremoteUnshareFlag: 0x%04" PRIX16 "", remoteUnshareFlag);
306 WLog_INFO(TAG, "\tgeneralCompressionLevel: 0x%04" PRIX16 "", generalCompressionLevel);
307 WLog_INFO(TAG, "\trefreshRectSupport: 0x%02" PRIX8 "", refreshRectSupport);
308 WLog_INFO(TAG, "\tsuppressOutputSupport: 0x%02" PRIX8 "", suppressOutputSupport);
309 return TRUE;
310 }
311 #endif
312
313 /**
314 * Read bitmap capability set.\n
315 * @msdn{cc240554}
316 * @param s stream
317 * @param settings settings
318 * @return if the operation completed successfully
319 */
320
rdp_read_bitmap_capability_set(wStream * s,rdpSettings * settings)321 static BOOL rdp_read_bitmap_capability_set(wStream* s, rdpSettings* settings)
322 {
323 BYTE drawingFlags;
324 UINT16 desktopWidth;
325 UINT16 desktopHeight;
326 UINT16 desktopResizeFlag;
327 UINT16 preferredBitsPerPixel;
328
329 if (Stream_GetRemainingLength(s) < 24)
330 return FALSE;
331
332 Stream_Read_UINT16(s, preferredBitsPerPixel); /* preferredBitsPerPixel (2 bytes) */
333 Stream_Seek_UINT16(s); /* receive1BitPerPixel (2 bytes) */
334 Stream_Seek_UINT16(s); /* receive4BitsPerPixel (2 bytes) */
335 Stream_Seek_UINT16(s); /* receive8BitsPerPixel (2 bytes) */
336 Stream_Read_UINT16(s, desktopWidth); /* desktopWidth (2 bytes) */
337 Stream_Read_UINT16(s, desktopHeight); /* desktopHeight (2 bytes) */
338 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
339 Stream_Read_UINT16(s, desktopResizeFlag); /* desktopResizeFlag (2 bytes) */
340 Stream_Seek_UINT16(s); /* bitmapCompressionFlag (2 bytes) */
341 Stream_Seek_UINT8(s); /* highColorFlags (1 byte) */
342 Stream_Read_UINT8(s, drawingFlags); /* drawingFlags (1 byte) */
343 Stream_Seek_UINT16(s); /* multipleRectangleSupport (2 bytes) */
344 Stream_Seek_UINT16(s); /* pad2OctetsB (2 bytes) */
345
346 if (!settings->ServerMode && (preferredBitsPerPixel != settings->ColorDepth))
347 {
348 /* The client must respect the actual color depth used by the server */
349 settings->ColorDepth = preferredBitsPerPixel;
350 }
351
352 if (desktopResizeFlag == FALSE)
353 settings->DesktopResize = FALSE;
354
355 if (!settings->ServerMode && settings->DesktopResize)
356 {
357 /* The server may request a different desktop size during Deactivation-Reactivation sequence
358 */
359 settings->DesktopWidth = desktopWidth;
360 settings->DesktopHeight = desktopHeight;
361 }
362
363 if (settings->DrawAllowSkipAlpha)
364 settings->DrawAllowSkipAlpha = (drawingFlags & DRAW_ALLOW_SKIP_ALPHA) ? TRUE : FALSE;
365
366 if (settings->DrawAllowDynamicColorFidelity)
367 settings->DrawAllowDynamicColorFidelity =
368 (drawingFlags & DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY) ? TRUE : FALSE;
369
370 if (settings->DrawAllowColorSubsampling)
371 settings->DrawAllowColorSubsampling =
372 (drawingFlags & DRAW_ALLOW_COLOR_SUBSAMPLING) ? TRUE : FALSE;
373
374 return TRUE;
375 }
376
377 /**
378 * Write bitmap capability set.\n
379 * @msdn{cc240554}
380 * @param s stream
381 * @param settings settings
382 */
383
rdp_write_bitmap_capability_set(wStream * s,const rdpSettings * settings)384 static BOOL rdp_write_bitmap_capability_set(wStream* s, const rdpSettings* settings)
385 {
386 size_t header;
387 BYTE drawingFlags = 0;
388 UINT16 preferredBitsPerPixel;
389
390 if (!Stream_EnsureRemainingCapacity(s, 64))
391 return FALSE;
392
393 header = rdp_capability_set_start(s);
394 if (header > UINT16_MAX)
395 return FALSE;
396 if (settings->DrawAllowSkipAlpha)
397 drawingFlags |= DRAW_ALLOW_SKIP_ALPHA;
398
399 if (settings->DrawAllowDynamicColorFidelity)
400 drawingFlags |= DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY;
401
402 if (settings->DrawAllowColorSubsampling)
403 drawingFlags |= DRAW_ALLOW_COLOR_SUBSAMPLING; /* currently unimplemented */
404
405 /* While bitmap_decode.c now implements YCoCg, in turning it
406 * on we have found Microsoft is inconsistent on whether to invert R & B.
407 * And it's not only from one server to another; on Win7/2008R2, it appears
408 * to send the main content with a different inversion than the Windows
409 * button! So... don't advertise that we support YCoCg and the server
410 * will not send it. YCoCg is still needed for EGFX, but it at least
411 * appears consistent in its use.
412 */
413
414 if ((settings->ColorDepth > UINT16_MAX) || (settings->DesktopWidth > UINT16_MAX) ||
415 (settings->DesktopHeight > UINT16_MAX))
416 return FALSE;
417
418 if (settings->RdpVersion >= RDP_VERSION_5_PLUS)
419 preferredBitsPerPixel = (UINT16)settings->ColorDepth;
420 else
421 preferredBitsPerPixel = 8;
422
423 Stream_Write_UINT16(s, preferredBitsPerPixel); /* preferredBitsPerPixel (2 bytes) */
424 Stream_Write_UINT16(s, 1); /* receive1BitPerPixel (2 bytes) */
425 Stream_Write_UINT16(s, 1); /* receive4BitsPerPixel (2 bytes) */
426 Stream_Write_UINT16(s, 1); /* receive8BitsPerPixel (2 bytes) */
427 Stream_Write_UINT16(s, (UINT16)settings->DesktopWidth); /* desktopWidth (2 bytes) */
428 Stream_Write_UINT16(s, (UINT16)settings->DesktopHeight); /* desktopHeight (2 bytes) */
429 Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
430 Stream_Write_UINT16(s, (UINT16)settings->DesktopResize); /* desktopResizeFlag (2 bytes) */
431 Stream_Write_UINT16(s, 1); /* bitmapCompressionFlag (2 bytes) */
432 Stream_Write_UINT8(s, 0); /* highColorFlags (1 byte) */
433 Stream_Write_UINT8(s, drawingFlags); /* drawingFlags (1 byte) */
434 Stream_Write_UINT16(s, 1); /* multipleRectangleSupport (2 bytes) */
435 Stream_Write_UINT16(s, 0); /* pad2OctetsB (2 bytes) */
436 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP);
437 }
438
439 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_bitmap_capability_set(wStream * s)440 static BOOL rdp_print_bitmap_capability_set(wStream* s)
441 {
442 UINT16 preferredBitsPerPixel;
443 UINT16 receive1BitPerPixel;
444 UINT16 receive4BitsPerPixel;
445 UINT16 receive8BitsPerPixel;
446 UINT16 desktopWidth;
447 UINT16 desktopHeight;
448 UINT16 pad2Octets;
449 UINT16 desktopResizeFlag;
450 UINT16 bitmapCompressionFlag;
451 BYTE highColorFlags;
452 BYTE drawingFlags;
453 UINT16 multipleRectangleSupport;
454 UINT16 pad2OctetsB;
455 WLog_INFO(TAG, "BitmapCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
456
457 if (Stream_GetRemainingLength(s) < 24)
458 return FALSE;
459
460 Stream_Read_UINT16(s, preferredBitsPerPixel); /* preferredBitsPerPixel (2 bytes) */
461 Stream_Read_UINT16(s, receive1BitPerPixel); /* receive1BitPerPixel (2 bytes) */
462 Stream_Read_UINT16(s, receive4BitsPerPixel); /* receive4BitsPerPixel (2 bytes) */
463 Stream_Read_UINT16(s, receive8BitsPerPixel); /* receive8BitsPerPixel (2 bytes) */
464 Stream_Read_UINT16(s, desktopWidth); /* desktopWidth (2 bytes) */
465 Stream_Read_UINT16(s, desktopHeight); /* desktopHeight (2 bytes) */
466 Stream_Read_UINT16(s, pad2Octets); /* pad2Octets (2 bytes) */
467 Stream_Read_UINT16(s, desktopResizeFlag); /* desktopResizeFlag (2 bytes) */
468 Stream_Read_UINT16(s, bitmapCompressionFlag); /* bitmapCompressionFlag (2 bytes) */
469 Stream_Read_UINT8(s, highColorFlags); /* highColorFlags (1 byte) */
470 Stream_Read_UINT8(s, drawingFlags); /* drawingFlags (1 byte) */
471 Stream_Read_UINT16(s, multipleRectangleSupport); /* multipleRectangleSupport (2 bytes) */
472 Stream_Read_UINT16(s, pad2OctetsB); /* pad2OctetsB (2 bytes) */
473 WLog_INFO(TAG, "\tpreferredBitsPerPixel: 0x%04" PRIX16 "", preferredBitsPerPixel);
474 WLog_INFO(TAG, "\treceive1BitPerPixel: 0x%04" PRIX16 "", receive1BitPerPixel);
475 WLog_INFO(TAG, "\treceive4BitsPerPixel: 0x%04" PRIX16 "", receive4BitsPerPixel);
476 WLog_INFO(TAG, "\treceive8BitsPerPixel: 0x%04" PRIX16 "", receive8BitsPerPixel);
477 WLog_INFO(TAG, "\tdesktopWidth: 0x%04" PRIX16 "", desktopWidth);
478 WLog_INFO(TAG, "\tdesktopHeight: 0x%04" PRIX16 "", desktopHeight);
479 WLog_INFO(TAG, "\tpad2Octets: 0x%04" PRIX16 "", pad2Octets);
480 WLog_INFO(TAG, "\tdesktopResizeFlag: 0x%04" PRIX16 "", desktopResizeFlag);
481 WLog_INFO(TAG, "\tbitmapCompressionFlag: 0x%04" PRIX16 "", bitmapCompressionFlag);
482 WLog_INFO(TAG, "\thighColorFlags: 0x%02" PRIX8 "", highColorFlags);
483 WLog_INFO(TAG, "\tdrawingFlags: 0x%02" PRIX8 "", drawingFlags);
484 WLog_INFO(TAG, "\tmultipleRectangleSupport: 0x%04" PRIX16 "", multipleRectangleSupport);
485 WLog_INFO(TAG, "\tpad2OctetsB: 0x%04" PRIX16 "", pad2OctetsB);
486 return TRUE;
487 }
488 #endif
489
490 /**
491 * Read order capability set.\n
492 * @msdn{cc240556}
493 * @param s stream
494 * @param settings settings
495 * @return if the operation completed successfully
496 */
497
rdp_read_order_capability_set(wStream * s,rdpSettings * settings)498 static BOOL rdp_read_order_capability_set(wStream* s, rdpSettings* settings)
499 {
500 int i;
501 UINT16 orderFlags;
502 BYTE orderSupport[32];
503 UINT16 orderSupportExFlags;
504 BOOL BitmapCacheV3Enabled = FALSE;
505 BOOL FrameMarkerCommandEnabled = FALSE;
506
507 if (Stream_GetRemainingLength(s) < 84)
508 return FALSE;
509
510 Stream_Seek(s, 16); /* terminalDescriptor (16 bytes) */
511 Stream_Seek_UINT32(s); /* pad4OctetsA (4 bytes) */
512 Stream_Seek_UINT16(s); /* desktopSaveXGranularity (2 bytes) */
513 Stream_Seek_UINT16(s); /* desktopSaveYGranularity (2 bytes) */
514 Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */
515 Stream_Seek_UINT16(s); /* maximumOrderLevel (2 bytes) */
516 Stream_Seek_UINT16(s); /* numberFonts (2 bytes) */
517 Stream_Read_UINT16(s, orderFlags); /* orderFlags (2 bytes) */
518 Stream_Read(s, orderSupport, 32); /* orderSupport (32 bytes) */
519 Stream_Seek_UINT16(s); /* textFlags (2 bytes) */
520 Stream_Read_UINT16(s, orderSupportExFlags); /* orderSupportExFlags (2 bytes) */
521 Stream_Seek_UINT32(s); /* pad4OctetsB (4 bytes) */
522 Stream_Seek_UINT32(s); /* desktopSaveSize (4 bytes) */
523 Stream_Seek_UINT16(s); /* pad2OctetsC (2 bytes) */
524 Stream_Seek_UINT16(s); /* pad2OctetsD (2 bytes) */
525 Stream_Seek_UINT16(s); /* textANSICodePage (2 bytes) */
526 Stream_Seek_UINT16(s); /* pad2OctetsE (2 bytes) */
527
528 for (i = 0; i < 32; i++)
529 {
530 if (orderSupport[i] == FALSE)
531 settings->OrderSupport[i] = FALSE;
532 }
533
534 if (orderFlags & ORDER_FLAGS_EXTRA_SUPPORT)
535 {
536 if (orderSupportExFlags & CACHE_BITMAP_V3_SUPPORT)
537 BitmapCacheV3Enabled = TRUE;
538
539 if (orderSupportExFlags & ALTSEC_FRAME_MARKER_SUPPORT)
540 FrameMarkerCommandEnabled = TRUE;
541 }
542
543 if (settings->BitmapCacheV3Enabled && BitmapCacheV3Enabled)
544 settings->BitmapCacheVersion = 3;
545 else
546 settings->BitmapCacheV3Enabled = FALSE;
547
548 if (settings->FrameMarkerCommandEnabled && !FrameMarkerCommandEnabled)
549 settings->FrameMarkerCommandEnabled = FALSE;
550
551 return TRUE;
552 }
553
554 /**
555 * Write order capability set.\n
556 * @msdn{cc240556}
557 * @param s stream
558 * @param settings settings
559 */
560
rdp_write_order_capability_set(wStream * s,const rdpSettings * settings)561 static BOOL rdp_write_order_capability_set(wStream* s, const rdpSettings* settings)
562 {
563 size_t header;
564 UINT16 orderFlags;
565 UINT16 orderSupportExFlags;
566 UINT16 textANSICodePage = 0;
567
568 if (!Stream_EnsureRemainingCapacity(s, 64))
569 return FALSE;
570
571 header = rdp_capability_set_start(s);
572 if (header > UINT16_MAX)
573 return FALSE;
574 /* see [MSDN-CP]: http://msdn.microsoft.com/en-us/library/dd317756 */
575 if (!settings->ServerMode)
576 textANSICodePage = CP_UTF8; /* Unicode (UTF-8) */
577
578 orderSupportExFlags = 0;
579 orderFlags = NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT | COLOR_INDEX_SUPPORT;
580
581 if (settings->BitmapCacheV3Enabled)
582 {
583 orderSupportExFlags |= CACHE_BITMAP_V3_SUPPORT;
584 orderFlags |= ORDER_FLAGS_EXTRA_SUPPORT;
585 }
586
587 if (settings->FrameMarkerCommandEnabled)
588 {
589 orderSupportExFlags |= ALTSEC_FRAME_MARKER_SUPPORT;
590 orderFlags |= ORDER_FLAGS_EXTRA_SUPPORT;
591 }
592
593 Stream_Zero(s, 16); /* terminalDescriptor (16 bytes) */
594 Stream_Write_UINT32(s, 0); /* pad4OctetsA (4 bytes) */
595 Stream_Write_UINT16(s, 1); /* desktopSaveXGranularity (2 bytes) */
596 Stream_Write_UINT16(s, 20); /* desktopSaveYGranularity (2 bytes) */
597 Stream_Write_UINT16(s, 0); /* pad2OctetsA (2 bytes) */
598 Stream_Write_UINT16(s, 1); /* maximumOrderLevel (2 bytes) */
599 Stream_Write_UINT16(s, 0); /* numberFonts (2 bytes) */
600 Stream_Write_UINT16(s, orderFlags); /* orderFlags (2 bytes) */
601 Stream_Write(s, settings->OrderSupport, 32); /* orderSupport (32 bytes) */
602 Stream_Write_UINT16(s, 0); /* textFlags (2 bytes) */
603 Stream_Write_UINT16(s, orderSupportExFlags); /* orderSupportExFlags (2 bytes) */
604 Stream_Write_UINT32(s, 0); /* pad4OctetsB (4 bytes) */
605 Stream_Write_UINT32(s, 230400); /* desktopSaveSize (4 bytes) */
606 Stream_Write_UINT16(s, 0); /* pad2OctetsC (2 bytes) */
607 Stream_Write_UINT16(s, 0); /* pad2OctetsD (2 bytes) */
608 Stream_Write_UINT16(s, textANSICodePage); /* textANSICodePage (2 bytes) */
609 Stream_Write_UINT16(s, 0); /* pad2OctetsE (2 bytes) */
610 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_ORDER);
611 }
612
613 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_order_capability_set(wStream * s)614 static BOOL rdp_print_order_capability_set(wStream* s)
615 {
616 BYTE terminalDescriptor[16];
617 UINT32 pad4OctetsA;
618 UINT16 desktopSaveXGranularity;
619 UINT16 desktopSaveYGranularity;
620 UINT16 pad2OctetsA;
621 UINT16 maximumOrderLevel;
622 UINT16 numberFonts;
623 UINT16 orderFlags;
624 BYTE orderSupport[32];
625 UINT16 textFlags;
626 UINT16 orderSupportExFlags;
627 UINT32 pad4OctetsB;
628 UINT32 desktopSaveSize;
629 UINT16 pad2OctetsC;
630 UINT16 pad2OctetsD;
631 UINT16 textANSICodePage;
632 UINT16 pad2OctetsE;
633 WLog_INFO(TAG, "OrderCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
634
635 if (Stream_GetRemainingLength(s) < 84)
636 return FALSE;
637
638 Stream_Read(s, terminalDescriptor, 16); /* terminalDescriptor (16 bytes) */
639 Stream_Read_UINT32(s, pad4OctetsA); /* pad4OctetsA (4 bytes) */
640 Stream_Read_UINT16(s, desktopSaveXGranularity); /* desktopSaveXGranularity (2 bytes) */
641 Stream_Read_UINT16(s, desktopSaveYGranularity); /* desktopSaveYGranularity (2 bytes) */
642 Stream_Read_UINT16(s, pad2OctetsA); /* pad2OctetsA (2 bytes) */
643 Stream_Read_UINT16(s, maximumOrderLevel); /* maximumOrderLevel (2 bytes) */
644 Stream_Read_UINT16(s, numberFonts); /* numberFonts (2 bytes) */
645 Stream_Read_UINT16(s, orderFlags); /* orderFlags (2 bytes) */
646 Stream_Read(s, orderSupport, 32); /* orderSupport (32 bytes) */
647 Stream_Read_UINT16(s, textFlags); /* textFlags (2 bytes) */
648 Stream_Read_UINT16(s, orderSupportExFlags); /* orderSupportExFlags (2 bytes) */
649 Stream_Read_UINT32(s, pad4OctetsB); /* pad4OctetsB (4 bytes) */
650 Stream_Read_UINT32(s, desktopSaveSize); /* desktopSaveSize (4 bytes) */
651 Stream_Read_UINT16(s, pad2OctetsC); /* pad2OctetsC (2 bytes) */
652 Stream_Read_UINT16(s, pad2OctetsD); /* pad2OctetsD (2 bytes) */
653 Stream_Read_UINT16(s, textANSICodePage); /* textANSICodePage (2 bytes) */
654 Stream_Read_UINT16(s, pad2OctetsE); /* pad2OctetsE (2 bytes) */
655 WLog_INFO(TAG, "\tpad4OctetsA: 0x%08" PRIX32 "", pad4OctetsA);
656 WLog_INFO(TAG, "\tdesktopSaveXGranularity: 0x%04" PRIX16 "", desktopSaveXGranularity);
657 WLog_INFO(TAG, "\tdesktopSaveYGranularity: 0x%04" PRIX16 "", desktopSaveYGranularity);
658 WLog_INFO(TAG, "\tpad2OctetsA: 0x%04" PRIX16 "", pad2OctetsA);
659 WLog_INFO(TAG, "\tmaximumOrderLevel: 0x%04" PRIX16 "", maximumOrderLevel);
660 WLog_INFO(TAG, "\tnumberFonts: 0x%04" PRIX16 "", numberFonts);
661 WLog_INFO(TAG, "\torderFlags: 0x%04" PRIX16 "", orderFlags);
662 WLog_INFO(TAG, "\torderSupport:");
663 WLog_INFO(TAG, "\t\tDSTBLT: %" PRIu8 "", orderSupport[NEG_DSTBLT_INDEX]);
664 WLog_INFO(TAG, "\t\tPATBLT: %" PRIu8 "", orderSupport[NEG_PATBLT_INDEX]);
665 WLog_INFO(TAG, "\t\tSCRBLT: %" PRIu8 "", orderSupport[NEG_SCRBLT_INDEX]);
666 WLog_INFO(TAG, "\t\tMEMBLT: %" PRIu8 "", orderSupport[NEG_MEMBLT_INDEX]);
667 WLog_INFO(TAG, "\t\tMEM3BLT: %" PRIu8 "", orderSupport[NEG_MEM3BLT_INDEX]);
668 WLog_INFO(TAG, "\t\tATEXTOUT: %" PRIu8 "", orderSupport[NEG_ATEXTOUT_INDEX]);
669 WLog_INFO(TAG, "\t\tAEXTTEXTOUT: %" PRIu8 "", orderSupport[NEG_AEXTTEXTOUT_INDEX]);
670 WLog_INFO(TAG, "\t\tDRAWNINEGRID: %" PRIu8 "", orderSupport[NEG_DRAWNINEGRID_INDEX]);
671 WLog_INFO(TAG, "\t\tLINETO: %" PRIu8 "", orderSupport[NEG_LINETO_INDEX]);
672 WLog_INFO(TAG, "\t\tMULTI_DRAWNINEGRID: %" PRIu8 "",
673 orderSupport[NEG_MULTI_DRAWNINEGRID_INDEX]);
674 WLog_INFO(TAG, "\t\tOPAQUE_RECT: %" PRIu8 "", orderSupport[NEG_OPAQUE_RECT_INDEX]);
675 WLog_INFO(TAG, "\t\tSAVEBITMAP: %" PRIu8 "", orderSupport[NEG_SAVEBITMAP_INDEX]);
676 WLog_INFO(TAG, "\t\tWTEXTOUT: %" PRIu8 "", orderSupport[NEG_WTEXTOUT_INDEX]);
677 WLog_INFO(TAG, "\t\tMEMBLT_V2: %" PRIu8 "", orderSupport[NEG_MEMBLT_V2_INDEX]);
678 WLog_INFO(TAG, "\t\tMEM3BLT_V2: %" PRIu8 "", orderSupport[NEG_MEM3BLT_V2_INDEX]);
679 WLog_INFO(TAG, "\t\tMULTIDSTBLT: %" PRIu8 "", orderSupport[NEG_MULTIDSTBLT_INDEX]);
680 WLog_INFO(TAG, "\t\tMULTIPATBLT: %" PRIu8 "", orderSupport[NEG_MULTIPATBLT_INDEX]);
681 WLog_INFO(TAG, "\t\tMULTISCRBLT: %" PRIu8 "", orderSupport[NEG_MULTISCRBLT_INDEX]);
682 WLog_INFO(TAG, "\t\tMULTIOPAQUERECT: %" PRIu8 "", orderSupport[NEG_MULTIOPAQUERECT_INDEX]);
683 WLog_INFO(TAG, "\t\tFAST_INDEX: %" PRIu8 "", orderSupport[NEG_FAST_INDEX_INDEX]);
684 WLog_INFO(TAG, "\t\tPOLYGON_SC: %" PRIu8 "", orderSupport[NEG_POLYGON_SC_INDEX]);
685 WLog_INFO(TAG, "\t\tPOLYGON_CB: %" PRIu8 "", orderSupport[NEG_POLYGON_CB_INDEX]);
686 WLog_INFO(TAG, "\t\tPOLYLINE: %" PRIu8 "", orderSupport[NEG_POLYLINE_INDEX]);
687 WLog_INFO(TAG, "\t\tUNUSED23: %" PRIu8 "", orderSupport[NEG_UNUSED23_INDEX]);
688 WLog_INFO(TAG, "\t\tFAST_GLYPH: %" PRIu8 "", orderSupport[NEG_FAST_GLYPH_INDEX]);
689 WLog_INFO(TAG, "\t\tELLIPSE_SC: %" PRIu8 "", orderSupport[NEG_ELLIPSE_SC_INDEX]);
690 WLog_INFO(TAG, "\t\tELLIPSE_CB: %" PRIu8 "", orderSupport[NEG_ELLIPSE_CB_INDEX]);
691 WLog_INFO(TAG, "\t\tGLYPH_INDEX: %" PRIu8 "", orderSupport[NEG_GLYPH_INDEX_INDEX]);
692 WLog_INFO(TAG, "\t\tGLYPH_WEXTTEXTOUT: %" PRIu8 "", orderSupport[NEG_GLYPH_WEXTTEXTOUT_INDEX]);
693 WLog_INFO(TAG, "\t\tGLYPH_WLONGTEXTOUT: %" PRIu8 "",
694 orderSupport[NEG_GLYPH_WLONGTEXTOUT_INDEX]);
695 WLog_INFO(TAG, "\t\tGLYPH_WLONGEXTTEXTOUT: %" PRIu8 "",
696 orderSupport[NEG_GLYPH_WLONGEXTTEXTOUT_INDEX]);
697 WLog_INFO(TAG, "\t\tUNUSED31: %" PRIu8 "", orderSupport[NEG_UNUSED31_INDEX]);
698 WLog_INFO(TAG, "\ttextFlags: 0x%04" PRIX16 "", textFlags);
699 WLog_INFO(TAG, "\torderSupportExFlags: 0x%04" PRIX16 "", orderSupportExFlags);
700 WLog_INFO(TAG, "\tpad4OctetsB: 0x%08" PRIX32 "", pad4OctetsB);
701 WLog_INFO(TAG, "\tdesktopSaveSize: 0x%08" PRIX32 "", desktopSaveSize);
702 WLog_INFO(TAG, "\tpad2OctetsC: 0x%04" PRIX16 "", pad2OctetsC);
703 WLog_INFO(TAG, "\tpad2OctetsD: 0x%04" PRIX16 "", pad2OctetsD);
704 WLog_INFO(TAG, "\ttextANSICodePage: 0x%04" PRIX16 "", textANSICodePage);
705 WLog_INFO(TAG, "\tpad2OctetsE: 0x%04" PRIX16 "", pad2OctetsE);
706 return TRUE;
707 }
708 #endif
709
710 /**
711 * Read bitmap cache capability set.\n
712 * @msdn{cc240559}
713 * @param s stream
714 * @param settings settings
715 * @return if the operation completed successfully
716 */
717
rdp_read_bitmap_cache_capability_set(wStream * s,rdpSettings * settings)718 static BOOL rdp_read_bitmap_cache_capability_set(wStream* s, rdpSettings* settings)
719 {
720 WINPR_UNUSED(settings);
721 if (Stream_GetRemainingLength(s) < 36)
722 return FALSE;
723
724 Stream_Seek_UINT32(s); /* pad1 (4 bytes) */
725 Stream_Seek_UINT32(s); /* pad2 (4 bytes) */
726 Stream_Seek_UINT32(s); /* pad3 (4 bytes) */
727 Stream_Seek_UINT32(s); /* pad4 (4 bytes) */
728 Stream_Seek_UINT32(s); /* pad5 (4 bytes) */
729 Stream_Seek_UINT32(s); /* pad6 (4 bytes) */
730 Stream_Seek_UINT16(s); /* Cache0Entries (2 bytes) */
731 Stream_Seek_UINT16(s); /* Cache0MaximumCellSize (2 bytes) */
732 Stream_Seek_UINT16(s); /* Cache1Entries (2 bytes) */
733 Stream_Seek_UINT16(s); /* Cache1MaximumCellSize (2 bytes) */
734 Stream_Seek_UINT16(s); /* Cache2Entries (2 bytes) */
735 Stream_Seek_UINT16(s); /* Cache2MaximumCellSize (2 bytes) */
736 return TRUE;
737 }
738
739 /**
740 * Write bitmap cache capability set.\n
741 * @msdn{cc240559}
742 * @param s stream
743 * @param settings settings
744 */
745
rdp_write_bitmap_cache_capability_set(wStream * s,const rdpSettings * settings)746 static BOOL rdp_write_bitmap_cache_capability_set(wStream* s, const rdpSettings* settings)
747 {
748 UINT32 bpp;
749 size_t header;
750 UINT32 size;
751
752 if (!Stream_EnsureRemainingCapacity(s, 64))
753 return FALSE;
754
755 header = rdp_capability_set_start(s);
756 if (header > UINT16_MAX)
757 return FALSE;
758 bpp = (settings->ColorDepth + 7) / 8;
759 if (bpp > UINT16_MAX)
760 return FALSE;
761 Stream_Write_UINT32(s, 0); /* pad1 (4 bytes) */
762 Stream_Write_UINT32(s, 0); /* pad2 (4 bytes) */
763 Stream_Write_UINT32(s, 0); /* pad3 (4 bytes) */
764 Stream_Write_UINT32(s, 0); /* pad4 (4 bytes) */
765 Stream_Write_UINT32(s, 0); /* pad5 (4 bytes) */
766 Stream_Write_UINT32(s, 0); /* pad6 (4 bytes) */
767 size = bpp * 256;
768 if (size > UINT16_MAX)
769 return FALSE;
770 Stream_Write_UINT16(s, 200); /* Cache0Entries (2 bytes) */
771 Stream_Write_UINT16(s, (UINT16)size); /* Cache0MaximumCellSize (2 bytes) */
772 size = bpp * 1024;
773 if (size > UINT16_MAX)
774 return FALSE;
775 Stream_Write_UINT16(s, 600); /* Cache1Entries (2 bytes) */
776 Stream_Write_UINT16(s, (UINT16)size); /* Cache1MaximumCellSize (2 bytes) */
777 size = bpp * 4096;
778 if (size > UINT16_MAX)
779 return FALSE;
780 Stream_Write_UINT16(s, 1000); /* Cache2Entries (2 bytes) */
781 Stream_Write_UINT16(s, (UINT16)size); /* Cache2MaximumCellSize (2 bytes) */
782 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE);
783 }
784
785 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_bitmap_cache_capability_set(wStream * s)786 static BOOL rdp_print_bitmap_cache_capability_set(wStream* s)
787 {
788 UINT32 pad1, pad2, pad3;
789 UINT32 pad4, pad5, pad6;
790 UINT16 Cache0Entries;
791 UINT16 Cache0MaximumCellSize;
792 UINT16 Cache1Entries;
793 UINT16 Cache1MaximumCellSize;
794 UINT16 Cache2Entries;
795 UINT16 Cache2MaximumCellSize;
796 WLog_INFO(TAG, "BitmapCacheCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
797
798 if (Stream_GetRemainingLength(s) < 36)
799 return FALSE;
800
801 Stream_Read_UINT32(s, pad1); /* pad1 (4 bytes) */
802 Stream_Read_UINT32(s, pad2); /* pad2 (4 bytes) */
803 Stream_Read_UINT32(s, pad3); /* pad3 (4 bytes) */
804 Stream_Read_UINT32(s, pad4); /* pad4 (4 bytes) */
805 Stream_Read_UINT32(s, pad5); /* pad5 (4 bytes) */
806 Stream_Read_UINT32(s, pad6); /* pad6 (4 bytes) */
807 Stream_Read_UINT16(s, Cache0Entries); /* Cache0Entries (2 bytes) */
808 Stream_Read_UINT16(s, Cache0MaximumCellSize); /* Cache0MaximumCellSize (2 bytes) */
809 Stream_Read_UINT16(s, Cache1Entries); /* Cache1Entries (2 bytes) */
810 Stream_Read_UINT16(s, Cache1MaximumCellSize); /* Cache1MaximumCellSize (2 bytes) */
811 Stream_Read_UINT16(s, Cache2Entries); /* Cache2Entries (2 bytes) */
812 Stream_Read_UINT16(s, Cache2MaximumCellSize); /* Cache2MaximumCellSize (2 bytes) */
813 WLog_INFO(TAG, "\tpad1: 0x%08" PRIX32 "", pad1);
814 WLog_INFO(TAG, "\tpad2: 0x%08" PRIX32 "", pad2);
815 WLog_INFO(TAG, "\tpad3: 0x%08" PRIX32 "", pad3);
816 WLog_INFO(TAG, "\tpad4: 0x%08" PRIX32 "", pad4);
817 WLog_INFO(TAG, "\tpad5: 0x%08" PRIX32 "", pad5);
818 WLog_INFO(TAG, "\tpad6: 0x%08" PRIX32 "", pad6);
819 WLog_INFO(TAG, "\tCache0Entries: 0x%04" PRIX16 "", Cache0Entries);
820 WLog_INFO(TAG, "\tCache0MaximumCellSize: 0x%04" PRIX16 "", Cache0MaximumCellSize);
821 WLog_INFO(TAG, "\tCache1Entries: 0x%04" PRIX16 "", Cache1Entries);
822 WLog_INFO(TAG, "\tCache1MaximumCellSize: 0x%04" PRIX16 "", Cache1MaximumCellSize);
823 WLog_INFO(TAG, "\tCache2Entries: 0x%04" PRIX16 "", Cache2Entries);
824 WLog_INFO(TAG, "\tCache2MaximumCellSize: 0x%04" PRIX16 "", Cache2MaximumCellSize);
825 return TRUE;
826 }
827 #endif
828
829 /**
830 * Read control capability set.\n
831 * @msdn{cc240568}
832 * @param s stream
833 * @param settings settings
834 * @return if the operation completed successfully
835 */
836
rdp_read_control_capability_set(wStream * s,rdpSettings * settings)837 static BOOL rdp_read_control_capability_set(wStream* s, rdpSettings* settings)
838 {
839 WINPR_UNUSED(settings);
840 if (Stream_GetRemainingLength(s) < 8)
841 return FALSE;
842
843 Stream_Seek_UINT16(s); /* controlFlags (2 bytes) */
844 Stream_Seek_UINT16(s); /* remoteDetachFlag (2 bytes) */
845 Stream_Seek_UINT16(s); /* controlInterest (2 bytes) */
846 Stream_Seek_UINT16(s); /* detachInterest (2 bytes) */
847 return TRUE;
848 }
849
850 /**
851 * Write control capability set.\n
852 * @msdn{cc240568}
853 * @param s stream
854 * @param settings settings
855 */
856
rdp_write_control_capability_set(wStream * s,const rdpSettings * settings)857 static BOOL rdp_write_control_capability_set(wStream* s, const rdpSettings* settings)
858 {
859 size_t header;
860
861 WINPR_UNUSED(settings);
862 if (!Stream_EnsureRemainingCapacity(s, 32))
863 return FALSE;
864
865 header = rdp_capability_set_start(s);
866 if (header > UINT16_MAX)
867 return FALSE;
868 Stream_Write_UINT16(s, 0); /* controlFlags (2 bytes) */
869 Stream_Write_UINT16(s, 0); /* remoteDetachFlag (2 bytes) */
870 Stream_Write_UINT16(s, 2); /* controlInterest (2 bytes) */
871 Stream_Write_UINT16(s, 2); /* detachInterest (2 bytes) */
872 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_CONTROL);
873 }
874
875 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_control_capability_set(wStream * s)876 static BOOL rdp_print_control_capability_set(wStream* s)
877 {
878 UINT16 controlFlags;
879 UINT16 remoteDetachFlag;
880 UINT16 controlInterest;
881 UINT16 detachInterest;
882 WLog_INFO(TAG, "ControlCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
883
884 if (Stream_GetRemainingLength(s) < 8)
885 return FALSE;
886
887 Stream_Read_UINT16(s, controlFlags); /* controlFlags (2 bytes) */
888 Stream_Read_UINT16(s, remoteDetachFlag); /* remoteDetachFlag (2 bytes) */
889 Stream_Read_UINT16(s, controlInterest); /* controlInterest (2 bytes) */
890 Stream_Read_UINT16(s, detachInterest); /* detachInterest (2 bytes) */
891 WLog_INFO(TAG, "\tcontrolFlags: 0x%04" PRIX16 "", controlFlags);
892 WLog_INFO(TAG, "\tremoteDetachFlag: 0x%04" PRIX16 "", remoteDetachFlag);
893 WLog_INFO(TAG, "\tcontrolInterest: 0x%04" PRIX16 "", controlInterest);
894 WLog_INFO(TAG, "\tdetachInterest: 0x%04" PRIX16 "", detachInterest);
895 return TRUE;
896 }
897 #endif
898
899 /**
900 * Read window activation capability set.\n
901 * @msdn{cc240569}
902 * @param s stream
903 * @param settings settings
904 * @return if the operation completed successfully
905 */
906
rdp_read_window_activation_capability_set(wStream * s,rdpSettings * settings)907 static BOOL rdp_read_window_activation_capability_set(wStream* s, rdpSettings* settings)
908 {
909 WINPR_UNUSED(settings);
910 if (Stream_GetRemainingLength(s) < 8)
911 return FALSE;
912
913 Stream_Seek_UINT16(s); /* helpKeyFlag (2 bytes) */
914 Stream_Seek_UINT16(s); /* helpKeyIndexFlag (2 bytes) */
915 Stream_Seek_UINT16(s); /* helpExtendedKeyFlag (2 bytes) */
916 Stream_Seek_UINT16(s); /* windowManagerKeyFlag (2 bytes) */
917 return TRUE;
918 }
919
920 /**
921 * Write window activation capability set.\n
922 * @msdn{cc240569}
923 * @param s stream
924 * @param settings settings
925 */
926
rdp_write_window_activation_capability_set(wStream * s,const rdpSettings * settings)927 static BOOL rdp_write_window_activation_capability_set(wStream* s, const rdpSettings* settings)
928 {
929 size_t header;
930
931 WINPR_UNUSED(settings);
932 if (!Stream_EnsureRemainingCapacity(s, 32))
933 return FALSE;
934
935 header = rdp_capability_set_start(s);
936 if (header > UINT16_MAX)
937 return FALSE;
938 Stream_Write_UINT16(s, 0); /* helpKeyFlag (2 bytes) */
939 Stream_Write_UINT16(s, 0); /* helpKeyIndexFlag (2 bytes) */
940 Stream_Write_UINT16(s, 0); /* helpExtendedKeyFlag (2 bytes) */
941 Stream_Write_UINT16(s, 0); /* windowManagerKeyFlag (2 bytes) */
942 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_ACTIVATION);
943 }
944
945 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_window_activation_capability_set(wStream * s)946 static BOOL rdp_print_window_activation_capability_set(wStream* s)
947 {
948 UINT16 helpKeyFlag;
949 UINT16 helpKeyIndexFlag;
950 UINT16 helpExtendedKeyFlag;
951 UINT16 windowManagerKeyFlag;
952 WLog_INFO(TAG,
953 "WindowActivationCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
954
955 if (Stream_GetRemainingLength(s) < 8)
956 return FALSE;
957
958 Stream_Read_UINT16(s, helpKeyFlag); /* helpKeyFlag (2 bytes) */
959 Stream_Read_UINT16(s, helpKeyIndexFlag); /* helpKeyIndexFlag (2 bytes) */
960 Stream_Read_UINT16(s, helpExtendedKeyFlag); /* helpExtendedKeyFlag (2 bytes) */
961 Stream_Read_UINT16(s, windowManagerKeyFlag); /* windowManagerKeyFlag (2 bytes) */
962 WLog_INFO(TAG, "\thelpKeyFlag: 0x%04" PRIX16 "", helpKeyFlag);
963 WLog_INFO(TAG, "\thelpKeyIndexFlag: 0x%04" PRIX16 "", helpKeyIndexFlag);
964 WLog_INFO(TAG, "\thelpExtendedKeyFlag: 0x%04" PRIX16 "", helpExtendedKeyFlag);
965 WLog_INFO(TAG, "\twindowManagerKeyFlag: 0x%04" PRIX16 "", windowManagerKeyFlag);
966 return TRUE;
967 }
968 #endif
969
970 /**
971 * Read pointer capability set.\n
972 * @msdn{cc240562}
973 * @param s stream
974 * @param settings settings
975 * @return if the operation completed successfully
976 */
977
rdp_read_pointer_capability_set(wStream * s,rdpSettings * settings)978 static BOOL rdp_read_pointer_capability_set(wStream* s, rdpSettings* settings)
979 {
980 UINT16 colorPointerFlag;
981 UINT16 colorPointerCacheSize;
982 UINT16 pointerCacheSize;
983
984 if (Stream_GetRemainingLength(s) < 4)
985 return FALSE;
986
987 Stream_Read_UINT16(s, colorPointerFlag); /* colorPointerFlag (2 bytes) */
988 Stream_Read_UINT16(s, colorPointerCacheSize); /* colorPointerCacheSize (2 bytes) */
989
990 /* pointerCacheSize is optional */
991 if (Stream_GetRemainingLength(s) >= 2)
992 Stream_Read_UINT16(s, pointerCacheSize); /* pointerCacheSize (2 bytes) */
993 else
994 pointerCacheSize = 0;
995
996 if (colorPointerFlag == FALSE)
997 settings->ColorPointerFlag = FALSE;
998
999 if (settings->ServerMode)
1000 {
1001 settings->PointerCacheSize = pointerCacheSize;
1002 }
1003
1004 return TRUE;
1005 }
1006
1007 /**
1008 * Write pointer capability set.\n
1009 * @msdn{cc240562}
1010 * @param s stream
1011 * @param settings settings
1012 */
1013
rdp_write_pointer_capability_set(wStream * s,const rdpSettings * settings)1014 static BOOL rdp_write_pointer_capability_set(wStream* s, const rdpSettings* settings)
1015 {
1016 size_t header;
1017 UINT16 colorPointerFlag;
1018
1019 if (!Stream_EnsureRemainingCapacity(s, 32))
1020 return FALSE;
1021
1022 header = rdp_capability_set_start(s);
1023 if (header > UINT16_MAX)
1024 return FALSE;
1025 if (settings->PointerCacheSize > UINT16_MAX)
1026 return FALSE;
1027
1028 colorPointerFlag = (settings->ColorPointerFlag) ? 1 : 0;
1029 Stream_Write_UINT16(s, colorPointerFlag); /* colorPointerFlag (2 bytes) */
1030 Stream_Write_UINT16(s,
1031 (UINT16)settings->PointerCacheSize); /* colorPointerCacheSize (2 bytes) */
1032
1033 if (settings->LargePointerFlag)
1034 {
1035 Stream_Write_UINT16(s, (UINT16)settings->PointerCacheSize); /* pointerCacheSize (2 bytes) */
1036 }
1037
1038 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_POINTER);
1039 }
1040
1041 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_pointer_capability_set(wStream * s)1042 static BOOL rdp_print_pointer_capability_set(wStream* s)
1043 {
1044 UINT16 colorPointerFlag;
1045 UINT16 colorPointerCacheSize;
1046 UINT16 pointerCacheSize;
1047
1048 if (Stream_GetRemainingLength(s) < 6)
1049 return FALSE;
1050
1051 WLog_INFO(TAG, "PointerCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1052 Stream_Read_UINT16(s, colorPointerFlag); /* colorPointerFlag (2 bytes) */
1053 Stream_Read_UINT16(s, colorPointerCacheSize); /* colorPointerCacheSize (2 bytes) */
1054 Stream_Read_UINT16(s, pointerCacheSize); /* pointerCacheSize (2 bytes) */
1055 WLog_INFO(TAG, "\tcolorPointerFlag: 0x%04" PRIX16 "", colorPointerFlag);
1056 WLog_INFO(TAG, "\tcolorPointerCacheSize: 0x%04" PRIX16 "", colorPointerCacheSize);
1057 WLog_INFO(TAG, "\tpointerCacheSize: 0x%04" PRIX16 "", pointerCacheSize);
1058 return TRUE;
1059 }
1060 #endif
1061
1062 /**
1063 * Read share capability set.\n
1064 * @msdn{cc240570}
1065 * @param s stream
1066 * @param settings settings
1067 * @return if the operation completed successfully
1068 */
1069
rdp_read_share_capability_set(wStream * s,rdpSettings * settings)1070 static BOOL rdp_read_share_capability_set(wStream* s, rdpSettings* settings)
1071 {
1072 WINPR_UNUSED(settings);
1073 if (Stream_GetRemainingLength(s) < 4)
1074 return FALSE;
1075
1076 Stream_Seek_UINT16(s); /* nodeId (2 bytes) */
1077 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
1078 return TRUE;
1079 }
1080
1081 /**
1082 * Write share capability set.\n
1083 * @msdn{cc240570}
1084 * @param s stream
1085 * @param settings settings
1086 */
1087
rdp_write_share_capability_set(wStream * s,const rdpSettings * settings)1088 static BOOL rdp_write_share_capability_set(wStream* s, const rdpSettings* settings)
1089 {
1090 size_t header;
1091 UINT16 nodeId;
1092
1093 if (!Stream_EnsureRemainingCapacity(s, 32))
1094 return FALSE;
1095
1096 header = rdp_capability_set_start(s);
1097 if (header > UINT16_MAX)
1098 return FALSE;
1099 nodeId = (settings->ServerMode) ? 0x03EA : 0;
1100 Stream_Write_UINT16(s, nodeId); /* nodeId (2 bytes) */
1101 Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
1102 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_SHARE);
1103 }
1104
1105 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_share_capability_set(wStream * s)1106 static BOOL rdp_print_share_capability_set(wStream* s)
1107 {
1108 UINT16 nodeId;
1109 UINT16 pad2Octets;
1110 WLog_INFO(TAG, "ShareCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1111
1112 if (Stream_GetRemainingLength(s) < 4)
1113 return FALSE;
1114
1115 Stream_Read_UINT16(s, nodeId); /* nodeId (2 bytes) */
1116 Stream_Read_UINT16(s, pad2Octets); /* pad2Octets (2 bytes) */
1117 WLog_INFO(TAG, "\tnodeId: 0x%04" PRIX16 "", nodeId);
1118 WLog_INFO(TAG, "\tpad2Octets: 0x%04" PRIX16 "", pad2Octets);
1119 return TRUE;
1120 }
1121 #endif
1122
1123 /**
1124 * Read color cache capability set.\n
1125 * @msdn{cc241564}
1126 * @param s stream
1127 * @param settings settings
1128 * @return if the operation completed successfully
1129 */
1130
rdp_read_color_cache_capability_set(wStream * s,rdpSettings * settings)1131 static BOOL rdp_read_color_cache_capability_set(wStream* s, rdpSettings* settings)
1132 {
1133 WINPR_UNUSED(settings);
1134 if (Stream_GetRemainingLength(s) < 4)
1135 return FALSE;
1136
1137 Stream_Seek_UINT16(s); /* colorTableCacheSize (2 bytes) */
1138 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
1139 return TRUE;
1140 }
1141
1142 /**
1143 * Write color cache capability set.\n
1144 * @msdn{cc241564}
1145 * @param s stream
1146 * @param settings settings
1147 */
1148
rdp_write_color_cache_capability_set(wStream * s,const rdpSettings * settings)1149 static BOOL rdp_write_color_cache_capability_set(wStream* s, const rdpSettings* settings)
1150 {
1151 size_t header;
1152
1153 WINPR_UNUSED(settings);
1154 if (!Stream_EnsureRemainingCapacity(s, 32))
1155 return FALSE;
1156
1157 header = rdp_capability_set_start(s);
1158 if (header > UINT16_MAX)
1159 return FALSE;
1160 Stream_Write_UINT16(s, 6); /* colorTableCacheSize (2 bytes) */
1161 Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
1162 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_COLOR_CACHE);
1163 }
1164
1165 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_color_cache_capability_set(wStream * s)1166 static BOOL rdp_print_color_cache_capability_set(wStream* s)
1167 {
1168 UINT16 colorTableCacheSize;
1169 UINT16 pad2Octets;
1170 WLog_INFO(TAG, "ColorCacheCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1171
1172 if (Stream_GetRemainingLength(s) < 4)
1173 return FALSE;
1174
1175 Stream_Read_UINT16(s, colorTableCacheSize); /* colorTableCacheSize (2 bytes) */
1176 Stream_Read_UINT16(s, pad2Octets); /* pad2Octets (2 bytes) */
1177 WLog_INFO(TAG, "\tcolorTableCacheSize: 0x%04" PRIX16 "", colorTableCacheSize);
1178 WLog_INFO(TAG, "\tpad2Octets: 0x%04" PRIX16 "", pad2Octets);
1179 return TRUE;
1180 }
1181 #endif
1182
1183 /**
1184 * Read sound capability set.\n
1185 * @msdn{cc240552}
1186 * @param s stream
1187 * @param settings settings
1188 * @return if the operation completed successfully
1189 */
1190
rdp_read_sound_capability_set(wStream * s,rdpSettings * settings)1191 static BOOL rdp_read_sound_capability_set(wStream* s, rdpSettings* settings)
1192 {
1193 UINT16 soundFlags;
1194
1195 if (Stream_GetRemainingLength(s) < 4)
1196 return FALSE;
1197
1198 Stream_Read_UINT16(s, soundFlags); /* soundFlags (2 bytes) */
1199 Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */
1200 settings->SoundBeepsEnabled = (soundFlags & SOUND_BEEPS_FLAG) ? TRUE : FALSE;
1201 return TRUE;
1202 }
1203
1204 /**
1205 * Write sound capability set.\n
1206 * @msdn{cc240552}
1207 * @param s stream
1208 * @param settings settings
1209 */
1210
rdp_write_sound_capability_set(wStream * s,const rdpSettings * settings)1211 static BOOL rdp_write_sound_capability_set(wStream* s, const rdpSettings* settings)
1212 {
1213 size_t header;
1214 UINT16 soundFlags;
1215
1216 if (!Stream_EnsureRemainingCapacity(s, 32))
1217 return FALSE;
1218
1219 header = rdp_capability_set_start(s);
1220 if (header > UINT16_MAX)
1221 return FALSE;
1222 soundFlags = (settings->SoundBeepsEnabled) ? SOUND_BEEPS_FLAG : 0;
1223 Stream_Write_UINT16(s, soundFlags); /* soundFlags (2 bytes) */
1224 Stream_Write_UINT16(s, 0); /* pad2OctetsA (2 bytes) */
1225 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_SOUND);
1226 }
1227
1228 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_sound_capability_set(wStream * s)1229 static BOOL rdp_print_sound_capability_set(wStream* s)
1230 {
1231 UINT16 soundFlags;
1232 UINT16 pad2OctetsA;
1233 WLog_INFO(TAG, "SoundCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1234
1235 if (Stream_GetRemainingLength(s) < 4)
1236 return FALSE;
1237
1238 Stream_Read_UINT16(s, soundFlags); /* soundFlags (2 bytes) */
1239 Stream_Read_UINT16(s, pad2OctetsA); /* pad2OctetsA (2 bytes) */
1240 WLog_INFO(TAG, "\tsoundFlags: 0x%04" PRIX16 "", soundFlags);
1241 WLog_INFO(TAG, "\tpad2OctetsA: 0x%04" PRIX16 "", pad2OctetsA);
1242 return TRUE;
1243 }
1244 #endif
1245
1246 /**
1247 * Read input capability set.\n
1248 * @msdn{cc240563}
1249 * @param s stream
1250 * @param settings settings
1251 * @return if the operation completed successfully
1252 */
1253
rdp_read_input_capability_set(wStream * s,rdpSettings * settings)1254 static BOOL rdp_read_input_capability_set(wStream* s, rdpSettings* settings)
1255 {
1256 UINT16 inputFlags;
1257
1258 if (Stream_GetRemainingLength(s) < 84)
1259 return FALSE;
1260
1261 Stream_Read_UINT16(s, inputFlags); /* inputFlags (2 bytes) */
1262 Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */
1263
1264 if (settings->ServerMode)
1265 {
1266 Stream_Read_UINT32(s, settings->KeyboardLayout); /* keyboardLayout (4 bytes) */
1267 Stream_Read_UINT32(s, settings->KeyboardType); /* keyboardType (4 bytes) */
1268 Stream_Read_UINT32(s, settings->KeyboardSubType); /* keyboardSubType (4 bytes) */
1269 Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* keyboardFunctionKeys (4 bytes) */
1270 }
1271 else
1272 {
1273 Stream_Seek_UINT32(s); /* keyboardLayout (4 bytes) */
1274 Stream_Seek_UINT32(s); /* keyboardType (4 bytes) */
1275 Stream_Seek_UINT32(s); /* keyboardSubType (4 bytes) */
1276 Stream_Seek_UINT32(s); /* keyboardFunctionKeys (4 bytes) */
1277 }
1278
1279 Stream_Seek(s, 64); /* imeFileName (64 bytes) */
1280
1281 if (!settings->ServerMode)
1282 {
1283 if (inputFlags & INPUT_FLAG_FASTPATH_INPUT)
1284 {
1285 /* advertised by RDP 5.0 and 5.1 servers */
1286 }
1287 else if (inputFlags & INPUT_FLAG_FASTPATH_INPUT2)
1288 {
1289 /* advertised by RDP 5.2, 6.0, 6.1 and 7.0 servers */
1290 }
1291 else
1292 {
1293 /* server does not support fastpath input */
1294 settings->FastPathInput = FALSE;
1295 }
1296
1297 if (inputFlags & TS_INPUT_FLAG_MOUSE_HWHEEL)
1298 settings->HasHorizontalWheel = TRUE;
1299
1300 if (inputFlags & INPUT_FLAG_UNICODE)
1301 settings->UnicodeInput = TRUE;
1302
1303 if (inputFlags & INPUT_FLAG_MOUSEX)
1304 settings->HasExtendedMouseEvent = TRUE;
1305 }
1306
1307 return TRUE;
1308 }
1309
1310 /**
1311 * Write input capability set.\n
1312 * @msdn{cc240563}
1313 * @param s stream
1314 * @param settings settings
1315 */
1316
rdp_write_input_capability_set(wStream * s,const rdpSettings * settings)1317 static BOOL rdp_write_input_capability_set(wStream* s, const rdpSettings* settings)
1318 {
1319 size_t header;
1320 UINT16 inputFlags;
1321
1322 if (!Stream_EnsureRemainingCapacity(s, 128))
1323 return FALSE;
1324
1325 header = rdp_capability_set_start(s);
1326 if (header > UINT16_MAX)
1327 return FALSE;
1328 inputFlags = INPUT_FLAG_SCANCODES;
1329
1330 if (settings->FastPathInput)
1331 {
1332 inputFlags |= INPUT_FLAG_FASTPATH_INPUT;
1333 inputFlags |= INPUT_FLAG_FASTPATH_INPUT2;
1334 }
1335
1336 if (settings->HasHorizontalWheel)
1337 inputFlags |= TS_INPUT_FLAG_MOUSE_HWHEEL;
1338
1339 if (settings->UnicodeInput)
1340 inputFlags |= INPUT_FLAG_UNICODE;
1341
1342 if (settings->HasExtendedMouseEvent)
1343 inputFlags |= INPUT_FLAG_MOUSEX;
1344
1345 Stream_Write_UINT16(s, inputFlags); /* inputFlags (2 bytes) */
1346 Stream_Write_UINT16(s, 0); /* pad2OctetsA (2 bytes) */
1347 Stream_Write_UINT32(s, settings->KeyboardLayout); /* keyboardLayout (4 bytes) */
1348 Stream_Write_UINT32(s, settings->KeyboardType); /* keyboardType (4 bytes) */
1349 Stream_Write_UINT32(s, settings->KeyboardSubType); /* keyboardSubType (4 bytes) */
1350 Stream_Write_UINT32(s, settings->KeyboardFunctionKey); /* keyboardFunctionKeys (4 bytes) */
1351 Stream_Zero(s, 64); /* imeFileName (64 bytes) */
1352 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_INPUT);
1353 }
1354
1355 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_input_capability_set(wStream * s)1356 static BOOL rdp_print_input_capability_set(wStream* s)
1357 {
1358 UINT16 inputFlags;
1359 UINT16 pad2OctetsA;
1360 UINT32 keyboardLayout;
1361 UINT32 keyboardType;
1362 UINT32 keyboardSubType;
1363 UINT32 keyboardFunctionKey;
1364 WLog_INFO(TAG, "InputCapabilitySet (length %" PRIuz ")", Stream_GetRemainingLength(s));
1365
1366 if (Stream_GetRemainingLength(s) < 84)
1367 return FALSE;
1368
1369 Stream_Read_UINT16(s, inputFlags); /* inputFlags (2 bytes) */
1370 Stream_Read_UINT16(s, pad2OctetsA); /* pad2OctetsA (2 bytes) */
1371 Stream_Read_UINT32(s, keyboardLayout); /* keyboardLayout (4 bytes) */
1372 Stream_Read_UINT32(s, keyboardType); /* keyboardType (4 bytes) */
1373 Stream_Read_UINT32(s, keyboardSubType); /* keyboardSubType (4 bytes) */
1374 Stream_Read_UINT32(s, keyboardFunctionKey); /* keyboardFunctionKeys (4 bytes) */
1375 Stream_Seek(s, 64); /* imeFileName (64 bytes) */
1376 WLog_INFO(TAG, "\tinputFlags: 0x%04" PRIX16 "", inputFlags);
1377 WLog_INFO(TAG, "\tpad2OctetsA: 0x%04" PRIX16 "", pad2OctetsA);
1378 WLog_INFO(TAG, "\tkeyboardLayout: 0x%08" PRIX32 "", keyboardLayout);
1379 WLog_INFO(TAG, "\tkeyboardType: 0x%08" PRIX32 "", keyboardType);
1380 WLog_INFO(TAG, "\tkeyboardSubType: 0x%08" PRIX32 "", keyboardSubType);
1381 WLog_INFO(TAG, "\tkeyboardFunctionKey: 0x%08" PRIX32 "", keyboardFunctionKey);
1382 return TRUE;
1383 }
1384 #endif
1385
1386 /**
1387 * Read font capability set.\n
1388 * @msdn{cc240571}
1389 * @param s stream
1390 * @param settings settings
1391 * @return if the operation completed successfully
1392 */
1393
rdp_read_font_capability_set(wStream * s,rdpSettings * settings)1394 static BOOL rdp_read_font_capability_set(wStream* s, rdpSettings* settings)
1395 {
1396 WINPR_UNUSED(settings);
1397 if (Stream_GetRemainingLength(s) >= 2)
1398 Stream_Seek_UINT16(s); /* fontSupportFlags (2 bytes) */
1399
1400 if (Stream_GetRemainingLength(s) >= 2)
1401 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
1402
1403 return TRUE;
1404 }
1405
1406 /**
1407 * Write font capability set.\n
1408 * @msdn{cc240571}
1409 * @param s stream
1410 * @param settings settings
1411 */
1412
rdp_write_font_capability_set(wStream * s,const rdpSettings * settings)1413 static BOOL rdp_write_font_capability_set(wStream* s, const rdpSettings* settings)
1414 {
1415 size_t header;
1416
1417 WINPR_UNUSED(settings);
1418 if (!Stream_EnsureRemainingCapacity(s, 32))
1419 return FALSE;
1420
1421 header = rdp_capability_set_start(s);
1422 if (header > UINT16_MAX)
1423 return FALSE;
1424 Stream_Write_UINT16(s, FONTSUPPORT_FONTLIST); /* fontSupportFlags (2 bytes) */
1425 Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
1426 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_FONT);
1427 }
1428
1429 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_font_capability_set(wStream * s)1430 static BOOL rdp_print_font_capability_set(wStream* s)
1431 {
1432 UINT16 fontSupportFlags = 0;
1433 UINT16 pad2Octets = 0;
1434 WLog_INFO(TAG, "FontCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1435
1436 if (Stream_GetRemainingLength(s) >= 2)
1437 Stream_Read_UINT16(s, fontSupportFlags); /* fontSupportFlags (2 bytes) */
1438
1439 if (Stream_GetRemainingLength(s) >= 2)
1440 Stream_Read_UINT16(s, pad2Octets); /* pad2Octets (2 bytes) */
1441
1442 WLog_INFO(TAG, "\tfontSupportFlags: 0x%04" PRIX16 "", fontSupportFlags);
1443 WLog_INFO(TAG, "\tpad2Octets: 0x%04" PRIX16 "", pad2Octets);
1444 return TRUE;
1445 }
1446 #endif
1447
1448 /**
1449 * Read brush capability set.
1450 * @msdn{cc240564}
1451 * @param s stream
1452 * @param settings settings
1453 * @return if the operation completed successfully
1454 */
1455
rdp_read_brush_capability_set(wStream * s,rdpSettings * settings)1456 static BOOL rdp_read_brush_capability_set(wStream* s, rdpSettings* settings)
1457 {
1458 WINPR_UNUSED(settings);
1459 return Stream_SafeSeek(s, 4); /* brushSupportLevel (4 bytes) */
1460 }
1461
1462 /**
1463 * Write brush capability set.\n
1464 * @msdn{cc240564}
1465 * @param s stream
1466 * @param settings settings
1467 */
1468
rdp_write_brush_capability_set(wStream * s,const rdpSettings * settings)1469 static BOOL rdp_write_brush_capability_set(wStream* s, const rdpSettings* settings)
1470 {
1471 size_t header;
1472
1473 if (!Stream_EnsureRemainingCapacity(s, 32))
1474 return FALSE;
1475
1476 header = rdp_capability_set_start(s);
1477 if (header > UINT16_MAX)
1478 return FALSE;
1479 Stream_Write_UINT32(s, settings->BrushSupportLevel); /* brushSupportLevel (4 bytes) */
1480 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BRUSH);
1481 }
1482
1483 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_brush_capability_set(wStream * s)1484 static BOOL rdp_print_brush_capability_set(wStream* s)
1485 {
1486 UINT32 brushSupportLevel;
1487 WLog_INFO(TAG, "BrushCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1488
1489 if (Stream_GetRemainingLength(s) < 4)
1490 return FALSE;
1491
1492 Stream_Read_UINT32(s, brushSupportLevel); /* brushSupportLevel (4 bytes) */
1493 WLog_INFO(TAG, "\tbrushSupportLevel: 0x%08" PRIX32 "", brushSupportLevel);
1494 return TRUE;
1495 }
1496 #endif
1497
1498 /**
1499 * Read cache definition (glyph).\n
1500 * @msdn{cc240566}
1501 * @param s stream
1502 */
rdp_read_cache_definition(wStream * s,GLYPH_CACHE_DEFINITION * cache_definition)1503 static void rdp_read_cache_definition(wStream* s, GLYPH_CACHE_DEFINITION* cache_definition)
1504 {
1505 Stream_Read_UINT16(s, cache_definition->cacheEntries); /* cacheEntries (2 bytes) */
1506 Stream_Read_UINT16(s,
1507 cache_definition->cacheMaximumCellSize); /* cacheMaximumCellSize (2 bytes) */
1508 }
1509
1510 /**
1511 * Write cache definition (glyph).\n
1512 * @msdn{cc240566}
1513 * @param s stream
1514 */
rdp_write_cache_definition(wStream * s,GLYPH_CACHE_DEFINITION * cache_definition)1515 static void rdp_write_cache_definition(wStream* s, GLYPH_CACHE_DEFINITION* cache_definition)
1516 {
1517 Stream_Write_UINT16(s, cache_definition->cacheEntries); /* cacheEntries (2 bytes) */
1518 Stream_Write_UINT16(
1519 s, cache_definition->cacheMaximumCellSize); /* cacheMaximumCellSize (2 bytes) */
1520 }
1521
1522 /**
1523 * Read glyph cache capability set.\n
1524 * @msdn{cc240565}
1525 * @param s stream
1526 * @param settings settings
1527 * @return if the operation completed successfully
1528 */
1529
rdp_read_glyph_cache_capability_set(wStream * s,rdpSettings * settings)1530 static BOOL rdp_read_glyph_cache_capability_set(wStream* s, rdpSettings* settings)
1531 {
1532 if (Stream_GetRemainingLength(s) < 48)
1533 return FALSE;
1534
1535 /* glyphCache (40 bytes) */
1536 rdp_read_cache_definition(s, &(settings->GlyphCache[0])); /* glyphCache0 (4 bytes) */
1537 rdp_read_cache_definition(s, &(settings->GlyphCache[1])); /* glyphCache1 (4 bytes) */
1538 rdp_read_cache_definition(s, &(settings->GlyphCache[2])); /* glyphCache2 (4 bytes) */
1539 rdp_read_cache_definition(s, &(settings->GlyphCache[3])); /* glyphCache3 (4 bytes) */
1540 rdp_read_cache_definition(s, &(settings->GlyphCache[4])); /* glyphCache4 (4 bytes) */
1541 rdp_read_cache_definition(s, &(settings->GlyphCache[5])); /* glyphCache5 (4 bytes) */
1542 rdp_read_cache_definition(s, &(settings->GlyphCache[6])); /* glyphCache6 (4 bytes) */
1543 rdp_read_cache_definition(s, &(settings->GlyphCache[7])); /* glyphCache7 (4 bytes) */
1544 rdp_read_cache_definition(s, &(settings->GlyphCache[8])); /* glyphCache8 (4 bytes) */
1545 rdp_read_cache_definition(s, &(settings->GlyphCache[9])); /* glyphCache9 (4 bytes) */
1546 rdp_read_cache_definition(s, settings->FragCache); /* fragCache (4 bytes) */
1547 Stream_Read_UINT16(s, settings->GlyphSupportLevel); /* glyphSupportLevel (2 bytes) */
1548 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
1549 return TRUE;
1550 }
1551
1552 /**
1553 * Write glyph cache capability set.\n
1554 * @msdn{cc240565}
1555 * @param s stream
1556 * @param settings settings
1557 */
1558
rdp_write_glyph_cache_capability_set(wStream * s,const rdpSettings * settings)1559 static BOOL rdp_write_glyph_cache_capability_set(wStream* s, const rdpSettings* settings)
1560 {
1561 size_t header;
1562
1563 if (!Stream_EnsureRemainingCapacity(s, 64))
1564 return FALSE;
1565
1566 header = rdp_capability_set_start(s);
1567 if (header > UINT16_MAX)
1568 return FALSE;
1569 if (settings->GlyphSupportLevel > UINT16_MAX)
1570 return FALSE;
1571 /* glyphCache (40 bytes) */
1572 rdp_write_cache_definition(s, &(settings->GlyphCache[0])); /* glyphCache0 (4 bytes) */
1573 rdp_write_cache_definition(s, &(settings->GlyphCache[1])); /* glyphCache1 (4 bytes) */
1574 rdp_write_cache_definition(s, &(settings->GlyphCache[2])); /* glyphCache2 (4 bytes) */
1575 rdp_write_cache_definition(s, &(settings->GlyphCache[3])); /* glyphCache3 (4 bytes) */
1576 rdp_write_cache_definition(s, &(settings->GlyphCache[4])); /* glyphCache4 (4 bytes) */
1577 rdp_write_cache_definition(s, &(settings->GlyphCache[5])); /* glyphCache5 (4 bytes) */
1578 rdp_write_cache_definition(s, &(settings->GlyphCache[6])); /* glyphCache6 (4 bytes) */
1579 rdp_write_cache_definition(s, &(settings->GlyphCache[7])); /* glyphCache7 (4 bytes) */
1580 rdp_write_cache_definition(s, &(settings->GlyphCache[8])); /* glyphCache8 (4 bytes) */
1581 rdp_write_cache_definition(s, &(settings->GlyphCache[9])); /* glyphCache9 (4 bytes) */
1582 rdp_write_cache_definition(s, settings->FragCache); /* fragCache (4 bytes) */
1583 Stream_Write_UINT16(s, (UINT16)settings->GlyphSupportLevel); /* glyphSupportLevel (2 bytes) */
1584 Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
1585 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_GLYPH_CACHE);
1586 }
1587
1588 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_glyph_cache_capability_set(wStream * s)1589 static BOOL rdp_print_glyph_cache_capability_set(wStream* s)
1590 {
1591 GLYPH_CACHE_DEFINITION glyphCache[10];
1592 GLYPH_CACHE_DEFINITION fragCache;
1593 UINT16 glyphSupportLevel;
1594 UINT16 pad2Octets;
1595 WLog_INFO(TAG, "GlyphCacheCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1596
1597 if (Stream_GetRemainingLength(s) < 48)
1598 return FALSE;
1599
1600 /* glyphCache (40 bytes) */
1601 rdp_read_cache_definition(s, &glyphCache[0]); /* glyphCache0 (4 bytes) */
1602 rdp_read_cache_definition(s, &glyphCache[1]); /* glyphCache1 (4 bytes) */
1603 rdp_read_cache_definition(s, &glyphCache[2]); /* glyphCache2 (4 bytes) */
1604 rdp_read_cache_definition(s, &glyphCache[3]); /* glyphCache3 (4 bytes) */
1605 rdp_read_cache_definition(s, &glyphCache[4]); /* glyphCache4 (4 bytes) */
1606 rdp_read_cache_definition(s, &glyphCache[5]); /* glyphCache5 (4 bytes) */
1607 rdp_read_cache_definition(s, &glyphCache[6]); /* glyphCache6 (4 bytes) */
1608 rdp_read_cache_definition(s, &glyphCache[7]); /* glyphCache7 (4 bytes) */
1609 rdp_read_cache_definition(s, &glyphCache[8]); /* glyphCache8 (4 bytes) */
1610 rdp_read_cache_definition(s, &glyphCache[9]); /* glyphCache9 (4 bytes) */
1611 rdp_read_cache_definition(s, &fragCache); /* fragCache (4 bytes) */
1612 Stream_Read_UINT16(s, glyphSupportLevel); /* glyphSupportLevel (2 bytes) */
1613 Stream_Read_UINT16(s, pad2Octets); /* pad2Octets (2 bytes) */
1614 WLog_INFO(TAG, "\tglyphCache0: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1615 glyphCache[0].cacheEntries, glyphCache[0].cacheMaximumCellSize);
1616 WLog_INFO(TAG, "\tglyphCache1: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1617 glyphCache[1].cacheEntries, glyphCache[1].cacheMaximumCellSize);
1618 WLog_INFO(TAG, "\tglyphCache2: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1619 glyphCache[2].cacheEntries, glyphCache[2].cacheMaximumCellSize);
1620 WLog_INFO(TAG, "\tglyphCache3: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1621 glyphCache[3].cacheEntries, glyphCache[3].cacheMaximumCellSize);
1622 WLog_INFO(TAG, "\tglyphCache4: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1623 glyphCache[4].cacheEntries, glyphCache[4].cacheMaximumCellSize);
1624 WLog_INFO(TAG, "\tglyphCache5: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1625 glyphCache[5].cacheEntries, glyphCache[5].cacheMaximumCellSize);
1626 WLog_INFO(TAG, "\tglyphCache6: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1627 glyphCache[6].cacheEntries, glyphCache[6].cacheMaximumCellSize);
1628 WLog_INFO(TAG, "\tglyphCache7: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1629 glyphCache[7].cacheEntries, glyphCache[7].cacheMaximumCellSize);
1630 WLog_INFO(TAG, "\tglyphCache8: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1631 glyphCache[8].cacheEntries, glyphCache[8].cacheMaximumCellSize);
1632 WLog_INFO(TAG, "\tglyphCache9: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1633 glyphCache[9].cacheEntries, glyphCache[9].cacheMaximumCellSize);
1634 WLog_INFO(TAG, "\tfragCache: Entries: %" PRIu16 " MaximumCellSize: %" PRIu16 "",
1635 fragCache.cacheEntries, fragCache.cacheMaximumCellSize);
1636 WLog_INFO(TAG, "\tglyphSupportLevel: 0x%04" PRIX16 "", glyphSupportLevel);
1637 WLog_INFO(TAG, "\tpad2Octets: 0x%04" PRIX16 "", pad2Octets);
1638 return TRUE;
1639 }
1640 #endif
1641
1642 /**
1643 * Read offscreen bitmap cache capability set.\n
1644 * @msdn{cc240550}
1645 * @param s stream
1646 * @param settings settings
1647 * @return if the operation completed successfully
1648 */
1649
rdp_read_offscreen_bitmap_cache_capability_set(wStream * s,rdpSettings * settings)1650 static BOOL rdp_read_offscreen_bitmap_cache_capability_set(wStream* s, rdpSettings* settings)
1651 {
1652 UINT32 offscreenSupportLevel;
1653
1654 if (Stream_GetRemainingLength(s) < 8)
1655 return FALSE;
1656
1657 Stream_Read_UINT32(s, offscreenSupportLevel); /* offscreenSupportLevel (4 bytes) */
1658 Stream_Read_UINT16(s, settings->OffscreenCacheSize); /* offscreenCacheSize (2 bytes) */
1659 Stream_Read_UINT16(s, settings->OffscreenCacheEntries); /* offscreenCacheEntries (2 bytes) */
1660
1661 if (offscreenSupportLevel & TRUE)
1662 settings->OffscreenSupportLevel = TRUE;
1663
1664 return TRUE;
1665 }
1666
1667 /**
1668 * Write offscreen bitmap cache capability set.\n
1669 * @msdn{cc240550}
1670 * @param s stream
1671 * @param settings settings
1672 */
1673
rdp_write_offscreen_bitmap_cache_capability_set(wStream * s,const rdpSettings * settings)1674 static BOOL rdp_write_offscreen_bitmap_cache_capability_set(wStream* s, const rdpSettings* settings)
1675 {
1676 size_t header;
1677 UINT32 offscreenSupportLevel = 0x00;
1678
1679 if (!Stream_EnsureRemainingCapacity(s, 32))
1680 return FALSE;
1681
1682 header = rdp_capability_set_start(s);
1683 if (header > UINT16_MAX)
1684 return FALSE;
1685 if (settings->OffscreenSupportLevel)
1686 {
1687 offscreenSupportLevel = 0x01;
1688 Stream_Write_UINT32(s, offscreenSupportLevel); /* offscreenSupportLevel (4 bytes) */
1689 Stream_Write_UINT16(s, settings->OffscreenCacheSize); /* offscreenCacheSize (2 bytes) */
1690 Stream_Write_UINT16(s,
1691 settings->OffscreenCacheEntries); /* offscreenCacheEntries (2 bytes) */
1692 }
1693 else
1694 Stream_Zero(s, 8);
1695
1696 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_OFFSCREEN_CACHE);
1697 }
1698
1699 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_offscreen_bitmap_cache_capability_set(wStream * s)1700 static BOOL rdp_print_offscreen_bitmap_cache_capability_set(wStream* s)
1701 {
1702 UINT32 offscreenSupportLevel;
1703 UINT16 offscreenCacheSize;
1704 UINT16 offscreenCacheEntries;
1705 WLog_INFO(TAG, "OffscreenBitmapCacheCapabilitySet (length %" PRIuz "):",
1706 Stream_GetRemainingLength(s));
1707
1708 if (Stream_GetRemainingLength(s) < 8)
1709 return FALSE;
1710
1711 Stream_Read_UINT32(s, offscreenSupportLevel); /* offscreenSupportLevel (4 bytes) */
1712 Stream_Read_UINT16(s, offscreenCacheSize); /* offscreenCacheSize (2 bytes) */
1713 Stream_Read_UINT16(s, offscreenCacheEntries); /* offscreenCacheEntries (2 bytes) */
1714 WLog_INFO(TAG, "\toffscreenSupportLevel: 0x%08" PRIX32 "", offscreenSupportLevel);
1715 WLog_INFO(TAG, "\toffscreenCacheSize: 0x%04" PRIX16 "", offscreenCacheSize);
1716 WLog_INFO(TAG, "\toffscreenCacheEntries: 0x%04" PRIX16 "", offscreenCacheEntries);
1717 return TRUE;
1718 }
1719 #endif
1720
1721 /**
1722 * Read bitmap cache host support capability set.\n
1723 * @msdn{cc240557}
1724 * @param s stream
1725 * @param settings settings
1726 * @return if the operation completed successfully
1727 */
1728
rdp_read_bitmap_cache_host_support_capability_set(wStream * s,rdpSettings * settings)1729 static BOOL rdp_read_bitmap_cache_host_support_capability_set(wStream* s, rdpSettings* settings)
1730 {
1731 BYTE cacheVersion;
1732
1733 if (Stream_GetRemainingLength(s) < 4)
1734 return FALSE;
1735
1736 Stream_Read_UINT8(s, cacheVersion); /* cacheVersion (1 byte) */
1737 Stream_Seek_UINT8(s); /* pad1 (1 byte) */
1738 Stream_Seek_UINT16(s); /* pad2 (2 bytes) */
1739
1740 if (cacheVersion & BITMAP_CACHE_V2)
1741 settings->BitmapCachePersistEnabled = TRUE;
1742
1743 return TRUE;
1744 }
1745
1746 /**
1747 * Write bitmap cache host support capability set.\n
1748 * @msdn{cc240557}
1749 * @param s stream
1750 * @param settings settings
1751 */
1752
rdp_write_bitmap_cache_host_support_capability_set(wStream * s,const rdpSettings * settings)1753 static BOOL rdp_write_bitmap_cache_host_support_capability_set(wStream* s,
1754 const rdpSettings* settings)
1755 {
1756 size_t header;
1757
1758 WINPR_UNUSED(settings);
1759 if (!Stream_EnsureRemainingCapacity(s, 32))
1760 return FALSE;
1761
1762 header = rdp_capability_set_start(s);
1763 if (header > UINT16_MAX)
1764 return FALSE;
1765 Stream_Write_UINT8(s, BITMAP_CACHE_V2); /* cacheVersion (1 byte) */
1766 Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */
1767 Stream_Write_UINT16(s, 0); /* pad2 (2 bytes) */
1768 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT);
1769 }
1770
1771 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_bitmap_cache_host_support_capability_set(wStream * s)1772 static BOOL rdp_print_bitmap_cache_host_support_capability_set(wStream* s)
1773 {
1774 BYTE cacheVersion;
1775 BYTE pad1;
1776 UINT16 pad2;
1777 WLog_INFO(TAG, "BitmapCacheHostSupportCapabilitySet (length %" PRIuz "):",
1778 Stream_GetRemainingLength(s));
1779
1780 if (Stream_GetRemainingLength(s) < 4)
1781 return FALSE;
1782
1783 Stream_Read_UINT8(s, cacheVersion); /* cacheVersion (1 byte) */
1784 Stream_Read_UINT8(s, pad1); /* pad1 (1 byte) */
1785 Stream_Read_UINT16(s, pad2); /* pad2 (2 bytes) */
1786 WLog_INFO(TAG, "\tcacheVersion: 0x%02" PRIX8 "", cacheVersion);
1787 WLog_INFO(TAG, "\tpad1: 0x%02" PRIX8 "", pad1);
1788 WLog_INFO(TAG, "\tpad2: 0x%04" PRIX16 "", pad2);
1789 return TRUE;
1790 }
1791
rdp_read_bitmap_cache_cell_info(wStream * s,BITMAP_CACHE_V2_CELL_INFO * cellInfo)1792 static void rdp_read_bitmap_cache_cell_info(wStream* s, BITMAP_CACHE_V2_CELL_INFO* cellInfo)
1793 {
1794 UINT32 info;
1795 /**
1796 * numEntries is in the first 31 bits, while the last bit (k)
1797 * is used to indicate a persistent bitmap cache.
1798 */
1799 Stream_Read_UINT32(s, info);
1800 cellInfo->numEntries = (info & 0x7FFFFFFF);
1801 cellInfo->persistent = (info & 0x80000000) ? 1 : 0;
1802 }
1803 #endif
1804
rdp_write_bitmap_cache_cell_info(wStream * s,BITMAP_CACHE_V2_CELL_INFO * cellInfo)1805 static void rdp_write_bitmap_cache_cell_info(wStream* s, BITMAP_CACHE_V2_CELL_INFO* cellInfo)
1806 {
1807 UINT32 info;
1808 /**
1809 * numEntries is in the first 31 bits, while the last bit (k)
1810 * is used to indicate a persistent bitmap cache.
1811 */
1812 info = (cellInfo->numEntries | (cellInfo->persistent << 31));
1813 Stream_Write_UINT32(s, info);
1814 }
1815
1816 /**
1817 * Read bitmap cache v2 capability set.\n
1818 * @msdn{cc240560}
1819 * @param s stream
1820 * @param settings settings
1821 * @return if the operation completed successfully
1822 */
1823
rdp_read_bitmap_cache_v2_capability_set(wStream * s,rdpSettings * settings)1824 static BOOL rdp_read_bitmap_cache_v2_capability_set(wStream* s, rdpSettings* settings)
1825 {
1826 WINPR_UNUSED(settings);
1827 if (Stream_GetRemainingLength(s) < 36)
1828 return FALSE;
1829
1830 Stream_Seek_UINT16(s); /* cacheFlags (2 bytes) */
1831 Stream_Seek_UINT8(s); /* pad2 (1 byte) */
1832 Stream_Seek_UINT8(s); /* numCellCaches (1 byte) */
1833 Stream_Seek(s, 4); /* bitmapCache0CellInfo (4 bytes) */
1834 Stream_Seek(s, 4); /* bitmapCache1CellInfo (4 bytes) */
1835 Stream_Seek(s, 4); /* bitmapCache2CellInfo (4 bytes) */
1836 Stream_Seek(s, 4); /* bitmapCache3CellInfo (4 bytes) */
1837 Stream_Seek(s, 4); /* bitmapCache4CellInfo (4 bytes) */
1838 Stream_Seek(s, 12); /* pad3 (12 bytes) */
1839 return TRUE;
1840 }
1841
1842 /**
1843 * Write bitmap cache v2 capability set.\n
1844 * @msdn{cc240560}
1845 * @param s stream
1846 * @param settings settings
1847 */
1848
rdp_write_bitmap_cache_v2_capability_set(wStream * s,const rdpSettings * settings)1849 static BOOL rdp_write_bitmap_cache_v2_capability_set(wStream* s, const rdpSettings* settings)
1850 {
1851 size_t header;
1852 UINT16 cacheFlags;
1853
1854 if (!Stream_EnsureRemainingCapacity(s, 64))
1855 return FALSE;
1856
1857 header = rdp_capability_set_start(s);
1858 if (header > UINT16_MAX)
1859 return FALSE;
1860 cacheFlags = ALLOW_CACHE_WAITING_LIST_FLAG;
1861
1862 if (settings->BitmapCachePersistEnabled)
1863 cacheFlags |= PERSISTENT_KEYS_EXPECTED_FLAG;
1864
1865 Stream_Write_UINT16(s, cacheFlags); /* cacheFlags (2 bytes) */
1866 Stream_Write_UINT8(s, 0); /* pad2 (1 byte) */
1867 Stream_Write_UINT8(s, settings->BitmapCacheV2NumCells); /* numCellCaches (1 byte) */
1868 rdp_write_bitmap_cache_cell_info(
1869 s, &settings->BitmapCacheV2CellInfo[0]); /* bitmapCache0CellInfo (4 bytes) */
1870 rdp_write_bitmap_cache_cell_info(
1871 s, &settings->BitmapCacheV2CellInfo[1]); /* bitmapCache1CellInfo (4 bytes) */
1872 rdp_write_bitmap_cache_cell_info(
1873 s, &settings->BitmapCacheV2CellInfo[2]); /* bitmapCache2CellInfo (4 bytes) */
1874 rdp_write_bitmap_cache_cell_info(
1875 s, &settings->BitmapCacheV2CellInfo[3]); /* bitmapCache3CellInfo (4 bytes) */
1876 rdp_write_bitmap_cache_cell_info(
1877 s, &settings->BitmapCacheV2CellInfo[4]); /* bitmapCache4CellInfo (4 bytes) */
1878 Stream_Zero(s, 12); /* pad3 (12 bytes) */
1879 return rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_V2);
1880 }
1881
1882 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_bitmap_cache_v2_capability_set(wStream * s)1883 static BOOL rdp_print_bitmap_cache_v2_capability_set(wStream* s)
1884 {
1885 UINT16 cacheFlags;
1886 BYTE pad2;
1887 BYTE numCellCaches;
1888 BITMAP_CACHE_V2_CELL_INFO bitmapCacheV2CellInfo[5];
1889 WLog_INFO(TAG, "BitmapCacheV2CapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1890
1891 if (Stream_GetRemainingLength(s) < 36)
1892 return FALSE;
1893
1894 Stream_Read_UINT16(s, cacheFlags); /* cacheFlags (2 bytes) */
1895 Stream_Read_UINT8(s, pad2); /* pad2 (1 byte) */
1896 Stream_Read_UINT8(s, numCellCaches); /* numCellCaches (1 byte) */
1897 rdp_read_bitmap_cache_cell_info(s,
1898 &bitmapCacheV2CellInfo[0]); /* bitmapCache0CellInfo (4 bytes) */
1899 rdp_read_bitmap_cache_cell_info(s,
1900 &bitmapCacheV2CellInfo[1]); /* bitmapCache1CellInfo (4 bytes) */
1901 rdp_read_bitmap_cache_cell_info(s,
1902 &bitmapCacheV2CellInfo[2]); /* bitmapCache2CellInfo (4 bytes) */
1903 rdp_read_bitmap_cache_cell_info(s,
1904 &bitmapCacheV2CellInfo[3]); /* bitmapCache3CellInfo (4 bytes) */
1905 rdp_read_bitmap_cache_cell_info(s,
1906 &bitmapCacheV2CellInfo[4]); /* bitmapCache4CellInfo (4 bytes) */
1907 Stream_Seek(s, 12); /* pad3 (12 bytes) */
1908 WLog_INFO(TAG, "\tcacheFlags: 0x%04" PRIX16 "", cacheFlags);
1909 WLog_INFO(TAG, "\tpad2: 0x%02" PRIX8 "", pad2);
1910 WLog_INFO(TAG, "\tnumCellCaches: 0x%02" PRIX8 "", numCellCaches);
1911 WLog_INFO(TAG, "\tbitmapCache0CellInfo: numEntries: %" PRIu32 " persistent: %" PRId32 "",
1912 bitmapCacheV2CellInfo[0].numEntries, bitmapCacheV2CellInfo[0].persistent);
1913 WLog_INFO(TAG, "\tbitmapCache1CellInfo: numEntries: %" PRIu32 " persistent: %" PRId32 "",
1914 bitmapCacheV2CellInfo[1].numEntries, bitmapCacheV2CellInfo[1].persistent);
1915 WLog_INFO(TAG, "\tbitmapCache2CellInfo: numEntries: %" PRIu32 " persistent: %" PRId32 "",
1916 bitmapCacheV2CellInfo[2].numEntries, bitmapCacheV2CellInfo[2].persistent);
1917 WLog_INFO(TAG, "\tbitmapCache3CellInfo: numEntries: %" PRIu32 " persistent: %" PRId32 "",
1918 bitmapCacheV2CellInfo[3].numEntries, bitmapCacheV2CellInfo[3].persistent);
1919 WLog_INFO(TAG, "\tbitmapCache4CellInfo: numEntries: %" PRIu32 " persistent: %" PRId32 "",
1920 bitmapCacheV2CellInfo[4].numEntries, bitmapCacheV2CellInfo[4].persistent);
1921 return TRUE;
1922 }
1923 #endif
1924
1925 /**
1926 * Read virtual channel capability set.\n
1927 * @msdn{cc240551}
1928 * @param s stream
1929 * @param settings settings
1930 * @return if the operation completed successfully
1931 */
1932
rdp_read_virtual_channel_capability_set(wStream * s,rdpSettings * settings)1933 static BOOL rdp_read_virtual_channel_capability_set(wStream* s, rdpSettings* settings)
1934 {
1935 UINT32 flags;
1936 UINT32 VCChunkSize;
1937
1938 if (Stream_GetRemainingLength(s) < 4)
1939 return FALSE;
1940
1941 Stream_Read_UINT32(s, flags); /* flags (4 bytes) */
1942
1943 if (Stream_GetRemainingLength(s) >= 4)
1944 Stream_Read_UINT32(s, VCChunkSize); /* VCChunkSize (4 bytes) */
1945 else
1946 VCChunkSize = 1600;
1947
1948 if (settings->ServerMode != TRUE)
1949 settings->VirtualChannelChunkSize = VCChunkSize;
1950
1951 return TRUE;
1952 }
1953
1954 /**
1955 * Write virtual channel capability set.\n
1956 * @msdn{cc240551}
1957 * @param s stream
1958 * @param settings settings
1959 */
1960
rdp_write_virtual_channel_capability_set(wStream * s,const rdpSettings * settings)1961 static BOOL rdp_write_virtual_channel_capability_set(wStream* s, const rdpSettings* settings)
1962 {
1963 size_t header;
1964 UINT32 flags;
1965
1966 if (!Stream_EnsureRemainingCapacity(s, 32))
1967 return FALSE;
1968
1969 header = rdp_capability_set_start(s);
1970 if (header > UINT16_MAX)
1971 return FALSE;
1972 flags = VCCAPS_NO_COMPR;
1973 Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
1974 Stream_Write_UINT32(s, settings->VirtualChannelChunkSize); /* VCChunkSize (4 bytes) */
1975 return rdp_capability_set_finish(s, header, CAPSET_TYPE_VIRTUAL_CHANNEL);
1976 }
1977
1978 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_virtual_channel_capability_set(wStream * s)1979 static BOOL rdp_print_virtual_channel_capability_set(wStream* s)
1980 {
1981 UINT32 flags;
1982 UINT32 VCChunkSize;
1983 WLog_INFO(TAG,
1984 "VirtualChannelCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
1985
1986 if (Stream_GetRemainingLength(s) < 4)
1987 return FALSE;
1988
1989 Stream_Read_UINT32(s, flags); /* flags (4 bytes) */
1990
1991 if (Stream_GetRemainingLength(s) >= 4)
1992 Stream_Read_UINT32(s, VCChunkSize); /* VCChunkSize (4 bytes) */
1993 else
1994 VCChunkSize = 1600;
1995
1996 WLog_INFO(TAG, "\tflags: 0x%08" PRIX32 "", flags);
1997 WLog_INFO(TAG, "\tVCChunkSize: 0x%08" PRIX32 "", VCChunkSize);
1998 return TRUE;
1999 }
2000 #endif
2001
2002 /**
2003 * Read drawn nine grid cache capability set.\n
2004 * @msdn{cc241565}
2005 * @param s stream
2006 * @param settings settings
2007 * @return if the operation completed successfully
2008 */
2009
rdp_read_draw_nine_grid_cache_capability_set(wStream * s,rdpSettings * settings)2010 static BOOL rdp_read_draw_nine_grid_cache_capability_set(wStream* s, rdpSettings* settings)
2011 {
2012 UINT32 drawNineGridSupportLevel;
2013
2014 if (Stream_GetRemainingLength(s) < 8)
2015 return FALSE;
2016
2017 Stream_Read_UINT32(s, drawNineGridSupportLevel); /* drawNineGridSupportLevel (4 bytes) */
2018 Stream_Read_UINT16(s, settings->DrawNineGridCacheSize); /* drawNineGridCacheSize (2 bytes) */
2019 Stream_Read_UINT16(s,
2020 settings->DrawNineGridCacheEntries); /* drawNineGridCacheEntries (2 bytes) */
2021
2022 if ((drawNineGridSupportLevel & DRAW_NINEGRID_SUPPORTED) ||
2023 (drawNineGridSupportLevel & DRAW_NINEGRID_SUPPORTED_V2))
2024 settings->DrawNineGridEnabled = TRUE;
2025
2026 return TRUE;
2027 }
2028
2029 /**
2030 * Write drawn nine grid cache capability set.\n
2031 * @msdn{cc241565}
2032 * @param s stream
2033 * @param settings settings
2034 */
2035
rdp_write_draw_nine_grid_cache_capability_set(wStream * s,const rdpSettings * settings)2036 static BOOL rdp_write_draw_nine_grid_cache_capability_set(wStream* s, const rdpSettings* settings)
2037 {
2038 size_t header;
2039 UINT32 drawNineGridSupportLevel;
2040
2041 if (!Stream_EnsureRemainingCapacity(s, 32))
2042 return FALSE;
2043
2044 header = rdp_capability_set_start(s);
2045 if (header > UINT16_MAX)
2046 return FALSE;
2047 drawNineGridSupportLevel =
2048 (settings->DrawNineGridEnabled) ? DRAW_NINEGRID_SUPPORTED_V2 : DRAW_NINEGRID_NO_SUPPORT;
2049 Stream_Write_UINT32(s, drawNineGridSupportLevel); /* drawNineGridSupportLevel (4 bytes) */
2050 Stream_Write_UINT16(s, settings->DrawNineGridCacheSize); /* drawNineGridCacheSize (2 bytes) */
2051 Stream_Write_UINT16(
2052 s, settings->DrawNineGridCacheEntries); /* drawNineGridCacheEntries (2 bytes) */
2053 return rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_NINE_GRID_CACHE);
2054 }
2055
rdp_write_gdiplus_cache_entries(wStream * s,UINT16 gce,UINT16 bce,UINT16 pce,UINT16 ice,UINT16 ace)2056 static void rdp_write_gdiplus_cache_entries(wStream* s, UINT16 gce, UINT16 bce, UINT16 pce,
2057 UINT16 ice, UINT16 ace)
2058 {
2059 Stream_Write_UINT16(s, gce); /* gdipGraphicsCacheEntries (2 bytes) */
2060 Stream_Write_UINT16(s, bce); /* gdipBrushCacheEntries (2 bytes) */
2061 Stream_Write_UINT16(s, pce); /* gdipPenCacheEntries (2 bytes) */
2062 Stream_Write_UINT16(s, ice); /* gdipImageCacheEntries (2 bytes) */
2063 Stream_Write_UINT16(s, ace); /* gdipImageAttributesCacheEntries (2 bytes) */
2064 }
2065
rdp_write_gdiplus_cache_chunk_size(wStream * s,UINT16 gccs,UINT16 obccs,UINT16 opccs,UINT16 oiaccs)2066 static void rdp_write_gdiplus_cache_chunk_size(wStream* s, UINT16 gccs, UINT16 obccs, UINT16 opccs,
2067 UINT16 oiaccs)
2068 {
2069 Stream_Write_UINT16(s, gccs); /* gdipGraphicsCacheChunkSize (2 bytes) */
2070 Stream_Write_UINT16(s, obccs); /* gdipObjectBrushCacheChunkSize (2 bytes) */
2071 Stream_Write_UINT16(s, opccs); /* gdipObjectPenCacheChunkSize (2 bytes) */
2072 Stream_Write_UINT16(s, oiaccs); /* gdipObjectImageAttributesCacheChunkSize (2 bytes) */
2073 }
2074
rdp_write_gdiplus_image_cache_properties(wStream * s,UINT16 oiccs,UINT16 oicts,UINT16 oicms)2075 static void rdp_write_gdiplus_image_cache_properties(wStream* s, UINT16 oiccs, UINT16 oicts,
2076 UINT16 oicms)
2077 {
2078 Stream_Write_UINT16(s, oiccs); /* gdipObjectImageCacheChunkSize (2 bytes) */
2079 Stream_Write_UINT16(s, oicts); /* gdipObjectImageCacheTotalSize (2 bytes) */
2080 Stream_Write_UINT16(s, oicms); /* gdipObjectImageCacheMaxSize (2 bytes) */
2081 }
2082
2083 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_draw_nine_grid_cache_capability_set(wStream * s)2084 static BOOL rdp_print_draw_nine_grid_cache_capability_set(wStream* s)
2085 {
2086 UINT32 drawNineGridSupportLevel;
2087 UINT16 DrawNineGridCacheSize;
2088 UINT16 DrawNineGridCacheEntries;
2089 WLog_INFO(TAG,
2090 "DrawNineGridCacheCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
2091
2092 if (Stream_GetRemainingLength(s) < 8)
2093 return FALSE;
2094
2095 Stream_Read_UINT32(s, drawNineGridSupportLevel); /* drawNineGridSupportLevel (4 bytes) */
2096 Stream_Read_UINT16(s, DrawNineGridCacheSize); /* drawNineGridCacheSize (2 bytes) */
2097 Stream_Read_UINT16(s, DrawNineGridCacheEntries); /* drawNineGridCacheEntries (2 bytes) */
2098 return TRUE;
2099 }
2100 #endif
2101
2102 /**
2103 * Read GDI+ cache capability set.\n
2104 * @msdn{cc241566}
2105 * @param s stream
2106 * @param settings settings
2107 * @return if the operation completed successfully
2108 */
2109
rdp_read_draw_gdiplus_cache_capability_set(wStream * s,rdpSettings * settings)2110 static BOOL rdp_read_draw_gdiplus_cache_capability_set(wStream* s, rdpSettings* settings)
2111 {
2112 UINT32 drawGDIPlusSupportLevel;
2113 UINT32 drawGdiplusCacheLevel;
2114
2115 if (Stream_GetRemainingLength(s) < 36)
2116 return FALSE;
2117
2118 Stream_Read_UINT32(s, drawGDIPlusSupportLevel); /* drawGDIPlusSupportLevel (4 bytes) */
2119 Stream_Seek_UINT32(s); /* GdipVersion (4 bytes) */
2120 Stream_Read_UINT32(s, drawGdiplusCacheLevel); /* drawGdiplusCacheLevel (4 bytes) */
2121 Stream_Seek(s, 10); /* GdipCacheEntries (10 bytes) */
2122 Stream_Seek(s, 8); /* GdipCacheChunkSize (8 bytes) */
2123 Stream_Seek(s, 6); /* GdipImageCacheProperties (6 bytes) */
2124
2125 if (drawGDIPlusSupportLevel & DRAW_GDIPLUS_SUPPORTED)
2126 settings->DrawGdiPlusEnabled = TRUE;
2127
2128 if (drawGdiplusCacheLevel & DRAW_GDIPLUS_CACHE_LEVEL_ONE)
2129 settings->DrawGdiPlusCacheEnabled = TRUE;
2130
2131 return TRUE;
2132 }
2133
2134 /**
2135 * Write GDI+ cache capability set.\n
2136 * @msdn{cc241566}
2137 * @param s stream
2138 * @param settings settings
2139 */
2140
rdp_write_draw_gdiplus_cache_capability_set(wStream * s,const rdpSettings * settings)2141 static BOOL rdp_write_draw_gdiplus_cache_capability_set(wStream* s, const rdpSettings* settings)
2142 {
2143 size_t header;
2144 UINT32 drawGDIPlusSupportLevel;
2145 UINT32 drawGdiplusCacheLevel;
2146
2147 if (!Stream_EnsureRemainingCapacity(s, 64))
2148 return FALSE;
2149
2150 header = rdp_capability_set_start(s);
2151 if (header > UINT16_MAX)
2152 return FALSE;
2153 drawGDIPlusSupportLevel =
2154 (settings->DrawGdiPlusEnabled) ? DRAW_GDIPLUS_SUPPORTED : DRAW_GDIPLUS_DEFAULT;
2155 drawGdiplusCacheLevel = (settings->DrawGdiPlusEnabled) ? DRAW_GDIPLUS_CACHE_LEVEL_ONE
2156 : DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT;
2157 Stream_Write_UINT32(s, drawGDIPlusSupportLevel); /* drawGDIPlusSupportLevel (4 bytes) */
2158 Stream_Write_UINT32(s, 0); /* GdipVersion (4 bytes) */
2159 Stream_Write_UINT32(s, drawGdiplusCacheLevel); /* drawGdiplusCacheLevel (4 bytes) */
2160 rdp_write_gdiplus_cache_entries(s, 10, 5, 5, 10, 2); /* GdipCacheEntries (10 bytes) */
2161 rdp_write_gdiplus_cache_chunk_size(s, 512, 2048, 1024, 64); /* GdipCacheChunkSize (8 bytes) */
2162 rdp_write_gdiplus_image_cache_properties(s, 4096, 256,
2163 128); /* GdipImageCacheProperties (6 bytes) */
2164 return rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_GDI_PLUS);
2165 }
2166
2167 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_draw_gdiplus_cache_capability_set(wStream * s)2168 static BOOL rdp_print_draw_gdiplus_cache_capability_set(wStream* s)
2169 {
2170 UINT32 drawGdiPlusSupportLevel;
2171 UINT32 GdipVersion;
2172 UINT32 drawGdiplusCacheLevel;
2173 WLog_INFO(TAG,
2174 "DrawGdiPlusCacheCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
2175
2176 if (Stream_GetRemainingLength(s) < 36)
2177 return FALSE;
2178
2179 Stream_Read_UINT32(s, drawGdiPlusSupportLevel); /* drawGdiPlusSupportLevel (4 bytes) */
2180 Stream_Read_UINT32(s, GdipVersion); /* GdipVersion (4 bytes) */
2181 Stream_Read_UINT32(s, drawGdiplusCacheLevel); /* drawGdiPlusCacheLevel (4 bytes) */
2182 Stream_Seek(s, 10); /* GdipCacheEntries (10 bytes) */
2183 Stream_Seek(s, 8); /* GdipCacheChunkSize (8 bytes) */
2184 Stream_Seek(s, 6); /* GdipImageCacheProperties (6 bytes) */
2185 return TRUE;
2186 }
2187 #endif
2188
2189 /**
2190 * Read remote programs capability set.\n
2191 * @msdn{cc242518}
2192 * @param s stream
2193 * @param settings settings
2194 * @return if the operation completed successfully
2195 */
2196
rdp_read_remote_programs_capability_set(wStream * s,rdpSettings * settings)2197 static BOOL rdp_read_remote_programs_capability_set(wStream* s, rdpSettings* settings)
2198 {
2199 UINT32 railSupportLevel;
2200
2201 if (Stream_GetRemainingLength(s) < 4)
2202 return FALSE;
2203
2204 Stream_Read_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */
2205
2206 if ((railSupportLevel & RAIL_LEVEL_SUPPORTED) == 0)
2207 {
2208 if (settings->RemoteApplicationMode == TRUE)
2209 {
2210 /* RemoteApp Failure! */
2211 settings->RemoteApplicationMode = FALSE;
2212 }
2213 }
2214
2215 /* 2.2.2.2.3 HandshakeEx PDU (TS_RAIL_ORDER_HANDSHAKE_EX)
2216 * the handshake ex pdu is supported when both, client and server announce
2217 * it OR if we are ready to begin enhanced remoteAPP mode. */
2218 if (settings->RemoteApplicationMode)
2219 railSupportLevel |= RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
2220
2221 settings->RemoteApplicationSupportLevel =
2222 railSupportLevel & settings->RemoteApplicationSupportMask;
2223 return TRUE;
2224 }
2225
2226 /**
2227 * Write remote programs capability set.\n
2228 * @msdn{cc242518}
2229 * @param s stream
2230 * @param settings settings
2231 */
2232
rdp_write_remote_programs_capability_set(wStream * s,const rdpSettings * settings)2233 static BOOL rdp_write_remote_programs_capability_set(wStream* s, const rdpSettings* settings)
2234 {
2235 size_t header;
2236 UINT32 railSupportLevel;
2237
2238 if (!Stream_EnsureRemainingCapacity(s, 64))
2239 return FALSE;
2240
2241 header = rdp_capability_set_start(s);
2242 if (header > UINT16_MAX)
2243 return FALSE;
2244 railSupportLevel = RAIL_LEVEL_SUPPORTED;
2245
2246 if (settings->RemoteApplicationSupportLevel & RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)
2247 {
2248 if (settings->RemoteAppLanguageBarSupported)
2249 railSupportLevel |= RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED;
2250 }
2251
2252 railSupportLevel |= RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED;
2253 railSupportLevel |= RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED;
2254 railSupportLevel |= RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED;
2255 railSupportLevel |= RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED;
2256 railSupportLevel |= RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED;
2257 railSupportLevel |= RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
2258 /* Mask out everything the server does not support. */
2259 railSupportLevel &= settings->RemoteApplicationSupportLevel;
2260 Stream_Write_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */
2261 return rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL);
2262 }
2263
2264 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_remote_programs_capability_set(wStream * s)2265 static BOOL rdp_print_remote_programs_capability_set(wStream* s)
2266 {
2267 UINT32 railSupportLevel;
2268 WLog_INFO(TAG,
2269 "RemoteProgramsCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
2270
2271 if (Stream_GetRemainingLength(s) < 4)
2272 return FALSE;
2273
2274 Stream_Read_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */
2275 WLog_INFO(TAG, "\trailSupportLevel: 0x%08" PRIX32 "", railSupportLevel);
2276 return TRUE;
2277 }
2278 #endif
2279
2280 /**
2281 * Read window list capability set.\n
2282 * @msdn{cc242564}
2283 * @param s stream
2284 * @param settings settings
2285 * @return if the operation completed successfully
2286 */
2287
rdp_read_window_list_capability_set(wStream * s,rdpSettings * settings)2288 static BOOL rdp_read_window_list_capability_set(wStream* s, rdpSettings* settings)
2289 {
2290 if (Stream_GetRemainingLength(s) < 7)
2291 return FALSE;
2292
2293 Stream_Read_UINT32(s, settings->RemoteWndSupportLevel); /* wndSupportLevel (4 bytes) */
2294 Stream_Read_UINT8(s, settings->RemoteAppNumIconCaches); /* numIconCaches (1 byte) */
2295 Stream_Read_UINT16(s,
2296 settings->RemoteAppNumIconCacheEntries); /* numIconCacheEntries (2 bytes) */
2297 return TRUE;
2298 }
2299
2300 /**
2301 * Write window list capability set.\n
2302 * @msdn{cc242564}
2303 * @param s stream
2304 * @param settings settings
2305 */
2306
rdp_write_window_list_capability_set(wStream * s,const rdpSettings * settings)2307 static BOOL rdp_write_window_list_capability_set(wStream* s, const rdpSettings* settings)
2308 {
2309 size_t header;
2310
2311 if (!Stream_EnsureRemainingCapacity(s, 32))
2312 return FALSE;
2313
2314 header = rdp_capability_set_start(s);
2315 if (header > UINT16_MAX)
2316 return FALSE;
2317 Stream_Write_UINT32(s, settings->RemoteWndSupportLevel); /* wndSupportLevel (4 bytes) */
2318 Stream_Write_UINT8(s, settings->RemoteAppNumIconCaches); /* numIconCaches (1 byte) */
2319 Stream_Write_UINT16(s,
2320 settings->RemoteAppNumIconCacheEntries); /* numIconCacheEntries (2 bytes) */
2321 return rdp_capability_set_finish(s, header, CAPSET_TYPE_WINDOW);
2322 }
2323
2324 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_window_list_capability_set(wStream * s)2325 static BOOL rdp_print_window_list_capability_set(wStream* s)
2326 {
2327 UINT32 wndSupportLevel;
2328 BYTE numIconCaches;
2329 UINT16 numIconCacheEntries;
2330 WLog_INFO(TAG, "WindowListCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
2331
2332 if (Stream_GetRemainingLength(s) < 7)
2333 return FALSE;
2334
2335 Stream_Read_UINT32(s, wndSupportLevel); /* wndSupportLevel (4 bytes) */
2336 Stream_Read_UINT8(s, numIconCaches); /* numIconCaches (1 byte) */
2337 Stream_Read_UINT16(s, numIconCacheEntries); /* numIconCacheEntries (2 bytes) */
2338 WLog_INFO(TAG, "\twndSupportLevel: 0x%08" PRIX32 "", wndSupportLevel);
2339 WLog_INFO(TAG, "\tnumIconCaches: 0x%02" PRIX8 "", numIconCaches);
2340 WLog_INFO(TAG, "\tnumIconCacheEntries: 0x%04" PRIX16 "", numIconCacheEntries);
2341 return TRUE;
2342 }
2343 #endif
2344
2345 /**
2346 * Read desktop composition capability set.\n
2347 * @msdn{cc240855}
2348 * @param s stream
2349 * @param settings settings
2350 * @return if the operation completed successfully
2351 */
2352
rdp_read_desktop_composition_capability_set(wStream * s,rdpSettings * settings)2353 static BOOL rdp_read_desktop_composition_capability_set(wStream* s, rdpSettings* settings)
2354 {
2355 WINPR_UNUSED(settings);
2356 if (Stream_GetRemainingLength(s) < 2)
2357 return FALSE;
2358
2359 Stream_Seek_UINT16(s); /* compDeskSupportLevel (2 bytes) */
2360 return TRUE;
2361 }
2362
2363 /**
2364 * Write desktop composition capability set.\n
2365 * @msdn{cc240855}
2366 * @param s stream
2367 * @param settings settings
2368 */
2369
rdp_write_desktop_composition_capability_set(wStream * s,const rdpSettings * settings)2370 static BOOL rdp_write_desktop_composition_capability_set(wStream* s, const rdpSettings* settings)
2371 {
2372 size_t header;
2373 UINT16 compDeskSupportLevel;
2374
2375 if (!Stream_EnsureRemainingCapacity(s, 32))
2376 return FALSE;
2377
2378 header = rdp_capability_set_start(s);
2379 if (header > UINT16_MAX)
2380 return FALSE;
2381 compDeskSupportLevel =
2382 (settings->AllowDesktopComposition) ? COMPDESK_SUPPORTED : COMPDESK_NOT_SUPPORTED;
2383 Stream_Write_UINT16(s, compDeskSupportLevel); /* compDeskSupportLevel (2 bytes) */
2384 return rdp_capability_set_finish(s, header, CAPSET_TYPE_COMP_DESK);
2385 }
2386
2387 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_desktop_composition_capability_set(wStream * s)2388 static BOOL rdp_print_desktop_composition_capability_set(wStream* s)
2389 {
2390 UINT16 compDeskSupportLevel;
2391 WLog_INFO(TAG,
2392 "DesktopCompositionCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
2393
2394 if (Stream_GetRemainingLength(s) < 2)
2395 return FALSE;
2396
2397 Stream_Read_UINT16(s, compDeskSupportLevel); /* compDeskSupportLevel (2 bytes) */
2398 WLog_INFO(TAG, "\tcompDeskSupportLevel: 0x%04" PRIX16 "", compDeskSupportLevel);
2399 return TRUE;
2400 }
2401 #endif
2402
2403 /**
2404 * Read multifragment update capability set.\n
2405 * @msdn{cc240649}
2406 * @param s stream
2407 * @param settings settings
2408 * @return if the operation completed successfully
2409 */
2410
rdp_read_multifragment_update_capability_set(wStream * s,rdpSettings * settings)2411 static BOOL rdp_read_multifragment_update_capability_set(wStream* s, rdpSettings* settings)
2412 {
2413 UINT32 multifragMaxRequestSize;
2414
2415 if (Stream_GetRemainingLength(s) < 4)
2416 return FALSE;
2417
2418 Stream_Read_UINT32(s, multifragMaxRequestSize); /* MaxRequestSize (4 bytes) */
2419
2420 if (settings->ServerMode)
2421 {
2422 /*
2423 * Special case: The client announces multifragment update support but sets the maximum
2424 * request size to something smaller than maximum size for *one* fast-path PDU. In this case
2425 * behave like no multifragment updates were supported and make sure no fragmentation
2426 * happens by setting FASTPATH_FRAGMENT_SAFE_SIZE.
2427 *
2428 * This behaviour was observed with some windows ce rdp clients.
2429 */
2430 if (multifragMaxRequestSize < FASTPATH_MAX_PACKET_SIZE)
2431 multifragMaxRequestSize = FASTPATH_FRAGMENT_SAFE_SIZE;
2432
2433 if (settings->RemoteFxCodec)
2434 {
2435 /**
2436 * If we are using RemoteFX the client MUST use a value greater
2437 * than or equal to the value we've previously sent in the server to
2438 * client multi-fragment update capability set (MS-RDPRFX 1.5)
2439 */
2440 if (multifragMaxRequestSize < settings->MultifragMaxRequestSize)
2441 {
2442 /**
2443 * If it happens to be smaller we honor the client's value but
2444 * have to disable RemoteFX
2445 */
2446 settings->RemoteFxCodec = FALSE;
2447 settings->MultifragMaxRequestSize = multifragMaxRequestSize;
2448 }
2449 else
2450 {
2451 /* no need to increase server's max request size setting here */
2452 }
2453 }
2454 else
2455 {
2456 settings->MultifragMaxRequestSize = multifragMaxRequestSize;
2457 }
2458 }
2459 else
2460 {
2461 /**
2462 * In client mode we keep up with the server's capabilites.
2463 * In RemoteFX mode we MUST do this but it might also be useful to
2464 * receive larger related bitmap updates.
2465 */
2466 if (multifragMaxRequestSize > settings->MultifragMaxRequestSize)
2467 settings->MultifragMaxRequestSize = multifragMaxRequestSize;
2468 }
2469
2470 return TRUE;
2471 }
2472
2473 /**
2474 * Write multifragment update capability set.\n
2475 * @msdn{cc240649}
2476 * @param s stream
2477 * @param settings settings
2478 */
2479
rdp_write_multifragment_update_capability_set(wStream * s,rdpSettings * settings)2480 static BOOL rdp_write_multifragment_update_capability_set(wStream* s, rdpSettings* settings)
2481 {
2482 size_t header;
2483
2484 if (settings->ServerMode && settings->MultifragMaxRequestSize == 0)
2485 {
2486 /**
2487 * In server mode we prefer to use the highest useful request size that
2488 * will allow us to pack a complete screen update into a single fast
2489 * path PDU using any of the supported codecs.
2490 * However, the client is completely free to accept our proposed
2491 * max request size or send a different value in the client-to-server
2492 * multi-fragment update capability set and we have to accept that,
2493 * unless we are using RemoteFX where the client MUST announce a value
2494 * greater than or equal to the value we're sending here.
2495 * See [MS-RDPRFX 1.5 capability #2]
2496 */
2497 UINT32 tileNumX = (settings->DesktopWidth + 63) / 64;
2498 UINT32 tileNumY = (settings->DesktopHeight + 63) / 64;
2499 settings->MultifragMaxRequestSize = tileNumX * tileNumY * 16384;
2500 /* and add room for headers, regions, frame markers, etc. */
2501 settings->MultifragMaxRequestSize += 16384;
2502 }
2503
2504 if (!Stream_EnsureRemainingCapacity(s, 32))
2505 return FALSE;
2506 header = rdp_capability_set_start(s);
2507 if (header > UINT16_MAX)
2508 return FALSE;
2509 Stream_Write_UINT32(s, settings->MultifragMaxRequestSize); /* MaxRequestSize (4 bytes) */
2510 return rdp_capability_set_finish(s, header, CAPSET_TYPE_MULTI_FRAGMENT_UPDATE);
2511 }
2512
2513 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_multifragment_update_capability_set(wStream * s)2514 static BOOL rdp_print_multifragment_update_capability_set(wStream* s)
2515 {
2516 UINT32 maxRequestSize;
2517 WLog_INFO(
2518 TAG, "MultifragmentUpdateCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
2519
2520 if (Stream_GetRemainingLength(s) < 4)
2521 return FALSE;
2522
2523 Stream_Read_UINT32(s, maxRequestSize); /* maxRequestSize (4 bytes) */
2524 WLog_INFO(TAG, "\tmaxRequestSize: 0x%08" PRIX32 "", maxRequestSize);
2525 return TRUE;
2526 }
2527 #endif
2528
2529 /**
2530 * Read large pointer capability set.\n
2531 * @msdn{cc240650}
2532 * @param s stream
2533 * @param settings settings
2534 * @return if the operation completed successfully
2535 */
2536
rdp_read_large_pointer_capability_set(wStream * s,rdpSettings * settings)2537 static BOOL rdp_read_large_pointer_capability_set(wStream* s, rdpSettings* settings)
2538 {
2539 UINT16 largePointerSupportFlags;
2540
2541 if (Stream_GetRemainingLength(s) < 2)
2542 return FALSE;
2543
2544 Stream_Read_UINT16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */
2545 settings->LargePointerFlag &= largePointerSupportFlags;
2546 if ((largePointerSupportFlags & ~(LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384)) != 0)
2547 {
2548 WLog_WARN(
2549 TAG,
2550 "TS_LARGE_POINTER_CAPABILITYSET with unsupported flags %04X (all flags %04X) received",
2551 largePointerSupportFlags & ~(LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384),
2552 largePointerSupportFlags);
2553 }
2554 return TRUE;
2555 }
2556
2557 /**
2558 * Write large pointer capability set.\n
2559 * @msdn{cc240650}
2560 * @param s stream
2561 * @param settings settings
2562 */
2563
rdp_write_large_pointer_capability_set(wStream * s,const rdpSettings * settings)2564 static BOOL rdp_write_large_pointer_capability_set(wStream* s, const rdpSettings* settings)
2565 {
2566 size_t header;
2567 UINT16 largePointerSupportFlags;
2568
2569 if (!Stream_EnsureRemainingCapacity(s, 32))
2570 return FALSE;
2571
2572 header = rdp_capability_set_start(s);
2573 if (header > UINT16_MAX)
2574 return FALSE;
2575 largePointerSupportFlags =
2576 settings->LargePointerFlag & (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384);
2577 Stream_Write_UINT16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */
2578 return rdp_capability_set_finish(s, header, CAPSET_TYPE_LARGE_POINTER);
2579 }
2580
2581 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_large_pointer_capability_set(wStream * s)2582 static BOOL rdp_print_large_pointer_capability_set(wStream* s)
2583 {
2584 UINT16 largePointerSupportFlags;
2585 WLog_INFO(TAG, "LargePointerCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
2586
2587 if (Stream_GetRemainingLength(s) < 2)
2588 return FALSE;
2589
2590 Stream_Read_UINT16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */
2591 WLog_INFO(TAG, "\tlargePointerSupportFlags: 0x%04" PRIX16 "", largePointerSupportFlags);
2592 return TRUE;
2593 }
2594 #endif
2595
2596 /**
2597 * Read surface commands capability set.\n
2598 * @msdn{dd871563}
2599 * @param s stream
2600 * @param settings settings
2601 * @return if the operation completed successfully
2602 */
2603
rdp_read_surface_commands_capability_set(wStream * s,rdpSettings * settings)2604 static BOOL rdp_read_surface_commands_capability_set(wStream* s, rdpSettings* settings)
2605 {
2606 UINT32 cmdFlags;
2607
2608 if (Stream_GetRemainingLength(s) < 8)
2609 return FALSE;
2610
2611 Stream_Read_UINT32(s, cmdFlags); /* cmdFlags (4 bytes) */
2612 Stream_Seek_UINT32(s); /* reserved (4 bytes) */
2613 settings->SurfaceCommandsEnabled = TRUE;
2614 settings->SurfaceFrameMarkerEnabled = (cmdFlags & SURFCMDS_FRAME_MARKER) ? TRUE : FALSE;
2615 return TRUE;
2616 }
2617
2618 /**
2619 * Write surface commands capability set.\n
2620 * @msdn{dd871563}
2621 * @param s stream
2622 * @param settings settings
2623 */
2624
rdp_write_surface_commands_capability_set(wStream * s,const rdpSettings * settings)2625 static BOOL rdp_write_surface_commands_capability_set(wStream* s, const rdpSettings* settings)
2626 {
2627 size_t header;
2628 UINT32 cmdFlags;
2629
2630 if (!Stream_EnsureRemainingCapacity(s, 32))
2631 return FALSE;
2632
2633 header = rdp_capability_set_start(s);
2634 if (header > UINT16_MAX)
2635 return FALSE;
2636 cmdFlags = SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS;
2637
2638 if (settings->SurfaceFrameMarkerEnabled)
2639 cmdFlags |= SURFCMDS_FRAME_MARKER;
2640
2641 Stream_Write_UINT32(s, cmdFlags); /* cmdFlags (4 bytes) */
2642 Stream_Write_UINT32(s, 0); /* reserved (4 bytes) */
2643 return rdp_capability_set_finish(s, header, CAPSET_TYPE_SURFACE_COMMANDS);
2644 }
2645
2646 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_surface_commands_capability_set(wStream * s)2647 static BOOL rdp_print_surface_commands_capability_set(wStream* s)
2648 {
2649 UINT32 cmdFlags;
2650 UINT32 reserved;
2651 WLog_INFO(TAG,
2652 "SurfaceCommandsCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
2653
2654 if (Stream_GetRemainingLength(s) < 8)
2655 return FALSE;
2656
2657 Stream_Read_UINT32(s, cmdFlags); /* cmdFlags (4 bytes) */
2658 Stream_Read_UINT32(s, reserved); /* reserved (4 bytes) */
2659 WLog_INFO(TAG, "\tcmdFlags: 0x%08" PRIX32 "", cmdFlags);
2660 WLog_INFO(TAG, "\treserved: 0x%08" PRIX32 "", reserved);
2661 return TRUE;
2662 }
2663
rdp_print_bitmap_codec_guid(const GUID * guid)2664 static void rdp_print_bitmap_codec_guid(const GUID* guid)
2665 {
2666 WLog_INFO(TAG,
2667 "%08" PRIX32 "%04" PRIX16 "%04" PRIX16 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8
2668 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "",
2669 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2],
2670 guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
2671 }
2672
rdp_get_bitmap_codec_guid_name(const GUID * guid)2673 static char* rdp_get_bitmap_codec_guid_name(const GUID* guid)
2674 {
2675 RPC_STATUS rpc_status;
2676
2677 if (UuidEqual(guid, &CODEC_GUID_REMOTEFX, &rpc_status))
2678 return "CODEC_GUID_REMOTEFX";
2679 else if (UuidEqual(guid, &CODEC_GUID_NSCODEC, &rpc_status))
2680 return "CODEC_GUID_NSCODEC";
2681 else if (UuidEqual(guid, &CODEC_GUID_IGNORE, &rpc_status))
2682 return "CODEC_GUID_IGNORE";
2683 else if (UuidEqual(guid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status))
2684 return "CODEC_GUID_IMAGE_REMOTEFX";
2685
2686 #if defined(WITH_JPEG)
2687 else if (UuidEqual(guid, &CODEC_GUID_JPEG, &rpc_status))
2688 return "CODEC_GUID_JPEG";
2689
2690 #endif
2691 return "CODEC_GUID_UNKNOWN";
2692 }
2693 #endif
2694
rdp_read_bitmap_codec_guid(wStream * s,GUID * guid)2695 static BOOL rdp_read_bitmap_codec_guid(wStream* s, GUID* guid)
2696 {
2697 BYTE g[16];
2698 if (Stream_GetRemainingLength(s) < 16)
2699 return FALSE;
2700 Stream_Read(s, g, 16);
2701 guid->Data1 = ((UINT32)g[3] << 24U) | ((UINT32)g[2] << 16U) | (g[1] << 8U) | g[0];
2702 guid->Data2 = (g[5] << 8U) | g[4];
2703 guid->Data3 = (g[7] << 8U) | g[6];
2704 guid->Data4[0] = g[8];
2705 guid->Data4[1] = g[9];
2706 guid->Data4[2] = g[10];
2707 guid->Data4[3] = g[11];
2708 guid->Data4[4] = g[12];
2709 guid->Data4[5] = g[13];
2710 guid->Data4[6] = g[14];
2711 guid->Data4[7] = g[15];
2712 return TRUE;
2713 }
2714
rdp_write_bitmap_codec_guid(wStream * s,const GUID * guid)2715 static void rdp_write_bitmap_codec_guid(wStream* s, const GUID* guid)
2716 {
2717 BYTE g[16];
2718 g[0] = guid->Data1 & 0xFF;
2719 g[1] = (guid->Data1 >> 8) & 0xFF;
2720 g[2] = (guid->Data1 >> 16) & 0xFF;
2721 g[3] = (guid->Data1 >> 24) & 0xFF;
2722 g[4] = (guid->Data2) & 0xFF;
2723 g[5] = (guid->Data2 >> 8) & 0xFF;
2724 g[6] = (guid->Data3) & 0xFF;
2725 g[7] = (guid->Data3 >> 8) & 0xFF;
2726 g[8] = guid->Data4[0];
2727 g[9] = guid->Data4[1];
2728 g[10] = guid->Data4[2];
2729 g[11] = guid->Data4[3];
2730 g[12] = guid->Data4[4];
2731 g[13] = guid->Data4[5];
2732 g[14] = guid->Data4[6];
2733 g[15] = guid->Data4[7];
2734 Stream_Write(s, g, 16);
2735 }
2736
2737 /**
2738 * Read bitmap codecs capability set.\n
2739 * @msdn{dd891377}
2740 * @param s stream
2741 * @param settings settings
2742 * @return if the operation completed successfully
2743 */
2744
rdp_read_bitmap_codecs_capability_set(wStream * s,rdpSettings * settings)2745 static BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings)
2746 {
2747 BYTE codecId;
2748 GUID codecGuid;
2749 RPC_STATUS rpc_status;
2750 BYTE bitmapCodecCount;
2751 UINT16 codecPropertiesLength;
2752
2753 BOOL guidNSCodec = FALSE;
2754 BOOL guidRemoteFx = FALSE;
2755 BOOL guidRemoteFxImage = FALSE;
2756
2757 if (Stream_GetRemainingLength(s) < 1)
2758 return FALSE;
2759
2760 Stream_Read_UINT8(s, bitmapCodecCount); /* bitmapCodecCount (1 byte) */
2761
2762 while (bitmapCodecCount > 0)
2763 {
2764 size_t rest;
2765 wStream sub;
2766 if (!rdp_read_bitmap_codec_guid(s, &codecGuid)) /* codecGuid (16 bytes) */
2767 return FALSE;
2768 if (Stream_GetRemainingLength(s) < 3)
2769 return FALSE;
2770 Stream_Read_UINT8(s, codecId); /* codecId (1 byte) */
2771 Stream_Read_UINT16(s, codecPropertiesLength); /* codecPropertiesLength (2 bytes) */
2772
2773 Stream_StaticInit(&sub, Stream_Pointer(s), codecPropertiesLength);
2774 if (!Stream_SafeSeek(s, codecPropertiesLength))
2775 return FALSE;
2776
2777 if (settings->ServerMode)
2778 {
2779 if (UuidEqual(&codecGuid, &CODEC_GUID_REMOTEFX, &rpc_status))
2780 {
2781 UINT32 rfxCapsLength;
2782 UINT32 rfxPropsLength;
2783 UINT32 captureFlags;
2784 guidRemoteFx = TRUE;
2785 settings->RemoteFxCodecId = codecId;
2786 if (Stream_GetRemainingLength(&sub) < 12)
2787 return FALSE;
2788 Stream_Read_UINT32(&sub, rfxPropsLength); /* length (4 bytes) */
2789 Stream_Read_UINT32(&sub, captureFlags); /* captureFlags (4 bytes) */
2790 Stream_Read_UINT32(&sub, rfxCapsLength); /* capsLength (4 bytes) */
2791 settings->RemoteFxCaptureFlags = captureFlags;
2792 settings->RemoteFxOnly = (captureFlags & CARDP_CAPS_CAPTURE_NON_CAC) ? TRUE : FALSE;
2793
2794 if (rfxCapsLength)
2795 {
2796 UINT16 blockType;
2797 UINT32 blockLen;
2798 UINT16 numCapsets;
2799 BYTE rfxCodecId;
2800 UINT16 capsetType;
2801 UINT16 numIcaps;
2802 UINT16 icapLen;
2803 /* TS_RFX_CAPS */
2804 if (Stream_GetRemainingLength(&sub) < 21)
2805 return FALSE;
2806 Stream_Read_UINT16(&sub, blockType); /* blockType (2 bytes) */
2807 Stream_Read_UINT32(&sub, blockLen); /* blockLen (4 bytes) */
2808 Stream_Read_UINT16(&sub, numCapsets); /* numCapsets (2 bytes) */
2809
2810 if (blockType != 0xCBC0)
2811 return FALSE;
2812
2813 if (blockLen != 8)
2814 return FALSE;
2815
2816 if (numCapsets != 1)
2817 return FALSE;
2818
2819 /* TS_RFX_CAPSET */
2820 Stream_Read_UINT16(&sub, blockType); /* blockType (2 bytes) */
2821 Stream_Read_UINT32(&sub, blockLen); /* blockLen (4 bytes) */
2822 Stream_Read_UINT8(&sub, rfxCodecId); /* codecId (1 byte) */
2823 Stream_Read_UINT16(&sub, capsetType); /* capsetType (2 bytes) */
2824 Stream_Read_UINT16(&sub, numIcaps); /* numIcaps (2 bytes) */
2825 Stream_Read_UINT16(&sub, icapLen); /* icapLen (2 bytes) */
2826
2827 if (blockType != 0xCBC1)
2828 return FALSE;
2829
2830 if (rfxCodecId != 1)
2831 return FALSE;
2832
2833 if (capsetType != 0xCFC0)
2834 return FALSE;
2835
2836 while (numIcaps--)
2837 {
2838 UINT16 version;
2839 UINT16 tileSize;
2840 BYTE codecFlags;
2841 BYTE colConvBits;
2842 BYTE transformBits;
2843 BYTE entropyBits;
2844 /* TS_RFX_ICAP */
2845 if (Stream_GetRemainingLength(&sub) < 8)
2846 return FALSE;
2847 Stream_Read_UINT16(&sub, version); /* version (2 bytes) */
2848 Stream_Read_UINT16(&sub, tileSize); /* tileSize (2 bytes) */
2849 Stream_Read_UINT8(&sub, codecFlags); /* flags (1 byte) */
2850 Stream_Read_UINT8(&sub, colConvBits); /* colConvBits (1 byte) */
2851 Stream_Read_UINT8(&sub, transformBits); /* transformBits (1 byte) */
2852 Stream_Read_UINT8(&sub, entropyBits); /* entropyBits (1 byte) */
2853
2854 if (version == 0x0009)
2855 {
2856 /* Version 0.9 */
2857 if (tileSize != 0x0080)
2858 return FALSE;
2859 }
2860 else if (version == 0x0100)
2861 {
2862 /* Version 1.0 */
2863 if (tileSize != 0x0040)
2864 return FALSE;
2865 }
2866 else
2867 return FALSE;
2868
2869 if (colConvBits != 1)
2870 return FALSE;
2871
2872 if (transformBits != 1)
2873 return FALSE;
2874 }
2875 }
2876 }
2877 else if (UuidEqual(&codecGuid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status))
2878 {
2879 /* Microsoft RDP servers ignore CODEC_GUID_IMAGE_REMOTEFX codec properties */
2880 guidRemoteFxImage = TRUE;
2881 if (!Stream_SafeSeek(&sub, codecPropertiesLength)) /* codecProperties */
2882 return FALSE;
2883 }
2884 else if (UuidEqual(&codecGuid, &CODEC_GUID_NSCODEC, &rpc_status))
2885 {
2886 BYTE colorLossLevel;
2887 BYTE fAllowSubsampling;
2888 BYTE fAllowDynamicFidelity;
2889 guidNSCodec = TRUE;
2890 settings->NSCodecId = codecId;
2891 if (Stream_GetRemainingLength(&sub) < 3)
2892 return FALSE;
2893 Stream_Read_UINT8(&sub, fAllowDynamicFidelity); /* fAllowDynamicFidelity (1 byte) */
2894 Stream_Read_UINT8(&sub, fAllowSubsampling); /* fAllowSubsampling (1 byte) */
2895 Stream_Read_UINT8(&sub, colorLossLevel); /* colorLossLevel (1 byte) */
2896
2897 if (colorLossLevel < 1)
2898 colorLossLevel = 1;
2899
2900 if (colorLossLevel > 7)
2901 colorLossLevel = 7;
2902
2903 settings->NSCodecAllowDynamicColorFidelity = fAllowDynamicFidelity;
2904 settings->NSCodecAllowSubsampling = fAllowSubsampling;
2905 settings->NSCodecColorLossLevel = colorLossLevel;
2906 }
2907 else if (UuidEqual(&codecGuid, &CODEC_GUID_IGNORE, &rpc_status))
2908 {
2909 if (!Stream_SafeSeek(&sub, codecPropertiesLength)) /* codecProperties */
2910 return FALSE;
2911 }
2912 else
2913 {
2914 if (!Stream_SafeSeek(&sub, codecPropertiesLength)) /* codecProperties */
2915 return FALSE;
2916 }
2917 }
2918 else
2919 {
2920 if (!Stream_SafeSeek(&sub, codecPropertiesLength)) /* codecProperties */
2921 return FALSE;
2922 }
2923
2924 rest = Stream_GetRemainingLength(&sub);
2925 if (rest > 0)
2926 {
2927 WLog_ERR(TAG,
2928 "error while reading codec properties: actual size: %" PRIuz
2929 " expected size: %" PRIu32 "",
2930 rest + codecPropertiesLength, codecPropertiesLength);
2931 }
2932 bitmapCodecCount--;
2933 }
2934
2935 if (settings->ServerMode)
2936 {
2937 /* only enable a codec if we've announced/enabled it before */
2938 settings->RemoteFxCodec = settings->RemoteFxCodec && guidRemoteFx;
2939 settings->RemoteFxImageCodec = settings->RemoteFxImageCodec && guidRemoteFxImage;
2940 settings->NSCodec = settings->NSCodec && guidNSCodec;
2941 settings->JpegCodec = FALSE;
2942 }
2943
2944 return TRUE;
2945 }
2946
2947 /**
2948 * Write RemoteFX Client Capability Container.\n
2949 * @param s stream
2950 * @param settings settings
2951 */
rdp_write_rfx_client_capability_container(wStream * s,const rdpSettings * settings)2952 static BOOL rdp_write_rfx_client_capability_container(wStream* s, const rdpSettings* settings)
2953 {
2954 UINT32 captureFlags;
2955 BYTE codecMode;
2956
2957 if (!Stream_EnsureRemainingCapacity(s, 64))
2958 return FALSE;
2959
2960 captureFlags = settings->RemoteFxOnly ? 0 : CARDP_CAPS_CAPTURE_NON_CAC;
2961 codecMode = settings->RemoteFxCodecMode;
2962 Stream_Write_UINT16(s, 49); /* codecPropertiesLength */
2963 /* TS_RFX_CLNT_CAPS_CONTAINER */
2964 Stream_Write_UINT32(s, 49); /* length */
2965 Stream_Write_UINT32(s, captureFlags); /* captureFlags */
2966 Stream_Write_UINT32(s, 37); /* capsLength */
2967 /* TS_RFX_CAPS */
2968 Stream_Write_UINT16(s, CBY_CAPS); /* blockType */
2969 Stream_Write_UINT32(s, 8); /* blockLen */
2970 Stream_Write_UINT16(s, 1); /* numCapsets */
2971 /* TS_RFX_CAPSET */
2972 Stream_Write_UINT16(s, CBY_CAPSET); /* blockType */
2973 Stream_Write_UINT32(s, 29); /* blockLen */
2974 Stream_Write_UINT8(s, 0x01); /* codecId (MUST be set to 0x01) */
2975 Stream_Write_UINT16(s, CLY_CAPSET); /* capsetType */
2976 Stream_Write_UINT16(s, 2); /* numIcaps */
2977 Stream_Write_UINT16(s, 8); /* icapLen */
2978 /* TS_RFX_ICAP (RLGR1) */
2979 Stream_Write_UINT16(s, CLW_VERSION_1_0); /* version */
2980 Stream_Write_UINT16(s, CT_TILE_64x64); /* tileSize */
2981 Stream_Write_UINT8(s, codecMode); /* flags */
2982 Stream_Write_UINT8(s, CLW_COL_CONV_ICT); /* colConvBits */
2983 Stream_Write_UINT8(s, CLW_XFORM_DWT_53_A); /* transformBits */
2984 Stream_Write_UINT8(s, CLW_ENTROPY_RLGR1); /* entropyBits */
2985 /* TS_RFX_ICAP (RLGR3) */
2986 Stream_Write_UINT16(s, CLW_VERSION_1_0); /* version */
2987 Stream_Write_UINT16(s, CT_TILE_64x64); /* tileSize */
2988 Stream_Write_UINT8(s, codecMode); /* flags */
2989 Stream_Write_UINT8(s, CLW_COL_CONV_ICT); /* colConvBits */
2990 Stream_Write_UINT8(s, CLW_XFORM_DWT_53_A); /* transformBits */
2991 Stream_Write_UINT8(s, CLW_ENTROPY_RLGR3); /* entropyBits */
2992 return TRUE;
2993 }
2994
2995 /**
2996 * Write NSCODEC Client Capability Container.\n
2997 * @param s stream
2998 * @param settings settings
2999 */
rdp_write_nsc_client_capability_container(wStream * s,const rdpSettings * settings)3000 static BOOL rdp_write_nsc_client_capability_container(wStream* s, const rdpSettings* settings)
3001 {
3002 BYTE colorLossLevel;
3003 BYTE fAllowSubsampling;
3004 BYTE fAllowDynamicFidelity;
3005 fAllowDynamicFidelity = settings->NSCodecAllowDynamicColorFidelity;
3006 fAllowSubsampling = settings->NSCodecAllowSubsampling;
3007 colorLossLevel = settings->NSCodecColorLossLevel;
3008
3009 if (colorLossLevel < 1)
3010 colorLossLevel = 1;
3011
3012 if (colorLossLevel > 7)
3013 colorLossLevel = 7;
3014
3015 if (!Stream_EnsureRemainingCapacity(s, 8))
3016 return FALSE;
3017
3018 Stream_Write_UINT16(s, 3); /* codecPropertiesLength */
3019 /* TS_NSCODEC_CAPABILITYSET */
3020 Stream_Write_UINT8(s, fAllowDynamicFidelity); /* fAllowDynamicFidelity (1 byte) */
3021 Stream_Write_UINT8(s, fAllowSubsampling); /* fAllowSubsampling (1 byte) */
3022 Stream_Write_UINT8(s, colorLossLevel); /* colorLossLevel (1 byte) */
3023 return TRUE;
3024 }
3025
3026 #if defined(WITH_JPEG)
rdp_write_jpeg_client_capability_container(wStream * s,const rdpSettings * settings)3027 static BOOL rdp_write_jpeg_client_capability_container(wStream* s, const rdpSettings* settings)
3028 {
3029 if (!Stream_EnsureRemainingCapacity(s, 8))
3030 return FALSE;
3031
3032 Stream_Write_UINT16(s, 1); /* codecPropertiesLength */
3033 Stream_Write_UINT8(s, settings->JpegQuality);
3034 return TRUE;
3035 }
3036 #endif
3037
3038 /**
3039 * Write RemoteFX Server Capability Container.\n
3040 * @param s stream
3041 * @param settings settings
3042 */
rdp_write_rfx_server_capability_container(wStream * s,const rdpSettings * settings)3043 static BOOL rdp_write_rfx_server_capability_container(wStream* s, const rdpSettings* settings)
3044 {
3045 WINPR_UNUSED(settings);
3046 if (!Stream_EnsureRemainingCapacity(s, 8))
3047 return FALSE;
3048
3049 Stream_Write_UINT16(s, 4); /* codecPropertiesLength */
3050 Stream_Write_UINT32(s, 0); /* reserved */
3051 return TRUE;
3052 }
3053
rdp_write_jpeg_server_capability_container(wStream * s,const rdpSettings * settings)3054 static BOOL rdp_write_jpeg_server_capability_container(wStream* s, const rdpSettings* settings)
3055 {
3056 WINPR_UNUSED(settings);
3057 if (!Stream_EnsureRemainingCapacity(s, 8))
3058 return FALSE;
3059
3060 Stream_Write_UINT16(s, 1); /* codecPropertiesLength */
3061 Stream_Write_UINT8(s, 75);
3062 return TRUE;
3063 }
3064
3065 /**
3066 * Write NSCODEC Server Capability Container.\n
3067 * @param s stream
3068 * @param settings settings
3069 */
rdp_write_nsc_server_capability_container(wStream * s,const rdpSettings * settings)3070 static BOOL rdp_write_nsc_server_capability_container(wStream* s, const rdpSettings* settings)
3071 {
3072 WINPR_UNUSED(settings);
3073 if (!Stream_EnsureRemainingCapacity(s, 8))
3074 return FALSE;
3075
3076 Stream_Write_UINT16(s, 4); /* codecPropertiesLength */
3077 Stream_Write_UINT32(s, 0); /* reserved */
3078 return TRUE;
3079 }
3080
3081 /**
3082 * Write bitmap codecs capability set.\n
3083 * @msdn{dd891377}
3084 * @param s stream
3085 * @param settings settings
3086 */
3087
rdp_write_bitmap_codecs_capability_set(wStream * s,const rdpSettings * settings)3088 static BOOL rdp_write_bitmap_codecs_capability_set(wStream* s, const rdpSettings* settings)
3089 {
3090 size_t header;
3091 BYTE bitmapCodecCount;
3092
3093 if (!Stream_EnsureRemainingCapacity(s, 64))
3094 return FALSE;
3095
3096 header = rdp_capability_set_start(s);
3097 if (header > UINT16_MAX)
3098 return FALSE;
3099 bitmapCodecCount = 0;
3100
3101 if (settings->RemoteFxCodec)
3102 bitmapCodecCount++;
3103
3104 if (settings->NSCodec)
3105 bitmapCodecCount++;
3106
3107 #if defined(WITH_JPEG)
3108
3109 if (settings->JpegCodec)
3110 bitmapCodecCount++;
3111
3112 #endif
3113
3114 if (settings->RemoteFxImageCodec)
3115 bitmapCodecCount++;
3116
3117 Stream_Write_UINT8(s, bitmapCodecCount);
3118
3119 if (settings->RemoteFxCodec)
3120 {
3121 rdp_write_bitmap_codec_guid(s, &CODEC_GUID_REMOTEFX); /* codecGUID */
3122
3123 if (settings->ServerMode)
3124 {
3125 Stream_Write_UINT8(s, 0); /* codecID is defined by the client */
3126
3127 if (!rdp_write_rfx_server_capability_container(s, settings))
3128 return FALSE;
3129 }
3130 else
3131 {
3132 Stream_Write_UINT8(s, RDP_CODEC_ID_REMOTEFX); /* codecID */
3133
3134 if (!rdp_write_rfx_client_capability_container(s, settings))
3135 return FALSE;
3136 }
3137 }
3138
3139 if (settings->NSCodec)
3140 {
3141 rdp_write_bitmap_codec_guid(s, &CODEC_GUID_NSCODEC); /* codecGUID */
3142
3143 if (settings->ServerMode)
3144 {
3145 Stream_Write_UINT8(s, 0); /* codecID is defined by the client */
3146
3147 if (!rdp_write_nsc_server_capability_container(s, settings))
3148 return FALSE;
3149 }
3150 else
3151 {
3152 Stream_Write_UINT8(s, RDP_CODEC_ID_NSCODEC); /* codecID */
3153
3154 if (!rdp_write_nsc_client_capability_container(s, settings))
3155 return FALSE;
3156 }
3157 }
3158
3159 #if defined(WITH_JPEG)
3160
3161 if (settings->JpegCodec)
3162 {
3163 rdp_write_bitmap_codec_guid(s, &CODEC_GUID_JPEG); /* codecGUID */
3164
3165 if (settings->ServerMode)
3166 {
3167 Stream_Write_UINT8(s, 0); /* codecID is defined by the client */
3168
3169 if (!rdp_write_jpeg_server_capability_container(s, settings))
3170 return FALSE;
3171 }
3172 else
3173 {
3174 Stream_Write_UINT8(s, RDP_CODEC_ID_JPEG); /* codecID */
3175
3176 if (!rdp_write_jpeg_client_capability_container(s, settings))
3177 return FALSE;
3178 }
3179 }
3180
3181 #endif
3182
3183 if (settings->RemoteFxImageCodec)
3184 {
3185 rdp_write_bitmap_codec_guid(s, &CODEC_GUID_IMAGE_REMOTEFX); /* codecGUID */
3186
3187 if (settings->ServerMode)
3188 {
3189 Stream_Write_UINT8(s, 0); /* codecID is defined by the client */
3190
3191 if (!rdp_write_rfx_server_capability_container(s, settings))
3192 return FALSE;
3193 }
3194 else
3195 {
3196 Stream_Write_UINT8(s, RDP_CODEC_ID_IMAGE_REMOTEFX); /* codecID */
3197
3198 if (!rdp_write_rfx_client_capability_container(s, settings))
3199 return FALSE;
3200 }
3201 }
3202
3203 return rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CODECS);
3204 }
3205
3206 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_bitmap_codecs_capability_set(wStream * s)3207 static BOOL rdp_print_bitmap_codecs_capability_set(wStream* s)
3208 {
3209 GUID codecGuid;
3210 BYTE bitmapCodecCount;
3211 BYTE codecId;
3212 UINT16 codecPropertiesLength;
3213
3214 WLog_INFO(TAG, "BitmapCodecsCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
3215
3216 if (Stream_GetRemainingLength(s) < 1)
3217 return FALSE;
3218
3219 Stream_Read_UINT8(s, bitmapCodecCount); /* bitmapCodecCount (1 byte) */
3220 WLog_INFO(TAG, "\tbitmapCodecCount: %" PRIu8 "", bitmapCodecCount);
3221
3222 while (bitmapCodecCount > 0)
3223 {
3224 if (!rdp_read_bitmap_codec_guid(s, &codecGuid)) /* codecGuid (16 bytes) */
3225 return FALSE;
3226 if (Stream_GetRemainingLength(s) < 3)
3227 return FALSE;
3228 Stream_Read_UINT8(s, codecId); /* codecId (1 byte) */
3229 WLog_INFO(TAG, "\tcodecGuid: 0x");
3230 rdp_print_bitmap_codec_guid(&codecGuid);
3231 WLog_INFO(TAG, " (%s)", rdp_get_bitmap_codec_guid_name(&codecGuid));
3232 WLog_INFO(TAG, "\tcodecId: %" PRIu8 "", codecId);
3233 Stream_Read_UINT16(s, codecPropertiesLength); /* codecPropertiesLength (2 bytes) */
3234 WLog_INFO(TAG, "\tcodecPropertiesLength: %" PRIu16 "", codecPropertiesLength);
3235
3236 if (!Stream_SafeSeek(s, codecPropertiesLength)) /* codecProperties */
3237 return FALSE;
3238 bitmapCodecCount--;
3239 }
3240
3241 return TRUE;
3242 }
3243 #endif
3244
3245 /**
3246 * Read frame acknowledge capability set.\n
3247 * @param s stream
3248 * @param settings settings
3249 * @return if the operation completed successfully
3250 */
3251
rdp_read_frame_acknowledge_capability_set(wStream * s,rdpSettings * settings)3252 static BOOL rdp_read_frame_acknowledge_capability_set(wStream* s, rdpSettings* settings)
3253 {
3254 if (Stream_GetRemainingLength(s) < 4)
3255 return FALSE;
3256
3257 if (settings->ServerMode)
3258 {
3259 Stream_Read_UINT32(s, settings->FrameAcknowledge); /* (4 bytes) */
3260 }
3261 else
3262 {
3263 Stream_Seek_UINT32(s); /* (4 bytes) */
3264 }
3265
3266 return TRUE;
3267 }
3268
3269 /**
3270 * Write frame acknowledge capability set.\n
3271 * @param s stream
3272 * @param settings settings
3273 */
3274
rdp_write_frame_acknowledge_capability_set(wStream * s,const rdpSettings * settings)3275 static BOOL rdp_write_frame_acknowledge_capability_set(wStream* s, const rdpSettings* settings)
3276 {
3277 size_t header;
3278
3279 if (!Stream_EnsureRemainingCapacity(s, 32))
3280 return FALSE;
3281
3282 header = rdp_capability_set_start(s);
3283 if (header > UINT16_MAX)
3284 return FALSE;
3285 Stream_Write_UINT32(s, settings->FrameAcknowledge); /* (4 bytes) */
3286 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_FRAME_ACKNOWLEDGE);
3287 }
3288
3289 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_frame_acknowledge_capability_set(wStream * s)3290 static BOOL rdp_print_frame_acknowledge_capability_set(wStream* s)
3291 {
3292 UINT32 frameAcknowledge;
3293 WLog_INFO(TAG,
3294 "FrameAcknowledgeCapabilitySet (length %" PRIuz "):", Stream_GetRemainingLength(s));
3295
3296 if (Stream_GetRemainingLength(s) < 4)
3297 return FALSE;
3298
3299 Stream_Read_UINT32(s, frameAcknowledge); /* frameAcknowledge (4 bytes) */
3300 WLog_INFO(TAG, "\tframeAcknowledge: 0x%08" PRIX32 "", frameAcknowledge);
3301 return TRUE;
3302 }
3303 #endif
3304
rdp_read_bitmap_cache_v3_codec_id_capability_set(wStream * s,rdpSettings * settings)3305 static BOOL rdp_read_bitmap_cache_v3_codec_id_capability_set(wStream* s, rdpSettings* settings)
3306 {
3307 BYTE bitmapCacheV3CodecId;
3308
3309 WINPR_UNUSED(settings);
3310 if (Stream_GetRemainingLength(s) < 1)
3311 return FALSE;
3312
3313 Stream_Read_UINT8(s, bitmapCacheV3CodecId); /* bitmapCacheV3CodecId (1 byte) */
3314 return TRUE;
3315 }
3316
rdp_write_bitmap_cache_v3_codec_id_capability_set(wStream * s,const rdpSettings * settings)3317 static BOOL rdp_write_bitmap_cache_v3_codec_id_capability_set(wStream* s,
3318 const rdpSettings* settings)
3319 {
3320 size_t header;
3321
3322 if (!Stream_EnsureRemainingCapacity(s, 32))
3323 return FALSE;
3324
3325 header = rdp_capability_set_start(s);
3326 if (header > UINT16_MAX)
3327 return FALSE;
3328 if (settings->BitmapCacheV3CodecId > UINT8_MAX)
3329 return FALSE;
3330 Stream_Write_UINT8(s, (UINT8)settings->BitmapCacheV3CodecId);
3331 return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID);
3332 }
3333
3334 #ifdef WITH_DEBUG_CAPABILITIES
rdp_print_bitmap_cache_v3_codec_id_capability_set(wStream * s)3335 static BOOL rdp_print_bitmap_cache_v3_codec_id_capability_set(wStream* s)
3336 {
3337 BYTE bitmapCacheV3CodecId;
3338 WLog_INFO(TAG, "BitmapCacheV3CodecIdCapabilitySet (length %" PRIuz "):",
3339 Stream_GetRemainingLength(s));
3340
3341 if (Stream_GetRemainingLength(s) < 1)
3342 return FALSE;
3343
3344 Stream_Read_UINT8(s, bitmapCacheV3CodecId); /* bitmapCacheV3CodecId (1 byte) */
3345 WLog_INFO(TAG, "\tbitmapCacheV3CodecId: 0x%02" PRIX8 "", bitmapCacheV3CodecId);
3346 return TRUE;
3347 }
3348
rdp_print_capability_sets(wStream * s,UINT16 numberCapabilities,BOOL receiving)3349 static BOOL rdp_print_capability_sets(wStream* s, UINT16 numberCapabilities, BOOL receiving)
3350 {
3351 UINT16 type;
3352 UINT16 length;
3353
3354 while (numberCapabilities > 0)
3355 {
3356 size_t rest;
3357 wStream sub;
3358 if (!rdp_read_capability_set_header(s, &length, &type))
3359 return FALSE;
3360
3361 WLog_INFO(TAG, "%s ", receiving ? "Receiving" : "Sending");
3362 Stream_StaticInit(&sub, Stream_Pointer(s), length - 4);
3363 if (!Stream_SafeSeek(s, length - 4))
3364 return FALSE;
3365
3366 switch (type)
3367 {
3368 case CAPSET_TYPE_GENERAL:
3369 if (!rdp_print_general_capability_set(&sub))
3370 return FALSE;
3371
3372 break;
3373
3374 case CAPSET_TYPE_BITMAP:
3375 if (!rdp_print_bitmap_capability_set(&sub))
3376 return FALSE;
3377
3378 break;
3379
3380 case CAPSET_TYPE_ORDER:
3381 if (!rdp_print_order_capability_set(&sub))
3382 return FALSE;
3383
3384 break;
3385
3386 case CAPSET_TYPE_BITMAP_CACHE:
3387 if (!rdp_print_bitmap_cache_capability_set(&sub))
3388 return FALSE;
3389
3390 break;
3391
3392 case CAPSET_TYPE_CONTROL:
3393 if (!rdp_print_control_capability_set(&sub))
3394 return FALSE;
3395
3396 break;
3397
3398 case CAPSET_TYPE_ACTIVATION:
3399 if (!rdp_print_window_activation_capability_set(&sub))
3400 return FALSE;
3401
3402 break;
3403
3404 case CAPSET_TYPE_POINTER:
3405 if (!rdp_print_pointer_capability_set(&sub))
3406 return FALSE;
3407
3408 break;
3409
3410 case CAPSET_TYPE_SHARE:
3411 if (!rdp_print_share_capability_set(&sub))
3412 return FALSE;
3413
3414 break;
3415
3416 case CAPSET_TYPE_COLOR_CACHE:
3417 if (!rdp_print_color_cache_capability_set(&sub))
3418 return FALSE;
3419
3420 break;
3421
3422 case CAPSET_TYPE_SOUND:
3423 if (!rdp_print_sound_capability_set(&sub))
3424 return FALSE;
3425
3426 break;
3427
3428 case CAPSET_TYPE_INPUT:
3429 if (!rdp_print_input_capability_set(&sub))
3430 return FALSE;
3431
3432 break;
3433
3434 case CAPSET_TYPE_FONT:
3435 if (!rdp_print_font_capability_set(&sub))
3436 return FALSE;
3437
3438 break;
3439
3440 case CAPSET_TYPE_BRUSH:
3441 if (!rdp_print_brush_capability_set(&sub))
3442 return FALSE;
3443
3444 break;
3445
3446 case CAPSET_TYPE_GLYPH_CACHE:
3447 if (!rdp_print_glyph_cache_capability_set(&sub))
3448 return FALSE;
3449
3450 break;
3451
3452 case CAPSET_TYPE_OFFSCREEN_CACHE:
3453 if (!rdp_print_offscreen_bitmap_cache_capability_set(&sub))
3454 return FALSE;
3455
3456 break;
3457
3458 case CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT:
3459 if (!rdp_print_bitmap_cache_host_support_capability_set(&sub))
3460 return FALSE;
3461
3462 break;
3463
3464 case CAPSET_TYPE_BITMAP_CACHE_V2:
3465 if (!rdp_print_bitmap_cache_v2_capability_set(&sub))
3466 return FALSE;
3467
3468 break;
3469
3470 case CAPSET_TYPE_VIRTUAL_CHANNEL:
3471 if (!rdp_print_virtual_channel_capability_set(&sub))
3472 return FALSE;
3473
3474 break;
3475
3476 case CAPSET_TYPE_DRAW_NINE_GRID_CACHE:
3477 if (!rdp_print_draw_nine_grid_cache_capability_set(&sub))
3478 return FALSE;
3479
3480 break;
3481
3482 case CAPSET_TYPE_DRAW_GDI_PLUS:
3483 if (!rdp_print_draw_gdiplus_cache_capability_set(&sub))
3484 return FALSE;
3485
3486 break;
3487
3488 case CAPSET_TYPE_RAIL:
3489 if (!rdp_print_remote_programs_capability_set(&sub))
3490 return FALSE;
3491
3492 break;
3493
3494 case CAPSET_TYPE_WINDOW:
3495 if (!rdp_print_window_list_capability_set(&sub))
3496 return FALSE;
3497
3498 break;
3499
3500 case CAPSET_TYPE_COMP_DESK:
3501 if (!rdp_print_desktop_composition_capability_set(&sub))
3502 return FALSE;
3503
3504 break;
3505
3506 case CAPSET_TYPE_MULTI_FRAGMENT_UPDATE:
3507 if (!rdp_print_multifragment_update_capability_set(&sub))
3508 return FALSE;
3509
3510 break;
3511
3512 case CAPSET_TYPE_LARGE_POINTER:
3513 if (!rdp_print_large_pointer_capability_set(&sub))
3514 return FALSE;
3515
3516 break;
3517
3518 case CAPSET_TYPE_SURFACE_COMMANDS:
3519 if (!rdp_print_surface_commands_capability_set(&sub))
3520 return FALSE;
3521
3522 break;
3523
3524 case CAPSET_TYPE_BITMAP_CODECS:
3525 if (!rdp_print_bitmap_codecs_capability_set(&sub))
3526 return FALSE;
3527
3528 break;
3529
3530 case CAPSET_TYPE_FRAME_ACKNOWLEDGE:
3531 if (!rdp_print_frame_acknowledge_capability_set(&sub))
3532 return FALSE;
3533
3534 break;
3535
3536 case CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID:
3537 if (!rdp_print_bitmap_cache_v3_codec_id_capability_set(&sub))
3538 return FALSE;
3539
3540 break;
3541
3542 default:
3543 WLog_ERR(TAG, "unknown capability type %" PRIu16 "", type);
3544 break;
3545 }
3546
3547 rest = Stream_GetRemainingLength(&sub);
3548 if (rest > 0)
3549 {
3550 WLog_WARN(TAG,
3551 "incorrect capability offset, type:0x%04" PRIX16 " %" PRIu16
3552 " bytes expected, %" PRIuz "bytes remaining",
3553 type, length, rest);
3554 }
3555
3556 numberCapabilities--;
3557 }
3558
3559 return TRUE;
3560 }
3561 #endif
3562
rdp_read_capability_sets(wStream * s,rdpSettings * settings,UINT16 numberCapabilities,UINT16 totalLength)3563 static BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCapabilities,
3564 UINT16 totalLength)
3565 {
3566 BOOL treated;
3567 size_t start, end, len;
3568 UINT16 count = numberCapabilities;
3569
3570 start = Stream_GetPosition(s);
3571 while (numberCapabilities > 0 && Stream_GetRemainingLength(s) >= 4)
3572 {
3573 size_t rest;
3574 UINT16 type;
3575 UINT16 length;
3576 wStream sub;
3577
3578 if (!rdp_read_capability_set_header(s, &length, &type))
3579 return FALSE;
3580 Stream_StaticInit(&sub, Stream_Pointer(s), length - 4);
3581 if (!Stream_SafeSeek(s, length - 4))
3582 return FALSE;
3583
3584 if (type < 32)
3585 {
3586 settings->ReceivedCapabilities[type] = TRUE;
3587 }
3588 else
3589 {
3590 WLog_WARN(TAG, "not handling capability type %" PRIu16 " yet", type);
3591 }
3592
3593 treated = TRUE;
3594
3595 switch (type)
3596 {
3597 case CAPSET_TYPE_GENERAL:
3598 if (!rdp_read_general_capability_set(&sub, settings))
3599 return FALSE;
3600
3601 break;
3602
3603 case CAPSET_TYPE_BITMAP:
3604 if (!rdp_read_bitmap_capability_set(&sub, settings))
3605 return FALSE;
3606
3607 break;
3608
3609 case CAPSET_TYPE_ORDER:
3610 if (!rdp_read_order_capability_set(&sub, settings))
3611 return FALSE;
3612
3613 break;
3614
3615 case CAPSET_TYPE_POINTER:
3616 if (!rdp_read_pointer_capability_set(&sub, settings))
3617 return FALSE;
3618
3619 break;
3620
3621 case CAPSET_TYPE_INPUT:
3622 if (!rdp_read_input_capability_set(&sub, settings))
3623 return FALSE;
3624
3625 break;
3626
3627 case CAPSET_TYPE_VIRTUAL_CHANNEL:
3628 if (!rdp_read_virtual_channel_capability_set(&sub, settings))
3629 return FALSE;
3630
3631 break;
3632
3633 case CAPSET_TYPE_SHARE:
3634 if (!rdp_read_share_capability_set(&sub, settings))
3635 return FALSE;
3636
3637 break;
3638
3639 case CAPSET_TYPE_COLOR_CACHE:
3640 if (!rdp_read_color_cache_capability_set(&sub, settings))
3641 return FALSE;
3642
3643 break;
3644
3645 case CAPSET_TYPE_FONT:
3646 if (!rdp_read_font_capability_set(&sub, settings))
3647 return FALSE;
3648
3649 break;
3650
3651 case CAPSET_TYPE_DRAW_GDI_PLUS:
3652 if (!rdp_read_draw_gdiplus_cache_capability_set(&sub, settings))
3653 return FALSE;
3654
3655 break;
3656
3657 case CAPSET_TYPE_RAIL:
3658 if (!rdp_read_remote_programs_capability_set(&sub, settings))
3659 return FALSE;
3660
3661 break;
3662
3663 case CAPSET_TYPE_WINDOW:
3664 if (!rdp_read_window_list_capability_set(&sub, settings))
3665 return FALSE;
3666
3667 break;
3668
3669 case CAPSET_TYPE_MULTI_FRAGMENT_UPDATE:
3670 if (!rdp_read_multifragment_update_capability_set(&sub, settings))
3671 return FALSE;
3672
3673 break;
3674
3675 case CAPSET_TYPE_LARGE_POINTER:
3676 if (!rdp_read_large_pointer_capability_set(&sub, settings))
3677 return FALSE;
3678
3679 break;
3680
3681 case CAPSET_TYPE_COMP_DESK:
3682 if (!rdp_read_desktop_composition_capability_set(&sub, settings))
3683 return FALSE;
3684
3685 break;
3686
3687 case CAPSET_TYPE_SURFACE_COMMANDS:
3688 if (!rdp_read_surface_commands_capability_set(&sub, settings))
3689 return FALSE;
3690
3691 break;
3692
3693 case CAPSET_TYPE_BITMAP_CODECS:
3694 if (!rdp_read_bitmap_codecs_capability_set(&sub, settings))
3695 return FALSE;
3696
3697 break;
3698
3699 case CAPSET_TYPE_FRAME_ACKNOWLEDGE:
3700 if (!rdp_read_frame_acknowledge_capability_set(&sub, settings))
3701 return FALSE;
3702
3703 break;
3704
3705 case CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID:
3706 if (!rdp_read_bitmap_cache_v3_codec_id_capability_set(&sub, settings))
3707 return FALSE;
3708
3709 break;
3710
3711 default:
3712 treated = FALSE;
3713 break;
3714 }
3715
3716 if (!treated)
3717 {
3718 if (settings->ServerMode)
3719 {
3720 /* treating capabilities that are supposed to be send only from the client */
3721 switch (type)
3722 {
3723 case CAPSET_TYPE_BITMAP_CACHE:
3724 if (!rdp_read_bitmap_cache_capability_set(&sub, settings))
3725 return FALSE;
3726
3727 break;
3728
3729 case CAPSET_TYPE_BITMAP_CACHE_V2:
3730 if (!rdp_read_bitmap_cache_v2_capability_set(&sub, settings))
3731 return FALSE;
3732
3733 break;
3734
3735 case CAPSET_TYPE_BRUSH:
3736 if (!rdp_read_brush_capability_set(&sub, settings))
3737 return FALSE;
3738
3739 break;
3740
3741 case CAPSET_TYPE_GLYPH_CACHE:
3742 if (!rdp_read_glyph_cache_capability_set(&sub, settings))
3743 return FALSE;
3744
3745 break;
3746
3747 case CAPSET_TYPE_OFFSCREEN_CACHE:
3748 if (!rdp_read_offscreen_bitmap_cache_capability_set(&sub, settings))
3749 return FALSE;
3750
3751 break;
3752
3753 case CAPSET_TYPE_SOUND:
3754 if (!rdp_read_sound_capability_set(&sub, settings))
3755 return FALSE;
3756
3757 break;
3758
3759 case CAPSET_TYPE_CONTROL:
3760 if (!rdp_read_control_capability_set(&sub, settings))
3761 return FALSE;
3762
3763 break;
3764
3765 case CAPSET_TYPE_ACTIVATION:
3766 if (!rdp_read_window_activation_capability_set(&sub, settings))
3767 return FALSE;
3768
3769 break;
3770
3771 case CAPSET_TYPE_DRAW_NINE_GRID_CACHE:
3772 if (!rdp_read_draw_nine_grid_cache_capability_set(&sub, settings))
3773 return FALSE;
3774
3775 break;
3776
3777 default:
3778 WLog_ERR(TAG, "capability %s(%" PRIu16 ") not expected from client",
3779 get_capability_name(type), type);
3780 return FALSE;
3781 }
3782 }
3783 else
3784 {
3785 /* treating capabilities that are supposed to be send only from the server */
3786 switch (type)
3787 {
3788 case CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT:
3789 if (!rdp_read_bitmap_cache_host_support_capability_set(&sub, settings))
3790 return FALSE;
3791
3792 break;
3793
3794 default:
3795 WLog_ERR(TAG, "capability %s(%" PRIu16 ") not expected from server",
3796 get_capability_name(type), type);
3797 return FALSE;
3798 }
3799 }
3800 }
3801
3802 rest = Stream_GetRemainingLength(&sub);
3803 if (rest > 0)
3804 {
3805 WLog_ERR(TAG,
3806 "incorrect offset, type:0x%04" PRIX16 " actual:%" PRIuz " expected:%" PRIu16
3807 "",
3808 type, length - rest, length);
3809 }
3810
3811 numberCapabilities--;
3812 }
3813
3814 end = Stream_GetPosition(s);
3815 len = end - start;
3816
3817 if (numberCapabilities)
3818 {
3819 WLog_ERR(TAG,
3820 "strange we haven't read the number of announced capacity sets, read=%d "
3821 "expected=%" PRIu16 "",
3822 count - numberCapabilities, count);
3823 }
3824
3825 #ifdef WITH_DEBUG_CAPABILITIES
3826 {
3827 Stream_SetPosition(s, start);
3828 numberCapabilities = count;
3829 rdp_print_capability_sets(s, numberCapabilities, TRUE);
3830 Stream_SetPosition(s, end);
3831 }
3832 #endif
3833
3834 if (len > totalLength)
3835 {
3836 WLog_ERR(TAG, "Capability length expected %" PRIu16 ", actual %" PRIdz, totalLength, len);
3837 return FALSE;
3838 }
3839 return TRUE;
3840 }
3841
rdp_recv_get_active_header(rdpRdp * rdp,wStream * s,UINT16 * pChannelId,UINT16 * length)3842 BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId, UINT16* length)
3843 {
3844 UINT16 securityFlags = 0;
3845
3846 if (!rdp_read_header(rdp, s, length, pChannelId))
3847 return FALSE;
3848
3849 if (freerdp_shall_disconnect(rdp->instance))
3850 return TRUE;
3851
3852 if (rdp->settings->UseRdpSecurityLayer)
3853 {
3854 if (!rdp_read_security_header(s, &securityFlags, length))
3855 return FALSE;
3856
3857 if (securityFlags & SEC_ENCRYPT)
3858 {
3859 if (!rdp_decrypt(rdp, s, length, securityFlags))
3860 {
3861 WLog_ERR(TAG, "rdp_decrypt failed");
3862 return FALSE;
3863 }
3864 }
3865 }
3866
3867 if (*pChannelId != MCS_GLOBAL_CHANNEL_ID)
3868 {
3869 UINT16 mcsMessageChannelId = rdp->mcs->messageChannelId;
3870
3871 if ((mcsMessageChannelId == 0) || (*pChannelId != mcsMessageChannelId))
3872 {
3873 WLog_ERR(TAG, "unexpected MCS channel id %04" PRIx16 " received", *pChannelId);
3874 return FALSE;
3875 }
3876 }
3877
3878 return TRUE;
3879 }
3880
rdp_recv_demand_active(rdpRdp * rdp,wStream * s)3881 BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s)
3882 {
3883 UINT16 channelId;
3884 UINT16 pduType;
3885 UINT16 pduSource;
3886 UINT16 length;
3887 UINT16 numberCapabilities;
3888 UINT16 lengthSourceDescriptor;
3889 UINT16 lengthCombinedCapabilities;
3890
3891 if (!rdp_recv_get_active_header(rdp, s, &channelId, &length))
3892 return FALSE;
3893
3894 if (freerdp_shall_disconnect(rdp->instance))
3895 return TRUE;
3896
3897 if (!rdp_read_share_control_header(s, NULL, NULL, &pduType, &pduSource))
3898 {
3899 WLog_ERR(TAG, "rdp_read_share_control_header failed");
3900 return FALSE;
3901 }
3902
3903 if (pduType == PDU_TYPE_DATA)
3904 {
3905 /**
3906 * We can receive a Save Session Info Data PDU containing a LogonErrorInfo
3907 * structure at this point from the server to indicate a connection error.
3908 */
3909 if (rdp_recv_data_pdu(rdp, s) < 0)
3910 return FALSE;
3911
3912 return FALSE;
3913 }
3914
3915 if (pduType != PDU_TYPE_DEMAND_ACTIVE)
3916 {
3917 if (pduType != PDU_TYPE_SERVER_REDIRECTION)
3918 WLog_ERR(TAG, "expected PDU_TYPE_DEMAND_ACTIVE %04x, got %04" PRIx16 "",
3919 PDU_TYPE_DEMAND_ACTIVE, pduType);
3920
3921 return FALSE;
3922 }
3923
3924 rdp->settings->PduSource = pduSource;
3925
3926 if (Stream_GetRemainingLength(s) < 8)
3927 return FALSE;
3928
3929 Stream_Read_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
3930 Stream_Read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
3931 Stream_Read_UINT16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */
3932
3933 if (!Stream_SafeSeek(s, lengthSourceDescriptor) ||
3934 Stream_GetRemainingLength(s) < 4) /* sourceDescriptor */
3935 return FALSE;
3936
3937 Stream_Read_UINT16(s, numberCapabilities); /* numberCapabilities (2 bytes) */
3938 Stream_Seek(s, 2); /* pad2Octets (2 bytes) */
3939
3940 /* capabilitySets */
3941 if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities, lengthCombinedCapabilities))
3942 {
3943 WLog_ERR(TAG, "rdp_read_capability_sets failed");
3944 return FALSE;
3945 }
3946
3947 if (!Stream_SafeSeek(s, 4)) /* SessionId */
3948 return FALSE;
3949
3950 rdp->update->secondary->glyph_v2 = (rdp->settings->GlyphSupportLevel > GLYPH_SUPPORT_FULL);
3951 return tpkt_ensure_stream_consumed(s, length);
3952 }
3953
rdp_write_demand_active(wStream * s,rdpSettings * settings)3954 static BOOL rdp_write_demand_active(wStream* s, rdpSettings* settings)
3955 {
3956 size_t bm, em, lm;
3957 UINT16 numberCapabilities;
3958 size_t lengthCombinedCapabilities;
3959
3960 if (!Stream_EnsureRemainingCapacity(s, 64))
3961 return FALSE;
3962
3963 Stream_Write_UINT32(s, settings->ShareId); /* shareId (4 bytes) */
3964 Stream_Write_UINT16(s, 4); /* lengthSourceDescriptor (2 bytes) */
3965 lm = Stream_GetPosition(s);
3966 Stream_Seek_UINT16(s); /* lengthCombinedCapabilities (2 bytes) */
3967 Stream_Write(s, "RDP", 4); /* sourceDescriptor */
3968 bm = Stream_GetPosition(s);
3969 Stream_Seek_UINT16(s); /* numberCapabilities (2 bytes) */
3970 Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
3971 numberCapabilities = 14;
3972
3973 if (!rdp_write_general_capability_set(s, settings) ||
3974 !rdp_write_bitmap_capability_set(s, settings) ||
3975 !rdp_write_order_capability_set(s, settings) ||
3976 !rdp_write_pointer_capability_set(s, settings) ||
3977 !rdp_write_input_capability_set(s, settings) ||
3978 !rdp_write_virtual_channel_capability_set(s, settings) ||
3979 !rdp_write_share_capability_set(s, settings) ||
3980 !rdp_write_font_capability_set(s, settings) ||
3981 !rdp_write_multifragment_update_capability_set(s, settings) ||
3982 !rdp_write_large_pointer_capability_set(s, settings) ||
3983 !rdp_write_desktop_composition_capability_set(s, settings) ||
3984 !rdp_write_surface_commands_capability_set(s, settings) ||
3985 !rdp_write_bitmap_codecs_capability_set(s, settings) ||
3986 !rdp_write_frame_acknowledge_capability_set(s, settings))
3987 {
3988 return FALSE;
3989 }
3990
3991 if (settings->BitmapCachePersistEnabled)
3992 {
3993 numberCapabilities++;
3994
3995 if (!rdp_write_bitmap_cache_host_support_capability_set(s, settings))
3996 return FALSE;
3997 }
3998
3999 if (settings->RemoteApplicationMode)
4000 {
4001 numberCapabilities += 2;
4002
4003 if (!rdp_write_remote_programs_capability_set(s, settings) ||
4004 !rdp_write_window_list_capability_set(s, settings))
4005 return FALSE;
4006 }
4007
4008 em = Stream_GetPosition(s);
4009 Stream_SetPosition(s, lm); /* go back to lengthCombinedCapabilities */
4010 lengthCombinedCapabilities = (em - bm);
4011 if (lengthCombinedCapabilities > UINT16_MAX)
4012 return FALSE;
4013 Stream_Write_UINT16(
4014 s, (UINT16)lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */
4015 Stream_SetPosition(s, bm); /* go back to numberCapabilities */
4016 Stream_Write_UINT16(s, numberCapabilities); /* numberCapabilities (2 bytes) */
4017 #ifdef WITH_DEBUG_CAPABILITIES
4018 Stream_Seek_UINT16(s);
4019 rdp_print_capability_sets(s, numberCapabilities, FALSE);
4020 Stream_SetPosition(s, bm);
4021 Stream_Seek_UINT16(s);
4022 #endif
4023 Stream_SetPosition(s, em);
4024 Stream_Write_UINT32(s, 0); /* sessionId */
4025 return TRUE;
4026 }
4027
rdp_send_demand_active(rdpRdp * rdp)4028 BOOL rdp_send_demand_active(rdpRdp* rdp)
4029 {
4030 wStream* s = rdp_send_stream_pdu_init(rdp);
4031 BOOL status;
4032
4033 if (!s)
4034 return FALSE;
4035
4036 rdp->settings->ShareId = 0x10000 + rdp->mcs->userId;
4037 status = rdp_write_demand_active(s, rdp->settings) &&
4038 rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->userId);
4039 Stream_Release(s);
4040 return status;
4041 }
4042
rdp_recv_confirm_active(rdpRdp * rdp,wStream * s,UINT16 pduLength)4043 BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s, UINT16 pduLength)
4044 {
4045 rdpSettings* settings;
4046 UINT16 lengthSourceDescriptor;
4047 UINT16 lengthCombinedCapabilities;
4048 UINT16 numberCapabilities;
4049 settings = rdp->settings;
4050
4051 if (Stream_GetRemainingLength(s) < 10)
4052 return FALSE;
4053
4054 Stream_Seek_UINT32(s); /* shareId (4 bytes) */
4055 Stream_Seek_UINT16(s); /* originatorId (2 bytes) */
4056 Stream_Read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
4057 Stream_Read_UINT16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */
4058
4059 if (Stream_GetRemainingLength(s) < lengthSourceDescriptor + 4U)
4060 return FALSE;
4061
4062 Stream_Seek(s, lengthSourceDescriptor); /* sourceDescriptor */
4063 Stream_Read_UINT16(s, numberCapabilities); /* numberCapabilities (2 bytes) */
4064 Stream_Seek(s, 2); /* pad2Octets (2 bytes) */
4065 if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities, lengthCombinedCapabilities))
4066 return FALSE;
4067
4068 if (!settings->ReceivedCapabilities[CAPSET_TYPE_SURFACE_COMMANDS])
4069 {
4070 /* client does not support surface commands */
4071 settings->SurfaceCommandsEnabled = FALSE;
4072 settings->SurfaceFrameMarkerEnabled = FALSE;
4073 }
4074
4075 if (!settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
4076 {
4077 /* client does not support frame acks */
4078 settings->FrameAcknowledge = 0;
4079 }
4080
4081 if (!settings->ReceivedCapabilities[CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID])
4082 {
4083 /* client does not support bitmap cache v3 */
4084 settings->BitmapCacheV3Enabled = FALSE;
4085 }
4086
4087 if (!settings->ReceivedCapabilities[CAPSET_TYPE_BITMAP_CODECS])
4088 {
4089 /* client does not support bitmap codecs */
4090 settings->RemoteFxCodec = FALSE;
4091 settings->NSCodec = FALSE;
4092 settings->JpegCodec = FALSE;
4093 }
4094
4095 if (!settings->ReceivedCapabilities[CAPSET_TYPE_MULTI_FRAGMENT_UPDATE])
4096 {
4097 /* client does not support multi fragment updates - make sure packages are not fragmented */
4098 settings->MultifragMaxRequestSize = FASTPATH_FRAGMENT_SAFE_SIZE;
4099 }
4100
4101 if (!settings->ReceivedCapabilities[CAPSET_TYPE_LARGE_POINTER])
4102 {
4103 /* client does not support large pointers */
4104 settings->LargePointerFlag = 0;
4105 }
4106
4107 return tpkt_ensure_stream_consumed(s, pduLength);
4108 }
4109
rdp_write_confirm_active(wStream * s,rdpSettings * settings)4110 static BOOL rdp_write_confirm_active(wStream* s, rdpSettings* settings)
4111 {
4112 size_t bm, em, lm;
4113 UINT16 numberCapabilities;
4114 UINT16 lengthSourceDescriptor;
4115 size_t lengthCombinedCapabilities;
4116 BOOL ret;
4117 lengthSourceDescriptor = sizeof(SOURCE_DESCRIPTOR);
4118 Stream_Write_UINT32(s, settings->ShareId); /* shareId (4 bytes) */
4119 Stream_Write_UINT16(s, 0x03EA); /* originatorId (2 bytes) */
4120 Stream_Write_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
4121 lm = Stream_GetPosition(s);
4122 Stream_Seek_UINT16(s); /* lengthCombinedCapabilities (2 bytes) */
4123 Stream_Write(s, SOURCE_DESCRIPTOR, lengthSourceDescriptor); /* sourceDescriptor */
4124 bm = Stream_GetPosition(s);
4125 Stream_Seek_UINT16(s); /* numberCapabilities (2 bytes) */
4126 Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
4127 /* Capability Sets */
4128 numberCapabilities = 15;
4129
4130 if (!rdp_write_general_capability_set(s, settings) ||
4131 !rdp_write_bitmap_capability_set(s, settings) ||
4132 !rdp_write_order_capability_set(s, settings))
4133 return FALSE;
4134
4135 if (settings->RdpVersion >= RDP_VERSION_5_PLUS)
4136 ret = rdp_write_bitmap_cache_v2_capability_set(s, settings);
4137 else
4138 ret = rdp_write_bitmap_cache_capability_set(s, settings);
4139
4140 if (!ret)
4141 return FALSE;
4142
4143 if (!rdp_write_pointer_capability_set(s, settings) ||
4144 !rdp_write_input_capability_set(s, settings) ||
4145 !rdp_write_brush_capability_set(s, settings) ||
4146 !rdp_write_glyph_cache_capability_set(s, settings) ||
4147 !rdp_write_virtual_channel_capability_set(s, settings) ||
4148 !rdp_write_sound_capability_set(s, settings) ||
4149 !rdp_write_share_capability_set(s, settings) ||
4150 !rdp_write_font_capability_set(s, settings) ||
4151 !rdp_write_control_capability_set(s, settings) ||
4152 !rdp_write_color_cache_capability_set(s, settings) ||
4153 !rdp_write_window_activation_capability_set(s, settings))
4154 {
4155 return FALSE;
4156 }
4157
4158 if (settings->OffscreenSupportLevel)
4159 {
4160 numberCapabilities++;
4161
4162 if (!rdp_write_offscreen_bitmap_cache_capability_set(s, settings))
4163 return FALSE;
4164 }
4165
4166 if (settings->DrawNineGridEnabled)
4167 {
4168 numberCapabilities++;
4169
4170 if (!rdp_write_draw_nine_grid_cache_capability_set(s, settings))
4171 return FALSE;
4172 }
4173
4174 if (settings->ReceivedCapabilities[CAPSET_TYPE_LARGE_POINTER])
4175 {
4176 if (settings->LargePointerFlag)
4177 {
4178 numberCapabilities++;
4179
4180 if (!rdp_write_large_pointer_capability_set(s, settings))
4181 return FALSE;
4182 }
4183 }
4184
4185 if (settings->RemoteApplicationMode)
4186 {
4187 numberCapabilities += 2;
4188
4189 if (!rdp_write_remote_programs_capability_set(s, settings) ||
4190 !rdp_write_window_list_capability_set(s, settings))
4191 return FALSE;
4192 }
4193
4194 if (settings->ReceivedCapabilities[CAPSET_TYPE_MULTI_FRAGMENT_UPDATE])
4195 {
4196 numberCapabilities++;
4197
4198 if (!rdp_write_multifragment_update_capability_set(s, settings))
4199 return FALSE;
4200 }
4201
4202 if (settings->ReceivedCapabilities[CAPSET_TYPE_SURFACE_COMMANDS])
4203 {
4204 numberCapabilities++;
4205
4206 if (!rdp_write_surface_commands_capability_set(s, settings))
4207 return FALSE;
4208 }
4209
4210 if (settings->ReceivedCapabilities[CAPSET_TYPE_BITMAP_CODECS])
4211 {
4212 numberCapabilities++;
4213
4214 if (!rdp_write_bitmap_codecs_capability_set(s, settings))
4215 return FALSE;
4216 }
4217
4218 if (!settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
4219 settings->FrameAcknowledge = 0;
4220
4221 if (settings->FrameAcknowledge)
4222 {
4223 numberCapabilities++;
4224
4225 if (!rdp_write_frame_acknowledge_capability_set(s, settings))
4226 return FALSE;
4227 }
4228
4229 if (settings->ReceivedCapabilities[CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID])
4230 {
4231 if (settings->BitmapCacheV3CodecId != 0)
4232 {
4233 numberCapabilities++;
4234
4235 if (!rdp_write_bitmap_cache_v3_codec_id_capability_set(s, settings))
4236 return FALSE;
4237 }
4238 }
4239
4240 em = Stream_GetPosition(s);
4241 Stream_SetPosition(s, lm); /* go back to lengthCombinedCapabilities */
4242 lengthCombinedCapabilities = (em - bm);
4243 if (lengthCombinedCapabilities > UINT16_MAX)
4244 return FALSE;
4245 Stream_Write_UINT16(
4246 s, (UINT16)lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */
4247 Stream_SetPosition(s, bm); /* go back to numberCapabilities */
4248 Stream_Write_UINT16(s, numberCapabilities); /* numberCapabilities (2 bytes) */
4249 #ifdef WITH_DEBUG_CAPABILITIES
4250 Stream_Seek_UINT16(s);
4251 rdp_print_capability_sets(s, numberCapabilities, FALSE);
4252 Stream_SetPosition(s, bm);
4253 Stream_Seek_UINT16(s);
4254 #endif
4255 Stream_SetPosition(s, em);
4256
4257 return TRUE;
4258 }
4259
rdp_send_confirm_active(rdpRdp * rdp)4260 BOOL rdp_send_confirm_active(rdpRdp* rdp)
4261 {
4262 wStream* s = rdp_send_stream_pdu_init(rdp);
4263 BOOL status;
4264
4265 if (!s)
4266 return FALSE;
4267
4268 status = rdp_write_confirm_active(s, rdp->settings) &&
4269 rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->userId);
4270 Stream_Release(s);
4271 return status;
4272 }
4273