/src/libfsntfs/libfwnt/libfwnt_lzx.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * LZX (un)compression functions | 
| 3 |  |  * | 
| 4 |  |  * Copyright (C) 2009-2024, Joachim Metz <joachim.metz@gmail.com> | 
| 5 |  |  * | 
| 6 |  |  * Refer to AUTHORS for acknowledgements. | 
| 7 |  |  * | 
| 8 |  |  * This program is free software: you can redistribute it and/or modify | 
| 9 |  |  * it under the terms of the GNU Lesser General Public License as published by | 
| 10 |  |  * the Free Software Foundation, either version 3 of the License, or | 
| 11 |  |  * (at your option) any later version. | 
| 12 |  |  * | 
| 13 |  |  * This program is distributed in the hope that it will be useful, | 
| 14 |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 15 |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 16 |  |  * GNU General Public License for more details. | 
| 17 |  |  * | 
| 18 |  |  * You should have received a copy of the GNU Lesser General Public License | 
| 19 |  |  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | 
| 20 |  |  */ | 
| 21 |  |  | 
| 22 |  | #include <common.h> | 
| 23 |  | #include <byte_stream.h> | 
| 24 |  | #include <memory.h> | 
| 25 |  | #include <types.h> | 
| 26 |  |  | 
| 27 |  | #include "libfwnt_bit_stream.h" | 
| 28 |  | #include "libfwnt_huffman_tree.h" | 
| 29 |  | #include "libfwnt_libcerror.h" | 
| 30 |  | #include "libfwnt_libcnotify.h" | 
| 31 |  | #include "libfwnt_lzx.h" | 
| 32 |  |  | 
| 33 |  | #if !defined( LIBFWNT_LZX_ATTRIBUTE_FALLTHROUGH ) | 
| 34 |  | #if defined( __GNUC__ ) && __GNUC__ >= 7 | 
| 35 |  | #define LIBFWNT_LZX_ATTRIBUTE_FALLTHROUGH      __attribute__ ((fallthrough)) | 
| 36 |  | #else | 
| 37 |  | #define LIBFWNT_LZX_ATTRIBUTE_FALLTHROUGH | 
| 38 |  | #endif | 
| 39 |  | #endif | 
| 40 |  |  | 
| 41 |  | /* Base position - 2 | 
| 42 |  |  */ | 
| 43 |  | const int32_t libfwnt_lzx_compression_offset_base[ 50 ] = { | 
| 44 |  |   -2, -1, 0, 1, 2, 4, 6, 10, 14, 22, 30, 46, 62, 94, 126, 190, | 
| 45 |  |   254, 382, 510, 766, 1022, 1534, 2046, 3070, 4094, 6142, 8190, 12286, 16382, 24574, 32766, 49150, | 
| 46 |  |   65534, 98302, 131070, 196606, 262142, 393214, 524286, 655358, 786430, 917502, 1048574, 1179646, 1310718, 1441790, 1572862, 1703934, | 
| 47 |  |   1835006, 1966078 }; | 
| 48 |  |  | 
| 49 |  | const uint8_t libfwnt_lzx_number_of_footer_bits[ 50 ] = { | 
| 50 |  |   0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, | 
| 51 |  |   7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, | 
| 52 |  |   15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | 
| 53 |  |   17, 17, 17 }; | 
| 54 |  |  | 
| 55 |  | /* Reads the Huffman code sizes | 
| 56 |  |  * Returns 1 on success or -1 on error | 
| 57 |  |  */ | 
| 58 |  | int libfwnt_lzx_read_huffman_code_sizes( | 
| 59 |  |      libfwnt_bit_stream_t *bit_stream, | 
| 60 |  |      uint8_t *code_size_array, | 
| 61 |  |      int number_of_code_sizes, | 
| 62 |  |      libcerror_error_t **error ) | 
| 63 | 9.29k | { | 
| 64 | 9.29k |   uint8_t pre_code_size_array[ 20 ]; | 
| 65 |  |  | 
| 66 | 9.29k |   libfwnt_huffman_tree_t *pre_codes_huffman_tree = NULL; | 
| 67 | 9.29k |   static char *function                          = "libfwnt_lzx_read_huffman_code_sizes"; | 
| 68 | 9.29k |   uint32_t symbol                                = 0; | 
| 69 | 9.29k |   uint32_t times_to_repeat                       = 0; | 
| 70 | 9.29k |   uint32_t value_32bit                           = 0; | 
| 71 | 9.29k |   int32_t code_size                              = 0; | 
| 72 | 9.29k |   uint8_t pre_code_index                         = 0; | 
| 73 | 9.29k |   int code_size_index                            = 0; | 
| 74 |  |  | 
| 75 | 9.29k |   if( bit_stream == NULL ) | 
| 76 | 0 |   { | 
| 77 | 0 |     libcerror_error_set( | 
| 78 | 0 |      error, | 
| 79 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 80 | 0 |      LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, | 
| 81 | 0 |      "%s: invalid bit-stream.", | 
| 82 | 0 |      function ); | 
| 83 |  | 
 | 
| 84 | 0 |     return( -1 ); | 
| 85 | 0 |   } | 
| 86 | 9.29k |   for( pre_code_index = 0; | 
| 87 | 195k |        pre_code_index < 20; | 
| 88 | 185k |        pre_code_index++ ) | 
| 89 | 185k |   { | 
| 90 | 185k |     if( libfwnt_bit_stream_get_value( | 
| 91 | 185k |          bit_stream, | 
| 92 | 185k |          4, | 
| 93 | 185k |          &value_32bit, | 
| 94 | 185k |          error ) != 1 ) | 
| 95 | 0 |     { | 
| 96 | 0 |       libcerror_error_set( | 
| 97 | 0 |        error, | 
| 98 | 0 |        LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 99 | 0 |        LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 100 | 0 |        "%s: unable to retrieve pre-code: %" PRIu8 " size from bit stream.", | 
| 101 | 0 |        function, | 
| 102 | 0 |        pre_code_index ); | 
| 103 |  | 
 | 
| 104 | 0 |       goto on_error; | 
| 105 | 0 |     } | 
| 106 | 185k |     if( libcnotify_verbose != 0 ) | 
| 107 | 0 |     { | 
| 108 | 0 |       libcnotify_printf( | 
| 109 | 0 |        "%s: pre-code: % 2" PRIu8 " value\t\t\t: %" PRIu32 "\n", | 
| 110 | 0 |        function, | 
| 111 | 0 |        pre_code_index, | 
| 112 | 0 |        value_32bit) ; | 
| 113 | 0 |     } | 
| 114 | 185k |     pre_code_size_array[ pre_code_index ] = (uint8_t) value_32bit; | 
| 115 | 185k |   } | 
| 116 | 9.29k |   if( libcnotify_verbose != 0 ) | 
| 117 | 0 |   { | 
| 118 | 0 |     libcnotify_printf( | 
| 119 | 0 |      "\n" ); | 
| 120 | 0 |   } | 
| 121 | 9.29k |   if( libfwnt_huffman_tree_initialize( | 
| 122 | 9.29k |        &pre_codes_huffman_tree, | 
| 123 | 9.29k |        20, | 
| 124 | 9.29k |        15, | 
| 125 | 9.29k |        error ) != 1 ) | 
| 126 | 0 |   { | 
| 127 | 0 |     libcerror_error_set( | 
| 128 | 0 |      error, | 
| 129 | 0 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 130 | 0 |      LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 131 | 0 |      "%s: unable to create pre-codes Huffman tree.", | 
| 132 | 0 |      function ); | 
| 133 |  | 
 | 
| 134 | 0 |     goto on_error; | 
| 135 | 0 |   } | 
| 136 | 9.29k |   if( libfwnt_huffman_tree_build( | 
| 137 | 9.29k |        pre_codes_huffman_tree, | 
| 138 | 9.29k |        pre_code_size_array, | 
| 139 | 9.29k |        20, | 
| 140 | 9.29k |        error ) != 1 ) | 
| 141 | 169 |   { | 
| 142 | 169 |     libcerror_error_set( | 
| 143 | 169 |      error, | 
| 144 | 169 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 145 | 169 |      LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 146 | 169 |      "%s: unable to build pre-codes Huffman tree.", | 
| 147 | 169 |      function ); | 
| 148 |  |  | 
| 149 | 169 |     goto on_error; | 
| 150 | 169 |   } | 
| 151 | 9.12k |   code_size_index = 0; | 
| 152 |  |  | 
| 153 | 150k |   while( code_size_index < number_of_code_sizes ) | 
| 154 | 141k |   { | 
| 155 | 141k |     if( libfwnt_huffman_tree_get_symbol_from_bit_stream( | 
| 156 | 141k |          pre_codes_huffman_tree, | 
| 157 | 141k |          bit_stream, | 
| 158 | 141k |          &symbol, | 
| 159 | 141k |          error ) != 1 ) | 
| 160 | 43 |     { | 
| 161 | 43 |       libcerror_error_set( | 
| 162 | 43 |        error, | 
| 163 | 43 |        LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 164 | 43 |        LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 165 | 43 |        "%s: unable to retrieve symbol from pre-codes Huffman tree.", | 
| 166 | 43 |        function ); | 
| 167 |  |  | 
| 168 | 43 |       goto on_error; | 
| 169 | 43 |     } | 
| 170 | 140k |     if( libcnotify_verbose != 0 ) | 
| 171 | 0 |     { | 
| 172 | 0 |       libcnotify_printf( | 
| 173 | 0 |        "%s: code size: % 3" PRIu32 " symbol\t\t: %" PRIu32 "\n", | 
| 174 | 0 |        function, | 
| 175 | 0 |        code_size_index, | 
| 176 | 0 |        symbol ); | 
| 177 | 0 |     } | 
| 178 | 140k |     if( symbol < 17 ) | 
| 179 | 82.6k |     { | 
| 180 | 82.6k |       code_size = code_size_array[ code_size_index ] - symbol; | 
| 181 |  |  | 
| 182 | 82.6k |       if( code_size < 0 ) | 
| 183 | 58.8k |       { | 
| 184 | 58.8k |         code_size += 17; | 
| 185 | 58.8k |       } | 
| 186 | 82.6k |       if( libcnotify_verbose != 0 ) | 
| 187 | 0 |       { | 
| 188 | 0 |         libcnotify_printf( | 
| 189 | 0 |          "%s: code size: % 3" PRIu32 " value\t\t: %" PRIi32 "\n", | 
| 190 | 0 |          function, | 
| 191 | 0 |          code_size_index, | 
| 192 | 0 |          code_size ); | 
| 193 | 0 |       } | 
| 194 | 82.6k |       code_size_array[ code_size_index++ ] = (uint8_t) code_size; | 
| 195 |  |  | 
| 196 | 82.6k |       continue; | 
| 197 | 82.6k |     } | 
| 198 | 58.2k |     code_size = 0; | 
| 199 |  |  | 
| 200 | 58.2k |     if( symbol == 17 ) | 
| 201 | 1.12k |     { | 
| 202 | 1.12k |       if( libfwnt_bit_stream_get_value( | 
| 203 | 1.12k |            bit_stream, | 
| 204 | 1.12k |            4, | 
| 205 | 1.12k |            ×_to_repeat, | 
| 206 | 1.12k |            error ) != 1 ) | 
| 207 | 0 |       { | 
| 208 | 0 |         libcerror_error_set( | 
| 209 | 0 |          error, | 
| 210 | 0 |          LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 211 | 0 |          LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 212 | 0 |          "%s: unable to retrieve times to repeat from bit stream.", | 
| 213 | 0 |          function ); | 
| 214 |  | 
 | 
| 215 | 0 |         goto on_error; | 
| 216 | 0 |       } | 
| 217 | 1.12k |       times_to_repeat += 4; | 
| 218 | 1.12k |     } | 
| 219 | 57.1k |     else if( symbol == 18 ) | 
| 220 | 56.4k |     { | 
| 221 | 56.4k |       if( libfwnt_bit_stream_get_value( | 
| 222 | 56.4k |            bit_stream, | 
| 223 | 56.4k |            5, | 
| 224 | 56.4k |            ×_to_repeat, | 
| 225 | 56.4k |            error ) != 1 ) | 
| 226 | 0 |       { | 
| 227 | 0 |         libcerror_error_set( | 
| 228 | 0 |          error, | 
| 229 | 0 |          LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 230 | 0 |          LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 231 | 0 |          "%s: unable to retrieve times to repeat from bit stream.", | 
| 232 | 0 |          function ); | 
| 233 |  | 
 | 
| 234 | 0 |         goto on_error; | 
| 235 | 0 |       } | 
| 236 | 56.4k |       times_to_repeat += 20; | 
| 237 | 56.4k |     } | 
| 238 | 717 |     else if( symbol == 19 ) | 
| 239 | 717 |     { | 
| 240 | 717 |       if( libfwnt_bit_stream_get_value( | 
| 241 | 717 |            bit_stream, | 
| 242 | 717 |            1, | 
| 243 | 717 |            ×_to_repeat, | 
| 244 | 717 |            error ) != 1 ) | 
| 245 | 0 |       { | 
| 246 | 0 |         libcerror_error_set( | 
| 247 | 0 |          error, | 
| 248 | 0 |          LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 249 | 0 |          LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 250 | 0 |          "%s: unable to retrieve times to repeat from bit stream.", | 
| 251 | 0 |          function ); | 
| 252 |  | 
 | 
| 253 | 0 |         goto on_error; | 
| 254 | 0 |       } | 
| 255 | 717 |       times_to_repeat += 4; | 
| 256 |  |  | 
| 257 | 717 |       if( libfwnt_huffman_tree_get_symbol_from_bit_stream( | 
| 258 | 717 |            pre_codes_huffman_tree, | 
| 259 | 717 |            bit_stream, | 
| 260 | 717 |            &symbol, | 
| 261 | 717 |            error ) != 1 ) | 
| 262 | 2 |       { | 
| 263 | 2 |         libcerror_error_set( | 
| 264 | 2 |          error, | 
| 265 | 2 |          LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 266 | 2 |          LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 267 | 2 |          "%s: unable to retrieve symbol from pre-codes Huffman tree.", | 
| 268 | 2 |          function ); | 
| 269 |  |  | 
| 270 | 2 |         goto on_error; | 
| 271 | 2 |       } | 
| 272 | 715 |       if( symbol > 17 ) | 
| 273 | 8 |       { | 
| 274 | 8 |         libcerror_error_set( | 
| 275 | 8 |          error, | 
| 276 | 8 |          LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 277 | 8 |          LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, | 
| 278 | 8 |          "%s: invalid code size symbol value out of bounds.", | 
| 279 | 8 |          function ); | 
| 280 |  |  | 
| 281 | 8 |         goto on_error; | 
| 282 | 8 |       } | 
| 283 | 707 |       code_size = code_size_array[ code_size_index ] - symbol; | 
| 284 |  |  | 
| 285 | 707 |       if( code_size < 0 ) | 
| 286 | 401 |       { | 
| 287 | 401 |         code_size += 17; | 
| 288 | 401 |       } | 
| 289 | 707 |     } | 
| 290 | 0 |     else | 
| 291 | 0 |     { | 
| 292 | 0 |       libcerror_error_set( | 
| 293 | 0 |        error, | 
| 294 | 0 |        LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 295 | 0 |        LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, | 
| 296 | 0 |        "%s: invalid code size symbol value out of bounds.", | 
| 297 | 0 |        function ); | 
| 298 |  | 
 | 
| 299 | 0 |       goto on_error; | 
| 300 | 0 |     } | 
| 301 | 58.2k |     if( libcnotify_verbose != 0 ) | 
| 302 | 0 |     { | 
| 303 | 0 |       libcnotify_printf( | 
| 304 | 0 |        "%s: times to repeat\t\t\t: %" PRIu32 "\n", | 
| 305 | 0 |        function, | 
| 306 | 0 |        times_to_repeat ); | 
| 307 | 0 |     } | 
| 308 | 58.2k |     if( times_to_repeat > (uint32_t) ( number_of_code_sizes - code_size_index ) ) | 
| 309 | 6.87k |     { | 
| 310 | 6.87k |       if( libcnotify_verbose != 0 ) | 
| 311 | 0 |       { | 
| 312 | 0 |         libcnotify_printf( | 
| 313 | 0 |          "%s: times to repeat value out of bounds.\n", | 
| 314 | 0 |          function ); | 
| 315 | 0 |       } | 
| 316 | 6.87k |       times_to_repeat = (uint32_t) ( number_of_code_sizes - code_size_index ); | 
| 317 | 6.87k |     } | 
| 318 | 2.23M |     while( times_to_repeat > 0 ) | 
| 319 | 2.17M |     { | 
| 320 | 2.17M |       if( libcnotify_verbose != 0 ) | 
| 321 | 0 |       { | 
| 322 | 0 |         libcnotify_printf( | 
| 323 | 0 |          "%s: code size: % 3" PRIu32 " value\t\t: %" PRIi32 "\n", | 
| 324 | 0 |          function, | 
| 325 | 0 |          code_size_index, | 
| 326 | 0 |          code_size ); | 
| 327 | 0 |       } | 
| 328 | 2.17M |       code_size_array[ code_size_index++ ] = (uint8_t) code_size; | 
| 329 |  |  | 
| 330 | 2.17M |       times_to_repeat--; | 
| 331 | 2.17M |     } | 
| 332 | 58.2k |   } | 
| 333 | 9.07k |   if( libfwnt_huffman_tree_free( | 
| 334 | 9.07k |        &pre_codes_huffman_tree, | 
| 335 | 9.07k |        error ) != 1 ) | 
| 336 | 0 |   { | 
| 337 | 0 |     libcerror_error_set( | 
| 338 | 0 |      error, | 
| 339 | 0 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 340 | 0 |      LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, | 
| 341 | 0 |      "%s: unable to free pre-codes Huffman tree.", | 
| 342 | 0 |      function ); | 
| 343 |  | 
 | 
| 344 | 0 |     goto on_error; | 
| 345 | 0 |   } | 
| 346 | 9.07k |   if( libcnotify_verbose != 0 ) | 
| 347 | 0 |   { | 
| 348 | 0 |     libcnotify_printf( | 
| 349 | 0 |      "\n" ); | 
| 350 | 0 |   } | 
| 351 | 9.07k |   return( 1 ); | 
| 352 |  |  | 
| 353 | 222 | on_error: | 
| 354 | 222 |   if( pre_codes_huffman_tree != NULL ) | 
| 355 | 222 |   { | 
| 356 | 222 |     libfwnt_huffman_tree_free( | 
| 357 | 222 |      &pre_codes_huffman_tree, | 
| 358 | 222 |      NULL ); | 
| 359 | 222 |   } | 
| 360 | 222 |   return( -1 ); | 
| 361 | 9.07k | } | 
| 362 |  |  | 
| 363 |  | /* Reads and builds the literals and match headers Huffman tree | 
| 364 |  |  * Returns 1 on success or -1 on error | 
| 365 |  |  */ | 
| 366 |  | int libfwnt_lzx_build_main_huffman_tree( | 
| 367 |  |      libfwnt_bit_stream_t *bit_stream, | 
| 368 |  |      uint8_t *code_size_array, | 
| 369 |  |      libfwnt_huffman_tree_t *huffman_tree, | 
| 370 |  |      libcerror_error_t **error ) | 
| 371 | 3.18k | { | 
| 372 | 3.18k |   static char *function = "libfwnt_lzx_build_main_huffman_tree"; | 
| 373 |  |  | 
| 374 | 3.18k |   if( libfwnt_lzx_read_huffman_code_sizes( | 
| 375 | 3.18k |        bit_stream, | 
| 376 | 3.18k |        code_size_array, | 
| 377 | 3.18k |        256, | 
| 378 | 3.18k |        error ) != 1 ) | 
| 379 | 74 |   { | 
| 380 | 74 |     libcerror_error_set( | 
| 381 | 74 |      error, | 
| 382 | 74 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 383 | 74 |      LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 384 | 74 |      "%s: unable to read literals Huffman code sizes.", | 
| 385 | 74 |      function ); | 
| 386 |  |  | 
| 387 | 74 |     return( -1 ); | 
| 388 | 74 |   } | 
| 389 | 3.11k |   if( libfwnt_lzx_read_huffman_code_sizes( | 
| 390 | 3.11k |        bit_stream, | 
| 391 | 3.11k |        &( code_size_array[ 256 ] ), | 
| 392 | 3.11k |        240, | 
| 393 | 3.11k |        error ) != 1 ) | 
| 394 | 111 |   { | 
| 395 | 111 |     libcerror_error_set( | 
| 396 | 111 |      error, | 
| 397 | 111 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 398 | 111 |      LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 399 | 111 |      "%s: unable to read literals Huffman code sizes.", | 
| 400 | 111 |      function ); | 
| 401 |  |  | 
| 402 | 111 |     return( -1 ); | 
| 403 | 111 |   } | 
| 404 | 3.00k |   if( libfwnt_huffman_tree_build( | 
| 405 | 3.00k |        huffman_tree, | 
| 406 | 3.00k |        code_size_array, | 
| 407 | 3.00k |        256 + 240, | 
| 408 | 3.00k |        error ) != 1 ) | 
| 409 | 14 |   { | 
| 410 | 14 |     libcerror_error_set( | 
| 411 | 14 |      error, | 
| 412 | 14 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 413 | 14 |      LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 414 | 14 |      "%s: unable to build literals and match headers Huffman tree.", | 
| 415 | 14 |      function ); | 
| 416 |  |  | 
| 417 | 14 |     return( -1 ); | 
| 418 | 14 |   } | 
| 419 | 2.99k |   return( 1 ); | 
| 420 | 3.00k | } | 
| 421 |  |  | 
| 422 |  | /* Reads and builds the lengths Huffman tree | 
| 423 |  |  * Returns 1 on success or -1 on error | 
| 424 |  |  */ | 
| 425 |  | int libfwnt_lzx_build_lengths_huffman_tree( | 
| 426 |  |      libfwnt_bit_stream_t *bit_stream, | 
| 427 |  |      uint8_t *code_size_array, | 
| 428 |  |      libfwnt_huffman_tree_t *huffman_tree, | 
| 429 |  |      libcerror_error_t **error ) | 
| 430 | 2.99k | { | 
| 431 | 2.99k |   static char *function = "libfwnt_lzx_build_lengths_huffman_tree"; | 
| 432 |  |  | 
| 433 | 2.99k |   if( libfwnt_lzx_read_huffman_code_sizes( | 
| 434 | 2.99k |        bit_stream, | 
| 435 | 2.99k |        code_size_array, | 
| 436 | 2.99k |        249, | 
| 437 | 2.99k |        error ) != 1 ) | 
| 438 | 37 |   { | 
| 439 | 37 |     libcerror_error_set( | 
| 440 | 37 |      error, | 
| 441 | 37 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 442 | 37 |      LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 443 | 37 |      "%s: unable to read literals Huffman code sizes.", | 
| 444 | 37 |      function ); | 
| 445 |  |  | 
| 446 | 37 |     return( -1 ); | 
| 447 | 37 |   } | 
| 448 | 2.95k |   if( libfwnt_huffman_tree_build( | 
| 449 | 2.95k |        huffman_tree, | 
| 450 | 2.95k |        code_size_array, | 
| 451 | 2.95k |        249, | 
| 452 | 2.95k |        error ) != 1 ) | 
| 453 | 7 |   { | 
| 454 | 7 |     libcerror_error_set( | 
| 455 | 7 |      error, | 
| 456 | 7 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 457 | 7 |      LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 458 | 7 |      "%s: unable to build lengths Huffman tree.", | 
| 459 | 7 |      function ); | 
| 460 |  |  | 
| 461 | 7 |     return( -1 ); | 
| 462 | 7 |   } | 
| 463 | 2.94k |   return( 1 ); | 
| 464 | 2.95k | } | 
| 465 |  |  | 
| 466 |  | /* Reads and builds the aligned offsets Huffman tree | 
| 467 |  |  * Returns 1 on success or -1 on error | 
| 468 |  |  */ | 
| 469 |  | int libfwnt_lzx_build_aligned_offsets_huffman_tree( | 
| 470 |  |      libfwnt_bit_stream_t *bit_stream, | 
| 471 |  |      uint8_t *code_size_array, | 
| 472 |  |      libfwnt_huffman_tree_t *huffman_tree, | 
| 473 |  |      libcerror_error_t **error ) | 
| 474 | 1.12k | { | 
| 475 | 1.12k |   static char *function = "libfwnt_lzx_build_aligned_offsets_huffman_tree"; | 
| 476 | 1.12k |   uint32_t code_size    = 0; | 
| 477 | 1.12k |   int code_size_index   = 0; | 
| 478 |  |  | 
| 479 | 1.12k |   for( code_size_index = 0; | 
| 480 | 10.1k |        code_size_index < 8; | 
| 481 | 9.02k |        code_size_index++ ) | 
| 482 | 9.02k |   { | 
| 483 | 9.02k |     if( libfwnt_bit_stream_get_value( | 
| 484 | 9.02k |          bit_stream, | 
| 485 | 9.02k |          3, | 
| 486 | 9.02k |          &code_size, | 
| 487 | 9.02k |          error ) != 1 ) | 
| 488 | 0 |     { | 
| 489 | 0 |       libcerror_error_set( | 
| 490 | 0 |        error, | 
| 491 | 0 |        LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 492 | 0 |        LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 493 | 0 |        "%s: unable to retrieve value from bit stream.", | 
| 494 | 0 |        function ); | 
| 495 |  | 
 | 
| 496 | 0 |       return( -1 ); | 
| 497 | 0 |     } | 
| 498 | 9.02k |     if( libcnotify_verbose != 0 ) | 
| 499 | 0 |     { | 
| 500 | 0 |       libcnotify_printf( | 
| 501 | 0 |        "%s: code size: % 2d value\t: %" PRIu32 "\n", | 
| 502 | 0 |        function, | 
| 503 | 0 |        code_size_index, | 
| 504 | 0 |        code_size ); | 
| 505 | 0 |     } | 
| 506 | 9.02k |     code_size_array[ code_size_index ] = (uint8_t) code_size; | 
| 507 | 9.02k |   } | 
| 508 | 1.12k |   if( libfwnt_huffman_tree_build( | 
| 509 | 1.12k |        huffman_tree, | 
| 510 | 1.12k |        code_size_array, | 
| 511 | 1.12k |        8, | 
| 512 | 1.12k |        error ) != 1 ) | 
| 513 | 7 |   { | 
| 514 | 7 |     libcerror_error_set( | 
| 515 | 7 |      error, | 
| 516 | 7 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 517 | 7 |      LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 518 | 7 |      "%s: unable to build aligned offsets Huffman tree.", | 
| 519 | 7 |      function ); | 
| 520 |  |  | 
| 521 | 7 |     return( -1 ); | 
| 522 | 7 |   } | 
| 523 | 1.12k |   return( 1 ); | 
| 524 | 1.12k | } | 
| 525 |  |  | 
| 526 |  | /* Decodes a Huffman compressed block | 
| 527 |  |  * Returns 1 on success or -1 on error | 
| 528 |  |  */ | 
| 529 |  | int libfwnt_lzx_decode_huffman( | 
| 530 |  |      libfwnt_bit_stream_t *bit_stream, | 
| 531 |  |      uint32_t block_size, | 
| 532 |  |      libfwnt_huffman_tree_t *main_huffman_tree, | 
| 533 |  |      libfwnt_huffman_tree_t *lengths_huffman_tree, | 
| 534 |  |      libfwnt_huffman_tree_t *aligned_offsets_huffman_tree, | 
| 535 |  |      uint32_t *recent_compression_offsets, | 
| 536 |  |      uint8_t *uncompressed_data, | 
| 537 |  |      size_t uncompressed_data_size, | 
| 538 |  |      size_t *uncompressed_data_offset, | 
| 539 |  |      libcerror_error_t **error ) | 
| 540 | 2.94k | { | 
| 541 | 2.94k |   static char *function            = "libfwnt_lzx_decode_huffman"; | 
| 542 | 2.94k |   size_t data_end_offset           = 0; | 
| 543 | 2.94k |   size_t data_offset               = 0; | 
| 544 | 2.94k |   uint32_t aligned_offset          = 0; | 
| 545 | 2.94k |   uint32_t compression_offset      = 0; | 
| 546 | 2.94k |   uint32_t compression_offset_slot = 0; | 
| 547 | 2.94k |   uint32_t compression_size        = 0; | 
| 548 | 2.94k |   uint32_t symbol                  = 0; | 
| 549 | 2.94k |   uint8_t number_of_bits           = 0; | 
| 550 |  |  | 
| 551 | 2.94k |   if( recent_compression_offsets == NULL ) | 
| 552 | 0 |   { | 
| 553 | 0 |     libcerror_error_set( | 
| 554 | 0 |      error, | 
| 555 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 556 | 0 |      LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, | 
| 557 | 0 |      "%s: invalid recent compression offsets.", | 
| 558 | 0 |      function ); | 
| 559 |  | 
 | 
| 560 | 0 |     return( -1 ); | 
| 561 | 0 |   } | 
| 562 | 2.94k |   if( uncompressed_data == NULL ) | 
| 563 | 0 |   { | 
| 564 | 0 |     libcerror_error_set( | 
| 565 | 0 |      error, | 
| 566 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 567 | 0 |      LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, | 
| 568 | 0 |      "%s: invalid uncompressed data.", | 
| 569 | 0 |      function ); | 
| 570 |  | 
 | 
| 571 | 0 |     return( -1 ); | 
| 572 | 0 |   } | 
| 573 | 2.94k |   if( uncompressed_data_size > (size_t) SSIZE_MAX ) | 
| 574 | 0 |   { | 
| 575 | 0 |     libcerror_error_set( | 
| 576 | 0 |      error, | 
| 577 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 578 | 0 |      LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, | 
| 579 | 0 |      "%s: invalid uncompressed data size value exceeds maximum.", | 
| 580 | 0 |      function ); | 
| 581 |  | 
 | 
| 582 | 0 |     return( -1 ); | 
| 583 | 0 |   } | 
| 584 | 2.94k |   if( uncompressed_data_offset == NULL ) | 
| 585 | 0 |   { | 
| 586 | 0 |     libcerror_error_set( | 
| 587 | 0 |      error, | 
| 588 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 589 | 0 |      LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, | 
| 590 | 0 |      "%s: invalid uncompressed data offset.", | 
| 591 | 0 |      function ); | 
| 592 |  | 
 | 
| 593 | 0 |     return( -1 ); | 
| 594 | 0 |   } | 
| 595 | 2.94k |   data_offset     = *uncompressed_data_offset; | 
| 596 | 2.94k |   data_end_offset = data_offset + block_size; | 
| 597 |  |  | 
| 598 | 2.77M |   while( data_offset < data_end_offset ) | 
| 599 | 2.77M |   { | 
| 600 | 2.77M |     if( libfwnt_huffman_tree_get_symbol_from_bit_stream( | 
| 601 | 2.77M |          main_huffman_tree, | 
| 602 | 2.77M |          bit_stream, | 
| 603 | 2.77M |          &symbol, | 
| 604 | 2.77M |          error ) != 1 ) | 
| 605 | 5 |     { | 
| 606 | 5 |       libcerror_error_set( | 
| 607 | 5 |        error, | 
| 608 | 5 |        LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 609 | 5 |        LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 610 | 5 |        "%s: unable to retrieve symbol from literals and match headers Huffman tree.", | 
| 611 | 5 |        function ); | 
| 612 |  |  | 
| 613 | 5 |       return( -1 ); | 
| 614 | 5 |     } | 
| 615 | 2.77M |     if( libcnotify_verbose != 0 ) | 
| 616 | 0 |     { | 
| 617 | 0 |       libcnotify_printf( | 
| 618 | 0 |        "%s: symbol\t\t\t\t\t: %" PRIu32 "\n", | 
| 619 | 0 |        function, | 
| 620 | 0 |        symbol ); | 
| 621 | 0 |     } | 
| 622 | 2.77M |     if( symbol < 256 ) | 
| 623 | 2.51M |     { | 
| 624 | 2.51M |       if( data_offset >= uncompressed_data_size ) | 
| 625 | 1 |       { | 
| 626 | 1 |         libcerror_error_set( | 
| 627 | 1 |          error, | 
| 628 | 1 |          LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 629 | 1 |          LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, | 
| 630 | 1 |          "%s: invalid uncompressed data value too small.", | 
| 631 | 1 |          function ); | 
| 632 |  |  | 
| 633 | 1 |         return( -1 ); | 
| 634 | 1 |       } | 
| 635 | 2.51M |       uncompressed_data[ data_offset++ ] = (uint8_t) symbol; | 
| 636 | 2.51M |     } | 
| 637 | 263k |     else | 
| 638 | 263k |     { | 
| 639 | 263k |       compression_size        = symbol % 8; | 
| 640 | 263k |       compression_offset_slot = ( symbol - 256 ) / 8; | 
| 641 |  |  | 
| 642 | 263k |       if( compression_size == 7 ) | 
| 643 | 51.3k |       { | 
| 644 | 51.3k |         if( libfwnt_huffman_tree_get_symbol_from_bit_stream( | 
| 645 | 51.3k |              lengths_huffman_tree, | 
| 646 | 51.3k |              bit_stream, | 
| 647 | 51.3k |              &compression_size, | 
| 648 | 51.3k |              error ) != 1 ) | 
| 649 | 2 |         { | 
| 650 | 2 |           libcerror_error_set( | 
| 651 | 2 |            error, | 
| 652 | 2 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 653 | 2 |            LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 654 | 2 |            "%s: unable to retrieve symbol from lengths Huffman tree.", | 
| 655 | 2 |            function ); | 
| 656 |  |  | 
| 657 | 2 |           return( -1 ); | 
| 658 | 2 |         } | 
| 659 | 51.3k |         compression_size += 7; | 
| 660 | 51.3k |       } | 
| 661 | 263k |       compression_size += 2; | 
| 662 |  |  | 
| 663 | 263k |       if( compression_offset_slot < 3 ) | 
| 664 | 56.2k |       { | 
| 665 | 56.2k |         compression_offset = recent_compression_offsets[ compression_offset_slot ]; | 
| 666 |  |  | 
| 667 | 56.2k |         recent_compression_offsets[ compression_offset_slot ] = recent_compression_offsets[ 0 ]; | 
| 668 | 56.2k |       } | 
| 669 | 207k |       else | 
| 670 | 207k |       { | 
| 671 | 207k |         number_of_bits = libfwnt_lzx_number_of_footer_bits[ compression_offset_slot ]; | 
| 672 |  |  | 
| 673 | 207k |         if( ( aligned_offsets_huffman_tree != NULL ) | 
| 674 | 207k |          && ( compression_offset_slot >= 8 ) ) | 
| 675 | 1.11k |         { | 
| 676 | 1.11k |           number_of_bits -= 3; | 
| 677 | 1.11k |         } | 
| 678 | 207k |         if( libcnotify_verbose != 0 ) | 
| 679 | 0 |         { | 
| 680 | 0 |           libcnotify_printf( | 
| 681 | 0 |            "%s: number of footer bits\t\t\t: %" PRIu8 "\n", | 
| 682 | 0 |            function, | 
| 683 | 0 |            number_of_bits ); | 
| 684 | 0 |         } | 
| 685 | 207k |         if( libfwnt_bit_stream_get_value( | 
| 686 | 207k |              bit_stream, | 
| 687 | 207k |              number_of_bits, | 
| 688 | 207k |              &compression_offset, | 
| 689 | 207k |              error ) != 1 ) | 
| 690 | 0 |         { | 
| 691 | 0 |           libcerror_error_set( | 
| 692 | 0 |            error, | 
| 693 | 0 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 694 | 0 |            LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 695 | 0 |            "%s: unable to retrieve compression offset from bit stream.", | 
| 696 | 0 |            function ); | 
| 697 |  | 
 | 
| 698 | 0 |           return( -1 ); | 
| 699 | 0 |         } | 
| 700 | 207k |         if( ( aligned_offsets_huffman_tree != NULL ) | 
| 701 | 207k |          && ( compression_offset_slot >= 8 ) ) | 
| 702 | 1.11k |         { | 
| 703 | 1.11k |           if( libfwnt_huffman_tree_get_symbol_from_bit_stream( | 
| 704 | 1.11k |                aligned_offsets_huffman_tree, | 
| 705 | 1.11k |                bit_stream, | 
| 706 | 1.11k |                &aligned_offset, | 
| 707 | 1.11k |                error ) != 1 ) | 
| 708 | 1 |           { | 
| 709 | 1 |             libcerror_error_set( | 
| 710 | 1 |              error, | 
| 711 | 1 |              LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 712 | 1 |              LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 713 | 1 |              "%s: unable to retrieve symbol from literals and match headers Huffman tree.", | 
| 714 | 1 |              function ); | 
| 715 |  |  | 
| 716 | 1 |             return( -1 ); | 
| 717 | 1 |           } | 
| 718 | 1.11k |           if( libcnotify_verbose != 0 ) | 
| 719 | 0 |           { | 
| 720 | 0 |             libcnotify_printf( | 
| 721 | 0 |              "%s: aligned offset\t\t\t\t: %" PRIu32 "\n", | 
| 722 | 0 |              function, | 
| 723 | 0 |              aligned_offset ); | 
| 724 | 0 |           } | 
| 725 | 1.11k |           compression_offset <<= 3; | 
| 726 | 1.11k |           compression_offset  |= aligned_offset; | 
| 727 | 1.11k |         } | 
| 728 | 207k |         compression_offset += libfwnt_lzx_compression_offset_base[ compression_offset_slot ]; | 
| 729 |  |  | 
| 730 | 207k |         recent_compression_offsets[ 2 ] = recent_compression_offsets[ 1 ]; | 
| 731 | 207k |         recent_compression_offsets[ 1 ] = recent_compression_offsets[ 0 ]; | 
| 732 | 207k |       } | 
| 733 | 263k |       recent_compression_offsets[ 0 ] = compression_offset; | 
| 734 |  |  | 
| 735 | 263k |       if( libcnotify_verbose != 0 ) | 
| 736 | 0 |       { | 
| 737 | 0 |         libcnotify_printf( | 
| 738 | 0 |          "%s: compression size\t\t\t\t: %" PRIu32 "\n", | 
| 739 | 0 |          function, | 
| 740 | 0 |          compression_size ); | 
| 741 |  | 
 | 
| 742 | 0 |         libcnotify_printf( | 
| 743 | 0 |          "%s: compression offset slot\t\t\t: %" PRIu32 "\n", | 
| 744 | 0 |          function, | 
| 745 | 0 |          compression_offset_slot ); | 
| 746 |  | 
 | 
| 747 | 0 |         libcnotify_printf( | 
| 748 | 0 |          "%s: compression offset\t\t\t\t: %" PRIu32 "\n", | 
| 749 | 0 |          function, | 
| 750 | 0 |          compression_offset ); | 
| 751 | 0 |       } | 
| 752 | 263k |       if( compression_offset > data_offset ) | 
| 753 | 54 |       { | 
| 754 | 54 |         libcerror_error_set( | 
| 755 | 54 |          error, | 
| 756 | 54 |          LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 757 | 54 |          LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, | 
| 758 | 54 |          "%s: invalid compression offset value out of bounds.", | 
| 759 | 54 |          function ); | 
| 760 |  |  | 
| 761 | 54 |         return( -1 ); | 
| 762 | 54 |       } | 
| 763 | 263k |       if( ( data_offset + compression_size ) > uncompressed_data_size ) | 
| 764 | 10 |       { | 
| 765 | 10 |         libcerror_error_set( | 
| 766 | 10 |          error, | 
| 767 | 10 |          LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 768 | 10 |          LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, | 
| 769 | 10 |          "%s: invalid uncompressed data value too small.", | 
| 770 | 10 |          function ); | 
| 771 |  |  | 
| 772 | 10 |         return( -1 ); | 
| 773 | 10 |       } | 
| 774 | 4.23M |       while( compression_size > 0 ) | 
| 775 | 3.97M |       { | 
| 776 | 3.97M |         uncompressed_data[ data_offset ] = uncompressed_data[ data_offset - compression_offset ]; | 
| 777 |  |  | 
| 778 | 3.97M |         data_offset++; | 
| 779 | 3.97M |         compression_size--; | 
| 780 | 3.97M |       } | 
| 781 | 263k |     } | 
| 782 | 2.77M |   } | 
| 783 | 2.87k |   *uncompressed_data_offset = data_offset; | 
| 784 |  |  | 
| 785 | 2.87k |   return( 1 ); | 
| 786 | 2.94k | } | 
| 787 |  |  | 
| 788 |  | /* Adjusts the 32-bit Intel 80x86 CALL (0xe8) instructions after decompression | 
| 789 |  |  * Returns 1 on success or -1 on error | 
| 790 |  |  */ | 
| 791 |  | int libfwnt_lzx_decompress_adjust_call_instructions( | 
| 792 |  |      uint8_t *uncompressed_data, | 
| 793 |  |      size_t uncompressed_data_size, | 
| 794 |  |      libcerror_error_t **error ) | 
| 795 | 357 | { | 
| 796 | 357 |   static char *function           = "libfwnt_lzx_decompress_adjust_call_instructions"; | 
| 797 | 357 |   size_t uncompressed_data_offset = 0; | 
| 798 | 357 |   uint32_t address                = 0; | 
| 799 |  |  | 
| 800 | 357 |   if( uncompressed_data == NULL ) | 
| 801 | 0 |   { | 
| 802 | 0 |     libcerror_error_set( | 
| 803 | 0 |      error, | 
| 804 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 805 | 0 |      LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, | 
| 806 | 0 |      "%s: invalid uncompressed data.", | 
| 807 | 0 |      function ); | 
| 808 |  | 
 | 
| 809 | 0 |     return( -1 ); | 
| 810 | 0 |   } | 
| 811 | 357 |   if( ( uncompressed_data_size < 6 ) | 
| 812 | 357 |    || ( uncompressed_data_size > (size_t) SSIZE_MAX ) ) | 
| 813 | 110 |   { | 
| 814 | 110 |     libcerror_error_set( | 
| 815 | 110 |      error, | 
| 816 | 110 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 817 | 110 |      LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, | 
| 818 | 110 |      "%s: invalid uncompressed data size value out of bounds.", | 
| 819 | 110 |      function ); | 
| 820 |  |  | 
| 821 | 110 |     return( -1 ); | 
| 822 | 110 |   } | 
| 823 | 247 |   for( uncompressed_data_offset = 0; | 
| 824 | 4.01M |        uncompressed_data_offset < ( uncompressed_data_size - 6 ); | 
| 825 | 4.01M |        uncompressed_data_offset++ ) | 
| 826 | 4.01M |   { | 
| 827 | 4.01M |     if( uncompressed_data[ uncompressed_data_offset ] != 0xe8 ) | 
| 828 | 3.88M |     { | 
| 829 | 3.88M |       continue; | 
| 830 | 3.88M |     } | 
| 831 | 125k |     byte_stream_copy_to_uint32_little_endian( | 
| 832 | 125k |      &( uncompressed_data[ uncompressed_data_offset + 1 ] ), | 
| 833 | 125k |      address ); | 
| 834 |  |  | 
| 835 | 125k |     if( address > (uint32_t) INT32_MAX ) | 
| 836 | 76.1k |     { | 
| 837 | 76.1k |       if( (int32_t) address > ( -1 * (int32_t) uncompressed_data_offset ) ) | 
| 838 | 21.3k |       { | 
| 839 | 21.3k |         address = (uint32_t) ( (int32_t) address + 12000000 ); | 
| 840 |  |  | 
| 841 | 21.3k |         byte_stream_copy_from_uint32_little_endian( | 
| 842 | 21.3k |          &( uncompressed_data[ uncompressed_data_offset + 1 ] ), | 
| 843 | 21.3k |          address ); | 
| 844 | 21.3k |       } | 
| 845 | 76.1k |     } | 
| 846 | 48.9k |     else | 
| 847 | 48.9k |     { | 
| 848 | 48.9k |       if( address < 12000000 ) | 
| 849 | 24.6k |       { | 
| 850 | 24.6k |         address = (uint32_t) ( (int32_t) address - uncompressed_data_offset ); | 
| 851 |  |  | 
| 852 | 24.6k |         byte_stream_copy_from_uint32_little_endian( | 
| 853 | 24.6k |          &( uncompressed_data[ uncompressed_data_offset + 1 ] ), | 
| 854 | 24.6k |          address ); | 
| 855 | 24.6k |       } | 
| 856 | 48.9k |     } | 
| 857 | 125k |     uncompressed_data_offset += 4; | 
| 858 | 125k |   } | 
| 859 | 247 |   return( 1 ); | 
| 860 | 357 | } | 
| 861 |  |  | 
| 862 |  | /* Decompresses LZX compressed data | 
| 863 |  |  * Returns 1 on success or -1 on error | 
| 864 |  |  */ | 
| 865 |  | int libfwnt_lzx_decompress( | 
| 866 |  |      const uint8_t *compressed_data, | 
| 867 |  |      size_t compressed_data_size, | 
| 868 |  |      uint8_t *uncompressed_data, | 
| 869 |  |      size_t *uncompressed_data_size, | 
| 870 |  |      libcerror_error_t **error ) | 
| 871 | 762 | { | 
| 872 | 762 |   uint8_t aligned_offsets_code_size_array[ 8 ]; | 
| 873 | 762 |   uint8_t lengths_code_size_array[ 249 ]; | 
| 874 | 762 |   uint8_t main_code_size_array[ 256 + 240 ]; | 
| 875 |  |  | 
| 876 | 762 |   uint32_t recent_compression_offsets[ 3 ]             = { 1, 1, 1 }; | 
| 877 |  |  | 
| 878 | 762 |   libfwnt_bit_stream_t *bit_stream                     = NULL; | 
| 879 | 762 |   libfwnt_huffman_tree_t *aligned_offsets_huffman_tree = NULL; | 
| 880 | 762 |   libfwnt_huffman_tree_t *lengths_huffman_tree         = NULL; | 
| 881 | 762 |   libfwnt_huffman_tree_t *main_huffman_tree            = NULL; | 
| 882 | 762 |   static char *function                                = "libfwnt_lzx_decompress"; | 
| 883 | 762 |   size_t safe_uncompressed_data_size                   = 0; | 
| 884 | 762 |   size_t uncompressed_data_offset                      = 0; | 
| 885 | 762 |   uint32_t block_size                                  = 0; | 
| 886 | 762 |   uint32_t block_type                                  = 0; | 
| 887 | 762 |   int initialized_aligned_offsets_code_size_array      = 0; | 
| 888 | 762 |   int initialized_main_and_length_code_size_arrays     = 0; | 
| 889 |  |  | 
| 890 | 762 |   if( compressed_data == NULL ) | 
| 891 | 0 |   { | 
| 892 | 0 |     libcerror_error_set( | 
| 893 | 0 |      error, | 
| 894 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 895 | 0 |      LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, | 
| 896 | 0 |      "%s: invalid compressed data.", | 
| 897 | 0 |      function ); | 
| 898 |  | 
 | 
| 899 | 0 |     return( -1 ); | 
| 900 | 0 |   } | 
| 901 | 762 |   if( compressed_data_size > (size_t) SSIZE_MAX ) | 
| 902 | 0 |   { | 
| 903 | 0 |     libcerror_error_set( | 
| 904 | 0 |      error, | 
| 905 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 906 | 0 |      LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, | 
| 907 | 0 |      "%s: invalid compressed data size value exceeds maximum.", | 
| 908 | 0 |      function ); | 
| 909 |  | 
 | 
| 910 | 0 |     return( -1 ); | 
| 911 | 0 |   } | 
| 912 | 762 |   if( uncompressed_data == NULL ) | 
| 913 | 0 |   { | 
| 914 | 0 |     libcerror_error_set( | 
| 915 | 0 |      error, | 
| 916 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 917 | 0 |      LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, | 
| 918 | 0 |      "%s: invalid uncompressed data.", | 
| 919 | 0 |      function ); | 
| 920 |  | 
 | 
| 921 | 0 |     return( -1 ); | 
| 922 | 0 |   } | 
| 923 | 762 |   if( uncompressed_data_size == NULL ) | 
| 924 | 0 |   { | 
| 925 | 0 |     libcerror_error_set( | 
| 926 | 0 |      error, | 
| 927 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 928 | 0 |      LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, | 
| 929 | 0 |      "%s: invalid uncompressed data size.", | 
| 930 | 0 |      function ); | 
| 931 |  | 
 | 
| 932 | 0 |     return( -1 ); | 
| 933 | 0 |   } | 
| 934 | 762 |   if( *uncompressed_data_size > (size_t) SSIZE_MAX ) | 
| 935 | 0 |   { | 
| 936 | 0 |     libcerror_error_set( | 
| 937 | 0 |      error, | 
| 938 | 0 |      LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 939 | 0 |      LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, | 
| 940 | 0 |      "%s: invalid uncompressed data size value exceeds maximum.", | 
| 941 | 0 |      function ); | 
| 942 |  | 
 | 
| 943 | 0 |     return( -1 ); | 
| 944 | 0 |   } | 
| 945 | 762 |   safe_uncompressed_data_size = *uncompressed_data_size; | 
| 946 |  |  | 
| 947 | 762 |   if( libfwnt_bit_stream_initialize( | 
| 948 | 762 |        &bit_stream, | 
| 949 | 762 |        compressed_data, | 
| 950 | 762 |        compressed_data_size, | 
| 951 | 762 |        error ) != 1 ) | 
| 952 | 0 |   { | 
| 953 | 0 |     libcerror_error_set( | 
| 954 | 0 |      error, | 
| 955 | 0 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 956 | 0 |      LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 957 | 0 |      "%s: unable to create bit-stream.", | 
| 958 | 0 |      function ); | 
| 959 |  | 
 | 
| 960 | 0 |     goto on_error; | 
| 961 | 0 |   } | 
| 962 |  | /* TODO find optimized solution to read bit stream from bytes */ | 
| 963 | 4.66k |   while( bit_stream->byte_stream_offset < bit_stream->byte_stream_size ) | 
| 964 | 4.31k |   { | 
| 965 | 4.31k |     if( uncompressed_data_offset >= safe_uncompressed_data_size ) | 
| 966 | 1 |     { | 
| 967 | 1 |       break; | 
| 968 | 1 |     } | 
| 969 | 4.31k |     if( libfwnt_bit_stream_get_value( | 
| 970 | 4.31k |          bit_stream, | 
| 971 | 4.31k |          3, | 
| 972 | 4.31k |          &block_type, | 
| 973 | 4.31k |          error ) != 1 ) | 
| 974 | 0 |     { | 
| 975 | 0 |       libcerror_error_set( | 
| 976 | 0 |        error, | 
| 977 | 0 |        LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 978 | 0 |        LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 979 | 0 |        "%s: unable to retrieve value from bit stream.", | 
| 980 | 0 |        function ); | 
| 981 |  | 
 | 
| 982 | 0 |       goto on_error; | 
| 983 | 0 |     } | 
| 984 | 4.31k |     if( libfwnt_bit_stream_get_value( | 
| 985 | 4.31k |          bit_stream, | 
| 986 | 4.31k |          1, | 
| 987 | 4.31k |          &block_size, | 
| 988 | 4.31k |          error ) != 1 ) | 
| 989 | 0 |     { | 
| 990 | 0 |       libcerror_error_set( | 
| 991 | 0 |        error, | 
| 992 | 0 |        LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 993 | 0 |        LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 994 | 0 |        "%s: unable to retrieve value from bit stream.", | 
| 995 | 0 |        function ); | 
| 996 |  | 
 | 
| 997 | 0 |       goto on_error; | 
| 998 | 0 |     } | 
| 999 | 4.31k |     if( block_size != 0 ) | 
| 1000 | 582 |     { | 
| 1001 | 582 |       block_size = 32768; | 
| 1002 | 582 |     } | 
| 1003 | 3.72k |     else | 
| 1004 | 3.72k |     { | 
| 1005 | 3.72k |       if( libfwnt_bit_stream_get_value( | 
| 1006 | 3.72k |            bit_stream, | 
| 1007 | 3.72k |            16, | 
| 1008 | 3.72k |            &block_size, | 
| 1009 | 3.72k |            error ) != 1 ) | 
| 1010 | 0 |       { | 
| 1011 | 0 |         libcerror_error_set( | 
| 1012 | 0 |          error, | 
| 1013 | 0 |          LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1014 | 0 |          LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 1015 | 0 |          "%s: unable to retrieve value from bit stream.", | 
| 1016 | 0 |          function ); | 
| 1017 |  | 
 | 
| 1018 | 0 |         goto on_error; | 
| 1019 | 0 |       } | 
| 1020 |  | /* TODO add extended block size support ? */ | 
| 1021 | 3.72k |     } | 
| 1022 | 4.31k |     if( libcnotify_verbose != 0 ) | 
| 1023 | 0 |     { | 
| 1024 | 0 |       libcnotify_printf( | 
| 1025 | 0 |        "%s: block header block type\t\t\t\t: %" PRIu32 " (", | 
| 1026 | 0 |        function, | 
| 1027 | 0 |        block_type ); | 
| 1028 |  | 
 | 
| 1029 | 0 |       switch( block_type ) | 
| 1030 | 0 |       { | 
| 1031 | 0 |         case LIBFWNT_LZX_BLOCK_TYPE_ALIGNED: | 
| 1032 | 0 |           libcnotify_printf( | 
| 1033 | 0 |            "Aligned" ); | 
| 1034 | 0 |           break; | 
| 1035 |  |  | 
| 1036 | 0 |         case LIBFWNT_LZX_BLOCK_TYPE_VERBATIM: | 
| 1037 | 0 |           libcnotify_printf( | 
| 1038 | 0 |            "Verbatim" ); | 
| 1039 | 0 |           break; | 
| 1040 |  |  | 
| 1041 | 0 |         case LIBFWNT_LZX_BLOCK_TYPE_UNCOMPRESSED: | 
| 1042 | 0 |           libcnotify_printf( | 
| 1043 | 0 |            "Uncompressed" ); | 
| 1044 | 0 |           break; | 
| 1045 |  |  | 
| 1046 | 0 |         default: | 
| 1047 | 0 |           libcnotify_printf( | 
| 1048 | 0 |            "Invalid" ); | 
| 1049 | 0 |           break; | 
| 1050 | 0 |       } | 
| 1051 | 0 |       libcnotify_printf( | 
| 1052 | 0 |        ")\n" ); | 
| 1053 |  | 
 | 
| 1054 | 0 |       libcnotify_printf( | 
| 1055 | 0 |        "%s: block header block size\t\t\t\t: %" PRIu32 "\n", | 
| 1056 | 0 |        function, | 
| 1057 | 0 |        block_size ); | 
| 1058 |  | 
 | 
| 1059 | 0 |       libcnotify_printf( | 
| 1060 | 0 |        "\n" ); | 
| 1061 | 0 |     } | 
| 1062 | 4.31k |     switch( block_type ) | 
| 1063 | 4.31k |     { | 
| 1064 | 1.12k |       case LIBFWNT_LZX_BLOCK_TYPE_ALIGNED: | 
| 1065 | 1.12k |         if( initialized_aligned_offsets_code_size_array == 0 ) | 
| 1066 | 111 |         { | 
| 1067 | 111 |           if( memory_set( | 
| 1068 | 111 |                aligned_offsets_code_size_array, | 
| 1069 | 111 |                0, | 
| 1070 | 111 |                sizeof( uint8_t ) * 8 ) == NULL ) | 
| 1071 | 0 |           { | 
| 1072 | 0 |             libcerror_error_set( | 
| 1073 | 0 |              error, | 
| 1074 | 0 |              LIBCERROR_ERROR_DOMAIN_MEMORY, | 
| 1075 | 0 |              LIBCERROR_MEMORY_ERROR_SET_FAILED, | 
| 1076 | 0 |              "%s: unable to clear aligned offsets code size array.", | 
| 1077 | 0 |              function ); | 
| 1078 |  | 
 | 
| 1079 | 0 |             goto on_error; | 
| 1080 | 0 |           } | 
| 1081 | 111 |           initialized_aligned_offsets_code_size_array = 1; | 
| 1082 | 111 |         } | 
| 1083 | 1.12k |         if( libfwnt_huffman_tree_initialize( | 
| 1084 | 1.12k |              &aligned_offsets_huffman_tree, | 
| 1085 | 1.12k |              256, | 
| 1086 | 1.12k |              16, | 
| 1087 | 1.12k |              error ) != 1 ) | 
| 1088 | 0 |         { | 
| 1089 | 0 |           libcerror_error_set( | 
| 1090 | 0 |            error, | 
| 1091 | 0 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1092 | 0 |            LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 1093 | 0 |            "%s: unable to create aligned offsets Huffman tree.", | 
| 1094 | 0 |            function ); | 
| 1095 |  | 
 | 
| 1096 | 0 |           goto on_error; | 
| 1097 | 0 |         } | 
| 1098 | 1.12k |         if( libfwnt_lzx_build_aligned_offsets_huffman_tree( | 
| 1099 | 1.12k |              bit_stream, | 
| 1100 | 1.12k |              aligned_offsets_code_size_array, | 
| 1101 | 1.12k |              aligned_offsets_huffman_tree, | 
| 1102 | 1.12k |              error ) != 1 ) | 
| 1103 | 7 |         { | 
| 1104 | 7 |           libcerror_error_set( | 
| 1105 | 7 |            error, | 
| 1106 | 7 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1107 | 7 |            LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 1108 | 7 |            "%s: unable to build aligned offsets Huffman tree.", | 
| 1109 | 7 |            function ); | 
| 1110 |  |  | 
| 1111 | 7 |           goto on_error; | 
| 1112 | 7 |         } | 
| 1113 |  |  | 
| 1114 | 1.12k |       LIBFWNT_LZX_ATTRIBUTE_FALLTHROUGH; | 
| 1115 | 3.18k |       case LIBFWNT_LZX_BLOCK_TYPE_VERBATIM: | 
| 1116 | 3.18k |         if( initialized_main_and_length_code_size_arrays == 0 ) | 
| 1117 | 476 |         { | 
| 1118 | 476 |           if( memory_set( | 
| 1119 | 476 |                main_code_size_array, | 
| 1120 | 476 |                0, | 
| 1121 | 476 |                sizeof( uint8_t ) * ( 256 + 240 ) ) == NULL ) | 
| 1122 | 0 |           { | 
| 1123 | 0 |             libcerror_error_set( | 
| 1124 | 0 |              error, | 
| 1125 | 0 |              LIBCERROR_ERROR_DOMAIN_MEMORY, | 
| 1126 | 0 |              LIBCERROR_MEMORY_ERROR_SET_FAILED, | 
| 1127 | 0 |              "%s: unable to clear main code size array.", | 
| 1128 | 0 |              function ); | 
| 1129 |  | 
 | 
| 1130 | 0 |             goto on_error; | 
| 1131 | 0 |           } | 
| 1132 | 476 |           if( memory_set( | 
| 1133 | 476 |                lengths_code_size_array, | 
| 1134 | 476 |                0, | 
| 1135 | 476 |                sizeof( uint8_t ) * 249 ) == NULL ) | 
| 1136 | 0 |           { | 
| 1137 | 0 |             libcerror_error_set( | 
| 1138 | 0 |              error, | 
| 1139 | 0 |              LIBCERROR_ERROR_DOMAIN_MEMORY, | 
| 1140 | 0 |              LIBCERROR_MEMORY_ERROR_SET_FAILED, | 
| 1141 | 0 |              "%s: unable to clear lengths code size array.", | 
| 1142 | 0 |              function ); | 
| 1143 |  | 
 | 
| 1144 | 0 |             goto on_error; | 
| 1145 | 0 |           } | 
| 1146 | 476 |           initialized_main_and_length_code_size_arrays = 1; | 
| 1147 | 476 |         } | 
| 1148 | 3.18k |         if( libfwnt_huffman_tree_initialize( | 
| 1149 | 3.18k |              &main_huffman_tree, | 
| 1150 | 3.18k |              256 + 240, | 
| 1151 | 3.18k |              16, | 
| 1152 | 3.18k |              error ) != 1 ) | 
| 1153 | 0 |         { | 
| 1154 | 0 |           libcerror_error_set( | 
| 1155 | 0 |            error, | 
| 1156 | 0 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1157 | 0 |            LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 1158 | 0 |            "%s: unable to create literals and match headers Huffman tree.", | 
| 1159 | 0 |            function ); | 
| 1160 |  | 
 | 
| 1161 | 0 |           goto on_error; | 
| 1162 | 0 |         } | 
| 1163 | 3.18k |         if( libfwnt_lzx_build_main_huffman_tree( | 
| 1164 | 3.18k |              bit_stream, | 
| 1165 | 3.18k |              main_code_size_array, | 
| 1166 | 3.18k |              main_huffman_tree, | 
| 1167 | 3.18k |              error ) != 1 ) | 
| 1168 | 199 |         { | 
| 1169 | 199 |           libcerror_error_set( | 
| 1170 | 199 |            error, | 
| 1171 | 199 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1172 | 199 |            LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 1173 | 199 |            "%s: unable to build literals and match headers Huffman tree.", | 
| 1174 | 199 |            function ); | 
| 1175 |  |  | 
| 1176 | 199 |           goto on_error; | 
| 1177 | 199 |         } | 
| 1178 | 2.99k |         if( libfwnt_huffman_tree_initialize( | 
| 1179 | 2.99k |              &lengths_huffman_tree, | 
| 1180 | 2.99k |              249, | 
| 1181 | 2.99k |              16, | 
| 1182 | 2.99k |              error ) != 1 ) | 
| 1183 | 0 |         { | 
| 1184 | 0 |           libcerror_error_set( | 
| 1185 | 0 |            error, | 
| 1186 | 0 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1187 | 0 |            LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 1188 | 0 |            "%s: unable to create lengths Huffman tree.", | 
| 1189 | 0 |            function ); | 
| 1190 |  | 
 | 
| 1191 | 0 |           goto on_error; | 
| 1192 | 0 |         } | 
| 1193 | 2.99k |         if( libfwnt_lzx_build_lengths_huffman_tree( | 
| 1194 | 2.99k |              bit_stream, | 
| 1195 | 2.99k |              lengths_code_size_array, | 
| 1196 | 2.99k |              lengths_huffman_tree, | 
| 1197 | 2.99k |              error ) != 1 ) | 
| 1198 | 44 |         { | 
| 1199 | 44 |           libcerror_error_set( | 
| 1200 | 44 |            error, | 
| 1201 | 44 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1202 | 44 |            LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, | 
| 1203 | 44 |            "%s: unable to build lengths Huffman tree.", | 
| 1204 | 44 |            function ); | 
| 1205 |  |  | 
| 1206 | 44 |           goto on_error; | 
| 1207 | 44 |         } | 
| 1208 | 2.94k |         if( libfwnt_lzx_decode_huffman( | 
| 1209 | 2.94k |              bit_stream, | 
| 1210 | 2.94k |              block_size, | 
| 1211 | 2.94k |              main_huffman_tree, | 
| 1212 | 2.94k |              lengths_huffman_tree, | 
| 1213 | 2.94k |              aligned_offsets_huffman_tree, | 
| 1214 | 2.94k |              recent_compression_offsets, | 
| 1215 | 2.94k |              uncompressed_data, | 
| 1216 | 2.94k |              safe_uncompressed_data_size, | 
| 1217 | 2.94k |              &uncompressed_data_offset, | 
| 1218 | 2.94k |              error ) != 1 ) | 
| 1219 | 73 |         { | 
| 1220 | 73 |           libcerror_error_set( | 
| 1221 | 73 |            error, | 
| 1222 | 73 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1223 | 73 |            LIBCERROR_RUNTIME_ERROR_GET_FAILED, | 
| 1224 | 73 |            "%s: unable to decode fixed Huffman encoded bit stream.", | 
| 1225 | 73 |            function ); | 
| 1226 |  |  | 
| 1227 | 73 |           goto on_error; | 
| 1228 | 73 |         } | 
| 1229 | 2.87k |         if( aligned_offsets_huffman_tree != NULL ) | 
| 1230 | 1.04k |         { | 
| 1231 | 1.04k |           if( libfwnt_huffman_tree_free( | 
| 1232 | 1.04k |                &aligned_offsets_huffman_tree, | 
| 1233 | 1.04k |                error ) != 1 ) | 
| 1234 | 0 |           { | 
| 1235 | 0 |             libcerror_error_set( | 
| 1236 | 0 |              error, | 
| 1237 | 0 |              LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1238 | 0 |              LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, | 
| 1239 | 0 |              "%s: unable to free aligned offsets Huffman tree.", | 
| 1240 | 0 |              function ); | 
| 1241 |  | 
 | 
| 1242 | 0 |             goto on_error; | 
| 1243 | 0 |           } | 
| 1244 | 1.04k |         } | 
| 1245 | 2.87k |         if( libfwnt_huffman_tree_free( | 
| 1246 | 2.87k |              &lengths_huffman_tree, | 
| 1247 | 2.87k |              error ) != 1 ) | 
| 1248 | 0 |         { | 
| 1249 | 0 |           libcerror_error_set( | 
| 1250 | 0 |            error, | 
| 1251 | 0 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1252 | 0 |            LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, | 
| 1253 | 0 |            "%s: unable to free lengths Huffman tree.", | 
| 1254 | 0 |            function ); | 
| 1255 |  | 
 | 
| 1256 | 0 |           goto on_error; | 
| 1257 | 0 |         } | 
| 1258 | 2.87k |         if( libfwnt_huffman_tree_free( | 
| 1259 | 2.87k |              &main_huffman_tree, | 
| 1260 | 2.87k |              error ) != 1 ) | 
| 1261 | 0 |         { | 
| 1262 | 0 |           libcerror_error_set( | 
| 1263 | 0 |            error, | 
| 1264 | 0 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1265 | 0 |            LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, | 
| 1266 | 0 |            "%s: unable to free literals and match headers Huffman tree.", | 
| 1267 | 0 |            function ); | 
| 1268 |  | 
 | 
| 1269 | 0 |           goto on_error; | 
| 1270 | 0 |         } | 
| 1271 | 2.87k |         break; | 
| 1272 |  |  | 
| 1273 | 2.87k |       case LIBFWNT_LZX_BLOCK_TYPE_UNCOMPRESSED: | 
| 1274 |  | /* TODO align byte stream */ | 
| 1275 | 1.05k |         if( ( bit_stream->byte_stream_size - bit_stream->byte_stream_offset ) < 12 ) | 
| 1276 | 8 |         { | 
| 1277 | 8 |           libcerror_error_set( | 
| 1278 | 8 |            error, | 
| 1279 | 8 |            LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 1280 | 8 |            LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, | 
| 1281 | 8 |            "%s: invalid compressed data value too small.", | 
| 1282 | 8 |            function ); | 
| 1283 |  |  | 
| 1284 | 8 |           goto on_error; | 
| 1285 | 8 |         } | 
| 1286 | 1.04k |         byte_stream_copy_to_uint32_little_endian( | 
| 1287 | 1.04k |          &( compressed_data[ bit_stream->byte_stream_offset ] ), | 
| 1288 | 1.04k |          recent_compression_offsets[ 0 ] ); | 
| 1289 |  |  | 
| 1290 | 1.04k |         bit_stream->byte_stream_offset += 4; | 
| 1291 |  |  | 
| 1292 | 1.04k |         byte_stream_copy_to_uint32_little_endian( | 
| 1293 | 1.04k |          &( compressed_data[ bit_stream->byte_stream_offset ] ), | 
| 1294 | 1.04k |          recent_compression_offsets[ 1 ] ); | 
| 1295 |  |  | 
| 1296 | 1.04k |         bit_stream->byte_stream_offset += 4; | 
| 1297 |  |  | 
| 1298 | 1.04k |         byte_stream_copy_to_uint32_little_endian( | 
| 1299 | 1.04k |          &( compressed_data[ bit_stream->byte_stream_offset ] ), | 
| 1300 | 1.04k |          recent_compression_offsets[ 2 ] ); | 
| 1301 |  |  | 
| 1302 | 1.04k |         bit_stream->byte_stream_offset += 4; | 
| 1303 |  |  | 
| 1304 | 1.04k |         if( recent_compression_offsets[ 0 ] == 0 ) | 
| 1305 | 1 |         { | 
| 1306 | 1 |           libcerror_error_set( | 
| 1307 | 1 |            error, | 
| 1308 | 1 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1309 | 1 |            LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, | 
| 1310 | 1 |            "%s: unsupported R0 value.", | 
| 1311 | 1 |            function ); | 
| 1312 |  |  | 
| 1313 | 1 |           goto on_error; | 
| 1314 | 1 |         } | 
| 1315 | 1.04k |         if( recent_compression_offsets[ 1 ] == 0 ) | 
| 1316 | 1 |         { | 
| 1317 | 1 |           libcerror_error_set( | 
| 1318 | 1 |            error, | 
| 1319 | 1 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1320 | 1 |            LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, | 
| 1321 | 1 |            "%s: unsupported R1 value.", | 
| 1322 | 1 |            function ); | 
| 1323 |  |  | 
| 1324 | 1 |           goto on_error; | 
| 1325 | 1 |         } | 
| 1326 | 1.04k |         if( recent_compression_offsets[ 2 ] == 0 ) | 
| 1327 | 1 |         { | 
| 1328 | 1 |           libcerror_error_set( | 
| 1329 | 1 |            error, | 
| 1330 | 1 |            LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1331 | 1 |            LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, | 
| 1332 | 1 |            "%s: unsupported R2 value.", | 
| 1333 | 1 |            function ); | 
| 1334 |  |  | 
| 1335 | 1 |           goto on_error; | 
| 1336 | 1 |         } | 
| 1337 | 1.04k |         if( libcnotify_verbose != 0 ) | 
| 1338 | 0 |         { | 
| 1339 | 0 |           libcnotify_printf( | 
| 1340 | 0 |            "%s: R0 value\t\t\t\t\t: 0x%08" PRIx32 "\n", | 
| 1341 | 0 |            function, | 
| 1342 | 0 |            recent_compression_offsets[ 0 ] ); | 
| 1343 |  | 
 | 
| 1344 | 0 |           libcnotify_printf( | 
| 1345 | 0 |            "%s: R1 value\t\t\t\t\t: 0x%08" PRIx32 "\n", | 
| 1346 | 0 |            function, | 
| 1347 | 0 |            recent_compression_offsets[ 1 ] ); | 
| 1348 |  | 
 | 
| 1349 | 0 |           libcnotify_printf( | 
| 1350 | 0 |            "%s: R2 value\t\t\t\t\t: 0x%08" PRIx32 "\n", | 
| 1351 | 0 |            function, | 
| 1352 | 0 |            recent_compression_offsets[ 2 ] ); | 
| 1353 |  | 
 | 
| 1354 | 0 |           libcnotify_printf( | 
| 1355 | 0 |            "\n" ); | 
| 1356 | 0 |         } | 
| 1357 | 1.04k |         if( (size_t) block_size > ( bit_stream->byte_stream_size - bit_stream->byte_stream_offset ) ) | 
| 1358 | 244 |         { | 
| 1359 | 244 |           block_size = (uint32_t) ( bit_stream->byte_stream_size - bit_stream->byte_stream_offset ); | 
| 1360 | 244 |         } | 
| 1361 | 1.04k |         if( (size_t) block_size > ( safe_uncompressed_data_size - uncompressed_data_offset ) ) | 
| 1362 | 8 |         { | 
| 1363 | 8 |           libcerror_error_set( | 
| 1364 | 8 |            error, | 
| 1365 | 8 |            LIBCERROR_ERROR_DOMAIN_ARGUMENTS, | 
| 1366 | 8 |            LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, | 
| 1367 | 8 |            "%s: invalid uncompressed data value too small.", | 
| 1368 | 8 |            function ); | 
| 1369 |  |  | 
| 1370 | 8 |           goto on_error; | 
| 1371 | 8 |         } | 
| 1372 | 1.03k |         if( memory_copy( | 
| 1373 | 1.03k |              &( uncompressed_data[ uncompressed_data_offset ] ), | 
| 1374 | 1.03k |              &( compressed_data[ bit_stream->byte_stream_offset ] ), | 
| 1375 | 1.03k |              (size_t) block_size ) == NULL ) | 
| 1376 | 0 |         { | 
| 1377 | 0 |           libcerror_error_set( | 
| 1378 | 0 |            error, | 
| 1379 | 0 |            LIBCERROR_ERROR_DOMAIN_MEMORY, | 
| 1380 | 0 |            LIBCERROR_MEMORY_ERROR_COPY_FAILED, | 
| 1381 | 0 |            "%s: unable to initialize lz buffer.", | 
| 1382 | 0 |            function ); | 
| 1383 |  | 
 | 
| 1384 | 0 |           goto on_error; | 
| 1385 | 0 |         } | 
| 1386 | 1.03k |         bit_stream->byte_stream_offset += block_size; | 
| 1387 | 1.03k |         uncompressed_data_offset       += block_size; | 
| 1388 |  |  | 
| 1389 |  |         /* Flush the bit-stream buffer | 
| 1390 |  |          */ | 
| 1391 | 1.03k |         bit_stream->bit_buffer      = 0; | 
| 1392 | 1.03k |         bit_stream->bit_buffer_size = 0; | 
| 1393 |  |  | 
| 1394 | 1.03k |         break; | 
| 1395 |  |  | 
| 1396 | 63 |       default: | 
| 1397 | 63 |         libcerror_error_set( | 
| 1398 | 63 |          error, | 
| 1399 | 63 |          LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1400 | 63 |          LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, | 
| 1401 | 63 |          "%s: unsupported block type.", | 
| 1402 | 63 |          function ); | 
| 1403 |  |  | 
| 1404 | 63 |         goto on_error; | 
| 1405 | 4.31k |     } | 
| 1406 | 4.31k |   } | 
| 1407 | 357 |   if( libfwnt_bit_stream_free( | 
| 1408 | 357 |        &bit_stream, | 
| 1409 | 357 |        error ) != 1 ) | 
| 1410 | 0 |   { | 
| 1411 | 0 |     libcerror_error_set( | 
| 1412 | 0 |      error, | 
| 1413 | 0 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1414 | 0 |      LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, | 
| 1415 | 0 |      "%s: unable to free bit-stream.", | 
| 1416 | 0 |      function ); | 
| 1417 |  | 
 | 
| 1418 | 0 |     goto on_error; | 
| 1419 | 0 |   } | 
| 1420 | 357 |   if( libfwnt_lzx_decompress_adjust_call_instructions( | 
| 1421 | 357 |        uncompressed_data, | 
| 1422 | 357 |        uncompressed_data_offset, | 
| 1423 | 357 |        error ) != 1 ) | 
| 1424 | 110 |   { | 
| 1425 | 110 |     libcerror_error_set( | 
| 1426 | 110 |      error, | 
| 1427 | 110 |      LIBCERROR_ERROR_DOMAIN_RUNTIME, | 
| 1428 | 110 |      LIBCERROR_RUNTIME_ERROR_SET_FAILED, | 
| 1429 | 110 |      "%s: unable to adjust call instructions.", | 
| 1430 | 110 |      function ); | 
| 1431 |  |  | 
| 1432 | 110 |     goto on_error; | 
| 1433 | 110 |   } | 
| 1434 | 247 |   *uncompressed_data_size = uncompressed_data_offset; | 
| 1435 |  |  | 
| 1436 | 247 |   return( 1 ); | 
| 1437 |  |  | 
| 1438 | 515 | on_error: | 
| 1439 | 515 |   if( lengths_huffman_tree != NULL ) | 
| 1440 | 117 |   { | 
| 1441 | 117 |     libfwnt_huffman_tree_free( | 
| 1442 | 117 |      &lengths_huffman_tree, | 
| 1443 | 117 |      NULL ); | 
| 1444 | 117 |   } | 
| 1445 | 515 |   if( main_huffman_tree != NULL ) | 
| 1446 | 316 |   { | 
| 1447 | 316 |     libfwnt_huffman_tree_free( | 
| 1448 | 316 |      &main_huffman_tree, | 
| 1449 | 316 |      NULL ); | 
| 1450 | 316 |   } | 
| 1451 | 515 |   if( aligned_offsets_huffman_tree != NULL ) | 
| 1452 | 83 |   { | 
| 1453 | 83 |     libfwnt_huffman_tree_free( | 
| 1454 | 83 |      &aligned_offsets_huffman_tree, | 
| 1455 | 83 |      NULL ); | 
| 1456 | 83 |   } | 
| 1457 | 515 |   if( bit_stream != NULL ) | 
| 1458 | 405 |   { | 
| 1459 | 405 |     libfwnt_bit_stream_free( | 
| 1460 | 405 |      &bit_stream, | 
| 1461 | 405 |      NULL ); | 
| 1462 | 405 |   } | 
| 1463 | 515 |   return( -1 ); | 
| 1464 | 357 | } | 
| 1465 |  |  |