mirror of
https://github.com/Elpisdev/unarchive.git
synced 2026-09-24 23:47:59 +03:00
264 lines
5.0 KiB
NASM
264 lines
5.0 KiB
NASM
section .data
|
|
qar_filename_size equ 132
|
|
|
|
section .bss
|
|
qar_num_files resd 1
|
|
qar_file_size resd 1
|
|
qar_filename resb qar_filename_size
|
|
qar_padding resd 1
|
|
qar_header_pad resd 1
|
|
|
|
section .text
|
|
extract_qar:
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
push FILE_BEGIN
|
|
push 0
|
|
push 0
|
|
push dword [file_handle]
|
|
call _SetFilePointer@16
|
|
|
|
push FILE_CURRENT
|
|
push 0
|
|
push 4
|
|
push dword [file_handle]
|
|
call _SetFilePointer@16
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 4
|
|
push qar_num_files
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz .done
|
|
|
|
.extract_loop:
|
|
mov ecx, [qar_num_files]
|
|
test ecx, ecx
|
|
jz .done
|
|
|
|
push ecx
|
|
mov edi, qar_filename
|
|
mov ecx, qar_filename_size
|
|
xor al, al
|
|
rep stosb
|
|
pop ecx
|
|
|
|
push 0
|
|
push bytes_read
|
|
push qar_filename_size
|
|
push qar_filename
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz .done
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 4
|
|
push qar_padding
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz .done
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 4
|
|
push qar_file_size
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz .done
|
|
|
|
push 0
|
|
push bytes_read
|
|
push 4
|
|
push qar_padding
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz .done
|
|
|
|
mov al, [qar_filename]
|
|
test al, al
|
|
jz .next_file
|
|
|
|
call create_qar_path
|
|
call extract_qar_file
|
|
|
|
.next_file:
|
|
dec dword [qar_num_files]
|
|
jmp .extract_loop
|
|
|
|
.done:
|
|
mov esp, ebp
|
|
pop ebp
|
|
jmp cleanup
|
|
|
|
create_qar_path:
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
mov esi, input_file
|
|
mov edi, output_path
|
|
.copy_base:
|
|
lodsb
|
|
stosb
|
|
test al, al
|
|
jz .base_done
|
|
jmp .copy_base
|
|
|
|
.base_done:
|
|
dec edi
|
|
mov esi, extract_suffix
|
|
mov ecx, extract_suffix_len
|
|
rep movsb
|
|
|
|
mov byte [edi], '/'
|
|
inc edi
|
|
|
|
mov esi, qar_filename
|
|
.copy_name:
|
|
lodsb
|
|
test al, al
|
|
jz .name_done
|
|
cmp al, ' '
|
|
jz .name_done
|
|
cmp al, 0x0D
|
|
je .next_char
|
|
cmp al, 0x0A
|
|
je .next_char
|
|
cmp al, '\'
|
|
jne .store_char
|
|
mov al, '/'
|
|
.store_char:
|
|
stosb
|
|
.next_char:
|
|
jmp .copy_name
|
|
|
|
.name_done:
|
|
mov byte [edi], 0
|
|
|
|
mov esi, output_path
|
|
mov edi, chunk_buffer
|
|
.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 chunk_buffer
|
|
call _CreateDirectoryA@8
|
|
|
|
pop eax
|
|
mov byte [edi-1], '/'
|
|
jmp .create_dirs
|
|
|
|
.dirs_done:
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
|
|
extract_qar_file:
|
|
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, [qar_file_size]
|
|
.copy_loop:
|
|
mov eax, CHUNK_SIZE
|
|
cmp ecx, eax
|
|
jb .last_chunk
|
|
jmp .do_copy
|
|
|
|
.last_chunk:
|
|
mov eax, ecx
|
|
|
|
.do_copy:
|
|
push ecx
|
|
|
|
push 0
|
|
push bytes_read
|
|
push eax
|
|
push chunk_buffer
|
|
push dword [file_handle]
|
|
call _ReadFile@20
|
|
test eax, eax
|
|
jz .read_error
|
|
|
|
push 0
|
|
push bytes_written
|
|
push dword [bytes_read]
|
|
push chunk_buffer
|
|
push ebx
|
|
call _WriteFile@20
|
|
test eax, eax
|
|
jz .write_error
|
|
|
|
pop ecx
|
|
sub ecx, [bytes_read]
|
|
jnz .copy_loop
|
|
|
|
push ebx
|
|
call _CloseHandle@4
|
|
mov eax, 1
|
|
jmp .done
|
|
|
|
.read_error:
|
|
.write_error:
|
|
pop ecx
|
|
.error:
|
|
test ebx, ebx
|
|
jz .done
|
|
push ebx
|
|
call _CloseHandle@4
|
|
xor eax, eax
|
|
|
|
.done:
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret |