Blame libfreerdp/codec/mppc.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * MPPC Bulk Data Compression
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
#include <winpr/print.h>
Packit Service fa4841
#include <winpr/stream.h>
Packit Service fa4841
#include <winpr/bitstream.h>
Packit Service fa4841
Packit Service fa4841
#include <freerdp/log.h>
Packit Service fa4841
#include <freerdp/codec/mppc.h>
Packit Service fa4841
Packit Service fa4841
#define TAG FREERDP_TAG("codec.mppc")
Packit Service fa4841
Packit Service bb5c11
#define MPPC_MATCH_INDEX(_sym1, _sym2, _sym3) \
Packit Service bb5c11
	((((MPPC_MATCH_TABLE[_sym3] << 16) + (MPPC_MATCH_TABLE[_sym2] << 8) + MPPC_MATCH_TABLE[_sym1]) & 0x07FFF000) >> 12)
Packit Service fa4841
Packit Service bb5c11
static const UINT32 MPPC_MATCH_TABLE[256] =
Packit Service fa4841
{
Packit Service fa4841
	0x00000000, 0x009CCF93, 0x01399F26, 0x01D66EB9, 0x02733E4C, 0x03100DDF, 0x03ACDD72, 0x0449AD05,
Packit Service fa4841
	0x04E67C98, 0x05834C2B, 0x06201BBE, 0x06BCEB51, 0x0759BAE4, 0x07F68A77, 0x08935A0A, 0x0930299D,
Packit Service fa4841
	0x09CCF930, 0x0A69C8C3, 0x0B069856, 0x0BA367E9, 0x0C40377C, 0x0CDD070F, 0x0D79D6A2, 0x0E16A635,
Packit Service fa4841
	0x0EB375C8, 0x0F50455B, 0x0FED14EE, 0x1089E481, 0x1126B414, 0x11C383A7, 0x1260533A, 0x12FD22CD,
Packit Service fa4841
	0x1399F260, 0x1436C1F3, 0x14D39186, 0x15706119, 0x160D30AC, 0x16AA003F, 0x1746CFD2, 0x17E39F65,
Packit Service fa4841
	0x18806EF8, 0x191D3E8B, 0x19BA0E1E, 0x1A56DDB1, 0x1AF3AD44, 0x1B907CD7, 0x1C2D4C6A, 0x1CCA1BFD,
Packit Service fa4841
	0x1D66EB90, 0x1E03BB23, 0x1EA08AB6, 0x1F3D5A49, 0x1FDA29DC, 0x2076F96F, 0x2113C902, 0x21B09895,
Packit Service fa4841
	0x224D6828, 0x22EA37BB, 0x2387074E, 0x2423D6E1, 0x24C0A674, 0x255D7607, 0x25FA459A, 0x2697152D,
Packit Service fa4841
	0x2733E4C0, 0x27D0B453, 0x286D83E6, 0x290A5379, 0x29A7230C, 0x2A43F29F, 0x2AE0C232, 0x2B7D91C5,
Packit Service fa4841
	0x2C1A6158, 0x2CB730EB, 0x2D54007E, 0x2DF0D011, 0x2E8D9FA4, 0x2F2A6F37, 0x2FC73ECA, 0x30640E5D,
Packit Service fa4841
	0x3100DDF0, 0x319DAD83, 0x323A7D16, 0x32D74CA9, 0x33741C3C, 0x3410EBCF, 0x34ADBB62, 0x354A8AF5,
Packit Service fa4841
	0x35E75A88, 0x36842A1B, 0x3720F9AE, 0x37BDC941, 0x385A98D4, 0x38F76867, 0x399437FA, 0x3A31078D,
Packit Service fa4841
	0x3ACDD720, 0x3B6AA6B3, 0x3C077646, 0x3CA445D9, 0x3D41156C, 0x3DDDE4FF, 0x3E7AB492, 0x3F178425,
Packit Service fa4841
	0x3FB453B8, 0x4051234B, 0x40EDF2DE, 0x418AC271, 0x42279204, 0x42C46197, 0x4361312A, 0x43FE00BD,
Packit Service fa4841
	0x449AD050, 0x45379FE3, 0x45D46F76, 0x46713F09, 0x470E0E9C, 0x47AADE2F, 0x4847ADC2, 0x48E47D55,
Packit Service fa4841
	0x49814CE8, 0x4A1E1C7B, 0x4ABAEC0E, 0x4B57BBA1, 0x4BF48B34, 0x4C915AC7, 0x4D2E2A5A, 0x4DCAF9ED,
Packit Service fa4841
	0x4E67C980, 0x4F049913, 0x4FA168A6, 0x503E3839, 0x50DB07CC, 0x5177D75F, 0x5214A6F2, 0x52B17685,
Packit Service fa4841
	0x534E4618, 0x53EB15AB, 0x5487E53E, 0x5524B4D1, 0x55C18464, 0x565E53F7, 0x56FB238A, 0x5797F31D,
Packit Service fa4841
	0x5834C2B0, 0x58D19243, 0x596E61D6, 0x5A0B3169, 0x5AA800FC, 0x5B44D08F, 0x5BE1A022, 0x5C7E6FB5,
Packit Service fa4841
	0x5D1B3F48, 0x5DB80EDB, 0x5E54DE6E, 0x5EF1AE01, 0x5F8E7D94, 0x602B4D27, 0x60C81CBA, 0x6164EC4D,
Packit Service fa4841
	0x6201BBE0, 0x629E8B73, 0x633B5B06, 0x63D82A99, 0x6474FA2C, 0x6511C9BF, 0x65AE9952, 0x664B68E5,
Packit Service fa4841
	0x66E83878, 0x6785080B, 0x6821D79E, 0x68BEA731, 0x695B76C4, 0x69F84657, 0x6A9515EA, 0x6B31E57D,
Packit Service fa4841
	0x6BCEB510, 0x6C6B84A3, 0x6D085436, 0x6DA523C9, 0x6E41F35C, 0x6EDEC2EF, 0x6F7B9282, 0x70186215,
Packit Service fa4841
	0x70B531A8, 0x7152013B, 0x71EED0CE, 0x728BA061, 0x73286FF4, 0x73C53F87, 0x74620F1A, 0x74FEDEAD,
Packit Service fa4841
	0x759BAE40, 0x76387DD3, 0x76D54D66, 0x77721CF9, 0x780EEC8C, 0x78ABBC1F, 0x79488BB2, 0x79E55B45,
Packit Service fa4841
	0x7A822AD8, 0x7B1EFA6B, 0x7BBBC9FE, 0x7C589991, 0x7CF56924, 0x7D9238B7, 0x7E2F084A, 0x7ECBD7DD,
Packit Service fa4841
	0x7F68A770, 0x80057703, 0x80A24696, 0x813F1629, 0x81DBE5BC, 0x8278B54F, 0x831584E2, 0x83B25475,
Packit Service fa4841
	0x844F2408, 0x84EBF39B, 0x8588C32E, 0x862592C1, 0x86C26254, 0x875F31E7, 0x87FC017A, 0x8898D10D,
Packit Service fa4841
	0x8935A0A0, 0x89D27033, 0x8A6F3FC6, 0x8B0C0F59, 0x8BA8DEEC, 0x8C45AE7F, 0x8CE27E12, 0x8D7F4DA5,
Packit Service fa4841
	0x8E1C1D38, 0x8EB8ECCB, 0x8F55BC5E, 0x8FF28BF1, 0x908F5B84, 0x912C2B17, 0x91C8FAAA, 0x9265CA3D,
Packit Service fa4841
	0x930299D0, 0x939F6963, 0x943C38F6, 0x94D90889, 0x9575D81C, 0x9612A7AF, 0x96AF7742, 0x974C46D5,
Packit Service fa4841
	0x97E91668, 0x9885E5FB, 0x9922B58E, 0x99BF8521, 0x9A5C54B4, 0x9AF92447, 0x9B95F3DA, 0x9C32C36D
Packit Service fa4841
};
Packit Service fa4841
Packit Service fa4841
//#define DEBUG_MPPC	1
Packit Service fa4841
Packit Service fa4841
int mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData,
Packit Service fa4841
                    UINT32* pDstSize, UINT32 flags)
Packit Service fa4841
{
Packit Service fa4841
	BYTE Literal;
Packit Service fa4841
	BYTE* SrcPtr;
Packit Service fa4841
	UINT32 CopyOffset;
Packit Service fa4841
	UINT32 LengthOfMatch;
Packit Service fa4841
	UINT32 accumulator;
Packit Service fa4841
	BYTE* HistoryPtr;
Packit Service fa4841
	BYTE* HistoryBuffer;
Packit Service fa4841
	BYTE* HistoryBufferEnd;
Packit Service fa4841
	UINT32 HistoryBufferSize;
Packit Service fa4841
	UINT32 CompressionLevel;
Packit Service fa4841
	wBitStream* bs = mppc->bs;
Packit Service fa4841
	HistoryBuffer = mppc->HistoryBuffer;
Packit Service fa4841
	HistoryBufferSize = mppc->HistoryBufferSize;
Packit Service fa4841
	HistoryBufferEnd = &HistoryBuffer[HistoryBufferSize - 1];
Packit Service fa4841
	CompressionLevel = mppc->CompressionLevel;
Packit Service fa4841
	BitStream_Attach(bs, pSrcData, SrcSize);
Packit Service fa4841
	BitStream_Fetch(bs);
Packit Service fa4841
Packit Service fa4841
	if (flags & PACKET_AT_FRONT)
Packit Service fa4841
	{
Packit Service fa4841
		mppc->HistoryOffset = 0;
Packit Service fa4841
		mppc->HistoryPtr = HistoryBuffer;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (flags & PACKET_FLUSHED)
Packit Service fa4841
	{
Packit Service fa4841
		mppc->HistoryOffset = 0;
Packit Service fa4841
		mppc->HistoryPtr = HistoryBuffer;
Packit Service fa4841
		ZeroMemory(HistoryBuffer, mppc->HistoryBufferSize);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	HistoryPtr = mppc->HistoryPtr;
Packit Service fa4841
Packit Service fa4841
	if (!(flags & PACKET_COMPRESSED))
Packit Service fa4841
	{
Packit Service fa4841
		*pDstSize = SrcSize;
Packit Service fa4841
		*ppDstData = pSrcData;
Packit Service fa4841
		return 1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	while ((bs->length - bs->position) >= 8)
Packit Service fa4841
	{
Packit Service fa4841
		accumulator = bs->accumulator;
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Literal Encoding
Packit Service fa4841
		 */
Packit Service fa4841
Packit Service fa4841
		if (HistoryPtr > HistoryBufferEnd)
Packit Service fa4841
		{
Packit Service bb5c11
			WLog_ERR(TAG,  "history buffer index out of range");
Packit Service fa4841
			return -1004;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if ((accumulator & 0x80000000) == 0x00000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * Literal, less than 0x80
Packit Service fa4841
			 * bit 0 followed by the lower 7 bits of the literal
Packit Service fa4841
			 */
Packit Service fa4841
			Literal = ((accumulator & 0x7F000000) >> 24);
Packit Service fa4841
			*(HistoryPtr) = Literal;
Packit Service fa4841
			HistoryPtr++;
Packit Service fa4841
			BitStream_Shift(bs, 8);
Packit Service fa4841
			continue;
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xC0000000) == 0x80000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * Literal, greater than 0x7F
Packit Service fa4841
			 * bits 10 followed by the lower 7 bits of the literal
Packit Service fa4841
			 */
Packit Service fa4841
			Literal = ((accumulator & 0x3F800000) >> 23) + 0x80;
Packit Service fa4841
			*(HistoryPtr) = Literal;
Packit Service fa4841
			HistoryPtr++;
Packit Service fa4841
			BitStream_Shift(bs, 9);
Packit Service fa4841
			continue;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * CopyOffset Encoding
Packit Service fa4841
		 */
Packit Service fa4841
		if (CompressionLevel) /* RDP5 */
Packit Service fa4841
		{
Packit Service fa4841
			if ((accumulator & 0xF8000000) == 0xF8000000)
Packit Service fa4841
			{
Packit Service fa4841
				/**
Packit Service fa4841
				 * CopyOffset, range [0, 63]
Packit Service fa4841
				 * bits 11111 + lower 6 bits of CopyOffset
Packit Service fa4841
				 */
Packit Service fa4841
				CopyOffset = ((accumulator >> 21) & 0x3F);
Packit Service fa4841
				BitStream_Shift(bs, 11);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((accumulator & 0xF8000000) == 0xF0000000)
Packit Service fa4841
			{
Packit Service fa4841
				/**
Packit Service fa4841
				 * CopyOffset, range [64, 319]
Packit Service fa4841
				 * bits 11110 + lower 8 bits of (CopyOffset - 64)
Packit Service fa4841
				 */
Packit Service fa4841
				CopyOffset = ((accumulator >> 19) & 0xFF) + 64;
Packit Service fa4841
				BitStream_Shift(bs, 13);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((accumulator & 0xF0000000) == 0xE0000000)
Packit Service fa4841
			{
Packit Service fa4841
				/**
Packit Service fa4841
				 * CopyOffset, range [320, 2367]
Packit Service fa4841
				 * bits 1110 + lower 11 bits of (CopyOffset - 320)
Packit Service fa4841
				 */
Packit Service fa4841
				CopyOffset = ((accumulator >> 17) & 0x7FF) + 320;
Packit Service fa4841
				BitStream_Shift(bs, 15);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((accumulator & 0xE0000000) == 0xC0000000)
Packit Service fa4841
			{
Packit Service fa4841
				/**
Packit Service fa4841
				 * CopyOffset, range [2368, ]
Packit Service fa4841
				 * bits 110 + lower 16 bits of (CopyOffset - 2368)
Packit Service fa4841
				 */
Packit Service fa4841
				CopyOffset = ((accumulator >> 13) & 0xFFFF) + 2368;
Packit Service fa4841
				BitStream_Shift(bs, 19);
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				/* Invalid CopyOffset Encoding */
Packit Service fa4841
				return -1001;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else /* RDP4 */
Packit Service fa4841
		{
Packit Service fa4841
			if ((accumulator & 0xF0000000) == 0xF0000000)
Packit Service fa4841
			{
Packit Service fa4841
				/**
Packit Service fa4841
				 * CopyOffset, range [0, 63]
Packit Service fa4841
				 * bits 1111 + lower 6 bits of CopyOffset
Packit Service fa4841
				 */
Packit Service fa4841
				CopyOffset = ((accumulator >> 22) & 0x3F);
Packit Service fa4841
				BitStream_Shift(bs, 10);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((accumulator & 0xF0000000) == 0xE0000000)
Packit Service fa4841
			{
Packit Service fa4841
				/**
Packit Service fa4841
				 * CopyOffset, range [64, 319]
Packit Service fa4841
				 * bits 1110 + lower 8 bits of (CopyOffset - 64)
Packit Service fa4841
				 */
Packit Service fa4841
				CopyOffset = ((accumulator >> 20) & 0xFF) + 64;
Packit Service fa4841
				BitStream_Shift(bs, 12);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((accumulator & 0xE0000000) == 0xC0000000)
Packit Service fa4841
			{
Packit Service fa4841
				/**
Packit Service fa4841
				 * CopyOffset, range [320, 8191]
Packit Service fa4841
				 * bits 110 + lower 13 bits of (CopyOffset - 320)
Packit Service fa4841
				 */
Packit Service fa4841
				CopyOffset = ((accumulator >> 16) & 0x1FFF) + 320;
Packit Service fa4841
				BitStream_Shift(bs, 16);
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				/* Invalid CopyOffset Encoding */
Packit Service fa4841
				return -1002;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * LengthOfMatch Encoding
Packit Service fa4841
		 */
Packit Service fa4841
		accumulator = bs->accumulator;
Packit Service fa4841
Packit Service fa4841
		if ((accumulator & 0x80000000) == 0x00000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [3]
Packit Service fa4841
			 * bit 0 + 0 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = 3;
Packit Service fa4841
			BitStream_Shift(bs, 1);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xC0000000) == 0x80000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [4, 7]
Packit Service fa4841
			 * bits 10 + 2 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 28) & 0x0003) + 0x0004;
Packit Service fa4841
			BitStream_Shift(bs, 4);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xE0000000) == 0xC0000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [8, 15]
Packit Service fa4841
			 * bits 110 + 3 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 26) & 0x0007) + 0x0008;
Packit Service fa4841
			BitStream_Shift(bs, 6);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xF0000000) == 0xE0000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [16, 31]
Packit Service fa4841
			 * bits 1110 + 4 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 24) & 0x000F) + 0x0010;
Packit Service fa4841
			BitStream_Shift(bs, 8);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xF8000000) == 0xF0000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [32, 63]
Packit Service fa4841
			 * bits 11110 + 5 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 22) & 0x001F) + 0x0020;
Packit Service fa4841
			BitStream_Shift(bs, 10);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xFC000000) == 0xF8000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [64, 127]
Packit Service fa4841
			 * bits 111110 + 6 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 20) & 0x003F) + 0x0040;
Packit Service fa4841
			BitStream_Shift(bs, 12);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xFE000000) == 0xFC000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [128, 255]
Packit Service fa4841
			 * bits 1111110 + 7 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 18) & 0x007F) + 0x0080;
Packit Service fa4841
			BitStream_Shift(bs, 14);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xFF000000) == 0xFE000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [256, 511]
Packit Service fa4841
			 * bits 11111110 + 8 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 16) & 0x00FF) + 0x0100;
Packit Service fa4841
			BitStream_Shift(bs, 16);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xFF800000) == 0xFF000000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [512, 1023]
Packit Service fa4841
			 * bits 111111110 + 9 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 14) & 0x01FF) + 0x0200;
Packit Service fa4841
			BitStream_Shift(bs, 18);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xFFC00000) == 0xFF800000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [1024, 2047]
Packit Service fa4841
			 * bits 1111111110 + 10 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 12) & 0x03FF) + 0x0400;
Packit Service fa4841
			BitStream_Shift(bs, 20);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xFFE00000) == 0xFFC00000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [2048, 4095]
Packit Service fa4841
			 * bits 11111111110 + 11 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 10) & 0x07FF) + 0x0800;
Packit Service fa4841
			BitStream_Shift(bs, 22);
Packit Service fa4841
		}
Packit Service fa4841
		else if ((accumulator & 0xFFF00000) == 0xFFE00000)
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [4096, 8191]
Packit Service fa4841
			 * bits 111111111110 + 12 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 8) & 0x0FFF) + 0x1000;
Packit Service fa4841
			BitStream_Shift(bs, 24);
Packit Service fa4841
		}
Packit Service fa4841
		else if (((accumulator & 0xFFF80000) == 0xFFF00000) && CompressionLevel) /* RDP5 */
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [8192, 16383]
Packit Service fa4841
			 * bits 1111111111110 + 13 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 6) & 0x1FFF) + 0x2000;
Packit Service fa4841
			BitStream_Shift(bs, 26);
Packit Service fa4841
		}
Packit Service fa4841
		else if (((accumulator & 0xFFFC0000) == 0xFFF80000) && CompressionLevel) /* RDP5 */
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [16384, 32767]
Packit Service fa4841
			 * bits 11111111111110 + 14 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 4) & 0x3FFF) + 0x4000;
Packit Service fa4841
			BitStream_Shift(bs, 28);
Packit Service fa4841
		}
Packit Service fa4841
		else if (((accumulator & 0xFFFE0000) == 0xFFFC0000) && CompressionLevel) /* RDP5 */
Packit Service fa4841
		{
Packit Service fa4841
			/**
Packit Service fa4841
			 * LengthOfMatch [32768, 65535]
Packit Service fa4841
			 * bits 111111111111110 + 15 lower bits of LengthOfMatch
Packit Service fa4841
			 */
Packit Service fa4841
			LengthOfMatch = ((accumulator >> 2) & 0x7FFF) + 0x8000;
Packit Service fa4841
			BitStream_Shift(bs, 30);
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			/* Invalid LengthOfMatch Encoding */
Packit Service fa4841
			return -1003;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
#ifdef DEBUG_MPPC
Packit Service bb5c11
		WLog_DBG(TAG, "<%"PRIu32",%"PRIu32">", CopyOffset, LengthOfMatch);
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
		if ((HistoryPtr + LengthOfMatch - 1) > HistoryBufferEnd)
Packit Service fa4841
		{
Packit Service bb5c11
			WLog_ERR(TAG,  "history buffer overflow");
Packit Service fa4841
			return -1005;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service bb5c11
		SrcPtr = &HistoryBuffer[(HistoryPtr - HistoryBuffer - CopyOffset) & (CompressionLevel ? 0xFFFF :
Packit Service bb5c11
		                        0x1FFF)];
Packit Service fa4841
Packit Service fa4841
		do
Packit Service fa4841
		{
Packit Service fa4841
			*HistoryPtr++ = *SrcPtr++;
Packit Service bb5c11
		}
Packit Service bb5c11
		while (--LengthOfMatch);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	*pDstSize = (UINT32)(HistoryPtr - mppc->HistoryPtr);
Packit Service fa4841
	*ppDstData = mppc->HistoryPtr;
Packit Service fa4841
	mppc->HistoryPtr = HistoryPtr;
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData,
Packit Service fa4841
                  UINT32* pDstSize, UINT32* pFlags)
Packit Service fa4841
{
Packit Service fa4841
	BYTE* pSrcPtr;
Packit Service fa4841
	BYTE* pSrcEnd;
Packit Service fa4841
	BYTE* MatchPtr;
Packit Service fa4841
	UINT32 DstSize;
Packit Service fa4841
	BYTE* pDstData;
Packit Service fa4841
	UINT32 MatchIndex;
Packit Service fa4841
	UINT32 accumulator;
Packit Service fa4841
	BOOL PacketFlushed;
Packit Service fa4841
	BOOL PacketAtFront;
Packit Service fa4841
	DWORD CopyOffset;
Packit Service fa4841
	DWORD LengthOfMatch;
Packit Service fa4841
	BYTE* HistoryBuffer;
Packit Service fa4841
	BYTE* HistoryPtr;
Packit Service fa4841
	UINT32 HistoryOffset;
Packit Service fa4841
	UINT32 HistoryBufferSize;
Packit Service fa4841
	BYTE Sym1, Sym2, Sym3;
Packit Service fa4841
	UINT32 CompressionLevel;
Packit Service fa4841
	wBitStream* bs = mppc->bs;
Packit Service fa4841
	HistoryBuffer = mppc->HistoryBuffer;
Packit Service fa4841
	HistoryBufferSize = mppc->HistoryBufferSize;
Packit Service fa4841
	CompressionLevel = mppc->CompressionLevel;
Packit Service fa4841
	HistoryOffset = mppc->HistoryOffset;
Packit Service fa4841
	*pFlags = 0;
Packit Service fa4841
	PacketFlushed = FALSE;
Packit Service fa4841
Packit Service fa4841
	if (((HistoryOffset + SrcSize) < (HistoryBufferSize - 3)) && HistoryOffset)
Packit Service fa4841
	{
Packit Service fa4841
		PacketAtFront = FALSE;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		if (HistoryOffset == (HistoryBufferSize + 1))
Packit Service fa4841
			PacketFlushed = TRUE;
Packit Service fa4841
Packit Service fa4841
		HistoryOffset = 0;
Packit Service fa4841
		PacketAtFront = TRUE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	HistoryPtr = &(HistoryBuffer[HistoryOffset]);
Packit Service fa4841
	pDstData = *ppDstData;
Packit Service fa4841
Packit Service fa4841
	if (!pDstData)
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service fa4841
	if (*pDstSize > SrcSize)
Packit Service fa4841
		DstSize = SrcSize;
Packit Service fa4841
	else
Packit Service fa4841
		DstSize = *pDstSize;
Packit Service fa4841
Packit Service fa4841
	BitStream_Attach(bs, pDstData, DstSize);
Packit Service fa4841
	pSrcPtr = pSrcData;
Packit Service fa4841
	pSrcEnd = &(pSrcData[SrcSize - 1]);
Packit Service fa4841
Packit Service fa4841
	while (pSrcPtr < (pSrcEnd - 2))
Packit Service fa4841
	{
Packit Service fa4841
		Sym1 = pSrcPtr[0];
Packit Service fa4841
		Sym2 = pSrcPtr[1];
Packit Service fa4841
		Sym3 = pSrcPtr[2];
Packit Service fa4841
		*HistoryPtr++ = *pSrcPtr++;
Packit Service fa4841
		MatchIndex = MPPC_MATCH_INDEX(Sym1, Sym2, Sym3);
Packit Service fa4841
		MatchPtr = &(HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
Packit Service fa4841
Packit Service fa4841
		if (MatchPtr != (HistoryPtr - 1))
Packit Service fa4841
			mppc->MatchBuffer[MatchIndex] = (UINT16)(HistoryPtr - HistoryBuffer);
Packit Service fa4841
Packit Service fa4841
		if (mppc->HistoryPtr < HistoryPtr)
Packit Service fa4841
			mppc->HistoryPtr = HistoryPtr;
Packit Service fa4841
Packit Service fa4841
		if ((Sym1 != *(MatchPtr - 1)) || (Sym2 != MatchPtr[0]) || (Sym3 != MatchPtr[1]) ||
Packit Service fa4841
		    (&MatchPtr[1] > mppc->HistoryPtr) || (MatchPtr == HistoryBuffer) ||
Packit Service fa4841
		    (MatchPtr == (HistoryPtr - 1)) || (MatchPtr == HistoryPtr))
Packit Service fa4841
		{
Packit Service fa4841
			if (((bs->position / 8) + 2) > (DstSize - 1))
Packit Service fa4841
			{
Packit Service fa4841
				mppc_context_reset(mppc, TRUE);
Packit Service fa4841
				*pFlags |= PACKET_FLUSHED;
Packit Service fa4841
				*pFlags |= CompressionLevel;
Packit Service fa4841
				*ppDstData = pSrcData;
Packit Service fa4841
				*pDstSize = SrcSize;
Packit Service fa4841
				return 1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			accumulator = Sym1;
Packit Service fa4841
#ifdef DEBUG_MPPC
Packit Service bb5c11
			WLog_DBG(TAG, "%"PRIu32"", accumulator);
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
			if (accumulator < 0x80)
Packit Service fa4841
			{
Packit Service fa4841
				/* 8 bits of literal are encoded as-is */
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 8);
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				/* bits 10 followed by lower 7 bits of literal */
Packit Service fa4841
				accumulator = 0x100 | (accumulator & 0x7F);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 9);
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			CopyOffset = (HistoryBufferSize - 1) & (HistoryPtr - MatchPtr);
Packit Service fa4841
			*HistoryPtr++ = Sym2;
Packit Service fa4841
			*HistoryPtr++ = Sym3;
Packit Service fa4841
			pSrcPtr += 2;
Packit Service fa4841
			LengthOfMatch = 3;
Packit Service fa4841
			MatchPtr += 2;
Packit Service fa4841
Packit Service fa4841
			while ((*pSrcPtr == *MatchPtr) && (pSrcPtr < pSrcEnd) && (MatchPtr <= mppc->HistoryPtr))
Packit Service fa4841
			{
Packit Service fa4841
				MatchPtr++;
Packit Service fa4841
				*HistoryPtr++ = *pSrcPtr++;
Packit Service fa4841
				LengthOfMatch++;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
#ifdef DEBUG_MPPC
Packit Service bb5c11
			WLog_DBG(TAG, "<%"PRIu32",%"PRIu32">", CopyOffset, LengthOfMatch);
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
			/* Encode CopyOffset */
Packit Service fa4841
Packit Service fa4841
			if (((bs->position / 8) + 7) > (DstSize - 1))
Packit Service fa4841
			{
Packit Service fa4841
				mppc_context_reset(mppc, TRUE);
Packit Service fa4841
				*pFlags |= PACKET_FLUSHED;
Packit Service fa4841
				*pFlags |= CompressionLevel;
Packit Service fa4841
				*ppDstData = pSrcData;
Packit Service fa4841
				*pDstSize = SrcSize;
Packit Service fa4841
				return 1;
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (CompressionLevel) /* RDP5 */
Packit Service fa4841
			{
Packit Service fa4841
				if (CopyOffset < 64)
Packit Service fa4841
				{
Packit Service fa4841
					/* bits 11111 + lower 6 bits of CopyOffset */
Packit Service fa4841
					accumulator = 0x07C0 | (CopyOffset & 0x003F);
Packit Service fa4841
					BitStream_Write_Bits(bs, accumulator, 11);
Packit Service fa4841
				}
Packit Service fa4841
				else if ((CopyOffset >= 64) && (CopyOffset < 320))
Packit Service fa4841
				{
Packit Service fa4841
					/* bits 11110 + lower 8 bits of (CopyOffset - 64) */
Packit Service fa4841
					accumulator = 0x1E00 | ((CopyOffset - 64) & 0x00FF);
Packit Service fa4841
					BitStream_Write_Bits(bs, accumulator, 13);
Packit Service fa4841
				}
Packit Service fa4841
				else if ((CopyOffset >= 320) && (CopyOffset < 2368))
Packit Service fa4841
				{
Packit Service fa4841
					/* bits 1110 + lower 11 bits of (CopyOffset - 320) */
Packit Service fa4841
					accumulator = 0x7000 | ((CopyOffset - 320) & 0x07FF);
Packit Service fa4841
					BitStream_Write_Bits(bs, accumulator, 15);
Packit Service fa4841
				}
Packit Service fa4841
				else
Packit Service fa4841
				{
Packit Service fa4841
					/* bits 110 + lower 16 bits of (CopyOffset - 2368) */
Packit Service fa4841
					accumulator = 0x060000 | ((CopyOffset - 2368) & 0xFFFF);
Packit Service fa4841
					BitStream_Write_Bits(bs, accumulator, 19);
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
			else /* RDP4 */
Packit Service fa4841
			{
Packit Service fa4841
				if (CopyOffset < 64)
Packit Service fa4841
				{
Packit Service fa4841
					/* bits 1111 + lower 6 bits of CopyOffset */
Packit Service fa4841
					accumulator = 0x03C0 | (CopyOffset & 0x003F);
Packit Service fa4841
					BitStream_Write_Bits(bs, accumulator, 10);
Packit Service fa4841
				}
Packit Service fa4841
				else if ((CopyOffset >= 64) && (CopyOffset < 320))
Packit Service fa4841
				{
Packit Service fa4841
					/* bits 1110 + lower 8 bits of (CopyOffset - 64) */
Packit Service fa4841
					accumulator = 0x0E00 | ((CopyOffset - 64) & 0x00FF);
Packit Service fa4841
					BitStream_Write_Bits(bs, accumulator, 12);
Packit Service fa4841
				}
Packit Service fa4841
				else if ((CopyOffset >= 320) && (CopyOffset < 8192))
Packit Service fa4841
				{
Packit Service fa4841
					/* bits 110 + lower 13 bits of (CopyOffset - 320) */
Packit Service fa4841
					accumulator = 0xC000 | ((CopyOffset - 320) & 0x1FFF);
Packit Service fa4841
					BitStream_Write_Bits(bs, accumulator, 16);
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			/* Encode LengthOfMatch */
Packit Service fa4841
Packit Service fa4841
			if (LengthOfMatch == 3)
Packit Service fa4841
			{
Packit Service fa4841
				/* 0 + 0 lower bits of LengthOfMatch */
Packit Service fa4841
				BitStream_Write_Bits(bs, 0, 1);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 4) && (LengthOfMatch < 8))
Packit Service fa4841
			{
Packit Service fa4841
				/* 10 + 2 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x0008 | (LengthOfMatch & 0x0003);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 4);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 8) && (LengthOfMatch < 16))
Packit Service fa4841
			{
Packit Service fa4841
				/* 110 + 3 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x0030 | (LengthOfMatch & 0x0007);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 6);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 16) && (LengthOfMatch < 32))
Packit Service fa4841
			{
Packit Service fa4841
				/* 1110 + 4 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x00E0 | (LengthOfMatch & 0x000F);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 8);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 32) && (LengthOfMatch < 64))
Packit Service fa4841
			{
Packit Service fa4841
				/* 11110 + 5 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x03C0 | (LengthOfMatch & 0x001F);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 10);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 64) && (LengthOfMatch < 128))
Packit Service fa4841
			{
Packit Service fa4841
				/* 111110 + 6 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x0F80 | (LengthOfMatch & 0x003F);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 12);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 128) && (LengthOfMatch < 256))
Packit Service fa4841
			{
Packit Service fa4841
				/* 1111110 + 7 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x3F00 | (LengthOfMatch & 0x007F);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 14);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 256) && (LengthOfMatch < 512))
Packit Service fa4841
			{
Packit Service fa4841
				/* 11111110 + 8 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0xFE00 | (LengthOfMatch & 0x00FF);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 16);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 512) && (LengthOfMatch < 1024))
Packit Service fa4841
			{
Packit Service fa4841
				/* 111111110 + 9 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x3FC00 | (LengthOfMatch & 0x01FF);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 18);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 1024) && (LengthOfMatch < 2048))
Packit Service fa4841
			{
Packit Service fa4841
				/* 1111111110 + 10 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0xFF800 | (LengthOfMatch & 0x03FF);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 20);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 2048) && (LengthOfMatch < 4096))
Packit Service fa4841
			{
Packit Service fa4841
				/* 11111111110 + 11 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x3FF000 | (LengthOfMatch & 0x07FF);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 22);
Packit Service fa4841
			}
Packit Service fa4841
			else if ((LengthOfMatch >= 4096) && (LengthOfMatch < 8192))
Packit Service fa4841
			{
Packit Service fa4841
				/* 111111111110 + 12 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0xFFE000 | (LengthOfMatch & 0x0FFF);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 24);
Packit Service fa4841
			}
Packit Service bb5c11
			else if (((LengthOfMatch >= 8192) && (LengthOfMatch < 16384)) && CompressionLevel) /* RDP5 */
Packit Service fa4841
			{
Packit Service fa4841
				/* 1111111111110 + 13 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x3FFC000 | (LengthOfMatch & 0x1FFF);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 26);
Packit Service fa4841
			}
Packit Service bb5c11
			else if (((LengthOfMatch >= 16384) && (LengthOfMatch < 32768)) && CompressionLevel) /* RDP5 */
Packit Service fa4841
			{
Packit Service fa4841
				/* 11111111111110 + 14 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0xFFF8000 | (LengthOfMatch & 0x3FFF);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 28);
Packit Service fa4841
			}
Packit Service bb5c11
			else if (((LengthOfMatch >= 32768) && (LengthOfMatch < 65536)) && CompressionLevel) /* RDP5 */
Packit Service fa4841
			{
Packit Service fa4841
				/* 111111111111110 + 15 lower bits of LengthOfMatch */
Packit Service fa4841
				accumulator = 0x3FFF0000 | (LengthOfMatch & 0x7FFF);
Packit Service fa4841
				BitStream_Write_Bits(bs, accumulator, 30);
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* Encode trailing symbols as literals */
Packit Service fa4841
Packit Service fa4841
	while (pSrcPtr <= pSrcEnd)
Packit Service fa4841
	{
Packit Service fa4841
		if (((bs->position / 8) + 2) > (DstSize - 1))
Packit Service fa4841
		{
Packit Service fa4841
			mppc_context_reset(mppc, TRUE);
Packit Service fa4841
			*pFlags |= PACKET_FLUSHED;
Packit Service fa4841
			*pFlags |= CompressionLevel;
Packit Service fa4841
			*ppDstData = pSrcData;
Packit Service fa4841
			*pDstSize = SrcSize;
Packit Service fa4841
			return 1;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		accumulator = *pSrcPtr;
Packit Service fa4841
#ifdef DEBUG_MPPC
Packit Service bb5c11
		WLog_DBG(TAG, "%"PRIu32"", accumulator);
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
		if (accumulator < 0x80)
Packit Service fa4841
		{
Packit Service fa4841
			/* 8 bits of literal are encoded as-is */
Packit Service fa4841
			BitStream_Write_Bits(bs, accumulator, 8);
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			/* bits 10 followed by lower 7 bits of literal */
Packit Service fa4841
			accumulator = 0x100 | (accumulator & 0x7F);
Packit Service fa4841
			BitStream_Write_Bits(bs, accumulator, 9);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		*HistoryPtr++ = *pSrcPtr++;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	BitStream_Flush(bs);
Packit Service fa4841
	*pFlags |= PACKET_COMPRESSED;
Packit Service fa4841
	*pFlags |= CompressionLevel;
Packit Service fa4841
Packit Service fa4841
	if (PacketAtFront)
Packit Service fa4841
		*pFlags |= PACKET_AT_FRONT;
Packit Service fa4841
Packit Service fa4841
	if (PacketFlushed)
Packit Service fa4841
		*pFlags |= PACKET_FLUSHED;
Packit Service fa4841
Packit Service fa4841
	*pDstSize = ((bs->position + 7) / 8);
Packit Service fa4841
	mppc->HistoryPtr = HistoryPtr;
Packit Service fa4841
	mppc->HistoryOffset = HistoryPtr - HistoryBuffer;
Packit Service fa4841
	return 1;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void mppc_set_compression_level(MPPC_CONTEXT* mppc, DWORD CompressionLevel)
Packit Service fa4841
{
Packit Service fa4841
	if (CompressionLevel < 1)
Packit Service fa4841
	{
Packit Service fa4841
		mppc->CompressionLevel = 0;
Packit Service fa4841
		mppc->HistoryBufferSize = 8192;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		mppc->CompressionLevel = 1;
Packit Service fa4841
		mppc->HistoryBufferSize = 65536;
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void mppc_context_reset(MPPC_CONTEXT* mppc, BOOL flush)
Packit Service fa4841
{
Packit Service fa4841
	ZeroMemory(&(mppc->HistoryBuffer), sizeof(mppc->HistoryBuffer));
Packit Service fa4841
	ZeroMemory(&(mppc->MatchBuffer), sizeof(mppc->MatchBuffer));
Packit Service fa4841
Packit Service fa4841
	if (flush)
Packit Service fa4841
		mppc->HistoryOffset = mppc->HistoryBufferSize + 1;
Packit Service fa4841
	else
Packit Service fa4841
		mppc->HistoryOffset = 0;
Packit Service bb5c11
Packit Service fa4841
	mppc->HistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryOffset]);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor)
Packit Service fa4841
{
Packit Service fa4841
	MPPC_CONTEXT* mppc;
Packit Service fa4841
	mppc = calloc(1, sizeof(MPPC_CONTEXT));
Packit Service fa4841
Packit Service fa4841
	if (mppc)
Packit Service fa4841
	{
Packit Service fa4841
		mppc->Compressor = Compressor;
Packit Service fa4841
Packit Service fa4841
		if (CompressionLevel < 1)
Packit Service fa4841
		{
Packit Service fa4841
			mppc->CompressionLevel = 0;
Packit Service fa4841
			mppc->HistoryBufferSize = 8192;
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			mppc->CompressionLevel = 1;
Packit Service fa4841
			mppc->HistoryBufferSize = 65536;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		mppc->bs = BitStream_New();
Packit Service fa4841
Packit Service fa4841
		if (!mppc->bs)
Packit Service fa4841
		{
Packit Service fa4841
			free(mppc);
Packit Service fa4841
			return NULL;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		mppc_context_reset(mppc, FALSE);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return mppc;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void mppc_context_free(MPPC_CONTEXT* mppc)
Packit Service fa4841
{
Packit Service fa4841
	if (mppc)
Packit Service fa4841
	{
Packit Service fa4841
		BitStream_Free(mppc->bs);
Packit Service fa4841
		free(mppc);
Packit Service fa4841
	}
Packit Service fa4841
}