Files
Eren 9742c47cb7 xd
xd
2024-11-14 23:30:43 +03:00

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