pedump 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/.travis.yml +4 -0
  2. data/Gemfile +10 -6
  3. data/Gemfile.lock +27 -19
  4. data/README.md +37 -25
  5. data/Rakefile +45 -6
  6. data/VERSION +1 -1
  7. data/data/fs.txt +37 -1408
  8. data/data/jc-userdb.txt +14371 -0
  9. data/data/sig.bin +0 -0
  10. data/lib/pedump.rb +355 -618
  11. data/lib/pedump/cli.rb +214 -113
  12. data/lib/pedump/comparer.rb +147 -0
  13. data/lib/pedump/composite_io.rb +56 -0
  14. data/lib/pedump/core.rb +38 -0
  15. data/lib/pedump/core_ext/try.rb +57 -0
  16. data/lib/pedump/loader.rb +393 -0
  17. data/lib/pedump/loader/minidump.rb +187 -0
  18. data/lib/pedump/loader/section.rb +57 -0
  19. data/lib/pedump/logger.rb +67 -0
  20. data/lib/pedump/ne.rb +425 -0
  21. data/lib/pedump/ne/version_info.rb +171 -0
  22. data/lib/pedump/packer.rb +50 -2
  23. data/lib/pedump/pe.rb +121 -0
  24. data/lib/pedump/resources.rb +436 -0
  25. data/lib/pedump/security.rb +58 -0
  26. data/lib/pedump/sig_parser.rb +145 -24
  27. data/lib/pedump/tls.rb +17 -0
  28. data/lib/pedump/unpacker.rb +26 -0
  29. data/lib/pedump/unpacker/aspack.rb +858 -0
  30. data/lib/pedump/unpacker/upx.rb +13 -0
  31. data/lib/pedump/version.rb +1 -1
  32. data/lib/pedump/version_info.rb +15 -10
  33. data/misc/aspack/Makefile +3 -0
  34. data/misc/aspack/aspack_unlzx.c +92 -0
  35. data/misc/aspack/lzxdec.c +479 -0
  36. data/misc/aspack/lzxdec.h +56 -0
  37. data/misc/nedump.c +751 -0
  38. data/pedump.gemspec +75 -25
  39. data/samples/bad/68.exe +0 -0
  40. data/samples/bad/data_dir_15_entries.exe +0 -0
  41. data/spec/65535sects_spec.rb +8 -0
  42. data/spec/bad_imports_spec.rb +20 -0
  43. data/spec/bad_samples_spec.rb +13 -0
  44. data/spec/composite_io_spec.rb +122 -0
  45. data/spec/data/calc.exe_sections.yml +49 -0
  46. data/spec/data/data_dir_15_entries.exe_sections.yml +95 -0
  47. data/spec/dllord_spec.rb +21 -0
  48. data/spec/foldedhdr_spec.rb +28 -0
  49. data/spec/imports_badterm_spec.rb +52 -0
  50. data/spec/imports_vterm_spec.rb +52 -0
  51. data/spec/loader/names_spec.rb +24 -0
  52. data/spec/loader/va_spec.rb +44 -0
  53. data/spec/manyimportsW7_spec.rb +22 -0
  54. data/spec/ne_spec.rb +125 -0
  55. data/spec/packer_spec.rb +17 -0
  56. data/spec/pe_spec.rb +67 -0
  57. data/spec/pedump_spec.rb +16 -4
  58. data/spec/sections_spec.rb +11 -0
  59. data/spec/sig_all_packers_spec.rb +15 -5
  60. data/spec/sig_spec.rb +6 -1
  61. data/spec/spec_helper.rb +15 -3
  62. data/spec/support/samples.rb +24 -0
  63. data/spec/unpackers/aspack_spec.rb +69 -0
  64. data/spec/unpackers/find_spec.rb +21 -0
  65. data/spec/virtsectblXP_spec.rb +12 -0
  66. data/tmp/.keep +0 -0
  67. metadata +146 -35
  68. data/README.md.tpl +0 -90
  69. data/samples/calc.7z +0 -0
  70. data/samples/zlib.dll +0 -0
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: binary
3
+ require 'pedump/loader'
4
+ require 'pedump/cli'
5
+
6
+ module PEdump::Unpacker; end
7
+
8
+ class PEdump::Unpacker::UPX
9
+ def self.unpack src_fname, dst_fname, log = ''
10
+ log << `upx -dqq #{src_fname} -o #{dst_fname} 2>&1`
11
+ $?.success?
12
+ end
13
+ end
@@ -1,7 +1,7 @@
1
1
  class PEdump
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 4
4
+ MINOR = 5
5
5
  PATCH = 0
6
6
  BUILD = nil
7
7
 
@@ -1,5 +1,5 @@
1
1
  class PEdump
2
- class VS_VERSIONINFO < PEdump.create_struct( 'v3a32v',
2
+ class VS_VERSIONINFO < IOStruct.new( 'v3a32v',
3
3
  :wLength,
4
4
  :wValueLength,
5
5
  :wType,
@@ -40,7 +40,7 @@ class PEdump
40
40
  end
41
41
  end
42
42
 
43
- class VS_FIXEDFILEINFO < PEdump.create_struct( 'V13',
43
+ class VS_FIXEDFILEINFO < IOStruct.new( 'V13',
44
44
  :dwSignature,
45
45
  :dwStrucVersion,
46
46
  :dwFileVersionMS,
@@ -64,7 +64,7 @@ class PEdump
64
64
  end
65
65
  end
66
66
 
67
- class StringFileInfo < PEdump.create_struct( 'v3a30',
67
+ class StringFileInfo < IOStruct.new( 'v3a30',
68
68
  :wLength,
69
69
  :wValueLength, # always 0
70
70
  :wType, # 1 => text data, 0 => binary data
@@ -85,7 +85,7 @@ class PEdump
85
85
  end
86
86
  end
87
87
 
88
- class StringTable < PEdump.create_struct( 'v3a16v',
88
+ class StringTable < IOStruct.new( 'v3a16v',
89
89
  :wLength, # The length, in bytes, of this StringTable structure,
90
90
  # including all structures indicated by the Children member.
91
91
  :wValueLength, # always 0
@@ -107,7 +107,7 @@ class PEdump
107
107
  end
108
108
  end
109
109
 
110
- class VersionString < PEdump.create_struct( 'v3',
110
+ class VersionString < IOStruct.new( 'v3',
111
111
  :wLength, # The length, in bytes, of this String structure.
112
112
  :wValueLength, # The size, in words, of the Value member
113
113
  :wType, # 1 => text data, 0 => binary data
@@ -116,21 +116,26 @@ class PEdump
116
116
  :Value # A zero-terminated string. See the szKey member description for more information
117
117
  )
118
118
  def self.read f, size = SIZE
119
+ pos = f.tell
119
120
  super.tap do |x|
120
121
  x.szKey = ''
121
122
  x.szKey << f.read(2) until x.szKey[-2..-1] == "\x00\x00" || f.eof?
122
123
  x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
123
- x.Value = f.read(x.wValueLength*2)
124
+
125
+ value_len = [x.wValueLength*2, x.wLength - (f.tell-pos)].min
126
+ value_len = 0 if value_len < 0
127
+
128
+ x.Value = f.read(value_len)
124
129
  if f.tell%4 > 0
125
130
  f.read(4-f.tell%4) # undoc padding?
126
131
  end
127
- x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
128
- x.Value.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
132
+ x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000+$/,'') rescue nil
133
+ x.Value.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000+$/,'') rescue nil
129
134
  end
130
135
  end
131
136
  end
132
137
 
133
- class VarFileInfo < PEdump.create_struct( 'v3a24v',
138
+ class VarFileInfo < IOStruct.new( 'v3a24v',
134
139
  :wLength,
135
140
  :wValueLength, # always 0
136
141
  :wType, # 1 => text data, 0 => binary data
@@ -147,7 +152,7 @@ class PEdump
147
152
  end
148
153
  end
149
154
 
150
- class Var < PEdump.create_struct( 'v3a24',
155
+ class Var < IOStruct.new( 'v3a24',
151
156
  :wLength,
152
157
  :wValueLength, # The length, in bytes, of the Value member
153
158
  :wType, # 1 => text data, 0 => binary data
@@ -0,0 +1,3 @@
1
+ all: aspack_unlzx
2
+ aspack_unlzx:
3
+ gcc aspack_unlzx.c -o aspack_unlzx
@@ -0,0 +1,92 @@
1
+ #include <stdlib.h>
2
+ #include <stdio.h>
3
+ #include <strings.h> // for bzero()
4
+
5
+ #include "lzxdec.c"
6
+
7
+ // based on ASPack Unpacker v1.00 by Dr.Golova (thx! :)
8
+
9
+ /* error codes for unpacker thread */
10
+ #define ERR_OK (0)
11
+ #define ERR_NO_FILE (1)
12
+ #define ERR_FILE_OPEN (2)
13
+ #define ERR_NO_MEM (3)
14
+ #define ERR_CANT_MAP (4)
15
+ #define ERR_FILE_CREATE (5)
16
+ #define ERR_FILE_WRITE (6)
17
+ #define ERR_COPY_OVL (7)
18
+ #define ERR_CORRUPT (8)
19
+ #define ERR_UNKNOWN (9)
20
+ #define ERR_SKIPPED (10)
21
+ #define ERR_UNPACK (11)
22
+ #define ERR_FAILED (12)
23
+
24
+
25
+ void write_result(void*buf, int size){
26
+ fwrite(buf,1,size,stdout);
27
+ }
28
+
29
+ int unpack(BYTE*packed_data, size_t packed_size, size_t unpacked_size){
30
+ LZX_CONTEXT LZX;
31
+ BYTE* unpacked_data = NULL;
32
+ size_t decoded_size;
33
+
34
+ bzero(&LZX, sizeof(LZX));
35
+
36
+ if ( NULL == (unpacked_data = calloc(1, unpacked_size + 300)) ){
37
+ perror("no mem");
38
+ return(ERR_NO_MEM);
39
+ }
40
+
41
+ decoded_size = DecodeLZX(&LZX, packed_data, unpacked_data, packed_size, unpacked_size);
42
+ if ( decoded_size < 0 || decoded_size < unpacked_size ) {
43
+ free(unpacked_data);
44
+ fprintf(stderr,"ERR_UNPACK\n");
45
+ return(ERR_UNPACK);
46
+ }
47
+
48
+ write_result(unpacked_data, decoded_size);
49
+ free(unpacked_data);
50
+ return 0;
51
+ }
52
+
53
+ int main(int argc, char*argv[]){
54
+ size_t packed_size, unpacked_size;
55
+ BYTE* packed_data = NULL;
56
+ int r;
57
+
58
+ if(argc != 3){
59
+ fprintf(stderr, "ASPack unLZX\n");
60
+ fprintf(stderr, "usage: %s <packed_size> <unpacked_size>\n", argv[0]);
61
+ fprintf(stderr, "(data is read from stdin and written to stdout)\n", argv[0]);
62
+ return 1;
63
+ }
64
+
65
+ sscanf(argv[1],"%zu",&packed_size);
66
+ if( packed_size < 1 || packed_size > 0x10000000 ){ // 256 Mb max
67
+ fprintf(stderr, "invalid packed_size: %zu\n", packed_size);
68
+ return 1;
69
+ }
70
+
71
+ sscanf(argv[2],"%zu",&unpacked_size);
72
+ if( unpacked_size < 1 || unpacked_size > 0x10000000 ){ // 256 Mb max
73
+ fprintf(stderr, "invalid unpacked_size: %zu\n", unpacked_size);
74
+ return 1;
75
+ }
76
+
77
+ /* alloc buffer */
78
+ if ( NULL == (packed_data = calloc(1, packed_size + 300)) ){
79
+ perror("no mem");
80
+ return(ERR_NO_MEM);
81
+ }
82
+
83
+ if( packed_size != fread(packed_data, 1, packed_size, stdin)){
84
+ free(packed_data);
85
+ perror("read");
86
+ return(ERR_NO_FILE);
87
+ }
88
+
89
+ r = unpack(packed_data, packed_size, unpacked_size);
90
+ free(packed_data);
91
+ return r;
92
+ }
@@ -0,0 +1,479 @@
1
+ //#include <windows.h>
2
+
3
+ typedef unsigned char BYTE;
4
+ typedef int INT;
5
+ typedef unsigned int UINT;
6
+ typedef unsigned long DWORD;
7
+ typedef int BOOL;
8
+
9
+ #define FALSE 0
10
+ #define TRUE 1
11
+
12
+ #include "lzxdec.h"
13
+
14
+ /* #define LZX_DEBUG_LOG */
15
+
16
+ #if defined _DEBUG && defined LZX_DEBUG_LOG
17
+ # include <stdio.h>
18
+ static FILE* FDebLog = NULL;
19
+ #endif
20
+
21
+ /* ##### *** COMMON FUNCTIONS *** ########################################## */
22
+
23
+ /* memset local redefinition */
24
+ static void lzx_memset(void* dst, int val, unsigned int count)
25
+ {
26
+ while( count-- )
27
+ {
28
+ *(char*)(dst) = val;
29
+ dst = (char*)(dst) + 1;
30
+ }
31
+ }
32
+
33
+ /* memcpy local redefinition */
34
+ static void lzx_memcpy(void* dst, void* src, unsigned int count)
35
+ {
36
+ while( count-- )
37
+ {
38
+ *(char*)(dst) = *(char*)(src);
39
+ dst = (char*)(dst) + 1;
40
+ src = (char*)(src) + 1;
41
+ }
42
+ }
43
+
44
+ /* ##### *** BIT READER FUNCTIONS *** ###################################### */
45
+
46
+ /* init bit reader */
47
+ #define BITRDR_INIT(BitRdr, RawSrc, RawLen) { \
48
+ (BitRdr)->SrcData = (RawSrc); \
49
+ (BitRdr)->SrcSize = (RawLen); \
50
+ (BitRdr)->CurOffs = 0; \
51
+ (BitRdr)->BitBuff = 0; \
52
+ (BitRdr)->BitFree = 32; \
53
+ }
54
+
55
+ /* read input byte (can be rewritten for file io) */
56
+ #define BITRDR_GETBYTE(BitRdr, RetVal) { \
57
+ if ( (BitRdr)->CurOffs < (BitRdr)->SrcSize ) \
58
+ RetVal = (BitRdr)->SrcData[(BitRdr)->CurOffs++]; \
59
+ else \
60
+ return(-1); /* error */ \
61
+ }
62
+
63
+ /* remove number of bits from bit buffer */
64
+ #define BITRDR_DROPBITS(BitRdr, BitNum) { \
65
+ (BitRdr)->BitFree += (BitNum); \
66
+ }
67
+
68
+ /* extract integer from bit buffer */
69
+ #define BITRDR_GETINT(BitRdr, RetVal) { \
70
+ DWORD BitBuff = (BitRdr)->BitBuff; \
71
+ UINT BitFree = (BitRdr)->BitFree; \
72
+ UINT UVal; \
73
+ while( BitFree >= 8 ) { \
74
+ BITRDR_GETBYTE(BitRdr, UVal); \
75
+ BitBuff = (BitBuff << 8) | UVal; \
76
+ BitFree -= 8; \
77
+ } \
78
+ RetVal = (BitBuff >> (8 - BitFree)) & 0x00ffffff; \
79
+ (BitRdr)->BitFree = BitFree; \
80
+ (BitRdr)->BitBuff = BitBuff; \
81
+ }
82
+
83
+ /* read number of bits from bit buffer */
84
+ #define BITRDR_GETBITS(BitRdr, BitNum, RetVal) { \
85
+ DWORD BitBuff = (BitRdr)->BitBuff; \
86
+ UINT BitFree = (BitRdr)->BitFree; \
87
+ UINT UVal; \
88
+ while( BitFree >= 8 ) { \
89
+ BITRDR_GETBYTE(BitRdr, UVal); \
90
+ BitBuff = (BitBuff << 8) | UVal; \
91
+ BitFree -= 8; \
92
+ } \
93
+ RetVal = (BitBuff >> (8 - BitFree)); \
94
+ RetVal = (RetVal & 0x00ffffff) >> (24 - (BitNum)); \
95
+ (BitRdr)->BitFree = (BitFree + (BitNum)); \
96
+ (BitRdr)->BitBuff = BitBuff; \
97
+ }
98
+
99
+ /* ##### *** SLIDING WINDOW DICTIONARY FUNCTIONS *** ####################### */
100
+
101
+ /* init swd context */
102
+ #define SWD_INIT(Wnd, Mem, Len) { \
103
+ (Wnd)->Window = (Mem); \
104
+ (Wnd)->WndLen = (Len); \
105
+ (Wnd)->CurOfs = 0; \
106
+ }
107
+
108
+ /* put byte to dictionary */
109
+ #define SWD_PUTBYTE(Wnd, DVal) { \
110
+ if ( (Wnd)->CurOfs < (Wnd)->WndLen ) \
111
+ (Wnd)->Window[(Wnd)->CurOfs++] = (BYTE)(DVal); \
112
+ else \
113
+ return(-1); /* error */ \
114
+ }
115
+
116
+ /* copy lz phrase in window */
117
+ #define SWD_DELTACOPY(Wnd, DOfs, DLen) { \
118
+ BYTE* WndPtr; \
119
+ if ( (Wnd)->CurOfs < (DOfs) ) \
120
+ return(-1); /* error */ \
121
+ if ( (Wnd)->CurOfs + (DLen) > (Wnd)->WndLen ) \
122
+ return(-1); /* error */ \
123
+ WndPtr = (Wnd)->Window + (Wnd)->CurOfs; \
124
+ lzx_memcpy(WndPtr, WndPtr - (DOfs), (DLen)); \
125
+ (Wnd)->CurOfs += (DLen); \
126
+ }
127
+
128
+ /* ##### *** HUFFMAN DECODERS FUNCTIONS *** ################################ */
129
+
130
+ /* init huffman decoder, return next table address */
131
+ static BYTE* LzxHuf_Init(LZX_HUFF* Huf, LZX_BITRDR* BitRdr, UINT SymNum,
132
+ BYTE* HufTbl)
133
+ {
134
+ Huf->BitRdr = BitRdr;
135
+ Huf->SymNum = SymNum;
136
+ Huf->Symbol = (UINT*)(HufTbl);
137
+ HufTbl += (SymNum * sizeof(Huf->Symbol[0]));
138
+ Huf->Length = HufTbl;
139
+ HufTbl += (256 * sizeof(Huf->Length[0]));
140
+ return(HufTbl);
141
+ }
142
+
143
+ /* decode one huffman symbol */
144
+ static INT LzxHuf_DecodeSymbol(LZX_HUFF* Huf)
145
+ {
146
+ UINT HVal, BNum, IOfs;
147
+
148
+ BITRDR_GETINT(Huf->BitRdr, HVal);
149
+ HVal &= 0x00fffe00;
150
+
151
+ if ( HVal < Huf->SymLim[8] )
152
+ BNum = Huf->Length[HVal >> 16];
153
+ else if ( HVal < Huf->SymLim[10] )
154
+ BNum = (HVal < Huf->SymLim[9]) ? (9) : (10);
155
+ else if ( HVal < Huf->SymLim[11] )
156
+ BNum = 11;
157
+ else if ( HVal < Huf->SymLim[12] )
158
+ BNum = 12;
159
+ else if ( HVal < Huf->SymLim[13] )
160
+ BNum = 13;
161
+ else
162
+ BNum = (HVal < Huf->SymLim[14]) ? (14) : (15);
163
+
164
+ BITRDR_DROPBITS(Huf->BitRdr, BNum);
165
+ IOfs = (HVal - Huf->SymLim[BNum-1]) >> (24 - BNum);
166
+ return(Huf->Symbol[Huf->SymIdx[BNum] + IOfs]);
167
+ }
168
+
169
+ /* construct huffman tables */
170
+ static INT LzxHuf_HufTblBuild(LZX_HUFF* Huf, BYTE* CodeLen)
171
+ {
172
+ UINT LenCnt[16];
173
+ UINT CurIdx[16];
174
+ UINT SymIdx, I;
175
+ UINT Lim, Idx;
176
+ UINT Ofs;
177
+
178
+ for ( I = 0; I < 16; I++ )
179
+ LenCnt[I] = 0;
180
+ for ( SymIdx = 0; SymIdx < Huf->SymNum; SymIdx++ )
181
+ LenCnt[CodeLen[SymIdx]]++;
182
+
183
+ #ifdef LZX_DEBUG_LOG
184
+ if ( NULL == FDebLog )
185
+ FDebLog = fopen("lzxdeb.log", "wt");
186
+ #endif
187
+
188
+ LenCnt[0] = 0;
189
+ CurIdx[0] = 0;
190
+ Huf->SymIdx[0] = 0;
191
+ Huf->SymLim[0] = 0;
192
+ Lim = 0;
193
+ Idx = 0;
194
+
195
+ for ( I = 1; I < 16; I++ )
196
+ {
197
+ Lim += (LenCnt[I] << (24 - I));
198
+ if ( Lim > 0x1000000 )
199
+ return(-1); /* overrun */
200
+
201
+ Huf->SymLim[I] = Lim;
202
+ Huf->SymIdx[I] = Huf->SymIdx[I-1] + LenCnt[I-1];
203
+ CurIdx[I] = Huf->SymIdx[I];
204
+
205
+ if ( I <= 8 )
206
+ {
207
+ Ofs = (Huf->SymLim[I] >> 16);
208
+ lzx_memset(&Huf->Length[Idx], I, Ofs - Idx);
209
+ Idx = Ofs;
210
+ }
211
+ }
212
+
213
+ if ( Lim != 0x1000000 )
214
+ return(-1); /* not full set */
215
+
216
+ #ifdef LZX_DEBUG_LOG
217
+ fprintf(FDebLog, "Huf->SymNum == %u\n", Huf->SymNum);
218
+ fprintf(FDebLog, "Huf->SymIdx == ");
219
+ for ( I = 0; I < 16; I++ )
220
+ fprintf(FDebLog, "%u ", Huf->SymIdx[I]);
221
+ fprintf(FDebLog, "\n");
222
+ fprintf(FDebLog, "Huf->SymLim == ");
223
+ for ( I = 0; I < 16; I++ )
224
+ fprintf(FDebLog, "%u ", Huf->SymLim[I]);
225
+ fprintf(FDebLog, "\n");
226
+ fflush(FDebLog);
227
+ #endif
228
+
229
+ for ( SymIdx = 0; SymIdx < Huf->SymNum; SymIdx++ )
230
+ {
231
+ if ( CodeLen[SymIdx] )
232
+ {
233
+ #ifdef LZX_DEBUG_LOG
234
+ fprintf(FDebLog, "%u\n", SymIdx);
235
+ fflush(FDebLog);
236
+ #endif
237
+ Huf->Symbol[CurIdx[CodeLen[SymIdx]]++] = SymIdx;
238
+ }
239
+ }
240
+
241
+ return(0); /* all ok */
242
+ }
243
+
244
+ /* ##### *** LZX DECODER FUNCTIONS *** ##################################### */
245
+
246
+ /* basic lzx tables */
247
+ static const UINT LzxTblLenBits[28] = {
248
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
249
+ 5, 5, 5, 5
250
+ };
251
+ static const UINT LzxTblLenBase[28] = {
252
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32,
253
+ 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224
254
+ };
255
+ static const UINT LzxTblOfsBits[58] = {
256
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
257
+ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
258
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18,
259
+ 18, 18, 18, 18
260
+ };
261
+ static const UINT LzxTblOfsBase[58] = {
262
+ 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000006,
263
+ 0x00000008, 0x0000000C, 0x00000010, 0x00000018, 0x00000020, 0x00000030,
264
+ 0x00000040, 0x00000060, 0x00000080, 0x000000C0, 0x00000100, 0x00000180,
265
+ 0x00000200, 0x00000300, 0x00000400, 0x00000600, 0x00000800, 0x00000C00,
266
+ 0x00001000, 0x00001800, 0x00002000, 0x00003000, 0x00004000, 0x00006000,
267
+ 0x00008000, 0x0000C000, 0x00010000, 0x00018000, 0x00020000, 0x00030000,
268
+ 0x00040000, 0x00060000, 0x00080000, 0x000A0000, 0x000C0000, 0x000E0000,
269
+ 0x00100000, 0x00120000, 0x00140000, 0x00160000, 0x00180000, 0x001A0000,
270
+ 0x001C0000, 0x001E0000, 0x00200000, 0x00240000, 0x00280000, 0x002C0000,
271
+ 0x00300000, 0x00340000, 0x00380000, 0x003C0000
272
+ };
273
+
274
+ /* ------------------------------------------------------------------------- */
275
+
276
+ /* build lzx tables */
277
+ static INT Lzx_LzxTblBuild(LZX_CONTEXT* Ctx)
278
+ {
279
+ BYTE* Heap;
280
+ BYTE LenTbl[19];
281
+ BYTE HufSym[757];
282
+ UINT Val, I, Sym;
283
+ INT ISym;
284
+
285
+ Heap = Ctx->LstMem;
286
+ BITRDR_GETBITS(&Ctx->BitRdr, 1, Val);
287
+ if ( !Val ) lzx_memset(Heap, 0, 757);
288
+
289
+ for ( I = 0; I < 19; I++ )
290
+ {
291
+ BITRDR_GETBITS(&Ctx->BitRdr, 4, Val);
292
+ LenTbl[I] = (BYTE)(Val);
293
+ }
294
+
295
+ if ( LzxHuf_HufTblBuild(&Ctx->HufSpec, LenTbl) )
296
+ return(-1); /* error */
297
+
298
+ I = 0;
299
+ while ( I < 757 )
300
+ {
301
+ if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufSpec)) == -1 )
302
+ return(-1); /* error */
303
+
304
+ if ( (Sym = (UINT)(ISym)) < 16 )
305
+ {
306
+ HufSym[I] = (BYTE)((Heap[I] + Sym) & 15); I++;
307
+ continue;
308
+ }
309
+
310
+ if ( Sym == 16 )
311
+ {
312
+ BITRDR_GETBITS(&Ctx->BitRdr, 2, Val); Val += 3;
313
+ while ( Val > 0 && I < 757 )
314
+ {
315
+ HufSym[I] = HufSym[I-1];
316
+ Val--; I++;
317
+ }
318
+ continue;
319
+ }
320
+
321
+ if ( Sym == 17 )
322
+ {
323
+ BITRDR_GETBITS(&Ctx->BitRdr, 3, Val);
324
+ Val += 3;
325
+ }
326
+ else
327
+ {
328
+ BITRDR_GETBITS(&Ctx->BitRdr, 7, Val);
329
+ Val += 11;
330
+ }
331
+
332
+ while ( Val > 0 && I < 757 )
333
+ {
334
+ HufSym[I] = 0;
335
+ Val--; I++;
336
+ }
337
+ }
338
+
339
+ if ( LzxHuf_HufTblBuild(&Ctx->HufBase, &HufSym[0]) )
340
+ return(-1);
341
+ if ( LzxHuf_HufTblBuild(&Ctx->HufLens, &HufSym[721]) )
342
+ return(-1);
343
+ if ( LzxHuf_HufTblBuild(&Ctx->HufOffs, &HufSym[749]) )
344
+ return(-1);
345
+
346
+ Ctx->HasOffs = FALSE;
347
+ for ( I = 0; I < 8; I++ )
348
+ {
349
+ if ( HufSym[749+I] != 3 )
350
+ {
351
+ Ctx->HasOffs = TRUE;
352
+ break;
353
+ }
354
+ }
355
+
356
+ lzx_memcpy(Heap, &HufSym[0], 757);
357
+ return(0); /* all ok */
358
+ }
359
+
360
+ /* ------------------------------------------------------------------------- */
361
+
362
+ INT DecodeLZX(LZX_CONTEXT* Ctx, BYTE* Src, BYTE* Dst, UINT PSize, UINT USize)
363
+ {
364
+ UINT Written;
365
+ UINT Symbol;
366
+ BYTE* HufMem;
367
+ UINT Ofs;
368
+ UINT Len;
369
+ UINT Num;
370
+ UINT Val;
371
+ INT ISym;
372
+
373
+ /* check params */
374
+ if ( !Ctx || !Src || !Dst || !USize )
375
+ return(-1); /* invalid param */
376
+
377
+ /* init lzx context */
378
+ BITRDR_INIT(&Ctx->BitRdr, Src, PSize);
379
+ SWD_INIT(&Ctx->Window, Dst, USize);
380
+ Ctx->HasOffs = FALSE;
381
+ Ctx->LstOfs[0] = 0;
382
+ Ctx->LstOfs[1] = 0;
383
+ Ctx->LstOfs[2] = 0;
384
+
385
+ /* init huffman coders */
386
+ HufMem = &Ctx->HufTbl[0];
387
+ HufMem = LzxHuf_Init(&Ctx->HufBase, &Ctx->BitRdr, 721, HufMem);
388
+ HufMem = LzxHuf_Init(&Ctx->HufLens, &Ctx->BitRdr, 28, HufMem);
389
+ HufMem = LzxHuf_Init(&Ctx->HufOffs, &Ctx->BitRdr, 8, HufMem);
390
+ HufMem = LzxHuf_Init(&Ctx->HufSpec, &Ctx->BitRdr, 19, HufMem);
391
+ lzx_memset(Ctx->LstMem = HufMem, 0, 757);
392
+
393
+ /* build lzx tables */
394
+ if ( Lzx_LzxTblBuild(Ctx) )
395
+ return(-1);
396
+
397
+ /* decode */
398
+ Written = 0;
399
+ while ( Written < USize )
400
+ {
401
+ if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufBase)) == -1 )
402
+ return(-1);
403
+
404
+ if ( (Symbol = (UINT)(ISym)) < 256 )
405
+ {
406
+ /* literal */
407
+ SWD_PUTBYTE(&Ctx->Window, Symbol);
408
+ Written++;
409
+ continue;
410
+ }
411
+
412
+ if ( Symbol < 720 )
413
+ {
414
+ /* phrase */
415
+ Symbol -= 256;
416
+ Ofs = (Symbol >> 3);
417
+ Len = (Symbol & 7) + 2;
418
+
419
+ if ( Len == 9 )
420
+ {
421
+ if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufLens)) == -1 )
422
+ return(-1);
423
+
424
+ Symbol = (UINT)(ISym);
425
+ Num = LzxTblLenBits[Symbol];
426
+ BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
427
+ Len += (Val + LzxTblLenBase[Symbol]);
428
+ }
429
+
430
+ Num = LzxTblOfsBits[Ofs];
431
+ Ofs = LzxTblOfsBase[Ofs];
432
+
433
+ if ( Num < 3 || !Ctx->HasOffs )
434
+ {
435
+ BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
436
+ Ofs += Val;
437
+ }
438
+ else
439
+ {
440
+ Num -= 3;
441
+ BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
442
+ if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufOffs)) == -1 )
443
+ return(-1);
444
+ Ofs += ((UINT)(ISym) + (Val << 3));
445
+ }
446
+
447
+ if ( Ofs < 3 )
448
+ {
449
+ /* use saved last offset */
450
+ Ofs = Ctx->LstOfs[Num = Ofs];
451
+ if ( Num )
452
+ {
453
+ Ctx->LstOfs[Num] = Ctx->LstOfs[0];
454
+ Ctx->LstOfs[0] = Ofs;
455
+ }
456
+ }
457
+ else
458
+ {
459
+ /* update last offset */
460
+ Ctx->LstOfs[2] = Ctx->LstOfs[1];
461
+ Ctx->LstOfs[1] = Ctx->LstOfs[0];
462
+ Ctx->LstOfs[0] = (Ofs -= 3);
463
+ }
464
+
465
+ /* copy phrase */
466
+ SWD_DELTACOPY(&Ctx->Window, Ofs+1, Len);
467
+ Written += Len;
468
+ continue;
469
+ }
470
+
471
+ /* update trees */
472
+ if ( Lzx_LzxTblBuild(Ctx) )
473
+ return(-1);
474
+ }
475
+
476
+ return(Written); /* all ok */
477
+ }
478
+
479
+ /* ------------------------------------------------------------------------- */