Coverage Report

Created: 2024-05-20 06:11

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