diff --git a/programs/fs/kfar/trunk/kfar_arc/deflate.inc b/programs/fs/kfar/trunk/kfar_arc/deflate.inc new file mode 100644 index 0000000000..210828ab79 --- /dev/null +++ b/programs/fs/kfar/trunk/kfar_arc/deflate.inc @@ -0,0 +1,560 @@ +; Deflate and Deflate64 decoders for *.zip and *.7z archives. +; Written by diamond in 2007. + +deflate_decoder: +virtual at 0 +.outStream rb streamInfo.size +.inStream dd ? +.bDeflate64 db ? +.dl db ? +.bLast db ? + rb 1 +.outEnd dd ? +.inLen dd ? +.inPtr dd ? +.continue dd ? +.blockLen dd ? +.lit_len rb 19 + rb 1 +.lengths rb 288+32 +.huff_bl rd 18*2 +.huff_dist rd 31*2 +.huff_lit rd 287*2 +.size = $ +end virtual + +.fillBuf: + mov ebp, eax + jecxz .nodata + add ecx, edi + mov [ebp+.outEnd], ecx + mov esi, [ebp+.inPtr] + mov dl, [ebp+.dl] + jmp [ebp+.continue] +.nodata: + popad + ret +.block_loop_done: + mov [ebp+.inPtr], esi + mov [ebp+.dl], dl + mov [ebp+.continue], .block_loop + popad + ret +.start: + xor edx, edx + mov [ebp+.inLen], edx + mov [ebp+.bLast], dl +.block_loop: + cmp edi, [ebp+.outEnd] + jae .block_loop_done + cmp [ebp+.bLast], 0 + jnz return.err + call .get_bit + setc [ebp+.bLast] + call .get_bit + jc .test_block_fh + call .get_bit + jc .block_dh +.block_stored: ; Stored + xor edx, edx + xor eax, eax + call .get_word + mov ecx, eax + call .get_word + not ax + cmp eax, ecx + jnz return.err + mov [ebp+.blockLen], ecx +.continue_stored: + mov ecx, [ebp+.blockLen] + mov eax, [ebp+.outEnd] + sub eax, edi + cmp eax, ecx + jae @f + mov ecx, eax +@@: + sub [ebp+.blockLen], ecx +.bs_loop: + mov eax, [ebp+.inLen] + test eax, eax + jnz @f + call .refill + mov eax, [ebp+.inLen] + inc eax + mov [ebp+.inLen], eax +@@: + push ecx + sub ecx, eax + sbb eax, eax + and ecx, eax + add ecx, [ebp+.inLen] + sub [ebp+.inLen], ecx + sub [esp], ecx + rep movsb + pop ecx + jnz .bs_loop + cmp [ebp+.blockLen], ecx + jz .block_loop + mov [ebp+.inPtr], esi + mov [ebp+.dl], dl + mov [ebp+.continue], .continue_stored + popad + ret +.test_block_fh: + call .get_bit + jc return.err +.block_fh: ; Fixed Huffman + push edi + lea edi, [ebp+.huff_dist] + lea eax, [edi+8] + xor ecx, ecx + mov cl, 30 +@@: + stosd + add eax, 8 + loop @b + xor eax, eax + mov cl, 32 +@@: + stosd + inc eax + loop @b + lea eax, [edi+8] + mov cl, 126 +@@: + stosd + add eax, 8 + loop @b + push eax + mov eax, 256 + mov cl, 24 +@@: + stosd + inc eax + loop @b + pop eax + mov cl, 104 +@@: + stosd + add eax, 8 + loop @b + push eax + xor eax, eax + mov cl, 144 +@@: + stosd + inc eax + loop @b + mov eax, 280 + mov cl, 8 +@@: + stosd + inc eax + loop @b + pop eax + mov cl, 56 +@@: + stosd + add eax, 8 + loop @b + mov eax, 144 + mov cl, 112 +@@: + stosd + inc eax + loop @b + jmp .block_h_start +.block_dh: ; Dynamic Huffman + xor ecx, ecx + mov cl, 5 + push edi + lea edi, [ebp+.lit_len] + push edi + xor eax, eax + rep stosd + pop edi + mov cl, 5 + call .get_bits + push eax + mov cl, 5 + call .get_bits + push eax + mov cl, 4 + call .get_bits + lea ecx, [eax+4] + mov ebx, deflate.CodeLengthOrder +iglobal +deflate.CodeLengthOrder: + db 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 +endg +@@: + push ecx + mov cl, 3 + call .get_bits + mov cl, [ebx] + inc ebx + mov [edi+ecx], al + pop ecx + loop @b + lea ebx, [ebp+.huff_bl] + mov cl, 19 + push 18*8 + call .construct_huffman_tree + mov ecx, [esp] + add ecx, [esp+4] + add ecx, 258 + lea edi, [ebp+.lengths] +.dhl: + lea ebx, [ebp+.huff_bl] + call .get_huffman_code + cmp eax, 16 + jae .dh_special + stosb + loop .dhl + jmp .dhd +.dh_special: + push ecx + sub eax, 16 + jnz .dh_norep + push 2 + pop ecx + call .get_bits + pop ecx + add eax, 3 + sub ecx, eax + jb return.err +@@: + mov bl, [edi-1] + mov [edi], bl + inc edi + dec eax + jnz @b + test ecx, ecx + jnz .dhl + jmp .dhd +.dh_norep: + dec eax + jz .dh_0 + dec eax + jnz return.err + push 7 + pop ecx + call .get_bits + add eax, 11 + jmp @f +.dh_0: + push 3 + pop ecx + call .get_bits + add eax, 3 +@@: + pop ecx + sub ecx, eax + jb return.err + push ecx + mov ecx, eax + xor eax, eax + rep stosb + pop ecx + test ecx, ecx + jnz .dhl +.dhd: + pop ecx + inc ecx + lea ebx, [ebp+.huff_dist] + pop edi + push edi + lea edi, [edi+ebp+.lengths+257] + push 31*8 + call .construct_huffman_tree + pop ecx + add ecx, 257 + lea ebx, [ebp+.huff_lit] + lea edi, [ebp+.lengths] + push 287*8 + call .construct_huffman_tree +.block_h_start: ; Huffman + pop edi +.block_h: + lea ebx, [ebp+.huff_lit] + call .get_huffman_code + sub eax, 256 + jnc .not_char + stosb +.bhc: + cmp edi, [ebp+.outEnd] + jb .block_h + mov [ebp+.inPtr], esi + mov [ebp+.dl], dl + mov [ebp+.continue], .block_h + popad + ret +.not_char: + jz .block_loop + cmp eax, 285-256 + ja return.err + jz .h_max +iglobal +deflate.LengthCodesStart: + db 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59 + db 67,83,99,115,131,163,195,227 +deflate.LengthCodesExtra: + db 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5 +endg + movzx ebx, byte [deflate.LengthCodesStart+eax-1] + movzx ecx, byte [deflate.LengthCodesExtra+eax-1] + call .get_bits + add ebx, eax +.length_known: + push ebx + lea ebx, [ebp+.huff_dist] + call .get_huffman_code + cmp eax, 32 + jae return.err +iglobal +align 4 +deflate.DistCodesStart: + dd 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537 + dd 2049,3073,4097,6145,8193,12289,16385,24577,32769,49153 +deflate.DistCodesExtra: + db 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14 +endg + mov ebx, [deflate.DistCodesStart+eax*4] + movzx ecx, byte [deflate.DistCodesExtra+eax] + call .get_bits + add ebx, eax + pop ecx +; ecx=length, ebx=distance +.repmovsbz: + push esi +.repmovsbr: + mov esi, edi + sub esi, ebx + mov eax, [ebp+streamInfo.bufPtr] + sub eax, esi + ja .repmovsb0 + mov eax, [ebp+.outEnd] + sub eax, edi + push ecx + cmp ecx, eax + jb @f + mov ecx, eax +@@: + sub [esp], ecx + rep movsb + pop ecx + jz .repmovsb1 +.repmovsbc: + pop [ebp+.inPtr] + mov [ebp+.blockLen], ecx + mov dword [ebp+.lit_len], ebx + mov [ebp+.dl], dl + mov [ebp+.continue], .restart_repmovsb + popad + ret +.repmovsb0: + add esi, 0x10000 + push ecx + cmp ecx, eax + jb @f + mov ecx, eax +@@: + mov eax, [ebp+.outEnd] + sub eax, edi + cmp ecx, eax + jb @f + mov ecx, eax +@@: + sub [esp], ecx + rep movsb + pop ecx + jz .repmovsb1 + cmp edi, [ebp+.outEnd] + jb .repmovsbr + jmp .repmovsbc +.repmovsb1: + pop esi + jmp .bhc +.restart_repmovsb: + mov ecx, [ebp+.blockLen] + mov ebx, dword [ebp+.lit_len] + jmp .repmovsbz +.h_max: + mov ebx, 258 + xor ecx, ecx + cmp [ebp+.bDeflate64], cl + jz .length_known + mov cl, 16 + call .get_bits + lea ebx, [eax+3] + jmp .length_known + +align 16 +.get_bit: + shr dl, 1 + jnz .ret + sub [ebp+.inLen], 1 + js .gb_refill +@@: + mov dl, [esi] + sub esi, -1 + rcr dl, 1 +.ret: + ret +.gb_refill: + call .refill + jmp @b + +.refill: + push eax + mov eax, [ebp+.inStream] + call fillBuf + mov esi, [eax+streamInfo.bufPtr] + mov eax, [eax+streamInfo.bufDataLen] + dec eax + js return.err + mov [ebp+.inLen], eax + pop eax + ret + +.get_bits: + push ebx + mov ebx, ecx + xor eax, eax + jecxz .gbr +@@: + call .get_bit + rcr eax, 1 + loop @b + mov cl, 32 + sub cl, bl + shr eax, cl +.gbr: + pop ebx + ret + +.get_word: + sub [ebp+.inLen], 1 + jns @f + call .refill +@@: + lodsb + sub [ebp+.inLen], 1 + jns @f + call .refill +@@: + mov ah, [esi] + inc esi + ret + +.construct_huffman_tree: +; edi->bit lengths array, ecx=number of items, ebx->tree root, [esp+4]=size of tree + add [esp+4], ebx + push edx esi + xor eax, eax + xor edx, edx + mov dword [ebx], eax + mov dword [ebx+4], eax +.cht1: + cmp al, [edi+edx] + ja @f + mov al, [edi+edx] +@@: + inc edx + cmp edx, ecx + jb .cht1 + test eax, eax + jz .chtd + push ecx ; remember number of items + push eax ; remember maximum length + lea eax, [ebx+8] + xor edx, edx + inc edx + push 2 + pop ecx +.cht2: + push eax + xor eax, eax +.cht3: + cmp dl, [edi+eax] + jnz @f + dec ecx + js return.err + cmp ebx, [esp+24] + jae return.err + mov [ebx], eax + add ebx, 4 +@@: + inc eax + cmp eax, [esp+8] + jnz .cht3 + pop eax + jecxz .cht4 + push ecx +.cht5: + cmp eax, [esp+24] + jb @f + or eax, -1 +@@: + cmp ebx, [esp+24] + jae return.err + mov [ebx], eax + add ebx, 4 + cmp eax, -1 + jz @f + add eax, 8 +@@: + loop .cht5 + pop ecx + add ecx, ecx +.cht4: + inc edx + cmp edx, [esp] + jbe .cht2 + pop eax + pop eax + jecxz .chtd + or eax, -1 +@@: + cmp ebx, [esp+12] + jae .chtd + mov [ebx], eax + add ebx, 4 + loop @b +.chtd: + pop esi edx + ret 4 + +.get_huffman_code: +; ebx->tree root + xor eax, eax + cmp dword [ebx+4], eax + jz .ghcret +@@: + call .get_bit + setc al + mov ebx, [ebx+4*eax] + cmp ebx, -1 + jz @f + cmp ebx, 0x1000 + jae @b +@@: + mov eax, ebx +.ghcret: + ret + +deflate_get_buf_size: + mov eax, deflate_decoder.size + mov edx, 0x10000 + ret + +deflate_init_decoder: + mov [ebp+deflate_decoder.bDeflate64], 0 + jmp @f + +deflate64_init_decoder: + mov [ebp+deflate_decoder.bDeflate64], 1 +@@: + mov [ebp+streamInfo.fillBuf], deflate_decoder.fillBuf + mov [ebp+deflate_decoder.continue], deflate_decoder.start + ret diff --git a/programs/fs/kfar/trunk/kfar_arc/zip.inc b/programs/fs/kfar/trunk/kfar_arc/zip.inc new file mode 100644 index 0000000000..83e24d2852 --- /dev/null +++ b/programs/fs/kfar/trunk/kfar_arc/zip.inc @@ -0,0 +1,1312 @@ +; Loader of ZIP archives for KFar_Arc. +; Written by diamond in 2007. + +virtual at 0 +file_in_zip: +.fullname dd ? ; pointer to cp866 string +.name dd ? +.namelen dd ? +.bIsDirectory db ? +.bPseudoFolder db ? + rb 2 +.parent dd ? ; pointer to parent directory record +.subfolders dd ? ; head of L2-list of subfolders [for folders] +.subfolders.end dd ? +.subfiles dd ? ; head of L2-list of files [for folders] +.subfiles.end dd ? +.NumSubItems dd ? +.next dd ? ; next item of list of subfolders or files +.prev dd ? ; previous item of list of subfolders or files +.stamp dd ? +.version_made_by dw ? +.version_needed dw ? +.flags dw ? +.method dw ? +.time dw ? +.date dw ? +.crc dd ? +.compressed_size dq ? +.uncompressed_size dq ? +.local_hdr dq ? +.disk dd ? +.attr dd ? +.size = $ +end virtual + +virtual at 0 +handle_zip: +.type dd ? +.root.subfolders dd ? +.root.subfolders.end dd ? +.root.subfiles dd ? +.root.subfiles.end dd ? +.root.NumSubItems dd ? +.curdir dd ? +.NumFiles dd ? +.names_buf dd ? +.host dd ? +.host_datetime rd 6 +.num_disks dd ? +.cur_disk dd ? +.cur_handle dd ? +.host_hPlugin dd ? +.host_idPlugin dd ? +.password_len dd ? ; -1 if no password defined; in characters +.password rb password_maxlen +.basesize = $ +end virtual + +uglobal +align 4 +zip.num_disks dd ? +zip.cur_disk dd ? +zip.cur_handle dd ? +zip.NumAllocated dd ? +zip.NamesSize dd ? +zip.disk_name rb 1024 + +zip64eocd: ; zip64 end of central directory record +.sig dd ? ; signature +.size dq ? ; size of this record +.version_made_by dw ? ; version made by +.version_needed dw ? ; version needed to extract +.disk dd ? ; number of this disk +.cdir_disk dd ? ; number of the disk with the start + ; of the central directory +.cdir_entries_disk dq ? ; total number of entries in the central + ; directory on this disk +.cdir_entries dq ? ; total number of entries in the central directory +.cdir_size dq ? ; size of the central directory +.cdir_start dq ? ; offset of start of central directory +.sz = $ - zip64eocd + +zip.file_header: +.sig dd ? +.version_made_by dw ? ; (absent in local file header) +.version_needed dw ? +.flags dw ? ; general purpose bit flag +.method dw ? ; compression method +.time dw ? ; last modified file time +.date dw ? ; last modified file date +.crc dd ? +.compressed_size dd ? +.uncompressed_size dd ? +.fname_len dw ? ; file name length +.extra_len dw ? ; extra field length +.sz_local = $ - (zip.file_header+2) ; size of local file header +.fcmt_len dw ? ; file comment length +.disk dw ? ; disk number start +.internal_attr dw ? +.external_attr dd ? +.local_hdr dd ? ; relative offset of local header +.sz_cdir = $ - zip.file_header ; size of file header in central directory + +zip.extra: +.id dw ? +.size dw ? +zip.extra.zip64: +.uncompressed_size dq ? +.compressed_size dq ? +.local_hdr dq ? +.disk dd ? +.sz = $ - zip.extra.zip64 +endg + +open_zip: + and [zip.cur_handle], 0 +; look for end of central directory record + push ebp + call [filesize] + sub eax, 1024 + sbb edx, 0 + jnb @f + xor eax, eax + xor edx, edx +@@: + push edx + push eax + push 0 + push ebp + call [seek] + push 1024 + push buffer + push ebp + call [read] + cmp eax, 22 + jge @f + xor eax, eax +.ret: + ret +@@: + mov [inStream], ebp + lea edi, [buffer+eax-22] +@@: + cmp dword [edi], 0x06054B50 + jz .eocd_found + dec edi + cmp edi, buffer + jae @b + xor eax, eax + ret +.eocd_found: + cmp edi, buffer+20 + jb .no_eocd64 + cmp dword [edi-20], 0x07064B50 + jnz .no_eocd64 + mov ebx, ebp + mov ecx, [edi-16] + mov edx, [edi-4] + mov [zip.num_disks], edx + dec edx + mov [zip.cur_disk], edx + cmp edx, ecx + jz @f + push 1 + push dword [esp+8+28] + push dword [esp+12+24] + push dword [esp+16+20] + call zip.open_splitted + test eax, eax + jz .ret + mov ebx, eax +@@: + push dword [edi-8] + push dword [edi-12] + push 0 + push ebx + call [seek] + push zip64eocd.sz + push zip64eocd + push ebx + call [read] + cmp eax, zip64eocd.sz + jnz .close_err + cmp [zip64eocd.sig], 0x06064B50 + jnz .close_err + mov ecx, [zip64eocd.cdir_disk] + cmp ecx, [zip.cur_disk] + jz @f + push 1 + push dword [esp+8+28] + push dword [esp+12+24] + push dword [esp+16+20] + call zip.open_splitted + test eax, eax + jz .ret + mov ebx, eax +@@: + push dword [zip64eocd.cdir_start+4] + push dword [zip64eocd.cdir_start] + push 0 + push ebx + call [seek] + mov ecx, dword [zip64eocd.cdir_entries] + jmp .parse_cdir +.close_err: + call close_cur_handle + or eax, -1 + ret +.no_eocd64: + mov ebx, ebp + movzx ecx, word [edi+6] + movzx edx, word [edi+4] + inc edx + mov [zip.num_disks], edx + dec edx + mov [zip.cur_disk], edx + cmp edx, ecx + jz @f + push 1 + push dword [esp+8+28] + push dword [esp+12+24] + push dword [esp+16+20] + call zip.open_splitted + test eax, eax + jz .ret + mov ebx, eax +@@: + push 0 + push dword [edi+16] + push 0 + push ebx + call [seek] + movzx ecx, word [edi+10] +.parse_cdir: + mov [zip.NumAllocated], ecx + imul ecx, file_in_zip.size + jc .close_err + add ecx, handle_zip.basesize + jc .close_err + mov [hOut.allocated], ecx + call [pgalloc] + test eax, eax + jz .close_err + mov [hOut], eax + push eax + mov edi, eax + shr ecx, 2 + xor eax, eax + rep stosd + mov edi, [esp+8+28] + dec ecx + repnz scasb + not ecx + mov [zip.NamesSize], ecx + call [pgalloc] + mov ebp, eax + pop edi + test eax, eax + jz .free_err + push edi + mov edi, ebp + mov esi, [esp+8+28] + rep movsb + pop edi + mov byte [edi+handle_zip.type], type_zip + add edi, handle_zip.basesize + file_in_zip.version_made_by +.cdir_loop: + mov esi, zip.file_header + push zip.file_header.sz_cdir + push esi + push ebx + call [read] + cmp eax, zip.file_header.sz_cdir + jz .cdir_item_ok + mov ecx, [zip.cur_disk] + inc ecx + cmp ecx, [zip.num_disks] + jz .cdir_done + push 1 + push dword [esp+8+28] + push dword [esp+12+24] + push dword [esp+16+20] + call zip.open_splitted + test eax, eax + jz .free_err + mov ebx, eax + jmp .cdir_loop +.cdir_item_ok: + lodsd + cmp eax, 0x02014B50 + jnz .cdir_done + mov eax, [hOut] + inc [eax+handle_zip.NumFiles] + mov eax, [eax+handle_zip.NumFiles] + cmp eax, [zip.NumAllocated] + jbe .norealloc + inc [zip.NumAllocated] + mov ecx, [hOut.allocated] + add ecx, file_in_zip.size + push ecx + and ecx, 0xFFF + cmp ecx, file_in_zip.size + pop ecx + mov [hOut.allocated], ecx + ja .norealloc + mov edx, [hOut] + call [pgrealloc] + test eax, eax + jnz @f +.free_err: + mov ecx, [hOut] + call [pgfree] + mov ecx, ebp + call [pgfree] + jmp .close_err +@@: + mov [hOut], eax + sub edi, edx + add edi, eax +.norealloc: + push 5 + pop ecx + rep movsd + xor eax, eax + stosd + movsd + stosd + lodsw + mov ecx, [zip.NamesSize] + lea edx, [ecx+0xFFF] + and edx, not 0xFFF + lea ecx, [ecx+eax+1] + mov [zip.NamesSize], ecx + push ecx + add ecx, 0xFFF + and ecx, not 0xFFF + cmp ecx, edx + pop ecx + jz .noreallocname + mov edx, ebp + call [pgrealloc] + test eax, eax + jz .free_err + mov ebp, eax +.noreallocname: + movzx eax, word [esi-2] + inc eax + mov edx, [zip.NamesSize] + sub edx, eax + mov dword [edi-(file_in_zip.uncompressed_size+8)+file_in_zip.fullname], edx + add edx, ebp + dec eax + mov byte [edx+eax], 0 + push eax + push edx + push ebx + call [read] + movzx eax, word [esi-2] + cmp byte [edx+eax-1], '/' + jnz @f + mov byte [edx+eax-1], 0 + mov byte [edi-(file_in_zip.uncompressed_size+8)+file_in_zip.bIsDirectory], 1 +@@: + mov eax, [esi+12] + mov [edi], eax + movzx eax, word [esi+4] + mov [edi+8], eax + lodsw + push esi + movzx ecx, ax + mov edx, ecx +.parse_extra: + sub ecx, 4 + jb .extra_done + mov esi, zip.extra + push 4 + push esi + push ebx + call [read] + cmp eax, 4 + jnz .extra_done + sub edx, eax + cmp word [esi], 1 + jnz .extra_skip + mov esi, zip.extra.zip64 + push esi edi + sub edi, 8 + xchg esi, edi + movsd + movsd + sub esi, 16 + movsd + movsd + add esi, 8 + movsd + movsd + movsd + pop edi esi + movzx eax, [zip.extra.size] + cmp eax, zip.extra.zip64.sz + jb @f + mov al, zip.extra.zip64.sz +@@: + sub ecx, eax + jb .extra_done + push eax + push esi + push ebx + call [read] + sub edx, eax + sub [zip.extra.size], ax + sub edi, 8 + movsd + movsd + sub edi, 16 + movsd + movsd + add edi, 8 + movsd + movsd + movsd + sub edi, 12 +.extra_skip: + movzx eax, word [zip.extra.size] + sub ecx, eax + jb .extra_done + sub edx, eax + push 0 + push eax + push 1 + push ebx + call [seek] + jmp .parse_extra +.extra_done: + pop esi + xor eax, eax + lodsw + add edx, eax + jz @f + push 0 + push edx + push 1 + push ebx + call [seek] +@@: + mov eax, [esi+4] + mov dword [edi+file_in_zip.attr-(file_in_zip.uncompressed_size+8)], eax +; test al, 10h +; setnz byte [edi+file_in_zip.bIsDirectory-(file_in_zip.uncompressed_size+8)] + add edi, file_in_zip.size-file_in_zip.uncompressed_size-8+file_in_zip.version_made_by + jmp .cdir_loop +.cdir_done: + mov edi, [hOut] + mov esi, zip.num_disks + push edi + add edi, handle_zip.num_disks + movsd + movsd + movsd + pop edi + mov [edi+handle_zip.names_buf], ebp + mov ecx, [edi+handle_zip.NumFiles] + jecxz .nofiles + add edi, handle_zip.basesize + file_in_zip.fullname +@@: + add [edi], ebp + add edi, file_in_zip.size + loop @b +.nofiles: + mov edx, [hOut] + mov ebx, [edx+handle_zip.NumFiles] + lea edi, [edx+handle_zip.root.subfolders] + add edx, handle_zip.basesize + push file_in_zip.size + call init_file_links + mov eax, [hOut] + and [eax+handle_zip.curdir], 0 ; set root directory + mov esi, [inStream] + mov [eax+handle_zip.host], esi + or [eax+handle_zip.password_len], -1 + mov esi, [esp+4+20] + mov [eax+handle_zip.host_idPlugin], esi + mov esi, [esp+4+24] + mov [eax+handle_zip.host_hPlugin], esi + lea edi, [eax+handle_zip.host_datetime] + mov esi, [esp+12] + add esi, 8 + mov ecx, 6 + rep movsd + ret + +close_cur_handle: + mov edx, zip.cur_handle + or dword [edx-4], -1 + cmp dword [edx], 0 + jz @f + push dword [edx] + call [close] + and dword [edx], 0 +@@: + ret + +zip.open_splitted: + call close_cur_handle + mov [zip.cur_disk], ecx + inc ecx + mov edx, ecx + cmp ecx, [zip.num_disks] + jnz @f + mov ecx, [inStream] + push 0 + push 0 + push 0 + push ecx + call [seek] + mov eax, ecx + ret 16 +@@: + push esi edi + mov esi, [esp+8+12] + mov edi, zip.disk_name + mov [esp+8+12], edi + mov ecx, 1024 +@@: + lodsb + stosb + test al, al + loopnz @b + jnz .ret0 + cmp ecx, 4 + jb .ret0 + dec edi + mov al, '.' + stosb + cmp edx, 100 + jae .big + mov al, 'z' + stosb + mov eax, edx + aam + add ax, '00' + xchg al, ah + stosw + mov byte [edi], 0 +.nameok: + pop edi esi + push dword [esp+16] + push dword [esp+16] + push dword [esp+16] + push dword [esp+16] + call [open2] + mov [zip.cur_handle], eax + ret 16 +.ret0: + mov byte [edi-1], 0 + pop edi esi + xor eax, eax + ret 16 +.big: + cmp ecx, 12 + jb .ret0 + push 10 + pop ecx + push -'0' + mov eax, edx +@@: + xor edx, edx + div ecx + push edx + test eax, eax + jnz @b +@@: + pop eax + add al, '0' + jz .nameok + stosb + jmp @b + +close_zip: + mov esi, [esp+4] + push [esi+handle_zip.host] + call [close] + mov ecx, [esi+handle_zip.names_buf] + call [pgfree] + mov ecx, [esi+handle_zip.cur_handle] + jecxz @f + push ecx + call [close] +@@: + mov ecx, esi + call [pgfree] + ret 4 + +; ebp=hPlugin, eax->item, edi->info +getattr_zip: + cmp [eax+file_in_zip.bPseudoFolder], 0 + jnz .pseudo + mov esi, eax + mov eax, [eax+file_in_zip.attr] + stosd + xor eax, eax + stosd + stosd + stosd + stosd + stosd + movzx eax, word [esi+file_in_zip.time] + mov ecx, eax + and al, 0x1F + shr ecx, 5 + add eax, eax + stosb + mov eax, ecx + and al, 0x3F + shr ecx, 6 + stosb + mov eax, ecx + stosw + movzx eax, word [esi+file_in_zip.date] + mov ecx, eax + and al, 0x1F + shr ecx, 5 + stosb + mov eax, ecx + and al, 0xF + shr ecx, 4 + stosb + lea eax, [ecx+1980] + stosw + mov eax, dword [esi+file_in_zip.uncompressed_size] + stosd + mov eax, dword [esi+file_in_zip.uncompressed_size+4] + stosd + ret +.pseudo: + push 0x10 ; attributes: folder + pop eax + stosd + xor eax, eax + stosd + lea esi, [ebp+handle_zip.host_datetime] + push 6 + pop ecx + rep movsd + stosd + stosd + ret + +virtual at 0 +file_handle_zip: +.type dd ? +.item dd ? +.base dd ? +.start_disk dd ? +.start dq ? +.pos dq ? +.posc dq ? +.decoder dd ? +.cur_disk dd ? +.cur_disk_start dq ? +.bError db ? +.bPassProtected db ? +.bPassInited db ? + rb 1 +.keys rd 3 +.saved_keys rd 3 +.size = $ +end virtual + +iglobal +handle_table_zip dd handle_table_zip, handle_table_zip +endg + +; ebp=hPlugin, eax->item, edi=mode +open_file_zip: + mov [_esp], esp + mov [_ebp], ebp + mov [error_proc], .error + mov [clear_proc], .clear + mov ecx, [ebp+handle_zip.password_len] + inc ecx + setnz [bPasswordDefined] + jz @f + dec ecx + mov [password_size], ecx + lea esi, [ebp+handle_zip.password] + mov edi, password_ansi + rep movsb +@@: + xor edi, edi + mov [hOut], edi + mov [hOut.allocated], edi + mov ebx, eax + movzx eax, [ebx+file_in_zip.method] + test eax, eax + jz .common +.notcopy: + cmp eax, 8 + jz .deflate + cmp eax, 9 + jz .deflate + push -'0' + push 10 + pop ecx +@@: + xor edx, edx + div ecx + push edx + test eax, eax + jnz @b + mov edi, aUnknownMethod.z + mov al, ' ' + stosb +@@: + pop eax + add al, '0' + stosb + jnz @b + push ContinueBtn + push 1 + push aUnknownMethod_ptr + push 1 + call [SayErr] + xor eax, eax +.ret1: + ret +.deflate: + mov ecx, 0x12000 + call [pgalloc] + test eax, eax + jz .ret1 + mov [hOut], eax + mov ecx, dword [ebx+file_in_zip.compressed_size] + mov dword [eax+streamInfo.fullSize], ecx + mov ecx, dword [ebx+file_in_zip.compressed_size+4] + mov dword [eax+streamInfo.fullSize+4], ecx + mov [eax+streamInfo.fillBuf], zipin.fillBuf + mov [eax+streamInfo.bufSize], 0x2000 - (streamInfo.size+4) - deflate_decoder.size + and [eax+streamInfo.bufDataLen], 0 + lea edx, [eax+streamInfo.size+4] + mov [eax+streamInfo.bufPtr], edx + add edx, [eax+streamInfo.bufSize] + mov ecx, dword [ebx+file_in_zip.uncompressed_size] + mov dword [edx+streamInfo.fullSize], ecx + mov ecx, dword [ebx+file_in_zip.uncompressed_size+4] + mov dword [edx+streamInfo.fullSize+4], ecx + mov [edx+streamInfo.bufSize], 0x10000 + and [edx+streamInfo.bufDataLen], 0 + mov [edx+streamInfo.size], eax + lea eax, [edx+deflate_decoder.size] + mov [edx+streamInfo.bufPtr], eax + push ebp + mov ebp, edx + call deflate_init_decoder + mov edi, ebp + pop ebp + cmp [ebx+file_in_zip.method], 9 + setz [edi+deflate_decoder.bDeflate64] +.common: + mov esi, handle_table_zip + push file_handle_zip.size + pop ecx + call alloc_handle + test eax, eax + jz return.clear + mov edx, [hOut] + mov [edx+streamInfo.size], eax + mov [eax+file_handle_zip.type], type_zip + xor edx, edx + mov dword [eax+file_handle_zip.pos], edx + mov dword [eax+file_handle_zip.pos+4], edx + mov dword [eax+file_handle_zip.posc], edx + mov dword [eax+file_handle_zip.posc+4], edx + mov [eax+file_handle_zip.item], ebx + mov [eax+file_handle_zip.base], ebp + mov [eax+file_handle_zip.decoder], edi + mov [eax+file_handle_zip.bError], dl + mov [eax+file_handle_zip.bPassInited], dl + test [ebx+file_in_zip.flags], 1 + setnz [eax+file_handle_zip.bPassProtected] + mov ecx, [ebx+file_in_zip.disk] + mov [eax+file_handle_zip.start_disk], ecx + mov [eax+file_handle_zip.cur_disk], ecx + mov ecx, dword [ebx+file_in_zip.local_hdr] + mov dword [eax+file_handle_zip.start], ecx + mov ecx, dword [ebx+file_in_zip.local_hdr+4] + mov dword [eax+file_handle_zip.start+4], ecx + mov dword [eax+file_handle_zip.cur_disk_start], edx + mov dword [eax+file_handle_zip.cur_disk_start+4], edx + mov [hOut.allocated], eax + mov [hOut], edx + push ebx + mov ebx, eax + push zip.file_header.sz_local + pop ecx + mov edi, zip.file_header+2 + call zip.read + cmp dword [edi-zip.file_header.sz_local], 0x04034B50 + jnz return.err + movzx ecx, word [edi-4] + movzx eax, word [edi-2] + lea esi, [ecx+eax+zip.file_header.sz_local] + xor edi, edi + call zip.setpos + call zip.update_start + cmp [ebx+file_handle_zip.bPassProtected], 0 + jz .nopass +.redo_pass: + call query_password + jz return.clear + call zip.init_keys + push 12 + pop ecx + mov edi, buffer + call zip.read + mov eax, [ebx+file_handle_zip.item] + mov al, byte [eax+file_in_zip.crc+3] + cmp [edi-1], al + jz .passok + push CancelPassBtn + push 2 + push aArchiveDataErrorPass_ptr + push 1 + call [SayErr] + cmp al, 1 + jnz return.clear + xor eax, eax + mov dword [ebx+file_handle_zip.posc], eax + mov dword [ebx+file_handle_zip.posc+4], eax + mov dword [ebx+file_handle_zip.cur_disk_start], eax + mov dword [ebx+file_handle_zip.cur_disk_start+4], eax + mov eax, [ebx+file_handle_zip.start_disk] + mov [ebx+file_handle_zip.cur_disk], eax + mov [bPasswordDefined], 0 + jmp .redo_pass +.passok: + mov ecx, [password_size] + mov [ebp+handle_zip.password_len], ecx + mov esi, password_ansi + lea edi, [ebp+handle_zip.password] + rep movsb + lea esi, [ebx+file_handle_zip.keys] + lea edi, [ebx+file_handle_zip.saved_keys] + movsd + movsd + movsd + mov esi, 12 + xor edi, edi + call zip.update_start +.nopass: + pop ebx + mov eax, [hOut.allocated] + cmp dword [ebx+file_in_zip.uncompressed_size+4], 0 + jnz .ret + mov ecx, dword [ebx+file_in_zip.uncompressed_size] +if defined LIMIT_FOR_MEM_STREAM + cmp ecx, LIMIT_FOR_MEM_STREAM + ja .ret +end if + push eax ecx + add ecx, 0x3FF + shr ecx, 10 ; get size in Kb + call [getfreemem] + shr eax, 2 + cmp ecx, eax + pop ecx eax + ja .ret +; create memory stream and unpack to memory + mov ebx, eax + add ecx, mem_stream.buf + call [pgalloc] + sub ecx, mem_stream.buf + test eax, eax + jz return.clear + mov edi, eax + mov [hOut], eax + xor eax, eax ; type_mem_stream + stosd ; mem_stream.type + mov eax, ecx + stosd ; mem_stream.size + xor eax, eax + stosd ; mem_stream.pos + push ecx edi + push ecx + push edi + push ebx + call read_zip + pop esi ecx + mov [_esp], esp + mov [_ebp], ebp + mov [error_proc], .error + mov [clear_proc], .clear + cmp eax, -1 + jz .clear +; cmp eax, ecx +; jnz .error +; call crc +; mov edx, [ebx+file_handle_zip.item] +; cmp eax, [edx+file_in_zip.crc] +; jnz .error + call .1 + mov eax, [hOut] +.ret: + ret + +.error: + push ContinueBtn + push 1 + push aArchiveDataError_ptr + push 1 + call [SayErr] +.clear: + mov ecx, [hOut] + call [pgfree] +.1: + mov ebx, [hOut.allocated] + test ebx, ebx + jz @f + push ebx + call close_file_zip +@@: + xor eax, eax + ret + +close_file_zip: + mov ecx, [ebx+file_handle_zip.decoder] + jecxz @f + mov ecx, [ecx+streamInfo.size] + call [pgfree] +@@: + mov esi, ebx + call free_handle + ret 4 + +zip.init_keys: + mov [ebx+file_handle_zip.keys+0], 305419896 + mov [ebx+file_handle_zip.keys+4], 591751049 + mov [ebx+file_handle_zip.keys+8], 878082192 + mov ecx, [password_size] + jecxz .empty + mov esi, password_ansi + xor eax, eax +@@: + lodsb + call zip.update_keys + loop @b +.empty: + mov [ebx+file_handle_zip.bPassInited], 1 + ret + +zip.update_keys: + mov dl, byte [ebx+file_handle_zip.keys] + xor dl, al + movzx edx, dl + mov eax, [ebx+file_handle_zip.keys] + shr eax, 8 + xor eax, [crc_table+edx*4] + mov [ebx+file_handle_zip.keys], eax + movzx eax, al + add eax, [ebx+file_handle_zip.keys+4] + imul eax, 134775813 + inc eax + mov [ebx+file_handle_zip.keys+4], eax + shr eax, 24 + mov edx, [ebx+file_handle_zip.keys+8] + xor al, dl + shr edx, 8 + xor edx, [crc_table+eax*4] + mov [ebx+file_handle_zip.keys+8], edx + ret + +zip.decrypt_byte: +; out: ah = result + mov eax, [ebx+file_handle_zip.keys+8] + or eax, 2 + mov edx, eax + xor edx, 1 + mul edx + ret + +zip.get_cur_handle: + mov edx, [ebp+handle_zip.host] + mov eax, [ebp+handle_zip.num_disks] + dec eax + cmp eax, [ebx+file_handle_zip.cur_disk] + jz .handleok + inc eax + mov [zip.num_disks], eax + mov edx, [ebp+handle_zip.cur_handle] + mov eax, [ebp+handle_zip.cur_disk] + cmp eax, [ebx+file_handle_zip.cur_disk] + jz .handleok + mov [zip.cur_handle], edx + push ecx + mov ecx, [ebx+file_handle_zip.cur_disk] + push 1 + push [ebp+handle_zip.names_buf] + push [ebp+handle_zip.host_hPlugin] + push [ebp+handle_zip.host_idPlugin] + call zip.open_splitted + pop ecx + mov edx, eax + test eax, eax + jnz @f + push zip.disk_name + push aCannotOpenFile + mov eax, esp + push ContinueBtn + push 1 + push eax + push 2 + call [SayErr] + jmp return.clear +@@: + mov [ebp+handle_zip.cur_handle], eax + mov eax, [ebx+file_handle_zip.cur_disk] + mov [ebp+handle_zip.cur_disk], eax +.handleok: + ret + +zip.read: +; in: ebx=hFile, edi->buf, ecx=size + push ebp edi + mov ebp, [ebx+file_handle_zip.base] +.s: + call zip.get_cur_handle + mov eax, dword [ebx+file_handle_zip.posc] + mov esi, dword [ebx+file_handle_zip.posc+4] + sub eax, dword [ebx+file_handle_zip.cur_disk_start] + sbb esi, dword [ebx+file_handle_zip.cur_disk_start+4] + push eax + mov eax, dword [ebx+file_handle_zip.cur_disk] + cmp eax, dword [ebx+file_handle_zip.start_disk] + pop eax + jnz @f + add eax, dword [ebx+file_handle_zip.start] + adc esi, dword [ebx+file_handle_zip.start+4] +@@: + push esi + push eax + push 0 + push edx + call [seek] + push ecx + push edi + push edx + call [read] + cmp eax, -1 + jz .error + add edi, eax + add dword [ebx+file_handle_zip.posc], eax + adc dword [ebx+file_handle_zip.posc+4], 0 + sub ecx, eax + jz .ok + inc dword [ebx+file_handle_zip.cur_disk] + mov eax, dword [ebx+file_handle_zip.posc] + mov dword [ebx+file_handle_zip.cur_disk_start], eax + mov eax, dword [ebx+file_handle_zip.posc+4] + mov dword [ebx+file_handle_zip.cur_disk_start+4], eax + jmp .s +.ok: + cmp [ebx+file_handle_zip.bPassInited], 0 + jnz .decrypt + pop eax ebp + ret +.decrypt: + mov ecx, edi + pop edi + sub ecx, edi + jz .nodata +@@: + call zip.decrypt_byte + xor [edi], ah + mov al, [edi] + inc edi + call zip.update_keys + loop @b +.nodata: + pop ebp + ret +.error: + push ContinueBtn + push 1 + push aReadError_ptr + push 1 + call [SayErr] + jmp return.clear + +zip.setpos: +; in: ebx=hFile, edi:esi=newpos + cmp [ebx+file_handle_zip.bPassInited], 0 + jnz .pass + push ebp + mov ebp, [ebx+file_handle_zip.base] + push edi esi + sub esi, dword [ebx+file_handle_zip.cur_disk_start] + sbb edi, dword [ebx+file_handle_zip.cur_disk_start+4] + jae .fwd + mov eax, [ebx+file_handle_zip.start_disk] + mov [ebx+file_handle_zip.cur_disk], eax + and dword [ebx+file_handle_zip.cur_disk_start], 0 + and dword [ebx+file_handle_zip.cur_disk_start+4], 0 + pop esi edi + push edi esi +.fwd: + call zip.get_cur_handle + push edx + call [filesize] + push eax + mov eax, [ebx+file_handle_zip.cur_disk] + cmp eax, [ebx+file_handle_zip.start_disk] + pop eax + jnz @f + sub eax, dword [ebx+file_handle_zip.start] + sbb edx, dword [ebx+file_handle_zip.start+4] +@@: + sub esi, eax + sbb edi, edx + jb @f + inc [ebx+file_handle_zip.cur_disk] + add dword [ebx+file_handle_zip.cur_disk_start], eax + adc dword [ebx+file_handle_zip.cur_disk_start+4], edx + jmp .fwd +@@: + pop esi edi + mov dword [ebx+file_handle_zip.posc], esi + mov dword [ebx+file_handle_zip.posc+4], edi + pop ebp + ret +.pass: + push edi esi + sub esi, dword [ebx+file_handle_zip.posc] + sbb edi, dword [ebx+file_handle_zip.posc+4] + jae .pfwd + lea esi, [ebx+file_handle_zip.saved_keys] + lea edi, [ebx+file_handle_zip.keys] + movsd + movsd + movsd + and dword [ebx+file_handle_zip.posc], 0 + and dword [ebx+file_handle_zip.posc+4], 0 + mov eax, [ebx+file_handle_zip.start_disk] + mov [ebx+file_handle_zip.cur_disk], eax + and dword [ebx+file_handle_zip.cur_disk_start], 0 + and dword [ebx+file_handle_zip.cur_disk_start+4], 0 + pop esi edi + push edi esi +.pfwd: + push edi esi + mov ecx, 1024 + sub esi, ecx + sbb edi, 0 + jae @f + add ecx, esi +@@: + push ecx + mov edi, buffer + call zip.read + pop ecx + pop esi edi + sub esi, ecx + sbb edi, 0 + mov eax, esi + or eax, edi + jnz .pfwd + pop esi edi + ret + +zip.update_start: +; edi=0, esi=pos + sub esi, dword [ebx+file_handle_zip.cur_disk_start] + mov dword [ebx+file_handle_zip.cur_disk_start], edi + add dword [ebx+file_handle_zip.start], esi + adc dword [ebx+file_handle_zip.start+4], edi + mov dword [ebx+file_handle_zip.posc], edi + mov dword [ebx+file_handle_zip.posc+4], edi + mov eax, [ebx+file_handle_zip.cur_disk] + cmp eax, [ebx+file_handle_zip.start_disk] + jz @f + mov [ebx+file_handle_zip.start_disk], eax + mov dword [ebx+file_handle_zip.start], esi + mov dword [ebx+file_handle_zip.start+4], edi +@@: + ret + +; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size); +read_zip: + mov [_esp], esp + mov [_ebp], ebp + mov [error_proc], .error + mov [clear_proc], .clear + cmp [ebx+file_handle_zip.bError], 0 + jnz .reterr + mov edi, [esp+8] + mov ecx, [esp+12] + mov esi, [ebx+file_handle_zip.item] + mov edx, dword [esi+file_in_zip.uncompressed_size] + mov esi, dword [esi+file_in_zip.uncompressed_size+4] + sub edx, dword [ebx+file_handle_zip.pos] + sbb esi, dword [ebx+file_handle_zip.pos+4] + jnz @f + cmp edx, ecx + jae @f + mov ecx, edx +@@: + jecxz .done + mov eax, [ebx+file_handle_zip.decoder] + test eax, eax + jnz .notcopy + call zip.read + jmp .done +.notcopy: + mov dword [eax+streamInfo.fullSize], ecx + and dword [eax+streamInfo.fullSize+4], 0 + call read_7z_to_buf +.done: + sub edi, [esp+8] + mov eax, edi + add dword [ebx+file_handle_zip.pos], eax + adc dword [ebx+file_handle_zip.pos+4], 0 +.ret: + ret 12 + +.error: + push ContinueBtn + push 1 + push aArchiveDataError_ptr + push 1 + call [SayErr] +.clear: + mov ebx, [esp+4] + mov [ebx+file_handle_zip.bError], 1 +.reterr: + or eax, -1 + ret 12 + +zipin.fillBuf: + mov ebx, [eax+streamInfo.size] + call zip.read + popad + ret + +; void __stdcall setpos(HANDLE hFile, __int64 pos); +setpos_zip: + mov [_esp], esp + mov [_ebp], ebp + mov [error_proc], read_zip.error + mov [clear_proc], read_zip.clear + cmp [ebx+file_handle_zip.decoder], 0 + jnz .notcopy + mov esi, [esp+8] + mov edi, [esp+12] + call zip.setpos + mov dword [ebx+file_handle_zip.pos], esi + mov dword [ebx+file_handle_zip.pos+4], edi + ret 12 +.notcopy: + cmp [ebx+file_handle_zip.bError], 0 + jnz .backward + mov ecx, [esp+8] + mov edx, [esp+12] + sub ecx, dword [ebx+file_handle_zip.pos] + sbb edx, dword [ebx+file_handle_zip.pos+4] + jb .backward + mov eax, [ebx+file_handle_zip.decoder] + mov dword [eax+streamInfo.fullSize], ecx + mov dword [eax+streamInfo.fullSize+4], edx + call skip_7z + add dword [ebx+file_handle_zip.pos], ecx + adc dword [ebx+file_handle_zip.pos+4], edx + ret 12 +.backward: + xor eax, eax + mov [ebx+file_handle_zip.bError], al + mov dword [ebx+file_handle_zip.pos], eax + mov dword [ebx+file_handle_zip.pos+4], eax + mov dword [ebx+file_handle_zip.posc], eax + mov dword [ebx+file_handle_zip.posc+4], eax + mov dword [ebx+file_handle_zip.cur_disk_start], eax + mov dword [ebx+file_handle_zip.cur_disk_start+4], eax + lea esi, [ebx+file_handle_zip.saved_keys] + lea edi, [ebx+file_handle_zip.keys] + movsd + movsd + movsd + mov eax, [ebx+file_handle_zip.start_disk] + mov [ebx+file_handle_zip.cur_disk], eax + mov eax, [ebx+file_handle_zip.decoder] + mov eax, [eax+deflate_decoder.inStream] + mov esi, [ebx+file_handle_zip.item] + mov ecx, dword [esi+file_in_zip.compressed_size] + mov dword [eax+streamInfo.fullSize], ecx + mov ecx, dword [esi+file_in_zip.compressed_size+4] + mov dword [eax+streamInfo.fullSize+4], ecx + and [eax+streamInfo.bufDataLen], 0 + lea ebp, [eax+streamInfo.size+4] + add ebp, [eax+streamInfo.bufSize] + and [ebp+streamInfo.bufDataLen], 0 + call deflate_init_decoder + cmp [esi+file_in_zip.method], 9 + setz [ebp+deflate_decoder.bDeflate64] + mov eax, [esp+8] + mov dword [ebp+streamInfo.fullSize], eax + mov eax, [esp+12] + mov dword [ebp+streamInfo.fullSize+4], eax + mov eax, ebp + call skip_7z + mov eax, [esp+8] + mov dword [ebx+file_handle_zip.pos], eax + mov eax, [esp+12] + mov dword [ebx+file_handle_zip.pos+4], eax + ret 12