2 * FreeRDP: A Remote Desktop Protocol Client
3 * T.124 Generic Conference Control (GCC)
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <freerdp/utils/print.h>
23 #include "certificate.h"
26 * T.124 GCC is defined in:
28 * http://www.itu.int/rec/T-REC-T.124-199802-S/en
29 * ITU-T T.124 (02/98): Generic Conference Control
33 * ConnectData ::= SEQUENCE
36 * connectPDU OCTET_STRING
41 * object OBJECT_IDENTIFIER,
42 * h221NonStandard H221NonStandardIdentifier
45 * ConnectGCCPDU ::= CHOICE
47 * conferenceCreateRequest ConferenceCreateRequest,
48 * conferenceCreateResponse ConferenceCreateResponse,
49 * conferenceQueryRequest ConferenceQueryRequest,
50 * conferenceQueryResponse ConferenceQueryResponse,
51 * conferenceJoinRequest ConferenceJoinRequest,
52 * conferenceJoinResponse ConferenceJoinResponse,
53 * conferenceInviteRequest ConferenceInviteRequest,
54 * conferenceInviteResponse ConferenceInviteResponse,
58 * ConferenceCreateRequest ::= SEQUENCE
60 * conferenceName ConferenceName,
61 * convenerPassword Password OPTIONAL,
62 * password Password OPTIONAL,
63 * lockedConference BOOLEAN,
64 * listedConference BOOLEAN,
65 * conductibleConference BOOLEAN,
66 * terminationMethod TerminationMethod,
67 * conductorPrivileges SET OF Privilege OPTIONAL,
68 * conductedPrivileges SET OF Privilege OPTIONAL,
69 * nonConductedPrivileges SET OF Privilege OPTIONAL,
70 * conferenceDescription TextString OPTIONAL,
71 * callerIdentifier TextString OPTIONAL,
72 * userData UserData OPTIONAL,
74 * conferencePriority ConferencePriority OPTIONAL,
75 * conferenceMode ConferenceMode OPTIONAL
78 * ConferenceCreateResponse ::= SEQUENCE
86 * resourcesNotAvailable (2),
87 * rejectedForSymmetryBreaking (3),
88 * lockedConferenceNotSupported (4)
90 * userData UserData OPTIONAL,
94 * ConferenceName ::= SEQUENCE
96 * numeric SimpleNumericString
97 * text SimpleTextString OPTIONAL,
101 * SimpleNumericString ::= NumericString (SIZE (1..255)) (FROM ("0123456789"))
103 * UserData ::= SET OF SEQUENCE
106 * value OCTET_STRING OPTIONAL
109 * H221NonStandardIdentifier ::= OCTET STRING (SIZE (4..255))
111 * UserID ::= DynamicChannelID
113 * ChannelID ::= INTEGER (1..65535)
114 * StaticChannelID ::= INTEGER (1..1000)
115 * DynamicChannelID ::= INTEGER (1001..65535)
120 * OID = 0.0.20.124.0.1
121 * { itu-t(0) recommendation(0) t(20) t124(124) version(0) 1 }
122 * v.1 of ITU-T Recommendation T.124 (Feb 1998): "Generic Conference Control"
124 uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
126 uint8 h221_cs_key[4] = "Duca";
127 uint8 h221_sc_key[4] = "McDn";
130 * Read a GCC Conference Create Request.\n
133 * @param settings rdp settings
136 boolean gcc_read_conference_create_request(STREAM* s, rdpSettings* settings)
144 if (!per_read_choice(s, &choice))
146 if (!per_read_object_identifier(s, t124_02_98_oid))
149 /* ConnectData::connectPDU (OCTET_STRING) */
150 if (!per_read_length(s, &length))
154 if (!per_read_choice(s, &choice))
156 if (!per_read_selection(s, &selection))
159 /* ConferenceCreateRequest::conferenceName */
160 if (!per_read_numeric_string(s, 1)) /* ConferenceName::numeric */
162 if (!per_read_padding(s, 1)) /* padding */
165 /* UserData (SET OF SEQUENCE) */
166 if (!per_read_number_of_sets(s, &number) || number != 1) /* one set of UserData */
168 if (!per_read_choice(s, &choice) || choice != 0xC0) /* UserData::value present + select h221NonStandard (1) */
171 /* h221NonStandard */
172 if (!per_read_octet_string(s, h221_cs_key, 4, 4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */
175 /* userData::value (OCTET_STRING) */
176 if (!per_read_length(s, &length))
178 if (stream_get_left(s) < length)
180 if (!gcc_read_client_data_blocks(s, settings, length))
187 * Write a GCC Conference Create Request.\n
190 * @param user_data client data blocks
193 void gcc_write_conference_create_request(STREAM* s, STREAM* user_data)
196 per_write_choice(s, 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */
197 per_write_object_identifier(s, t124_02_98_oid); /* ITU-T T.124 (02/98) OBJECT_IDENTIFIER */
199 /* ConnectData::connectPDU (OCTET_STRING) */
200 per_write_length(s, stream_get_length(user_data) + 14); /* connectPDU length */
203 per_write_choice(s, 0); /* From ConnectGCCPDU select conferenceCreateRequest (0) of type ConferenceCreateRequest */
204 per_write_selection(s, 0x08); /* select optional userData from ConferenceCreateRequest */
206 /* ConferenceCreateRequest::conferenceName */
207 per_write_numeric_string(s, (uint8*)"1", 1, 1); /* ConferenceName::numeric */
208 per_write_padding(s, 1); /* padding */
210 /* UserData (SET OF SEQUENCE) */
211 per_write_number_of_sets(s, 1); /* one set of UserData */
212 per_write_choice(s, 0xC0); /* UserData::value present + select h221NonStandard (1) */
214 /* h221NonStandard */
215 per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */
217 /* userData::value (OCTET_STRING) */
218 per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of client data blocks */
221 boolean gcc_read_conference_create_response(STREAM* s, rdpSettings* settings)
231 per_read_choice(s, &choice);
232 per_read_object_identifier(s, t124_02_98_oid);
234 /* ConnectData::connectPDU (OCTET_STRING) */
235 per_read_length(s, &length);
238 per_read_choice(s, &choice);
240 /* ConferenceCreateResponse::nodeID (UserID) */
241 per_read_integer16(s, &nodeID, 1001);
243 /* ConferenceCreateResponse::tag (INTEGER) */
244 per_read_integer(s, &tag);
246 /* ConferenceCreateResponse::result (ENUMERATED) */
247 per_read_enumerated(s, &result, MCS_Result_enum_length);
249 /* number of UserData sets */
250 per_read_number_of_sets(s, &number);
252 /* UserData::value present + select h221NonStandard (1) */
253 per_read_choice(s, &choice);
255 /* h221NonStandard */
256 if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
259 /* userData (OCTET_STRING) */
260 per_read_length(s, &length);
261 if (!gcc_read_server_data_blocks(s, settings, length))
263 printf("gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
270 void gcc_write_conference_create_response(STREAM* s, STREAM* user_data)
273 per_write_choice(s, 0);
274 per_write_object_identifier(s, t124_02_98_oid);
276 /* ConnectData::connectPDU (OCTET_STRING) */
277 per_write_length(s, stream_get_length(user_data) + 2);
280 per_write_choice(s, 0x14);
282 /* ConferenceCreateResponse::nodeID (UserID) */
283 per_write_integer16(s, 0x79F3, 1001);
285 /* ConferenceCreateResponse::tag (INTEGER) */
286 per_write_integer(s, 1);
288 /* ConferenceCreateResponse::result (ENUMERATED) */
289 per_write_enumerated(s, 0, MCS_Result_enum_length);
291 /* number of UserData sets */
292 per_write_number_of_sets(s, 1);
294 /* UserData::value present + select h221NonStandard (1) */
295 per_write_choice(s, 0xC0);
297 /* h221NonStandard */
298 per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
300 /* userData (OCTET_STRING) */
301 per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of server data blocks */
304 boolean gcc_read_client_data_blocks(STREAM* s, rdpSettings *settings, int length)
312 pos = stream_get_pos(s);
313 gcc_read_user_data_header(s, &type, &blockLength);
318 if (!gcc_read_client_core_data(s, settings, blockLength - 4))
323 if (!gcc_read_client_security_data(s, settings, blockLength - 4))
328 if (!gcc_read_client_network_data(s, settings, blockLength - 4))
333 if (!gcc_read_client_cluster_data(s, settings, blockLength - 4))
338 if (!gcc_read_client_monitor_data(s, settings, blockLength - 4))
346 length -= blockLength;
347 stream_set_pos(s, pos + blockLength);
353 void gcc_write_client_data_blocks(STREAM* s, rdpSettings *settings)
355 gcc_write_client_core_data(s, settings);
356 gcc_write_client_cluster_data(s, settings);
357 gcc_write_client_security_data(s, settings);
358 gcc_write_client_network_data(s, settings);
359 gcc_write_client_monitor_data(s, settings);
362 boolean gcc_read_server_data_blocks(STREAM* s, rdpSettings *settings, int length)
369 while (offset < length)
373 if (!gcc_read_user_data_header(s, &type, &blockLength))
375 printf("gcc_read_server_data_blocks: gcc_read_user_data_header failed\n");
382 if (!gcc_read_server_core_data(s, settings))
384 printf("gcc_read_server_data_blocks: gcc_read_server_core_data failed\n");
390 if (!gcc_read_server_security_data(s, settings))
392 printf("gcc_read_server_data_blocks: gcc_read_server_security_data failed\n");
398 if (!gcc_read_server_network_data(s, settings))
400 printf("gcc_read_server_data_blocks: gcc_read_server_network_data failed\n");
408 offset += blockLength;
409 s->p = holdp + blockLength;
415 void gcc_write_server_data_blocks(STREAM* s, rdpSettings *settings)
417 gcc_write_server_core_data(s, settings);
418 gcc_write_server_network_data(s, settings);
419 gcc_write_server_security_data(s, settings);
422 boolean gcc_read_user_data_header(STREAM* s, uint16* type, uint16* length)
424 stream_read_uint16(s, *type); /* type */
425 stream_read_uint16(s, *length); /* length */
427 if (stream_get_left(s) < *length - 4)
434 * Write a user data header (TS_UD_HEADER).\n
437 * @param type data block type
438 * @param length data block length
441 void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length)
443 stream_write_uint16(s, type); /* type */
444 stream_write_uint16(s, length); /* length */
448 * Read a client core data block (TS_UD_CS_CORE).\n
451 * @param settings rdp settings
454 boolean gcc_read_client_core_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
457 uint16 colorDepth = 0;
458 uint16 postBeta2ColorDepth = 0;
459 uint16 highColorDepth = 0;
460 uint16 supportedColorDepths = 0;
461 uint16 earlyCapabilityFlags = 0;
462 uint32 serverSelectedProtocol = 0;
465 /* Length of all required fields, until imeFileName */
466 if (blockLength < 128)
469 stream_read_uint32(s, version); /* version */
470 settings->rdp_version = (version == RDP_VERSION_4 ? 4 : 7);
472 stream_read_uint16(s, settings->width); /* desktopWidth */
473 stream_read_uint16(s, settings->height); /* desktopHeight */
474 stream_read_uint16(s, colorDepth); /* colorDepth */
475 stream_seek_uint16(s); /* SASSequence (Secure Access Sequence) */
476 stream_read_uint32(s, settings->kbd_layout); /* keyboardLayout */
477 stream_read_uint32(s, settings->client_build); /* clientBuild */
479 /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
480 str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 32);
482 snprintf(settings->client_hostname, sizeof(settings->client_hostname), "%s", str);
485 stream_read_uint32(s, settings->kbd_type); /* keyboardType */
486 stream_read_uint32(s, settings->kbd_subtype); /* keyboardSubType */
487 stream_read_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */
489 stream_seek(s, 64); /* imeFileName */
494 * The following fields are all optional. If one field is present, all of the preceding
495 * fields MUST also be present. If one field is not present, all of the subsequent fields
496 * MUST NOT be present.
497 * We must check the bytes left before reading each field.
504 stream_read_uint16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */
509 stream_seek_uint16(s); /* clientProductID */
514 stream_seek_uint32(s); /* serialNumber */
519 stream_read_uint16(s, highColorDepth); /* highColorDepth */
524 stream_read_uint16(s, supportedColorDepths); /* supportedColorDepths */
529 stream_read_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
532 if (blockLength < 64)
534 str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64);
536 snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str);
542 stream_read_uint8(s, settings->performance_flags); /* connectionType */
547 stream_seek_uint8(s); /* pad1octet */
552 stream_read_uint32(s, serverSelectedProtocol); /* serverSelectedProtocol */
555 if (settings->selected_protocol != serverSelectedProtocol)
559 if (highColorDepth > 0)
560 settings->color_depth = highColorDepth;
561 else if (postBeta2ColorDepth > 0)
563 switch (postBeta2ColorDepth)
565 case RNS_UD_COLOR_4BPP:
566 settings->color_depth = 4;
568 case RNS_UD_COLOR_8BPP:
569 settings->color_depth = 8;
571 case RNS_UD_COLOR_16BPP_555:
572 settings->color_depth = 15;
574 case RNS_UD_COLOR_16BPP_565:
575 settings->color_depth = 16;
577 case RNS_UD_COLOR_24BPP:
578 settings->color_depth = 24;
588 case RNS_UD_COLOR_4BPP:
589 settings->color_depth = 4;
591 case RNS_UD_COLOR_8BPP:
592 settings->color_depth = 8;
603 * Write a client core data block (TS_UD_CS_CORE).\n
606 * @param settings rdp settings
609 void gcc_write_client_core_data(STREAM* s, rdpSettings *settings)
613 size_t clientNameLength;
614 uint8 connectionType;
615 uint16 highColorDepth;
616 uint16 supportedColorDepths;
617 uint16 earlyCapabilityFlags;
618 char* clientDigProductId;
619 size_t clientDigProductIdLength;
621 gcc_write_user_data_header(s, CS_CORE, 216);
623 version = settings->rdp_version >= 5 ? RDP_VERSION_5_PLUS : RDP_VERSION_4;
624 clientName = freerdp_uniconv_out(settings->uniconv, settings->client_hostname, &clientNameLength);
625 clientDigProductId = freerdp_uniconv_out(settings->uniconv, settings->client_product_id, &clientDigProductIdLength);
627 stream_write_uint32(s, version); /* version */
628 stream_write_uint16(s, settings->width); /* desktopWidth */
629 stream_write_uint16(s, settings->height); /* desktopHeight */
630 stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* colorDepth, ignored because of postBeta2ColorDepth */
631 stream_write_uint16(s, RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */
632 stream_write_uint32(s, settings->kbd_layout); /* keyboardLayout */
633 stream_write_uint32(s, settings->client_build); /* clientBuild */
635 /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
636 if (clientNameLength > 30)
638 clientNameLength = 30;
639 clientName[clientNameLength] = 0;
640 clientName[clientNameLength + 1] = 0;
642 stream_write(s, clientName, clientNameLength + 2);
643 stream_write_zero(s, 32 - clientNameLength - 2);
646 stream_write_uint32(s, settings->kbd_type); /* keyboardType */
647 stream_write_uint32(s, settings->kbd_subtype); /* keyboardSubType */
648 stream_write_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */
650 stream_write_zero(s, 64); /* imeFileName */
652 stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */
653 stream_write_uint16(s, 1); /* clientProductID */
654 stream_write_uint32(s, 0); /* serialNumber (should be initialized to 0) */
656 highColorDepth = MIN(settings->color_depth, 24);
658 supportedColorDepths =
659 RNS_UD_24BPP_SUPPORT |
660 RNS_UD_16BPP_SUPPORT |
661 RNS_UD_15BPP_SUPPORT;
664 earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;
666 if (settings->performance_flags == PERF_FLAG_NONE)
668 earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;
669 connectionType = CONNECTION_TYPE_LAN;
672 if (settings->color_depth == 32)
674 supportedColorDepths |= RNS_UD_32BPP_SUPPORT;
675 earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
678 stream_write_uint16(s, highColorDepth); /* highColorDepth */
679 stream_write_uint16(s, supportedColorDepths); /* supportedColorDepths */
681 stream_write_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
683 /* clientDigProductId (64 bytes, null-terminated unicode, truncated to 30 characters) */
684 if (clientDigProductIdLength > 62)
686 clientDigProductIdLength = 62;
687 clientDigProductId[clientDigProductIdLength] = 0;
688 clientDigProductId[clientDigProductIdLength + 1] = 0;
690 stream_write(s, clientDigProductId, clientDigProductIdLength + 2);
691 stream_write_zero(s, 64 - clientDigProductIdLength - 2);
692 xfree(clientDigProductId);
694 stream_write_uint8(s, connectionType); /* connectionType */
695 stream_write_uint8(s, 0); /* pad1octet */
697 stream_write_uint32(s, settings->selected_protocol); /* serverSelectedProtocol */
700 boolean gcc_read_server_core_data(STREAM* s, rdpSettings *settings)
703 uint32 clientRequestedProtocols;
705 stream_read_uint32(s, version); /* version */
706 stream_read_uint32(s, clientRequestedProtocols); /* clientRequestedProtocols */
708 if (version == RDP_VERSION_4 && settings->rdp_version > 4)
709 settings->rdp_version = 4;
710 else if (version == RDP_VERSION_5_PLUS && settings->rdp_version < 5)
711 settings->rdp_version = 7;
716 void gcc_write_server_core_data(STREAM* s, rdpSettings *settings)
718 gcc_write_user_data_header(s, SC_CORE, 12);
720 stream_write_uint32(s, settings->rdp_version == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS);
721 stream_write_uint32(s, settings->requested_protocols); /* clientRequestedProtocols */
725 * Read a client security data block (TS_UD_CS_SEC).\n
728 * @param settings rdp settings
731 boolean gcc_read_client_security_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
736 stream_read_uint32(s, settings->encryption_method); /* encryptionMethods */
737 if (settings->encryption_method == 0)
738 stream_read_uint32(s, settings->encryption_method); /* extEncryptionMethods */
744 * Write a client security data block (TS_UD_CS_SEC).\n
747 * @param settings rdp settings
750 void gcc_write_client_security_data(STREAM* s, rdpSettings *settings)
752 gcc_write_user_data_header(s, CS_SECURITY, 12);
754 if (settings->encryption)
756 stream_write_uint32(s, settings->encryption_method); /* encryptionMethods */
757 stream_write_uint32(s, 0); /* extEncryptionMethods */
761 /* French locale, disable encryption */
762 stream_write_uint32(s, 0); /* encryptionMethods */
763 stream_write_uint32(s, settings->encryption_method); /* extEncryptionMethods */
767 boolean gcc_read_server_security_data(STREAM* s, rdpSettings *settings)
769 uint32 serverRandomLen;
770 uint32 serverCertLen;
774 stream_read_uint32(s, settings->encryption_method); /* encryptionMethod */
775 stream_read_uint32(s, settings->encryption_level); /* encryptionLevel */
777 if (settings->encryption_method == 0 && settings->encryption_level == 0)
779 /* serverRandom and serverRandom must not be present */
780 settings->encryption = False;
781 settings->encryption_method = ENCRYPTION_METHOD_NONE;
782 settings->encryption_level = ENCRYPTION_LEVEL_NONE;
786 stream_read_uint32(s, serverRandomLen); /* serverRandomLen */
787 stream_read_uint32(s, serverCertLen); /* serverCertLen */
789 if (serverRandomLen > 0)
792 freerdp_blob_alloc(&settings->server_random, serverRandomLen);
793 memcpy(settings->server_random.data, s->p, serverRandomLen);
794 stream_seek(s, serverRandomLen);
795 freerdp_hexdump(settings->server_random.data, settings->server_random.length);
802 if (serverCertLen > 0)
804 /* serverCertificate */
805 freerdp_blob_alloc(&settings->server_certificate, serverCertLen);
806 memcpy(settings->server_certificate.data, s->p, serverCertLen);
807 stream_seek(s, serverCertLen);
808 certificate_free(settings->server_cert);
809 settings->server_cert = certificate_new();
810 data = settings->server_certificate.data;
811 len = settings->server_certificate.length;
812 if (!certificate_read_server_certificate(settings->server_cert, data, len))
825 void gcc_write_server_security_data(STREAM* s, rdpSettings *settings)
827 gcc_write_user_data_header(s, SC_SECURITY, 12);
829 stream_write_uint32(s, ENCRYPTION_METHOD_NONE); /* encryptionMethod */
830 stream_write_uint32(s, ENCRYPTION_LEVEL_NONE); /* encryptionLevel */
832 stream_write_uint32(s, 0); /* serverRandomLen */
833 stream_write_uint32(s, 0); /* serverCertLen */
838 * Read a client network data block (TS_UD_CS_NET).\n
841 * @param settings rdp settings
844 boolean gcc_read_client_network_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
851 stream_read_uint32(s, settings->num_channels); /* channelCount */
852 if (blockLength < 4 + settings->num_channels * 12)
854 if (settings->num_channels > 16)
857 /* channelDefArray */
858 for (i = 0; i < settings->num_channels; i++)
861 stream_read(s, settings->channels[i].name, 8); /* name (8 bytes) */
862 stream_read_uint32(s, settings->channels[i].options); /* options (4 bytes) */
863 settings->channels[i].chan_id = MCS_GLOBAL_CHANNEL_ID + 1 + i;
870 * Write a client network data block (TS_UD_CS_NET).\n
873 * @param settings rdp settings
876 void gcc_write_client_network_data(STREAM* s, rdpSettings *settings)
881 if (settings->num_channels > 0)
883 length = settings->num_channels * 12 + 8;
884 gcc_write_user_data_header(s, CS_NET, length);
886 stream_write_uint32(s, settings->num_channels); /* channelCount */
888 /* channelDefArray */
889 for (i = 0; i < settings->num_channels; i++)
892 stream_write(s, settings->channels[i].name, 8); /* name (8 bytes) */
893 stream_write_uint32(s, settings->channels[i].options); /* options (4 bytes) */
898 boolean gcc_read_server_network_data(STREAM* s, rdpSettings *settings)
905 stream_read_uint16(s, MCSChannelId); /* MCSChannelId */
906 stream_read_uint16(s, channelCount); /* channelCount */
908 if (channelCount != settings->num_channels)
910 printf("requested %d channels, got %d instead\n",
911 settings->num_channels, channelCount);
914 for (i = 0; i < channelCount; i++)
916 stream_read_uint16(s, channelId); /* channelId */
917 settings->channels[i].chan_id = channelId;
920 if (channelCount % 2 == 1)
921 stream_seek(s, 2); /* padding */
926 void gcc_write_server_network_data(STREAM* s, rdpSettings *settings)
930 gcc_write_user_data_header(s, SC_NET, 8 + settings->num_channels * 2 + (settings->num_channels % 2 == 1 ? 2 : 0));
932 stream_write_uint16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */
933 stream_write_uint16(s, settings->num_channels); /* channelCount */
935 for (i = 0; i < settings->num_channels; i++)
937 stream_write_uint16(s, settings->channels[i].chan_id);
940 if (settings->num_channels % 2 == 1)
941 stream_write_uint16(s, 0);
945 * Read a client cluster data block (TS_UD_CS_CLUSTER).\n
948 * @param settings rdp settings
951 boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
958 stream_read_uint32(s, flags); /* flags */
960 if ((flags | REDIRECTED_SESSIONID_FIELD_VALID))
961 stream_read_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
967 * Write a client cluster data block (TS_UD_CS_CLUSTER).\n
970 * @param settings rdp settings
973 void gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings)
977 gcc_write_user_data_header(s, CS_CLUSTER, 12);
979 flags = REDIRECTION_SUPPORTED | (REDIRECTION_VERSION4 << 2);
981 if (settings->console_session || settings->redirected_session_id)
982 flags |= REDIRECTED_SESSIONID_FIELD_VALID;
984 stream_write_uint32(s, flags); /* flags */
985 stream_write_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
989 * Read a client monitor data block (TS_UD_CS_MONITOR).\n
992 * @param settings rdp settings
995 boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
997 printf("CS_MONITOR\n");
1002 * Write a client monitor data block (TS_UD_CS_MONITOR).\n
1005 * @param settings rdp settings
1008 void gcc_write_client_monitor_data(STREAM* s, rdpSettings *settings)
1012 uint32 left, top, right, bottom, flags;
1014 if (settings->num_monitors > 1)
1016 length = (20 * settings->num_monitors) + 12;
1017 gcc_write_user_data_header(s, CS_MONITOR, length);
1019 stream_write_uint32(s, 0); /* flags */
1020 stream_write_uint32(s, settings->num_monitors); /* monitorCount */
1022 for (i = 0; i < settings->num_monitors; i++)
1024 left = settings->monitors[i].x;
1025 top = settings->monitors[i].y;
1026 right = settings->monitors[i].x + settings->monitors[i].width - 1;
1027 bottom = settings->monitors[i].y + settings->monitors[i].height - 1;
1028 flags = settings->monitors[i].is_primary ? MONITOR_PRIMARY : 0;
1030 stream_write_uint32(s, left); /* left */
1031 stream_write_uint32(s, top); /* top */
1032 stream_write_uint32(s, right); /* right */
1033 stream_write_uint32(s, bottom); /* bottom */
1034 stream_write_uint32(s, flags); /* flags */