Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmppc.c
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 8 -*- 00002 rdesktop: A Remote Desktop Protocol client. 00003 Protocol services - RDP decompression 00004 Copyright (C) Matthew Chapman 1999-2005 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License along 00017 with this program; if not, write to the Free Software Foundation, Inc., 00018 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00019 */ 00020 00021 #include <precomp.h> 00022 00023 /* mppc decompression */ 00024 /* http://www.faqs.org/rfcs/rfc2118.html */ 00025 00026 /* Contacts: */ 00027 00028 /* hifn contact mentioned in the faq is */ 00029 /* Robert Friend rfriend at hifn dot com */ 00030 00031 /* if you have questions regarding MPPC */ 00032 /* our contact is */ 00033 /* Guus Dhaeze GDhaeze at hifn dot com */ 00034 00035 /* Licensing: */ 00036 00037 /* decompression is alright as long as we */ 00038 /* don't compress data */ 00039 00040 /* Algorithm: */ 00041 00042 /* as the rfc states the algorithm seems to */ 00043 /* be LZ77 with a sliding buffer */ 00044 /* that is empty at init. */ 00045 00046 /* the algorithm is called LZS and is */ 00047 /* patented for another couple of years. */ 00048 00049 /* more information is available in */ 00050 /* http://www.ietf.org/ietf/IPR/hifn-ipr-draft-friend-tls-lzs-compression.txt */ 00051 00052 00053 RDPCOMP g_mppc_dict; 00054 00055 int 00056 mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen) 00057 { 00058 int k, walker_len = 0, walker; 00059 uint32 i = 0; 00060 int next_offset, match_off; 00061 int match_len; 00062 int old_offset, match_bits; 00063 BOOL big = ctype & RDP_MPPC_BIG ? True : False; 00064 00065 uint8 *dict = g_mppc_dict.hist; 00066 00067 if ((ctype & RDP_MPPC_COMPRESSED) == 0) 00068 { 00069 *roff = 0; 00070 *rlen = clen; 00071 return 0; 00072 } 00073 00074 if ((ctype & RDP_MPPC_RESET) != 0) 00075 { 00076 g_mppc_dict.roff = 0; 00077 } 00078 00079 if ((ctype & RDP_MPPC_FLUSH) != 0) 00080 { 00081 memset(dict, 0, RDP_MPPC_DICT_SIZE); 00082 g_mppc_dict.roff = 0; 00083 } 00084 00085 *roff = 0; 00086 *rlen = 0; 00087 00088 walker = g_mppc_dict.roff; 00089 00090 next_offset = walker; 00091 old_offset = next_offset; 00092 *roff = old_offset; 00093 if (clen == 0) 00094 return 0; 00095 clen += i; 00096 00097 do 00098 { 00099 if (walker_len == 0) 00100 { 00101 if (i >= clen) 00102 break; 00103 walker = data[i++] << 24; 00104 walker_len = 8; 00105 } 00106 if (walker >= 0) 00107 { 00108 if (walker_len < 8) 00109 { 00110 if (i >= clen) 00111 { 00112 if (walker != 0) 00113 return -1; 00114 break; 00115 } 00116 walker |= (data[i++] & 0xff) << (24 - walker_len); 00117 walker_len += 8; 00118 } 00119 if (next_offset >= RDP_MPPC_DICT_SIZE) 00120 return -1; 00121 dict[next_offset++] = (((uint32) walker) >> ((uint32) 24)); 00122 walker <<= 8; 00123 walker_len -= 8; 00124 continue; 00125 } 00126 walker <<= 1; 00127 /* fetch next 8-bits */ 00128 if (--walker_len == 0) 00129 { 00130 if (i >= clen) 00131 return -1; 00132 walker = data[i++] << 24; 00133 walker_len = 8; 00134 } 00135 /* literal decoding */ 00136 if (walker >= 0) 00137 { 00138 if (walker_len < 8) 00139 { 00140 if (i >= clen) 00141 return -1; 00142 walker |= (data[i++] & 0xff) << (24 - walker_len); 00143 walker_len += 8; 00144 } 00145 if (next_offset >= RDP_MPPC_DICT_SIZE) 00146 return -1; 00147 dict[next_offset++] = (uint8) (walker >> 24 | 0x80); 00148 walker <<= 8; 00149 walker_len -= 8; 00150 continue; 00151 } 00152 00153 /* decode offset */ 00154 /* length pair */ 00155 walker <<= 1; 00156 if (--walker_len < (big ? 3 : 2)) 00157 { 00158 if (i >= clen) 00159 return -1; 00160 walker |= (data[i++] & 0xff) << (24 - walker_len); 00161 walker_len += 8; 00162 } 00163 00164 if (big) 00165 { 00166 /* offset decoding where offset len is: 00167 -63: 11111 followed by the lower 6 bits of the value 00168 64-319: 11110 followed by the lower 8 bits of the value ( value - 64 ) 00169 320-2367: 1110 followed by lower 11 bits of the value ( value - 320 ) 00170 2368-65535: 110 followed by lower 16 bits of the value ( value - 2368 ) 00171 */ 00172 switch (((uint32) walker) >> ((uint32) 29)) 00173 { 00174 case 7: /* - 63 */ 00175 for (; walker_len < 9; walker_len += 8) 00176 { 00177 if (i >= clen) 00178 return -1; 00179 walker |= (data[i++] & 0xff) << (24 - walker_len); 00180 } 00181 walker <<= 3; 00182 match_off = ((uint32) walker) >> ((uint32) 26); 00183 walker <<= 6; 00184 walker_len -= 9; 00185 break; 00186 00187 case 6: /* 64 - 319 */ 00188 for (; walker_len < 11; walker_len += 8) 00189 { 00190 if (i >= clen) 00191 return -1; 00192 walker |= (data[i++] & 0xff) << (24 - walker_len); 00193 } 00194 00195 walker <<= 3; 00196 match_off = (((uint32) walker) >> ((uint32) 24)) + 64; 00197 walker <<= 8; 00198 walker_len -= 11; 00199 break; 00200 00201 case 5: 00202 case 4: /* 320 - 2367 */ 00203 for (; walker_len < 13; walker_len += 8) 00204 { 00205 if (i >= clen) 00206 return -1; 00207 walker |= (data[i++] & 0xff) << (24 - walker_len); 00208 } 00209 00210 walker <<= 2; 00211 match_off = (((uint32) walker) >> ((uint32) 21)) + 320; 00212 walker <<= 11; 00213 walker_len -= 13; 00214 break; 00215 00216 default: /* 2368 - 65535 */ 00217 for (; walker_len < 17; walker_len += 8) 00218 { 00219 if (i >= clen) 00220 return -1; 00221 walker |= (data[i++] & 0xff) << (24 - walker_len); 00222 } 00223 00224 walker <<= 1; 00225 match_off = (((uint32) walker) >> ((uint32) 16)) + 2368; 00226 walker <<= 16; 00227 walker_len -= 17; 00228 break; 00229 } 00230 } 00231 else 00232 { 00233 /* offset decoding where offset len is: 00234 -63: 1111 followed by the lower 6 bits of the value 00235 64-319: 1110 followed by the lower 8 bits of the value ( value - 64 ) 00236 320-8191: 110 followed by the lower 13 bits of the value ( value - 320 ) 00237 */ 00238 switch (((uint32) walker) >> ((uint32) 30)) 00239 { 00240 case 3: /* - 63 */ 00241 if (walker_len < 8) 00242 { 00243 if (i >= clen) 00244 return -1; 00245 walker |= (data[i++] & 0xff) << (24 - walker_len); 00246 walker_len += 8; 00247 } 00248 walker <<= 2; 00249 match_off = ((uint32) walker) >> ((uint32) 26); 00250 walker <<= 6; 00251 walker_len -= 8; 00252 break; 00253 00254 case 2: /* 64 - 319 */ 00255 for (; walker_len < 10; walker_len += 8) 00256 { 00257 if (i >= clen) 00258 return -1; 00259 walker |= (data[i++] & 0xff) << (24 - walker_len); 00260 } 00261 00262 walker <<= 2; 00263 match_off = (((uint32) walker) >> ((uint32) 24)) + 64; 00264 walker <<= 8; 00265 walker_len -= 10; 00266 break; 00267 00268 default: /* 320 - 8191 */ 00269 for (; walker_len < 14; walker_len += 8) 00270 { 00271 if (i >= clen) 00272 return -1; 00273 walker |= (data[i++] & 0xff) << (24 - walker_len); 00274 } 00275 00276 match_off = (walker >> 18) + 320; 00277 walker <<= 14; 00278 walker_len -= 14; 00279 break; 00280 } 00281 } 00282 if (walker_len == 0) 00283 { 00284 if (i >= clen) 00285 return -1; 00286 walker = data[i++] << 24; 00287 walker_len = 8; 00288 } 00289 00290 /* decode length of match */ 00291 match_len = 0; 00292 if (walker >= 0) 00293 { /* special case - length of 3 is in bit 0 */ 00294 match_len = 3; 00295 walker <<= 1; 00296 walker_len--; 00297 } 00298 else 00299 { 00300 /* this is how it works len of: 00301 4-7: 10 followed by 2 bits of the value 00302 8-15: 110 followed by 3 bits of the value 00303 16-31: 1110 followed by 4 bits of the value 00304 32-63: .... and so forth 00305 64-127: 00306 128-255: 00307 256-511: 00308 512-1023: 00309 1024-2047: 00310 2048-4095: 00311 4096-8191: 00312 00313 i.e. 4097 is encoded as: 111111111110 000000000001 00314 meaning 4096 + 1... 00315 */ 00316 match_bits = big ? 14 : 11; /* 11 or 14 bits of value at most */ 00317 do 00318 { 00319 walker <<= 1; 00320 if (--walker_len == 0) 00321 { 00322 if (i >= clen) 00323 return -1; 00324 walker = data[i++] << 24; 00325 walker_len = 8; 00326 } 00327 if (walker >= 0) 00328 break; 00329 if (--match_bits == 0) 00330 { 00331 return -1; 00332 } 00333 } 00334 while (1); 00335 match_len = (big ? 16 : 13) - match_bits; 00336 walker <<= 1; 00337 if (--walker_len < match_len) 00338 { 00339 for (; walker_len < match_len; walker_len += 8) 00340 { 00341 if (i >= clen) 00342 { 00343 return -1; 00344 } 00345 walker |= (data[i++] & 0xff) << (24 - walker_len); 00346 } 00347 } 00348 00349 match_bits = match_len; 00350 match_len = 00351 ((walker >> (32 - match_bits)) & (~(-1 << match_bits))) | (1 << 00352 match_bits); 00353 walker <<= match_bits; 00354 walker_len -= match_bits; 00355 } 00356 if (next_offset + match_len >= RDP_MPPC_DICT_SIZE) 00357 { 00358 return -1; 00359 } 00360 /* memory areas can overlap - meaning we can't use memXXX functions */ 00361 k = (next_offset - match_off) & (big ? 65535 : 8191); 00362 do 00363 { 00364 dict[next_offset++] = dict[k++]; 00365 } 00366 while (--match_len != 0); 00367 } 00368 while (1); 00369 00370 /* store history offset */ 00371 g_mppc_dict.roff = next_offset; 00372 00373 *roff = old_offset; 00374 *rlen = next_offset - old_offset; 00375 00376 return 0; 00377 } Generated on Sat May 26 2012 04:16:05 for ReactOS by
1.7.6.1
|