/src/FreeRDP/libfreerdp/codec/mppc.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /**  | 
2  |  |  * FreeRDP: A Remote Desktop Protocol Implementation  | 
3  |  |  * MPPC Bulk Data Compression  | 
4  |  |  *  | 
5  |  |  * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>  | 
6  |  |  *  | 
7  |  |  * Licensed under the Apache License, Version 2.0 (the "License");  | 
8  |  |  * you may not use this file except in compliance with the License.  | 
9  |  |  * You may obtain a copy of the License at  | 
10  |  |  *  | 
11  |  |  *     http://www.apache.org/licenses/LICENSE-2.0  | 
12  |  |  *  | 
13  |  |  * Unless required by applicable law or agreed to in writing, software  | 
14  |  |  * distributed under the License is distributed on an "AS IS" BASIS,  | 
15  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
16  |  |  * See the License for the specific language governing permissions and  | 
17  |  |  * limitations under the License.  | 
18  |  |  */  | 
19  |  |  | 
20  |  | #include <winpr/assert.h>  | 
21  |  | #include <freerdp/config.h>  | 
22  |  |  | 
23  |  | #include <winpr/crt.h>  | 
24  |  | #include <winpr/print.h>  | 
25  |  | #include <winpr/stream.h>  | 
26  |  | #include <winpr/bitstream.h>  | 
27  |  |  | 
28  |  | #include <freerdp/log.h>  | 
29  |  | #include "mppc.h"  | 
30  |  |  | 
31  |  | #define TAG FREERDP_TAG("codec.mppc") | 
32  |  |  | 
33  |  | //#define DEBUG_MPPC  1  | 
34  |  |  | 
35  |  | #define MPPC_MATCH_INDEX(_sym1, _sym2, _sym3)                             \  | 
36  | 0  |   ((((MPPC_MATCH_TABLE[_sym3] << 16) + (MPPC_MATCH_TABLE[_sym2] << 8) + \  | 
37  | 0  |      MPPC_MATCH_TABLE[_sym1]) &                                         \  | 
38  | 0  |     0x07FFF000) >>                                                      \  | 
39  | 0  |    12)  | 
40  |  |  | 
41  |  | struct s_MPPC_CONTEXT  | 
42  |  | { | 
43  |  |   ALIGN64 wBitStream* bs;  | 
44  |  |   ALIGN64 BOOL Compressor;  | 
45  |  |   ALIGN64 BYTE* HistoryPtr;  | 
46  |  |   ALIGN64 UINT32 HistoryOffset;  | 
47  |  |   ALIGN64 UINT32 HistoryBufferSize;  | 
48  |  |   ALIGN64 BYTE HistoryBuffer[65536];  | 
49  |  |   ALIGN64 UINT16 MatchBuffer[32768];  | 
50  |  |   ALIGN64 UINT32 CompressionLevel;  | 
51  |  | };  | 
52  |  |  | 
53  |  | static const UINT32 MPPC_MATCH_TABLE[256] = { | 
54  |  |   0x00000000, 0x009CCF93, 0x01399F26, 0x01D66EB9, 0x02733E4C, 0x03100DDF, 0x03ACDD72, 0x0449AD05,  | 
55  |  |   0x04E67C98, 0x05834C2B, 0x06201BBE, 0x06BCEB51, 0x0759BAE4, 0x07F68A77, 0x08935A0A, 0x0930299D,  | 
56  |  |   0x09CCF930, 0x0A69C8C3, 0x0B069856, 0x0BA367E9, 0x0C40377C, 0x0CDD070F, 0x0D79D6A2, 0x0E16A635,  | 
57  |  |   0x0EB375C8, 0x0F50455B, 0x0FED14EE, 0x1089E481, 0x1126B414, 0x11C383A7, 0x1260533A, 0x12FD22CD,  | 
58  |  |   0x1399F260, 0x1436C1F3, 0x14D39186, 0x15706119, 0x160D30AC, 0x16AA003F, 0x1746CFD2, 0x17E39F65,  | 
59  |  |   0x18806EF8, 0x191D3E8B, 0x19BA0E1E, 0x1A56DDB1, 0x1AF3AD44, 0x1B907CD7, 0x1C2D4C6A, 0x1CCA1BFD,  | 
60  |  |   0x1D66EB90, 0x1E03BB23, 0x1EA08AB6, 0x1F3D5A49, 0x1FDA29DC, 0x2076F96F, 0x2113C902, 0x21B09895,  | 
61  |  |   0x224D6828, 0x22EA37BB, 0x2387074E, 0x2423D6E1, 0x24C0A674, 0x255D7607, 0x25FA459A, 0x2697152D,  | 
62  |  |   0x2733E4C0, 0x27D0B453, 0x286D83E6, 0x290A5379, 0x29A7230C, 0x2A43F29F, 0x2AE0C232, 0x2B7D91C5,  | 
63  |  |   0x2C1A6158, 0x2CB730EB, 0x2D54007E, 0x2DF0D011, 0x2E8D9FA4, 0x2F2A6F37, 0x2FC73ECA, 0x30640E5D,  | 
64  |  |   0x3100DDF0, 0x319DAD83, 0x323A7D16, 0x32D74CA9, 0x33741C3C, 0x3410EBCF, 0x34ADBB62, 0x354A8AF5,  | 
65  |  |   0x35E75A88, 0x36842A1B, 0x3720F9AE, 0x37BDC941, 0x385A98D4, 0x38F76867, 0x399437FA, 0x3A31078D,  | 
66  |  |   0x3ACDD720, 0x3B6AA6B3, 0x3C077646, 0x3CA445D9, 0x3D41156C, 0x3DDDE4FF, 0x3E7AB492, 0x3F178425,  | 
67  |  |   0x3FB453B8, 0x4051234B, 0x40EDF2DE, 0x418AC271, 0x42279204, 0x42C46197, 0x4361312A, 0x43FE00BD,  | 
68  |  |   0x449AD050, 0x45379FE3, 0x45D46F76, 0x46713F09, 0x470E0E9C, 0x47AADE2F, 0x4847ADC2, 0x48E47D55,  | 
69  |  |   0x49814CE8, 0x4A1E1C7B, 0x4ABAEC0E, 0x4B57BBA1, 0x4BF48B34, 0x4C915AC7, 0x4D2E2A5A, 0x4DCAF9ED,  | 
70  |  |   0x4E67C980, 0x4F049913, 0x4FA168A6, 0x503E3839, 0x50DB07CC, 0x5177D75F, 0x5214A6F2, 0x52B17685,  | 
71  |  |   0x534E4618, 0x53EB15AB, 0x5487E53E, 0x5524B4D1, 0x55C18464, 0x565E53F7, 0x56FB238A, 0x5797F31D,  | 
72  |  |   0x5834C2B0, 0x58D19243, 0x596E61D6, 0x5A0B3169, 0x5AA800FC, 0x5B44D08F, 0x5BE1A022, 0x5C7E6FB5,  | 
73  |  |   0x5D1B3F48, 0x5DB80EDB, 0x5E54DE6E, 0x5EF1AE01, 0x5F8E7D94, 0x602B4D27, 0x60C81CBA, 0x6164EC4D,  | 
74  |  |   0x6201BBE0, 0x629E8B73, 0x633B5B06, 0x63D82A99, 0x6474FA2C, 0x6511C9BF, 0x65AE9952, 0x664B68E5,  | 
75  |  |   0x66E83878, 0x6785080B, 0x6821D79E, 0x68BEA731, 0x695B76C4, 0x69F84657, 0x6A9515EA, 0x6B31E57D,  | 
76  |  |   0x6BCEB510, 0x6C6B84A3, 0x6D085436, 0x6DA523C9, 0x6E41F35C, 0x6EDEC2EF, 0x6F7B9282, 0x70186215,  | 
77  |  |   0x70B531A8, 0x7152013B, 0x71EED0CE, 0x728BA061, 0x73286FF4, 0x73C53F87, 0x74620F1A, 0x74FEDEAD,  | 
78  |  |   0x759BAE40, 0x76387DD3, 0x76D54D66, 0x77721CF9, 0x780EEC8C, 0x78ABBC1F, 0x79488BB2, 0x79E55B45,  | 
79  |  |   0x7A822AD8, 0x7B1EFA6B, 0x7BBBC9FE, 0x7C589991, 0x7CF56924, 0x7D9238B7, 0x7E2F084A, 0x7ECBD7DD,  | 
80  |  |   0x7F68A770, 0x80057703, 0x80A24696, 0x813F1629, 0x81DBE5BC, 0x8278B54F, 0x831584E2, 0x83B25475,  | 
81  |  |   0x844F2408, 0x84EBF39B, 0x8588C32E, 0x862592C1, 0x86C26254, 0x875F31E7, 0x87FC017A, 0x8898D10D,  | 
82  |  |   0x8935A0A0, 0x89D27033, 0x8A6F3FC6, 0x8B0C0F59, 0x8BA8DEEC, 0x8C45AE7F, 0x8CE27E12, 0x8D7F4DA5,  | 
83  |  |   0x8E1C1D38, 0x8EB8ECCB, 0x8F55BC5E, 0x8FF28BF1, 0x908F5B84, 0x912C2B17, 0x91C8FAAA, 0x9265CA3D,  | 
84  |  |   0x930299D0, 0x939F6963, 0x943C38F6, 0x94D90889, 0x9575D81C, 0x9612A7AF, 0x96AF7742, 0x974C46D5,  | 
85  |  |   0x97E91668, 0x9885E5FB, 0x9922B58E, 0x99BF8521, 0x9A5C54B4, 0x9AF92447, 0x9B95F3DA, 0x9C32C36D  | 
86  |  | };  | 
87  |  |  | 
88  |  | int mppc_decompress(MPPC_CONTEXT* mppc, const BYTE* pSrcData, UINT32 SrcSize,  | 
89  |  |                     const BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)  | 
90  | 19.1k  | { | 
91  | 19.1k  |   BYTE Literal = 0;  | 
92  | 19.1k  |   BYTE* SrcPtr = NULL;  | 
93  | 19.1k  |   UINT32 CopyOffset = 0;  | 
94  | 19.1k  |   UINT32 LengthOfMatch = 0;  | 
95  | 19.1k  |   UINT32 accumulator = 0;  | 
96  | 19.1k  |   BYTE* HistoryPtr = NULL;  | 
97  | 19.1k  |   BYTE* HistoryBuffer = NULL;  | 
98  | 19.1k  |   BYTE* HistoryBufferEnd = NULL;  | 
99  | 19.1k  |   UINT32 HistoryBufferSize = 0;  | 
100  | 19.1k  |   UINT32 CompressionLevel = 0;  | 
101  | 19.1k  |   wBitStream* bs = NULL;  | 
102  |  |  | 
103  | 19.1k  |   WINPR_ASSERT(mppc);  | 
104  | 19.1k  |   WINPR_ASSERT(pSrcData);  | 
105  | 19.1k  |   WINPR_ASSERT(ppDstData);  | 
106  | 19.1k  |   WINPR_ASSERT(pDstSize);  | 
107  |  |  | 
108  | 19.1k  |   bs = mppc->bs;  | 
109  | 19.1k  |   WINPR_ASSERT(bs);  | 
110  |  |  | 
111  | 19.1k  |   HistoryBuffer = mppc->HistoryBuffer;  | 
112  | 19.1k  |   WINPR_ASSERT(HistoryBuffer);  | 
113  |  |  | 
114  | 19.1k  |   HistoryBufferSize = mppc->HistoryBufferSize;  | 
115  | 19.1k  |   HistoryBufferEnd = &HistoryBuffer[HistoryBufferSize - 1];  | 
116  | 19.1k  |   CompressionLevel = mppc->CompressionLevel;  | 
117  | 19.1k  |   BitStream_Attach(bs, pSrcData, SrcSize);  | 
118  | 19.1k  |   BitStream_Fetch(bs);  | 
119  |  |  | 
120  | 19.1k  |   if (flags & PACKET_AT_FRONT)  | 
121  | 17.8k  |   { | 
122  | 17.8k  |     mppc->HistoryOffset = 0;  | 
123  | 17.8k  |     mppc->HistoryPtr = HistoryBuffer;  | 
124  | 17.8k  |   }  | 
125  |  |  | 
126  | 19.1k  |   if (flags & PACKET_FLUSHED)  | 
127  | 1.27k  |   { | 
128  | 1.27k  |     mppc->HistoryOffset = 0;  | 
129  | 1.27k  |     mppc->HistoryPtr = HistoryBuffer;  | 
130  | 1.27k  |     ZeroMemory(HistoryBuffer, mppc->HistoryBufferSize);  | 
131  | 1.27k  |   }  | 
132  |  |  | 
133  | 19.1k  |   HistoryPtr = mppc->HistoryPtr;  | 
134  |  |  | 
135  | 19.1k  |   if (!(flags & PACKET_COMPRESSED))  | 
136  | 0  |   { | 
137  | 0  |     *pDstSize = SrcSize;  | 
138  | 0  |     *ppDstData = pSrcData;  | 
139  | 0  |     return 1;  | 
140  | 0  |   }  | 
141  |  |  | 
142  | 169M  |   while ((bs->length - bs->position) >= 8)  | 
143  | 169M  |   { | 
144  | 169M  |     accumulator = bs->accumulator;  | 
145  |  |  | 
146  |  |     /**  | 
147  |  |      * Literal Encoding  | 
148  |  |      */  | 
149  |  |  | 
150  | 169M  |     if (HistoryPtr > HistoryBufferEnd)  | 
151  | 3.30k  |     { | 
152  | 3.30k  |       WLog_ERR(TAG, "history buffer index out of range");  | 
153  | 3.30k  |       return -1004;  | 
154  | 3.30k  |     }  | 
155  |  |  | 
156  | 169M  |     if ((accumulator & 0x80000000) == 0x00000000)  | 
157  | 168M  |     { | 
158  |  |       /**  | 
159  |  |        * Literal, less than 0x80  | 
160  |  |        * bit 0 followed by the lower 7 bits of the literal  | 
161  |  |        */  | 
162  | 168M  |       Literal = ((accumulator & 0x7F000000) >> 24);  | 
163  | 168M  |       *(HistoryPtr) = Literal;  | 
164  | 168M  |       HistoryPtr++;  | 
165  | 168M  |       BitStream_Shift(bs, 8);  | 
166  | 168M  |       continue;  | 
167  | 168M  |     }  | 
168  | 510k  |     else if ((accumulator & 0xC0000000) == 0x80000000)  | 
169  | 234k  |     { | 
170  |  |       /**  | 
171  |  |        * Literal, greater than 0x7F  | 
172  |  |        * bits 10 followed by the lower 7 bits of the literal  | 
173  |  |        */  | 
174  | 234k  |       Literal = ((accumulator & 0x3F800000) >> 23) + 0x80;  | 
175  | 234k  |       *(HistoryPtr) = Literal;  | 
176  | 234k  |       HistoryPtr++;  | 
177  | 234k  |       BitStream_Shift(bs, 9);  | 
178  | 234k  |       continue;  | 
179  | 234k  |     }  | 
180  |  |  | 
181  |  |     /**  | 
182  |  |      * CopyOffset Encoding  | 
183  |  |      */  | 
184  | 276k  |     if (CompressionLevel) /* RDP5 */  | 
185  | 209k  |     { | 
186  | 209k  |       if ((accumulator & 0xF8000000) == 0xF8000000)  | 
187  | 37.8k  |       { | 
188  |  |         /**  | 
189  |  |          * CopyOffset, range [0, 63]  | 
190  |  |          * bits 11111 + lower 6 bits of CopyOffset  | 
191  |  |          */  | 
192  | 37.8k  |         CopyOffset = ((accumulator >> 21) & 0x3F);  | 
193  | 37.8k  |         BitStream_Shift(bs, 11);  | 
194  | 37.8k  |       }  | 
195  | 172k  |       else if ((accumulator & 0xF8000000) == 0xF0000000)  | 
196  | 11.1k  |       { | 
197  |  |         /**  | 
198  |  |          * CopyOffset, range [64, 319]  | 
199  |  |          * bits 11110 + lower 8 bits of (CopyOffset - 64)  | 
200  |  |          */  | 
201  | 11.1k  |         CopyOffset = ((accumulator >> 19) & 0xFF) + 64;  | 
202  | 11.1k  |         BitStream_Shift(bs, 13);  | 
203  | 11.1k  |       }  | 
204  | 160k  |       else if ((accumulator & 0xF0000000) == 0xE0000000)  | 
205  | 77.5k  |       { | 
206  |  |         /**  | 
207  |  |          * CopyOffset, range [320, 2367]  | 
208  |  |          * bits 1110 + lower 11 bits of (CopyOffset - 320)  | 
209  |  |          */  | 
210  | 77.5k  |         CopyOffset = ((accumulator >> 17) & 0x7FF) + 320;  | 
211  | 77.5k  |         BitStream_Shift(bs, 15);  | 
212  | 77.5k  |       }  | 
213  | 83.3k  |       else if ((accumulator & 0xE0000000) == 0xC0000000)  | 
214  | 83.3k  |       { | 
215  |  |         /**  | 
216  |  |          * CopyOffset, range [2368, ]  | 
217  |  |          * bits 110 + lower 16 bits of (CopyOffset - 2368)  | 
218  |  |          */  | 
219  | 83.3k  |         CopyOffset = ((accumulator >> 13) & 0xFFFF) + 2368;  | 
220  | 83.3k  |         BitStream_Shift(bs, 19);  | 
221  | 83.3k  |       }  | 
222  | 0  |       else  | 
223  | 0  |       { | 
224  |  |         /* Invalid CopyOffset Encoding */  | 
225  | 0  |         return -1001;  | 
226  | 0  |       }  | 
227  | 209k  |     }  | 
228  | 66.2k  |     else /* RDP4 */  | 
229  | 66.2k  |     { | 
230  | 66.2k  |       if ((accumulator & 0xF0000000) == 0xF0000000)  | 
231  | 31.0k  |       { | 
232  |  |         /**  | 
233  |  |          * CopyOffset, range [0, 63]  | 
234  |  |          * bits 1111 + lower 6 bits of CopyOffset  | 
235  |  |          */  | 
236  | 31.0k  |         CopyOffset = ((accumulator >> 22) & 0x3F);  | 
237  | 31.0k  |         BitStream_Shift(bs, 10);  | 
238  | 31.0k  |       }  | 
239  | 35.2k  |       else if ((accumulator & 0xF0000000) == 0xE0000000)  | 
240  | 16.8k  |       { | 
241  |  |         /**  | 
242  |  |          * CopyOffset, range [64, 319]  | 
243  |  |          * bits 1110 + lower 8 bits of (CopyOffset - 64)  | 
244  |  |          */  | 
245  | 16.8k  |         CopyOffset = ((accumulator >> 20) & 0xFF) + 64;  | 
246  | 16.8k  |         BitStream_Shift(bs, 12);  | 
247  | 16.8k  |       }  | 
248  | 18.3k  |       else if ((accumulator & 0xE0000000) == 0xC0000000)  | 
249  | 18.3k  |       { | 
250  |  |         /**  | 
251  |  |          * CopyOffset, range [320, 8191]  | 
252  |  |          * bits 110 + lower 13 bits of (CopyOffset - 320)  | 
253  |  |          */  | 
254  | 18.3k  |         CopyOffset = ((accumulator >> 16) & 0x1FFF) + 320;  | 
255  | 18.3k  |         BitStream_Shift(bs, 16);  | 
256  | 18.3k  |       }  | 
257  | 0  |       else  | 
258  | 0  |       { | 
259  |  |         /* Invalid CopyOffset Encoding */  | 
260  | 0  |         return -1002;  | 
261  | 0  |       }  | 
262  | 66.2k  |     }  | 
263  |  |  | 
264  |  |     /**  | 
265  |  |      * LengthOfMatch Encoding  | 
266  |  |      */  | 
267  | 276k  |     accumulator = bs->accumulator;  | 
268  |  |  | 
269  | 276k  |     if ((accumulator & 0x80000000) == 0x00000000)  | 
270  | 113k  |     { | 
271  |  |       /**  | 
272  |  |        * LengthOfMatch [3]  | 
273  |  |        * bit 0 + 0 lower bits of LengthOfMatch  | 
274  |  |        */  | 
275  | 113k  |       LengthOfMatch = 3;  | 
276  | 113k  |       BitStream_Shift(bs, 1);  | 
277  | 113k  |     }  | 
278  | 162k  |     else if ((accumulator & 0xC0000000) == 0x80000000)  | 
279  | 28.5k  |     { | 
280  |  |       /**  | 
281  |  |        * LengthOfMatch [4, 7]  | 
282  |  |        * bits 10 + 2 lower bits of LengthOfMatch  | 
283  |  |        */  | 
284  | 28.5k  |       LengthOfMatch = ((accumulator >> 28) & 0x0003) + 0x0004;  | 
285  | 28.5k  |       BitStream_Shift(bs, 4);  | 
286  | 28.5k  |     }  | 
287  | 134k  |     else if ((accumulator & 0xE0000000) == 0xC0000000)  | 
288  | 29.0k  |     { | 
289  |  |       /**  | 
290  |  |        * LengthOfMatch [8, 15]  | 
291  |  |        * bits 110 + 3 lower bits of LengthOfMatch  | 
292  |  |        */  | 
293  | 29.0k  |       LengthOfMatch = ((accumulator >> 26) & 0x0007) + 0x0008;  | 
294  | 29.0k  |       BitStream_Shift(bs, 6);  | 
295  | 29.0k  |     }  | 
296  | 105k  |     else if ((accumulator & 0xF0000000) == 0xE0000000)  | 
297  | 7.26k  |     { | 
298  |  |       /**  | 
299  |  |        * LengthOfMatch [16, 31]  | 
300  |  |        * bits 1110 + 4 lower bits of LengthOfMatch  | 
301  |  |        */  | 
302  | 7.26k  |       LengthOfMatch = ((accumulator >> 24) & 0x000F) + 0x0010;  | 
303  | 7.26k  |       BitStream_Shift(bs, 8);  | 
304  | 7.26k  |     }  | 
305  | 97.7k  |     else if ((accumulator & 0xF8000000) == 0xF0000000)  | 
306  | 12.3k  |     { | 
307  |  |       /**  | 
308  |  |        * LengthOfMatch [32, 63]  | 
309  |  |        * bits 11110 + 5 lower bits of LengthOfMatch  | 
310  |  |        */  | 
311  | 12.3k  |       LengthOfMatch = ((accumulator >> 22) & 0x001F) + 0x0020;  | 
312  | 12.3k  |       BitStream_Shift(bs, 10);  | 
313  | 12.3k  |     }  | 
314  | 85.4k  |     else if ((accumulator & 0xFC000000) == 0xF8000000)  | 
315  | 36.0k  |     { | 
316  |  |       /**  | 
317  |  |        * LengthOfMatch [64, 127]  | 
318  |  |        * bits 111110 + 6 lower bits of LengthOfMatch  | 
319  |  |        */  | 
320  | 36.0k  |       LengthOfMatch = ((accumulator >> 20) & 0x003F) + 0x0040;  | 
321  | 36.0k  |       BitStream_Shift(bs, 12);  | 
322  | 36.0k  |     }  | 
323  | 49.3k  |     else if ((accumulator & 0xFE000000) == 0xFC000000)  | 
324  | 36.5k  |     { | 
325  |  |       /**  | 
326  |  |        * LengthOfMatch [128, 255]  | 
327  |  |        * bits 1111110 + 7 lower bits of LengthOfMatch  | 
328  |  |        */  | 
329  | 36.5k  |       LengthOfMatch = ((accumulator >> 18) & 0x007F) + 0x0080;  | 
330  | 36.5k  |       BitStream_Shift(bs, 14);  | 
331  | 36.5k  |     }  | 
332  | 12.8k  |     else if ((accumulator & 0xFF000000) == 0xFE000000)  | 
333  | 4.78k  |     { | 
334  |  |       /**  | 
335  |  |        * LengthOfMatch [256, 511]  | 
336  |  |        * bits 11111110 + 8 lower bits of LengthOfMatch  | 
337  |  |        */  | 
338  | 4.78k  |       LengthOfMatch = ((accumulator >> 16) & 0x00FF) + 0x0100;  | 
339  | 4.78k  |       BitStream_Shift(bs, 16);  | 
340  | 4.78k  |     }  | 
341  | 8.02k  |     else if ((accumulator & 0xFF800000) == 0xFF000000)  | 
342  | 790  |     { | 
343  |  |       /**  | 
344  |  |        * LengthOfMatch [512, 1023]  | 
345  |  |        * bits 111111110 + 9 lower bits of LengthOfMatch  | 
346  |  |        */  | 
347  | 790  |       LengthOfMatch = ((accumulator >> 14) & 0x01FF) + 0x0200;  | 
348  | 790  |       BitStream_Shift(bs, 18);  | 
349  | 790  |     }  | 
350  | 7.23k  |     else if ((accumulator & 0xFFC00000) == 0xFF800000)  | 
351  | 793  |     { | 
352  |  |       /**  | 
353  |  |        * LengthOfMatch [1024, 2047]  | 
354  |  |        * bits 1111111110 + 10 lower bits of LengthOfMatch  | 
355  |  |        */  | 
356  | 793  |       LengthOfMatch = ((accumulator >> 12) & 0x03FF) + 0x0400;  | 
357  | 793  |       BitStream_Shift(bs, 20);  | 
358  | 793  |     }  | 
359  | 6.43k  |     else if ((accumulator & 0xFFE00000) == 0xFFC00000)  | 
360  | 633  |     { | 
361  |  |       /**  | 
362  |  |        * LengthOfMatch [2048, 4095]  | 
363  |  |        * bits 11111111110 + 11 lower bits of LengthOfMatch  | 
364  |  |        */  | 
365  | 633  |       LengthOfMatch = ((accumulator >> 10) & 0x07FF) + 0x0800;  | 
366  | 633  |       BitStream_Shift(bs, 22);  | 
367  | 633  |     }  | 
368  | 5.80k  |     else if ((accumulator & 0xFFF00000) == 0xFFE00000)  | 
369  | 406  |     { | 
370  |  |       /**  | 
371  |  |        * LengthOfMatch [4096, 8191]  | 
372  |  |        * bits 111111111110 + 12 lower bits of LengthOfMatch  | 
373  |  |        */  | 
374  | 406  |       LengthOfMatch = ((accumulator >> 8) & 0x0FFF) + 0x1000;  | 
375  | 406  |       BitStream_Shift(bs, 24);  | 
376  | 406  |     }  | 
377  | 5.39k  |     else if (((accumulator & 0xFFF80000) == 0xFFF00000) && CompressionLevel) /* RDP5 */  | 
378  | 317  |     { | 
379  |  |       /**  | 
380  |  |        * LengthOfMatch [8192, 16383]  | 
381  |  |        * bits 1111111111110 + 13 lower bits of LengthOfMatch  | 
382  |  |        */  | 
383  | 317  |       LengthOfMatch = ((accumulator >> 6) & 0x1FFF) + 0x2000;  | 
384  | 317  |       BitStream_Shift(bs, 26);  | 
385  | 317  |     }  | 
386  | 5.08k  |     else if (((accumulator & 0xFFFC0000) == 0xFFF80000) && CompressionLevel) /* RDP5 */  | 
387  | 501  |     { | 
388  |  |       /**  | 
389  |  |        * LengthOfMatch [16384, 32767]  | 
390  |  |        * bits 11111111111110 + 14 lower bits of LengthOfMatch  | 
391  |  |        */  | 
392  | 501  |       LengthOfMatch = ((accumulator >> 4) & 0x3FFF) + 0x4000;  | 
393  | 501  |       BitStream_Shift(bs, 28);  | 
394  | 501  |     }  | 
395  | 4.58k  |     else if (((accumulator & 0xFFFE0000) == 0xFFFC0000) && CompressionLevel) /* RDP5 */  | 
396  | 492  |     { | 
397  |  |       /**  | 
398  |  |        * LengthOfMatch [32768, 65535]  | 
399  |  |        * bits 111111111111110 + 15 lower bits of LengthOfMatch  | 
400  |  |        */  | 
401  | 492  |       LengthOfMatch = ((accumulator >> 2) & 0x7FFF) + 0x8000;  | 
402  | 492  |       BitStream_Shift(bs, 30);  | 
403  | 492  |     }  | 
404  | 4.08k  |     else  | 
405  | 4.08k  |     { | 
406  |  |       /* Invalid LengthOfMatch Encoding */  | 
407  | 4.08k  |       return -1003;  | 
408  | 4.08k  |     }  | 
409  |  |  | 
410  |  | #if defined(DEBUG_MPPC)  | 
411  |  |     WLog_DBG(TAG, "<%" PRIu32 ",%" PRIu32 ">", CopyOffset, LengthOfMatch);  | 
412  |  | #endif  | 
413  |  |  | 
414  | 272k  |     if ((HistoryPtr + LengthOfMatch - 1) > HistoryBufferEnd)  | 
415  | 462  |     { | 
416  | 462  |       WLog_ERR(TAG, "history buffer overflow");  | 
417  | 462  |       return -1005;  | 
418  | 462  |     }  | 
419  |  |  | 
420  | 271k  |     SrcPtr = &HistoryBuffer[(HistoryPtr - HistoryBuffer - CopyOffset) &  | 
421  | 271k  |                             (CompressionLevel ? 0xFFFF : 0x1FFF)];  | 
422  |  |  | 
423  | 271k  |     do  | 
424  | 49.9M  |     { | 
425  | 49.9M  |       *HistoryPtr++ = *SrcPtr++;  | 
426  | 49.9M  |     } while (--LengthOfMatch);  | 
427  | 271k  |   }  | 
428  |  |  | 
429  | 11.2k  |   *pDstSize = (UINT32)(HistoryPtr - mppc->HistoryPtr);  | 
430  | 11.2k  |   *ppDstData = mppc->HistoryPtr;  | 
431  | 11.2k  |   mppc->HistoryPtr = HistoryPtr;  | 
432  | 11.2k  |   return 1;  | 
433  | 19.1k  | }  | 
434  |  |  | 
435  |  | int mppc_compress(MPPC_CONTEXT* mppc, const BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstBuffer,  | 
436  |  |                   const BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)  | 
437  | 0  | { | 
438  | 0  |   const BYTE* pSrcPtr = NULL;  | 
439  | 0  |   const BYTE* pSrcEnd = NULL;  | 
440  | 0  |   BYTE* MatchPtr = NULL;  | 
441  | 0  |   UINT32 DstSize = 0;  | 
442  | 0  |   BYTE* pDstData = NULL;  | 
443  | 0  |   UINT32 MatchIndex = 0;  | 
444  | 0  |   UINT32 accumulator = 0;  | 
445  | 0  |   BOOL PacketFlushed = 0;  | 
446  | 0  |   BOOL PacketAtFront = 0;  | 
447  | 0  |   DWORD CopyOffset = 0;  | 
448  | 0  |   DWORD LengthOfMatch = 0;  | 
449  | 0  |   BYTE* HistoryBuffer = NULL;  | 
450  | 0  |   BYTE* HistoryPtr = NULL;  | 
451  | 0  |   UINT32 HistoryOffset = 0;  | 
452  | 0  |   UINT32 HistoryBufferSize = 0;  | 
453  | 0  |   BYTE Sym1 = 0;  | 
454  | 0  |   BYTE Sym2 = 0;  | 
455  | 0  |   BYTE Sym3 = 0;  | 
456  | 0  |   UINT32 CompressionLevel = 0;  | 
457  | 0  |   wBitStream* bs = NULL;  | 
458  |  | 
  | 
459  | 0  |   WINPR_ASSERT(mppc);  | 
460  | 0  |   WINPR_ASSERT(pSrcData);  | 
461  | 0  |   WINPR_ASSERT(pDstBuffer);  | 
462  | 0  |   WINPR_ASSERT(ppDstData);  | 
463  | 0  |   WINPR_ASSERT(pDstSize);  | 
464  | 0  |   WINPR_ASSERT(pFlags);  | 
465  |  |  | 
466  | 0  |   bs = mppc->bs;  | 
467  | 0  |   WINPR_ASSERT(bs);  | 
468  |  |  | 
469  | 0  |   HistoryBuffer = mppc->HistoryBuffer;  | 
470  | 0  |   WINPR_ASSERT(HistoryBuffer);  | 
471  |  |  | 
472  | 0  |   HistoryBufferSize = mppc->HistoryBufferSize;  | 
473  | 0  |   CompressionLevel = mppc->CompressionLevel;  | 
474  | 0  |   HistoryOffset = mppc->HistoryOffset;  | 
475  | 0  |   *pFlags = 0;  | 
476  | 0  |   PacketFlushed = FALSE;  | 
477  |  | 
  | 
478  | 0  |   if (((HistoryOffset + SrcSize) < (HistoryBufferSize - 3)) && HistoryOffset)  | 
479  | 0  |   { | 
480  | 0  |     PacketAtFront = FALSE;  | 
481  | 0  |   }  | 
482  | 0  |   else  | 
483  | 0  |   { | 
484  | 0  |     if (HistoryOffset == (HistoryBufferSize + 1))  | 
485  | 0  |       PacketFlushed = TRUE;  | 
486  |  | 
  | 
487  | 0  |     HistoryOffset = 0;  | 
488  | 0  |     PacketAtFront = TRUE;  | 
489  | 0  |   }  | 
490  |  | 
  | 
491  | 0  |   HistoryPtr = &(HistoryBuffer[HistoryOffset]);  | 
492  | 0  |   pDstData = pDstBuffer;  | 
493  | 0  |   *ppDstData = pDstBuffer;  | 
494  |  | 
  | 
495  | 0  |   if (!pDstData)  | 
496  | 0  |     return -1;  | 
497  |  |  | 
498  | 0  |   if (*pDstSize > SrcSize)  | 
499  | 0  |     DstSize = SrcSize;  | 
500  | 0  |   else  | 
501  | 0  |     DstSize = *pDstSize;  | 
502  |  | 
  | 
503  | 0  |   BitStream_Attach(bs, pDstData, DstSize);  | 
504  | 0  |   pSrcPtr = pSrcData;  | 
505  | 0  |   pSrcEnd = &(pSrcData[SrcSize - 1]);  | 
506  |  | 
  | 
507  | 0  |   while (pSrcPtr < (pSrcEnd - 2))  | 
508  | 0  |   { | 
509  | 0  |     Sym1 = pSrcPtr[0];  | 
510  | 0  |     Sym2 = pSrcPtr[1];  | 
511  | 0  |     Sym3 = pSrcPtr[2];  | 
512  | 0  |     *HistoryPtr++ = *pSrcPtr++;  | 
513  | 0  |     MatchIndex = MPPC_MATCH_INDEX(Sym1, Sym2, Sym3);  | 
514  | 0  |     MatchPtr = &(HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);  | 
515  |  | 
  | 
516  | 0  |     if (MatchPtr != (HistoryPtr - 1))  | 
517  | 0  |       mppc->MatchBuffer[MatchIndex] = (UINT16)(HistoryPtr - HistoryBuffer);  | 
518  |  | 
  | 
519  | 0  |     if (mppc->HistoryPtr < HistoryPtr)  | 
520  | 0  |       mppc->HistoryPtr = HistoryPtr;  | 
521  |  | 
  | 
522  | 0  |     if ((Sym1 != *(MatchPtr - 1)) || (Sym2 != MatchPtr[0]) || (Sym3 != MatchPtr[1]) ||  | 
523  | 0  |         (&MatchPtr[1] > mppc->HistoryPtr) || (MatchPtr == HistoryBuffer) ||  | 
524  | 0  |         (MatchPtr == (HistoryPtr - 1)) || (MatchPtr == HistoryPtr))  | 
525  | 0  |     { | 
526  | 0  |       if (((bs->position / 8) + 2) > (DstSize - 1))  | 
527  | 0  |       { | 
528  | 0  |         mppc_context_reset(mppc, TRUE);  | 
529  | 0  |         *pFlags |= PACKET_FLUSHED;  | 
530  | 0  |         *pFlags |= CompressionLevel;  | 
531  | 0  |         *ppDstData = pSrcData;  | 
532  | 0  |         *pDstSize = SrcSize;  | 
533  | 0  |         return 1;  | 
534  | 0  |       }  | 
535  |  |  | 
536  | 0  |       accumulator = Sym1;  | 
537  |  | #if defined(DEBUG_MPPC)  | 
538  |  |       WLog_DBG(TAG, "%" PRIu32 "", accumulator);  | 
539  |  | #endif  | 
540  |  | 
  | 
541  | 0  |       if (accumulator < 0x80)  | 
542  | 0  |       { | 
543  |  |         /* 8 bits of literal are encoded as-is */  | 
544  | 0  |         BitStream_Write_Bits(bs, accumulator, 8);  | 
545  | 0  |       }  | 
546  | 0  |       else  | 
547  | 0  |       { | 
548  |  |         /* bits 10 followed by lower 7 bits of literal */  | 
549  | 0  |         accumulator = 0x100 | (accumulator & 0x7F);  | 
550  | 0  |         BitStream_Write_Bits(bs, accumulator, 9);  | 
551  | 0  |       }  | 
552  | 0  |     }  | 
553  | 0  |     else  | 
554  | 0  |     { | 
555  | 0  |       CopyOffset = (HistoryBufferSize - 1) & (HistoryPtr - MatchPtr);  | 
556  | 0  |       *HistoryPtr++ = Sym2;  | 
557  | 0  |       *HistoryPtr++ = Sym3;  | 
558  | 0  |       pSrcPtr += 2;  | 
559  | 0  |       LengthOfMatch = 3;  | 
560  | 0  |       MatchPtr += 2;  | 
561  |  | 
  | 
562  | 0  |       while ((*pSrcPtr == *MatchPtr) && (pSrcPtr < pSrcEnd) && (MatchPtr <= mppc->HistoryPtr))  | 
563  | 0  |       { | 
564  | 0  |         MatchPtr++;  | 
565  | 0  |         *HistoryPtr++ = *pSrcPtr++;  | 
566  | 0  |         LengthOfMatch++;  | 
567  | 0  |       }  | 
568  |  | 
  | 
569  |  | #if defined(DEBUG_MPPC)  | 
570  |  |       WLog_DBG(TAG, "<%" PRIu32 ",%" PRIu32 ">", CopyOffset, LengthOfMatch);  | 
571  |  | #endif  | 
572  |  |  | 
573  |  |       /* Encode CopyOffset */  | 
574  |  | 
  | 
575  | 0  |       if (((bs->position / 8) + 7) > (DstSize - 1))  | 
576  | 0  |       { | 
577  | 0  |         mppc_context_reset(mppc, TRUE);  | 
578  | 0  |         *pFlags |= PACKET_FLUSHED;  | 
579  | 0  |         *pFlags |= CompressionLevel;  | 
580  | 0  |         *ppDstData = pSrcData;  | 
581  | 0  |         *pDstSize = SrcSize;  | 
582  | 0  |         return 1;  | 
583  | 0  |       }  | 
584  |  |  | 
585  | 0  |       if (CompressionLevel) /* RDP5 */  | 
586  | 0  |       { | 
587  | 0  |         if (CopyOffset < 64)  | 
588  | 0  |         { | 
589  |  |           /* bits 11111 + lower 6 bits of CopyOffset */  | 
590  | 0  |           accumulator = 0x07C0 | (CopyOffset & 0x003F);  | 
591  | 0  |           BitStream_Write_Bits(bs, accumulator, 11);  | 
592  | 0  |         }  | 
593  | 0  |         else if ((CopyOffset >= 64) && (CopyOffset < 320))  | 
594  | 0  |         { | 
595  |  |           /* bits 11110 + lower 8 bits of (CopyOffset - 64) */  | 
596  | 0  |           accumulator = 0x1E00 | ((CopyOffset - 64) & 0x00FF);  | 
597  | 0  |           BitStream_Write_Bits(bs, accumulator, 13);  | 
598  | 0  |         }  | 
599  | 0  |         else if ((CopyOffset >= 320) && (CopyOffset < 2368))  | 
600  | 0  |         { | 
601  |  |           /* bits 1110 + lower 11 bits of (CopyOffset - 320) */  | 
602  | 0  |           accumulator = 0x7000 | ((CopyOffset - 320) & 0x07FF);  | 
603  | 0  |           BitStream_Write_Bits(bs, accumulator, 15);  | 
604  | 0  |         }  | 
605  | 0  |         else  | 
606  | 0  |         { | 
607  |  |           /* bits 110 + lower 16 bits of (CopyOffset - 2368) */  | 
608  | 0  |           accumulator = 0x060000 | ((CopyOffset - 2368) & 0xFFFF);  | 
609  | 0  |           BitStream_Write_Bits(bs, accumulator, 19);  | 
610  | 0  |         }  | 
611  | 0  |       }  | 
612  | 0  |       else /* RDP4 */  | 
613  | 0  |       { | 
614  | 0  |         if (CopyOffset < 64)  | 
615  | 0  |         { | 
616  |  |           /* bits 1111 + lower 6 bits of CopyOffset */  | 
617  | 0  |           accumulator = 0x03C0 | (CopyOffset & 0x003F);  | 
618  | 0  |           BitStream_Write_Bits(bs, accumulator, 10);  | 
619  | 0  |         }  | 
620  | 0  |         else if ((CopyOffset >= 64) && (CopyOffset < 320))  | 
621  | 0  |         { | 
622  |  |           /* bits 1110 + lower 8 bits of (CopyOffset - 64) */  | 
623  | 0  |           accumulator = 0x0E00 | ((CopyOffset - 64) & 0x00FF);  | 
624  | 0  |           BitStream_Write_Bits(bs, accumulator, 12);  | 
625  | 0  |         }  | 
626  | 0  |         else if ((CopyOffset >= 320) && (CopyOffset < 8192))  | 
627  | 0  |         { | 
628  |  |           /* bits 110 + lower 13 bits of (CopyOffset - 320) */  | 
629  | 0  |           accumulator = 0xC000 | ((CopyOffset - 320) & 0x1FFF);  | 
630  | 0  |           BitStream_Write_Bits(bs, accumulator, 16);  | 
631  | 0  |         }  | 
632  | 0  |       }  | 
633  |  |  | 
634  |  |       /* Encode LengthOfMatch */  | 
635  |  | 
  | 
636  | 0  |       if (LengthOfMatch == 3)  | 
637  | 0  |       { | 
638  |  |         /* 0 + 0 lower bits of LengthOfMatch */  | 
639  | 0  |         BitStream_Write_Bits(bs, 0, 1);  | 
640  | 0  |       }  | 
641  | 0  |       else if ((LengthOfMatch >= 4) && (LengthOfMatch < 8))  | 
642  | 0  |       { | 
643  |  |         /* 10 + 2 lower bits of LengthOfMatch */  | 
644  | 0  |         accumulator = 0x0008 | (LengthOfMatch & 0x0003);  | 
645  | 0  |         BitStream_Write_Bits(bs, accumulator, 4);  | 
646  | 0  |       }  | 
647  | 0  |       else if ((LengthOfMatch >= 8) && (LengthOfMatch < 16))  | 
648  | 0  |       { | 
649  |  |         /* 110 + 3 lower bits of LengthOfMatch */  | 
650  | 0  |         accumulator = 0x0030 | (LengthOfMatch & 0x0007);  | 
651  | 0  |         BitStream_Write_Bits(bs, accumulator, 6);  | 
652  | 0  |       }  | 
653  | 0  |       else if ((LengthOfMatch >= 16) && (LengthOfMatch < 32))  | 
654  | 0  |       { | 
655  |  |         /* 1110 + 4 lower bits of LengthOfMatch */  | 
656  | 0  |         accumulator = 0x00E0 | (LengthOfMatch & 0x000F);  | 
657  | 0  |         BitStream_Write_Bits(bs, accumulator, 8);  | 
658  | 0  |       }  | 
659  | 0  |       else if ((LengthOfMatch >= 32) && (LengthOfMatch < 64))  | 
660  | 0  |       { | 
661  |  |         /* 11110 + 5 lower bits of LengthOfMatch */  | 
662  | 0  |         accumulator = 0x03C0 | (LengthOfMatch & 0x001F);  | 
663  | 0  |         BitStream_Write_Bits(bs, accumulator, 10);  | 
664  | 0  |       }  | 
665  | 0  |       else if ((LengthOfMatch >= 64) && (LengthOfMatch < 128))  | 
666  | 0  |       { | 
667  |  |         /* 111110 + 6 lower bits of LengthOfMatch */  | 
668  | 0  |         accumulator = 0x0F80 | (LengthOfMatch & 0x003F);  | 
669  | 0  |         BitStream_Write_Bits(bs, accumulator, 12);  | 
670  | 0  |       }  | 
671  | 0  |       else if ((LengthOfMatch >= 128) && (LengthOfMatch < 256))  | 
672  | 0  |       { | 
673  |  |         /* 1111110 + 7 lower bits of LengthOfMatch */  | 
674  | 0  |         accumulator = 0x3F00 | (LengthOfMatch & 0x007F);  | 
675  | 0  |         BitStream_Write_Bits(bs, accumulator, 14);  | 
676  | 0  |       }  | 
677  | 0  |       else if ((LengthOfMatch >= 256) && (LengthOfMatch < 512))  | 
678  | 0  |       { | 
679  |  |         /* 11111110 + 8 lower bits of LengthOfMatch */  | 
680  | 0  |         accumulator = 0xFE00 | (LengthOfMatch & 0x00FF);  | 
681  | 0  |         BitStream_Write_Bits(bs, accumulator, 16);  | 
682  | 0  |       }  | 
683  | 0  |       else if ((LengthOfMatch >= 512) && (LengthOfMatch < 1024))  | 
684  | 0  |       { | 
685  |  |         /* 111111110 + 9 lower bits of LengthOfMatch */  | 
686  | 0  |         accumulator = 0x3FC00 | (LengthOfMatch & 0x01FF);  | 
687  | 0  |         BitStream_Write_Bits(bs, accumulator, 18);  | 
688  | 0  |       }  | 
689  | 0  |       else if ((LengthOfMatch >= 1024) && (LengthOfMatch < 2048))  | 
690  | 0  |       { | 
691  |  |         /* 1111111110 + 10 lower bits of LengthOfMatch */  | 
692  | 0  |         accumulator = 0xFF800 | (LengthOfMatch & 0x03FF);  | 
693  | 0  |         BitStream_Write_Bits(bs, accumulator, 20);  | 
694  | 0  |       }  | 
695  | 0  |       else if ((LengthOfMatch >= 2048) && (LengthOfMatch < 4096))  | 
696  | 0  |       { | 
697  |  |         /* 11111111110 + 11 lower bits of LengthOfMatch */  | 
698  | 0  |         accumulator = 0x3FF000 | (LengthOfMatch & 0x07FF);  | 
699  | 0  |         BitStream_Write_Bits(bs, accumulator, 22);  | 
700  | 0  |       }  | 
701  | 0  |       else if ((LengthOfMatch >= 4096) && (LengthOfMatch < 8192))  | 
702  | 0  |       { | 
703  |  |         /* 111111111110 + 12 lower bits of LengthOfMatch */  | 
704  | 0  |         accumulator = 0xFFE000 | (LengthOfMatch & 0x0FFF);  | 
705  | 0  |         BitStream_Write_Bits(bs, accumulator, 24);  | 
706  | 0  |       }  | 
707  | 0  |       else if (((LengthOfMatch >= 8192) && (LengthOfMatch < 16384)) &&  | 
708  | 0  |                CompressionLevel) /* RDP5 */  | 
709  | 0  |       { | 
710  |  |         /* 1111111111110 + 13 lower bits of LengthOfMatch */  | 
711  | 0  |         accumulator = 0x3FFC000 | (LengthOfMatch & 0x1FFF);  | 
712  | 0  |         BitStream_Write_Bits(bs, accumulator, 26);  | 
713  | 0  |       }  | 
714  | 0  |       else if (((LengthOfMatch >= 16384) && (LengthOfMatch < 32768)) &&  | 
715  | 0  |                CompressionLevel) /* RDP5 */  | 
716  | 0  |       { | 
717  |  |         /* 11111111111110 + 14 lower bits of LengthOfMatch */  | 
718  | 0  |         accumulator = 0xFFF8000 | (LengthOfMatch & 0x3FFF);  | 
719  | 0  |         BitStream_Write_Bits(bs, accumulator, 28);  | 
720  | 0  |       }  | 
721  | 0  |       else if (((LengthOfMatch >= 32768) && (LengthOfMatch < 65536)) &&  | 
722  | 0  |                CompressionLevel) /* RDP5 */  | 
723  | 0  |       { | 
724  |  |         /* 111111111111110 + 15 lower bits of LengthOfMatch */  | 
725  | 0  |         accumulator = 0x3FFF0000 | (LengthOfMatch & 0x7FFF);  | 
726  | 0  |         BitStream_Write_Bits(bs, accumulator, 30);  | 
727  | 0  |       }  | 
728  | 0  |     }  | 
729  | 0  |   }  | 
730  |  |  | 
731  |  |   /* Encode trailing symbols as literals */  | 
732  |  |  | 
733  | 0  |   while (pSrcPtr <= pSrcEnd)  | 
734  | 0  |   { | 
735  | 0  |     if (((bs->position / 8) + 2) > (DstSize - 1))  | 
736  | 0  |     { | 
737  | 0  |       mppc_context_reset(mppc, TRUE);  | 
738  | 0  |       *pFlags |= PACKET_FLUSHED;  | 
739  | 0  |       *pFlags |= CompressionLevel;  | 
740  | 0  |       *ppDstData = pSrcData;  | 
741  | 0  |       *pDstSize = SrcSize;  | 
742  | 0  |       return 1;  | 
743  | 0  |     }  | 
744  |  |  | 
745  | 0  |     accumulator = *pSrcPtr;  | 
746  |  | #if defined(DEBUG_MPPC)  | 
747  |  |     WLog_DBG(TAG, "%" PRIu32 "", accumulator);  | 
748  |  | #endif  | 
749  |  | 
  | 
750  | 0  |     if (accumulator < 0x80)  | 
751  | 0  |     { | 
752  |  |       /* 8 bits of literal are encoded as-is */  | 
753  | 0  |       BitStream_Write_Bits(bs, accumulator, 8);  | 
754  | 0  |     }  | 
755  | 0  |     else  | 
756  | 0  |     { | 
757  |  |       /* bits 10 followed by lower 7 bits of literal */  | 
758  | 0  |       accumulator = 0x100 | (accumulator & 0x7F);  | 
759  | 0  |       BitStream_Write_Bits(bs, accumulator, 9);  | 
760  | 0  |     }  | 
761  |  | 
  | 
762  | 0  |     *HistoryPtr++ = *pSrcPtr++;  | 
763  | 0  |   }  | 
764  |  |  | 
765  | 0  |   BitStream_Flush(bs);  | 
766  | 0  |   *pFlags |= PACKET_COMPRESSED;  | 
767  | 0  |   *pFlags |= CompressionLevel;  | 
768  |  | 
  | 
769  | 0  |   if (PacketAtFront)  | 
770  | 0  |     *pFlags |= PACKET_AT_FRONT;  | 
771  |  | 
  | 
772  | 0  |   if (PacketFlushed)  | 
773  | 0  |     *pFlags |= PACKET_FLUSHED;  | 
774  |  | 
  | 
775  | 0  |   *pDstSize = ((bs->position + 7) / 8);  | 
776  | 0  |   mppc->HistoryPtr = HistoryPtr;  | 
777  | 0  |   mppc->HistoryOffset = HistoryPtr - HistoryBuffer;  | 
778  | 0  |   return 1;  | 
779  | 0  | }  | 
780  |  |  | 
781  |  | void mppc_set_compression_level(MPPC_CONTEXT* mppc, DWORD CompressionLevel)  | 
782  | 677  | { | 
783  | 677  |   WINPR_ASSERT(mppc);  | 
784  |  |  | 
785  | 677  |   if (CompressionLevel < 1)  | 
786  | 238  |   { | 
787  | 238  |     mppc->CompressionLevel = 0;  | 
788  | 238  |     mppc->HistoryBufferSize = 8192;  | 
789  | 238  |   }  | 
790  | 439  |   else  | 
791  | 439  |   { | 
792  | 439  |     mppc->CompressionLevel = 1;  | 
793  | 439  |     mppc->HistoryBufferSize = 65536;  | 
794  | 439  |   }  | 
795  | 677  | }  | 
796  |  |  | 
797  |  | void mppc_context_reset(MPPC_CONTEXT* mppc, BOOL flush)  | 
798  | 106k  | { | 
799  | 106k  |   WINPR_ASSERT(mppc);  | 
800  |  |  | 
801  | 106k  |   ZeroMemory(&(mppc->HistoryBuffer), sizeof(mppc->HistoryBuffer));  | 
802  | 106k  |   ZeroMemory(&(mppc->MatchBuffer), sizeof(mppc->MatchBuffer));  | 
803  |  |  | 
804  | 106k  |   if (flush)  | 
805  | 0  |   { | 
806  | 0  |     mppc->HistoryOffset = mppc->HistoryBufferSize + 1;  | 
807  | 0  |     mppc->HistoryPtr = mppc->HistoryBuffer;  | 
808  | 0  |   }  | 
809  | 106k  |   else  | 
810  | 106k  |   { | 
811  | 106k  |     mppc->HistoryOffset = 0;  | 
812  | 106k  |     mppc->HistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryOffset]);  | 
813  | 106k  |   }  | 
814  | 106k  | }  | 
815  |  |  | 
816  |  | MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor)  | 
817  | 74.7k  | { | 
818  | 74.7k  |   MPPC_CONTEXT* mppc = calloc(1, sizeof(MPPC_CONTEXT));  | 
819  |  |  | 
820  | 74.7k  |   if (!mppc)  | 
821  | 0  |     goto fail;  | 
822  |  |  | 
823  | 74.7k  |   mppc->Compressor = Compressor;  | 
824  |  |  | 
825  | 74.7k  |   if (CompressionLevel < 1)  | 
826  | 5.40k  |   { | 
827  | 5.40k  |     mppc->CompressionLevel = 0;  | 
828  | 5.40k  |     mppc->HistoryBufferSize = 8192;  | 
829  | 5.40k  |   }  | 
830  | 69.2k  |   else  | 
831  | 69.2k  |   { | 
832  | 69.2k  |     mppc->CompressionLevel = 1;  | 
833  | 69.2k  |     mppc->HistoryBufferSize = 65536;  | 
834  | 69.2k  |   }  | 
835  |  |  | 
836  | 74.7k  |   mppc->bs = BitStream_New();  | 
837  |  |  | 
838  | 74.7k  |   if (!mppc->bs)  | 
839  | 0  |     goto fail;  | 
840  |  |  | 
841  | 74.7k  |   mppc_context_reset(mppc, FALSE);  | 
842  |  |  | 
843  | 74.7k  |   return mppc;  | 
844  |  |  | 
845  | 0  | fail:  | 
846  | 0  |   mppc_context_free(mppc);  | 
847  | 0  |   return NULL;  | 
848  | 74.7k  | }  | 
849  |  |  | 
850  |  | void mppc_context_free(MPPC_CONTEXT* mppc)  | 
851  | 74.7k  | { | 
852  | 74.7k  |   if (mppc)  | 
853  | 74.7k  |   { | 
854  | 74.7k  |     BitStream_Free(mppc->bs);  | 
855  | 74.7k  |     free(mppc);  | 
856  | 74.7k  |   }  | 
857  | 74.7k  | }  |