Subversion Repositories Kolibri OS

Rev

Rev 631 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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
  22. .stamp          dd      ?
  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]
  833.         mov     esi, [esp+12]
  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.bufDataLen]
  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. @@:
  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. @@:
  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
  2302.         dd      deflate_get_buf_size
  2303.         dd      deflate_get_buf_size
  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
  2311.         dd      deflate_init_decoder
  2312.         dd      deflate64_init_decoder
  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
  2841.