mirror of
https://github.com/Elpisdev/unarchive.git
synced 2026-09-22 22:48:01 +03:00
340 lines
6.7 KiB
NASM
340 lines
6.7 KiB
NASM
section .data
|
|
FILENAME_SIZE equ 256
|
|
|
|
section .bss
|
|
bar_num_files resw 1
|
|
bar_file_size resd 1
|
|
bar_bytes_remaining resd 1
|
|
bar_filename_buffer resb FILENAME_SIZE
|
|
bar_temp_filename resb FILENAME_SIZE
|
|
bar_check1 resd 1
|
|
bar_check2 resd 1
|
|
bar_current_dir resb 260
|
|
|
|
section .text
|
|
extract_bar:
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 10
|
|
push header_buffer
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz cleanup
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 2
|
|
push bar_num_files
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz cleanup
|
|
|
|
bar_extract_loop:
|
|
movzx ecx, word [bar_num_files]
|
|
test ecx, ecx
|
|
jz cleanup
|
|
|
|
push 0
|
|
push bytes_read
|
|
push FILENAME_SIZE
|
|
push bar_filename_buffer
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz cleanup
|
|
|
|
call bar_process_filename
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 8
|
|
push bar_check1
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
|
|
call bar_read_file_size
|
|
test eax, eax
|
|
jz cleanup
|
|
|
|
call bar_create_output_path
|
|
call bar_extract_file_data
|
|
test eax, eax
|
|
jz cleanup
|
|
|
|
dec word [bar_num_files]
|
|
jmp bar_extract_loop
|
|
|
|
.invalid_format:
|
|
push 0
|
|
push bytes_written
|
|
push msg_invalid_bar_len
|
|
push msg_invalid_bar
|
|
push dword [stdout_handle]
|
|
call _WriteFile@20
|
|
jmp cleanup
|
|
|
|
bar_process_filename:
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
mov al, [bar_filename_buffer + FILENAME_SIZE - 1]
|
|
cmp al, 0xFE
|
|
je .fe_format
|
|
|
|
mov esi, bar_filename_buffer
|
|
mov edi, bar_temp_filename
|
|
mov ecx, FILENAME_SIZE - 4
|
|
rep movsb
|
|
mov byte [edi], 0
|
|
|
|
push FILE_CURRENT
|
|
push 0
|
|
push -4
|
|
push dword [file_handle]
|
|
call _SetFilePointer@16
|
|
cmp eax, 0xFFFFFFFF
|
|
je .error
|
|
|
|
jmp .clean_filename
|
|
|
|
.fe_format:
|
|
mov esi, bar_filename_buffer
|
|
mov edi, bar_temp_filename
|
|
.find_fe:
|
|
lodsb
|
|
cmp al, 0xFE
|
|
je .fe_found
|
|
stosb
|
|
cmp esi, bar_filename_buffer + FILENAME_SIZE
|
|
jb .find_fe
|
|
.fe_found:
|
|
mov byte [edi], 0
|
|
|
|
.clean_filename:
|
|
mov edi, bar_temp_filename
|
|
xor edx, edx
|
|
.trim_loop:
|
|
mov al, [edi]
|
|
test al, al
|
|
jz .trim_done
|
|
cmp al, ' '
|
|
je .next_trim
|
|
cmp al, '.'
|
|
je .next_trim
|
|
cmp al, 9
|
|
je .next_trim
|
|
cmp al, 13
|
|
je .next_trim
|
|
cmp al, 10
|
|
je .next_trim
|
|
mov edx, edi
|
|
.next_trim:
|
|
inc edi
|
|
cmp edi, bar_temp_filename + FILENAME_SIZE
|
|
jb .trim_loop
|
|
|
|
.trim_done:
|
|
mov edi, edx
|
|
inc edi
|
|
mov byte [edi], 0
|
|
|
|
mov edi, bar_temp_filename
|
|
.convert_slashes:
|
|
mov al, [edi]
|
|
test al, al
|
|
jz .done
|
|
cmp al, '\\'
|
|
jne .next_char
|
|
mov byte [edi], '/'
|
|
.next_char:
|
|
inc edi
|
|
jmp .convert_slashes
|
|
|
|
.done:
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
|
|
.error:
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
|
|
bar_read_file_size:
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 4
|
|
push bar_file_size
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz .error
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 4
|
|
push bar_check1
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
|
|
.error:
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
|
|
bar_create_output_path:
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
mov esi, input_file
|
|
mov edi, output_path
|
|
.copy_path:
|
|
lodsb
|
|
stosb
|
|
test al, al
|
|
jnz .copy_path
|
|
|
|
dec edi
|
|
mov esi, extract_suffix
|
|
mov ecx, extract_suffix_len
|
|
rep movsb
|
|
|
|
mov byte [edi], '/'
|
|
inc edi
|
|
|
|
mov esi, bar_temp_filename
|
|
.copy_name:
|
|
lodsb
|
|
test al, al
|
|
jz .done
|
|
stosb
|
|
jmp .copy_name
|
|
.done:
|
|
mov byte [edi], 0
|
|
|
|
mov esi, output_path
|
|
mov edi, bar_current_dir
|
|
.create_dirs:
|
|
lodsb
|
|
stosb
|
|
test al, al
|
|
jz .dirs_done
|
|
cmp al, '/'
|
|
jne .create_dirs
|
|
|
|
mov byte [edi-1], 0
|
|
push eax
|
|
|
|
push 0
|
|
push bar_current_dir
|
|
call _CreateDirectoryA@8
|
|
|
|
pop eax
|
|
mov byte [edi-1], '/'
|
|
jmp .create_dirs
|
|
.dirs_done:
|
|
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
|
|
bar_extract_file_data:
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
push 0
|
|
push bytes_written
|
|
push msg_extract_len
|
|
push msg_extract
|
|
push dword [stdout_handle]
|
|
call _WriteFile@20
|
|
|
|
mov esi, output_path
|
|
call string_length
|
|
push 0
|
|
push bytes_written
|
|
push eax
|
|
push output_path
|
|
push dword [stdout_handle]
|
|
call _WriteFile@20
|
|
|
|
push 0
|
|
push bytes_written
|
|
push msg_newline_len
|
|
push msg_newline
|
|
push dword [stdout_handle]
|
|
call _WriteFile@20
|
|
|
|
push 0
|
|
push FILE_ATTRIBUTE_NORMAL
|
|
push CREATE_ALWAYS
|
|
push 0
|
|
push 0
|
|
push GENERIC_WRITE
|
|
push output_path
|
|
call _CreateFileA@28
|
|
|
|
cmp eax, INVALID_HANDLE_VALUE
|
|
je .error
|
|
mov ebx, eax
|
|
|
|
mov ecx, [bar_file_size]
|
|
mov [bar_bytes_remaining], ecx
|
|
|
|
.copy_loop:
|
|
mov eax, CHUNK_SIZE
|
|
cmp [bar_bytes_remaining], eax
|
|
jb .last_chunk
|
|
jmp .do_copy
|
|
|
|
.last_chunk:
|
|
mov eax, [bar_bytes_remaining]
|
|
|
|
.do_copy:
|
|
push 0
|
|
push bytes_read
|
|
push eax
|
|
push chunk_buffer
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz .error
|
|
|
|
push 0
|
|
push bytes_written
|
|
push dword [bytes_read]
|
|
push chunk_buffer
|
|
push ebx
|
|
call _WriteFile@20
|
|
test eax, eax
|
|
jz .error
|
|
|
|
mov eax, [bytes_read]
|
|
sub [bar_bytes_remaining], eax
|
|
jnz .copy_loop
|
|
|
|
push ebx
|
|
call _CloseHandle@4
|
|
mov eax, 1
|
|
jmp .done
|
|
|
|
.error:
|
|
push ebx
|
|
call _CloseHandle@4
|
|
xor eax, eax
|
|
.done:
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret |