The Client Control PDU (Cooperate) is a Standard RDP Connection Sequence PDU sent from client to server during the Connection Finalization phase (see section ). It is sent after transmitting the Client Synchronize PDU.
file:///C:/ts_dev/TestSuites/MS-RDPBCGR/TestSuite/Src/TD/latest_XMLS_16may/RDPBCGR/ _rfc_ms-rdpbcgr2_1_1_15.xml
Inheritance: RdpbcgrClientPdu
        /// <summary>
        /// Decode Control PDU 
        /// </summary>
        /// <param name="data">data to be parsed</param>
        /// <param name="decryptedUserData">decrypted user data to be parsed</param>
        /// <param name="type">security header type</param>
        /// <returns>decoded Control PDU</returns>
        public StackPacket DecodeControlPDU(
            byte[] data,
            byte[] decryptedUserData,
            SecurityHeaderType type)
        {
            // data index
            int dataIndex = 0;

            // ControlPDU: commonHeader
            SlowPathPduCommonHeader commonHeader = ParseMcsCommonHeader(data, ref dataIndex, type);

            // user data index
            int userDataIndex = 0;

            // ControlPDU: controlPduData
            TS_CONTROL_PDU controlPduData = ParseTsControlPdu(decryptedUserData, ref userDataIndex);

            // Get pdu by action type
            StackPacket pdu;
            if (controlPduData.action == action_Values.CTRLACTION_COOPERATE)
            {
                // Control PDU - cooperate
                Client_Control_Pdu_Cooperate cooperatePdu = new Client_Control_Pdu_Cooperate();
                cooperatePdu.commonHeader = commonHeader;
                cooperatePdu.controlPduData = controlPduData;
                pdu = cooperatePdu;

                // ETW Provider Dump Message
                if (cooperatePdu.commonHeader.securityHeader != null)
                {
                    // RDP Standard Security
                    string messageName = "RDPBCGR:" + cooperatePdu.GetType().Name;
                    ExtendedLogger.DumpMessage(messageName, RdpbcgrUtility.DumpLevel_Layer3, cooperatePdu.GetType().Name, decryptedUserData);
                }
            }
            else if (controlPduData.action == action_Values.CTRLACTION_REQUEST_CONTROL)
            {
                // Control PDU - granted control
                Client_Control_Pdu_Request_Control requestPdu = new Client_Control_Pdu_Request_Control();
                requestPdu.commonHeader = commonHeader;
                requestPdu.controlPduData = controlPduData;
                pdu = requestPdu;

                // ETW Provider Dump Message
                if (requestPdu.commonHeader.securityHeader != null)
                {
                    // RDP Standard Security
                    string messageName = "RDPBCGR:" + requestPdu.GetType().Name;
                    ExtendedLogger.DumpMessage(messageName, RdpbcgrUtility.DumpLevel_Layer3, requestPdu.GetType().Name, decryptedUserData);
                }
            }
            else
            {
                throw new FormatException(ConstValue.ERROR_MESSAGE_ENUM_UNRECOGNIZED);
            }

            // Check if data length exceeded expectation
            VerifyDataLength(decryptedUserData.Length, userDataIndex, ConstValue.ERROR_MESSAGE_DATA_LENGTH_EXCEEDED);
            return pdu;
        }
        /// <summary>
        /// 2.2.1.15
        /// </summary>
        /// <param name="clientCoopPdu"></param>
        public void VerifyPdu(Client_Control_Pdu_Cooperate clientCoopPdu)
        {
            if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT ||
                serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT ||
                serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT)
            {
                site.CaptureRequirementIfIsInstanceOfType(clientCoopPdu.commonHeader.securityHeader, typeof(TS_SECURITY_HEADER1), 747,
                    @"[In Client Control PDU - Cooperate]securityHeader (variable):  The securityHeader in "
                    + @"Server Demand Active PDU is a Non-FIPS Security Header (section 2.2.8.1.1.2.2) if "
                    + @"the Encryption LevelMethod selected by the server (see sections 5.3.2 and 2.2.1.4.3) "
                    + @"is ENCRYPTION_LEVEL_CLIENT_COMPATIBLE (2)METHOD_40BIT (0x00000001), ENCRYPTION_METHOD_56BIT"
                    + @" (0x00000008), or ENCRYPTION_LEVEL_HIGH (3METHOD_128BIT (0x00000002).");
            }
            else if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_FIPS)
            {
                site.CaptureRequirementIfIsInstanceOfType(clientCoopPdu.commonHeader.securityHeader, typeof(TS_SECURITY_HEADER2), 748,
                    @"[In Client Control PDU - Cooperate]securityHeader (variable):The securityHeader in Server"
                    + @" Demand Active PDU is a FIPS Security Header,if the Encryption LevelMethod selected by "
                    + @"the server is ENCRYPTION_METHOD_FIPS (0x00000010).");
            }
            else if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_NONE)
            {
                site.CaptureRequirementIfIsNull(clientCoopPdu.commonHeader.securityHeader, 749,
                    @" Client Control PDU - Cooperate ,If Enhanced RDP Security is in effect or the Encryption "
                    + @"Method selected by the server is ENCRYPTION_METHOD_NONE (0), then securityHeader MUST NOT"
                    + @" be  included in the Client Control PDU - Cooperate.");
            }
            site.CaptureRequirementIfIsTrue(clientCoopPdu.controlPduData.controlId == 0 && clientCoopPdu.controlPduData.grantId == 0, 751,
                @"In controlPduData of Client Control PDU - Cooperate, The grantId and controlId fields of the "
                + @"Control PDU Data MUST both be set to zero.");

            site.CaptureRequirementIfAreEqual<action_Values>(action_Values.CTRLACTION_COOPERATE, clientCoopPdu.controlPduData.action, 752,
                @"In controlPduData of Client Control PDU - Cooperate, the action field MUST be set to "
                + @"CTRLACTION_COOPERATE (0x0004).");

            site.CaptureRequirementIfAreEqual<int>(7, (clientCoopPdu.controlPduData.shareDataHeader.shareControlHeader.pduType.typeAndVersionLow & 0xf), 755,
                @"In TS_CONTROL_PDU, the type subfield of the pduType field of the Share Control Header of TS_CONTROL_PDU"
                + @" structure MUST be set to PDUTYPE_DATAPDU (7). ");

            site.CaptureRequirementIfAreEqual<pduType2_Values>(pduType2_Values.PDUTYPE2_CONTROL, clientCoopPdu.controlPduData.shareDataHeader.pduType2, 756,
                @" In TS_CONTROL_PDU, the pduType2 field of the Share Data Header  of TS_CONTROL_PDU structure MUST be set"
                + @" to PDUTYPE2_CONTROL (20).");
            bool isR758Satisfied = clientCoopPdu.controlPduData.action == action_Values.CTRLACTION_REQUEST_CONTROL ||
                clientCoopPdu.controlPduData.action == action_Values.CTRLACTION_GRANTED_CONTROL ||
                clientCoopPdu.controlPduData.action == action_Values.CTRLACTION_DETACH ||
                clientCoopPdu.controlPduData.action == action_Values.CTRLACTION_COOPERATE;
            site.CaptureRequirementIfIsTrue(isR758Satisfied, 758,
                @"In TS_CONTROL_PDU, the action field must take one of the following values  1.CTRLACTION_REQUEST_CONTROL"
                + @" 0x0001 - Request control 2.CTRLACTION_GRANTED_CONTROL 0x0002 - Granted control 3.CTRLACTION_DETACH "
                + @"0x0003 - Detach 4.CTRLACTION_COOPERATE 0x0004 - Cooperate");
        }
        /// <summary>
        /// Create an instance of the class that is identical to the current PDU. 
        /// </summary>
        /// <returns>The new instance.</returns>
        public override StackPacket Clone()
        {
            Client_Control_Pdu_Cooperate cloneControlCoopPdu = new Client_Control_Pdu_Cooperate(context);

            cloneControlCoopPdu.commonHeader = commonHeader.Clone();
            cloneControlCoopPdu.controlPduData = controlPduData;

            return cloneControlCoopPdu;
        }