public static byte[] DecompressStream(byte[] inputStream)
{
#region Consts
// Size of Version field in RPC_HEADER_EXT
const int RpcHeaderExtVersionByteSize = 2;
// Size of Flags field in RPC_HEADER_EXT
const int RpcHeaderExtFlagsByteSize = 2;
// Size of Size field in RPC_HEADER_EXT
const int RpcHeaderExtSizeByteSize = 2;
// Size of SizeActual field in RPC_HEADER_EXT
const int RpcHeaderExtSizeActualByteSize = 2;
// The length of RPC_HEADER_EXT.
const int RPCHeaderExtLength = 8;
#endregion
if (inputStream == null)
{
throw new ArgumentNullException("inputStream");
}
if (inputStream.Length < RPCHeaderExtLength)
{
throw new ArgumentException("Input must contain valid RPC_HEADER_EXT.", "inputStream");
}
// The third and fourth byte represents Flags field in RPC_HEADER_EXT
RpcHeaderExtFlags flag = (RpcHeaderExtFlags)BitConverter.ToInt16(inputStream, RpcHeaderExtVersionByteSize);
if ((flag & RpcHeaderExtFlags.Compressed) == RpcHeaderExtFlags.None)
{
// Data is not compressed, no need to decompress
return inputStream;
}
ushort compressedSize = BitConverter.ToUInt16(inputStream, RpcHeaderExtVersionByteSize + RpcHeaderExtFlagsByteSize);
ushort actualSize = BitConverter.ToUInt16(inputStream, RpcHeaderExtVersionByteSize + RpcHeaderExtFlagsByteSize + RpcHeaderExtSizeByteSize);
// Decompress payload
byte[] originalPayload = new byte[compressedSize];
Array.Copy(inputStream, RPCHeaderExtLength, originalPayload, 0, compressedSize);
byte[] decompressedPayload = LZ77Decompress(originalPayload, actualSize);
byte[] outStream = new byte[RPCHeaderExtLength + actualSize];
Array.Copy(inputStream, 0, outStream, 0, RPCHeaderExtLength);
Array.Copy(decompressedPayload, 0, outStream, RPCHeaderExtLength, actualSize);
// Change Flag field to uncompressed
flag &= ~RpcHeaderExtFlags.Compressed;
Array.Copy(BitConverter.GetBytes((short)flag), 0, outStream, RpcHeaderExtVersionByteSize, RpcHeaderExtFlagsByteSize);
// Set Size value to ActualSize value.
Array.Copy(outStream, RpcHeaderExtVersionByteSize + RpcHeaderExtFlagsByteSize + RpcHeaderExtSizeActualByteSize, outStream, RpcHeaderExtVersionByteSize + RpcHeaderExtFlagsByteSize, RpcHeaderExtSizeByteSize);
return outStream;
}