Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3907 → Rev 3908

/kernel/branches/Kolibri-acpi/fs/ntfs.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7,7 → 7,65
 
$Revision$
 
struct NTFS PARTITION
Lock MUTEX ? ; currently operations with one partition
; can not be executed in parallel since the
; legacy code is not ready; this mutex guards
; all operations
sectors_per_cluster dd ?
mft_cluster dd ?
mftmirr_cluster dd ?
frs_size dd ? ; FRS size in bytes
iab_size dd ? ; IndexAllocationBuffer size in bytes
frs_buffer dd ?
iab_buffer dd ?
mft_retrieval dd ?
mft_retrieval_size dd ?
mft_retrieval_alloc dd ?
mft_retrieval_end dd ?
cur_index_size dd ?
cur_index_buf dd ?
 
ntfs_cur_attr dd ?
ntfs_cur_iRecord dd ?
ntfs_cur_offs dd ? ; in sectors
ntfs_cur_size dd ? ; in sectors
ntfs_cur_buf dd ?
ntfs_cur_read dd ? ; [output]
ntfs_bCanContinue db ?
rb 3
 
cur_subnode_size dd ?
ntfs_attr_iRecord dd ?
ntfs_attr_iBaseRecord dd ?
ntfs_attr_offs dd ?
ntfs_attr_list dd ?
ntfs_attr_size dq ?
ntfs_cur_tail dd ?
 
ntfs_attrlist_buf rb 0x400
ntfs_attrlist_mft_buf rb 0x400
ntfs_bitmap_buf rb 0x400
ends
 
iglobal
align 4
ntfs_user_functions:
dd ntfs_free
dd (ntfs_user_functions_end - ntfs_user_functions - 4) / 4
dd ntfs_Read
dd ntfs_ReadFolder
dd ntfs_Rewrite
dd ntfs_Write
dd ntfs_SetFileEnd
dd ntfs_GetFileInfo
dd ntfs_SetFileInfo
dd 0
dd ntfs_Delete
dd ntfs_CreateFolder
ntfs_user_functions_end:
endg
 
ntfs_test_bootsec:
; in: ebx->buffer, edx=size of partition
; out: CF set <=> invalid
93,25 → 151,66
stc
ret
 
ntfs_setup: ; CODE XREF: part_set.inc
proc ntfs_create_partition
mov edx, dword [ebp+PARTITION.Length]
cmp dword [esp+4], 0
jz .boot_read_ok
add ebx, 512
lea eax, [edx-1]
call fs_read32_sys
test eax, eax
jnz @f
call ntfs_test_bootsec
jnc .ntfs_setup
@@:
mov eax, edx
shr eax, 1
call fs_read32_sys
test eax, eax
jnz .nope ; no chance...
.boot_read_ok:
call ntfs_test_bootsec
jnc .ntfs_setup
.nope:
xor eax, eax
jmp .exit
 
.ntfs_setup:
; By given bootsector, initialize some NTFS variables
; call ntfs_test_bootsec ; checking boot sector was already
; jc problem_fat_dec_count
movi eax, sizeof.NTFS
call malloc
test eax, eax
jz .exit
mov ecx, dword [ebp+PARTITION.FirstSector]
mov dword [eax+NTFS.FirstSector], ecx
mov ecx, dword [ebp+PARTITION.FirstSector+4]
mov dword [eax+NTFS.FirstSector+4], ecx
mov ecx, dword [ebp+PARTITION.Length]
mov dword [eax+NTFS.Length], ecx
mov ecx, dword [ebp+PARTITION.Length+4]
mov dword [eax+NTFS.Length+4], ecx
mov ecx, [ebp+PARTITION.Disk]
mov [eax+NTFS.Disk], ecx
mov [eax+NTFS.FSUserFunctions], ntfs_user_functions
push ebx ebp esi
mov ebp, eax
 
lea ecx, [ebp+NTFS.Lock]
call mutex_init
 
movzx eax, byte [ebx+13]
mov [ntfs_data.sectors_per_cluster], eax
mov [ebp+NTFS.sectors_per_cluster], eax
mov eax, [ebx+0x28]
add eax, [PARTITION_START]
dec eax
mov [PARTITION_END], eax
mov [fs_type], 1
mov dword [ebp+NTFS.Length], eax
and dword [ebp+NTFS.Length+4], 0
mov eax, [ebx+0x30]
mov [ntfs_data.mft_cluster], eax
mov [ebp+NTFS.mft_cluster], eax
mov eax, [ebx+0x38]
mov [ntfs_data.mftmirr_cluster], eax
mov [ebp+NTFS.mftmirr_cluster], eax
movsx eax, byte [ebx+0x40]
test eax, eax
js .1
mul [ntfs_data.sectors_per_cluster]
mul [ebp+NTFS.sectors_per_cluster]
shl eax, 9
jmp .2
.1:
120,11 → 219,11
mov eax, 1
shl eax, cl
.2:
mov [ntfs_data.frs_size], eax
mov [ebp+NTFS.frs_size], eax
movsx eax, byte [ebx+0x44]
test eax, eax
js .3
mul [ntfs_data.sectors_per_cluster]
mul [ebp+NTFS.sectors_per_cluster]
shl eax, 9
jmp .4
.3:
133,21 → 232,21
mov eax, 1
shl eax, cl
.4:
mov [ntfs_data.iab_size], eax
mov [ebp+NTFS.iab_size], eax
; allocate space for buffers
add eax, [ntfs_data.frs_size]
add eax, [ebp+NTFS.frs_size]
push eax
call kernel_alloc
test eax, eax
jz problem_fat_dec_count
mov [ntfs_data.frs_buffer], eax
add eax, [ntfs_data.frs_size]
mov [ntfs_data.iab_buffer], eax
jz .fail_free
mov [ebp+NTFS.frs_buffer], eax
add eax, [ebp+NTFS.frs_size]
mov [ebp+NTFS.iab_buffer], eax
; read $MFT disposition
mov eax, [ntfs_data.mft_cluster]
mul [ntfs_data.sectors_per_cluster]
mov eax, [ebp+NTFS.mft_cluster]
mul [ebp+NTFS.sectors_per_cluster]
call ntfs_read_frs_sector
cmp [hd_error], 0
test eax, eax
jnz .usemirr
cmp dword [ebx], 'FILE'
jnz .usemirr
154,11 → 253,10
call ntfs_restore_usa_frs
jnc .mftok
.usemirr:
and [hd_error], 0
mov eax, [ntfs_data.mftmirr_cluster]
mul [ntfs_data.sectors_per_cluster]
mov eax, [ebp+NTFS.mftmirr_cluster]
mul [ebp+NTFS.sectors_per_cluster]
call ntfs_read_frs_sector
cmp [hd_error], 0
test eax, eax
jnz @f
cmp dword [ebx], 'FILE'
jnz @f
167,11 → 265,22
@@:
; $MFT and $MFTMirr invalid!
.fail_free_frs:
push [ntfs_data.frs_buffer]
push [ebp+NTFS.frs_buffer]
call kernel_free
jmp problem_fat_dec_count
.fail_free:
mov eax, ebp
call free
xor eax, eax
.pop_exit:
pop esi ebp ebx
.exit:
cmp dword [esp+4], 0
jz @f
sub ebx, 512
@@:
ret
.fail_free_mft:
push [ntfs_data.mft_retrieval]
push [ebp+NTFS.mft_retrieval]
call kernel_free
jmp .fail_free_frs
.mftok:
183,9 → 292,9
pop ebx
test eax, eax
jz .fail_free_frs
mov [ntfs_data.mft_retrieval], eax
and [ntfs_data.mft_retrieval_size], 0
mov [ntfs_data.mft_retrieval_alloc], 0x1000/8
mov [ebp+NTFS.mft_retrieval], eax
and [ebp+NTFS.mft_retrieval_size], 0
mov [ebp+NTFS.mft_retrieval_alloc], 0x1000/8
; $MFT base record must contain unnamed non-resident $DATA attribute
movzx eax, word [ebx+14h]
add eax, ebx
204,7 → 313,7
jz .fail_free_mft
; load first portion of $DATA attribute retrieval information
mov edx, [eax+0x18]
mov [ntfs_data.mft_retrieval_end], edx
mov [ebp+NTFS.mft_retrieval_end], edx
mov esi, eax
movzx eax, word [eax+0x20]
add esi, eax
217,7 → 326,7
mov [eax], edx
mov edx, [esp+8] ; block addr (relative)
mov [eax+4], edx
inc [ntfs_data.mft_retrieval_size]
inc [ebp+NTFS.mft_retrieval_size]
jmp .scanmcb
.scanmcbend:
add esp, 10h
224,25 → 333,24
; there may be other portions of $DATA attribute in auxiliary records;
; if they will be needed, they will be loaded later
 
mov [ntfs_data.cur_index_size], 0x1000/0x200
mov [ebp+NTFS.cur_index_size], 0x1000/0x200
push 0x1000
call kernel_alloc
test eax, eax
jz .fail_free_mft
mov [ntfs_data.cur_index_buf], eax
mov [ebp+NTFS.cur_index_buf], eax
 
popad
call free_hd_channel
and [hd1_status], 0
ret
mov eax, ebp
jmp .pop_exit
endp
 
.get_mft_retrieval_ptr:
pushad
mov eax, [ntfs_data.mft_retrieval_size]
cmp eax, [ntfs_data.mft_retrieval_alloc]
mov eax, [ebp+NTFS.mft_retrieval_size]
cmp eax, [ebp+NTFS.mft_retrieval_alloc]
jnz .ok
add eax, 0x1000/8
mov [ntfs_data.mft_retrieval_alloc], eax
mov [ebp+NTFS.mft_retrieval_alloc], eax
shl eax, 3
push eax
call kernel_alloc
252,83 → 360,88
add esp, 14h
jmp .fail_free_mft
@@:
mov esi, [ntfs_data.mft_retrieval]
mov esi, [ebp+NTFS.mft_retrieval]
mov edi, eax
mov ecx, [ntfs_data.mft_retrieval_size]
mov ecx, [ebp+NTFS.mft_retrieval_size]
add ecx, ecx
rep movsd
push [ntfs_data.mft_retrieval]
mov [ntfs_data.mft_retrieval], eax
push [ebp+NTFS.mft_retrieval]
mov [ebp+NTFS.mft_retrieval], eax
call kernel_free
mov eax, [ntfs_data.mft_retrieval_size]
mov eax, [ebp+NTFS.mft_retrieval_size]
.ok:
shl eax, 3
add eax, [ntfs_data.mft_retrieval]
add eax, [ebp+NTFS.mft_retrieval]
mov [esp+28], eax
popad
ret
 
proc ntfs_free
push ebx
xchg ebx, eax
stdcall kernel_free, [ebx+NTFS.frs_buffer]
stdcall kernel_free, [ebx+NTFS.mft_retrieval]
stdcall kernel_free, [ebx+NTFS.cur_index_buf]
xchg ebx, eax
call free
pop ebx
ret
endp
 
proc ntfs_lock
lea ecx, [ebp+NTFS.Lock]
jmp mutex_lock
endp
 
proc ntfs_unlock
lea ecx, [ebp+NTFS.Lock]
jmp mutex_unlock
endp
 
ntfs_read_frs_sector:
push eax ecx
add eax, [PARTITION_START]
mov ecx, [ntfs_data.frs_size]
push ecx
mov ebx, [ebp+NTFS.frs_buffer]
push ebx
mov ecx, [ebp+NTFS.frs_size]
shr ecx, 9
mov ebx, [ntfs_data.frs_buffer]
push ebx
push ecx
mov ecx, eax
@@:
call hd_read
cmp [hd_error], 0
mov eax, ecx
call fs_read32_sys
test eax, eax
jnz .fail
add ebx, 0x200
inc eax
loop @b
inc ecx
dec dword [esp]
jnz @b
pop eax
.fail:
pop ebx
pop ecx eax
pop ecx
ret
 
uglobal
align 4
ntfs_cur_attr dd ?
ntfs_cur_iRecord dd ?
ntfs_cur_offs dd ? ; in sectors
ntfs_cur_size dd ? ; in sectors
ntfs_cur_buf dd ?
ntfs_cur_read dd ? ; [output]
ntfs_bCanContinue db ?
rb 3
 
ntfs_attrlist_buf rb 0x400
ntfs_attrlist_mft_buf rb 0x400
ntfs_bitmap_buf rb 0x400
 
ntfs_attr_iRecord dd ?
ntfs_attr_iBaseRecord dd ?
ntfs_attr_offs dd ?
ntfs_attr_list dd ?
ntfs_attr_size dq ?
ntfs_cur_tail dd ?
endg
 
ntfs_read_attr:
; in: global variables
; out: [ntfs_cur_read]
; in: variables in ebp+NTFS.*
; out: [ebp+NTFS.ntfs_cur_read]
; out: CF=1 => notfound, in this case eax=0 => disk ok, otherwise eax=disk error code
xor eax, eax
pushad
and [ntfs_cur_read], 0
cmp [ntfs_cur_iRecord], 0
and [ebp+NTFS.ntfs_cur_read], 0
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jnz .nomft
cmp [ntfs_cur_attr], 0x80
cmp [ebp+NTFS.ntfs_cur_attr], 0x80
jnz .nomft
mov eax, [ntfs_data.mft_retrieval_end]
mov eax, [ebp+NTFS.mft_retrieval_end]
inc eax
mul [ntfs_data.sectors_per_cluster]
cmp eax, [ntfs_cur_offs]
mul [ebp+NTFS.sectors_per_cluster]
cmp eax, [ebp+NTFS.ntfs_cur_offs]
jbe .nomft
; precalculated part of $Mft $DATA
mov esi, [ntfs_data.mft_retrieval]
mov eax, [ntfs_cur_offs]
mov esi, [ebp+NTFS.mft_retrieval]
mov eax, [ebp+NTFS.ntfs_cur_offs]
xor edx, edx
div [ntfs_data.sectors_per_cluster]
div [ebp+NTFS.sectors_per_cluster]
; eax = VCN, edx = offset in sectors from beginning of cluster
xor ecx, ecx ; ecx will contain LCN
.mftscan:
337,9 → 450,9
jb @f
add esi, 8
push eax
mov eax, [ntfs_data.mft_retrieval_end]
mov eax, [ebp+NTFS.mft_retrieval_end]
shl eax, 3
add eax, [ntfs_data.mft_retrieval]
add eax, [ebp+NTFS.mft_retrieval]
cmp eax, esi
pop eax
jnz .mftscan
350,42 → 463,43
add ecx, [esi]
push eax
push edx
mov eax, [ntfs_data.sectors_per_cluster]
mov eax, [ebp+NTFS.sectors_per_cluster]
mul ecx
; eax = sector on partition
add eax, [PARTITION_START]
pop edx
add eax, edx
mov ebx, [ntfs_cur_buf]
mov ebx, [ebp+NTFS.ntfs_cur_buf]
pop ecx
neg ecx
imul ecx, [ntfs_data.sectors_per_cluster]
imul ecx, [ebp+NTFS.sectors_per_cluster]
sub ecx, edx
cmp ecx, [ntfs_cur_size]
cmp ecx, [ebp+NTFS.ntfs_cur_size]
jb @f
mov ecx, [ntfs_cur_size]
mov ecx, [ebp+NTFS.ntfs_cur_size]
@@:
; ecx = number of sequential sectors to read
call hd_read
cmp [hd_error], 0
push eax
call fs_read32_sys
pop edx
test eax, eax
jnz .errread
add [ntfs_cur_read], 0x200
dec [ntfs_cur_size]
inc [ntfs_cur_offs]
add [ebp+NTFS.ntfs_cur_read], 0x200
dec [ebp+NTFS.ntfs_cur_size]
inc [ebp+NTFS.ntfs_cur_offs]
add ebx, 0x200
mov [ntfs_cur_buf], ebx
inc eax
mov [ebp+NTFS.ntfs_cur_buf], ebx
lea eax, [edx+1]
loop @b
pop ecx
xor eax, eax
xor edx, edx
cmp [ntfs_cur_size], eax
cmp [ebp+NTFS.ntfs_cur_size], eax
jz @f
add esi, 8
push eax
mov eax, [ntfs_data.mft_retrieval_end]
mov eax, [ebp+NTFS.mft_retrieval_end]
shl eax, 3
add eax, [ntfs_data.mft_retrieval]
add eax, [ebp+NTFS.mft_retrieval]
cmp eax, esi
pop eax
jz .nomft
396,6 → 510,7
.errread:
pop ecx
.errret:
mov [esp+28], eax
stc
popad
ret
402,17 → 517,16
.nomft:
; 1. Read file record.
; N.B. This will do recursive call of read_attr for $MFT::$Data.
mov eax, [ntfs_cur_iRecord]
mov [ntfs_attr_iRecord], eax
and [ntfs_attr_list], 0
or dword [ntfs_attr_size], -1
or dword [ntfs_attr_size+4], -1
or [ntfs_attr_iBaseRecord], -1
mov eax, [ebp+NTFS.ntfs_cur_iRecord]
mov [ebp+NTFS.ntfs_attr_iRecord], eax
and [ebp+NTFS.ntfs_attr_list], 0
or dword [ebp+NTFS.ntfs_attr_size], -1
or dword [ebp+NTFS.ntfs_attr_size+4], -1
or [ebp+NTFS.ntfs_attr_iBaseRecord], -1
call ntfs_read_file_record
test eax, eax
jz .errret
jc .errret
; 2. Find required attribute.
mov eax, [ntfs_data.frs_buffer]
mov eax, [ebp+NTFS.frs_buffer]
; a) For auxiliary records, read base record
; N.B. If base record is present,
; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero
422,27 → 536,26
; test eax, eax
; jz @f
.beginfindattr:
mov [ntfs_attr_iRecord], eax
mov [ebp+NTFS.ntfs_attr_iRecord], eax
call ntfs_read_file_record
test eax, eax
jz .errret
jc .errret
@@:
; b) Scan for required attribute and for $ATTR_LIST
mov eax, [ntfs_data.frs_buffer]
mov eax, [ebp+NTFS.frs_buffer]
movzx ecx, word [eax+14h]
add eax, ecx
mov ecx, [ntfs_cur_attr]
and [ntfs_attr_offs], 0
mov ecx, [ebp+NTFS.ntfs_cur_attr]
and [ebp+NTFS.ntfs_attr_offs], 0
.scanattr:
cmp dword [eax], -1
jz .scandone
cmp dword [eax], ecx
jz .okattr
cmp [ntfs_attr_iBaseRecord], -1
cmp [ebp+NTFS.ntfs_attr_iBaseRecord], -1
jnz .scancont
cmp dword [eax], 0x20 ; $ATTR_LIST
jnz .scancont
mov [ntfs_attr_list], eax
mov [ebp+NTFS.ntfs_attr_list], eax
jmp .scancont
.okattr:
; ignore named $DATA attributes (aka NTFS streams)
451,30 → 564,30
cmp byte [eax+9], 0
jnz .scancont
@@:
mov [ntfs_attr_offs], eax
mov [ebp+NTFS.ntfs_attr_offs], eax
.scancont:
add eax, [eax+4]
jmp .scanattr
.continue:
pushad
and [ntfs_cur_read], 0
and [ebp+NTFS.ntfs_cur_read], 0
.scandone:
; c) Check for required offset and length
mov ecx, [ntfs_attr_offs]
mov ecx, [ebp+NTFS.ntfs_attr_offs]
jecxz .noattr
push [ntfs_cur_size]
push [ntfs_cur_read]
push [ebp+NTFS.ntfs_cur_size]
push [ebp+NTFS.ntfs_cur_read]
call .doreadattr
pop edx
pop eax
pop ecx
jc @f
cmp [ntfs_bCanContinue], 0
cmp [ebp+NTFS.ntfs_bCanContinue], 0
jz @f
sub edx, [ntfs_cur_read]
sub edx, [ebp+NTFS.ntfs_cur_read]
neg edx
shr edx, 9
sub eax, edx
mov [ntfs_cur_size], eax
sub ecx, edx
mov [ebp+NTFS.ntfs_cur_size], ecx
jnz .not_in_cur
@@:
popad
481,13 → 594,14
ret
.noattr:
.not_in_cur:
cmp [ntfs_cur_attr], 0x20
cmp [ebp+NTFS.ntfs_cur_attr], 0x20
jz @f
mov ecx, [ntfs_attr_list]
mov ecx, [ebp+NTFS.ntfs_attr_list]
test ecx, ecx
jnz .lookattr
.ret_is_attr:
cmp [ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0
and dword [esp+28], 0
cmp [ebp+NTFS.ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0
popad
ret
.lookattr:
494,49 → 608,49
; required attribute or required offset was not found in base record;
; it may be present in auxiliary records;
; scan $ATTR_LIST
mov eax, [ntfs_attr_iBaseRecord]
mov eax, [ebp+NTFS.ntfs_attr_iBaseRecord]
cmp eax, -1
jz @f
call ntfs_read_file_record
test eax, eax
jz .errret
or [ntfs_attr_iBaseRecord], -1
jc .errret
or [ebp+NTFS.ntfs_attr_iBaseRecord], -1
@@:
push [ntfs_cur_offs]
push [ntfs_cur_size]
push [ntfs_cur_read]
push [ntfs_cur_buf]
push dword [ntfs_attr_size]
push dword [ntfs_attr_size+4]
or dword [ntfs_attr_size], -1
or dword [ntfs_attr_size+4], -1
and [ntfs_cur_offs], 0
mov [ntfs_cur_size], 2
and [ntfs_cur_read], 0
mov eax, ntfs_attrlist_buf
cmp [ntfs_cur_iRecord], 0
push [ebp+NTFS.ntfs_cur_offs]
push [ebp+NTFS.ntfs_cur_size]
push [ebp+NTFS.ntfs_cur_read]
push [ebp+NTFS.ntfs_cur_buf]
push dword [ebp+NTFS.ntfs_attr_size]
push dword [ebp+NTFS.ntfs_attr_size+4]
or dword [ebp+NTFS.ntfs_attr_size], -1
or dword [ebp+NTFS.ntfs_attr_size+4], -1
and [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 2
and [ebp+NTFS.ntfs_cur_read], 0
lea eax, [ebp+NTFS.ntfs_attrlist_buf]
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jnz @f
mov eax, ntfs_attrlist_mft_buf
lea eax, [ebp+NTFS.ntfs_attrlist_mft_buf]
@@:
mov [ntfs_cur_buf], eax
mov [ebp+NTFS.ntfs_cur_buf], eax
push eax
call .doreadattr
pop esi
mov edx, 1
pop dword [ntfs_attr_size+4]
pop dword [ntfs_attr_size]
mov ebp, [ntfs_cur_read]
pop [ntfs_cur_buf]
pop [ntfs_cur_read]
pop [ntfs_cur_size]
pop [ntfs_cur_offs]
pop dword [ebp+NTFS.ntfs_attr_size+4]
pop dword [ebp+NTFS.ntfs_attr_size]
mov ecx, [ebp+NTFS.ntfs_cur_read]
pop [ebp+NTFS.ntfs_cur_buf]
pop [ebp+NTFS.ntfs_cur_read]
pop [ebp+NTFS.ntfs_cur_size]
pop [ebp+NTFS.ntfs_cur_offs]
jc .errret
or edi, -1
lea ebp, [ebp+esi-1Ah]
lea ecx, [ecx+esi-1Ah]
.scanliststart:
mov eax, [ntfs_cur_attr]
push ecx
mov eax, [ebp+NTFS.ntfs_cur_attr]
.scanlist:
cmp esi, ebp
cmp esi, [esp]
jae .scanlistdone
cmp eax, [esi]
jz @f
555,26 → 669,28
mov eax, [esi+8]
test eax, eax
jnz .testf
mov eax, dword [ntfs_attr_size]
and eax, dword [ntfs_attr_size+4]
mov eax, dword [ebp+NTFS.ntfs_attr_size]
and eax, dword [ebp+NTFS.ntfs_attr_size+4]
cmp eax, -1
jnz .testfz
; if attribute is in auxiliary records, its size is defined only in first
mov eax, [esi+10h]
call ntfs_read_file_record
test eax, eax
jnz @f
jnc @f
.errret_pop:
pop eax
pop ecx ecx
jmp .errret
.errret2_pop:
xor eax, eax
jmp .errret_pop
@@:
mov eax, [ntfs_data.frs_buffer]
mov eax, [ebp+NTFS.frs_buffer]
movzx ecx, word [eax+14h]
add eax, ecx
mov ecx, [ntfs_cur_attr]
mov ecx, [ebp+NTFS.ntfs_cur_attr]
@@:
cmp dword [eax], -1
jz .errret_pop
jz .errret2_pop
cmp dword [eax], ecx
jz @f
.l1:
589,24 → 705,25
cmp byte [eax+8], 0
jnz .sdnores
mov eax, [eax+10h]
mov dword [ntfs_attr_size], eax
and dword [ntfs_attr_size+4], 0
mov dword [ebp+NTFS.ntfs_attr_size], eax
and dword [ebp+NTFS.ntfs_attr_size+4], 0
jmp .testfz
.sdnores:
mov ecx, [eax+30h]
mov dword [ntfs_attr_size], ecx
mov dword [ebp+NTFS.ntfs_attr_size], ecx
mov ecx, [eax+34h]
mov dword [ntfs_attr_size+4], ecx
mov dword [ebp+NTFS.ntfs_attr_size+4], ecx
.testfz:
xor eax, eax
.testf:
imul eax, [ntfs_data.sectors_per_cluster]
cmp eax, [ntfs_cur_offs]
imul eax, [ebp+NTFS.sectors_per_cluster]
cmp eax, [ebp+NTFS.ntfs_cur_offs]
pop eax
ja @f
mov edi, [esi+10h] ; keep previous iRecord
jmp .scanlistcont
@@:
pop ecx
.scanlistfound:
cmp edi, -1
jnz @f
613,30 → 730,28
popad
ret
@@:
mov eax, [ntfs_cur_iRecord]
mov [ntfs_attr_iBaseRecord], eax
mov eax, [ebp+NTFS.ntfs_cur_iRecord]
mov [ebp+NTFS.ntfs_attr_iBaseRecord], eax
mov eax, edi
jmp .beginfindattr
.sde:
popad
stc
ret
.scanlistdone:
sub ebp, ntfs_attrlist_buf-1Ah
cmp [ntfs_cur_iRecord], 0
pop ecx
sub ecx, ebp
sub ecx, NTFS.ntfs_attrlist_buf-1Ah
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jnz @f
sub ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf
sub ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf
@@:
cmp ebp, 0x400
cmp ecx, 0x400
jnz .scanlistfound
inc edx
push esi edi
mov esi, ntfs_attrlist_buf+0x200
mov edi, ntfs_attrlist_buf
cmp [ntfs_cur_iRecord], 0
lea esi, [ebp+NTFS.ntfs_attrlist_buf+0x200]
lea edi, [ebp+NTFS.ntfs_attrlist_buf]
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jnz @f
mov esi, ntfs_attrlist_mft_buf+0x200
mov edi, ntfs_attrlist_mft_buf
lea esi, [ebp+NTFS.ntfs_attrlist_mft_buf+0x200]
lea edi, [ebp+NTFS.ntfs_attrlist_mft_buf]
@@:
mov ecx, 0x200/4
rep movsd
643,43 → 758,43
mov eax, edi
pop edi esi
sub esi, 0x200
push [ntfs_cur_offs]
push [ntfs_cur_size]
push [ntfs_cur_read]
push [ntfs_cur_buf]
push dword [ntfs_attr_size]
push dword [ntfs_attr_size+4]
or dword [ntfs_attr_size], -1
or dword [ntfs_attr_size+4], -1
mov [ntfs_cur_offs], edx
mov [ntfs_cur_size], 1
and [ntfs_cur_read], 0
mov [ntfs_cur_buf], eax
mov ecx, [ntfs_attr_list]
push esi edx
push [ebp+NTFS.ntfs_cur_offs]
push [ebp+NTFS.ntfs_cur_size]
push [ebp+NTFS.ntfs_cur_read]
push [ebp+NTFS.ntfs_cur_buf]
push dword [ebp+NTFS.ntfs_attr_size]
push dword [ebp+NTFS.ntfs_attr_size+4]
or dword [ebp+NTFS.ntfs_attr_size], -1
or dword [ebp+NTFS.ntfs_attr_size+4], -1
mov [ebp+NTFS.ntfs_cur_offs], edx
mov [ebp+NTFS.ntfs_cur_size], 1
and [ebp+NTFS.ntfs_cur_read], 0
mov [ebp+NTFS.ntfs_cur_buf], eax
mov ecx, [ebp+NTFS.ntfs_attr_list]
push esi edx edi
call .doreadattr
pop edx esi
mov ebp, [ntfs_cur_read]
pop dword [ntfs_attr_size+4]
pop dword [ntfs_attr_size]
pop [ntfs_cur_buf]
pop [ntfs_cur_read]
pop [ntfs_cur_size]
pop [ntfs_cur_offs]
pop edi edx esi
mov ecx, [ebp+NTFS.ntfs_cur_read]
pop dword [ebp+NTFS.ntfs_attr_size+4]
pop dword [ebp+NTFS.ntfs_attr_size]
pop [ebp+NTFS.ntfs_cur_buf]
pop [ebp+NTFS.ntfs_cur_read]
pop [ebp+NTFS.ntfs_cur_size]
pop [ebp+NTFS.ntfs_cur_offs]
jc .errret
add ebp, ntfs_attrlist_buf+0x200-0x1A
cmp [ntfs_cur_iRecord], 0
lea ecx, [ecx+ebp+NTFS.ntfs_attrlist_buf+0x200-0x1A]
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jnz .scanliststart
add ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf
add ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf
jmp .scanliststart
 
.doreadattr:
mov [ntfs_bCanContinue], 0
mov [ebp+NTFS.ntfs_bCanContinue], 0
cmp byte [ecx+8], 0
jnz .nonresident
mov eax, [ecx+10h] ; length
mov esi, eax
mov edx, [ntfs_cur_offs]
mov edx, [ebp+NTFS.ntfs_cur_offs]
shr eax, 9
cmp eax, edx
jb .okret
688,7 → 803,7
movzx eax, word [ecx+14h]
add edx, eax
add edx, ecx ; edx -> data
mov eax, [ntfs_cur_size]
mov eax, [ebp+NTFS.ntfs_cur_size]
cmp eax, (0xFFFFFFFF shr 9)+1
jbe @f
mov eax, (0xFFFFFFFF shr 9)+1
699,17 → 814,17
mov eax, esi
@@:
; eax = length, edx -> data
mov [ntfs_cur_read], eax
mov [ebp+NTFS.ntfs_cur_read], eax
mov ecx, eax
mov eax, edx
mov ebx, [ntfs_cur_buf]
mov ebx, [ebp+NTFS.ntfs_cur_buf]
call memmove
and [ntfs_cur_size], 0 ; CF=0
and [ebp+NTFS.ntfs_cur_size], 0 ; CF=0
ret
.nonresident:
; Not all auxiliary records contain correct FileSize info
mov eax, dword [ntfs_attr_size]
mov edx, dword [ntfs_attr_size+4]
mov eax, dword [ebp+NTFS.ntfs_attr_size]
mov edx, dword [ebp+NTFS.ntfs_attr_size+4]
push eax
and eax, edx
cmp eax, -1
717,34 → 832,34
jnz @f
mov eax, [ecx+30h] ; FileSize
mov edx, [ecx+34h]
mov dword [ntfs_attr_size], eax
mov dword [ntfs_attr_size+4], edx
mov dword [ebp+NTFS.ntfs_attr_size], eax
mov dword [ebp+NTFS.ntfs_attr_size+4], edx
@@:
add eax, 0x1FF
adc edx, 0
shrd eax, edx, 9
sub eax, [ntfs_cur_offs]
sub eax, [ebp+NTFS.ntfs_cur_offs]
ja @f
; return with nothing read
and [ntfs_cur_size], 0
and [ebp+NTFS.ntfs_cur_size], 0
.okret:
clc
ret
@@:
; reduce read length
and [ntfs_cur_tail], 0
cmp [ntfs_cur_size], eax
and [ebp+NTFS.ntfs_cur_tail], 0
cmp [ebp+NTFS.ntfs_cur_size], eax
jb @f
mov [ntfs_cur_size], eax
mov eax, dword [ntfs_attr_size]
mov [ebp+NTFS.ntfs_cur_size], eax
mov eax, dword [ebp+NTFS.ntfs_attr_size]
and eax, 0x1FF
mov [ntfs_cur_tail], eax
mov [ebp+NTFS.ntfs_cur_tail], eax
@@:
cmp [ntfs_cur_size], 0
cmp [ebp+NTFS.ntfs_cur_size], 0
jz .okret
mov eax, [ntfs_cur_offs]
mov eax, [ebp+NTFS.ntfs_cur_offs]
xor edx, edx
div [ntfs_data.sectors_per_cluster]
div [ebp+NTFS.sectors_per_cluster]
sub eax, [ecx+10h] ; first_vbo
jb .okret
; eax = cluster, edx = starting sector
751,51 → 866,60
sub esp, 10h
movzx esi, word [ecx+20h] ; mcb_info_ofs
add esi, ecx
xor ebp, ebp
xor edi, edi
.readloop:
call ntfs_decode_mcb_entry
jnc .break
add ebp, [esp+8]
add edi, [esp+8]
sub eax, [esp]
jae .readloop
push ecx
push eax
add eax, [esp+8]
add eax, ebp
imul eax, [ntfs_data.sectors_per_cluster]
add eax, edi
imul eax, [ebp+NTFS.sectors_per_cluster]
add eax, edx
add eax, [PARTITION_START]
pop ecx
neg ecx
imul ecx, [ntfs_data.sectors_per_cluster]
imul ecx, [ebp+NTFS.sectors_per_cluster]
sub ecx, edx
cmp ecx, [ntfs_cur_size]
cmp ecx, [ebp+NTFS.ntfs_cur_size]
jb @f
mov ecx, [ntfs_cur_size]
mov ecx, [ebp+NTFS.ntfs_cur_size]
@@:
mov ebx, [ntfs_cur_buf]
mov ebx, [ebp+NTFS.ntfs_cur_buf]
@@:
call hd_read
cmp [hd_error], 0
push eax
cmp [ebp+NTFS.ntfs_cur_attr], 0x80
jnz .sys
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jz .sys
call fs_read32_app
jmp .appsys
.sys:
call fs_read32_sys
.appsys:
pop edx
test eax, eax
jnz .errread2
add ebx, 0x200
mov [ntfs_cur_buf], ebx
inc eax
add [ntfs_cur_read], 0x200
dec [ntfs_cur_size]
inc [ntfs_cur_offs]
mov [ebp+NTFS.ntfs_cur_buf], ebx
lea eax, [edx+1]
add [ebp+NTFS.ntfs_cur_read], 0x200
dec [ebp+NTFS.ntfs_cur_size]
inc [ebp+NTFS.ntfs_cur_offs]
loop @b
pop ecx
xor eax, eax
xor edx, edx
cmp [ntfs_cur_size], 0
cmp [ebp+NTFS.ntfs_cur_size], 0
jnz .readloop
add esp, 10h
mov eax, [ntfs_cur_tail]
mov eax, [ebp+NTFS.ntfs_cur_tail]
test eax, eax
jz @f
sub eax, 0x200
add [ntfs_cur_read], eax
add [ebp+NTFS.ntfs_cur_read], eax
@@:
clc
ret
806,58 → 930,57
ret
.break:
add esp, 10h ; CF=0
mov [ntfs_bCanContinue], 1
mov [ebp+NTFS.ntfs_bCanContinue], 1
ret
 
ntfs_read_file_record:
; in: eax=iRecord
; out: [ntfs_data.frs_buffer] contains information
; eax=0 - failed, eax=1 - success
; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size]
; out: [ebp+NTFS.frs_buffer] contains information
; CF=1 - failed, in this case eax=0 => something with FS, eax nonzero => disk error
; Read attr $DATA of $Mft, starting from eax*[ebp+NTFS.frs_size]
push ecx edx
mov ecx, [ntfs_data.frs_size]
mov ecx, [ebp+NTFS.frs_size]
mul ecx
shrd eax, edx, 9
shr edx, 9
jnz .err
push [ntfs_attr_iRecord]
push [ntfs_attr_iBaseRecord]
push [ntfs_attr_offs]
push [ntfs_attr_list]
push dword [ntfs_attr_size+4]
push dword [ntfs_attr_size]
push [ntfs_cur_iRecord]
push [ntfs_cur_attr]
push [ntfs_cur_offs]
push [ntfs_cur_size]
push [ntfs_cur_buf]
push [ntfs_cur_read]
mov [ntfs_cur_attr], 0x80 ; $DATA
and [ntfs_cur_iRecord], 0 ; $Mft
mov [ntfs_cur_offs], eax
jnz .errret
push [ebp+NTFS.ntfs_attr_iRecord]
push [ebp+NTFS.ntfs_attr_iBaseRecord]
push [ebp+NTFS.ntfs_attr_offs]
push [ebp+NTFS.ntfs_attr_list]
push dword [ebp+NTFS.ntfs_attr_size+4]
push dword [ebp+NTFS.ntfs_attr_size]
push [ebp+NTFS.ntfs_cur_iRecord]
push [ebp+NTFS.ntfs_cur_attr]
push [ebp+NTFS.ntfs_cur_offs]
push [ebp+NTFS.ntfs_cur_size]
push [ebp+NTFS.ntfs_cur_buf]
push [ebp+NTFS.ntfs_cur_read]
mov [ebp+NTFS.ntfs_cur_attr], 0x80 ; $DATA
and [ebp+NTFS.ntfs_cur_iRecord], 0 ; $Mft
mov [ebp+NTFS.ntfs_cur_offs], eax
shr ecx, 9
mov [ntfs_cur_size], ecx
mov eax, [ntfs_data.frs_buffer]
mov [ntfs_cur_buf], eax
mov [ebp+NTFS.ntfs_cur_size], ecx
mov eax, [ebp+NTFS.frs_buffer]
mov [ebp+NTFS.ntfs_cur_buf], eax
call ntfs_read_attr
mov eax, [ntfs_cur_read]
pop [ntfs_cur_read]
pop [ntfs_cur_buf]
pop [ntfs_cur_size]
pop [ntfs_cur_offs]
pop [ntfs_cur_attr]
pop [ntfs_cur_iRecord]
pop dword [ntfs_attr_size]
pop dword [ntfs_attr_size+4]
pop [ntfs_attr_list]
pop [ntfs_attr_offs]
pop [ntfs_attr_iBaseRecord]
pop [ntfs_attr_iRecord]
pop edx ecx
jc .errret
cmp eax, [ntfs_data.frs_size]
mov edx, [ebp+NTFS.ntfs_cur_read]
pop [ebp+NTFS.ntfs_cur_read]
pop [ebp+NTFS.ntfs_cur_buf]
pop [ebp+NTFS.ntfs_cur_size]
pop [ebp+NTFS.ntfs_cur_offs]
pop [ebp+NTFS.ntfs_cur_attr]
pop [ebp+NTFS.ntfs_cur_iRecord]
pop dword [ebp+NTFS.ntfs_attr_size]
pop dword [ebp+NTFS.ntfs_attr_size+4]
pop [ebp+NTFS.ntfs_attr_list]
pop [ebp+NTFS.ntfs_attr_offs]
pop [ebp+NTFS.ntfs_attr_iBaseRecord]
pop [ebp+NTFS.ntfs_attr_iRecord]
jc .ret
cmp edx, [ebp+NTFS.frs_size]
jnz .errret
mov eax, [ntfs_data.frs_buffer]
mov eax, [ebp+NTFS.frs_buffer]
cmp dword [eax], 'FILE'
jnz .errret
push ebx
864,18 → 987,18
mov ebx, eax
call ntfs_restore_usa_frs
pop ebx
setnc al
movzx eax, al
jc .errret
.ret:
pop edx ecx
ret
.err:
.errret:
pop edx ecx
.errret:
xor eax, eax
stc
ret
 
ntfs_restore_usa_frs:
mov eax, [ntfs_data.frs_size]
mov eax, [ebp+NTFS.frs_size]
ntfs_restore_usa:
pushad
shr eax, 9
955,82 → 1078,83
ret
 
ntfs_find_lfn:
; in: esi+ebp -> name
; in: esi+[esp+4] -> name
; out: CF=1 - file not found
; else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory
mov [ntfs_cur_iRecord], 5 ; start parse from root cluster
; else CF=0, [ebp+NTFS.ntfs_cur_iRecord] valid, eax->record in parent directory
mov [ebp+NTFS.ntfs_cur_iRecord], 5 ; start parse from root cluster
.doit2:
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT
and [ntfs_cur_offs], 0
mov eax, [ntfs_data.cur_index_size]
mov [ntfs_cur_size], eax
mov eax, [ntfs_data.cur_index_buf]
mov [ntfs_cur_buf], eax
mov [ebp+NTFS.ntfs_cur_attr], 0x90 ; $INDEX_ROOT
and [ebp+NTFS.ntfs_cur_offs], 0
mov eax, [ebp+NTFS.cur_index_size]
mov [ebp+NTFS.ntfs_cur_size], eax
mov eax, [ebp+NTFS.cur_index_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax
call ntfs_read_attr
jnc @f
.ret:
ret
ret 4
@@:
cmp [ntfs_cur_read], 0x20
xor eax, eax
cmp [ebp+NTFS.ntfs_cur_read], 0x20
jc .ret
pushad
mov esi, [ntfs_data.cur_index_buf]
mov esi, [ebp+NTFS.cur_index_buf]
mov eax, [esi+14h]
add eax, 10h
cmp [ntfs_cur_read], eax
cmp [ebp+NTFS.ntfs_cur_read], eax
jae .readok1
add eax, 1FFh
shr eax, 9
cmp eax, [ntfs_data.cur_index_size]
cmp eax, [ebp+NTFS.cur_index_size]
ja @f
.stc_ret:
popad
stc
ret
ret 4
@@:
; reallocate
push eax
push [ntfs_data.cur_index_buf]
push [ebp+NTFS.cur_index_buf]
call kernel_free
pop eax
mov [ntfs_data.cur_index_size], eax
mov [ebp+NTFS.cur_index_size], eax
push eax
call kernel_alloc
test eax, eax
jnz @f
and [ntfs_data.cur_index_size], 0
and [ntfs_data.cur_index_buf], 0
and [ebp+NTFS.cur_index_size], 0
and [ebp+NTFS.cur_index_buf], 0
jmp .stc_ret
@@:
mov [ntfs_data.cur_index_buf], eax
mov [ebp+NTFS.cur_index_buf], eax
popad
jmp .doit2
.readok1:
mov ebp, [esi+8] ; subnode_size
shr ebp, 9
cmp ebp, [ntfs_data.cur_index_size]
mov edx, [esi+8] ; subnode_size
shr edx, 9
cmp edx, [ebp+NTFS.cur_index_size]
jbe .ok2
push esi ebp
push ebp
push esi edx
push edx
call kernel_alloc
pop ebp esi
pop edx esi
test eax, eax
jz .stc_ret
mov edi, eax
mov ecx, [ntfs_data.cur_index_size]
mov ecx, [ebp+NTFS.cur_index_size]
shl ecx, 9-2
rep movsd
mov esi, eax
mov [ntfs_data.cur_index_size], ebp
push esi ebp
push [ntfs_data.cur_index_buf]
mov [ebp+NTFS.cur_index_size], edx
push esi edx
push [ebp+NTFS.cur_index_buf]
call kernel_free
pop ebp esi
mov [ntfs_data.cur_index_buf], esi
pop edx esi
mov [ebp+NTFS.cur_index_buf], esi
.ok2:
add esi, 10h
mov edi, [esp+4]
; edi -> name, esi -> current index data, ebp = subnode size
; edi -> name, esi -> current index data, edx = subnode size
.scanloop:
add esi, [esi]
.scanloopint:
1070,17 → 1194,19
jz .notfound
movzx eax, word [esi+8]
mov eax, [esi+eax-8]
mul [ntfs_data.sectors_per_cluster]
mov [ntfs_cur_offs], eax
mov [ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION
mov [ntfs_cur_size], ebp
mov eax, [ntfs_data.cur_index_buf]
imul eax, [ebp+NTFS.sectors_per_cluster]
mov [ebp+NTFS.ntfs_cur_offs], eax
mov [ebp+NTFS.ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION
mov [ebp+NTFS.ntfs_cur_size], edx
mov eax, [ebp+NTFS.cur_index_buf]
mov esi, eax
mov [ntfs_cur_buf], eax
mov [ebp+NTFS.ntfs_cur_buf], eax
push edx
call ntfs_read_attr
mov eax, ebp
pop edx
mov eax, edx
shl eax, 9
cmp [ntfs_cur_read], eax
cmp [ebp+NTFS.ntfs_cur_read], eax
jnz .notfound
cmp dword [esi], 'INDX'
jnz .notfound
1092,7 → 1218,7
.notfound:
popad
stc
ret
ret 4
.found:
cmp byte [edi], 0
jz .done
1106,7 → 1232,7
pop esi
pop esi
mov eax, [esi]
mov [ntfs_cur_iRecord], eax
mov [ebp+NTFS.ntfs_cur_iRecord], eax
mov [esp+1Ch], esi
mov [esp+4], edi
popad
1113,29 → 1239,22
inc esi
cmp byte [esi-1], 0
jnz .doit2
test ebp, ebp
cmp dword [esp+4], 0
jz @f
mov esi, ebp
xor ebp, ebp
mov esi, [esp+4]
mov dword [esp+4], 0
jmp .doit2
@@:
ret
ret 4
 
;----------------------------------------------------------------
;
; ntfs_HdRead - read NTFS hard disk
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdRead:
; ntfs_Read - NTFS implementation of reading a file
; in: ebp = pointer to NTFS structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
ntfs_Read:
cmp byte [esi], 0
jnz @f
or ebx, -1
1142,17 → 1261,20
movi eax, ERROR_ACCESS_DENIED
ret
@@:
call ntfs_find_lfn
call ntfs_lock
stdcall ntfs_find_lfn, [esp+4]
jnc .found
call ntfs_unlock
or ebx, -1
movi eax, ERROR_FILE_NOT_FOUND
ret
.found:
mov [ntfs_cur_attr], 0x80 ; $DATA
and [ntfs_cur_offs], 0
and [ntfs_cur_size], 0
mov [ebp+NTFS.ntfs_cur_attr], 0x80 ; $DATA
and [ebp+NTFS.ntfs_cur_offs], 0
and [ebp+NTFS.ntfs_cur_size], 0
call ntfs_read_attr
jnc @f
call ntfs_unlock
or ebx, -1
movi eax, ERROR_ACCESS_DENIED
ret
1160,9 → 1282,7
pushad
and dword [esp+10h], 0
xor eax, eax
test ebx, ebx
jz .zero1
cmp dword [ebx+4], 0x200
cmp dword [ebx+8], 0x200
jb @f
.eof0:
popad
1169,23 → 1289,29
xor ebx, ebx
.eof:
movi eax, ERROR_END_OF_FILE
push eax
call ntfs_unlock
pop eax
ret
@@:
mov eax, [ebx]
mov ecx, [ebx+12]
mov edx, [ebx+16]
mov eax, [ebx+4]
test eax, 0x1FF
jz .alignedstart
push edx
mov edx, [ebx+4]
mov edx, [ebx+8]
shrd eax, edx, 9
pop edx
mov [ntfs_cur_offs], eax
mov [ntfs_cur_size], 1
mov [ntfs_cur_buf], ntfs_bitmap_buf
mov [ebp+NTFS.ntfs_cur_offs], eax
mov [ebp+NTFS.ntfs_cur_size], 1
lea eax, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax
call ntfs_read_attr.continue
mov eax, [ebx]
mov eax, [ebx+4]
and eax, 0x1FF
lea esi, [ntfs_bitmap_buf+eax]
sub eax, [ntfs_cur_read]
lea esi, [ebp+NTFS.ntfs_bitmap_buf+eax]
sub eax, [ebp+NTFS.ntfs_cur_read]
jae .eof0
neg eax
push ecx
1202,115 → 1328,113
jnz @f
.retok:
popad
call ntfs_unlock
xor eax, eax
ret
@@:
cmp [ntfs_cur_read], 0x200
cmp [ebp+NTFS.ntfs_cur_read], 0x200
jz .alignedstart
.eof_ebx:
popad
jmp .eof
.alignedstart:
mov eax, [ebx]
mov eax, [ebx+4]
push edx
mov edx, [ebx+4]
mov edx, [ebx+8]
add eax, 511
adc edx, 0
shrd eax, edx, 9
pop edx
.zero1:
mov [ntfs_cur_offs], eax
mov [ntfs_cur_buf], edx
mov [ebp+NTFS.ntfs_cur_offs], eax
mov [ebp+NTFS.ntfs_cur_buf], edx
mov eax, ecx
shr eax, 9
mov [ntfs_cur_size], eax
add eax, [ntfs_cur_offs]
mov [ebp+NTFS.ntfs_cur_size], eax
add eax, [ebp+NTFS.ntfs_cur_offs]
push eax
call ntfs_read_attr.continue
pop [ntfs_cur_offs]
mov eax, [ntfs_cur_read]
pop [ebp+NTFS.ntfs_cur_offs]
mov eax, [ebp+NTFS.ntfs_cur_read]
add [esp+10h], eax
mov eax, ecx
and eax, not 0x1FF
cmp [ntfs_cur_read], eax
cmp [ebp+NTFS.ntfs_cur_read], eax
jnz .eof_ebx
and ecx, 0x1FF
jz .retok
add edx, [ntfs_cur_read]
mov [ntfs_cur_size], 1
mov [ntfs_cur_buf], ntfs_bitmap_buf
add edx, [ebp+NTFS.ntfs_cur_read]
mov [ebp+NTFS.ntfs_cur_size], 1
lea eax, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax
call ntfs_read_attr.continue
cmp [ntfs_cur_read], ecx
cmp [ebp+NTFS.ntfs_cur_read], ecx
jb @f
mov [ntfs_cur_read], ecx
mov [ebp+NTFS.ntfs_cur_read], ecx
@@:
xchg ecx, [ntfs_cur_read]
xchg ecx, [ebp+NTFS.ntfs_cur_read]
push ecx
mov edi, edx
mov esi, ntfs_bitmap_buf
lea esi, [ebp+NTFS.ntfs_bitmap_buf]
add [esp+10h+4], ecx
rep movsb
pop ecx
xor eax, eax
cmp ecx, [ntfs_cur_read]
cmp ecx, [ebp+NTFS.ntfs_cur_read]
jz @f
mov al, ERROR_END_OF_FILE
@@:
mov [esp+1Ch], eax
call ntfs_unlock
popad
ret
 
;----------------------------------------------------------------
;
; ntfs_HdReadFolder - read NTFS hard disk folder
;
; esi points to filename
; ebx pointer to structure 32-bit number = first wanted block, 0+
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = blocks read or 0xffffffff folder not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdReadFolder:
; ntfs_ReadFolder - NTFS implementation of reading a folder
; in: ebp = pointer to NTFS structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
ntfs_ReadFolder:
call ntfs_lock
mov eax, 5 ; root cluster
cmp byte [esi], 0
jz .doit
call ntfs_find_lfn
stdcall ntfs_find_lfn, [esp+4]
jnc .doit2
.notfound:
or ebx, -1
push ERROR_FILE_NOT_FOUND
.pop_ret:
call ntfs_unlock
pop eax
ret
.doit:
mov [ntfs_cur_iRecord], eax
mov [ebp+NTFS.ntfs_cur_iRecord], eax
.doit2:
mov [ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION
and [ntfs_cur_offs], 0
mov [ntfs_cur_size], 1
mov [ntfs_cur_buf], ntfs_bitmap_buf
mov [ebp+NTFS.ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION
and [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 1
lea eax, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax
call ntfs_read_attr
jc .notfound
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT
and [ntfs_cur_offs], 0
mov eax, [ntfs_data.cur_index_size]
mov [ntfs_cur_size], eax
mov eax, [ntfs_data.cur_index_buf]
mov [ntfs_cur_buf], eax
mov [ebp+NTFS.ntfs_cur_attr], 0x90 ; $INDEX_ROOT
and [ebp+NTFS.ntfs_cur_offs], 0
mov eax, [ebp+NTFS.cur_index_size]
mov [ebp+NTFS.ntfs_cur_size], eax
mov eax, [ebp+NTFS.cur_index_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax
call ntfs_read_attr
jnc .ok
cmp [hd_error], 0
test eax, eax
jz .notfound
or ebx, -1
push 11
jmp .pop_ret
.ok:
cmp [ntfs_cur_read], 0x20
cmp [ebp+NTFS.ntfs_cur_read], 0x20
jae @f
or ebx, -1
.fserr:
1318,14 → 1442,14
jmp .pop_ret
@@:
pushad
mov esi, [ntfs_data.cur_index_buf]
mov esi, [ebp+NTFS.cur_index_buf]
mov eax, [esi+14h]
add eax, 10h
cmp [ntfs_cur_read], eax
cmp [ebp+NTFS.ntfs_cur_read], eax
jae .readok1
add eax, 1FFh
shr eax, 9
cmp eax, [ntfs_data.cur_index_size]
cmp eax, [ebp+NTFS.cur_index_size]
ja @f
popad
jmp .fserr
1332,53 → 1456,51
@@:
; reallocate
push eax
push [ntfs_data.cur_index_buf]
push [ebp+NTFS.cur_index_buf]
call kernel_free
pop eax
mov [ntfs_data.cur_index_size], eax
mov [ebp+NTFS.cur_index_size], eax
push eax
call kernel_alloc
test eax, eax
jnz @f
and [ntfs_data.cur_index_size], 0
and [ntfs_data.cur_index_buf], 0
and [ebp+NTFS.cur_index_size], 0
and [ebp+NTFS.cur_index_buf], 0
.nomem:
call ntfs_unlock
popad
or ebx, -1
movi eax, 12
ret
@@:
mov [ntfs_data.cur_index_buf], eax
mov [ebp+NTFS.cur_index_buf], eax
popad
jmp .doit2
.readok1:
mov ebp, [esi+8] ; subnode_size
shr ebp, 9
cmp ebp, [ntfs_data.cur_index_size]
mov edx, [esi+8] ; subnode_size
shr edx, 9
mov [ebp+NTFS.cur_subnode_size], edx
cmp edx, [ebp+NTFS.cur_index_size]
jbe .ok2
push esi ebp
push ebp
push esi edx
push edx
call kernel_alloc
pop ebp esi
pop edx esi
test eax, eax
jz .nomem
mov edi, eax
mov ecx, [ntfs_data.cur_index_size]
mov ecx, [ebp+NTFS.cur_index_size]
shl ecx, 9-2
rep movsd
mov esi, eax
mov [ntfs_data.cur_index_size], ebp
push esi ebp
push [ntfs_data.cur_index_buf]
mov [ebp+NTFS.cur_index_size], edx
push [ebp+NTFS.cur_index_buf]
call kernel_free
pop ebp esi
mov [ntfs_data.cur_index_buf], esi
mov [ebp+NTFS.cur_index_buf], esi
.ok2:
add esi, 10h
mov ebx, [esp+10h]
mov edx, [esp+14h]
push dword [ebx+4] ; read ANSI/UNICODE name
mov ebx, [ebx]
mov edx, [ebx+16]
push dword [ebx+8] ; read ANSI/UNICODE name
; init header
mov edi, edx
mov ecx, 32/4
1385,13 → 1507,14
xor eax, eax
rep stosd
mov byte [edx], 1 ; version
mov ecx, [esp+4+18h]
mov ecx, [ebx+12]
mov ebx, [ebx+4]
push edx
mov edx, esp
; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block,
; edi -> BDFE, esi -> current index data, ebx = first wanted block,
; ecx = number of blocks to read
; edx -> parameters block: dd <output>, dd <flags>
cmp [ntfs_cur_iRecord], 5
cmp [ebp+NTFS.ntfs_cur_iRecord], 5
jz .skip_specials
; dot and dotdot entries
push esi
1413,38 → 1536,39
.dump_root_done:
; now dump all subnodes
push ecx edi
mov edi, ntfs_bitmap_buf
mov [ntfs_cur_buf], edi
lea edi, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], edi
mov ecx, 0x400/4
xor eax, eax
rep stosd
mov [ntfs_cur_attr], 0xB0 ; $BITMAP
and [ntfs_cur_offs], 0
mov [ntfs_cur_size], 2
mov [ebp+NTFS.ntfs_cur_attr], 0xB0 ; $BITMAP
and [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 2
call ntfs_read_attr
pop edi ecx
push 0 ; save offset in $BITMAP attribute
and [ntfs_cur_offs], 0
and [ebp+NTFS.ntfs_cur_offs], 0
.dumploop:
mov [ntfs_cur_attr], 0xA0
mov [ntfs_cur_size], ebp
mov eax, [ntfs_data.cur_index_buf]
mov [ebp+NTFS.ntfs_cur_attr], 0xA0
mov eax, [ebp+NTFS.cur_subnode_size]
mov [ebp+NTFS.ntfs_cur_size], eax
mov eax, [ebp+NTFS.cur_index_buf]
mov esi, eax
mov [ntfs_cur_buf], eax
push [ntfs_cur_offs]
mov eax, [ntfs_cur_offs]
imul eax, ebp
mov [ntfs_cur_offs], eax
mov [ebp+NTFS.ntfs_cur_buf], eax
push [ebp+NTFS.ntfs_cur_offs]
mov eax, [ebp+NTFS.ntfs_cur_offs]
imul eax, [ebp+NTFS.cur_subnode_size]
mov [ebp+NTFS.ntfs_cur_offs], eax
call ntfs_read_attr
pop [ntfs_cur_offs]
mov eax, ebp
pop [ebp+NTFS.ntfs_cur_offs]
mov eax, [ebp+NTFS.cur_subnode_size]
shl eax, 9
cmp [ntfs_cur_read], eax
cmp [ebp+NTFS.ntfs_cur_read], eax
jnz .done
push eax
mov eax, [ntfs_cur_offs]
mov eax, [ebp+NTFS.ntfs_cur_offs]
and eax, 0x400*8-1
bt dword [ntfs_bitmap_buf], eax
bt dword [ebp+NTFS.ntfs_bitmap_buf], eax
pop eax
jnc .dump_subnode_done
cmp dword [esi], 'INDX'
1464,26 → 1588,26
add esi, eax
jmp .dump_subnode
.dump_subnode_done:
inc [ntfs_cur_offs]
test [ntfs_cur_offs], 0x400*8-1
inc [ebp+NTFS.ntfs_cur_offs]
test [ebp+NTFS.ntfs_cur_offs], 0x400*8-1
jnz .dumploop
mov [ntfs_cur_attr], 0xB0
mov [ebp+NTFS.ntfs_cur_attr], 0xB0
push ecx edi
mov edi, ntfs_bitmap_buf
mov [ntfs_cur_buf], edi
lea edi, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], edi
mov ecx, 0x400/4
xor eax, eax
rep stosd
pop edi ecx
pop eax
push [ntfs_cur_offs]
push [ebp+NTFS.ntfs_cur_offs]
inc eax
mov [ntfs_cur_offs], eax
mov [ntfs_cur_size], 2
mov [ebp+NTFS.ntfs_cur_offs], eax
mov [ebp+NTFS.ntfs_cur_size], 2
push eax
call ntfs_read_attr
pop eax
pop [ntfs_cur_offs]
pop [ebp+NTFS.ntfs_cur_offs]
push eax
jmp .dumploop
.done:
1498,6 → 1622,7
@@:
mov [esp+1Ch], eax
mov [esp+10h], ebx
call ntfs_unlock
popad
ret
 
1517,14 → 1642,14
stosd
scasd
push edx
mov eax, dword [ntfs_bitmap_buf]
mov edx, dword [ntfs_bitmap_buf+4]
mov eax, dword [ebp+NTFS.ntfs_bitmap_buf]
mov edx, dword [ebp+NTFS.ntfs_bitmap_buf+4]
call ntfs_datetime_to_bdfe
mov eax, dword [ntfs_bitmap_buf+0x18]
mov edx, dword [ntfs_bitmap_buf+0x1C]
mov eax, dword [ebp+NTFS.ntfs_bitmap_buf+0x18]
mov edx, dword [ebp+NTFS.ntfs_bitmap_buf+0x1C]
call ntfs_datetime_to_bdfe
mov eax, dword [ntfs_bitmap_buf+8]
mov edx, dword [ntfs_bitmap_buf+0xC]
mov eax, dword [ebp+NTFS.ntfs_bitmap_buf+8]
mov edx, dword [ebp+NTFS.ntfs_bitmap_buf+0xC]
call ntfs_datetime_to_bdfe
pop edx
xor eax, eax
1733,90 → 1858,69
ret
 
;----------------------------------------------------------------
;
; ntfs_HdRewrite - write to NTFS hard disk
;
; esi points to filename
; ebx ignored (reserved)
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = number of written bytes
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdRewrite:
; ntfs_Rewrite - NTFS implementation of creating a new file
; in: ebp = pointer to NTFS structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
ntfs_Rewrite:
ntfs_CreateFolder:
xor ebx, ebx
mov eax, ERROR_UNSUPPORTED_FS
ret
 
;----------------------------------------------------------------
;
; ntfs_HdWrite - write to NTFS hard disk
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = bytes written (maybe 0)
; eax = 0 ok write or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdWrite:
; ntfs_Write - NTFS implementation of writing to file
; in: ebp = pointer to NTFS structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
ntfs_Write:
xor ebx, ebx
mov eax, ERROR_UNSUPPORTED_FS
ret
 
;----------------------------------------------------------------
;
; ntfs_HdSetFileEnd - set end of file on NTFS hard disk
;
; esi points to filename
; ebx points to 64-bit number = new file size
; ecx ignored (reserved)
; edx ignored (reserved)
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdSetFileEnd:
ntfs_HdSetFileInfo:
;----------------------------------------------------------------
;
; ntfs_HdDelete - delete file or empty folder from NTFS hard disk
;
; esi points to filename
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdDelete:
ntfs_SetFileEnd:
ntfs_SetFileInfo:
ntfs_Delete:
mov eax, ERROR_UNSUPPORTED_FS
ret
 
ntfs_HdGetFileInfo:
;----------------------------------------------------------------
; ntfs_GetFileInfo - NTFS implementation of getting file info
; in: ebp = pointer to NTFS structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
ntfs_GetFileInfo:
cmp byte [esi], 0
jnz @f
movi eax, 2
ret
@@:
call ntfs_find_lfn
call ntfs_lock
stdcall ntfs_find_lfn, [esp+4]
jnc .doit
test eax, eax
movi eax, ERROR_FILE_NOT_FOUND
cmp [hd_error], 0
jz @f
mov al, 11
@@:
push eax
call ntfs_unlock
pop eax
ret
.doit:
push esi edi
mov esi, eax
mov edi, edx
mov edi, [ebx+16]
xor eax, eax
call ntfs_direntry_to_bdfe
pop edi esi
call ntfs_unlock
xor eax, eax
ret