ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mppc.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.