/// <summary>
        /// Composes ROP command buffer.
        /// </summary>
        /// <param name="requestROPs">The array of ROP commands.</param>
        /// <param name="requestSOHTable">The array of request handle table.</param>
        /// <returns>Returns byte array of serialized ROP command buffer.</returns>
        private byte[] BuildRequestBuffer(List <ISerializable> requestROPs, List <uint> requestSOHTable)
        {
            int payloadLen = ConstValues.RopSizeInRopInputOutputBufferSize;

            foreach (ISerializable requestROP in requestROPs)
            {
                payloadLen += requestROP.Size();
            }

            ushort ropSize = (ushort)payloadLen;

            payloadLen += requestSOHTable.Count * sizeof(uint);

            byte[] requestBuffer = new byte[RPCHeaderExtlength + payloadLen];
            int    index         = 0;

            // Constructs RPC_HEADER_EXT buffer
            RPC_HEADER_EXT rpcHeaderExt = new RPC_HEADER_EXT
            {
                Version = ConstValues.RpcHeaderExtVersionValue,
                Flags   = (ushort)RpcHeaderExtFlags.Last,
                Size    = (ushort)payloadLen
            };

            rpcHeaderExt.SizeActual = rpcHeaderExt.Size;

            IntPtr ptr = Marshal.AllocHGlobal(RPCHeaderExtlength);

            // Release ptr in final sub-statement to make sure the resources will be released even if an exception occurs
            try
            {
                Marshal.StructureToPtr(rpcHeaderExt, ptr, true);
                Marshal.Copy(ptr, requestBuffer, index, RPCHeaderExtlength);
                index += RPCHeaderExtlength;
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }

            Array.Copy(BitConverter.GetBytes(ropSize), 0, requestBuffer, index, ConstValues.RopSizeInRopInputOutputBufferSize);
            index += ConstValues.RopSizeInRopInputOutputBufferSize;

            foreach (ISerializable requestROP in requestROPs)
            {
                Array.Copy(requestROP.Serialize(), 0, requestBuffer, index, requestROP.Size());
                index += requestROP.Size();
            }

            foreach (uint serverHandle in requestSOHTable)
            {
                Array.Copy(BitConverter.GetBytes(serverHandle), 0, requestBuffer, index, sizeof(uint));
                index += sizeof(uint);
            }

            return(requestBuffer);
        }
        /// <summary>
        /// The method creates a request without ROPs.
        /// </summary>
        /// <returns>The ROPs request.</returns>
        public byte[] BuildRequestBufferWithoutRop()
        {
            // Only RopSize field (2 bytes) exists in the payload of request without ROPs.
            int    payloadLen         = 2;
            ushort ropSize            = 2;
            int    rpcHeaderExtlength = Marshal.SizeOf(typeof(RPC_HEADER_EXT));

            byte[] requestBuffer = new byte[rpcHeaderExtlength + payloadLen];
            int    index         = 0;

            // Constructs RPC header ext buffer
            RPC_HEADER_EXT rpcHeaderExt = new RPC_HEADER_EXT
            {
                // According to Open Specification, Version filed MUST be set to 0x0000.
                Version    = 0,
                Flags      = (byte)RpcHeaderExtFlags.Last,
                Size       = (ushort)payloadLen,
                SizeActual = (ushort)payloadLen
            };

            // No compression and No obfuscation
            IntPtr ptr = Marshal.AllocHGlobal(rpcHeaderExtlength);

            // Release ptr in final sub-statement to make sure the resources will be released even if an exception occurs
            try
            {
                Marshal.StructureToPtr(rpcHeaderExt, ptr, true);
                Marshal.Copy(ptr, requestBuffer, index, rpcHeaderExtlength);
                index += rpcHeaderExtlength;
            }
            catch (ArgumentException e)
            {
                // Marshal.StructureToPtr or Marshal.Copy throw exception.
                throw new NotImplementedException(e.Message);
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }

            Array.Copy(BitConverter.GetBytes(ropSize), 0, requestBuffer, index, sizeof(ushort));

            return(requestBuffer);
        }
        /// <summary>
        /// The method creates ROPs request buffer.
        /// </summary>
        /// <param name="requestROPs">ROPs in request.</param>
        /// <param name="requestSOHTable">Server object handles table.</param>
        /// <returns>The ROPs request buffer.</returns>
        public byte[] BuildRequestBuffer(List <ISerializable> requestROPs, List <uint> requestSOHTable)
        {
            // Definition for PayloadLen which indicates the length of the field that represents the length of payload.
            int payloadLen = 0x2;

            if (requestROPs != null)
            {
                foreach (ISerializable requestROP in requestROPs)
                {
                    payloadLen += requestROP.Size();
                }
            }

            ushort ropSize = (ushort)payloadLen;

            if (requestSOHTable != null)
            {
                payloadLen += requestSOHTable.Count * sizeof(uint);
            }

            byte[] requestBuffer = new byte[RPCHEADEREXTLEN + payloadLen];
            int    index         = 0;

            // Construct RPC header ext buffer
            RPC_HEADER_EXT rpcHeaderExt = new RPC_HEADER_EXT();

            // There is only one version of the header at this time so this value MUST be set to 0x00.
            rpcHeaderExt.Version = 0x00;

            // Last (0x04) indicates that no other RPC_HEADER_EXT follows the data of the current RPC_HEADER_EXT.
            rpcHeaderExt.Flags = LastForFlagsOfHeader;

            rpcHeaderExt.Size       = (ushort)payloadLen;
            rpcHeaderExt.SizeActual = rpcHeaderExt.Size;

            IntPtr ptr = Marshal.AllocHGlobal(RPCHEADEREXTLEN);

            try
            {
                Marshal.StructureToPtr(rpcHeaderExt, ptr, true);
                Marshal.Copy(ptr, requestBuffer, index, RPCHEADEREXTLEN);
                index += RPCHEADEREXTLEN;
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }

            // RopSize's type is ushort. So the offset will be 2.
            Array.Copy(BitConverter.GetBytes(ropSize), 0, requestBuffer, index, 2);
            index += 2;

            if (requestROPs != null)
            {
                foreach (ISerializable requestROP in requestROPs)
                {
                    Array.Copy(requestROP.Serialize(), 0, requestBuffer, index, requestROP.Size());
                    index += requestROP.Size();
                }
            }

            if (requestSOHTable != null)
            {
                foreach (uint serverHandle in requestSOHTable)
                {
                    Array.Copy(BitConverter.GetBytes(serverHandle), 0, requestBuffer, index, sizeof(uint));
                    index += sizeof(uint);
                }
            }

            // Compress and obfuscate request buffer as configured.
            requestBuffer = Common.CompressAndObfuscateRequest(requestBuffer, this.site);

            return(requestBuffer);
        }
        /// <summary>
        /// Add the object to TreeNode and calculate the byte number it consumed
        /// </summary>
        /// <param name="obj">The object need to display in TreeView</param>
        /// <param name="startIndex">The start position of the object in HexView</param>
        /// <param name="offset">The byte number consumed by the object</param>
        /// <returns>The TreeNode with object value information</returns>
        public static TreeNode AddNodesForTree(object obj, int startIndex, out int offset)
        {
            Type     t       = obj.GetType();
            int      current = startIndex;
            TreeNode res     = new TreeNode(t.Name);

            if (t.Name == "MAPIString")
            {
                int         os         = 0;
                FieldInfo[] infoString = t.GetFields();
                string      terminator = (string)infoString[2].GetValue(obj);
                TreeNode    node       = new TreeNode(string.Format("{0}:{1}", infoString[0].Name, infoString[0].GetValue(obj)));

                // If the Encoding is Unicode.
                if (infoString[1].GetValue(obj).ToString() == "System.Text.UnicodeEncoding")
                {
                    // If the StringLength is not equal 0, the StringLength will be os value.
                    if (infoString[3].GetValue(obj).ToString() != "0")
                    {
                        os = ((int)infoString[3].GetValue(obj)) * 2;
                    }
                    else
                    {
                        if (infoString[0].GetValue(obj) != null)
                        {
                            os = ((string)infoString[0].GetValue(obj)).Length * 2;
                        }

                        if (infoString[4].GetValue(obj).ToString() != "False")
                        {
                            os -= 1;
                        }

                        os += terminator.Length * 2;
                    }
                }
                else
                {
                    // If the Encoding is ASCII.
                    if (infoString[3].GetValue(obj).ToString() != "0")
                    {
                        // If the StringLength is not equal 0, the StringLength will be os value
                        os = (int)infoString[3].GetValue(obj);
                    }
                    else
                    {
                        if (infoString[0].GetValue(obj) != null)
                        {
                            os = ((string)infoString[0].GetValue(obj)).Length;
                        }

                        os += terminator.Length;
                    }
                }

                offset = os;
                Position positionString = new Position(current, os);
                node.Tag = positionString;
                res.Nodes.Add(node);
                return(res);
            }
            else if (t.Name == "MAPIStringAddressBook")
            {
                FieldInfo[] infoString = t.GetFields();

                // MagicByte node
                if (infoString[1].GetValue(obj) != null)
                {
                    TreeNode nodeMagic           = new TreeNode(string.Format("{0}:{1}", infoString[1].Name, infoString[1].GetValue(obj)));
                    Position positionStringMagic = new Position(current, 1);
                    nodeMagic.Tag = positionStringMagic;
                    res.Nodes.Add(nodeMagic);
                    current += 1;
                }

                // value node
                string   terminator = (string)infoString[3].GetValue(obj);
                int      os         = 0;
                TreeNode node       = new TreeNode(string.Format("{0}:{1}", infoString[0].Name, infoString[0].GetValue(obj)));

                // If the Encoding is Unicode.
                if (infoString[2].GetValue(obj).ToString() == "System.Text.UnicodeEncoding")
                {
                    // If the StringLength is not equal 0, the StringLength will be OS value.
                    if (infoString[4].GetValue(obj).ToString() != "0")
                    {
                        os = ((int)infoString[4].GetValue(obj)) * 2;
                    }
                    else
                    {
                        if (infoString[0].GetValue(obj) != null)
                        {
                            os = ((string)infoString[0].GetValue(obj)).Length * 2;
                        }

                        if (infoString[5].GetValue(obj).ToString() != "False")
                        {
                            os -= 1;
                        }

                        os += terminator.Length * 2;
                    }
                }
                else
                {
                    // If the Encoding is ASCII.
                    if (infoString[4].GetValue(obj).ToString() != "0")
                    {
                        // If the StringLength is not equal 0, the StringLength will be OS value.
                        os = (int)infoString[4].GetValue(obj);
                    }
                    else
                    {
                        if (infoString[0].GetValue(obj) != null)
                        {
                            os = ((string)infoString[0].GetValue(obj)).Length;
                        }

                        os += terminator.Length;
                    }
                }

                Position positionString = new Position(current, os);
                node.Tag = positionString;
                res.Nodes.Add(node);

                if (infoString[1].GetValue(obj) != null)
                {
                    offset = os + 1;
                }
                else
                {
                    offset = os;
                }

                return(res);
            }
            else if (t.Name == "AnnotatedBytes")
            {
                var infoString  = t.GetFields();
                var bytes       = (byte[])infoString[0].GetValue(obj);
                var bytesString = Utilities.ConvertArrayToHexString(bytes);
                var annotation  = (string)infoString[1].GetValue(obj);
                var node        = new TreeNode($"{infoString[0].Name}:{bytesString}");

                offset   = bytes.Length;
                node.Tag = new Position(current, offset);
                res.Nodes.Add(node);
                var annotationNode = new TreeNode($"annotation:{annotation}");
                annotationNode.Tag = new Position(current, offset);
                res.Nodes.Add(annotationNode);
                return(res);
            }

            // Check whether the data type is simple type
            if (Enum.IsDefined(typeof(DataType), t.Name))
            {
                throw new Exception("The method doesn't support handling simple data type.");
            }
            else
            {
                // If the data type is not simple type, we will loop each field, check the data type and then parse the value in different format
                FieldInfo[] info      = t.GetFields();
                int         bitLength = 0;

                // The is only for FastTransfer stream parse, Polymorphic in PropValue and NamedPropInfo
                if (obj is PropValue || obj is NamedPropInfo)
                {
                    info = MoveFirstNFieldsBehind(info, info.Length - 2);
                }

                for (int i = 0; i < info.Length; i++)
                {
                    int  os   = 0;
                    Type type = info[i].FieldType;

                    // If the field type is object type and its value is not null, set the field data type as details type (such as field A is Object (int/short) type, here setting it as int or short type)
                    if (type.Name == "Object" && info[i].GetValue(obj) != null)
                    {
                        type = info[i].GetValue(obj).GetType();
                    }

                    // If the field type is null-able simple data type (such as int?), set the field data type as basic data type (such as int in int?)
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
                    {
                        type = type.GetGenericArguments()[0];
                    }

                    // Check whether the field data type is simple type:
                    // Boolean, Byte, Char, Double, Decimal,Single, GUID, Int16, Int32, Int64, SByte, String, UInt16, UInt32, UInt64, DateTime
                    // calculate each field's offset and length.
                    if (Enum.IsDefined(typeof(DataType), type.Name))
                    {
                        if (info[i].GetValue(obj) != null)
                        {
                            Type     fieldType = type;
                            TreeNode tn        = new TreeNode(string.Format("{0}:{1}", info[i].Name, info[i].GetValue(obj).ToString()));
                            res.Nodes.Add(tn);

                            if (type.Name == "UInt64")
                            {
                                if (info[i].GetCustomAttributesData().Count == 0)
                                {
                                    os = 8;
                                }
                                else
                                {
                                    object[] attributes = info[i].GetCustomAttributes(typeof(BytesAttribute), false);
                                    os = (int)((BytesAttribute)attributes[0]).ByteLength;
                                }
                            }
                            else if (type.Name == "DateTime")
                            {
                                os = 8;
                            }
                            else if (type.Name == "Byte" && info[i].GetCustomAttributesData().Count != 0 && info[i].GetCustomAttributes(typeof(BitAttribute), false) != null)
                            {
                                // Check if it is bit.
                                BitAttribute attribute = (BitAttribute)info[i].GetCustomAttributes(typeof(BitAttribute), false)[0];

                                if (bitLength % 8 == 0)
                                {
                                    os += 1;
                                }
                                else
                                {
                                    current -= 1;
                                    os      += 1;
                                }

                                bitLength += attribute.BitLength;
                            }
                            else if (type.Name != "Boolean")
                            {
                                os = Marshal.SizeOf(fieldType);
                            }
                            else
                            {
                                os = sizeof(bool);
                            }

                            Position ps = new Position(current, os);
                            tn.Tag   = ps;
                            current += os;
                        }
                    }
                    else if ((type.IsEnum && Enum.IsDefined(typeof(DataType), type.GetEnumUnderlyingType().Name)) && info[i].GetValue(obj) != null)
                    {
                        // Else if the field data type is enum data type, its underlying type is simple type and its value is not null, calculate each field's offset
                        // and length. There are two situations: one is string type, we should calculate it's actual length (via getting value); another one is calculating
                        // the size of underlying type of enum.
                        Type fieldType = type;

                        TreeNode tn = new TreeNode(string.Format("{0}:{1}", info[i].Name, EnumToString(info[i].GetValue(obj))));
                        res.Nodes.Add(tn);

                        if (type.Name == "String")
                        {
                            os = ((string)info[i].GetValue(obj)).Length;
                        }
                        else if (info[i].GetCustomAttributesData().Count != 0 && info[i].GetCustomAttributes(typeof(BitAttribute), false) != null)
                        {
                            // Modify the bit OS for the NotificationFlagsT in MSOXCNOTIF
                            BitAttribute attribute = (BitAttribute)info[i].GetCustomAttributes(typeof(BitAttribute), false)[0];

                            if (bitLength % 8 != 0)
                            {
                                current -= 1;
                            }

                            if (attribute.BitLength % 8 == 0)
                            {
                                os += attribute.BitLength / 8;
                            }
                            else
                            {
                                os += (attribute.BitLength / 8) + 1;
                            }

                            bitLength += attribute.BitLength;
                        }
                        else
                        {
                            os = Marshal.SizeOf(fieldType.GetEnumUnderlyingType());
                        }

                        Position ps = new Position(current, os);
                        tn.Tag   = ps;
                        current += os;
                    }
                    else if (type.IsArray)
                    {
                        // If the field type is array, there are two properties need to know: optional or required, array element data type is simple or complex
                        // Field value considered: empty, null or value type displaying when not null/empty
                        // Getting the element type for required and optional array value
                        Type elementType = type.GetElementType();
                        if (!type.IsValueType && type.GetGenericArguments().Length > 0)
                        {
                            elementType = type.GetGenericArguments()[0];
                        }

                        // If the element type is simple data type, displaying the array in one line with string format.
                        if (Enum.IsDefined(typeof(DataType), elementType.Name))
                        {
                            Array arr = (Array)info[i].GetValue(obj);

                            if (arr != null && arr.Length != 0)
                            {
                                StringBuilder result = new StringBuilder();

                                // it the field is 6 bytes, updated the display text.
                                if (arr.Length == 6 && arr.GetType().ToString() == "System.Byte[]" && info[i].Name == "GlobalCounter")
                                {
                                    byte[] tempbytes = (byte[])info[i].GetValue(obj);
                                    result.Append("0x");

                                    foreach (byte tempbye in tempbytes)
                                    {
                                        result.Append(tempbye.ToString("X2"));
                                    }
                                }
                                else if (arr.GetType().ToString() == "System.Byte[]")
                                {
                                    result.Append(Utilities.ConvertArrayToHexString((byte[])arr));
                                }
                                else if (arr.GetType().ToString() == "System.Uint[]")
                                {
                                    result.Append(Utilities.ConvertArrayToHexString((uint[])arr));
                                }

                                TreeNode tn = new TreeNode(string.Format("{0}:{1}", info[i].Name, result.ToString()));
                                res.Nodes.Add(tn);

                                for (int j = 0; j < arr.Length; j++)
                                {
                                    os += Marshal.SizeOf(elementType);
                                }

                                Position ps = new Position(current, os);
                                tn.Tag   = ps;
                                current += os;
                            }
                        }
                        else
                        {
                            // Else if the element data type is not simple type, here will consider array type and complex type
                            Array    arr = (Array)info[i].GetValue(obj);
                            object[] a   = (object[])arr;

                            if (arr != null && arr.Length != 0)
                            {
                                string   fieldNameForAut = info[i].Name;
                                TreeNode treeNodeArray   = new TreeNode(info[i].Name);
                                TreeNode tn    = new TreeNode();
                                int      arros = 0;

                                if (fieldNameForAut == "RgbOutputBuffers" || fieldNameForAut == "buffers")
                                {
                                    compressBufferindex = 0;
                                }

                                for (int k = 0; k < arr.Length; k++)
                                {
                                    if (a[k] != null)
                                    {
                                        // If the item in array contains array (byte or other simple type), display the value in one line and set the offset and length.
                                        if (a[k].GetType().IsArray&& a[k].GetType().GetElementType().Name == "Byte")
                                        {
                                            StringBuilder result = new StringBuilder("[");
                                            Position      ps;

                                            foreach (var ar in (byte[])a[k])
                                            {
                                                result.Append(ar.ToString() + ",");
                                            }

                                            result.Remove(result.Length - 1, 1);
                                            result.Append("]");

                                            if (arr.Length == 1)
                                            {
                                                tn     = new TreeNode(string.Format("{0}:{1}", info[i].Name, result.ToString()));
                                                os     = ((byte[])a[k]).Length;
                                                ps     = new Position(current, os);
                                                tn.Tag = ps;
                                            }
                                            else
                                            {
                                                tn = new TreeNode(string.Format("{0}:{1}", info[i].Name, result.ToString()));
                                                treeNodeArray.Nodes.Add(tn);
                                                os     = ((byte[])a[k]).Length;
                                                ps     = new Position(current, os);
                                                tn.Tag = ps;
                                            }

                                            os = ((byte[])a[k]).Length;
                                            ps = new Position(current, os);
                                            treeNodeArray.Tag = ps;
                                        }
                                        else
                                        {
                                            // If the item in array is complex type, loop call the function to add it to tree.
                                            // compressBufferindex is used to recored the rgbOutputBuffer or ExtendedBuffer_Input number here
                                            if (a.GetType().Name == "RgbOutputBuffer[]" || a.GetType().Name == "ExtendedBuffer_Input[]")
                                            {
                                                compressBufferindex += 1;
                                            }

                                            tn = AddNodesForTree(a[k], current, out os);
                                            treeNodeArray.Nodes.Add(tn);
                                            Position ps = new Position(current, os);
                                            tn.Tag = ps;
                                        }
                                    }

                                    current += os;
                                    arros   += os;
                                }

                                Position pss = new Position(current - arros, arros);
                                treeNodeArray.Tag = pss;
                                res.Nodes.Add(treeNodeArray);
                            }
                        }
                    }
                    else
                    {
                        // If the field type is complex type, loop call the function until finding its data type.
                        if (info[i].GetValue(obj) != null)
                        {
                            string   fieldName = info[i].Name;
                            TreeNode node      = new TreeNode();

                            // The below logical is used to check whether the payload is compressed or XOR.
                            if (fieldName == "RPCHEADEREXT")
                            {
                                if (((ushort)((RPC_HEADER_EXT)info[i].GetValue(obj)).Flags & 0x0002) == (ushort)RpcHeaderFlags.XorMagic ||
                                    ((ushort)((RPC_HEADER_EXT)info[i].GetValue(obj)).Flags & 0x0001) == (ushort)RpcHeaderFlags.Compressed)
                                {
                                    IsCompressedXOR = true;
                                }
                                else
                                {
                                    IsCompressedXOR = false;
                                }
                            }

                            // If the field name is Payload and its compressed, recalculating the offset and length, else directly loop call this function
                            if (fieldName == "Payload" && IsCompressedXOR)
                            {
                                RPC_HEADER_EXT header = (RPC_HEADER_EXT)info[0].GetValue(obj);
                                node = AddNodesForTree(info[i].GetValue(obj), current, out os);
                                Position nodePosition = (Position)node.Tag;
                                nodePosition.Offset = header.Size;
                                os        = nodePosition.Offset;
                                node.Tag  = nodePosition;
                                fieldName = "Payload(CompressedOrObfuscated)";
                                node.Text = fieldName;
                                node      = TreeNodeForCompressed(node, current, compressBufferindex - 1);
                            }
                            else
                            {
                                if (fieldName == "Payload")
                                {
                                    // minus the Payload is not in compressed
                                    compressBufferindex -= 1;
                                }

                                node = AddNodesForTree(info[i].GetValue(obj), current, out os);
                                Position nodePosition = new Position(current, os);
                                node.Tag = nodePosition;
                            }

                            // Add the specific type(FastTransfer stream type) for TransferBuffer and TransferData fields.
                            if (fieldName == "TransferBuffer" || fieldName == "TransferData")
                            {
                                fieldName = string.Format(fieldName + ": " + info[i].GetValue(obj).GetType().Name);
                            }

                            node.Text = fieldName;
                            res.Nodes.Add(node);
                            current += os;
                        }
                    }
                }
            }

            offset = current - startIndex;
            Position position = new Position(startIndex, offset);

            res.Tag = position;

            return(res);
        }
        /// <summary>
        /// Composes rgbAuxIn buffer
        /// </summary>
        /// <param name="rgbAuxIn">Enum value of rgbAuxIn</param>
        /// <param name="rgbAuxInPayload">The payload of rgbAuxIn buffer.</param>
        /// <returns>Returns a buffer composed according to the parameters</returns>
        public static byte[] ComposeRgbAuxIn(RgbAuxInEnum rgbAuxIn, byte[] rgbAuxInPayload)
        {
            byte         version;
            byte         type;
            const string ErrorMessage = "This input structure name is not a valid AUX structure type";

            // Version set to 0x01 means the Version field of AUX_HEADER is AUX_VERSION_1
            // Version set to 0x02 means the Version field of AUX_HEADER is AUX_VERSION_2
            switch (rgbAuxIn)
            {
            case RgbAuxInEnum.AUX_PERF_SESSIONINFO:
                version = (byte)AuxVersions.AUX_VERSION_1;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_SESSIONINFO;
                break;

            case RgbAuxInEnum.AUX_PERF_SESSIONINFO_V2:
                version = (byte)AuxVersions.AUX_VERSION_2;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_SESSIONINFO;
                break;

            case RgbAuxInEnum.AUX_PERF_CLIENTINFO:
                version = (byte)AuxVersions.AUX_VERSION_1;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_CLIENTINFO;
                break;

            case RgbAuxInEnum.AUX_PERF_PROCESSINFO:
                version = (byte)AuxVersions.AUX_VERSION_2;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_PROCESSINFO;
                break;

            case RgbAuxInEnum.AUX_PERF_DEFMDB_SUCCESS:
                version = (byte)AuxVersions.AUX_VERSION_1;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_BG_DEFMDB_SUCCESS;
                break;

            case RgbAuxInEnum.AUX_PERF_DEFGC_SUCCESS:
                version = (byte)AuxVersions.AUX_VERSION_1;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_BG_DEFGC_SUCCESS;
                break;

            case RgbAuxInEnum.AUX_PERF_MDB_SUCCESS_V2:
                version = (byte)AuxVersions.AUX_VERSION_2;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_MDB_SUCCESS;
                break;

            case RgbAuxInEnum.AUX_PERF_GC_SUCCESS:
                version = (byte)AuxVersions.AUX_VERSION_1;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_BG_GC_SUCCESS;
                break;

            case RgbAuxInEnum.AUX_PERF_GC_SUCCESS_V2:
                version = (byte)AuxVersions.AUX_VERSION_2;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_BG_GC_SUCCESS;
                break;

            case RgbAuxInEnum.AUX_PERF_FAILURE:
                version = (byte)AuxVersions.AUX_VERSION_1;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_BG_FAILURE;
                break;

            case RgbAuxInEnum.AUX_PERF_FAILURE_V2:
                version = (byte)AuxVersions.AUX_VERSION_2;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_BG_FAILURE;
                break;

            case RgbAuxInEnum.AUX_PERF_ACCOUNTINFO:
                version = (byte)AuxVersions.AUX_VERSION_1;
                type    = (byte)AuxTypes.AUX_TYPE_PERF_ACCOUNTINFO;
                break;

            case RgbAuxInEnum.AUX_CLIENT_CONNECTION_INFO:
                version = (byte)AuxVersions.AUX_VERSION_1;
                type    = (byte)AuxTypes.AUX_CLIENT_CONNECTION_INFO;
                break;

            default:
                throw new NotImplementedException(ErrorMessage);
            }

            RPC_HEADER_EXT rpcHeaderExt = new RPC_HEADER_EXT
            {
                Version = 0x0000,                                                          // This value MUST be set to 0x0000.
                Flags   = (ushort)RpcHeaderExtFlags.Last,                                  // No Compression and no obfuscation
                Size    = (ushort)(rgbAuxInPayload.Length + ConstValues.AuxHeaderByteSize) // The total length of the payload data that follows the RPC_HEADER_EXT structure.
            };

            // The length of the payload data after it has been uncompressed.
            rpcHeaderExt.SizeActual = rpcHeaderExt.Size;

            // The length of AuxHeader is the length of AUX_HEADER structure plus the length of any additional payload data.
            AUX_HEADER auxHeader = new AUX_HEADER
            {
                Size    = (ushort)(rgbAuxInPayload.Length + ConstValues.AuxHeaderByteSize),
                Version = version,
                Type    = type
            };
            int returnSize = rgbAuxInPayload.Length + Marshal.SizeOf(rpcHeaderExt) + Marshal.SizeOf(auxHeader);

            byte[] returnByte = new byte[returnSize];

            // RgbAuxIn serialization
            // Serializes the RPC_HEADER_EXT
            int index = 0;

            Array.Copy(BitConverter.GetBytes(rpcHeaderExt.Version), 0, returnByte, index, sizeof(short));
            index += sizeof(short);
            Array.Copy(BitConverter.GetBytes(rpcHeaderExt.Flags), 0, returnByte, index, sizeof(short));
            index += sizeof(short);
            Array.Copy(BitConverter.GetBytes(rpcHeaderExt.Size), 0, returnByte, index, sizeof(short));
            index += sizeof(short);
            Array.Copy(BitConverter.GetBytes(rpcHeaderExt.SizeActual), 0, returnByte, index, sizeof(short));
            index += sizeof(short);

            // Serializes the AUX_HEADER
            Array.Copy(BitConverter.GetBytes(auxHeader.Size), 0, returnByte, index, sizeof(ushort));
            index            += sizeof(ushort);
            returnByte[index] = auxHeader.Version;
            index++;
            returnByte[index] = auxHeader.Type;
            index++;

            Array.Copy(rgbAuxInPayload, 0, returnByte, index, rgbAuxInPayload.Length);

            return(returnByte);
        }
Exemple #6
0
        /// <summary>
        /// The method creates ROPs request.
        /// </summary>
        /// <param name="requestROPs">ROPs in request.</param>
        /// <param name="requestSOHTable">Server object handles table.</param>
        /// <returns>The ROPs request.</returns>
        private byte[] BuildRequestBuffer(List <ISerializable> requestROPs, List <uint> requestSOHTable)
        {
            // Definition for PayloadLen which indicates the length of the field that represents the length of payload.
            int payloadLen = PayloadLen;

            if (requestROPs != null)
            {
                foreach (ISerializable requestROP in requestROPs)
                {
                    payloadLen += requestROP.Size();
                }
            }

            Site.Assert.IsTrue(
                payloadLen < ushort.MaxValue,
                "The number of bytes in this field MUST be 2 bytes less than the value specified in the RopSize field.");

            ushort ropSize = (ushort)payloadLen;

            if (requestSOHTable != null)
            {
                payloadLen += requestSOHTable.Count * sizeof(uint);
            }

            byte[] requestBuffer = new byte[RPCHEADEREXTLEN + payloadLen];
            int    index         = 0;

            // Construct RPC header extension buffer
            RPC_HEADER_EXT rpcHeaderExt = new RPC_HEADER_EXT
            {
                Version = VersionOfRpcHeaderExt, // There is only one version of the header at this time so this value MUST be set to 0x00.
                Flags   = LastForFlagsOfHeader,  // Last (0x04) indicates that no other RPC_HEADER_EXT follows the data of the current RPC_HEADER_EXT.
                Size    = (ushort)payloadLen
            };

            rpcHeaderExt.SizeActual = rpcHeaderExt.Size;

            IntPtr ptr = Marshal.AllocHGlobal(RPCHEADEREXTLEN);

            try
            {
                Marshal.StructureToPtr(rpcHeaderExt, ptr, true);
                Marshal.Copy(ptr, requestBuffer, index, RPCHEADEREXTLEN);
                index += RPCHEADEREXTLEN;
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }

            // RopSize's type is ushort. So the offset will be 2.
            Array.Copy(BitConverter.GetBytes(ropSize), 0, requestBuffer, index, 2);
            index += 2;

            if (requestROPs != null)
            {
                foreach (ISerializable requestROP in requestROPs)
                {
                    Array.Copy(requestROP.Serialize(), 0, requestBuffer, index, requestROP.Size());
                    index += requestROP.Size();
                }
            }

            if (requestSOHTable != null)
            {
                foreach (uint serverHandle in requestSOHTable)
                {
                    Array.Copy(BitConverter.GetBytes(serverHandle), 0, requestBuffer, index, sizeof(uint));
                    index += sizeof(uint);
                }
            }

            return(requestBuffer);
        }