0,0 → 1,3138 |
; Loading of 7z archives was ported from 7z sources (file 7zip\Archive\7z\7zIn.cpp). |
; The version 7-Zip 4.42 was used. |
; 7-Zip is copyright (C) 1999-2006 Igor Pavlov. |
; Assembler version as KFar plugin has been written by diamond, 2007. |
|
virtual at 0 |
file_in_7z: |
.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 |
.attr dd ? |
.FileCRC dd ? |
.startPos dq ? |
.CreationTime dq ? |
.LastAccessTime dq ? |
.LastWriteTime dq ? |
.UnPackSize dq ? |
.folder dd ? |
.folder_index dd ? |
.folderStart dq ? |
.bAttrDefined db ? |
.bStartPosDefined db ? |
.bCRCDefined db ? |
.bCreationTimeDefined db ? |
.bLastAccessTimeDefined db ? |
.bLastWriteTimeDefined db ? |
.bHasStream db ? |
.bAnti db ? |
.stamp dd ? |
.size = $ |
end virtual |
|
virtual at 0 |
handle_7z: |
.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 |
; streams info |
.numPackStreams dd ? |
.packSizes dd ? |
.numFolders dd ? |
.unpackCRCsDefined dd ? |
.unpackCRCs dd ? |
.folders dd ? |
.last_folder dd ? |
.last_pos dq ? |
.last_context dd ? |
.last_main_stream dd ? |
.password_len dd ? ; -1 if no password defined; in characters |
.password rw password_maxlen |
.basesize = $ |
; .size = .basesize + .NumFiles * file_in_7z.size |
end virtual |
|
iglobal |
align 4 |
empty_7z_handle: |
dd type_7z |
dd 0,0,0,0,0,0 |
endg |
|
kEnd = 0 |
kHeader = 1 |
kArchiveProperties = 2 |
kAdditionalStreamsInfo = 3 |
kMainStreamsInfo = 4 |
kFilesInfo = 5 |
kPackInfo = 6 |
kUnPackInfo = 7 |
kSubStreamsInfo = 8 |
kSize = 9 |
kCRC = 10 |
kFolder = 11 |
kCodersUnPackSize = 12 |
kNumUnPackStream = 13 |
kEmptyStream = 14 |
kEmptyFile = 15 |
kAnti = 16 |
kName = 17 |
kCreationTime = 18 |
kLastAccessTime = 19 |
kLastWriteTime = 20 |
kWinAttributes = 21 |
kComment = 22 |
kEncodedHeader = 23 |
kStartPos = 24 |
|
_7z.ReadByte: |
cmp edi, [bufend] |
jae return.err |
mov al, [edi] |
inc edi |
ret |
_7z.ReadWord: |
add edi, 2 |
cmp edi, [bufend] |
ja return.err |
mov ax, [edi-2] |
ret |
_7z.ReadDword: |
add edi, 4 |
cmp edi, [bufend] |
ja return.err |
mov eax, [edi-4] |
ret |
|
_7z.SkipSize: |
test edx, edx |
jnz return.err |
add edi, eax |
jc return.err |
cmp edi, [bufend] |
ja return.err |
ret |
|
_7z.ReadNumber: |
xor eax, eax |
push eax |
push eax |
call _7z.ReadByte |
push ecx |
xor ecx, ecx |
@@: |
add al, al |
jnc @f |
inc ecx |
jmp @b |
@@: |
shr eax, cl |
shr eax, 1 |
jz @f |
mov [esp+4+ecx], al |
@@: |
jecxz .ret |
push edx |
xor edx, edx |
@@: |
call _7z.ReadByte |
mov [esp+8+edx], al |
inc edx |
loop @b |
pop edx |
.ret: |
pop ecx |
pop eax |
pop edx |
ret |
|
_7z.ReadNum: |
push edx |
call _7z.ReadNumber |
test edx, edx |
jnz return.err |
test eax, eax |
js return.err |
pop edx |
ret |
|
open_7z: |
; CInArchive::ReadDatabase() |
cmp byte [esi+6], 0 ; major version must be 0 |
; minor version does not be checked ([byte +7]=2 for now) |
jz @f |
xor eax, eax |
ret |
@@: |
and [hOut], 0 |
and [_7z.FreeSubStreams], 0 |
and [_7z.tmpVector], 0 |
push esi |
add esi, 12 |
mov ecx, 20 |
call crc |
pop esi |
cmp eax, [esi+8] |
jnz .header_crc_error |
cmp dword [esi+24], 0 |
jnz .header_error |
mov edi, buffer |
mov ecx, [esi+20] |
mov [bufsize], ecx |
test ecx, ecx |
jnz .notempty |
mov eax, empty_7z_handle |
push ebp |
call [close] |
ret |
.notempty: |
cmp ecx, 1024 |
jbe @f |
call [pgalloc] |
test eax, eax |
jz .reterr |
mov edi, eax |
@@: |
mov [bufptr], edi |
lea eax, [edi+ecx] |
mov [bufend], eax |
mov eax, [esi+12] |
mov edx, [esi+16] |
add eax, 20h ; end of main header |
adc edx, 0 |
push edx |
push eax |
push 0 |
push ebp |
call [seek] |
push ecx |
push edi |
push ebp |
call [read] |
cmp eax, ecx |
jnz .header_error |
push esi |
mov esi, edi |
call crc |
pop esi |
cmp eax, [esi+28] |
jz .header_ok |
.header_crc_error: |
.header_error: |
push ContinueBtn |
push 1 |
push HeaderError_ptr |
push 1 |
call [SayErr] |
.clear: |
mov ecx, [_7z.tmpVector] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [hOut] |
jecxz @f |
call _7z.CloseHandle |
@@: |
mov ebx, [_7z.dataVectorSize] |
test ebx, ebx |
jz @f |
call _7z.ReadAndDecodePackedStreams.free2 |
@@: |
mov ecx, [_7z.FreeSubStreams] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [bufptr] |
cmp ecx, buffer |
jz .reterr |
call [pgfree] |
.reterr: |
or eax, -1 |
ret |
.header_ok: |
mov [_esp], esp |
mov [inStream], ebp |
.loop: |
mov [error_proc], .header_error |
mov [clear_proc], .clear |
and [_7z.dataVectorSize], 0 |
call _7z.ReadNum |
cmp eax, kHeader |
jz .found_header |
cmp eax, kEncodedHeader |
jnz .header_error |
call _7z.ReadAndDecodePackedStreams |
cmp [_7z.StreamsInfo.numFolders], 0 |
jz .free_empty |
cmp [_7z.StreamsInfo.numFolders], 1 |
jnz return.err |
mov ecx, [bufptr] |
cmp ecx, buffer |
jz @f |
call [pgfree] |
@@: |
mov edi, [_7z.unpbuf+4] |
mov [bufptr], edi |
mov ecx, [_7z.unpbuf] |
add ecx, edi |
mov [bufend], ecx |
mov [error_proc], .header_error |
mov [clear_proc], .clear |
and [_7z.dataVectorSize], 0 |
call _7z.ReadNum |
cmp eax, kHeader |
jz .found_header |
jmp return.err |
.free_empty: |
mov ecx, [bufptr] |
cmp ecx, buffer |
jz @f |
call [pgfree] |
@@: |
push [inStream] |
call [close] |
mov eax, empty_7z_handle |
ret |
.found_header: |
call _7z.ReadNum |
cmp eax, kArchiveProperties |
jnz .no_archive_props |
@@: |
call _7z.ReadNum |
test eax, eax |
jz @f |
call _7z.SkipData |
jmp @b |
@@: |
call _7z.ReadNum |
.no_archive_props: |
cmp eax, kAdditionalStreamsInfo |
jnz .no_additional_streams |
call _7z.ReadAndDecodePackedStreams |
mov eax, [_7z.unpacked] |
mov [_7z.dataVector], eax |
mov eax, [_7z.StreamsInfo.numFolders] |
mov [_7z.dataVectorSize], eax |
mov [error_proc], .header_error |
mov [clear_proc], .clear |
call _7z.ReadNum |
.no_additional_streams: |
cmp eax, kMainStreamsInfo |
jnz return.err |
call _7z.ReadStreamsInfo |
call _7z.ReadNum |
test eax, eax |
jnz .notempty2 |
.empty2: |
mov ebx, [_7z.dataVectorSize] |
test ebx, ebx |
jz @f |
call _7z.ReadAndDecodePackedStreams.free2 |
@@: |
mov ecx, [_7z.FreeSubStreams] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [bufptr] |
cmp ecx, buffer |
jz @f |
call [pgfree] |
@@: |
push [inStream] |
call [close] |
mov eax, empty_7z_handle |
ret |
.notempty2: |
cmp eax, kFilesInfo |
jnz return.err |
call _7z.ReadNum |
test eax, eax |
jz .empty2 |
mov ebx, eax ; number of files in archive |
imul ecx, ebx, file_in_7z.size |
add ecx, handle_7z.basesize |
mov [hOut.allocated], ecx |
call [pgalloc] |
test eax, eax |
jz return.clear |
mov [hOut], eax |
mov [eax+handle_7z.type], type_7z |
mov [eax+handle_7z.NumFiles], ebx |
push edi |
lea edi, [eax+handle_7z.numPackStreams] |
mov esi, _7z.StreamsInfo |
mov ecx, 6 |
rep movsd |
or [eax+handle_7z.password_len], -1 |
or [eax+handle_7z.last_folder], -1 |
mov [eax+handle_7z.last_context], ecx |
mov [eax+handle_7z.names_buf], ecx |
mov [eax+handle_7z.host], ecx |
cmp [bPasswordDefined], cl |
jz @f |
mov ecx, [password_size] |
mov [eax+handle_7z.password_len], ecx |
lea edi, [eax+handle_7z.password] |
mov esi, password_unicode |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
@@: |
lea edi, [eax+handle_7z.basesize] |
imul ecx, ebx, file_in_7z.size/4 |
xor eax, eax |
rep stosd |
pop edi |
mov eax, [_7z.StreamsInfo.SubStreamsSizes] |
mov [_7z.FreeSubStreams], eax |
mov [error_proc], .header_error |
mov [clear_proc], .clear |
mov ecx, ebx |
shl ecx, 2 |
call [pgalloc] |
test eax, eax |
jz return.clear |
push edi |
mov edi, eax |
mov [_7z.tmpVector], eax |
add eax, ebx |
mov [_7z.emptyStreams], eax |
add eax, ebx |
mov [_7z.emptyFiles], eax |
add eax, ebx |
mov [_7z.antiFiles], eax |
mov ecx, ebx |
xor eax, eax |
rep stosd |
pop edi |
mov [_7z.numEmptyStreams], eax |
.parse_header: |
call _7z.ReadNum |
test eax, eax |
jz .parse_header_done |
mov ecx, eax ; ecx = type |
call _7z.ReadNum ; eax = size |
cmp ecx, kName |
jz .parse_names |
cmp ecx, kWinAttributes |
jz .parse_winAttr |
cmp ecx, kStartPos |
jz .parse_startPos |
cmp ecx, kEmptyStream |
jz .parse_emptyStream |
cmp ecx, kEmptyFile |
jz .parse_emptyFile |
cmp ecx, kAnti |
jz .parse_anti |
cmp ecx, kCreationTime |
jz .parse_time |
cmp ecx, kLastWriteTime |
jz .parse_time |
cmp ecx, kLastAccessTime |
jz .parse_time |
xor edx, edx |
call _7z.SkipSize |
jmp .parse_header |
.parse_names: |
push eax |
call _7z.SwitchStream |
pop eax |
jz @f |
mov eax, [bufend] |
sub eax, edi |
@@: |
shr eax, 1 ; size of ANSI string is a half of size of UNICODE string |
mov ecx, eax |
call [pgalloc] |
test eax, eax |
jz return.clear |
mov ebp, eax |
mov esi, [hOut] |
mov [esi+handle_7z.names_buf], eax |
add eax, ecx |
push eax ; remember limit |
mov ecx, ebx |
add esi, handle_7z.basesize + file_in_7z.fullname |
mov [bWasWarning], 0 |
.parse_names_loop: |
mov [esi], ebp |
add esi, file_in_7z.size |
.parse_names_loop_int: |
cmp ebp, [esp] |
jae return.err |
call _7z.ReadWord |
; UNICODE char -> cp866 char |
cmp ax, 0x80 |
jb .id |
cmp ax, 0x401 |
jz .yo1 |
cmp ax, 0x451 |
jz .yo2 |
cmp ax, 0x410 |
jb .unk |
cmp ax, 0x440 |
jb .rus1 |
cmp ax, 0x450 |
jb .rus2 |
.unk: |
cmp [bWasWarning], 0 |
jnz @f |
push ContinueBtn |
push 1 |
push aEncodingProblem_str_ptr |
push 3 |
push aEncodingProblem |
call [Message] |
inc [bWasWarning] |
@@: |
mov al, '_' |
jmp .id |
.yo1: |
mov al, 'ð' |
jmp .id |
.yo2: |
mov al, 'ñ' |
jmp .id |
.rus1: |
; 0x410-0x43F -> 0x80-0xAF |
add al, 0x70 |
jmp .id |
.rus2: |
; 0x440-0x44F -> 0xE0-0xEF |
add al, 0xA0 |
.id: |
mov [ebp], al |
inc ebp |
test al, al |
jnz .parse_names_loop_int |
loop .parse_names_loop |
pop eax |
call _7z.UnswitchStream |
jmp .parse_header |
.parse_winAttr: |
mov edx, [_7z.tmpVector] |
push ebx |
mov ecx, ebx |
mov ebx, edx |
call _7z.ReadBoolVector2 |
pop ebx |
call _7z.SwitchStream |
mov esi, [hOut] |
add esi, handle_7z.basesize |
mov ecx, ebx |
.winAttrLoop: |
mov al, [edx] |
inc edx |
mov [esi+file_in_7z.bAttrDefined], al |
test al, al |
jz @f |
call _7z.ReadDword |
mov [esi+file_in_7z.attr], eax |
@@: |
add esi, file_in_7z.size |
loop .winAttrLoop |
call _7z.UnswitchStream |
jmp .parse_header |
.parse_startPos: |
mov edx, [_7z.tmpVector] |
push ebx |
mov ecx, ebx |
mov ebx, edx |
call _7z.ReadBoolVector2 |
pop ebx |
call _7z.SwitchStream |
mov esi, [hOut] |
add esi, handle_7z.basesize |
mov ecx, ebx |
.startPosLoop: |
mov al, [edx] |
inc edx |
mov [esi+file_in_7z.bStartPosDefined], al |
test al, al |
jz @f |
call _7z.ReadDword |
mov dword [esi+file_in_7z.startPos], eax |
call _7z.ReadDword |
mov dword [esi+file_in_7z.startPos+4], eax |
@@: |
add esi, file_in_7z.size |
loop .startPosLoop |
call _7z.UnswitchStream |
jmp .parse_header |
.parse_emptyStream: |
mov edx, [_7z.emptyStreams] |
push ebx |
mov ecx, ebx |
mov ebx, edx |
call _7z.ReadBoolVector |
pop ebx |
and [_7z.numEmptyStreams], 0 |
mov ecx, ebx |
.emptyStrLoop: |
cmp byte [edx], 0 |
jz @f |
inc [_7z.numEmptyStreams] |
@@: |
inc edx |
loop .emptyStrLoop |
jmp .parse_header |
.parse_emptyFile: |
push ebx |
mov ecx, [_7z.numEmptyStreams] |
mov ebx, [_7z.emptyFiles] |
call _7z.ReadBoolVector |
pop ebx |
jmp .parse_header |
.parse_anti: |
push ebx |
mov ecx, [_7z.numEmptyStreams] |
mov ebx, [_7z.antiFiles] |
call _7z.ReadBoolVector |
pop ebx |
jmp .parse_header |
.parse_time: |
push ecx |
push ebx |
mov ecx, ebx |
mov ebx, [_7z.tmpVector] |
call _7z.ReadBoolVector2 |
pop ebx |
call _7z.SwitchStream |
mov esi, [hOut] |
add esi, handle_7z.basesize |
xor ecx, ecx |
.timeLoop: |
mov eax, [_7z.tmpVector] |
mov al, [eax+ecx] |
pop edx |
push edx |
mov [esi + file_in_7z.bCreationTimeDefined + edx - kCreationTime], al |
test al, al |
jz @f |
call _7z.ReadDword |
push eax |
call _7z.ReadDword |
mov edx, eax |
pop eax |
push edi |
mov edi, [esp+4] |
lea edi, [esi + file_in_7z.CreationTime + (edi-kCreationTime)*8] |
call ntfs_datetime_to_bdfe |
pop edi |
@@: |
add esi, file_in_7z.size |
inc ecx |
cmp ecx, ebx |
jb .timeLoop |
call _7z.UnswitchStream |
pop eax |
jmp .parse_header |
.parse_header_done: |
xor ecx, ecx ; index in emptyFiles |
xor edx, edx ; index in subStreams |
xor ebp, ebp ; index in files |
mov esi, [hOut] |
add esi, handle_7z.basesize |
.filesLoop: |
mov eax, [_7z.emptyStreams] |
mov al, [eax+ebp] |
xor al, 1 |
mov [esi+file_in_7z.bHasStream], al |
jz .nostream |
mov [esi+file_in_7z.bIsDirectory], 0 |
mov [esi+file_in_7z.bAnti], 0 |
mov eax, [_7z.StreamsInfo.SubStreamsSizes] |
push dword [eax+edx*8] |
pop dword [esi+file_in_7z.UnPackSize] |
push dword [eax+edx*8+4] |
pop dword [esi+file_in_7z.UnPackSize+4] |
mov eax, [_7z.StreamsInfo.SubStreamsCRCsDefined] |
mov al, [eax+edx] |
mov [esi+file_in_7z.bCRCDefined], al |
test al, al |
jz @f |
mov eax, [_7z.StreamsInfo.SubStreamsCRCs] |
mov eax, [eax+edx*4] |
mov [esi+file_in_7z.FileCRC], eax |
@@: |
inc edx |
jmp .filesCont |
.nostream: |
mov eax, [_7z.emptyFiles] |
cmp byte [eax+ecx], 0 |
setz [esi+file_in_7z.bIsDirectory] |
mov eax, [_7z.antiFiles] |
cmp byte [eax+ecx], 0 |
setnz [esi+file_in_7z.bAnti] |
and dword [esi+file_in_7z.UnPackSize], 0 |
and dword [esi+file_in_7z.UnPackSize+4], 0 |
mov [esi+file_in_7z.bCRCDefined], 0 |
inc ecx |
.filesCont: |
inc ebp |
add esi, file_in_7z.size |
dec ebx |
jnz .filesLoop |
mov ecx, [_7z.tmpVector] |
call [pgfree] |
and [_7z.tmpVector], 0 |
mov ebx, [_7z.dataVectorSize] |
test ebx, ebx |
jz @f |
call _7z.ReadAndDecodePackedStreams.free2 |
and [_7z.dataVectorSize], 0 |
@@: |
mov ecx, [_7z.FreeSubStreams] |
jecxz @f |
call [pgfree] |
and [_7z.FreeSubStreams], 0 |
@@: |
mov ecx, [bufptr] |
cmp ecx, buffer |
jz @f |
call [pgfree] |
mov [bufptr], buffer |
@@: |
xor esi, esi ; index of folder |
mov edi, [hOut] |
mov ebx, [edi+handle_7z.NumFiles] |
add edi, handle_7z.basesize ; pointer to fileinfo |
push 0 ; start index of packed stream for folder |
.getfoldersloop0: |
xor edx, edx ; index in folder |
push edx edx ; position in folder |
.getfoldersloop: |
dec ebx |
js .getfoldersdone |
cmp [edi+file_in_7z.bHasStream], 0 |
jnz @f |
test edx, edx |
jz .nofolder |
@@: |
test edx, edx |
jnz .notfirst |
; skip empty folders |
@@: |
mov eax, [hOut] |
cmp esi, [eax+handle_7z.numFolders] |
jae return.err |
mov eax, [eax+handle_7z.folders] |
mov eax, [eax+esi*4] |
cmp edx, [eax+_7z.StreamsInfo.numUnPackStreams] |
jb @f |
inc esi |
jmp @b |
@@: |
.notfirst: |
mov [edi+file_in_7z.folder], esi |
mov [edi+file_in_7z.folder_index], edx |
mov eax, [esp] |
mov dword [edi+file_in_7z.folderStart], eax |
mov eax, [esp+4] |
mov dword [edi+file_in_7z.folderStart+4], eax |
mov ecx, dword [edi+file_in_7z.UnPackSize] |
add [esp], ecx |
mov ecx, dword [edi+file_in_7z.UnPackSize+4] |
adc [esp+4], ecx |
add edi, file_in_7z.size |
inc edx |
mov eax, [hOut] |
mov eax, [eax+handle_7z.folders] |
mov eax, [eax+esi*4] |
cmp edx, [eax+_7z.StreamsInfo.numUnPackStreams] |
jb .getfoldersloop |
inc esi |
pop edx edx |
jmp .getfoldersloop0 |
.nofolder: |
push -1 |
pop eax |
mov [edi+file_in_7z.folder], eax |
mov [edi+file_in_7z.folder_index], eax |
mov dword [edi+file_in_7z.folderStart], eax |
mov dword [edi+file_in_7z.folderStart+4], eax |
add edi, file_in_7z.size |
jmp .getfoldersloop |
.getfoldersdone: |
pop eax eax eax |
mov ebp, [hOut] |
mov esi, [ebp+handle_7z.folders] |
xor ebx, ebx |
cmp ebx, [ebp+handle_7z.numFolders] |
jae .getoffsdone |
.getoffsloop: |
lodsd |
test ebx, ebx |
jnz .getoffs2 |
mov edx, dword [_7z.StreamsInfo.dataOffset] |
mov dword [eax+_7z.StreamsInfo.packOffset], edx |
mov edx, dword [_7z.StreamsInfo.dataOffset+4] |
mov dword [eax+_7z.StreamsInfo.packOffset+4], edx |
jmp .getoffscont |
.getoffs2: |
mov ecx, [esi-8] |
mov edx, dword [ecx+_7z.StreamsInfo.packOffset] |
mov dword [eax+_7z.StreamsInfo.packOffset], edx |
mov edx, dword [ecx+_7z.StreamsInfo.packOffset+4] |
mov dword [eax+_7z.StreamsInfo.packOffset+4], edx |
mov edi, [ecx+_7z.StreamsInfo.startPackedStream] |
mov ecx, [ecx+_7z.StreamsInfo.numPackedStreams] |
push ecx |
add ecx, edi |
cmp ecx, [ebp+handle_7z.numPackStreams] |
ja return.err |
pop ecx |
shl edi, 3 |
add edi, [ebp+handle_7z.packSizes] |
@@: |
dec ecx |
js @f |
mov edx, [edi] |
add dword [eax+_7z.StreamsInfo.packOffset], edx |
mov edx, [edi+4] |
adc dword [eax+_7z.StreamsInfo.packOffset+4], edx |
add edi, 8 |
jmp @b |
@@: |
.getoffscont: |
inc ebx |
cmp ebx, [ebp+handle_7z.numFolders] |
jb .getoffsloop |
.getoffsdone: |
mov edx, [hOut] |
mov ebx, [edx+handle_7z.NumFiles] |
lea edi, [edx+handle_7z.root.subfolders] |
add edx, handle_7z.basesize |
push file_in_7z.size |
call init_file_links |
mov eax, [hOut] |
and [eax+handle_7z.curdir], 0 ; set root directory |
mov esi, [inStream] |
mov [eax+handle_7z.host], esi |
lea edi, [eax+handle_7z.host_datetime] |
mov esi, [esp+16] |
add esi, 8 |
mov ecx, 6 |
rep movsd |
ret |
|
_7z.CloseHandle: |
mov esi, ecx |
push [esi+handle_7z.host] |
call [close] |
mov ecx, [esi+handle_7z.packSizes] |
call [pgfree] |
mov ecx, [esi+handle_7z.folders] |
call [pgfree] |
mov ecx, [esi+handle_7z.names_buf] |
call [pgfree] |
mov ecx, [esi+handle_7z.last_context] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, esi |
call [pgfree] |
ret |
|
close_7z: |
mov ecx, [esp+4] |
cmp ecx, empty_7z_handle |
jz @f |
call _7z.CloseHandle |
@@: |
ret 4 |
|
uglobal |
align 4 |
_7z.unpacked dd ? |
_7z.unpbuf rd 2*8 |
_7z.CurInStream dd ? |
_7z.dataVector dd ? |
_7z.dataVectorSize dd ? |
_7z.FreeSubStreams dd ? |
_7z.tmpVector dd ? |
_7z.emptyStreams dd ? |
_7z.numEmptyStreams dd ? |
_7z.emptyFiles dd ? |
_7z.antiFiles dd ? |
endg |
|
_7z.ReadAndDecodePackedStreams: |
call _7z.ReadStreamsInfo |
mov ecx, [_7z.StreamsInfo.numFolders] |
test ecx, ecx |
jz .ret2 |
push ecx |
mov ecx, [_7z.StreamsInfo.SubStreamsSizes] |
jecxz @f |
call [pgfree] |
and [_7z.StreamsInfo.SubStreamsSizes], 0 |
@@: |
pop ecx |
mov eax, _7z.unpbuf |
cmp ecx, 8 |
jbe .1 |
shl ecx, 3 |
call [pgalloc] |
test eax, eax |
jz return.clear |
mov esi, eax |
@@: |
and dword [esi], 0 |
add esi, 4 |
sub ecx, 4 |
jnz @b |
.1: |
mov [_7z.unpacked], eax |
mov esi, eax |
xor ecx, ecx |
mov [_7z.CurInStream], ecx |
mov [error_proc], .error |
mov [clear_proc], .clear |
.loop: |
mov eax, [_7z.StreamsInfo.folders] |
mov ebx, [eax+ecx*4] |
call _7z.GetUnPackSize |
test edx, edx |
jnz return.err |
test eax, eax |
js return.err |
push ecx |
mov [esi], eax |
mov [_7z.decode.outBufferSize], eax |
mov ecx, eax |
call [pgalloc] |
test eax, eax |
jz return.err |
mov [esi+4], eax |
mov [_7z.decode.outBufferPtr], eax |
push esi |
call _7z.decode |
pop esi |
pop ecx |
push ecx |
mov eax, [_7z.StreamsInfo.unpackCRCsDefined] |
cmp byte [eax+ecx], 0 |
jz @f |
push esi |
mov ecx, [esi] |
mov esi, [esi+4] |
call crc |
pop esi |
pop ecx |
push ecx |
mov edx, [_7z.StreamsInfo.unpackCRCs] |
cmp [edx+ecx*4], eax |
jnz return.err |
@@: |
add esi, 8 |
pop ecx |
inc ecx |
cmp ecx, [_7z.StreamsInfo.numFolders] |
jb .loop |
.ret: |
mov ecx, [_7z.StreamsInfo.folders] |
call [pgfree] |
mov [error_proc], .error2 |
mov [clear_proc], .clear2 |
.ret2: |
mov ecx, [_7z.StreamsInfo.packSizes] |
call [pgfree] |
ret |
|
.error: |
call .free |
jmp _7z.ReadStreamsInfo.error |
.clear: |
call .free |
jmp _7z.ReadStreamsInfo.clear |
.error2: |
call .free |
jmp open_7z.header_error |
.clear2: |
call .free |
jmp open_7z.clear |
.free: |
mov ebx, [_7z.StreamsInfo.numFolders] |
.free2: |
dec ebx |
js @f |
mov ecx, [_7z.unpacked] |
mov ecx, [ecx+ebx*8+4] |
call [pgfree] |
jmp .free2 |
@@: |
mov ecx, [_7z.unpacked] |
cmp ecx, _7z.unpbuf |
jz @f |
call [pgfree] |
@@: |
ret |
|
_7z.GetUnPackSize: |
xor edx, edx |
mov eax, [ebx+_7z.StreamsInfo.numOutStreams] |
test eax, eax |
jz .ret |
.scan: |
dec eax |
js return.err |
push ecx |
mov ecx, [ebx+_7z.StreamsInfo.numBindPairs] |
mov edx, [ebx+_7z.StreamsInfo.bindPairs] |
@@: |
add edx, 8 |
dec ecx |
js .found |
cmp [edx-4], eax |
jnz @b |
pop ecx |
jmp .scan |
.found: |
mov [ebx+_7z.StreamsInfo.mainOutStream], eax |
mov ecx, [ebx+_7z.StreamsInfo.unpackSizes] |
mov edx, [ecx+eax*8+4] |
mov eax, [ecx+eax*8] |
pop ecx |
.ret: |
ret |
|
uglobal |
align 4 |
_7z.StreamsInfo: |
.numPackStreams dd ? |
.packSizes dd ? ; 8 bytes per item |
.numFolders dd ? |
.unpackCRCsDefined dd ? |
.unpackCRCs dd ? |
.folders dd ? |
.folders.size dd ? |
.folders.alloc dd ? |
.dataOffset dq ? |
.packCRCsDefined dd ? ; 1 byte per item |
.packCRCs dd ? ; 4 bytes per item |
virtual at 0 |
.numCoders dd ? |
.bindPairs dd ? |
.numBindPairs dd ? |
.packedStreams dd ? |
.numPackedStreams dd ? |
.startPackedStream dd ? |
.numOutStreams dd ? |
.unpackSizes dd ? |
.mainOutStream dd ? |
.numUnPackStreams dd ? |
.packOffset dq ? |
.fsz = $ |
end virtual |
.numSubStreams dd ? |
.SubStreamsSizes dd ? |
.SubStreamsCRCsDefined dd ? |
.SubStreamsCRCs dd ? |
.tmpSubStreamsCRCsDefined dd ? |
.tmpSubStreamsCRCs dd ? |
endg |
|
_7z.SkipData: |
call _7z.ReadNumber |
call _7z.SkipSize |
ret |
|
_7z.WaitAttribute: |
call _7z.ReadNumber |
cmp eax, ecx |
jz @f |
test eax, eax |
jz return.err |
call _7z.SkipData |
jmp _7z.WaitAttribute |
@@: |
ret |
|
_7z.ReadBoolVector2: |
; in: ebx->vector, ecx=size |
call _7z.ReadByte |
test al, al |
jz _7z.ReadBoolVector |
push ebx ecx |
jecxz .ret |
@@: |
mov byte [ebx], 1 |
inc ebx |
loop @b |
.ret: |
pop ecx ebx |
ret |
|
_7z.ReadBoolVector: |
push ebx ecx |
jecxz .ret |
xor eax, eax |
.1: |
add al, al |
jnz @f |
call _7z.ReadByte |
stc |
adc al, al |
@@: |
setc byte [ebx] |
inc ebx |
loop .1 |
.ret: |
pop ecx ebx |
ret |
|
_7z.ReadHashDigests: |
; in: ebx->bool vector, esi->crc, ecx=size |
call _7z.ReadBoolVector2 |
jecxz .ret |
.1: |
xor eax, eax |
cmp byte [ebx], al |
jz @f |
call _7z.ReadDword |
@@: |
mov [esi], eax |
add esi, 4 |
inc ebx |
loop .1 |
.ret: |
ret |
|
uglobal |
_7z.saved_edi dd ? |
_7z.saved_edi_end dd ? |
endg |
|
_7z.SwitchStream: |
mov eax, [bufend] |
mov [_7z.saved_edi_end], eax |
call _7z.ReadByte |
test al, al |
jnz @f |
ret |
@@: |
call _7z.ReadNum |
mov [_7z.saved_edi], edi |
cmp eax, [_7z.dataVectorSize] |
jae return.err |
shl eax, 3 |
add eax, [_7z.dataVector] |
mov edi, [eax+4] |
mov eax, [eax] |
add eax, edi |
mov [bufend], eax |
ret |
|
_7z.UnswitchStream: |
mov eax, [_7z.saved_edi_end] |
cmp eax, [bufend] |
jnz @f |
ret |
@@: |
mov [bufend], eax |
mov edi, [_7z.saved_edi] |
@@: |
ret |
|
; 6 ¯à®£à ¬¬¨á⮢ ¯ëâ «¨áì ª®¤ ¯®ïâì, |
; ¤¨ ¨§ ¨å á®èñ« á 㬠, ¨ ¨å ®áâ «®áì 5. |
|
_7z.ReadStreamsInfo: |
xor eax, eax |
mov [_7z.StreamsInfo.numPackStreams], eax |
mov [_7z.StreamsInfo.packSizes], eax |
mov [_7z.StreamsInfo.numFolders], eax |
mov [_7z.StreamsInfo.folders], eax |
mov [_7z.StreamsInfo.numSubStreams], eax |
mov [_7z.StreamsInfo.SubStreamsSizes], eax |
mov [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], eax |
mov [error_proc], .error |
mov [clear_proc], .clear |
.mainloop: |
call _7z.ReadNum |
test eax, eax |
jz @b |
cmp eax, kSubStreamsInfo |
jz .SubStreamsInfo |
cmp eax, kUnPackInfo |
jz .UnpackInfo |
cmp eax, kPackInfo |
jnz return.err |
|
.PackInfo: |
cmp [_7z.StreamsInfo.numPackStreams], 0 |
jnz return.err |
call _7z.ReadNumber |
add eax, 0x20 |
adc edx, 0 |
mov dword [_7z.StreamsInfo.dataOffset], eax |
mov dword [_7z.StreamsInfo.dataOffset+4], edx |
call _7z.ReadNum |
mov [_7z.StreamsInfo.numPackStreams], eax |
mov ecx, kSize |
call _7z.WaitAttribute |
mov ecx, [_7z.StreamsInfo.numPackStreams] |
imul ecx, 8+1+4 |
jecxz .nostreams1 |
call [pgalloc] |
test eax, eax |
jz return.clear |
mov [_7z.StreamsInfo.packSizes], eax |
mov ecx, [_7z.StreamsInfo.numPackStreams] |
push eax |
lea eax, [eax+ecx*8] |
mov [_7z.StreamsInfo.packCRCsDefined], eax |
mov ebx, eax |
add eax, ecx |
mov [_7z.StreamsInfo.packCRCs], eax |
@@: |
mov byte [ebx], 0 |
inc ebx |
loop @b |
pop eax |
.nostreams1: |
mov ecx, [_7z.StreamsInfo.numPackStreams] |
jecxz .noloop1 |
mov esi, eax |
@@: |
call _7z.ReadNumber |
mov [esi], eax |
mov [esi+4], edx |
add esi, 8 |
loop @b |
.noloop1: |
call _7z.ReadNum |
test eax, eax |
jz .mainloop |
cmp eax, kCRC |
jz .packInfo.crc |
call _7z.SkipData |
jmp .noloop1 |
.packInfo.crc: |
mov esi, [_7z.StreamsInfo.packCRCs] |
mov ebx, [_7z.StreamsInfo.packCRCsDefined] |
mov ecx, [_7z.StreamsInfo.numPackStreams] |
call _7z.ReadHashDigests |
jmp .noloop1 |
|
.UnpackInfo: |
cmp [_7z.StreamsInfo.folders], 0 |
jnz return.err |
mov ecx, kFolder |
call _7z.WaitAttribute |
call _7z.ReadNum |
mov ecx, eax |
mov [_7z.StreamsInfo.numFolders], eax |
call _7z.SwitchStream |
test ecx, ecx |
jz .nofolders |
push ecx |
mov ecx, 0x1000 |
and [_7z.StreamsInfo.folders.size], 0 |
mov [_7z.StreamsInfo.folders.alloc], ecx |
call [pgalloc] |
test eax, eax |
jz return.clear |
mov [_7z.StreamsInfo.folders], eax |
pop ecx |
lea ecx, [ecx*9] |
call .folders_alloc |
xor ecx, ecx |
.folderloop: |
mov eax, [_7z.StreamsInfo.folders] |
push [_7z.StreamsInfo.folders.size] |
pop dword [eax+ecx*4] |
push ebp |
mov [_ebp], ebp |
push ecx |
mov ecx, _7z.StreamsInfo.fsz |
call .folders_alloc |
mov ebp, eax |
add ebp, [_7z.StreamsInfo.folders] |
call _7z.ReadNum |
mov [ebp+_7z.StreamsInfo.numCoders], eax |
test eax, eax |
jz return.err |
mov ecx, eax |
push ecx |
shl ecx, 2 |
sub ebp, [_7z.StreamsInfo.folders] |
call .folders_alloc |
add ebp, [_7z.StreamsInfo.folders] |
pop ecx |
add eax, [_7z.StreamsInfo.folders] |
@@: |
and dword [eax], 0 |
add eax, 4 |
loop @b |
push 0 ; numOutStreams |
push 0 ; numInStreams |
; [folders] = array of pointers to coders info |
; Format of coder info: |
; dd NextCoder |
; db MethodID.IDSize |
; times IDSize db MethodID.ID |
; dd NumInStreams |
; dd NumOutStreams |
; dd PropSize |
; times PropSize db Properties |
xor esi, esi |
.coders_loop: |
call _7z.ReadByte |
mov dl, al |
and eax, 0xF |
lea ecx, [eax+17] |
sub ebp, [_7z.StreamsInfo.folders] |
call .folders_alloc |
add ebp, [_7z.StreamsInfo.folders] |
push eax |
mov ecx, [_7z.StreamsInfo.folders] |
lea ebx, [ebp+esi*4+_7z.StreamsInfo.fsz] |
@@: |
cmp dword [ebx], 0 |
jz @f |
mov ebx, [ebx] |
add ebx, ecx |
jmp @b |
@@: |
mov [ebx], eax |
pop ebx |
add ebx, ecx |
and dword [ebx], 0 |
add ebx, 4 |
mov ecx, edx |
and ecx, 0xF |
mov byte [ebx], cl |
inc ebx |
jecxz .2 |
@@: |
call _7z.ReadByte |
mov byte [ebx], al |
inc ebx |
loop @b |
.2: |
test dl, 10h |
jnz .coder_multiple_streams |
mov dword [ebx], 1 |
mov dword [ebx+4], 1 |
inc dword [esp] |
inc dword [esp+4] |
jmp @f |
.coder_multiple_streams: |
call _7z.ReadNum |
mov [ebx], eax |
add dword [esp], eax |
call _7z.ReadNum |
mov [ebx+4], eax |
add dword [esp+4], eax |
; all currently defined 7z coders have 1 unpacked stream |
; moreover, all reasonable coders have 1 unpacked stream |
; so assume 1 output stream for unpacker - this simplifies decoding procedure |
cmp eax, 1 |
jnz return.err |
@@: |
and dword [ebx+8], 0 |
add ebx, 12 |
test dl, 20h |
jz .coder_no_properties |
call _7z.ReadNum |
test eax, eax |
jz .coder_no_properties |
mov [ebx-4], eax |
mov ecx, eax |
sub ebx, [_7z.StreamsInfo.folders] |
sub ebp, [_7z.StreamsInfo.folders] |
call .folders_alloc |
add ebp, [_7z.StreamsInfo.folders] |
add ebx, [_7z.StreamsInfo.folders] |
@@: |
call _7z.ReadByte |
mov [ebx], al |
inc ebx |
loop @b |
.coder_no_properties: |
test dl, dl |
js .coders_loop |
inc esi |
cmp esi, [ebp+_7z.StreamsInfo.numCoders] |
jb .coders_loop |
mov [ebp+_7z.StreamsInfo.numUnPackStreams], 1 |
mov eax, [esp+4] |
dec eax |
js return.err |
mov [ebp+_7z.StreamsInfo.numBindPairs], eax |
push eax |
mov ecx, eax |
shl ecx, 3 |
sub ebp, [_7z.StreamsInfo.folders] |
call .folders_alloc |
add ebp, [_7z.StreamsInfo.folders] |
mov [ebp+_7z.StreamsInfo.bindPairs], eax |
pop ecx |
jecxz .noloop3 |
mov esi, eax |
add esi, [_7z.StreamsInfo.folders] |
@@: |
call _7z.ReadNum |
mov [esi], eax |
cmp eax, [esp] |
jae return.err |
call _7z.ReadNum |
mov [esi+4], eax |
cmp eax, [esp+4] |
jae return.err |
add esi, 8 |
loop @b |
.noloop3: |
pop eax ; numInStreams |
pop edx ; numOutStreams |
mov [ebp+_7z.StreamsInfo.numOutStreams], edx |
sub eax, edx |
js return.err |
inc eax |
mov [ebp+_7z.StreamsInfo.numPackedStreams], eax |
mov ecx, eax |
push eax |
shl ecx, 2 |
sub ebp, [_7z.StreamsInfo.folders] |
call .folders_alloc |
add ebp, [_7z.StreamsInfo.folders] |
mov [ebp+_7z.StreamsInfo.packedStreams], eax |
pop ecx |
mov esi, eax |
add esi, [_7z.StreamsInfo.folders] |
cmp ecx, 1 |
jnz .multiplePackedStreams |
mov ebx, [ebp+_7z.StreamsInfo.bindPairs] |
add ebx, [_7z.StreamsInfo.folders] |
push edx |
xor ecx, ecx |
.3: |
push ebx |
mov edx, [ebp+_7z.StreamsInfo.numBindPairs] |
@@: |
dec edx |
js .5 |
cmp dword [ebx], ecx |
jz .4 |
add ebx, 8 |
jmp @b |
.4: |
pop ebx |
inc ecx |
jmp .3 |
.5: |
pop ebx |
pop edx |
mov [esi], ecx |
jmp .commonPackedStreams |
.multiplePackedStreams: |
call _7z.ReadNum |
mov [esi], eax |
add esi, 4 |
loop .multiplePackedStreams |
.commonPackedStreams: |
mov ecx, edx |
shl ecx, 3 |
sub ebp, [_7z.StreamsInfo.folders] |
call .folders_alloc |
add ebp, [_7z.StreamsInfo.folders] |
mov [ebp+_7z.StreamsInfo.unpackSizes], eax |
pop ecx |
xor edx, edx |
jecxz @f |
mov eax, [_7z.StreamsInfo.folders] |
mov eax, [eax+(ecx-1)*4] |
add eax, [_7z.StreamsInfo.folders] |
mov edx, [eax+_7z.StreamsInfo.numPackedStreams] |
add edx, [eax+_7z.StreamsInfo.startPackedStream] |
@@: |
mov [ebp+_7z.StreamsInfo.startPackedStream], edx |
pop ebp |
inc ecx |
cmp ecx, [_7z.StreamsInfo.numFolders] |
jb .folderloop |
.nofolders: |
call _7z.UnswitchStream |
mov ecx, kCodersUnPackSize |
call _7z.WaitAttribute |
xor ecx, ecx |
.6: |
cmp ecx, [_7z.StreamsInfo.numFolders] |
jae .7 |
mov eax, [_7z.StreamsInfo.folders] |
push ebp |
mov ebp, [eax+ecx*4] |
add ebp, eax |
mov esi, [ebp+_7z.StreamsInfo.numOutStreams] |
mov ebp, [ebp+_7z.StreamsInfo.unpackSizes] |
add ebp, [_7z.StreamsInfo.folders] |
@@: |
call _7z.ReadNumber |
mov dword [ebp], eax |
mov dword [ebp+4], edx |
add ebp, 8 |
dec esi |
jnz @b |
pop ebp |
inc ecx |
jmp .6 |
.7: |
; convert all relative addresses to pointers |
xor ecx, ecx |
mov edx, [_7z.StreamsInfo.folders] |
.8: |
cmp ecx, [_7z.StreamsInfo.numFolders] |
jae .9 |
lea eax, [edx+ecx*4] |
add [eax], edx |
mov eax, [eax] |
add [eax+_7z.StreamsInfo.bindPairs], edx |
add [eax+_7z.StreamsInfo.packedStreams], edx |
add [eax+_7z.StreamsInfo.unpackSizes], edx |
mov ebx, [eax+_7z.StreamsInfo.numCoders] |
add eax, _7z.StreamsInfo.fsz |
inc ecx |
.11: |
dec ebx |
js .8 |
push eax |
@@: |
cmp dword [eax], 0 |
jz @f |
add [eax], edx |
mov eax, [eax] |
jmp @b |
@@: |
pop eax |
add eax, 4 |
jmp .11 |
.9: |
; done |
mov eax, [_7z.StreamsInfo.numFolders] |
lea edx, [edx+eax*4] |
mov [_7z.StreamsInfo.unpackCRCsDefined], edx |
add edx, eax |
mov [_7z.StreamsInfo.unpackCRCs], edx |
@@: |
call _7z.ReadNum |
test eax, eax |
jz .mainloop |
cmp eax, kCRC |
jz .unpackInfo.crc |
call _7z.SkipData |
jmp @b |
.unpackInfo.crc: |
mov esi, [_7z.StreamsInfo.unpackCRCs] |
mov ebx, [_7z.StreamsInfo.unpackCRCsDefined] |
mov ecx, [_7z.StreamsInfo.numFolders] |
call _7z.ReadHashDigests |
jmp @b |
|
.SubStreamsInfo: |
cmp [_7z.StreamsInfo.numFolders], 0 |
jz return.err |
cmp [_7z.StreamsInfo.numSubStreams], 0 |
jnz return.err |
mov ebx, [_7z.StreamsInfo.folders] |
.ssloop1: |
call _7z.ReadNum |
cmp eax, kNumUnPackStream |
jz .NumUnPackStream |
cmp eax, kCRC |
jz .break1 |
cmp eax, kSize |
jz .break1 |
test eax, eax |
jz .break1 |
call _7z.SkipData |
jmp .ssloop1 |
.NumUnPackStream: |
xor ecx, ecx |
@@: |
call _7z.ReadNum |
mov edx, [ebx+ecx*4] |
mov [edx+_7z.StreamsInfo.numUnPackStreams], eax |
inc ecx |
cmp ecx, [_7z.StreamsInfo.numFolders] |
jb @b |
jmp .ssloop1 |
.break1: |
; calculate number of substreams and number of defined digests |
xor ecx, ecx |
xor ebp, ebp |
push 0 |
push eax |
xor eax, eax |
.ssloop2: |
mov edx, [ebx+ecx*4] |
mov edx, [edx+_7z.StreamsInfo.numUnPackStreams] |
cmp edx, 1 |
jz @f |
inc ebp |
@@: |
add eax, edx |
jc return.err |
cmp edx, 1 |
jnz @f |
push eax |
mov eax, [_7z.StreamsInfo.unpackCRCsDefined] |
cmp byte [eax+ecx], 0 |
pop eax |
jz @f |
xor edx, edx |
@@: |
add [esp+4], edx |
inc ecx |
cmp ecx, [_7z.StreamsInfo.numFolders] |
jb .ssloop2 |
mov [_7z.StreamsInfo.numSubStreams], eax |
imul ecx, eax, 4+8+1 |
jecxz .noss1 |
push eax |
call [pgalloc] |
pop ecx |
test eax, eax |
jz return.clear |
mov [_7z.StreamsInfo.SubStreamsSizes], eax |
lea eax, [eax+ecx*8] |
mov [_7z.StreamsInfo.SubStreamsCRCsDefined], eax |
add eax, ecx |
mov [_7z.StreamsInfo.SubStreamsCRCs], eax |
@@: |
dec eax |
mov byte [eax], 0 |
loop @b |
.noss1: |
mov ecx, [esp+4] |
jecxz @f |
imul ecx, 4+1 |
call [pgalloc] |
test eax, eax |
jz return.clear |
mov [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], eax |
add eax, [esp+4] |
mov [_7z.StreamsInfo.tmpSubStreamsCRCs], eax |
@@: |
test ebp, ebp |
jz @f |
cmp dword [esp], kSize |
jnz return.err |
@@: |
xor ecx, ecx |
mov ebp, [_7z.StreamsInfo.SubStreamsSizes] |
.ssloop3: |
mov ebx, [_7z.StreamsInfo.folders] |
mov ebx, [ebx+ecx*4] |
mov eax, [ebx+_7z.StreamsInfo.numUnPackStreams] |
dec eax |
js .sscont3 |
push 0 |
push 0 |
@@: |
dec eax |
js @f |
push eax |
call _7z.ReadNumber |
mov [ebp], eax |
mov [ebp+4], edx |
add ebp, 8 |
add [esp+4], eax |
adc [esp+8], edx |
jc return.err |
pop eax |
jmp @b |
@@: |
call _7z.GetUnPackSize |
sub eax, [esp] |
sbb edx, [esp+4] |
jc return.err |
mov [ebp], eax |
mov [ebp+4], edx |
add ebp, 8 |
add esp, 8 |
.sscont3: |
inc ecx |
cmp ecx, [_7z.StreamsInfo.numFolders] |
jb .ssloop3 |
pop eax |
cmp eax, kSize |
jnz @f |
call _7z.ReadNum |
@@: |
cmp eax, kCRC |
jz .sscrc |
test eax, eax |
jz .ssend |
call _7z.SkipData |
.ssloop4: |
call _7z.ReadNum |
jmp @b |
.sscrc: |
pop ecx |
push ecx |
mov ebx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined] |
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCs] |
call _7z.ReadHashDigests |
xor ecx, ecx ; index in out |
xor edx, edx ; index in tmp |
push -1 |
pop ebx ; index in folders |
.ssloop5: |
inc ebx |
cmp ebx, [_7z.StreamsInfo.numFolders] |
jae .ssloop4 |
mov eax, [_7z.StreamsInfo.folders] |
mov ebp, [eax+ebx*4] |
mov ebp, [ebp+_7z.StreamsInfo.numUnPackStreams] |
cmp ebp, 1 |
jnz @f |
mov eax, [_7z.StreamsInfo.unpackCRCsDefined] |
cmp byte [eax+ebx], 0 |
jz @f |
mov esi, [_7z.StreamsInfo.SubStreamsCRCsDefined] |
mov byte [esi+ecx], 1 |
mov esi, [_7z.StreamsInfo.unpackCRCs] |
mov eax, [esi+ebx*4] |
mov esi, [_7z.StreamsInfo.SubStreamsCRCs] |
mov [esi+ecx*4], eax |
inc ecx |
jmp .ssloop5 |
@@: |
dec ebp |
js .ssloop5 |
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined] |
mov al, [esi+edx] |
mov esi, [_7z.StreamsInfo.SubStreamsCRCsDefined] |
mov [esi+ecx], al |
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCs] |
mov eax, [esi+edx*4] |
mov esi, [_7z.StreamsInfo.SubStreamsCRCs] |
mov [esi+ecx*4], eax |
inc edx |
inc ecx |
jmp @b |
.ssend: |
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined] |
call [pgfree] |
and [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], 0 |
pop ecx |
jmp .mainloop |
|
.folders_alloc: |
push ecx |
add ecx, [_7z.StreamsInfo.folders.size] |
sub ecx, [_7z.StreamsInfo.folders.alloc] |
jbe @f |
push edx |
or ecx, 0xFFF |
inc ecx |
add ecx, [_7z.StreamsInfo.folders.alloc] |
mov [_7z.StreamsInfo.folders.alloc], ecx |
mov edx, [_7z.StreamsInfo.folders] |
call [pgrealloc] |
pop edx |
test eax, eax |
jz return.clear |
mov [_7z.StreamsInfo.folders], eax |
@@: |
pop ecx |
mov eax, [_7z.StreamsInfo.folders.size] |
add [_7z.StreamsInfo.folders.size], ecx |
ret |
|
.error: |
mov ecx, [_7z.StreamsInfo.packSizes] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [_7z.StreamsInfo.folders] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [_7z.StreamsInfo.SubStreamsSizes] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined] |
jecxz @f |
call [pgfree] |
@@: |
jmp open_7z.header_error |
.clear: |
mov ecx, [_7z.StreamsInfo.packSizes] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [_7z.StreamsInfo.folders] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [_7z.StreamsInfo.SubStreamsSizes] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined] |
jecxz @f |
call [pgfree] |
@@: |
jmp open_7z.clear |
|
uglobal |
align 4 |
_7z.decode.mainbuf dd ? |
_7z.decode.pStreams dd ? |
_7z.decode.pStreams_def rd 8 |
_7z.decode.outBufferSize dd ? |
_7z.decode.outBufferPtr dd ? |
_7z.decode.outBufferRead dd ? |
endg |
|
virtual at 0 |
streamInfo: |
.fullSize dq ? |
.fillBuf dd ? ; procedure which fills the buffer |
.bufSize dd ? |
.bufDataLen dd ? |
.bufPtr dd ? |
.size = $ |
end virtual |
|
_7z.decode: |
; in: ebx->folder, outBufferSize, outBufferPtr |
; N.B. We assume that every coder has 1 output (unpacked) stream. |
and [.mainbuf], 0 |
mov [.pStreams], .pStreams_def |
mov [error_proc], .error |
mov [clear_proc], .clear |
call .init |
and [.outBufferRead], 0 |
@@: |
push edi |
mov eax, [ebx+_7z.StreamsInfo.mainOutStream] |
mov esi, [.pStreams] |
mov eax, [esi+eax*4] |
call fillBuf |
mov ecx, [eax+streamInfo.bufSize] |
mov esi, [eax+streamInfo.bufPtr] |
mov edi, [.outBufferPtr] |
add edi, [.outBufferRead] |
add [.outBufferRead], ecx |
mov edx, ecx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
pop edi |
mov eax, [.outBufferRead] |
cmp eax, [.outBufferSize] |
jb @b |
mov ecx, [.pStreams] |
cmp ecx, .pStreams_def |
jz @f |
call [pgfree] |
@@: |
mov ecx, [.mainbuf] |
jecxz @f |
call [pgfree] |
@@: |
mov [error_proc], _7z.ReadAndDecodePackedStreams.error |
mov [clear_proc], _7z.ReadAndDecodePackedStreams.clear |
ret |
|
.error: |
mov ecx, [.pStreams] |
cmp ecx, .pStreams_def |
jz @f |
call [pgfree] |
@@: |
mov ecx, [.mainbuf] |
jecxz @f |
call [pgfree] |
@@: |
jmp _7z.ReadAndDecodePackedStreams.error |
.clear: |
mov ecx, [.pStreams] |
cmp ecx, .pStreams_def |
jz @f |
call [pgfree] |
@@: |
mov ecx, [.mainbuf] |
jecxz @f |
call [pgfree] |
@@: |
jmp _7z.ReadAndDecodePackedStreams.clear |
|
.init: |
; We use stack to keep some information on streams, |
; to avoid stack overflow we limit possible number of coders. |
; Anyway, in real life maximum number of coders is 5 |
; (password protection filter + BCJ2 filter + 3 LZMA coders), |
; from command line user can define more coders, but |
; archive with, say, 32 coders is most likely bogus. |
cmp [ebx+_7z.StreamsInfo.numCoders], 128 |
ja return.err |
; allocate space for streams info array |
mov eax, .pStreams_def |
mov ecx, [ebx+_7z.StreamsInfo.numPackedStreams] |
add ecx, [ebx+_7z.StreamsInfo.numCoders] |
cmp ecx, 8 |
jbe @f |
shl ecx, 2 |
call [pgalloc] |
test eax, eax |
jz return.clear |
@@: |
mov [.pStreams], eax |
; calculate size of buffers required for decoders |
xor ecx, ecx |
push ecx |
mov ebp, [ebx+_7z.StreamsInfo.unpackSizes] |
.calcbufsz: |
; LZMA decoder: method ID = [size=03] 03 01 01, NumInStreams = NumOutStreams = 1 |
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4] |
call _7z.GetCoder |
jnc .known_id |
.unknown_method_id: |
movzx esi, byte [eax+4] |
lea ecx, [eax+5] |
mov ebx, aUnknownMethod.z |
@@: |
dec esi |
js @f |
mov byte [ebx], ' ' |
inc ebx |
mov al, [ecx] |
push eax |
shr al, 4 |
cmp al, 10 |
sbb al, 69h |
das |
mov [ebx], al |
inc ebx |
pop eax |
and al, 0xF |
cmp al, 10 |
sbb al, 69h |
das |
mov [ebx], al |
inc ebx |
inc ecx |
jmp @b |
@@: |
mov byte [ebx], 0 |
push ContinueBtn |
push 1 |
push aUnknownMethod_ptr |
push 1 |
call [SayErr] |
jmp return.clear |
iglobal |
if lang eq ru |
aUnknownMethod db '¥¨§¢¥áâë© ¬¥â®¤:' |
else |
aUnknownMethod db 'Unknown method:' |
end if |
.z: |
times 16*3+1 db 0 |
aUnknownMethod_ptr dd aUnknownMethod |
endg |
.known_id: |
movzx esi, byte [eax+4] |
lea esi, [esi+eax+17] |
call [_7z.GetBufSizeTable+edx*4] |
add eax, 3 |
and al, not 3 |
add [esp], eax |
jc .nomem |
cmp dword [ebp+4], 0 |
jnz @f |
cmp dword [ebp], edx |
jae @f |
mov edx, [ebp] |
@@: |
add edx, 0xF |
and edx, not 0xF |
add [esp], edx |
jc .nomem |
add ebp, 8 |
inc ecx |
cmp ecx, [ebx+_7z.StreamsInfo.numCoders] |
jb .calcbufsz |
; add 4 pages for each of not binded input streams |
mov ecx, [ebx+_7z.StreamsInfo.numPackedStreams] |
shl ecx, 14 |
add [esp], ecx |
;; calculate free RAM |
; call [getfreemem] |
; sub eax, 64 ; keep at least 64 Kb of free RAM |
; jbe .nomem |
; pop ecx |
; push ecx |
; add ecx, 0x3FF |
; shr ecx, 10 |
; cmp eax, ecx |
; jae .memok |
jmp .memok |
.nomem: |
push ContinueBtn |
push 1 |
push aNoFreeRam_ptr |
push 1 |
call [SayErr] |
jmp return.clear |
.memok: |
; allocate streamInfos |
pop ecx |
call [pgalloc] |
test eax, eax |
jz return.clear |
mov [.mainbuf], eax |
; initialize streamInfos for decoders |
xor ecx, ecx |
mov ebp, [ebx+_7z.StreamsInfo.unpackSizes] |
mov edx, [.pStreams] |
.init1: |
mov [edx], eax |
add edx, 4 |
push edx |
push dword [ebp] |
pop dword [eax] |
push dword [ebp+4] |
pop dword [eax+4] |
and dword [eax+streamInfo.size], 0 |
push eax |
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4] |
call _7z.GetCoder |
movzx esi, byte [eax+4] |
lea esi, [esi+eax+17] |
call [_7z.GetBufSizeTable+edx*4] |
pop esi |
push esi |
add eax, 3 |
and al, not 3 |
add [esp], eax |
pop [esi+streamInfo.bufPtr] |
push [esi+streamInfo.bufPtr] |
cmp dword [ebp+4], 0 |
jnz @f |
cmp dword [ebp], edx |
jae @f |
mov edx, [ebp] |
@@: |
add edx, 0xF |
and edx, not 0xF |
mov [esi+streamInfo.bufSize], edx |
and [esi+streamInfo.bufDataLen], 0 |
pop eax |
add eax, edx |
pop edx |
add ebp, 8 |
inc ecx |
cmp ecx, [ebx+_7z.StreamsInfo.numCoders] |
jb .init1 |
; initialize streamInfos for input streams |
xor ecx, ecx |
@@: |
mov [edx], eax |
add edx, 4 |
mov esi, [_7z.CurInStream] |
inc [_7z.CurInStream] |
shl esi, 3 |
add esi, [_7z.StreamsInfo.packSizes] |
push dword [esi] |
pop dword [eax] |
push dword [esi+4] |
pop dword [eax+4] |
mov [eax+streamInfo.fillBuf], fillBufFromInStream |
lea esi, [eax+streamInfo.size+8] |
mov [eax+streamInfo.bufPtr], esi |
mov [eax+streamInfo.bufSize], 0x4000 - streamInfo.size - 8 |
and [eax+streamInfo.bufDataLen], 0 |
mov esi, dword [_7z.StreamsInfo.dataOffset] |
mov dword [eax+streamInfo.size], esi |
mov esi, dword [_7z.StreamsInfo.dataOffset+4] |
mov dword [eax+streamInfo.size+4], esi |
mov esi, [eax] |
add dword [_7z.StreamsInfo.dataOffset], esi |
mov esi, [eax+4] |
adc dword [_7z.StreamsInfo.dataOffset+4], esi |
add eax, 0x4000 |
inc ecx |
cmp ecx, [ebx+_7z.StreamsInfo.numPackedStreams] |
jb @b |
; initialize links between streams |
push -1 |
mov edx, [ebx+_7z.StreamsInfo.mainOutStream] |
xor ecx, ecx |
.init_links: |
mov eax, [ebx+_7z.StreamsInfo.fsz+edx*4] |
movzx esi, byte [eax+4] |
cmp ecx, [eax+esi+5] |
jb @f |
pop ecx |
cmp ecx, -1 |
jz .inited_links |
pop edx |
jmp .init_links |
@@: |
push edx |
push ecx |
@@: |
dec edx |
js @f |
mov eax, [ebx+_7z.StreamsInfo.fsz+edx*4] |
movzx esi, byte [eax+4] |
add ecx, [eax+esi+5] |
jmp @b |
@@: |
mov esi, [ebx+_7z.StreamsInfo.bindPairs] |
mov edx, [ebx+_7z.StreamsInfo.numBindPairs] |
@@: |
add esi, 8 |
dec edx |
js .link_to_in |
cmp ecx, [esi-8] |
jnz @b |
pop ecx |
pop edx |
mov eax, [.pStreams] |
mov eax, [eax+edx*4] |
lea eax, [eax+streamInfo.size+ecx*4] |
push edx |
inc ecx |
push ecx |
mov edx, [esi-4] |
mov ecx, [.pStreams] |
mov ecx, [ecx+edx*4] |
mov [eax], ecx |
cmp dword [ecx+streamInfo.size], 0 |
jnz return.err |
xor ecx, ecx |
jmp .init_links |
.link_to_in: |
mov esi, [ebx+_7z.StreamsInfo.packedStreams] |
mov edx, [ebx+_7z.StreamsInfo.numPackedStreams] |
@@: |
dec edx |
js return.err |
cmp ecx, [esi+edx*4] |
jnz @b |
add edx, [ebx+_7z.StreamsInfo.numCoders] |
mov esi, [.pStreams] |
mov eax, [esi+edx*4] |
pop ecx |
pop edx |
mov esi, [esi+edx*4] |
mov [esi+streamInfo.size+ecx*4], eax |
inc ecx |
jmp .init_links |
.inited_links: |
; initialize all decoders |
; bool zzz_init_decoder(stream_info* ebp, esi->params, [esi-4]=params_size); |
xor ecx, ecx |
.init_decoders: |
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4] |
call _7z.GetCoder |
movzx esi, byte [eax+4] |
mov ebp, [.pStreams] |
mov ebp, [ebp+ecx*4] |
cmp dword [esi+eax], 0 |
jz @f |
cmp dword [ebp+streamInfo.size], 0 |
jz return.err |
@@: |
lea esi, [esi+eax+17] |
push ebx ecx edi |
xor ebx, ebx |
call [_7z.InitTable+edx*4] |
pop edi ecx ebx |
inc ecx |
cmp ecx, [ebx+_7z.StreamsInfo.numCoders] |
jb .init_decoders |
ret |
|
fillBuf: |
and [eax+streamInfo.bufDataLen], 0 |
fillBufNozero: |
pushad |
mov edx, [eax+streamInfo.bufSize] |
sub edx, [eax+streamInfo.bufDataLen] |
cmp dword [eax+streamInfo.fullSize+4], 0 |
jnz .full |
mov ecx, dword [eax+streamInfo.fullSize] |
cmp ecx, edx |
jbe @f |
.full: |
mov ecx, edx |
@@: |
sub dword [eax+streamInfo.fullSize], ecx |
sbb dword [eax+streamInfo.fullSize+4], 0 |
mov edi, [eax+streamInfo.bufPtr] |
add edi, [eax+streamInfo.bufDataLen] |
add [eax+streamInfo.bufDataLen], ecx |
jmp [eax+streamInfo.fillBuf] |
|
fillBufFromInStream: |
push eax |
push dword [eax+streamInfo.size+4] |
push dword [eax+streamInfo.size] |
push 0 |
push [inStream] |
call [seek] |
pop eax |
push eax |
push ecx |
push edi |
push [inStream] |
call [read] |
cmp eax, ecx |
pop eax |
jnz .error |
add dword [eax+streamInfo.size], ecx |
adc dword [eax+streamInfo.size+4], 0 |
popad |
ret |
.error: |
push ContinueBtn |
push 1 |
push aReadError_ptr |
push 1 |
call [SayErr] |
jmp return.clear |
|
_7z.GetCoder: |
; in: eax->coder |
; out: edx = coder type |
xor edx, edx |
; Copy decoder: method ID = [size=01] 00, NumInStreams = NumOutStreams = 1 |
cmp word [eax+4], 0x0001 |
jnz @f |
cmp dword [eax+6], 1 |
jz .ret |
@@: |
inc edx |
; LZMA decoder: method ID = [size=03] 03 01 01, NumInStreams = NumOutStreams = 1 |
cmp dword [eax+4], 0x01010303 |
jnz @f |
cmp dword [eax+8], 1 |
jz .ret |
@@: |
inc edx |
; PPMD decoder: method ID = [size=03] 03 04 01, NumInStreams = NumOutStreams = 1 |
cmp dword [eax+4], 0x01040303 |
jnz @f |
cmp dword [eax+8], 1 |
jz .ret |
@@: |
inc edx |
; BCJ filter: method ID = [size=04] 03 03 01 03, NumInStreams = NumOutStreams = 1 |
cmp byte [eax+4], 4 |
jnz @f |
cmp dword [eax+5], 0x03010303 |
jnz @f |
cmp dword [eax+9], 1 |
jz .ret |
@@: |
inc edx |
; BCJ2 filter: method ID = [size=04] 03 03 01 1B, NumInStreams = 4, NumOutStreams = 1 |
cmp byte [eax+4], 4 |
jnz @f |
cmp dword [eax+5], 0x1B010303 |
jnz @f |
cmp dword [eax+9], 4 |
jz .ret |
@@: |
inc edx |
; 7z-AES cryptor: method ID = [size=04] 06 F1 07 01, NumInStreams = NumOutStreams = 1 |
cmp byte [eax+4], 4 |
jnz @f |
cmp dword [eax+5], 0x0107F106 |
jnz @f |
cmp dword [eax+9], 1 |
jz .ret |
@@: |
stc |
.ret: |
ret |
|
iglobal |
align 4 |
label _7z.GetBufSizeTable dword |
dd copy_get_buf_size |
dd lzma_get_buf_size |
dd ppmd_get_buf_size |
dd bcj_get_buf_size |
dd bcj2_get_buf_size |
dd aes7z_get_buf_size |
label _7z.InitTable dword |
dd copy_init_decoder |
dd lzma_init_decoder |
dd ppmd_init_decoder |
dd bcj_init_decoder |
dd bcj2_init_decoder |
dd aes7z_init_decoder |
endg |
|
copy_get_buf_size: |
mov eax, streamInfo.size+8 |
mov edx, 0x10000 |
ret |
|
copy_init_decoder: |
mov [ebp+streamInfo.fillBuf], copy_fillBuf |
and dword [ebp+streamInfo.size+4], 0 |
ret |
|
copy_fillBuf: |
push eax |
mov esi, [eax+streamInfo.size+4] |
mov eax, [eax+streamInfo.size] |
.redo: |
push ecx |
mov edx, [eax+streamInfo.bufDataLen] |
sub edx, esi |
cmp ecx, edx |
jb @f |
mov ecx, edx |
@@: |
sub [esp], ecx |
add esi, [eax+streamInfo.bufPtr] |
mov edx, ecx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
pop ecx |
jecxz .done |
cmp dword [eax+streamInfo.fullSize+4], 0 |
jnz @f |
cmp dword [eax+streamInfo.fullSize], ecx |
jb return.err |
@@: |
call fillBuf |
xor esi, esi |
jmp .redo |
.done: |
sub esi, [eax+streamInfo.bufPtr] |
pop eax |
mov [eax+streamInfo.size+4], esi |
popad |
ret |
|
; int __stdcall ReadFolder([esp+4] = HANDLE hPlugin, |
; [esp+8] = unsigned dirinfo_start, [esp+12] = unsigned dirinfo_size, |
; [esp+16] = void* dirdata); |
ReadFolder_7z: |
; init header |
mov edi, [esp+16] |
mov ecx, 32/4 |
xor eax, eax |
rep stosd |
mov byte [edi-32], 1 ; version |
mov ebp, [esp+4] |
; get current directory |
lea ebx, [ebp+handle_7z.root.subfolders] |
cmp [ebp+handle_7z.curdir], 0 |
jz @f |
mov ebx, [ebp+handle_7z.curdir] |
add ebx, file_in_7z.subfolders |
@@: |
mov ecx, [ebx+16] |
mov [edi-24], ecx ; number of files |
; edi points to BDFE |
push 6 ; assume EOF |
pop eax |
sub ecx, [esp+8] |
ja @f |
and dword [edi-28], 0 ; number of files read |
ret 10h |
@@: |
cmp ecx, [esp+12] |
jb @f |
mov ecx, [esp+12] |
xor eax, eax ; OK |
@@: |
mov [edi-28], ecx |
push eax |
; copy files data |
test ecx, ecx |
jz .done |
; seek to required item |
mov eax, [esp+8+4] |
mov esi, [ebx] |
.0: |
test esi, esi |
jnz .1 |
mov esi, [ebx+8] |
.1: |
add esi, ebp |
dec eax |
js .2 |
mov esi, [esi+file_in_7z.next] |
jmp .0 |
.2: |
.copy: |
cmp [esi+file_in_7z.bPseudoFolder], 0 |
jnz .pseudo |
xor eax, eax |
cmp [esi+file_in_7z.bAttrDefined], 0 |
jz @f |
mov eax, [esi+file_in_7z.attr] |
@@: |
stosd |
xor eax, eax |
stosd |
push esi ecx |
add esi, file_in_7z.CreationTime |
mov ecx, 8 |
rep movsd |
pop ecx esi |
mov edx, [esi+file_in_7z.name] |
push edi |
@@: |
mov al, [edx] |
inc edx |
stosb |
test al, al |
jnz @b |
pop edi |
.cont: |
add edi, 264 |
mov esi, [esi+file_in_7z.next] |
test esi, esi |
jnz @f |
mov esi, [ebx+8] |
@@: |
add esi, ebp |
loop .copy |
jmp .done |
.pseudo: |
push 0x10 ; attributes: folder |
pop eax |
stosd |
xor eax, eax |
stosd |
push ecx esi |
lea esi, [ebp+handle_7z.host_datetime] |
mov ecx, 6 |
rep movsd |
pop esi |
stosd |
stosd |
push edi esi |
mov ecx, [esi+file_in_7z.namelen] |
mov esi, [esi+file_in_7z.name] |
rep movsb |
mov byte [edi], 0 |
pop esi edi ecx |
jmp .cont |
.done: |
pop eax |
ret 10h |
|
; bool __stdcall SetFolder([esp+4] = HANDLE hPlugin, |
; [esp+8] = const char* relative_path, [esp+12] = const char* absolute_path); |
SetFolder_7z: |
mov ebp, [esp+4] |
mov edx, [ebp+handle_7z.curdir] |
mov esi, [esp+8] |
cmp dword [esi], '..' |
jz .toparent |
xor ecx, ecx |
@@: |
inc ecx |
cmp byte [esi+ecx], 0 |
jnz @b |
mov ebx, [ebp+handle_7z.root.subfolders] |
test edx, edx |
jz .scan |
mov ebx, [edx+file_in_7z.subfolders] |
.scan: |
test ebx, ebx |
jz .err |
add ebx, ebp |
cmp [ebx+file_in_7z.namelen], ecx |
jnz .cont |
push ecx esi |
mov edi, [ebx+file_in_7z.name] |
repz cmpsb |
pop esi ecx |
jz .set |
.cont: |
mov ebx, [ebx+file_in_7z.next] |
jmp .scan |
.toparent: |
test edx, edx |
jz .err |
mov ebx, [edx+file_in_7z.parent] |
test ebx, ebx |
jz @f |
add ebx, ebp |
@@: |
.set: |
mov [ebp+handle_7z.curdir], ebx |
mov al, 1 |
ret 12 |
.err: |
xor eax, eax |
ret 12 |
|
; ebp=hPlugin, eax->item, edi->info |
getattr_7z: |
cmp [eax+file_in_7z.bPseudoFolder], 0 |
jnz .pseudo |
lea esi, [eax+file_in_7z.attr] |
movsd |
xor eax, eax |
stosd |
add esi, -(file_in_7z.attr+4) + file_in_7z.CreationTime |
mov ecx, 8 |
rep movsd |
ret |
.pseudo: |
mov esi, [eax+file_in_7z.name] |
mov ecx, [eax+file_in_7z.namelen] |
push 0x10 ; attributes: folder |
pop eax |
stosd |
xor eax, eax |
stosd |
push ecx esi |
lea esi, [ebp+handle_7z.host_datetime] |
push 6 |
pop ecx |
rep movsd |
pop esi ecx |
stosd |
stosd |
rep movsb |
mov byte [edi], 0 |
ret |
|
virtual at 0 |
file_handle_7z: |
.type dd ? |
.context dd ? |
.pos dq ? |
.base dd ? ; handle of archive |
.item dd ? ; pointer to file_in_7z |
.mainStream dd ? ; (pointer in context) |
.bError db ? |
rb 3 |
.size = $ |
end virtual |
|
iglobal |
align 4 |
handle_table_7z dd handle_table_7z,handle_table_7z |
endg |
|
; ebp=hPlugin, eax->item, edi=mode |
open_file_7z: |
cmp [eax+file_in_7z.bHasStream], 0 |
jnz @f |
mov eax, empty_7z_handle |
ret |
@@: |
mov ecx, [ebp+handle_7z.password_len] |
inc ecx |
setnz [bPasswordDefined] |
jz @f |
dec ecx |
lea esi, [ebp+handle_7z.password] |
push edi |
mov edi, password_unicode |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
pop edi |
@@: |
mov [hOut], ecx |
mov [_7z.decode.mainbuf], ecx |
mov ecx, [ebp+handle_7z.host] |
mov [inStream], ecx |
mov [_7z.decode.pStreams], _7z.decode.pStreams_def |
push eax |
mov [_esp], esp |
mov [_ebp], ebp |
mov [error_proc], .error |
mov [clear_proc], .clear |
mov ebx, [ebp+handle_7z.folders] |
mov ecx, [eax+file_in_7z.folder] |
cmp [ebp+handle_7z.last_folder], ecx |
jnz .nolast |
mov edx, dword [eax+file_in_7z.folderStart] |
sub edx, dword [ebp+handle_7z.last_pos] |
mov esi, dword [eax+file_in_7z.folderStart+4] |
sbb esi, dword [ebp+handle_7z.last_pos+4] |
jb .nolast |
xor ecx, ecx |
xchg ecx, [ebp+handle_7z.last_context] |
mov [_7z.decode.mainbuf], ecx |
mov eax, [ebp+handle_7z.last_main_stream] |
mov dword [eax+streamInfo.fullSize], edx |
mov dword [eax+streamInfo.fullSize+4], esi |
or [ebp+handle_7z.last_folder], -1 |
pop esi |
push esi |
jmp .commonl |
.nolast: |
mov ebx, [ebx+ecx*4] |
mov eax, [ebx+_7z.StreamsInfo.startPackedStream] |
mov [_7z.CurInStream], eax |
mov eax, dword [ebx+_7z.StreamsInfo.packOffset] |
mov dword [_7z.StreamsInfo.dataOffset], eax |
mov eax, dword [ebx+_7z.StreamsInfo.packOffset+4] |
mov dword [_7z.StreamsInfo.dataOffset+4], eax |
mov eax, [ebp+handle_7z.packSizes] |
mov [_7z.StreamsInfo.packSizes], eax |
push ebp |
call _7z.decode.init |
pop ebp |
mov eax, [ebx+_7z.StreamsInfo.mainOutStream] |
mov esi, [_7z.decode.pStreams] |
mov eax, [esi+eax*4] |
pop esi |
push esi |
mov ecx, dword [esi+file_in_7z.folderStart] |
mov dword [eax+streamInfo.fullSize], ecx |
mov ecx, dword [esi+file_in_7z.folderStart+4] |
mov dword [eax+streamInfo.fullSize+4], ecx |
.commonl: |
call skip_7z |
mov ecx, dword [esi+file_in_7z.UnPackSize] |
mov dword [eax+streamInfo.fullSize], ecx |
mov edx, dword [esi+file_in_7z.UnPackSize+4] |
mov dword [eax+streamInfo.fullSize+4], edx |
test edx, edx |
jnz .nomemstream |
if defined LIMIT_FOR_MEM_STREAM |
cmp ecx, LIMIT_FOR_MEM_STREAM |
ja .nomemstream |
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 .nomemstream |
; create memory stream and unpack to memory |
push eax ecx |
add ecx, mem_stream.buf |
call [pgalloc] |
test eax, eax |
jz return.clear |
mov edi, eax |
pop ecx |
push edi |
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 |
mov eax, [esp+4] |
push esi |
push ecx edi |
call read_7z_to_buf |
pop esi ecx |
mov ebx, [esp+12] |
cmp [ebx+file_in_7z.bCRCDefined], 0 |
jz @f |
call crc |
cmp eax, [ebx+file_in_7z.FileCRC] |
jnz return.err |
@@: |
pop esi |
xor ecx, ecx |
xchg ecx, [_7z.decode.mainbuf] |
xchg ecx, [ebp+handle_7z.last_context] |
jecxz @f |
call [pgfree] |
@@: |
and [hOut], 0 |
mov eax, [esi+file_in_7z.folder] |
mov [ebp+handle_7z.last_folder], eax |
mov eax, [esp+4] |
mov [ebp+handle_7z.last_main_stream], eax |
mov ecx, dword [esi+file_in_7z.UnPackSize] |
add ecx, dword [esi+file_in_7z.folderStart] |
mov dword [ebp+handle_7z.last_pos], ecx |
mov ecx, dword [esi+file_in_7z.UnPackSize+4] |
adc ecx, dword [esi+file_in_7z.folderStart+4] |
mov dword [ebp+handle_7z.last_pos+4], ecx |
call .done |
pop eax edi ecx |
ret |
.nomemstream: |
mov edi, eax |
push esi |
mov esi, handle_table_7z |
push file_handle_7z.size |
pop ecx |
call alloc_handle |
pop esi |
test eax, eax |
jz .clear |
mov [eax+file_handle_7z.type], type_7z |
xor edx, edx |
mov dword [eax+file_handle_7z.pos], edx |
mov dword [eax+file_handle_7z.pos+4], edx |
mov [eax+file_handle_7z.bError], dl |
xchg edx, [_7z.decode.mainbuf] |
mov [eax+file_handle_7z.context], edx |
mov [eax+file_handle_7z.mainStream], edi |
mov [eax+file_handle_7z.base], ebp |
mov [eax+file_handle_7z.item], esi |
push eax |
call .done |
pop eax ecx |
ret |
|
.done: |
cmp [bPasswordDefined], 0 |
jz @f |
mov ecx, [password_size] |
mov [ebp+handle_7z.password_len], ecx |
mov esi, password_unicode |
lea edi, [ebp+handle_7z.password] |
shr ecx, 1 |
rep movsd |
adc ecx, ecx |
rep movsw |
@@: |
jmp .clear |
|
.error: |
cmp [bPasswordDefined], 0 |
jz .realerror |
push CancelPassBtn |
push 2 |
push aArchiveDataErrorPass_ptr |
push 1 |
call [SayErr] |
cmp al, 1 |
jnz .clear |
; user wants to re-enter password |
call .clear |
pop eax |
jmp open_file_7z |
.realerror: |
push ContinueBtn |
push 1 |
push aArchiveDataError_ptr |
push 1 |
call [SayErr] |
.clear: |
mov ecx, [_7z.decode.pStreams] |
cmp ecx, _7z.decode.pStreams_def |
jz @f |
call [pgfree] |
@@: |
mov ecx, [_7z.decode.mainbuf] |
jecxz @f |
call [pgfree] |
@@: |
mov ecx, [hOut] |
jecxz @f |
call [pgfree] |
@@: |
cmp esp, [_esp] |
jnz @f |
pop eax |
@@: |
xor eax, eax |
ret |
|
read_7z_to_buf: |
mov esi, [eax+streamInfo.bufDataLen] |
cmp esi, [eax+streamInfo.bufSize] |
jnz @f |
xor esi, esi |
mov [eax+streamInfo.bufDataLen], esi |
@@: |
call fillBufNozero |
mov ecx, [eax+streamInfo.bufDataLen] |
sub ecx, esi |
add esi, [eax+streamInfo.bufPtr] |
mov edx, ecx |
shr ecx, 2 |
rep movsd |
mov ecx, edx |
and ecx, 3 |
rep movsb |
cmp dword [eax+streamInfo.fullSize], 0 |
jnz read_7z_to_buf |
ret |
|
skip_7z: |
push edx |
mov edx, [eax+streamInfo.bufDataLen] |
cmp edx, [eax+streamInfo.bufSize] |
jnz @f |
and [eax+streamInfo.bufDataLen], 0 |
@@: |
pop edx |
call fillBufNozero |
cmp dword [eax+streamInfo.fullSize], 0 |
jnz skip_7z |
cmp dword [eax+streamInfo.fullSize+4], 0 |
jnz skip_7z |
ret |
|
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size); |
read_7z: |
mov eax, [ebx+file_handle_7z.mainStream] |
test eax, eax |
jz .ret ; empty stream - return 0 bytes read |
cmp [ebx+file_handle_7z.bError], 0 |
jnz .reterr |
mov ecx, [ebx+file_handle_7z.base] |
mov ecx, [ecx+handle_7z.host] |
mov [inStream], ecx |
mov edi, [esp+8] |
mov ecx, [esp+12] |
mov dword [eax+streamInfo.fullSize], ecx |
and dword [eax+streamInfo.fullSize+4], 0 |
jecxz .nodata |
mov [_esp], esp |
mov [_ebp], ebp |
mov [error_proc], .error |
mov [clear_proc], .clear ; should not be called |
mov esi, [ebx+file_handle_7z.item] |
mov edx, dword [esi+file_in_7z.UnPackSize] |
mov esi, dword [esi+file_in_7z.UnPackSize+4] |
sub edx, dword [ebx+file_handle_7z.pos] |
sbb esi, dword [ebx+file_handle_7z.pos+4] |
jnz .do |
cmp edx, ecx |
jae .do |
mov dword [eax+streamInfo.fullSize], edx |
.do: |
call read_7z_to_buf |
.nodata: |
sub edi, [esp+8] |
mov eax, edi |
add dword [ebx+file_handle_7z.pos], eax |
adc dword [ebx+file_handle_7z.pos+4], 0 |
.ret: |
ret 12 |
|
.error: |
.clear: |
mov ebx, [esp+4] |
mov [ebx+file_handle_7z.bError], 1 |
push ContinueBtn |
push 1 |
push aArchiveDataError_ptr |
push 1 |
call [SayErr] |
.reterr: |
or eax, -1 |
ret 12 |
|
; void __stdcall setpos(HANDLE hFile, __int64 pos); |
setpos_7z: |
cmp [ebx+file_handle_7z.context], 0 |
jz .ret |
mov edi, [ebx+file_handle_7z.base] |
mov ecx, [edi+handle_7z.host] |
mov [inStream], ecx |
mov [_esp], esp |
mov [_ebp], ebp |
mov [error_proc], read_7z.error |
mov [clear_proc], read_7z.clear ; should not be called |
cmp [ebx+file_handle_7z.bError], 0 |
jnz .backward ; if was error, force reinitialization |
mov ecx, [esp+8] |
mov edx, [esp+12] |
sub ecx, dword [ebx+file_handle_7z.pos] |
sbb edx, dword [ebx+file_handle_7z.pos+4] |
jb .backward |
; move forward - skip some data |
mov eax, [ebx+file_handle_7z.mainStream] |
mov dword [eax+streamInfo.fullSize], ecx |
mov dword [eax+streamInfo.fullSize+4], edx |
call skip_7z |
add dword [ebx+file_handle_7z.pos], ecx |
adc dword [ebx+file_handle_7z.pos], edx |
.ret: |
ret 12 |
.backward: |
; move backward - reinitialize and skip start data |
mov [ebx+file_handle_7z.bError], 0 |
mov ebp, [ebx+file_handle_7z.context] |
mov eax, [ebx+file_handle_7z.item] |
mov ebx, [edi+handle_7z.folders] |
mov eax, [eax+file_in_7z.folder] |
mov ebx, [ebx+eax*4] |
; initialize streamInfos for decoders |
xor ecx, ecx |
mov esi, [ebx+_7z.StreamsInfo.unpackSizes] |
@@: |
lodsd |
mov [ebp], eax |
lodsd |
mov [ebp+4], eax |
and [ebp+streamInfo.bufDataLen], 0 |
push esi |
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4] |
call _7z.GetCoder |
movzx esi, byte [eax+4] |
lea esi, [esi+eax+17] |
push ebx ecx edi |
mov bl, 1 |
call [_7z.InitTable+edx*4] |
pop edi ecx ebx esi |
mov edx, [ebp+streamInfo.bufSize] |
mov ebp, [ebp+streamInfo.bufPtr] |
add ebp, edx |
inc ecx |
cmp ecx, [ebx+_7z.StreamsInfo.numCoders] |
jb @b |
; initialize streamInfos for input streams |
xor ecx, ecx |
mov esi, [ebx+_7z.StreamsInfo.startPackedStream] |
shl esi, 3 |
add esi, [edi+handle_7z.packSizes] |
mov edi, dword [ebx+_7z.StreamsInfo.packOffset] |
mov edx, dword [ebx+_7z.StreamsInfo.packOffset+4] |
@@: |
mov dword [ebp+streamInfo.size], edi |
mov dword [ebp+streamInfo.size+4], edx |
and [ebp+streamInfo.bufDataLen], 0 |
lodsd |
add edi, eax |
mov [ebp], eax |
lodsd |
adc edx, eax |
mov [ebp+4], eax |
add ebp, 0x4000 |
inc ecx |
cmp ecx, [ebx+_7z.StreamsInfo.numPackedStreams] |
jb @b |
mov ebx, [esp+4] |
mov esi, [ebx+file_handle_7z.item] |
mov eax, [ebx+file_handle_7z.mainStream] |
mov ecx, dword [esi+file_in_7z.folderStart] |
add ecx, [esp+8] |
mov dword [eax+streamInfo.fullSize], ecx |
mov ecx, dword [esi+file_in_7z.folderStart+4] |
adc ecx, [esp+12] |
mov dword [eax+streamInfo.fullSize+4], ecx |
and dword [ebx+file_handle_7z.pos], 0 |
and dword [ebx+file_handle_7z.pos+4], 0 |
and [eax+streamInfo.bufDataLen], 0 |
call skip_7z |
mov eax, [esp+8] |
mov dword [ebx+file_handle_7z.pos], eax |
mov eax, [esp+12] |
mov dword [ebx+file_handle_7z.pos+4], eax |
ret 12 |
|
close_file_7z: |
mov ecx, [ebx+file_handle_7z.context] |
jecxz .ret |
cmp [ebx+file_handle_7z.bError], 0 |
jnz @f |
push ebp |
mov ebp, [ebx+file_handle_7z.base] |
xchg ecx, [ebp+handle_7z.last_context] |
mov eax, [ebx+file_handle_7z.item] |
mov edx, [eax+file_in_7z.folder] |
mov [ebp+handle_7z.last_folder], edx |
mov edx, [ebx+file_handle_7z.mainStream] |
mov [ebp+handle_7z.last_main_stream], edx |
mov edx, dword [eax+file_in_7z.folderStart+4] |
mov eax, dword [eax+file_in_7z.folderStart] |
add eax, dword [ebx+file_handle_7z.pos] |
adc edx, dword [ebx+file_handle_7z.pos+4] |
mov dword [ebp+handle_7z.last_pos], eax |
mov dword [ebp+handle_7z.last_pos+4], edx |
pop ebp |
@@: |
jecxz @f |
call [pgfree] |
@@: |
mov esi, ebx |
call free_handle |
.ret: |
ret 4 |
|
iglobal |
cur_stamp dd 0 |
endg |
|
uglobal |
tmp_bdfe rb 304 |
endg |
|
GetFiles_7z: |
mov ecx, [ebp+handle_7z.NumFiles] |
test ecx, ecx |
jz .ret |
lea ebx, [ebp+handle_7z.basesize] |
inc [cur_stamp] |
.loop: |
push ecx |
mov esi, [ebx+file_in_7z.fullname] |
mov edx, [ebp+handle_7z.curdir] |
test edx, edx |
jz .incur |
mov eax, [cur_stamp] |
mov [edx+file_in_7z.stamp], eax |
mov edi, [edx+file_in_7z.fullname] |
mov ecx, [edx+file_in_7z.namelen] |
add ecx, [edx+file_in_7z.name] |
sub ecx, edi |
repz cmpsb |
jnz .cont |
.incur: |
cmp byte [esi], '/' |
jnz @f |
inc esi |
@@: |
mov ecx, [esp+12] ; NumItems |
mov edx, [esp+16] ; items |
cmp ecx, -1 |
jz .ok |
.check: |
sub ecx, 1 |
js .cont |
push esi |
mov edi, [edx] |
add edi, 40 |
@@: |
lodsb |
scasb |
jnz @f |
test al, al |
jz .ok2 |
jmp @b |
@@: |
pop esi |
cmp al, '/' |
jnz @f |
cmp byte [edi-1], 0 |
jz .ok |
@@: |
add edx, 4 |
jmp .check |
.ok2: |
pop esi |
.ok: |
; add all parents directories if needed |
.parloope: |
mov ecx, [ebx+file_in_7z.parent] |
jecxz .pardone |
add ecx, ebp |
mov eax, [cur_stamp] |
cmp [ecx+file_in_7z.stamp], eax |
jz .pardone |
.parloopi: |
mov edx, ecx |
mov ecx, [ecx+file_in_7z.parent] |
jecxz @f |
add ecx, ebp |
cmp [ecx+file_in_7z.stamp], eax |
jnz .parloopi |
@@: |
mov [edx+file_in_7z.stamp], eax |
push esi |
mov eax, edx |
mov edi, tmp_bdfe |
push edi |
sub esi, [ebx+file_in_7z.fullname] |
add esi, [edx+file_in_7z.fullname] |
push esi |
call getattr_7z |
mov eax, [esp+16+20] |
call eax |
pop esi |
test al, al |
jz .forced_exit |
jmp .parloope |
.pardone: |
cmp [ebx+file_in_7z.bIsDirectory], 0 |
jz .addfile |
mov eax, [cur_stamp] |
cmp [ebx+file_in_7z.stamp], eax |
jz .cont |
mov [ebx+file_in_7z.stamp], eax |
push esi |
mov eax, ebx |
mov edi, tmp_bdfe |
push edi |
push esi |
call getattr_7z |
mov eax, [esp+16+20] |
call eax |
pop esi |
test al, al |
jz .forced_exit |
jmp .cont |
.addfile: |
push ebx esi |
push 11h |
pop edi |
mov eax, ebx |
call open_file_7z |
pop esi ebx |
test eax, eax |
jz .cont |
push eax |
push eax |
mov edi, tmp_bdfe |
push edi |
push esi |
mov eax, ebx |
call getattr_7z |
mov eax, [esp+20+16] |
call eax |
pop ecx |
push eax |
push ebx |
push ecx |
call myclose |
pop ebx |
pop eax |
test al, al |
jz .forced_exit |
.cont: |
add ebx, file_in_7z.size |
pop ecx |
dec ecx |
jnz .loop |
.ret: |
ret 20 |
.forced_exit: |
pop ecx |
jmp .ret |