Subversion Repositories Kolibri OS

Rev

Rev 589 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
589 diamond 1
; Loading of 7z archives was ported from 7z sources (file 7zip\Archive\7z\7zIn.cpp).
2
; The version 7-Zip 4.42 was used.
3
; 7-Zip is copyright (C) 1999-2006 Igor Pavlov.
4
; Assembler version as KFar plugin has been written by diamond, 2007.
5
 
6
virtual at 0
7
file_in_7z:
8
.fullname       dd      ?       ; pointer to cp866 string
9
.name           dd      ?
10
.namelen        dd      ?
11
.bIsDirectory   db      ?
12
.bPseudoFolder  db      ?
13
                rb      2
14
.parent         dd      ?       ; pointer to parent directory record
15
.subfolders     dd      ?       ; head of L2-list of subfolders [for folders]
16
.subfolders.end dd      ?
17
.subfiles       dd      ?       ; head of L2-list of files [for folders]
18
.subfiles.end   dd      ?
19
.NumSubItems    dd      ?
20
.next           dd      ?       ; next item of list of subfolders or files
21
.prev           dd      ?       ; previous item of list of subfolders or files
631 diamond 22
.stamp          dd      ?
589 diamond 23
.attr           dd      ?
24
.FileCRC        dd      ?
25
.startPos       dq      ?
26
.CreationTime   dq      ?
27
.LastAccessTime dq      ?
28
.LastWriteTime  dq      ?
29
.UnPackSize     dq      ?
30
.folder         dd      ?
31
.folder_index   dd      ?
32
.folderStart    dq      ?
33
.bAttrDefined           db      ?
34
.bStartPosDefined       db      ?
35
.bCRCDefined            db      ?
36
.bCreationTimeDefined   db      ?
37
.bLastAccessTimeDefined db      ?
38
.bLastWriteTimeDefined  db      ?
39
.bHasStream             db      ?
40
.bAnti                  db      ?
41
.size = $
42
end virtual
43
 
44
virtual at 0
45
handle_7z:
46
.type           dd      ?
47
.root.subfolders dd     ?
48
.root.subfolders.end dd ?
49
.root.subfiles  dd      ?
50
.root.subfiles.end dd   ?
51
.root.NumSubItems dd    ?
52
.curdir         dd      ?
53
.NumFiles       dd      ?
54
.names_buf      dd      ?
55
.host           dd      ?
56
.host_datetime  rd      6
57
; streams info
58
.numPackStreams dd      ?
59
.packSizes      dd      ?
60
.numFolders     dd      ?
61
.unpackCRCsDefined dd   ?
62
.unpackCRCs     dd      ?
63
.folders        dd      ?
64
.last_folder    dd      ?
65
.last_pos       dq      ?
66
.last_context   dd      ?
67
.last_main_stream dd    ?
68
.password_len   dd      ?       ; -1 if no password defined; in characters
69
.password       rw      password_maxlen
70
.basesize = $
71
; .size = .basesize + .NumFiles * file_in_7z.size
72
end virtual
73
 
74
iglobal
75
align 4
76
empty_7z_handle:
77
        dd      type_7z
78
        dd      0,0,0,0,0,0
79
endg
80
 
81
kEnd = 0
82
kHeader = 1
83
kArchiveProperties = 2
84
kAdditionalStreamsInfo = 3
85
kMainStreamsInfo = 4
86
kFilesInfo = 5
87
kPackInfo = 6
88
kUnPackInfo = 7
89
kSubStreamsInfo = 8
90
kSize = 9
91
kCRC = 10
92
kFolder = 11
93
kCodersUnPackSize = 12
94
kNumUnPackStream = 13
95
kEmptyStream = 14
96
kEmptyFile = 15
97
kAnti = 16
98
kName = 17
99
kCreationTime = 18
100
kLastAccessTime = 19
101
kLastWriteTime = 20
102
kWinAttributes = 21
103
kComment = 22
104
kEncodedHeader = 23
105
kStartPos = 24
106
 
107
_7z.ReadByte:
108
        cmp     edi, [bufend]
109
        jae     return.err
110
        mov     al, [edi]
111
        inc     edi
112
        ret
113
_7z.ReadWord:
114
        add     edi, 2
115
        cmp     edi, [bufend]
116
        ja      return.err
117
        mov     ax, [edi-2]
118
        ret
119
_7z.ReadDword:
120
        add     edi, 4
121
        cmp     edi, [bufend]
122
        ja      return.err
123
        mov     eax, [edi-4]
124
        ret
125
 
126
_7z.SkipSize:
127
        test    edx, edx
128
        jnz     return.err
129
        add     edi, eax
130
        jc      return.err
131
        cmp     edi, [bufend]
132
        ja      return.err
133
        ret
134
 
135
_7z.ReadNumber:
136
        xor     eax, eax
137
        push    eax
138
        push    eax
139
        call    _7z.ReadByte
140
        push    ecx
141
        xor     ecx, ecx
142
@@:
143
        add     al, al
144
        jnc     @f
145
        inc     ecx
146
        jmp     @b
147
@@:
148
        shr     eax, cl
149
        shr     eax, 1
150
        jz      @f
151
        mov     [esp+4+ecx], al
152
@@:
153
        jecxz   .ret
154
        push    edx
155
        xor     edx, edx
156
@@:
157
        call    _7z.ReadByte
158
        mov     [esp+8+edx], al
159
        inc     edx
160
        loop    @b
161
        pop     edx
162
.ret:
163
        pop     ecx
164
        pop     eax
165
        pop     edx
166
        ret
167
 
168
_7z.ReadNum:
169
        push    edx
170
        call    _7z.ReadNumber
171
        test    edx, edx
172
        jnz     return.err
173
        test    eax, eax
174
        js      return.err
175
        pop     edx
176
        ret
177
 
178
open_7z:
179
; CInArchive::ReadDatabase()
180
        cmp     byte [esi+6], 0         ; major version must be 0
181
                                        ; minor version does not be checked ([byte +7]=2 for now)
182
        jz      @f
183
        xor     eax, eax
184
        ret
185
@@:
186
        and     [hOut], 0
187
        and     [_7z.FreeSubStreams], 0
188
        and     [_7z.tmpVector], 0
189
        push    esi
190
        add     esi, 12
191
        mov     ecx, 20
192
        call    crc
193
        pop     esi
194
        cmp     eax, [esi+8]
195
        jnz     .header_crc_error
196
        cmp     dword [esi+24], 0
197
        jnz     .header_error
198
        mov     edi, buffer
199
        mov     ecx, [esi+20]
200
        mov     [bufsize], ecx
201
        test    ecx, ecx
202
        jnz     .notempty
203
        mov     eax, empty_7z_handle
204
        push    ebp
205
        call    [close]
206
        ret
207
.notempty:
208
        cmp     ecx, 1024
209
        jbe     @f
210
        call    [pgalloc]
211
        test    eax, eax
212
        jz      .reterr
213
        mov     edi, eax
214
@@:
215
        mov     [bufptr], edi
216
        lea     eax, [edi+ecx]
217
        mov     [bufend], eax
218
        mov     eax, [esi+12]
219
        mov     edx, [esi+16]
220
        add     eax, 20h        ; end of main header
221
        adc     edx, 0
222
        push    edx
223
        push    eax
224
        push    0
225
        push    ebp
226
        call    [seek]
227
        push    ecx
228
        push    edi
229
        push    ebp
230
        call    [read]
231
        cmp     eax, ecx
232
        jnz     .header_error
233
        push    esi
234
        mov     esi, edi
235
        call    crc
236
        pop     esi
237
        cmp     eax, [esi+28]
238
        jz      .header_ok
239
.header_crc_error:
240
.header_error:
241
        push    ContinueBtn
242
        push    1
243
        push    HeaderError_ptr
244
        push    1
245
        call    [SayErr]
246
.clear:
247
        mov     ecx, [_7z.tmpVector]
248
        jecxz   @f
249
        call    [pgfree]
250
@@:
251
        mov     ecx, [hOut]
252
        jecxz   @f
253
        call    _7z.CloseHandle
254
@@:
255
        mov     ebx, [_7z.dataVectorSize]
256
        test    ebx, ebx
257
        jz      @f
258
        call    _7z.ReadAndDecodePackedStreams.free2
259
@@:
260
        mov     ecx, [_7z.FreeSubStreams]
261
        jecxz   @f
262
        call    [pgfree]
263
@@:
264
        mov     ecx, [bufptr]
265
        cmp     ecx, buffer
266
        jz      .reterr
267
        call    [pgfree]
268
.reterr:
269
        or      eax, -1
270
        ret
271
.header_ok:
272
        mov     [_esp], esp
273
        mov     [inStream], ebp
274
.loop:
275
        mov     [error_proc], .header_error
276
        mov     [clear_proc], .clear
277
        and     [_7z.dataVectorSize], 0
278
        call    _7z.ReadNum
279
        cmp     eax, kHeader
280
        jz      .found_header
281
        cmp     eax, kEncodedHeader
282
        jnz     .header_error
283
        call    _7z.ReadAndDecodePackedStreams
284
        cmp     [_7z.StreamsInfo.numFolders], 0
285
        jz      .free_empty
286
        cmp     [_7z.StreamsInfo.numFolders], 1
287
        jnz     return.err
288
        mov     ecx, [bufptr]
289
        cmp     ecx, buffer
290
        jz      @f
291
        call    [pgfree]
292
@@:
293
        mov     edi, [_7z.unpbuf+4]
294
        mov     [bufptr], edi
295
        mov     ecx, [_7z.unpbuf]
296
        add     ecx, edi
297
        mov     [bufend], ecx
298
        mov     [error_proc], .header_error
299
        mov     [clear_proc], .clear
300
        and     [_7z.dataVectorSize], 0
301
        call    _7z.ReadNum
302
        cmp     eax, kHeader
303
        jz      .found_header
304
        jmp     return.err
305
.free_empty:
306
        mov     ecx, [bufptr]
307
        cmp     ecx, buffer
308
        jz      @f
309
        call    [pgfree]
310
@@:
311
        push    [inStream]
312
        call    [close]
313
        mov     eax, empty_7z_handle
314
        ret
315
.found_header:
316
        call    _7z.ReadNum
317
        cmp     eax, kArchiveProperties
318
        jnz     .no_archive_props
319
@@:
320
        call    _7z.ReadNum
321
        test    eax, eax
322
        jz      @f
323
        call    _7z.SkipData
324
        jmp     @b
325
@@:
326
        call    _7z.ReadNum
327
.no_archive_props:
328
        cmp     eax, kAdditionalStreamsInfo
329
        jnz     .no_additional_streams
330
        call    _7z.ReadAndDecodePackedStreams
331
        mov     eax, [_7z.unpacked]
332
        mov     [_7z.dataVector], eax
333
        mov     eax, [_7z.StreamsInfo.numFolders]
334
        mov     [_7z.dataVectorSize], eax
335
        mov     [error_proc], .header_error
336
        mov     [clear_proc], .clear
337
        call    _7z.ReadNum
338
.no_additional_streams:
339
        cmp     eax, kMainStreamsInfo
340
        jnz     return.err
341
        call    _7z.ReadStreamsInfo
342
        call    _7z.ReadNum
343
        test    eax, eax
344
        jnz     .notempty2
345
.empty2:
346
        mov     ebx, [_7z.dataVectorSize]
347
        test    ebx, ebx
348
        jz      @f
349
        call    _7z.ReadAndDecodePackedStreams.free2
350
@@:
351
        mov     ecx, [_7z.FreeSubStreams]
352
        jecxz   @f
353
        call    [pgfree]
354
@@:
355
        mov     ecx, [bufptr]
356
        cmp     ecx, buffer
357
        jz      @f
358
        call    [pgfree]
359
@@:
360
        push    [inStream]
361
        call    [close]
362
        mov     eax, empty_7z_handle
363
        ret
364
.notempty2:
365
        cmp     eax, kFilesInfo
366
        jnz     return.err
367
        call    _7z.ReadNum
368
        test    eax, eax
369
        jz      .empty2
370
        mov     ebx, eax        ; number of files in archive
371
        imul    ecx, ebx, file_in_7z.size
372
        add     ecx, handle_7z.basesize
373
        mov     [hOut.allocated], ecx
374
        call    [pgalloc]
375
        test    eax, eax
376
        jz      return.clear
377
        mov     [hOut], eax
378
        mov     [eax+handle_7z.type], type_7z
379
        mov     [eax+handle_7z.NumFiles], ebx
380
        push    edi
381
        lea     edi, [eax+handle_7z.numPackStreams]
382
        mov     esi, _7z.StreamsInfo
383
        mov     ecx, 6
384
        rep     movsd
385
        or      [eax+handle_7z.password_len], -1
386
        or      [eax+handle_7z.last_folder], -1
387
        mov     [eax+handle_7z.last_context], ecx
388
        mov     [eax+handle_7z.names_buf], ecx
389
        mov     [eax+handle_7z.host], ecx
390
        cmp     [bPasswordDefined], cl
391
        jz      @f
392
        mov     ecx, [password_size]
393
        mov     [eax+handle_7z.password_len], ecx
394
        lea     edi, [eax+handle_7z.password]
395
        mov     esi, password_unicode
396
        shr     ecx, 1
397
        rep     movsd
398
        adc     ecx, ecx
399
        rep     movsw
400
@@:
401
        lea     edi, [eax+handle_7z.basesize]
402
        imul    ecx, ebx, file_in_7z.size/4
403
        xor     eax, eax
404
        rep     stosd
405
        pop     edi
406
        mov     eax, [_7z.StreamsInfo.SubStreamsSizes]
407
        mov     [_7z.FreeSubStreams], eax
408
        mov     [error_proc], .header_error
409
        mov     [clear_proc], .clear
410
        mov     ecx, ebx
411
        shl     ecx, 2
412
        call    [pgalloc]
413
        test    eax, eax
414
        jz      return.clear
415
        push    edi
416
        mov     edi, eax
417
        mov     [_7z.tmpVector], eax
418
        add     eax, ebx
419
        mov     [_7z.emptyStreams], eax
420
        add     eax, ebx
421
        mov     [_7z.emptyFiles], eax
422
        add     eax, ebx
423
        mov     [_7z.antiFiles], eax
424
        mov     ecx, ebx
425
        xor     eax, eax
426
        rep     stosd
427
        pop     edi
428
        mov     [_7z.numEmptyStreams], eax
429
.parse_header:
430
        call    _7z.ReadNum
431
        test    eax, eax
432
        jz      .parse_header_done
433
        mov     ecx, eax        ; ecx = type
434
        call    _7z.ReadNum     ; eax = size
435
        cmp     ecx, kName
436
        jz      .parse_names
437
        cmp     ecx, kWinAttributes
438
        jz      .parse_winAttr
439
        cmp     ecx, kStartPos
440
        jz      .parse_startPos
441
        cmp     ecx, kEmptyStream
442
        jz      .parse_emptyStream
443
        cmp     ecx, kEmptyFile
444
        jz      .parse_emptyFile
445
        cmp     ecx, kAnti
446
        jz      .parse_anti
447
        cmp     ecx, kCreationTime
448
        jz      .parse_time
449
        cmp     ecx, kLastWriteTime
450
        jz      .parse_time
451
        cmp     ecx, kLastAccessTime
452
        jz      .parse_time
453
        xor     edx, edx
454
        call    _7z.SkipSize
455
        jmp     .parse_header
456
.parse_names:
457
        push    eax
458
        call    _7z.SwitchStream
459
        pop     eax
460
        jz      @f
461
        mov     eax, [bufend]
462
        sub     eax, edi
463
@@:
464
        shr     eax, 1          ; size of ANSI string is a half of size of UNICODE string
465
        mov     ecx, eax
466
        call    [pgalloc]
467
        test    eax, eax
468
        jz      return.clear
469
        mov     ebp, eax
470
        mov     esi, [hOut]
471
        mov     [esi+handle_7z.names_buf], eax
472
        add     eax, ecx
473
        push    eax     ; remember limit
474
        mov     ecx, ebx
475
        add     esi, handle_7z.basesize + file_in_7z.fullname
476
        mov     [bWasWarning], 0
477
.parse_names_loop:
478
        mov     [esi], ebp
479
        add     esi, file_in_7z.size
480
.parse_names_loop_int:
481
        cmp     ebp, [esp]
482
        jae     return.err
483
        call    _7z.ReadWord
484
; UNICODE char -> cp866 char
485
        cmp     ax, 0x80
486
        jb      .id
487
        cmp     ax, 0x401
488
        jz      .yo1
489
        cmp     ax, 0x451
490
        jz      .yo2
491
        cmp     ax, 0x410
492
        jb      .unk
493
        cmp     ax, 0x440
494
        jb      .rus1
495
        cmp     ax, 0x450
496
        jb      .rus2
497
.unk:
498
        cmp     [bWasWarning], 0
499
        jnz     @f
500
        push    ContinueBtn
501
        push    1
502
        push    aEncodingProblem_str_ptr
503
        push    3
504
        push    aEncodingProblem
505
        call    [Message]
506
        inc     [bWasWarning]
507
@@:
508
        mov     al, '_'
509
        jmp     .id
510
.yo1:
511
        mov     al, 'ð'
512
        jmp     .id
513
.yo2:
514
        mov     al, 'ñ'
515
        jmp     .id
516
.rus1:
517
; 0x410-0x43F -> 0x80-0xAF
518
        add     al, 0x70
519
        jmp     .id
520
.rus2:
521
; 0x440-0x44F -> 0xE0-0xEF
522
        add     al, 0xA0
523
.id:
524
        mov     [ebp], al
525
        inc     ebp
526
        test    al, al
527
        jnz     .parse_names_loop_int
528
        loop    .parse_names_loop
529
        pop     eax
530
        call    _7z.UnswitchStream
531
        jmp     .parse_header
532
.parse_winAttr:
533
        mov     edx, [_7z.tmpVector]
534
        push    ebx
535
        mov     ecx, ebx
536
        mov     ebx, edx
537
        call    _7z.ReadBoolVector2
538
        pop     ebx
539
        call    _7z.SwitchStream
540
        mov     esi, [hOut]
541
        add     esi, handle_7z.basesize
542
        mov     ecx, ebx
543
.winAttrLoop:
544
        mov     al, [edx]
545
        inc     edx
546
        mov     [esi+file_in_7z.bAttrDefined], al
547
        test    al, al
548
        jz      @f
549
        call    _7z.ReadDword
550
        mov     [esi+file_in_7z.attr], eax
551
@@:
552
        add     esi, file_in_7z.size
553
        loop    .winAttrLoop
554
        call    _7z.UnswitchStream
555
        jmp     .parse_header
556
.parse_startPos:
557
        mov     edx, [_7z.tmpVector]
558
        push    ebx
559
        mov     ecx, ebx
560
        mov     ebx, edx
561
        call    _7z.ReadBoolVector2
562
        pop     ebx
563
        call    _7z.SwitchStream
564
        mov     esi, [hOut]
565
        add     esi, handle_7z.basesize
566
        mov     ecx, ebx
567
.startPosLoop:
568
        mov     al, [edx]
569
        inc     edx
570
        mov     [esi+file_in_7z.bStartPosDefined], al
571
        test    al, al
572
        jz      @f
573
        call    _7z.ReadDword
574
        mov     dword [esi+file_in_7z.startPos], eax
575
        call    _7z.ReadDword
576
        mov     dword [esi+file_in_7z.startPos+4], eax
577
@@:
578
        add     esi, file_in_7z.size
579
        loop    .startPosLoop
580
        call    _7z.UnswitchStream
581
        jmp     .parse_header
582
.parse_emptyStream:
583
        mov     edx, [_7z.emptyStreams]
584
        push    ebx
585
        mov     ecx, ebx
586
        mov     ebx, edx
587
        call    _7z.ReadBoolVector
588
        pop     ebx
589
        and     [_7z.numEmptyStreams], 0
590
        mov     ecx, ebx
591
.emptyStrLoop:
592
        cmp     byte [edx], 0
593
        jz      @f
594
        inc     [_7z.numEmptyStreams]
595
@@:
596
        inc     edx
597
        loop    .emptyStrLoop
598
        jmp     .parse_header
599
.parse_emptyFile:
600
        push    ebx
601
        mov     ecx, [_7z.numEmptyStreams]
602
        mov     ebx, [_7z.emptyFiles]
603
        call    _7z.ReadBoolVector
604
        pop     ebx
605
        jmp     .parse_header
606
.parse_anti:
607
        push    ebx
608
        mov     ecx, [_7z.numEmptyStreams]
609
        mov     ebx, [_7z.antiFiles]
610
        call    _7z.ReadBoolVector
611
        pop     ebx
612
        jmp     .parse_header
613
.parse_time:
614
        push    ecx
615
        push    ebx
616
        mov     ecx, ebx
617
        mov     ebx, [_7z.tmpVector]
618
        call    _7z.ReadBoolVector2
619
        pop     ebx
620
        call    _7z.SwitchStream
621
        mov     esi, [hOut]
622
        add     esi, handle_7z.basesize
623
        xor     ecx, ecx
624
.timeLoop:
625
        mov     eax, [_7z.tmpVector]
626
        mov     al, [eax+ecx]
627
        pop     edx
628
        push    edx
629
        mov     [esi + file_in_7z.bCreationTimeDefined + edx - kCreationTime], al
630
        test    al, al
631
        jz      @f
632
        call    _7z.ReadDword
633
        push    eax
634
        call    _7z.ReadDword
635
        mov     edx, eax
636
        pop     eax
637
        push    edi
638
        mov     edi, [esp+4]
639
        lea     edi, [esi + file_in_7z.CreationTime + (edi-kCreationTime)*8]
640
        call    ntfs_datetime_to_bdfe
641
        pop     edi
642
@@:
643
        add     esi, file_in_7z.size
644
        inc     ecx
645
        cmp     ecx, ebx
646
        jb      .timeLoop
647
        call    _7z.UnswitchStream
648
        pop     eax
649
        jmp     .parse_header
650
.parse_header_done:
651
        xor     ecx, ecx        ; index in emptyFiles
652
        xor     edx, edx        ; index in subStreams
653
        xor     ebp, ebp        ; index in files
654
        mov     esi, [hOut]
655
        add     esi, handle_7z.basesize
656
.filesLoop:
657
        mov     eax, [_7z.emptyStreams]
658
        mov     al, [eax+ebp]
659
        xor     al, 1
660
        mov     [esi+file_in_7z.bHasStream], al
661
        jz      .nostream
662
        mov     [esi+file_in_7z.bIsDirectory], 0
663
        mov     [esi+file_in_7z.bAnti], 0
664
        mov     eax, [_7z.StreamsInfo.SubStreamsSizes]
665
        push    dword [eax+edx*8]
666
        pop     dword [esi+file_in_7z.UnPackSize]
667
        push    dword [eax+edx*8+4]
668
        pop     dword [esi+file_in_7z.UnPackSize+4]
669
        mov     eax, [_7z.StreamsInfo.SubStreamsCRCsDefined]
670
        mov     al, [eax+edx]
671
        mov     [esi+file_in_7z.bCRCDefined], al
672
        test    al, al
673
        jz      @f
674
        mov     eax, [_7z.StreamsInfo.SubStreamsCRCs]
675
        mov     eax, [eax+edx*4]
676
        mov     [esi+file_in_7z.FileCRC], eax
677
@@:
678
        inc     edx
679
        jmp     .filesCont
680
.nostream:
681
        mov     eax, [_7z.emptyFiles]
682
        cmp     byte [eax+ecx], 0
683
        setz    [esi+file_in_7z.bIsDirectory]
684
        mov     eax, [_7z.antiFiles]
685
        cmp     byte [eax+ecx], 0
686
        setnz   [esi+file_in_7z.bAnti]
687
        and     dword [esi+file_in_7z.UnPackSize], 0
688
        and     dword [esi+file_in_7z.UnPackSize+4], 0
689
        mov     [esi+file_in_7z.bCRCDefined], 0
690
        inc     ecx
691
.filesCont:
692
        inc     ebp
693
        add     esi, file_in_7z.size
694
        dec     ebx
695
        jnz     .filesLoop
696
        mov     ecx, [_7z.tmpVector]
697
        call    [pgfree]
698
        and     [_7z.tmpVector], 0
699
        mov     ebx, [_7z.dataVectorSize]
700
        test    ebx, ebx
701
        jz      @f
702
        call    _7z.ReadAndDecodePackedStreams.free2
703
        and     [_7z.dataVectorSize], 0
704
@@:
705
        mov     ecx, [_7z.FreeSubStreams]
706
        jecxz   @f
707
        call    [pgfree]
708
        and     [_7z.FreeSubStreams], 0
709
@@:
710
        mov     ecx, [bufptr]
711
        cmp     ecx, buffer
712
        jz      @f
713
        call    [pgfree]
714
        mov     [bufptr], buffer
715
@@:
716
        xor     esi, esi        ; index of folder
717
        mov     edi, [hOut]
718
        mov     ebx, [edi+handle_7z.NumFiles]
719
        add     edi, handle_7z.basesize ; pointer to fileinfo
720
        push    0               ; start index of packed stream for folder
721
.getfoldersloop0:
722
        xor     edx, edx        ; index in folder
723
        push    edx edx         ; position in folder
724
.getfoldersloop:
725
        dec     ebx
726
        js      .getfoldersdone
727
        cmp     [edi+file_in_7z.bHasStream], 0
728
        jnz     @f
729
        test    edx, edx
730
        jz      .nofolder
731
@@:
732
        test    edx, edx
733
        jnz     .notfirst
734
; skip empty folders
735
@@:
736
        mov     eax, [hOut]
737
        cmp     esi, [eax+handle_7z.numFolders]
738
        jae     return.err
739
        mov     eax, [eax+handle_7z.folders]
740
        mov     eax, [eax+esi*4]
741
        cmp     edx, [eax+_7z.StreamsInfo.numUnPackStreams]
742
        jb      @f
743
        inc     esi
744
        jmp     @b
745
@@:
746
.notfirst:
747
        mov     [edi+file_in_7z.folder], esi
748
        mov     [edi+file_in_7z.folder_index], edx
749
        mov     eax, [esp]
750
        mov     dword [edi+file_in_7z.folderStart], eax
751
        mov     eax, [esp+4]
752
        mov     dword [edi+file_in_7z.folderStart+4], eax
753
        mov     ecx, dword [edi+file_in_7z.UnPackSize]
754
        add     [esp], ecx
755
        mov     ecx, dword [edi+file_in_7z.UnPackSize+4]
756
        adc     [esp+4], ecx
757
        add     edi, file_in_7z.size
758
        inc     edx
759
        mov     eax, [hOut]
760
        mov     eax, [eax+handle_7z.folders]
761
        mov     eax, [eax+esi*4]
762
        cmp     edx, [eax+_7z.StreamsInfo.numUnPackStreams]
763
        jb      .getfoldersloop
764
        inc     esi
765
        pop     edx edx
766
        jmp     .getfoldersloop0
767
.nofolder:
768
        push    -1
769
        pop     eax
770
        mov     [edi+file_in_7z.folder], eax
771
        mov     [edi+file_in_7z.folder_index], eax
772
        mov     dword [edi+file_in_7z.folderStart], eax
773
        mov     dword [edi+file_in_7z.folderStart+4], eax
774
        add     edi, file_in_7z.size
775
        jmp     .getfoldersloop
776
.getfoldersdone:
777
        pop     eax eax eax
778
        mov     ebp, [hOut]
779
        mov     esi, [ebp+handle_7z.folders]
780
        xor     ebx, ebx
781
        cmp     ebx, [ebp+handle_7z.numFolders]
782
        jae     .getoffsdone
783
.getoffsloop:
784
        lodsd
785
        test    ebx, ebx
786
        jnz     .getoffs2
787
        mov     edx, dword [_7z.StreamsInfo.dataOffset]
788
        mov     dword [eax+_7z.StreamsInfo.packOffset], edx
789
        mov     edx, dword [_7z.StreamsInfo.dataOffset+4]
790
        mov     dword [eax+_7z.StreamsInfo.packOffset+4], edx
791
        jmp     .getoffscont
792
.getoffs2:
793
        mov     ecx, [esi-8]
794
        mov     edx, dword [ecx+_7z.StreamsInfo.packOffset]
795
        mov     dword [eax+_7z.StreamsInfo.packOffset], edx
796
        mov     edx, dword [ecx+_7z.StreamsInfo.packOffset+4]
797
        mov     dword [eax+_7z.StreamsInfo.packOffset+4], edx
798
        mov     edi, [ecx+_7z.StreamsInfo.startPackedStream]
799
        mov     ecx, [ecx+_7z.StreamsInfo.numPackedStreams]
800
        push    ecx
801
        add     ecx, edi
802
        cmp     ecx, [ebp+handle_7z.numPackStreams]
803
        ja      return.err
804
        pop     ecx
805
        shl     edi, 3
806
        add     edi, [ebp+handle_7z.packSizes]
807
@@:
808
        dec     ecx
809
        js      @f
810
        mov     edx, [edi]
811
        add     dword [eax+_7z.StreamsInfo.packOffset], edx
812
        mov     edx, [edi+4]
813
        adc     dword [eax+_7z.StreamsInfo.packOffset+4], edx
814
        add     edi, 8
815
        jmp     @b
816
@@:
817
.getoffscont:
818
        inc     ebx
819
        cmp     ebx, [ebp+handle_7z.numFolders]
820
        jb      .getoffsloop
821
.getoffsdone:
822
        mov     edx, [hOut]
823
        mov     ebx, [edx+handle_7z.NumFiles]
824
        lea     edi, [edx+handle_7z.root.subfolders]
825
        add     edx, handle_7z.basesize
826
        push    file_in_7z.size
827
        call    init_file_links
828
        mov     eax, [hOut]
829
        and     [eax+handle_7z.curdir], 0       ; set root directory
830
        mov     esi, [inStream]
831
        mov     [eax+handle_7z.host], esi
832
        lea     edi, [eax+handle_7z.host_datetime]
631 diamond 833
        mov     esi, [esp+12]
589 diamond 834
        add     esi, 8
835
        mov     ecx, 6
836
        rep     movsd
837
        ret
838
 
839
_7z.CloseHandle:
840
        mov     esi, ecx
841
        push    [esi+handle_7z.host]
842
        call    [close]
843
        mov     ecx, [esi+handle_7z.packSizes]
844
        call    [pgfree]
845
        mov     ecx, [esi+handle_7z.folders]
846
        call    [pgfree]
847
        mov     ecx, [esi+handle_7z.names_buf]
848
        call    [pgfree]
849
        mov     ecx, [esi+handle_7z.last_context]
850
        jecxz   @f
851
        call    [pgfree]
852
@@:
853
        mov     ecx, esi
854
        call    [pgfree]
855
        ret
856
 
857
close_7z:
858
        mov     ecx, [esp+4]
859
        cmp     ecx, empty_7z_handle
860
        jz      @f
861
        call    _7z.CloseHandle
862
@@:
863
        ret     4
864
 
865
uglobal
866
align 4
867
_7z.unpacked    dd      ?
868
_7z.unpbuf      rd      2*8
869
_7z.CurInStream dd      ?
870
_7z.dataVector  dd      ?
871
_7z.dataVectorSize dd   ?
872
_7z.FreeSubStreams dd   ?
873
_7z.tmpVector   dd      ?
874
_7z.emptyStreams dd     ?
875
_7z.numEmptyStreams dd  ?
876
_7z.emptyFiles  dd      ?
877
_7z.antiFiles   dd      ?
878
endg
879
 
880
_7z.ReadAndDecodePackedStreams:
881
        call    _7z.ReadStreamsInfo
882
        mov     ecx, [_7z.StreamsInfo.numFolders]
883
        test    ecx, ecx
884
        jz      .ret2
885
        push    ecx
886
        mov     ecx, [_7z.StreamsInfo.SubStreamsSizes]
887
        jecxz   @f
888
        call    [pgfree]
889
        and     [_7z.StreamsInfo.SubStreamsSizes], 0
890
@@:
891
        pop     ecx
892
        mov     eax, _7z.unpbuf
893
        cmp     ecx, 8
894
        jbe     .1
895
        shl     ecx, 3
896
        call    [pgalloc]
897
        test    eax, eax
898
        jz      return.clear
899
        mov     esi, eax
900
@@:
901
        and     dword [esi], 0
902
        add     esi, 4
903
        sub     ecx, 4
904
        jnz     @b
905
.1:
906
        mov     [_7z.unpacked], eax
907
        mov     esi, eax
908
        xor     ecx, ecx
909
        mov     [_7z.CurInStream], ecx
910
        mov     [error_proc], .error
911
        mov     [clear_proc], .clear
912
.loop:
913
        mov     eax, [_7z.StreamsInfo.folders]
914
        mov     ebx, [eax+ecx*4]
915
        call    _7z.GetUnPackSize
916
        test    edx, edx
917
        jnz     return.err
918
        test    eax, eax
919
        js      return.err
920
        push    ecx
921
        mov     [esi], eax
922
        mov     [_7z.decode.outBufferSize], eax
923
        mov     ecx, eax
924
        call    [pgalloc]
925
        test    eax, eax
926
        jz      return.err
927
        mov     [esi+4], eax
928
        mov     [_7z.decode.outBufferPtr], eax
929
        push    esi
930
        call    _7z.decode
931
        pop     esi
932
        pop     ecx
933
        push    ecx
934
        mov     eax, [_7z.StreamsInfo.unpackCRCsDefined]
935
        cmp     byte [eax+ecx], 0
936
        jz      @f
937
        push    esi
938
        mov     ecx, [esi]
939
        mov     esi, [esi+4]
940
        call    crc
941
        pop     esi
942
        pop     ecx
943
        push    ecx
944
        mov     edx, [_7z.StreamsInfo.unpackCRCs]
945
        cmp     [edx+ecx*4], eax
946
        jnz     return.err
947
@@:
948
        add     esi, 8
949
        pop     ecx
950
        inc     ecx
951
        cmp     ecx, [_7z.StreamsInfo.numFolders]
952
        jb      .loop
953
.ret:
954
        mov     ecx, [_7z.StreamsInfo.folders]
955
        call    [pgfree]
956
        mov     [error_proc], .error2
957
        mov     [clear_proc], .clear2
958
.ret2:
959
        mov     ecx, [_7z.StreamsInfo.packSizes]
960
        call    [pgfree]
961
        ret
962
 
963
.error:
964
        call    .free
965
        jmp     _7z.ReadStreamsInfo.error
966
.clear:
967
        call    .free
968
        jmp     _7z.ReadStreamsInfo.clear
969
.error2:
970
        call    .free
971
        jmp     open_7z.header_error
972
.clear2:
973
        call    .free
974
        jmp     open_7z.clear
975
.free:
976
        mov     ebx, [_7z.StreamsInfo.numFolders]
977
.free2:
978
        dec     ebx
979
        js      @f
980
        mov     ecx, [_7z.unpacked]
981
        mov     ecx, [ecx+ebx*8+4]
982
        call    [pgfree]
983
        jmp     .free2
984
@@:
985
        mov     ecx, [_7z.unpacked]
986
        cmp     ecx, _7z.unpbuf
987
        jz      @f
988
        call    [pgfree]
989
@@:
990
        ret
991
 
992
_7z.GetUnPackSize:
993
        xor     edx, edx
994
        mov     eax, [ebx+_7z.StreamsInfo.numOutStreams]
995
        test    eax, eax
996
        jz      .ret
997
.scan:
998
        dec     eax
999
        js      return.err
1000
        push    ecx
1001
        mov     ecx, [ebx+_7z.StreamsInfo.numBindPairs]
1002
        mov     edx, [ebx+_7z.StreamsInfo.bindPairs]
1003
@@:
1004
        add     edx, 8
1005
        dec     ecx
1006
        js      .found
1007
        cmp     [edx-4], eax
1008
        jnz     @b
1009
        pop     ecx
1010
        jmp     .scan
1011
.found:
1012
        mov     [ebx+_7z.StreamsInfo.mainOutStream], eax
1013
        mov     ecx, [ebx+_7z.StreamsInfo.unpackSizes]
1014
        mov     edx, [ecx+eax*8+4]
1015
        mov     eax, [ecx+eax*8]
1016
        pop     ecx
1017
.ret:
1018
        ret
1019
 
1020
uglobal
1021
align 4
1022
_7z.StreamsInfo:
1023
.numPackStreams dd      ?
1024
.packSizes      dd      ?       ; 8 bytes per item
1025
.numFolders     dd      ?
1026
.unpackCRCsDefined dd   ?
1027
.unpackCRCs     dd      ?
1028
.folders        dd      ?
1029
.folders.size   dd      ?
1030
.folders.alloc  dd      ?
1031
.dataOffset     dq      ?
1032
.packCRCsDefined dd     ?       ; 1 byte per item
1033
.packCRCs       dd      ?       ; 4 bytes per item
1034
virtual at 0
1035
.numCoders      dd      ?
1036
.bindPairs      dd      ?
1037
.numBindPairs   dd      ?
1038
.packedStreams  dd      ?
1039
.numPackedStreams dd    ?
1040
.startPackedStream dd   ?
1041
.numOutStreams  dd      ?
1042
.unpackSizes    dd      ?
1043
.mainOutStream  dd      ?
1044
.numUnPackStreams dd    ?
1045
.packOffset     dq      ?
1046
.fsz = $
1047
end virtual
1048
.numSubStreams  dd      ?
1049
.SubStreamsSizes dd     ?
1050
.SubStreamsCRCsDefined dd ?
1051
.SubStreamsCRCs dd      ?
1052
.tmpSubStreamsCRCsDefined dd ?
1053
.tmpSubStreamsCRCs dd   ?
1054
endg
1055
 
1056
_7z.SkipData:
1057
        call    _7z.ReadNumber
1058
        call    _7z.SkipSize
1059
        ret
1060
 
1061
_7z.WaitAttribute:
1062
        call    _7z.ReadNumber
1063
        cmp     eax, ecx
1064
        jz      @f
1065
        test    eax, eax
1066
        jz      return.err
1067
        call    _7z.SkipData
1068
        jmp     _7z.WaitAttribute
1069
@@:
1070
        ret
1071
 
1072
_7z.ReadBoolVector2:
1073
; in: ebx->vector, ecx=size
1074
        call    _7z.ReadByte
1075
        test    al, al
1076
        jz      _7z.ReadBoolVector
1077
        push    ebx ecx
1078
        jecxz   .ret
1079
@@:
1080
        mov     byte [ebx], 1
1081
        inc     ebx
1082
        loop    @b
1083
.ret:
1084
        pop     ecx ebx
1085
        ret
1086
 
1087
_7z.ReadBoolVector:
1088
        push    ebx ecx
1089
        jecxz   .ret
1090
        xor     eax, eax
1091
.1:
1092
        add     al, al
1093
        jnz     @f
1094
        call    _7z.ReadByte
1095
        stc
1096
        adc     al, al
1097
@@:
1098
        setc    byte [ebx]
1099
        inc     ebx
1100
        loop    .1
1101
.ret:
1102
        pop     ecx ebx
1103
        ret
1104
 
1105
_7z.ReadHashDigests:
1106
; in: ebx->bool vector, esi->crc, ecx=size
1107
        call    _7z.ReadBoolVector2
1108
        jecxz   .ret
1109
.1:
1110
        xor     eax, eax
1111
        cmp     byte [ebx], al
1112
        jz      @f
1113
        call    _7z.ReadDword
1114
@@:
1115
        mov     [esi], eax
1116
        add     esi, 4
1117
        inc     ebx
1118
        loop    .1
1119
.ret:
1120
        ret
1121
 
1122
uglobal
1123
_7z.saved_edi   dd      ?
1124
_7z.saved_edi_end dd    ?
1125
endg
1126
 
1127
_7z.SwitchStream:
1128
        mov     eax, [bufend]
1129
        mov     [_7z.saved_edi_end], eax
1130
        call    _7z.ReadByte
1131
        test    al, al
1132
        jnz     @f
1133
        ret
1134
@@:
1135
        call    _7z.ReadNum
1136
        mov     [_7z.saved_edi], edi
1137
        cmp     eax, [_7z.dataVectorSize]
1138
        jae     return.err
1139
        shl     eax, 3
1140
        add     eax, [_7z.dataVector]
1141
        mov     edi, [eax+4]
1142
        mov     eax, [eax]
1143
        add     eax, edi
1144
        mov     [bufend], eax
1145
        ret
1146
 
1147
_7z.UnswitchStream:
1148
        mov     eax, [_7z.saved_edi_end]
1149
        cmp     eax, [bufend]
1150
        jnz     @f
1151
        ret
1152
@@:
1153
        mov     [bufend], eax
1154
        mov     edi, [_7z.saved_edi]
1155
@@:
1156
        ret
1157
 
1158
; 6 ¯à®£à ¬¬¨á⮢ ¯ëâ «¨áì ª®¤ ¯®­ïâì,
1159
; Ž¤¨­ ¨§ ­¨å á®èñ« á 㬠, ¨ ¨å ®áâ «®áì 5.
1160
 
1161
_7z.ReadStreamsInfo:
1162
        xor     eax, eax
1163
        mov     [_7z.StreamsInfo.numPackStreams], eax
1164
        mov     [_7z.StreamsInfo.packSizes], eax
1165
        mov     [_7z.StreamsInfo.numFolders], eax
1166
        mov     [_7z.StreamsInfo.folders], eax
1167
        mov     [_7z.StreamsInfo.numSubStreams], eax
1168
        mov     [_7z.StreamsInfo.SubStreamsSizes], eax
1169
        mov     [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], eax
1170
        mov     [error_proc], .error
1171
        mov     [clear_proc], .clear
1172
.mainloop:
1173
        call    _7z.ReadNum
1174
        test    eax, eax
1175
        jz      @b
1176
        cmp     eax, kSubStreamsInfo
1177
        jz      .SubStreamsInfo
1178
        cmp     eax, kUnPackInfo
1179
        jz      .UnpackInfo
1180
        cmp     eax, kPackInfo
1181
        jnz     return.err
1182
 
1183
.PackInfo:
1184
        cmp     [_7z.StreamsInfo.numPackStreams], 0
1185
        jnz     return.err
1186
        call    _7z.ReadNumber
1187
        add     eax, 0x20
1188
        adc     edx, 0
1189
        mov     dword [_7z.StreamsInfo.dataOffset], eax
1190
        mov     dword [_7z.StreamsInfo.dataOffset+4], edx
1191
        call    _7z.ReadNum
1192
        mov     [_7z.StreamsInfo.numPackStreams], eax
1193
        mov     ecx, kSize
1194
        call    _7z.WaitAttribute
1195
        mov     ecx, [_7z.StreamsInfo.numPackStreams]
1196
        imul    ecx, 8+1+4
1197
        jecxz   .nostreams1
1198
        call    [pgalloc]
1199
        test    eax, eax
1200
        jz      return.clear
1201
        mov     [_7z.StreamsInfo.packSizes], eax
1202
        mov     ecx, [_7z.StreamsInfo.numPackStreams]
1203
        push    eax
1204
        lea     eax, [eax+ecx*8]
1205
        mov     [_7z.StreamsInfo.packCRCsDefined], eax
1206
        mov     ebx, eax
1207
        add     eax, ecx
1208
        mov     [_7z.StreamsInfo.packCRCs], eax
1209
@@:
1210
        mov     byte [ebx], 0
1211
        inc     ebx
1212
        loop    @b
1213
        pop     eax
1214
.nostreams1:
1215
        mov     ecx, [_7z.StreamsInfo.numPackStreams]
1216
        jecxz   .noloop1
1217
        mov     esi, eax
1218
@@:
1219
        call    _7z.ReadNumber
1220
        mov     [esi], eax
1221
        mov     [esi+4], edx
1222
        add     esi, 8
1223
        loop    @b
1224
.noloop1:
1225
        call    _7z.ReadNum
1226
        test    eax, eax
1227
        jz      .mainloop
1228
        cmp     eax, kCRC
1229
        jz      .packInfo.crc
1230
        call    _7z.SkipData
1231
        jmp     .noloop1
1232
.packInfo.crc:
1233
        mov     esi, [_7z.StreamsInfo.packCRCs]
1234
        mov     ebx, [_7z.StreamsInfo.packCRCsDefined]
1235
        mov     ecx, [_7z.StreamsInfo.numPackStreams]
1236
        call    _7z.ReadHashDigests
1237
        jmp     .noloop1
1238
 
1239
.UnpackInfo:
1240
        cmp     [_7z.StreamsInfo.folders], 0
1241
        jnz     return.err
1242
        mov     ecx, kFolder
1243
        call    _7z.WaitAttribute
1244
        call    _7z.ReadNum
1245
        mov     ecx, eax
1246
        mov     [_7z.StreamsInfo.numFolders], eax
1247
        call    _7z.SwitchStream
1248
        test    ecx, ecx
1249
        jz      .nofolders
1250
        push    ecx
1251
        mov     ecx, 0x1000
1252
        and     [_7z.StreamsInfo.folders.size], 0
1253
        mov     [_7z.StreamsInfo.folders.alloc], ecx
1254
        call    [pgalloc]
1255
        test    eax, eax
1256
        jz      return.clear
1257
        mov     [_7z.StreamsInfo.folders], eax
1258
        pop     ecx
1259
        lea     ecx, [ecx*9]
1260
        call    .folders_alloc
1261
        xor     ecx, ecx
1262
.folderloop:
1263
        mov     eax, [_7z.StreamsInfo.folders]
1264
        push    [_7z.StreamsInfo.folders.size]
1265
        pop     dword [eax+ecx*4]
1266
        push    ebp
1267
        mov     [_ebp], ebp
1268
        push    ecx
1269
        mov     ecx, _7z.StreamsInfo.fsz
1270
        call    .folders_alloc
1271
        mov     ebp, eax
1272
        add     ebp, [_7z.StreamsInfo.folders]
1273
        call    _7z.ReadNum
1274
        mov     [ebp+_7z.StreamsInfo.numCoders], eax
1275
        test    eax, eax
1276
        jz      return.err
1277
        mov     ecx, eax
1278
        push    ecx
1279
        shl     ecx, 2
1280
        sub     ebp, [_7z.StreamsInfo.folders]
1281
        call    .folders_alloc
1282
        add     ebp, [_7z.StreamsInfo.folders]
1283
        pop     ecx
1284
        add     eax, [_7z.StreamsInfo.folders]
1285
@@:
1286
        and     dword [eax], 0
1287
        add     eax, 4
1288
        loop    @b
1289
        push    0       ; numOutStreams
1290
        push    0       ; numInStreams
1291
; [folders] = array of pointers to coders info
1292
; Format of coder info:
1293
; dd NextCoder
1294
; db MethodID.IDSize
1295
; times IDSize db MethodID.ID
1296
; dd NumInStreams
1297
; dd NumOutStreams
1298
; dd PropSize
1299
; times PropSize db Properties
1300
        xor     esi, esi
1301
.coders_loop:
1302
        call    _7z.ReadByte
1303
        mov     dl, al
1304
        and     eax, 0xF
1305
        lea     ecx, [eax+17]
1306
        sub     ebp, [_7z.StreamsInfo.folders]
1307
        call    .folders_alloc
1308
        add     ebp, [_7z.StreamsInfo.folders]
1309
        push    eax
1310
        mov     ecx, [_7z.StreamsInfo.folders]
1311
        lea     ebx, [ebp+esi*4+_7z.StreamsInfo.fsz]
1312
@@:
1313
        cmp     dword [ebx], 0
1314
        jz      @f
1315
        mov     ebx, [ebx]
1316
        add     ebx, ecx
1317
        jmp     @b
1318
@@:
1319
        mov     [ebx], eax
1320
        pop     ebx
1321
        add     ebx, ecx
1322
        and     dword [ebx], 0
1323
        add     ebx, 4
1324
        mov     ecx, edx
1325
        and     ecx, 0xF
1326
        mov     byte [ebx], cl
1327
        inc     ebx
1328
        jecxz   .2
1329
@@:
1330
        call    _7z.ReadByte
1331
        mov     byte [ebx], al
1332
        inc     ebx
1333
        loop    @b
1334
.2:
1335
        test    dl, 10h
1336
        jnz     .coder_multiple_streams
1337
        mov     dword [ebx], 1
1338
        mov     dword [ebx+4], 1
1339
        inc     dword [esp]
1340
        inc     dword [esp+4]
1341
        jmp     @f
1342
.coder_multiple_streams:
1343
        call    _7z.ReadNum
1344
        mov     [ebx], eax
1345
        add     dword [esp], eax
1346
        call    _7z.ReadNum
1347
        mov     [ebx+4], eax
1348
        add     dword [esp+4], eax
1349
; all currently defined 7z coders have 1 unpacked stream
1350
; moreover, all reasonable coders have 1 unpacked stream
1351
; so assume 1 output stream for unpacker - this simplifies decoding procedure
1352
        cmp     eax, 1
1353
        jnz     return.err
1354
@@:
1355
        and     dword [ebx+8], 0
1356
        add     ebx, 12
1357
        test    dl, 20h
1358
        jz      .coder_no_properties
1359
        call    _7z.ReadNum
1360
        test    eax, eax
1361
        jz      .coder_no_properties
1362
        mov     [ebx-4], eax
1363
        mov     ecx, eax
1364
        sub     ebx, [_7z.StreamsInfo.folders]
1365
        sub     ebp, [_7z.StreamsInfo.folders]
1366
        call    .folders_alloc
1367
        add     ebp, [_7z.StreamsInfo.folders]
1368
        add     ebx, [_7z.StreamsInfo.folders]
1369
@@:
1370
        call    _7z.ReadByte
1371
        mov     [ebx], al
1372
        inc     ebx
1373
        loop    @b
1374
.coder_no_properties:
1375
        test    dl, dl
1376
        js      .coders_loop
1377
        inc     esi
1378
        cmp     esi, [ebp+_7z.StreamsInfo.numCoders]
1379
        jb      .coders_loop
1380
        mov     [ebp+_7z.StreamsInfo.numUnPackStreams], 1
1381
        mov     eax, [esp+4]
1382
        dec     eax
1383
        js      return.err
1384
        mov     [ebp+_7z.StreamsInfo.numBindPairs], eax
1385
        push    eax
1386
        mov     ecx, eax
1387
        shl     ecx, 3
1388
        sub     ebp, [_7z.StreamsInfo.folders]
1389
        call    .folders_alloc
1390
        add     ebp, [_7z.StreamsInfo.folders]
1391
        mov     [ebp+_7z.StreamsInfo.bindPairs], eax
1392
        pop     ecx
1393
        jecxz   .noloop3
1394
        mov     esi, eax
1395
        add     esi, [_7z.StreamsInfo.folders]
1396
@@:
1397
        call    _7z.ReadNum
1398
        mov     [esi], eax
1399
        cmp     eax, [esp]
1400
        jae     return.err
1401
        call    _7z.ReadNum
1402
        mov     [esi+4], eax
1403
        cmp     eax, [esp+4]
1404
        jae     return.err
1405
        add     esi, 8
1406
        loop    @b
1407
.noloop3:
1408
        pop     eax     ; numInStreams
1409
        pop     edx     ; numOutStreams
1410
        mov     [ebp+_7z.StreamsInfo.numOutStreams], edx
1411
        sub     eax, edx
1412
        js      return.err
1413
        inc     eax
1414
        mov     [ebp+_7z.StreamsInfo.numPackedStreams], eax
1415
        mov     ecx, eax
1416
        push    eax
1417
        shl     ecx, 2
1418
        sub     ebp, [_7z.StreamsInfo.folders]
1419
        call    .folders_alloc
1420
        add     ebp, [_7z.StreamsInfo.folders]
1421
        mov     [ebp+_7z.StreamsInfo.packedStreams], eax
1422
        pop     ecx
1423
        mov     esi, eax
1424
        add     esi, [_7z.StreamsInfo.folders]
1425
        cmp     ecx, 1
1426
        jnz     .multiplePackedStreams
1427
        mov     ebx, [ebp+_7z.StreamsInfo.bindPairs]
1428
        add     ebx, [_7z.StreamsInfo.folders]
1429
        push    edx
1430
        xor     ecx, ecx
1431
.3:
1432
        push    ebx
1433
        mov     edx, [ebp+_7z.StreamsInfo.numBindPairs]
1434
@@:
1435
        dec     edx
1436
        js      .5
1437
        cmp     dword [ebx], ecx
1438
        jz      .4
1439
        add     ebx, 8
1440
        jmp     @b
1441
.4:
1442
        pop     ebx
1443
        inc     ecx
1444
        jmp     .3
1445
.5:
1446
        pop     ebx
1447
        pop     edx
1448
        mov     [esi], ecx
1449
        jmp     .commonPackedStreams
1450
.multiplePackedStreams:
1451
        call    _7z.ReadNum
1452
        mov     [esi], eax
1453
        add     esi, 4
1454
        loop    .multiplePackedStreams
1455
.commonPackedStreams:
1456
        mov     ecx, edx
1457
        shl     ecx, 3
1458
        sub     ebp, [_7z.StreamsInfo.folders]
1459
        call    .folders_alloc
1460
        add     ebp, [_7z.StreamsInfo.folders]
1461
        mov     [ebp+_7z.StreamsInfo.unpackSizes], eax
1462
        pop     ecx
1463
        xor     edx, edx
1464
        jecxz   @f
1465
        mov     eax, [_7z.StreamsInfo.folders]
1466
        mov     eax, [eax+(ecx-1)*4]
1467
        add     eax, [_7z.StreamsInfo.folders]
1468
        mov     edx, [eax+_7z.StreamsInfo.numPackedStreams]
1469
        add     edx, [eax+_7z.StreamsInfo.startPackedStream]
1470
@@:
1471
        mov     [ebp+_7z.StreamsInfo.startPackedStream], edx
1472
        pop     ebp
1473
        inc     ecx
1474
        cmp     ecx, [_7z.StreamsInfo.numFolders]
1475
        jb      .folderloop
1476
.nofolders:
1477
        call    _7z.UnswitchStream
1478
        mov     ecx, kCodersUnPackSize
1479
        call    _7z.WaitAttribute
1480
        xor     ecx, ecx
1481
.6:
1482
        cmp     ecx, [_7z.StreamsInfo.numFolders]
1483
        jae     .7
1484
        mov     eax, [_7z.StreamsInfo.folders]
1485
        push    ebp
1486
        mov     ebp, [eax+ecx*4]
1487
        add     ebp, eax
1488
        mov     esi, [ebp+_7z.StreamsInfo.numOutStreams]
1489
        mov     ebp, [ebp+_7z.StreamsInfo.unpackSizes]
1490
        add     ebp, [_7z.StreamsInfo.folders]
1491
@@:
1492
        call    _7z.ReadNumber
1493
        mov     dword [ebp], eax
1494
        mov     dword [ebp+4], edx
1495
        add     ebp, 8
1496
        dec     esi
1497
        jnz     @b
1498
        pop     ebp
1499
        inc     ecx
1500
        jmp     .6
1501
.7:
1502
; convert all relative addresses to pointers
1503
        xor     ecx, ecx
1504
        mov     edx, [_7z.StreamsInfo.folders]
1505
.8:
1506
        cmp     ecx, [_7z.StreamsInfo.numFolders]
1507
        jae     .9
1508
        lea     eax, [edx+ecx*4]
1509
        add     [eax], edx
1510
        mov     eax, [eax]
1511
        add     [eax+_7z.StreamsInfo.bindPairs], edx
1512
        add     [eax+_7z.StreamsInfo.packedStreams], edx
1513
        add     [eax+_7z.StreamsInfo.unpackSizes], edx
1514
        mov     ebx, [eax+_7z.StreamsInfo.numCoders]
1515
        add     eax, _7z.StreamsInfo.fsz
1516
        inc     ecx
1517
.11:
1518
        dec     ebx
1519
        js      .8
1520
        push    eax
1521
@@:
1522
        cmp     dword [eax], 0
1523
        jz      @f
1524
        add     [eax], edx
1525
        mov     eax, [eax]
1526
        jmp     @b
1527
@@:
1528
        pop     eax
1529
        add     eax, 4
1530
        jmp     .11
1531
.9:
1532
; done
1533
        mov     eax, [_7z.StreamsInfo.numFolders]
1534
        lea     edx, [edx+eax*4]
1535
        mov     [_7z.StreamsInfo.unpackCRCsDefined], edx
1536
        add     edx, eax
1537
        mov     [_7z.StreamsInfo.unpackCRCs], edx
1538
@@:
1539
        call    _7z.ReadNum
1540
        test    eax, eax
1541
        jz      .mainloop
1542
        cmp     eax, kCRC
1543
        jz      .unpackInfo.crc
1544
        call    _7z.SkipData
1545
        jmp     @b
1546
.unpackInfo.crc:
1547
        mov     esi, [_7z.StreamsInfo.unpackCRCs]
1548
        mov     ebx, [_7z.StreamsInfo.unpackCRCsDefined]
1549
        mov     ecx, [_7z.StreamsInfo.numFolders]
1550
        call    _7z.ReadHashDigests
1551
        jmp     @b
1552
 
1553
.SubStreamsInfo:
1554
        cmp     [_7z.StreamsInfo.numFolders], 0
1555
        jz      return.err
1556
        cmp     [_7z.StreamsInfo.numSubStreams], 0
1557
        jnz     return.err
1558
        mov     ebx, [_7z.StreamsInfo.folders]
1559
.ssloop1:
1560
        call    _7z.ReadNum
1561
        cmp     eax, kNumUnPackStream
1562
        jz      .NumUnPackStream
1563
        cmp     eax, kCRC
1564
        jz      .break1
1565
        cmp     eax, kSize
1566
        jz      .break1
1567
        test    eax, eax
1568
        jz      .break1
1569
        call    _7z.SkipData
1570
        jmp     .ssloop1
1571
.NumUnPackStream:
1572
        xor     ecx, ecx
1573
@@:
1574
        call    _7z.ReadNum
1575
        mov     edx, [ebx+ecx*4]
1576
        mov     [edx+_7z.StreamsInfo.numUnPackStreams], eax
1577
        inc     ecx
1578
        cmp     ecx, [_7z.StreamsInfo.numFolders]
1579
        jb      @b
1580
        jmp     .ssloop1
1581
.break1:
1582
; calculate number of substreams and number of defined digests
1583
        xor     ecx, ecx
1584
        xor     ebp, ebp
1585
        push    0
1586
        push    eax
1587
        xor     eax, eax
1588
.ssloop2:
1589
        mov     edx, [ebx+ecx*4]
1590
        mov     edx, [edx+_7z.StreamsInfo.numUnPackStreams]
1591
        cmp     edx, 1
1592
        jz      @f
1593
        inc     ebp
1594
@@:
1595
        add     eax, edx
1596
        jc      return.err
1597
        cmp     edx, 1
1598
        jnz     @f
1599
        push    eax
1600
        mov     eax, [_7z.StreamsInfo.unpackCRCsDefined]
1601
        cmp     byte [eax+ecx], 0
1602
        pop     eax
1603
        jz      @f
1604
        xor     edx, edx
1605
@@:
1606
        add     [esp+4], edx
1607
        inc     ecx
1608
        cmp     ecx, [_7z.StreamsInfo.numFolders]
1609
        jb      .ssloop2
1610
        mov     [_7z.StreamsInfo.numSubStreams], eax
1611
        imul    ecx, eax, 4+8+1
1612
        jecxz   .noss1
1613
        push    eax
1614
        call    [pgalloc]
1615
        pop     ecx
1616
        test    eax, eax
1617
        jz      return.clear
1618
        mov     [_7z.StreamsInfo.SubStreamsSizes], eax
1619
        lea     eax, [eax+ecx*8]
1620
        mov     [_7z.StreamsInfo.SubStreamsCRCsDefined], eax
1621
        add     eax, ecx
1622
        mov     [_7z.StreamsInfo.SubStreamsCRCs], eax
1623
@@:
1624
        dec     eax
1625
        mov     byte [eax], 0
1626
        loop    @b
1627
.noss1:
1628
        mov     ecx, [esp+4]
1629
        jecxz   @f
1630
        imul    ecx, 4+1
1631
        call    [pgalloc]
1632
        test    eax, eax
1633
        jz      return.clear
1634
        mov     [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], eax
1635
        add     eax, [esp+4]
1636
        mov     [_7z.StreamsInfo.tmpSubStreamsCRCs], eax
1637
@@:
1638
        test    ebp, ebp
1639
        jz      @f
1640
        cmp     dword [esp], kSize
1641
        jnz     return.err
1642
@@:
1643
        xor     ecx, ecx
1644
        mov     ebp, [_7z.StreamsInfo.SubStreamsSizes]
1645
.ssloop3:
1646
        mov     ebx, [_7z.StreamsInfo.folders]
1647
        mov     ebx, [ebx+ecx*4]
1648
        mov     eax, [ebx+_7z.StreamsInfo.numUnPackStreams]
1649
        dec     eax
1650
        js      .sscont3
1651
        push    0
1652
        push    0
1653
@@:
1654
        dec     eax
1655
        js      @f
1656
        push    eax
1657
        call    _7z.ReadNumber
1658
        mov     [ebp], eax
1659
        mov     [ebp+4], edx
1660
        add     ebp, 8
1661
        add     [esp+4], eax
1662
        adc     [esp+8], edx
1663
        jc      return.err
1664
        pop     eax
1665
        jmp     @b
1666
@@:
1667
        call    _7z.GetUnPackSize
1668
        sub     eax, [esp]
1669
        sbb     edx, [esp+4]
1670
        jc      return.err
1671
        mov     [ebp], eax
1672
        mov     [ebp+4], edx
1673
        add     ebp, 8
1674
        add     esp, 8
1675
.sscont3:
1676
        inc     ecx
1677
        cmp     ecx, [_7z.StreamsInfo.numFolders]
1678
        jb      .ssloop3
1679
        pop     eax
1680
        cmp     eax, kSize
1681
        jnz     @f
1682
        call    _7z.ReadNum
1683
@@:
1684
        cmp     eax, kCRC
1685
        jz      .sscrc
1686
        test    eax, eax
1687
        jz      .ssend
1688
        call    _7z.SkipData
1689
.ssloop4:
1690
        call    _7z.ReadNum
1691
        jmp     @b
1692
.sscrc:
1693
        pop     ecx
1694
        push    ecx
1695
        mov     ebx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
1696
        mov     esi, [_7z.StreamsInfo.tmpSubStreamsCRCs]
1697
        call    _7z.ReadHashDigests
1698
        xor     ecx, ecx        ; index in out
1699
        xor     edx, edx        ; index in tmp
1700
        push    -1
1701
        pop     ebx             ; index in folders
1702
.ssloop5:
1703
        inc     ebx
1704
        cmp     ebx, [_7z.StreamsInfo.numFolders]
1705
        jae     .ssloop4
1706
        mov     eax, [_7z.StreamsInfo.folders]
1707
        mov     ebp, [eax+ebx*4]
1708
        mov     ebp, [ebp+_7z.StreamsInfo.numUnPackStreams]
1709
        cmp     ebp, 1
1710
        jnz     @f
1711
        mov     eax, [_7z.StreamsInfo.unpackCRCsDefined]
1712
        cmp     byte [eax+ebx], 0
1713
        jz      @f
1714
        mov     esi, [_7z.StreamsInfo.SubStreamsCRCsDefined]
1715
        mov     byte [esi+ecx], 1
1716
        mov     esi, [_7z.StreamsInfo.unpackCRCs]
1717
        mov     eax, [esi+ebx*4]
1718
        mov     esi, [_7z.StreamsInfo.SubStreamsCRCs]
1719
        mov     [esi+ecx*4], eax
1720
        inc     ecx
1721
        jmp     .ssloop5
1722
@@:
1723
        dec     ebp
1724
        js      .ssloop5
1725
        mov     esi, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
1726
        mov     al, [esi+edx]
1727
        mov     esi, [_7z.StreamsInfo.SubStreamsCRCsDefined]
1728
        mov     [esi+ecx], al
1729
        mov     esi, [_7z.StreamsInfo.tmpSubStreamsCRCs]
1730
        mov     eax, [esi+edx*4]
1731
        mov     esi, [_7z.StreamsInfo.SubStreamsCRCs]
1732
        mov     [esi+ecx*4], eax
1733
        inc     edx
1734
        inc     ecx
1735
        jmp     @b
1736
.ssend:
1737
        mov     ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
1738
        call    [pgfree]
1739
        and     [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], 0
1740
        pop     ecx
1741
        jmp     .mainloop
1742
 
1743
.folders_alloc:
1744
        push    ecx
1745
        add     ecx, [_7z.StreamsInfo.folders.size]
1746
        sub     ecx, [_7z.StreamsInfo.folders.alloc]
1747
        jbe     @f
1748
        push    edx
1749
        or      ecx, 0xFFF
1750
        inc     ecx
1751
        add     ecx, [_7z.StreamsInfo.folders.alloc]
1752
        mov     [_7z.StreamsInfo.folders.alloc], ecx
1753
        mov     edx, [_7z.StreamsInfo.folders]
1754
        call    [pgrealloc]
1755
        pop     edx
1756
        test    eax, eax
1757
        jz      return.clear
1758
        mov     [_7z.StreamsInfo.folders], eax
1759
@@:
1760
        pop     ecx
1761
        mov     eax, [_7z.StreamsInfo.folders.size]
1762
        add     [_7z.StreamsInfo.folders.size], ecx
1763
        ret
1764
 
1765
.error:
1766
        mov     ecx, [_7z.StreamsInfo.packSizes]
1767
        jecxz   @f
1768
        call    [pgfree]
1769
@@:
1770
        mov     ecx, [_7z.StreamsInfo.folders]
1771
        jecxz   @f
1772
        call    [pgfree]
1773
@@:
1774
        mov     ecx, [_7z.StreamsInfo.SubStreamsSizes]
1775
        jecxz   @f
1776
        call    [pgfree]
1777
@@:
1778
        mov     ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
1779
        jecxz   @f
1780
        call    [pgfree]
1781
@@:
1782
        jmp     open_7z.header_error
1783
.clear:
1784
        mov     ecx, [_7z.StreamsInfo.packSizes]
1785
        jecxz   @f
1786
        call    [pgfree]
1787
@@:
1788
        mov     ecx, [_7z.StreamsInfo.folders]
1789
        jecxz   @f
1790
        call    [pgfree]
1791
@@:
1792
        mov     ecx, [_7z.StreamsInfo.SubStreamsSizes]
1793
        jecxz   @f
1794
        call    [pgfree]
1795
@@:
1796
        mov     ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
1797
        jecxz   @f
1798
        call    [pgfree]
1799
@@:
1800
        jmp     open_7z.clear
1801
 
1802
uglobal
1803
align 4
1804
_7z.decode.mainbuf      dd      ?
1805
_7z.decode.pStreams     dd      ?
1806
_7z.decode.pStreams_def rd      8
1807
_7z.decode.outBufferSize dd     ?
1808
_7z.decode.outBufferPtr dd      ?
1809
_7z.decode.outBufferRead dd     ?
1810
endg
1811
 
1812
virtual at 0
1813
streamInfo:
1814
.fullSize       dq      ?
1815
.fillBuf        dd      ?       ; procedure which fills the buffer
1816
.bufSize        dd      ?
1817
.bufDataLen     dd      ?
1818
.bufPtr         dd      ?
1819
.size = $
1820
end virtual
1821
 
1822
_7z.decode:
1823
; in: ebx->folder, outBufferSize, outBufferPtr
1824
; N.B. We assume that every coder has 1 output (unpacked) stream.
1825
        and     [.mainbuf], 0
1826
        mov     [.pStreams], .pStreams_def
1827
        mov     [error_proc], .error
1828
        mov     [clear_proc], .clear
1829
        call    .init
1830
        and     [.outBufferRead], 0
1831
@@:
1832
        push    edi
1833
        mov     eax, [ebx+_7z.StreamsInfo.mainOutStream]
1834
        mov     esi, [.pStreams]
1835
        mov     eax, [esi+eax*4]
1836
        call    fillBuf
1837
        mov     ecx, [eax+streamInfo.bufSize]
1838
        mov     esi, [eax+streamInfo.bufPtr]
1839
        mov     edi, [.outBufferPtr]
1840
        add     edi, [.outBufferRead]
1841
        add     [.outBufferRead], ecx
1842
        mov     edx, ecx
1843
        shr     ecx, 2
1844
        rep     movsd
1845
        mov     ecx, edx
1846
        and     ecx, 3
1847
        rep     movsb
1848
        pop     edi
1849
        mov     eax, [.outBufferRead]
1850
        cmp     eax, [.outBufferSize]
1851
        jb      @b
1852
        mov     ecx, [.pStreams]
1853
        cmp     ecx, .pStreams_def
1854
        jz      @f
1855
        call    [pgfree]
1856
@@:
1857
        mov     ecx, [.mainbuf]
1858
        jecxz   @f
1859
        call    [pgfree]
1860
@@:
1861
        mov     [error_proc], _7z.ReadAndDecodePackedStreams.error
1862
        mov     [clear_proc], _7z.ReadAndDecodePackedStreams.clear
1863
        ret
1864
 
1865
.error:
1866
        mov     ecx, [.pStreams]
1867
        cmp     ecx, .pStreams_def
1868
        jz      @f
1869
        call    [pgfree]
1870
@@:
1871
        mov     ecx, [.mainbuf]
1872
        jecxz   @f
1873
        call    [pgfree]
1874
@@:
1875
        jmp     _7z.ReadAndDecodePackedStreams.error
1876
.clear:
1877
        mov     ecx, [.pStreams]
1878
        cmp     ecx, .pStreams_def
1879
        jz      @f
1880
        call    [pgfree]
1881
@@:
1882
        mov     ecx, [.mainbuf]
1883
        jecxz   @f
1884
        call    [pgfree]
1885
@@:
1886
        jmp     _7z.ReadAndDecodePackedStreams.clear
1887
 
1888
.init:
1889
; We use stack to keep some information on streams,
1890
;   to avoid stack overflow we limit possible number of coders.
1891
; Anyway, in real life maximum number of coders is 5
1892
;   (password protection filter + BCJ2 filter + 3 LZMA coders),
1893
;   from command line user can define more coders, but
1894
;   archive with, say, 32 coders is most likely bogus.
1895
        cmp     [ebx+_7z.StreamsInfo.numCoders], 128
1896
        ja      return.err
1897
; allocate space for streams info array
1898
        mov     eax, .pStreams_def
1899
        mov     ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
1900
        add     ecx, [ebx+_7z.StreamsInfo.numCoders]
1901
        cmp     ecx, 8
1902
        jbe     @f
1903
        shl     ecx, 2
1904
        call    [pgalloc]
1905
        test    eax, eax
1906
        jz      return.clear
1907
@@:
1908
        mov     [.pStreams], eax
1909
; calculate size of buffers required for decoders
1910
        xor     ecx, ecx
1911
        push    ecx
1912
        mov     ebp, [ebx+_7z.StreamsInfo.unpackSizes]
1913
.calcbufsz:
1914
; LZMA decoder: method ID = [size=03] 03 01 01, NumInStreams = NumOutStreams = 1
1915
        mov     eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
1916
        call    _7z.GetCoder
1917
        jnc     .known_id
1918
.unknown_method_id:
1919
        movzx   esi, byte [eax+4]
1920
        lea     ecx, [eax+5]
1921
        mov     ebx, aUnknownMethod.z
1922
@@:
1923
        dec     esi
1924
        js      @f
1925
        mov     byte [ebx], ' '
1926
        inc     ebx
1927
        mov     al, [ecx]
1928
        push    eax
1929
        shr     al, 4
1930
        cmp     al, 10
1931
        sbb     al, 69h
1932
        das
1933
        mov     [ebx], al
1934
        inc     ebx
1935
        pop     eax
1936
        and     al, 0xF
1937
        cmp     al, 10
1938
        sbb     al, 69h
1939
        das
1940
        mov     [ebx], al
1941
        inc     ebx
1942
        inc     ecx
1943
        jmp     @b
1944
@@:
1945
        mov     byte [ebx], 0
1946
        push    ContinueBtn
1947
        push    1
1948
        push    aUnknownMethod_ptr
1949
        push    1
1950
        call    [SayErr]
1951
        jmp     return.clear
1952
iglobal
1953
if lang eq ru
1954
aUnknownMethod  db      '¥¨§¢¥áâ­ë© ¬¥â®¤:'
1955
else
1956
aUnknownMethod  db      'Unknown method:'
1957
end if
1958
.z:
1959
                times 16*3+1 db 0
1960
aUnknownMethod_ptr dd   aUnknownMethod
1961
endg
1962
.known_id:
1963
        movzx   esi, byte [eax+4]
1964
        lea     esi, [esi+eax+17]
1965
        call    [_7z.GetBufSizeTable+edx*4]
1966
        add     eax, 3
1967
        and     al, not 3
1968
        add     [esp], eax
1969
        jc      .nomem
1970
        cmp     dword [ebp+4], 0
1971
        jnz     @f
1972
        cmp     dword [ebp], edx
1973
        jae     @f
1974
        mov     edx, [ebp]
1975
@@:
1976
        add     edx, 0xF
1977
        and     edx, not 0xF
1978
        add     [esp], edx
1979
        jc      .nomem
1980
        add     ebp, 8
1981
        inc     ecx
1982
        cmp     ecx, [ebx+_7z.StreamsInfo.numCoders]
1983
        jb      .calcbufsz
1984
; add 4 pages for each of not binded input streams
1985
        mov     ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
1986
        shl     ecx, 14
1987
        add     [esp], ecx
1988
;; calculate free RAM
1989
;        call    [getfreemem]
1990
;        sub     eax, 64         ; keep at least 64 Kb of free RAM
1991
;        jbe     .nomem
1992
;        pop     ecx
1993
;        push    ecx
1994
;        add     ecx, 0x3FF
1995
;        shr     ecx, 10
1996
;        cmp     eax, ecx
1997
;        jae     .memok
1998
        jmp     .memok
1999
.nomem:
2000
        push    ContinueBtn
2001
        push    1
2002
        push    aNoFreeRam_ptr
2003
        push    1
2004
        call    [SayErr]
2005
        jmp     return.clear
2006
.memok:
2007
; allocate streamInfos
2008
        pop     ecx
2009
        call    [pgalloc]
2010
        test    eax, eax
2011
        jz      return.clear
2012
        mov     [.mainbuf], eax
2013
; initialize streamInfos for decoders
2014
        xor     ecx, ecx
2015
        mov     ebp, [ebx+_7z.StreamsInfo.unpackSizes]
2016
        mov     edx, [.pStreams]
2017
.init1:
2018
        mov     [edx], eax
2019
        add     edx, 4
2020
        push    edx
2021
        push    dword [ebp]
2022
        pop     dword [eax]
2023
        push    dword [ebp+4]
2024
        pop     dword [eax+4]
2025
        and     dword [eax+streamInfo.size], 0
2026
        push    eax
2027
        mov     eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
2028
        call    _7z.GetCoder
2029
        movzx   esi, byte [eax+4]
2030
        lea     esi, [esi+eax+17]
2031
        call    [_7z.GetBufSizeTable+edx*4]
2032
        pop     esi
2033
        push    esi
2034
        add     eax, 3
2035
        and     al, not 3
2036
        add     [esp], eax
2037
        pop     [esi+streamInfo.bufPtr]
2038
        push    [esi+streamInfo.bufPtr]
2039
        cmp     dword [ebp+4], 0
2040
        jnz     @f
2041
        cmp     dword [ebp], edx
2042
        jae     @f
2043
        mov     edx, [ebp]
2044
@@:
2045
        add     edx, 0xF
2046
        and     edx, not 0xF
2047
        mov     [esi+streamInfo.bufSize], edx
2048
        and     [esi+streamInfo.bufDataLen], 0
2049
        pop     eax
2050
        add     eax, edx
2051
        pop     edx
2052
        add     ebp, 8
2053
        inc     ecx
2054
        cmp     ecx, [ebx+_7z.StreamsInfo.numCoders]
2055
        jb      .init1
2056
; initialize streamInfos for input streams
2057
        xor     ecx, ecx
2058
@@:
2059
        mov     [edx], eax
2060
        add     edx, 4
2061
        mov     esi, [_7z.CurInStream]
2062
        inc     [_7z.CurInStream]
2063
        shl     esi, 3
2064
        add     esi, [_7z.StreamsInfo.packSizes]
2065
        push    dword [esi]
2066
        pop     dword [eax]
2067
        push    dword [esi+4]
2068
        pop     dword [eax+4]
2069
        mov     [eax+streamInfo.fillBuf], fillBufFromInStream
2070
        lea     esi, [eax+streamInfo.size+8]
2071
        mov     [eax+streamInfo.bufPtr], esi
2072
        mov     [eax+streamInfo.bufSize], 0x4000 - streamInfo.size - 8
2073
        and     [eax+streamInfo.bufDataLen], 0
2074
        mov     esi, dword [_7z.StreamsInfo.dataOffset]
2075
        mov     dword [eax+streamInfo.size], esi
2076
        mov     esi, dword [_7z.StreamsInfo.dataOffset+4]
2077
        mov     dword [eax+streamInfo.size+4], esi
2078
        mov     esi, [eax]
2079
        add     dword [_7z.StreamsInfo.dataOffset], esi
2080
        mov     esi, [eax+4]
2081
        adc     dword [_7z.StreamsInfo.dataOffset+4], esi
2082
        add     eax, 0x4000
2083
        inc     ecx
2084
        cmp     ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
2085
        jb      @b
2086
; initialize links between streams
2087
        push    -1
2088
        mov     edx, [ebx+_7z.StreamsInfo.mainOutStream]
2089
        xor     ecx, ecx
2090
.init_links:
2091
        mov     eax, [ebx+_7z.StreamsInfo.fsz+edx*4]
2092
        movzx   esi, byte [eax+4]
2093
        cmp     ecx, [eax+esi+5]
2094
        jb      @f
2095
        pop     ecx
2096
        cmp     ecx, -1
2097
        jz      .inited_links
2098
        pop     edx
2099
        jmp     .init_links
2100
@@:
2101
        push    edx
2102
        push    ecx
2103
@@:
2104
        dec     edx
2105
        js      @f
2106
        mov     eax, [ebx+_7z.StreamsInfo.fsz+edx*4]
2107
        movzx   esi, byte [eax+4]
2108
        add     ecx, [eax+esi+5]
2109
        jmp     @b
2110
@@:
2111
        mov     esi, [ebx+_7z.StreamsInfo.bindPairs]
2112
        mov     edx, [ebx+_7z.StreamsInfo.numBindPairs]
2113
@@:
2114
        add     esi, 8
2115
        dec     edx
2116
        js      .link_to_in
2117
        cmp     ecx, [esi-8]
2118
        jnz     @b
2119
        pop     ecx
2120
        pop     edx
2121
        mov     eax, [.pStreams]
2122
        mov     eax, [eax+edx*4]
2123
        lea     eax, [eax+streamInfo.size+ecx*4]
2124
        push    edx
2125
        inc     ecx
2126
        push    ecx
2127
        mov     edx, [esi-4]
2128
        mov     ecx, [.pStreams]
2129
        mov     ecx, [ecx+edx*4]
2130
        mov     [eax], ecx
2131
        cmp     dword [ecx+streamInfo.size], 0
2132
        jnz     return.err
2133
        xor     ecx, ecx
2134
        jmp     .init_links
2135
.link_to_in:
2136
        mov     esi, [ebx+_7z.StreamsInfo.packedStreams]
2137
        mov     edx, [ebx+_7z.StreamsInfo.numPackedStreams]
2138
@@:
2139
        dec     edx
2140
        js      return.err
2141
        cmp     ecx, [esi+edx*4]
2142
        jnz     @b
2143
        add     edx, [ebx+_7z.StreamsInfo.numCoders]
2144
        mov     esi, [.pStreams]
2145
        mov     eax, [esi+edx*4]
2146
        pop     ecx
2147
        pop     edx
2148
        mov     esi, [esi+edx*4]
2149
        mov     [esi+streamInfo.size+ecx*4], eax
2150
        inc     ecx
2151
        jmp     .init_links
2152
.inited_links:
2153
; initialize all decoders
2154
; bool zzz_init_decoder(stream_info* ebp, esi->params, [esi-4]=params_size);
2155
        xor     ecx, ecx
2156
.init_decoders:
2157
        mov     eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
2158
        call    _7z.GetCoder
2159
        movzx   esi, byte [eax+4]
2160
        mov     ebp, [.pStreams]
2161
        mov     ebp, [ebp+ecx*4]
2162
        cmp     dword [esi+eax], 0
2163
        jz      @f
2164
        cmp     dword [ebp+streamInfo.size], 0
2165
        jz      return.err
2166
@@:
2167
        lea     esi, [esi+eax+17]
2168
        push    ebx ecx edi
2169
        xor     ebx, ebx
2170
        call    [_7z.InitTable+edx*4]
2171
        pop     edi ecx ebx
2172
        inc     ecx
2173
        cmp     ecx, [ebx+_7z.StreamsInfo.numCoders]
2174
        jb      .init_decoders
2175
        ret
2176
 
2177
fillBuf:
2178
        and     [eax+streamInfo.bufDataLen], 0
2179
fillBufNozero:
2180
        pushad
2181
	mov	edx, [eax+streamInfo.bufSize]
2182
	sub	edx, [eax+streamInfo.bufDataLen]
2183
        cmp     dword [eax+streamInfo.fullSize+4], 0
2184
        jnz     .full
2185
        mov     ecx, dword [eax+streamInfo.fullSize]
2186
        cmp     ecx, edx
2187
        jbe     @f
2188
.full:
2189
        mov     ecx, edx
2190
@@:
2191
        sub     dword [eax+streamInfo.fullSize], ecx
2192
        sbb     dword [eax+streamInfo.fullSize+4], 0
2193
        mov     edi, [eax+streamInfo.bufPtr]
2194
        add     edi, [eax+streamInfo.bufDataLen]
2195
	add	[eax+streamInfo.bufDataLen], ecx
2196
        jmp     [eax+streamInfo.fillBuf]
2197
 
2198
fillBufFromInStream:
2199
        push    eax
2200
        push    dword [eax+streamInfo.size+4]
2201
        push    dword [eax+streamInfo.size]
2202
        push    0
2203
        push    [inStream]
2204
        call    [seek]
2205
        push    ecx
2206
        push    edi
2207
        push    [inStream]
2208
        call    [read]
2209
        cmp     eax, ecx
2210
        pop     eax
2211
        jnz     .error
2212
        add     dword [eax+streamInfo.size], ecx
2213
        adc     dword [eax+streamInfo.size+4], 0
2214
        popad
2215
        ret
2216
.error:
2217
        push    ContinueBtn
2218
        push    1
2219
        push    aReadError_ptr
2220
        push    1
2221
        call    [SayErr]
2222
        jmp     return.clear
2223
 
2224
_7z.GetCoder:
2225
; in: eax->coder
2226
; out: edx = coder type
2227
        xor     edx, edx
2228
; Copy decoder: method ID = [size=01] 00, NumInStreams = NumOutStreams = 1
2229
        cmp     word [eax+4], 0x0001
2230
        jnz     @f
2231
        cmp     dword [eax+6], 1
2232
        jz      .ret
2233
@@:
2234
        inc     edx
2235
; LZMA decoder: method ID = [size=03] 03 01 01, NumInStreams = NumOutStreams = 1
2236
        cmp     dword [eax+4], 0x01010303
2237
        jnz     @f
2238
        cmp     dword [eax+8], 1
2239
        jz      .ret
2240
@@:
2241
        inc     edx
2242
; PPMD decoder: method ID = [size=03] 03 04 01, NumInStreams = NumOutStreams = 1
2243
        cmp     dword [eax+4], 0x01040303
2244
        jnz     @f
2245
        cmp     dword [eax+8], 1
2246
        jz      .ret
2247
@@:
2248
        inc     edx
2249
; BCJ filter: method ID = [size=04] 03 03 01 03, NumInStreams = NumOutStreams = 1
2250
        cmp     byte [eax+4], 4
2251
        jnz     @f
2252
        cmp     dword [eax+5], 0x03010303
2253
        jnz     @f
2254
        cmp     dword [eax+9], 1
2255
        jz      .ret
2256
@@:
2257
        inc     edx
2258
; BCJ2 filter: method ID = [size=04] 03 03 01 1B, NumInStreams = 4, NumOutStreams = 1
2259
        cmp     byte [eax+4], 4
2260
        jnz     @f
2261
        cmp     dword [eax+5], 0x1B010303
2262
        jnz     @f
2263
        cmp     dword [eax+9], 4
2264
        jz      .ret
2265
@@:
2266
        inc     edx
2267
; 7z-AES cryptor: method ID = [size=04] 06 F1 07 01, NumInStreams = NumOutStreams = 1
2268
        cmp     byte [eax+4], 4
2269
        jnz     @f
2270
        cmp     dword [eax+5], 0x0107F106
2271
        jnz     @f
2272
        cmp     dword [eax+9], 1
2273
        jz      .ret
2274
@@:
631 diamond 2275
        inc     edx
2276
; Deflate decoder: method ID = [size=03] 04 01 08, NumInStreams = NumOutStreams = 1
2277
        cmp     dword [eax+4], 0x08010403
2278
        jnz     @f
2279
        cmp     dword [eax+8], 1
2280
        jz      .ret
2281
@@:
2282
        inc     edx
2283
; Deflate64 decoder: method ID = [size=03] 04 01 09, NumInStreams = NumOutStreams = 1
2284
        cmp     dword [eax+4], 0x09010403
2285
        jnz     @f
2286
        cmp     dword [eax+8], 1
2287
        jz      .ret
2288
@@:
589 diamond 2289
        stc
2290
.ret:
2291
        ret
2292
 
2293
iglobal
2294
align 4
2295
label _7z.GetBufSizeTable dword
2296
        dd      copy_get_buf_size
2297
        dd      lzma_get_buf_size
2298
        dd      ppmd_get_buf_size
2299
        dd      bcj_get_buf_size
2300
        dd      bcj2_get_buf_size
2301
        dd      aes7z_get_buf_size
631 diamond 2302
        dd      deflate_get_buf_size
2303
        dd      deflate_get_buf_size
589 diamond 2304
label _7z.InitTable dword
2305
        dd      copy_init_decoder
2306
        dd      lzma_init_decoder
2307
        dd      ppmd_init_decoder
2308
        dd      bcj_init_decoder
2309
        dd      bcj2_init_decoder
2310
        dd      aes7z_init_decoder
631 diamond 2311
        dd      deflate_init_decoder
2312
        dd      deflate64_init_decoder
589 diamond 2313
endg
2314
 
2315
copy_get_buf_size:
2316
        mov     eax, streamInfo.size+8
2317
        mov     edx, 0x10000
2318
        ret
2319
 
2320
copy_init_decoder:
2321
        mov     [ebp+streamInfo.fillBuf], copy_fillBuf
2322
        and     dword [ebp+streamInfo.size+4], 0
2323
        ret
2324
 
2325
copy_fillBuf:
2326
        push    eax
2327
        mov     esi, [eax+streamInfo.size+4]
2328
        mov     eax, [eax+streamInfo.size]
2329
.redo:
2330
        push    ecx
2331
        mov     edx, [eax+streamInfo.bufDataLen]
2332
        sub     edx, esi
2333
        cmp     ecx, edx
2334
        jb      @f
2335
        mov     ecx, edx
2336
@@:
2337
        sub     [esp], ecx
2338
        add     esi, [eax+streamInfo.bufPtr]
2339
        mov     edx, ecx
2340
        shr     ecx, 2
2341
        rep     movsd
2342
        mov     ecx, edx
2343
        and     ecx, 3
2344
        rep     movsb
2345
        pop     ecx
2346
        jecxz   .done
2347
        cmp     dword [eax+streamInfo.fullSize+4], 0
2348
        jnz     @f
2349
        cmp     dword [eax+streamInfo.fullSize], ecx
2350
        jb      return.err
2351
@@:
2352
        call    fillBuf
2353
        xor     esi, esi
2354
        jmp     .redo
2355
.done:
2356
        sub     esi, [eax+streamInfo.bufPtr]
2357
        pop     eax
2358
        mov     [eax+streamInfo.size+4], esi
2359
        popad
2360
        ret
2361
 
2362
; ebp=hPlugin, eax->item, edi->info
2363
getattr_7z:
2364
        cmp     [eax+file_in_7z.bPseudoFolder], 0
2365
        jnz     .pseudo
2366
        lea     esi, [eax+file_in_7z.attr]
2367
        movsd
2368
        xor     eax, eax
2369
        stosd
2370
        add     esi, -(file_in_7z.attr+4) + file_in_7z.CreationTime
2371
        mov     ecx, 8
2372
        rep     movsd
2373
        ret
2374
.pseudo:
2375
        push    0x10    ; attributes: folder
2376
        pop     eax
2377
        stosd
2378
        xor     eax, eax
2379
        stosd
2380
        lea     esi, [ebp+handle_7z.host_datetime]
2381
        push    6
2382
        pop     ecx
2383
        rep     movsd
2384
        stosd
2385
        stosd
2386
        ret
2387
 
2388
virtual at 0
2389
file_handle_7z:
2390
.type   dd      ?
2391
.context dd     ?
2392
.pos    dq      ?
2393
.base   dd      ?       ; handle of archive
2394
.item   dd      ?       ; pointer to file_in_7z
2395
.mainStream dd  ?       ; (pointer in context)
2396
.bError db      ?
2397
        rb      3
2398
.size = $
2399
end virtual
2400
 
2401
iglobal
2402
align 4
2403
handle_table_7z dd      handle_table_7z,handle_table_7z
2404
endg
2405
 
2406
; ebp=hPlugin, eax->item, edi=mode
2407
open_file_7z:
2408
        cmp     [eax+file_in_7z.bHasStream], 0
2409
        jnz     @f
2410
        mov     eax, empty_7z_handle
2411
        ret
2412
@@:
2413
        mov     ecx, [ebp+handle_7z.password_len]
2414
        inc     ecx
2415
        setnz   [bPasswordDefined]
2416
        jz      @f
2417
        dec     ecx
2418
        lea     esi, [ebp+handle_7z.password]
2419
        push    edi
2420
        mov     edi, password_unicode
2421
        shr     ecx, 1
2422
        rep     movsd
2423
        adc     ecx, ecx
2424
        rep     movsw
2425
        pop     edi
2426
@@:
2427
        mov     [hOut], ecx
2428
        mov     [_7z.decode.mainbuf], ecx
2429
        mov     ecx, [ebp+handle_7z.host]
2430
        mov     [inStream], ecx
2431
        mov     [_7z.decode.pStreams], _7z.decode.pStreams_def
2432
        push    eax
2433
        mov     [_esp], esp
2434
        mov     [_ebp], ebp
2435
        mov     [error_proc], .error
2436
        mov     [clear_proc], .clear
2437
        mov     ebx, [ebp+handle_7z.folders]
2438
        mov     ecx, [eax+file_in_7z.folder]
2439
        cmp     [ebp+handle_7z.last_folder], ecx
2440
        jnz     .nolast
2441
        mov     edx, dword [eax+file_in_7z.folderStart]
2442
        sub     edx, dword [ebp+handle_7z.last_pos]
2443
        mov     esi, dword [eax+file_in_7z.folderStart+4]
2444
        sbb     esi, dword [ebp+handle_7z.last_pos+4]
2445
        jb      .nolast
2446
        xor     ecx, ecx
2447
        xchg    ecx, [ebp+handle_7z.last_context]
2448
        mov     [_7z.decode.mainbuf], ecx
2449
        mov     eax, [ebp+handle_7z.last_main_stream]
2450
        mov     dword [eax+streamInfo.fullSize], edx
2451
        mov     dword [eax+streamInfo.fullSize+4], esi
2452
        or      [ebp+handle_7z.last_folder], -1
2453
        pop     esi
2454
        push    esi
2455
        jmp     .commonl
2456
.nolast:
2457
        mov     ebx, [ebx+ecx*4]
2458
        mov     eax, [ebx+_7z.StreamsInfo.startPackedStream]
2459
        mov     [_7z.CurInStream], eax
2460
        mov     eax, dword [ebx+_7z.StreamsInfo.packOffset]
2461
        mov     dword [_7z.StreamsInfo.dataOffset], eax
2462
        mov     eax, dword [ebx+_7z.StreamsInfo.packOffset+4]
2463
        mov     dword [_7z.StreamsInfo.dataOffset+4], eax
2464
        mov     eax, [ebp+handle_7z.packSizes]
2465
        mov     [_7z.StreamsInfo.packSizes], eax
2466
        push    ebp
2467
        call    _7z.decode.init
2468
        pop     ebp
2469
        mov     eax, [ebx+_7z.StreamsInfo.mainOutStream]
2470
        mov     esi, [_7z.decode.pStreams]
2471
        mov     eax, [esi+eax*4]
2472
        pop     esi
2473
        push    esi
2474
        mov     ecx, dword [esi+file_in_7z.folderStart]
2475
        mov     dword [eax+streamInfo.fullSize], ecx
2476
        mov     ecx, dword [esi+file_in_7z.folderStart+4]
2477
        mov     dword [eax+streamInfo.fullSize+4], ecx
2478
.commonl:
2479
        call    skip_7z
2480
        mov     ecx, dword [esi+file_in_7z.UnPackSize]
2481
        mov     dword [eax+streamInfo.fullSize], ecx
2482
        mov     edx, dword [esi+file_in_7z.UnPackSize+4]
2483
        mov     dword [eax+streamInfo.fullSize+4], edx
2484
        test    edx, edx
2485
        jnz     .nomemstream
2486
if defined LIMIT_FOR_MEM_STREAM
2487
        cmp     ecx, LIMIT_FOR_MEM_STREAM
2488
        ja      .nomemstream
2489
end if
2490
        push    eax ecx
2491
        add     ecx, 0x3FF
2492
        shr     ecx, 10         ; get size in Kb
2493
        call    [getfreemem]
2494
        shr     eax, 2
2495
        cmp     ecx, eax
2496
        pop     ecx eax
2497
        ja      .nomemstream
2498
; create memory stream and unpack to memory
2499
        push    eax ecx
2500
        add     ecx, mem_stream.buf
2501
        call    [pgalloc]
2502
        test    eax, eax
2503
        jz      return.clear
2504
        mov     edi, eax
2505
        pop     ecx
2506
        push    edi
2507
        mov     [hOut], eax
2508
        xor     eax, eax        ; type_mem_stream
2509
        stosd                   ; mem_stream.type
2510
        mov     eax, ecx
2511
        stosd                   ; mem_stream.size
2512
        xor     eax, eax
2513
        stosd                   ; mem_stream.pos
2514
        mov     eax, [esp+4]
2515
        push    esi
2516
        push    ecx edi
2517
        call    read_7z_to_buf
2518
        pop     esi ecx
2519
        mov     ebx, [esp+12]
2520
        cmp     [ebx+file_in_7z.bCRCDefined], 0
2521
        jz      @f
2522
        call    crc
2523
        cmp     eax, [ebx+file_in_7z.FileCRC]
2524
        jnz     return.err
2525
@@:
2526
        pop     esi
2527
        xor     ecx, ecx
2528
        xchg    ecx, [_7z.decode.mainbuf]
2529
        xchg    ecx, [ebp+handle_7z.last_context]
2530
        jecxz   @f
2531
        call    [pgfree]
2532
@@:
2533
        and     [hOut], 0
2534
        mov     eax, [esi+file_in_7z.folder]
2535
        mov     [ebp+handle_7z.last_folder], eax
2536
        mov     eax, [esp+4]
2537
        mov     [ebp+handle_7z.last_main_stream], eax
2538
        mov     ecx, dword [esi+file_in_7z.UnPackSize]
2539
        add     ecx, dword [esi+file_in_7z.folderStart]
2540
        mov     dword [ebp+handle_7z.last_pos], ecx
2541
        mov     ecx, dword [esi+file_in_7z.UnPackSize+4]
2542
        adc     ecx, dword [esi+file_in_7z.folderStart+4]
2543
        mov     dword [ebp+handle_7z.last_pos+4], ecx
2544
        call    .done
2545
        pop     eax edi ecx
2546
        ret
2547
.nomemstream:
2548
        mov     edi, eax
2549
        push    esi
2550
        mov     esi, handle_table_7z
2551
        push    file_handle_7z.size
2552
        pop     ecx
2553
        call    alloc_handle
2554
        pop     esi
2555
        test    eax, eax
2556
        jz      .clear
2557
        mov     [eax+file_handle_7z.type], type_7z
2558
        xor     edx, edx
2559
        mov     dword [eax+file_handle_7z.pos], edx
2560
        mov     dword [eax+file_handle_7z.pos+4], edx
2561
        mov     [eax+file_handle_7z.bError], dl
2562
        xchg    edx, [_7z.decode.mainbuf]
2563
        mov     [eax+file_handle_7z.context], edx
2564
        mov     [eax+file_handle_7z.mainStream], edi
2565
        mov     [eax+file_handle_7z.base], ebp
2566
        mov     [eax+file_handle_7z.item], esi
2567
        push    eax
2568
        call    .done
2569
        pop     eax ecx
2570
        ret
2571
 
2572
.done:
2573
        cmp     [bPasswordDefined], 0
2574
        jz      @f
2575
        mov     ecx, [password_size]
2576
        mov     [ebp+handle_7z.password_len], ecx
2577
        mov     esi, password_unicode
2578
        lea     edi, [ebp+handle_7z.password]
2579
        shr     ecx, 1
2580
        rep     movsd
2581
        adc     ecx, ecx
2582
        rep     movsw
2583
@@:
2584
        jmp     .clear
2585
 
2586
.error:
2587
        cmp     [bPasswordDefined], 0
2588
        jz      .realerror
2589
        push    CancelPassBtn
2590
        push    2
2591
        push    aArchiveDataErrorPass_ptr
2592
        push    1
2593
        call    [SayErr]
2594
        cmp     al, 1
2595
        jnz     .clear
2596
; user wants to re-enter password
2597
        call    .clear
2598
        pop     eax
2599
        jmp     open_file_7z
2600
.realerror:
2601
        push    ContinueBtn
2602
        push    1
2603
        push    aArchiveDataError_ptr
2604
        push    1
2605
        call    [SayErr]
2606
.clear:
2607
        mov     ecx, [_7z.decode.pStreams]
2608
        cmp     ecx, _7z.decode.pStreams_def
2609
        jz      @f
2610
        call    [pgfree]
2611
@@:
2612
        mov     ecx, [_7z.decode.mainbuf]
2613
        jecxz   @f
2614
        call    [pgfree]
2615
@@:
2616
        mov     ecx, [hOut]
2617
        jecxz   @f
2618
        call    [pgfree]
2619
@@:
2620
        cmp     esp, [_esp]
2621
        jnz     @f
2622
        pop     eax
2623
@@:
2624
        xor     eax, eax
2625
        ret
2626
 
2627
read_7z_to_buf:
2628
        mov     esi, [eax+streamInfo.bufDataLen]
2629
        cmp     esi, [eax+streamInfo.bufSize]
2630
        jnz     @f
2631
        xor     esi, esi
2632
        mov     [eax+streamInfo.bufDataLen], esi
2633
@@:
2634
        call    fillBufNozero
2635
        mov     ecx, [eax+streamInfo.bufDataLen]
2636
        sub     ecx, esi
2637
        add     esi, [eax+streamInfo.bufPtr]
2638
        mov     edx, ecx
2639
        shr     ecx, 2
2640
        rep     movsd
2641
        mov     ecx, edx
2642
        and     ecx, 3
2643
        rep     movsb
2644
        cmp     dword [eax+streamInfo.fullSize], 0
2645
        jnz     read_7z_to_buf
2646
        ret
2647
 
2648
skip_7z:
2649
        push    edx
2650
        mov     edx, [eax+streamInfo.bufDataLen]
2651
        cmp     edx, [eax+streamInfo.bufSize]
2652
        jnz     @f
2653
        and     [eax+streamInfo.bufDataLen], 0
2654
@@:
2655
        pop     edx
2656
        call    fillBufNozero
2657
        cmp     dword [eax+streamInfo.fullSize], 0
2658
        jnz     skip_7z
2659
        cmp     dword [eax+streamInfo.fullSize+4], 0
2660
        jnz     skip_7z
2661
        ret
2662
 
2663
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
2664
read_7z:
2665
        mov     eax, [ebx+file_handle_7z.mainStream]
2666
        test    eax, eax
2667
        jz      .ret    ; empty stream - return 0 bytes read
2668
        cmp     [ebx+file_handle_7z.bError], 0
2669
        jnz     .reterr
2670
        mov     ecx, [ebx+file_handle_7z.base]
2671
        mov     ecx, [ecx+handle_7z.host]
2672
        mov     [inStream], ecx
2673
        mov     edi, [esp+8]
2674
        mov     ecx, [esp+12]
2675
        mov     dword [eax+streamInfo.fullSize], ecx
2676
        and     dword [eax+streamInfo.fullSize+4], 0
2677
        jecxz   .nodata
2678
        mov     [_esp], esp
2679
        mov     [_ebp], ebp
2680
        mov     [error_proc], .error
2681
        mov     [clear_proc], .clear    ; should not be called
2682
        mov     esi, [ebx+file_handle_7z.item]
2683
        mov     edx, dword [esi+file_in_7z.UnPackSize]
2684
        mov     esi, dword [esi+file_in_7z.UnPackSize+4]
2685
        sub     edx, dword [ebx+file_handle_7z.pos]
2686
        sbb     esi, dword [ebx+file_handle_7z.pos+4]
2687
        jnz     .do
2688
        cmp     edx, ecx
2689
        jae     .do
2690
        mov     dword [eax+streamInfo.fullSize], edx
2691
.do:
2692
        call    read_7z_to_buf
2693
.nodata:
2694
        sub     edi, [esp+8]
2695
        mov     eax, edi
2696
        add     dword [ebx+file_handle_7z.pos], eax
2697
        adc     dword [ebx+file_handle_7z.pos+4], 0
2698
.ret:
2699
        ret     12
2700
 
2701
.error:
2702
.clear:
2703
        mov     ebx, [esp+4]
2704
        mov     [ebx+file_handle_7z.bError], 1
2705
        push    ContinueBtn
2706
        push    1
2707
        push    aArchiveDataError_ptr
2708
        push    1
2709
        call    [SayErr]
2710
.reterr:
2711
        or      eax, -1
2712
        ret     12
2713
 
2714
; void __stdcall setpos(HANDLE hFile, __int64 pos);
2715
setpos_7z:
2716
        cmp     [ebx+file_handle_7z.context], 0
2717
        jz      .ret
2718
        mov     edi, [ebx+file_handle_7z.base]
2719
        mov     ecx, [edi+handle_7z.host]
2720
        mov     [inStream], ecx
2721
        mov     [_esp], esp
2722
        mov     [_ebp], ebp
2723
        mov     [error_proc], read_7z.error
2724
        mov     [clear_proc], read_7z.clear     ; should not be called
2725
        cmp     [ebx+file_handle_7z.bError], 0
2726
        jnz     .backward       ; if was error, force reinitialization
2727
        mov     ecx, [esp+8]
2728
        mov     edx, [esp+12]
2729
        sub     ecx, dword [ebx+file_handle_7z.pos]
2730
        sbb     edx, dword [ebx+file_handle_7z.pos+4]
2731
        jb      .backward
2732
; move forward - skip some data
2733
        mov     eax, [ebx+file_handle_7z.mainStream]
2734
        mov     dword [eax+streamInfo.fullSize], ecx
2735
        mov     dword [eax+streamInfo.fullSize+4], edx
2736
        call    skip_7z
2737
        add     dword [ebx+file_handle_7z.pos], ecx
2738
        adc     dword [ebx+file_handle_7z.pos], edx
2739
.ret:
2740
        ret     12
2741
.backward:
2742
; move backward - reinitialize and skip start data
2743
        mov     [ebx+file_handle_7z.bError], 0
2744
        mov     ebp, [ebx+file_handle_7z.context]
2745
        mov     eax, [ebx+file_handle_7z.item]
2746
        mov     ebx, [edi+handle_7z.folders]
2747
        mov     eax, [eax+file_in_7z.folder]
2748
        mov     ebx, [ebx+eax*4]
2749
; initialize streamInfos for decoders
2750
        xor     ecx, ecx
2751
        mov     esi, [ebx+_7z.StreamsInfo.unpackSizes]
2752
@@:
2753
        lodsd
2754
        mov     [ebp], eax
2755
        lodsd
2756
        mov     [ebp+4], eax
2757
        and     [ebp+streamInfo.bufDataLen], 0
2758
        push    esi
2759
        mov     eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
2760
        call    _7z.GetCoder
2761
        movzx   esi, byte [eax+4]
2762
        lea     esi, [esi+eax+17]
2763
        push    ebx ecx edi
2764
        mov     bl, 1
2765
        call    [_7z.InitTable+edx*4]
2766
        pop     edi ecx ebx esi
2767
        mov     edx, [ebp+streamInfo.bufSize]
2768
        mov     ebp, [ebp+streamInfo.bufPtr]
2769
        add     ebp, edx
2770
        inc     ecx
2771
        cmp     ecx, [ebx+_7z.StreamsInfo.numCoders]
2772
        jb      @b
2773
; initialize streamInfos for input streams
2774
        xor     ecx, ecx
2775
        mov     esi, [ebx+_7z.StreamsInfo.startPackedStream]
2776
        shl     esi, 3
2777
        add     esi, [edi+handle_7z.packSizes]
2778
        mov     edi, dword [ebx+_7z.StreamsInfo.packOffset]
2779
        mov     edx, dword [ebx+_7z.StreamsInfo.packOffset+4]
2780
@@:
2781
        mov     dword [ebp+streamInfo.size], edi
2782
        mov     dword [ebp+streamInfo.size+4], edx
2783
        and     [ebp+streamInfo.bufDataLen], 0
2784
        lodsd
2785
        add     edi, eax
2786
        mov     [ebp], eax
2787
        lodsd
2788
        adc     edx, eax
2789
        mov     [ebp+4], eax
2790
        add     ebp, 0x4000
2791
        inc     ecx
2792
        cmp     ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
2793
        jb      @b
2794
        mov     ebx, [esp+4]
2795
        mov     esi, [ebx+file_handle_7z.item]
2796
        mov     eax, [ebx+file_handle_7z.mainStream]
2797
        mov     ecx, dword [esi+file_in_7z.folderStart]
2798
        add     ecx, [esp+8]
2799
        mov     dword [eax+streamInfo.fullSize], ecx
2800
        mov     ecx, dword [esi+file_in_7z.folderStart+4]
2801
        adc     ecx, [esp+12]
2802
        mov     dword [eax+streamInfo.fullSize+4], ecx
2803
        and     dword [ebx+file_handle_7z.pos], 0
2804
        and     dword [ebx+file_handle_7z.pos+4], 0
2805
        and     [eax+streamInfo.bufDataLen], 0
2806
        call    skip_7z
2807
        mov     eax, [esp+8]
2808
        mov     dword [ebx+file_handle_7z.pos], eax
2809
        mov     eax, [esp+12]
2810
        mov     dword [ebx+file_handle_7z.pos+4], eax
2811
        ret     12
2812
 
2813
close_file_7z:
2814
        mov     ecx, [ebx+file_handle_7z.context]
2815
        jecxz   .ret
2816
        cmp     [ebx+file_handle_7z.bError], 0
2817
        jnz     @f
2818
        push    ebp
2819
        mov     ebp, [ebx+file_handle_7z.base]
2820
        xchg    ecx, [ebp+handle_7z.last_context]
2821
        mov     eax, [ebx+file_handle_7z.item]
2822
        mov     edx, [eax+file_in_7z.folder]
2823
        mov     [ebp+handle_7z.last_folder], edx
2824
        mov     edx, [ebx+file_handle_7z.mainStream]
2825
        mov     [ebp+handle_7z.last_main_stream], edx
2826
        mov     edx, dword [eax+file_in_7z.folderStart+4]
2827
        mov     eax, dword [eax+file_in_7z.folderStart]
2828
        add     eax, dword [ebx+file_handle_7z.pos]
2829
        adc     edx, dword [ebx+file_handle_7z.pos+4]
2830
        mov     dword [ebp+handle_7z.last_pos], eax
2831
        mov     dword [ebp+handle_7z.last_pos+4], edx
2832
        pop     ebp
2833
@@:
2834
        jecxz   @f
2835
        call    [pgfree]
2836
@@:
2837
        mov     esi, ebx
2838
        call    free_handle
2839
.ret:
2840
        ret     4