/// <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); }
/// <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); }