Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3907 → Rev 3908

/kernel/branches/Kolibri-acpi/fs/ext2.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; 02.02.2010 turbanoff - support 70.5 ;;
;; 23.01.2010 turbanoff - support 70.0 70.1 ;;
177,14 → 177,50
ei_unused dw ? ;RUS: зарезервировано ;ENG: reserved
ends
 
ext2_test_superblock:
cmp [fs_type], 0x83
jne .no
struct EXTFS PARTITION
Lock MUTEX
log_block_size dd ?
block_size dd ?
count_block_in_block dd ?
blocks_per_group dd ?
global_desc_table dd ?
root_inode dd ? ; pointer to root inode in memory
inode_size dd ?
count_pointer_in_block dd ? ; block_size / 4
count_pointer_in_block_square dd ? ; (block_size / 4)**2
ext2_save_block dd ? ;RUS: блок на глобальную 1 процедуру ;ENG: block for 1 global procedure
ext2_temp_block dd ? ;RUS: блок для мелких процедур ;ENG: block for small procedures
ext2_save_inode dd ? ;RUS: inode на глобальную процедуру ;ENG: inode for global procedure
ext2_temp_inode dd ? ;RUS: inode для мелких процедур ;ENG: inode for small procedures
groups_count dd ?
superblock rd 512/4
ends
 
mov eax, [PARTITION_START]
add eax, 2 ;superblock start at 1024b
call hd_read
iglobal
align 4
ext2_user_functions:
dd ext2_free
dd (ext2_user_functions_end - ext2_user_functions - 4) / 4
dd ext2_Read
dd ext2_ReadFolder
dd ext2_Rewrite
dd ext2_Write
dd ext2_SetFileEnd
dd ext2_GetFileInfo
dd ext2_SetFileInfo
dd 0
dd ext2_Delete
dd ext2_CreateFolder
ext2_user_functions_end:
endg
 
proc ext2_create_partition
push ebx
 
mov eax, 2 ;superblock start at 1024b
add ebx, 512 ; get pointer to fs-specific buffer
call fs_read32_sys
 
cmp [ebx + EXT2_SB_STRUC.log_block_size], 3 ;0,1,2,3
ja .no
cmp [ebx + EXT2_SB_STRUC.magic], 0xEF53
198,27 → 234,41
test eax, EXT2_FEATURE_INCOMPAT_FILETYPE
jz .no
test eax, not EXT4_FEATURE_INCOMPAT_SUPP
jnz .no
jz ext2_setup
 
; OK, this is correct EXT2 superblock
clc
ret
.no:
; No, this superblock isn't EXT2
stc
pop ebx
xor eax, eax
ret
 
; OK, this is correct EXT2 superblock
ext2_setup:
mov [fs_type], 2
movi eax, sizeof.EXTFS
call malloc
test eax, eax
jz ext2_create_partition.no
 
push 512
call kernel_alloc ; mem for superblock
mov ecx, dword [ebp+PARTITION.FirstSector]
mov dword [eax+EXTFS.FirstSector], ecx
mov ecx, dword [ebp+PARTITION.FirstSector+4]
mov dword [eax+EXTFS.FirstSector+4], ecx
mov ecx, dword [ebp+PARTITION.Length]
mov dword [eax+EXTFS.Length], ecx
mov ecx, dword [ebp+PARTITION.Length+4]
mov dword [eax+EXTFS.Length+4], ecx
mov ecx, [ebp+PARTITION.Disk]
mov [eax+EXTFS.Disk], ecx
mov [eax+EXTFS.FSUserFunctions], ext2_user_functions
push ebp esi edi
mov ebp, eax
lea ecx, [eax+EXTFS.Lock]
call mutex_init
 
mov esi, ebx
mov edi, eax
lea edi, [ebp+EXTFS.superblock]
mov ecx, 512/4
rep movsd ; copy sb to reserved mem
mov ebx, eax
mov [ext2_data.sb], eax
 
mov eax, [ebx + EXT2_SB_STRUC.blocks_count]
sub eax, [ebx + EXT2_SB_STRUC.first_data_block]
226,72 → 276,103
xor edx, edx
div [ebx + EXT2_SB_STRUC.blocks_per_group]
inc eax
mov [ext2_data.groups_count], eax
mov [ebp+EXTFS.groups_count], eax
 
mov ecx, [ebx + EXT2_SB_STRUC.log_block_size]
inc ecx
mov [ext2_data.log_block_size], ecx ; 1, 2, 3, 4 equ 1kb, 2kb, 4kb, 8kb
mov [ebp+EXTFS.log_block_size], ecx ; 1, 2, 3, 4 equ 1kb, 2kb, 4kb, 8kb
 
mov eax, 1
shl eax, cl
mov [ext2_data.count_block_in_block], eax
mov [ebp+EXTFS.count_block_in_block], eax
 
shl eax, 7
mov [ext2_data.count_pointer_in_block], eax
mov [ebp+EXTFS.count_pointer_in_block], eax
mov edx, eax ;RUS: потом еще квадрат найдем ;ENG: we'll find a square later
 
shl eax, 2
mov [ext2_data.block_size], eax
mov [ebp+EXTFS.block_size], eax
 
push eax eax ; 2 kernel_alloc
 
mov eax, edx
mul edx
mov [ext2_data.count_pointer_in_block_square], eax
mov [ebp+EXTFS.count_pointer_in_block_square], eax
 
call kernel_alloc
mov [ext2_data.ext2_save_block], eax ; and for temp block
mov [ebp+EXTFS.ext2_save_block], eax ; and for temp block
call kernel_alloc
mov [ext2_data.ext2_temp_block], eax ; and for get_inode proc
mov [ebp+EXTFS.ext2_temp_block], eax ; and for get_inode proc
 
movzx ebp, word [ebx + EXT2_SB_STRUC.inode_size]
movzx eax, word [ebx + EXT2_SB_STRUC.inode_size]
mov ecx, [ebx + EXT2_SB_STRUC.blocks_per_group]
 
mov [ext2_data.inode_size], ebp
mov [ext2_data.blocks_per_group], ecx
mov [ebp+EXTFS.inode_size], eax
mov [ebp+EXTFS.blocks_per_group], ecx
 
push ebp ebp ebp ;3 kernel_alloc
push eax eax eax ;3 kernel_alloc
call kernel_alloc
mov [ext2_data.ext2_save_inode], eax
mov [ebp+EXTFS.ext2_save_inode], eax
call kernel_alloc
mov [ext2_data.ext2_temp_inode], eax
mov [ebp+EXTFS.ext2_temp_inode], eax
call kernel_alloc
mov [ext2_data.root_inode], eax
mov [ebp+EXTFS.root_inode], eax
 
mov ebx, eax
mov eax, EXT2_ROOT_INO
call ext2_get_inode ; read root inode
 
jmp return_from_part_set
mov eax, ebp ; return pointer to EXTFS
pop edi esi ebp ebx
ret
endp
 
proc ext2_free
push ebp
xchg ebp, eax
stdcall kernel_free, [ebp+EXTFS.ext2_save_block]
stdcall kernel_free, [ebp+EXTFS.ext2_temp_block]
stdcall kernel_free, [ebp+EXTFS.ext2_save_inode]
stdcall kernel_free, [ebp+EXTFS.ext2_temp_inode]
stdcall kernel_free, [ebp+EXTFS.root_inode]
xchg ebp, eax
call free
pop ebp
ret
endp
 
proc ext2_lock
lea ecx, [ebp+EXTFS.Lock]
jmp mutex_lock
endp
 
proc ext2_unlock
lea ecx, [ebp+EXTFS.Lock]
jmp mutex_unlock
endp
 
;==================================================================
;read ext2 block form FS to memory
;in: eax = i_block (address of block in ext2 terms)
; ebx = pointer to return memory
; ebp = pointer to EXTFS
;out: eax - error code (0 = no_error)
ext2_get_block:
push ebx ecx
mov ecx, [ext2_data.log_block_size]
mov ecx, [ebp+EXTFS.log_block_size]
shl eax, cl
add eax, [PARTITION_START]
mov ecx, [ext2_data.count_block_in_block]
mov ecx, eax
push [ebp+EXTFS.count_block_in_block]
@@:
call hd_read
cmp [hd_error], 0
mov eax, ecx
call fs_read32_sys
test eax, eax
jnz .fail
inc eax
inc ecx
add ebx, 512
loop @B
dec dword [esp]
jnz @B
pop ecx
xor eax, eax
@@:
pop ecx ebx
304,16 → 385,17
;===================================================================
;RUS: получает номер блока из extent inode ;ENG: receives block number from extent inode
;RUS: in: ecx = номер блока по порядку ;ENG: in: ecx = consecutive block number
;RUS: ebp = адрес extent header`а ;ENG: ebp = address of extent header
;RUS: esi = адрес extent header`а ;ENG: esi = address of extent header
;RUS: ebp = указатель на структуру EXTFS ;ENG: ebp = pointer to EXTFS
;RUS: out: ecx - адрес очередного блока в случае успеха ;ENG: out: ecx - address of next block, if successful
;RUS: eax - номер ошибки (если равно 0, то ошибки нет) ;ENG: eax - error number (0 - no error)
ext4_block_recursive_search:
cmp word [ebp + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC
cmp word [esi + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC
jne .fail
movzx ebx, [ebp + EXT4_EXTENT_HEADER.eh_entries]
add ebp, sizeof.EXT4_EXTENT_HEADER
cmp word [ebp - sizeof.EXT4_EXTENT_HEADER + EXT4_EXTENT_HEADER.eh_depth], 0
movzx ebx, [esi + EXT4_EXTENT_HEADER.eh_entries]
add esi, sizeof.EXT4_EXTENT_HEADER
cmp word [esi - sizeof.EXT4_EXTENT_HEADER + EXT4_EXTENT_HEADER.eh_depth], 0
je .leaf_block ;листовой ли это блок?
;не листовой блок, а индексный ; eax - ext4_extent_idx
325,48 → 407,48
cmp ebx, 1 ;у индексов не хранится длина,
je .end_search_index ;поэтому, если остался последний - то это нужный
cmp ecx, [ebp + EXT4_EXTENT_IDX.ei_block]
cmp ecx, [esi + EXT4_EXTENT_IDX.ei_block]
jb .fail
cmp ecx, [ebp + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса
cmp ecx, [esi + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса
jb .end_search_index ;следующий дальше - значит текущий, то что нам нужен
add ebp, sizeof.EXT4_EXTENT_IDX
add esi, sizeof.EXT4_EXTENT_IDX
dec ebx
jmp @B
.end_search_index:
;ebp указывает на нужный extent_idx, считываем следующий блок
mov ebx, [ext2_data.ext2_temp_block]
mov eax, [ebp + EXT4_EXTENT_IDX.ei_leaf_lo]
mov ebx, [ebp+EXTFS.ext2_temp_block]
mov eax, [esi + EXT4_EXTENT_IDX.ei_leaf_lo]
call ext2_get_block
test eax, eax
jnz .fail
mov ebp, ebx
mov esi, ebx
jmp ext4_block_recursive_search ;рекурсивно прыгаем в начало
.leaf_block: ;листовой блок ebp - ext4_extent
.leaf_block: ;листовой блок esi - ext4_extent
;цикл по экстентам
@@:
test ebx, ebx
jz .fail ;ни один узел не подошел - ошибка
 
mov edx, [ebp + EXT4_EXTENT.ee_block]
mov edx, [esi + EXT4_EXTENT.ee_block]
cmp ecx, edx
jb .fail ;если меньше, значит он был в предыдущих блоках -> ошибка
 
movzx edi, [ebp + EXT4_EXTENT.ee_len]
movzx edi, [esi + EXT4_EXTENT.ee_len]
add edx, edi
cmp ecx, edx
jb .end_search_extent ;нашли нужный блок
add ebp, sizeof.EXT4_EXTENT
add esi, sizeof.EXT4_EXTENT
dec ebx
jmp @B
.end_search_extent:
mov edx, [ebp + EXT4_EXTENT.ee_start_lo]
sub ecx, [ebp + EXT4_EXTENT.ee_block] ;разница в ext4 блоках
mov edx, [esi + EXT4_EXTENT.ee_start_lo]
sub ecx, [esi + EXT4_EXTENT.ee_block] ;разница в ext4 блоках
add ecx, edx
xor eax, eax
ret
378,15 → 460,16
;===================================================================
;получает адрес ext2 блока из inode с определнным номером
;RUS: in: ecx = номер блока в inode (0..) ;ENG: in: ecx = number of block in inode (0..)
;RUS: ebp = адрес inode ;ENG: ebp = inode address
;RUS: esi = адрес inode ;ENG: esi = inode address
;RUS: ebp = указатель на структуру EXTFS;ENG: ebp = pointer to EXTFS
;RUS: out: ecx = адрес очередного блока ;ENG: out: ecx = next block address
;RUS: eax - error code ;ENG: eax - error code
ext2_get_inode_block:
test [ebp + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL
test [esi + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL
jz @F
 
pushad
add ebp, EXT2_INODE_STRUC.i_block ;ebp - extent_header
add esi, EXT2_INODE_STRUC.i_block ;esi - extent_header
call ext4_block_recursive_search
mov PUSHAD_ECX, ecx
mov PUSHAD_EAX, eax
398,19 → 481,19
jb .get_direct_block
 
sub ecx, 12
cmp ecx, [ext2_data.count_pointer_in_block] ; 12.. - indirect blocks
cmp ecx, [ebp+EXTFS.count_pointer_in_block] ; 12.. - indirect blocks
jb .get_indirect_block
 
sub ecx, [ext2_data.count_pointer_in_block]
cmp ecx, [ext2_data.count_pointer_in_block_square]
sub ecx, [ebp+EXTFS.count_pointer_in_block]
cmp ecx, [ebp+EXTFS.count_pointer_in_block_square]
jb .get_double_indirect_block
 
sub ecx, [ext2_data.count_pointer_in_block_square]
sub ecx, [ebp+EXTFS.count_pointer_in_block_square]
;triple indirect block
push edx ebx
 
mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4]
mov ebx, [ext2_data.ext2_temp_block]
mov eax, [esi + EXT2_INODE_STRUC.i_block + 14*4]
mov ebx, [ebp+EXTFS.ext2_temp_block]
call ext2_get_block
test eax, eax
jnz .fail
417,7 → 500,7
 
xor edx, edx
mov eax, ecx
div [ext2_data.count_pointer_in_block_square]
div [ebp+EXTFS.count_pointer_in_block_square]
 
;RUS: eax - номер в полученном блоке edx - номер дальше
;ENG: eax - current block number, edx - next block number
432,8 → 515,8
.get_double_indirect_block:
push edx ebx
 
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 13*4]
mov ebx, [ext2_data.ext2_temp_block]
mov eax, [esi + EXT2_INODE_STRUC.i_block + 13*4]
mov ebx, [ebp+EXTFS.ext2_temp_block]
call ext2_get_block
test eax, eax
jnz .fail
441,7 → 524,7
mov eax, ecx
@@:
xor edx, edx
div [ext2_data.count_pointer_in_block]
div [ebp+EXTFS.count_pointer_in_block]
 
mov eax, [ebx + eax*4]
call ext2_get_block
455,8 → 538,8
 
.get_indirect_block:
push ebx
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 12*4]
mov ebx, [ext2_data.ext2_temp_block]
mov eax, [esi + EXT2_INODE_STRUC.i_block + 12*4]
mov ebx, [ebp+EXTFS.ext2_temp_block]
call ext2_get_block
test eax, eax
jnz @F ;RUS: если не было ошибки ;ENG: if there was no error
467,7 → 550,7
ret
 
.get_direct_block:
mov ecx, [ebp + EXT2_INODE_STRUC.i_block + ecx*4]
mov ecx, [esi + EXT2_INODE_STRUC.i_block + ecx*4]
xor eax, eax
ret
 
475,6 → 558,7
;get content inode by num
;in: eax = inode_num
; ebx = address of inode content
; ebp = pointer to EXTFS
;out: eax - error code
ext2_get_inode:
pushad
482,8 → 566,7
dec eax
xor edx, edx
mov ecx, [ext2_data.sb]
div [ecx + EXT2_SB_STRUC.inodes_per_group]
div [ebp + EXT2_SB_STRUC.inodes_per_group + EXTFS.superblock]
 
push edx ;locale num in group
 
494,10 → 577,10
;RUS: найдем блок в котором он находится
;ENG: in eax - inode group offset relative to global descriptor table start
;ENG: let's find the block this inode is in
div [ext2_data.block_size]
add eax, [ecx + EXT2_SB_STRUC.first_data_block]
div [ebp+EXTFS.block_size]
add eax, [ebp + EXT2_SB_STRUC.first_data_block + EXTFS.superblock]
inc eax
mov ebx, [ext2_data.ext2_temp_block]
mov ebx, [ebp+EXTFS.ext2_temp_block]
call ext2_get_block
test eax, eax
jnz .fail
505,27 → 588,28
add ebx, edx ;RUS: локальный номер в блоке ;ENG: local number inside block
mov eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table] ;RUS: номер блока - в терминах ext2
;ENG: block number - in ext2 terms
mov ecx, [ext2_data.log_block_size]
mov ecx, [ebp+EXTFS.log_block_size]
shl eax, cl
add eax, [PARTITION_START] ;RUS: а старт раздела - в терминах hdd (512)
;ENG: partition start - in HDD terms (512)
;RUS: eax - указывает на таблицу inode-ов на hdd ;ENG: eax - points to inode table on HDD
mov esi, eax ;RUS: сохраним его пока в esi ;ENG: let's save it in esi for now
 
;RUS: прибавим локальный адрес inode-а ;ENG: add local address of inode
pop eax ; index
mov ecx, [ext2_data.inode_size]
mov ecx, [ebp+EXTFS.inode_size]
mul ecx ; (index * inode_size)
mov ebp, 512
div ebp ;RUS: поделим на размер блока ;ENG: divide by block size
;RUS: поделим на размер блока ;ENG: divide by block size
mov ecx, eax
and ecx, 512 - 1
shrd eax, edx, 9
 
add eax, esi ;RUS: нашли адрес блока для чтения ;ENG: found block address to read
mov ebx, [ext2_data.ext2_temp_block]
call hd_read
cmp [hd_error], 0
mov ebx, [ebp+EXTFS.ext2_temp_block]
call fs_read32_sys
test eax, eax
jnz .fail
 
mov esi, edx ;RUS: добавим "остаток" ;ENG: add the "remainder"
mov esi, ecx ;RUS: добавим "остаток" ;ENG: add the "remainder"
mov ecx, [ebp+EXTFS.inode_size]
add esi, ebx ;RUS: к адресу ;ENG: to the address
rep movsb ;RUS: копируем inode ;ENG: copy inode
xor eax, eax
535,55 → 619,47
ret
 
;----------------------------------------------------------------
;
; ext2_HdReadFolder - read 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
;
;--------------------------------------------------------------
ext2_HdReadFolder:
; ext2_ReadFolder - EXT2FS implementation of reading a folder
; in: ebp = pointer to EXTFS structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
ext2_ReadFolder:
call ext2_lock
cmp byte [esi], 0
jz .root_folder
 
push ebx ecx edx
call ext2_find_lfn ;вернет в ebp адрес inode
pop edx ecx ebx
push ebx
stdcall ext2_find_lfn, [esp+4+4] ;вернет в esi адрес inode
pop ebx
test eax, eax
jnz .error_ret
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
jz .error_not_found
jmp @F
 
.root_folder:
mov ebp, [ext2_data.root_inode]
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
mov esi, [ebp+EXTFS.root_inode]
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
jz .error_root
;придется копировать inode
push ecx
mov esi, ebp
mov edi, [ext2_data.ext2_save_inode]
mov ecx, [ext2_data.inode_size]
mov edi, [ebp+EXTFS.ext2_save_inode]
mov ecx, [ebp+EXTFS.inode_size]
shr ecx, 2
mov ebp, edi
push edi
rep movsd
pop ecx
pop esi
@@:
cmp [ebp + EXT2_INODE_STRUC.i_size], 0 ;папка пуста
cmp [esi + EXT2_INODE_STRUC.i_size], 0 ;папка пуста
je .error_empty_dir
mov edx, [ebx + 16]
push edx ;адрес результата [edi + 28]
push 0 ;конец очередного блока папки [edi + 24]
push ecx ;сколько файлов нужно прочитать [edi + 20]
push dword [ebx] ;первый "нужный" файл [edi + 16]
push dword [ebx + 4];флаги [edi + 12]
push dword [ebx +12];сколько файлов нужно прочитать [edi + 20]
push dword [ebx + 4];первый "нужный" файл [edi + 16]
push dword [ebx + 8];флаги [edi + 12]
push 0 ;[EXT2_read_in_folder] [edi + 8]
push 0 ;[EXT2_files_in_folder] [edi + 4]
push 0 ;номер блока по порядку [edi]
601,14 → 677,14
jnz .error_get_block
 
mov eax, ecx
mov ebx, [ext2_data.ext2_save_block]
mov ebx, [ebp+EXTFS.ext2_save_block]
call ext2_get_block ; и считываем блок с hdd
test eax, eax
jnz .error_get_block
 
mov esi, ebx ; esi = current dir record
add ebx, [ext2_data.block_size]
mov [edi + 24], ebx ; запомним конец очередного блока
mov eax, ebx ; ebx = current dir record
add eax, [ebp+EXTFS.block_size]
mov [edi + 24], eax ; запомним конец очередного блока
 
mov ecx, [edi + 16] ; ecx = first wanted (flags ommited)
 
615,26 → 691,26
.find_wanted_start:
jecxz .find_wanted_end
.find_wanted_cycle:
cmp [esi + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used
cmp [ebx + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used
jz @F
inc dword [edi + 4] ; EXT2_files_in_folder
dec ecx
@@:
movzx ebx, [esi + EXT2_DIR_STRUC.rec_len]
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len]
 
cmp ebx, 12 ; минимальная длина записи
cmp eax, 12 ; минимальная длина записи
jb .error_bad_len
test ebx, 0x3 ; длина записи должна делиться на 4
test eax, 0x3 ; длина записи должна делиться на 4
jnz .error_bad_len
 
sub [ebp + EXT2_INODE_STRUC.i_size], ebx ;вычитаем напрямую из структуры inode
add esi, ebx ; к следующей записи
cmp esi, [edi + 24] ; сравниваем с концом блока
sub [esi + EXT2_INODE_STRUC.i_size], eax ;вычитаем напрямую из структуры inode
add ebx, eax ; к следующей записи
cmp ebx, [edi + 24] ; сравниваем с концом блока
jb .find_wanted_start
 
push .find_wanted_start
.end_block: ;вылетели из цикла
cmp [ebp + EXT2_INODE_STRUC.i_size], 0
cmp [esi + EXT2_INODE_STRUC.i_size], 0
jle .end_dir
 
inc dword [edi] ;получаем новый блок
645,15 → 721,15
jnz .error_get_block
 
mov eax, ecx
mov ebx, [ext2_data.ext2_save_block]
mov ebx, [ebp+EXTFS.ext2_save_block]
call ext2_get_block
test eax, eax
jnz .error_get_block
 
pop ecx
mov esi, ebx
add ebx, [ext2_data.block_size]
mov [edi + 24], ebx ;запомним конец блока
mov eax, ebx
add eax, [ebp+EXTFS.block_size]
mov [edi + 24], eax ;запомним конец блока
ret ; опять в цикл
 
.wanted_end:
664,7 → 740,7
mov ecx, [edi + 20]
.wanted_start: ; ищем first_wanted+count
jecxz .wanted_end
cmp [esi + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used
cmp [ebx + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used
jz .empty_rec
inc dword [edi + 8]
inc dword [edi + 4]
676,9 → 752,9
rep stosd
pop ecx edi
 
push esi edi edx
mov eax, [esi + EXT2_DIR_STRUC.inode] ;получим дочерний inode
mov ebx, [ext2_data.ext2_temp_inode]
push ebx edi edx
mov eax, [ebx + EXT2_DIR_STRUC.inode] ;получим дочерний inode
mov ebx, [ebp+EXTFS.ext2_temp_inode]
call ext2_get_inode
test eax, eax
jnz .error_read_subinode
716,13 → 792,14
xor dword [edx], FS_FT_DIR ;помечаем, что это файл
 
;теперь скопируем имя, сконвертировав из UTF-8 в CP866
push ecx ;edi и esi уже сохранены в стеке
push ecx esi ;edi уже сохранен в стеке
mov esi, [esp+12]
movzx ecx, [esi + EXT2_DIR_STRUC.name_len]
lea edi, [edx + 40]
lea esi, [esi + EXT2_DIR_STRUC.name]
call utf8_to_cp866
and byte [edi], 0
pop ecx edi esi
pop esi ecx edi ebx
 
cmp byte [edx + 40], '.' ; в linux файл, начинающийся с точки - скрытый
jne @F
732,15 → 809,15
add edx, 40 + 264 ; go to next record
dec ecx ; если запись пустая ecx не надо уменьшать
.empty_rec:
movzx ebx, [esi + EXT2_DIR_STRUC.rec_len]
cmp ebx, 12 ; минимальная длина записи
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len]
cmp eax, 12 ; минимальная длина записи
jb .error_bad_len
test ebx, 0x3 ; длина записи должна делиться на 4
test eax, 0x3 ; длина записи должна делиться на 4
jnz .error_bad_len
 
sub [ebp + EXT2_INODE_STRUC.i_size], ebx ;вычитаем напрямую из структуры inode
add esi, ebx
cmp esi, [edi + 24] ;дошли ли до конца блока?
sub [esi + EXT2_INODE_STRUC.i_size], eax ;вычитаем напрямую из структуры inode
add ebx, eax
cmp ebx, [edi + 24] ;дошли ли до конца блока?
jb .wanted_start
 
push .wanted_start ; дошли
747,6 → 824,7
jmp .end_block
 
.end_dir: ;конец папки, когда еще не дошли до нужного файла
call ext2_unlock
mov edx, [edi + 28] ;адрес структуры результата
mov ebx, [edi + 8] ;EXT2_read_in_folder
mov ecx, [edi + 4] ;EXT2_files_in_folder
770,6 → 848,9
lea esp, [edi + 32]
.error_ret:
or ebx, -1
push eax
call ext2_unlock
pop eax
ret
.error_empty_dir: ;RUS: inode папки без блоков ;ENG: inode of folder without blocks
834,84 → 915,76
ret
 
;----------------------------------------------------------------
;
; ext2_HdRead - read 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
 
;--------------------------------------------------------------
ext2_HdRead:
; ext2_Read - EXT2FS implementation of reading a file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
ext2_Read:
call ext2_lock
cmp byte [esi], 0
jnz @F
 
.this_is_nofile:
call ext2_unlock
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
 
@@:
push ecx ebx edx
call ext2_find_lfn
pop edx ebx ecx
push ebx
stdcall ext2_find_lfn, [esp+4+4]
pop ebx
test eax, eax
jz @F
 
call ext2_unlock
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
 
@@:
mov ax, [ebp + EXT2_INODE_STRUC.i_mode]
mov ax, [esi + EXT2_INODE_STRUC.i_mode]
and ax, EXT2_S_IFMT ;оставляем только тип inode в ax
cmp ax, EXT2_S_IFREG
jne .this_is_nofile
 
mov edi, edx ; edi = pointer to return mem
mov edi, [ebx+16] ; edi = pointer to return mem
mov ecx, [ebx+12]
 
test ebx, ebx
jz @F
mov esi, ebx ; esi = pointer to first_wanted
mov ebx, [esi+4]
mov eax, [esi] ;RUS: ebx : eax - стартовый номер байта ;ENG: ebx : eax - start byte number
mov eax, [ebx+4]
mov edx, [ebx+8] ;RUS: edx : eax - стартовый номер байта ;ENG: edx : eax - start byte number
 
;RUS: ///// сравним хватит ли нам файла или нет ;ENG: ///// check if file is big enough for us
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
cmp [esi + EXT2_INODE_STRUC.i_dir_acl], edx
ja .size_great
jb .size_less
 
cmp [ebp + EXT2_INODE_STRUC.i_size], eax
cmp [esi + EXT2_INODE_STRUC.i_size], eax
ja .size_great
 
.size_less:
call ext2_unlock
xor ebx, ebx
mov eax, ERROR_END_OF_FILE
ret
@@:
xor ebx, ebx
xor eax, eax
.size_great:
add eax, ecx ;RUS: add to first_wanted кол-во байт для чтения
;ENG: add to first_wanted number of bytes to read
adc ebx, 0
adc edx, 0
 
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
cmp [esi + EXT2_INODE_STRUC.i_dir_acl], edx
ja .size_great_great
jb .size_great_less
cmp [ebp + EXT2_INODE_STRUC.i_size], eax
cmp [esi + EXT2_INODE_STRUC.i_size], eax
jae .size_great_great ; and if it's equal, no matter where we jump
 
.size_great_less:
push 1 ;RUS: читаем по границе размера ;ENG: reading till the end of file
mov ecx, [ebp + EXT2_INODE_STRUC.i_size]
sub ecx, [esi] ;RUS: (размер - старт) = сколько читать ;ENG: to read = (size - start)
mov ecx, [esi + EXT2_INODE_STRUC.i_size]
sub ecx, [ebx+4] ;RUS: (размер - старт) = сколько читать ;ENG: to read = (size - start)
jmp @F
 
.size_great_great:
923,13 → 996,11
;esi -> first wanted
 
push ecx ;количество считанных байт
test esi, esi
jz .zero_start
 
;получим кусок из первого блока
mov edx, [esi+4]
mov eax, [esi]
div [ext2_data.block_size]
mov edx, [ebx+8]
mov eax, [ebx+4]
div [ebp+EXTFS.block_size]
 
push eax ;счетчик блоков ложим в стек
938,7 → 1009,7
call ext2_get_inode_block
test eax, eax
jnz .error_at_first_block
mov ebx, [ext2_data.ext2_save_block]
mov ebx, [ebp+EXTFS.ext2_save_block]
mov eax, ecx
call ext2_get_block
test eax, eax
947,7 → 1018,7
add ebx, edx
 
neg edx
add edx, [ext2_data.block_size] ;RUS: block_size - стартовый байт = сколько байт 1-го блока
add edx, [ebp+EXTFS.block_size] ;RUS: block_size - стартовый байт = сколько байт 1-го блока
;ENG: block_size - start byte = number of bytes in 1st block
cmp ecx, edx
jbe .only_one_block
956,18 → 1027,16
sub eax, edx
mov ecx, edx
 
push esi
mov esi, ebx
rep movsb ;RUS: кусок 1-го блока ;ENG: part of 1st block
jmp .calc_blocks_count
pop esi
 
.zero_start:
mov eax, ecx
push 0 ;счетчик блоков ложим в стек
;теперь в eax кол-во оставшихся байт для чтения
.calc_blocks_count:
mov ebx, edi ;чтение блока прям в ->ebx
xor edx, edx
div [ext2_data.block_size] ;кол-во байт в последнем блоке (остаток) в edx
div [ebp+EXTFS.block_size] ;кол-во байт в последнем блоке (остаток) в edx
mov edi, eax ;кол-во целых блоков в edi
@@:
test edi, edi
982,7 → 1051,7
call ext2_get_block
test eax, eax
jnz .error_at_read_cycle
add ebx, [ext2_data.block_size]
add ebx, [ebp+EXTFS.block_size]
 
dec edi
jmp @B
999,7 → 1068,7
 
mov edi, ebx
mov eax, ecx
mov ebx, [ext2_data.ext2_save_block]
mov ebx, [ebp+EXTFS.ext2_save_block]
call ext2_get_block
test eax, eax
jnz .error_at_finish_block
1013,6 → 1082,7
pop ecx ;счетчик блоков, который хранился в стеке
@@:
pop ebx ;количество считанных байт
call ext2_unlock
pop eax ; 1 или 0 - достигли ли конца файла
test eax, eax
jz @F
1035,17 → 1105,21
.error_at_finish_block:
pop ecx edx
or ebx, -1
push eax
call ext2_unlock
pop eax
ret
 
;----------------------------------------------------------------
; in: esi = file path
; ebx = pointer to dir block
; ebp = pointer to EXTFS structure
; out: esi - name without parent or not_changed
; ebx - dir_rec of inode children
ext2_test_block_by_name:
sub esp, 256 ;EXT2_filename
mov edx, ebx
add edx, [ext2_data.block_size] ;RUS: запомним конец блока ;ENG: save block end
add edx, [ebp+EXTFS.block_size] ;RUS: запомним конец блока ;ENG: save block end
 
.start_rec:
cmp [ebx + EXT2_DIR_STRUC.inode], 0
1097,32 → 1171,37
 
;========================
;Ищет inode по строке пути
;in: esi = name
;in: esi+[esp+4] = name
; ebp = pointer to EXTFS
;out: eax - error code
; ebp = inode
; esi = inode
; dl - первый байт из имени файла/папки
ext2_find_lfn:
mov ebp, [ext2_data.root_inode]
cmp [ebp + EXT2_INODE_STRUC.i_blocks], 0
mov edx, [ebp+EXTFS.root_inode]
cmp [edx + EXT2_INODE_STRUC.i_blocks], 0
je .error_empty_root
.next_path_part:
push [ebp + EXT2_INODE_STRUC.i_blocks]
push [edx + EXT2_INODE_STRUC.i_blocks]
xor ecx, ecx
.folder_block_cycle:
push ecx
xchg esi, edx
call ext2_get_inode_block
xchg esi, edx
test eax, eax
jnz .error_get_inode_block
mov eax, ecx
mov ebx, [ext2_data.ext2_save_block] ;ebx = cur dir record
mov ebx, [ebp+EXTFS.ext2_save_block] ;ebx = cur dir record
call ext2_get_block
test eax, eax
jnz .error_get_block
push esi
push edx
call ext2_test_block_by_name
pop edx
pop edi ecx
 
cmp edi, esi ;RUS: нашли имя? ;ENG: did we find a name?
1130,24 → 1209,29
cmp byte [esi], 0 ;RUS: дошли до "конца" пути -> возваращаемся
;ENG: reached the "end" of path -> returning
jnz @f
cmp dword [esp+8], 0
jz .get_inode_ret
mov esi, [esp+8]
mov dword [esp+8], 0
@@:
 
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR ;RUS: нашли, но это не папка
jne .not_found ;ENG: found, but it's not a folder
 
mov eax, [ebx + EXT2_DIR_STRUC.inode]
mov ebx, [ext2_data.ext2_save_inode] ;RUS: все же папка. ;ENG: it's a folder afterall
mov ebx, [ebp+EXTFS.ext2_save_inode] ;RUS: все же папка. ;ENG: it's a folder afterall
call ext2_get_inode
test eax, eax
jnz .error_get_inode
pop ecx ;RUS: в стеке лежит кол-во блоков ;ENG: stack top contains number of blocks
mov ebp, ebx
mov edx, ebx
jmp .next_path_part
.next_folder_block:
;к следующему блоку в текущей папке
pop eax ;RUS: счетчик блоков ;ENG: blocks counter
sub eax, [ext2_data.count_block_in_block]
sub eax, [ebp+EXTFS.count_block_in_block]
jle .not_found
push eax
1156,17 → 1240,17
 
.not_found:
mov eax, ERROR_FILE_NOT_FOUND
ret
ret 4
 
.get_inode_ret:
pop ecx ;RUS: в стеке лежит кол-во блоков ;ENG: stack top contains number of blocks
mov dl, [ebx + EXT2_DIR_STRUC.name] ;RUS: в dl - первый символ () ;ENG: ???
mov eax, [ebx + EXT2_DIR_STRUC.inode]
mov ebx, [ext2_data.ext2_save_inode]
mov ebx, [ebp+EXTFS.ext2_save_inode]
call ext2_get_inode
mov ebp, ebx
mov esi, ebx
xor eax, eax
ret
ret 4
 
.error_get_inode_block:
.error_get_block:
1175,30 → 1259,35
pop ebx
.error_empty_root:
mov eax, ERROR_FS_FAIL
ret
ret 4
 
;----------------------------------------------------------------
;ext2_HdGetFileInfo - read file info from block device
;
;in: esi points to filename
; edx mem location to return data
;--------------------------------------------------------------
ext2_HdGetFileInfo:
xchg bx, bx
; ext2_GetFileInfo - EXT2 implementation of getting file info
; in: ebp = pointer to EXTFS structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
ext2_GetFileInfo:
call ext2_lock
mov edx, [ebx+16]
cmp byte [esi], 0
jz .is_root
 
push edx
call ext2_find_lfn
stdcall ext2_find_lfn, [esp+4+4]
mov ebx, edx
pop edx
test eax, eax
jz @F
push eax
call ext2_unlock
pop eax
ret
 
.is_root:
xor ebx, ebx ;RUS: root не может быть скрытым ;ENG: root cannot be hidden
mov ebp, [ext2_data.root_inode]
mov esi, [ebp+EXTFS.root_inode]
@@:
xor eax, eax
mov edi, edx
1210,10 → 1299,10
or dword [edx], FS_FT_HIDDEN
@@:
 
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
jnz @F
mov eax, [ebp + EXT2_INODE_STRUC.i_size] ;low size
mov ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl] ;high size
mov eax, [esi + EXT2_INODE_STRUC.i_size] ;low size
mov ebx, [esi + EXT2_INODE_STRUC.i_dir_acl] ;high size
mov dword [edx+32], eax
mov dword [edx+36], ebx
xor dword [edx], FS_FT_DIR
1221,33 → 1310,34
xor dword [edx], FS_FT_DIR
 
lea edi, [edx + 8]
mov eax, [ebp + EXT2_INODE_STRUC.i_ctime]
mov eax, [esi + EXT2_INODE_STRUC.i_ctime]
xor edx, edx
add eax, 3054539008
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
mov eax, [ebp + EXT2_INODE_STRUC.i_atime]
mov eax, [esi + EXT2_INODE_STRUC.i_atime]
xor edx, edx
add eax, 3054539008
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
mov eax, [ebp + EXT2_INODE_STRUC.i_mtime]
mov eax, [esi + EXT2_INODE_STRUC.i_mtime]
xor edx, edx
add eax, 3054539008
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
call ext2_unlock
xor eax, eax
ret
 
ext2_HdRewrite:
ext2_HdWrite:
ext2_HdSetFileEnd:
ext2_HdSetFileInfo:
ext2_HdDelete:
ext2_HdCreateFolder:
ext2_Rewrite:
ext2_Write:
ext2_SetFileEnd:
ext2_SetFileInfo:
ext2_Delete:
ext2_CreateFolder:
xor ebx, ebx
mov eax, ERROR_UNSUPPORTED_FS
ret
/kernel/branches/Kolibri-acpi/fs/fat12.inc
221,7 → 221,7
frnoread2_1:
cmp [esp+16], dword 0; eof without read ?
je frnoread_1
mov [fdc_irq_func], fdc_null
 
pop edi esi edx ecx
add esp, 4
pop ebx; ebx <- eax : size of file
354,7 → 354,6
mov [FDD_Track], 0; Цилиндр
mov [FDD_Head], 0; Сторона
mov [FDD_Sector], 1; Сектор
call SetUserInterrupts
call FDDMotorON
call RecalibrateFDD
cmp [FDC_Status], 0
409,7 → 408,6
cmp [FDD_Sector], 16
jne save_flp_root_1
unnecessary_root_save:
mov [fdc_irq_func], fdc_null
popa
ret
 
445,7 → 443,6
jne unnecessary_flp_fat_save
mov [root_read], 0
unnecessary_flp_fat_save:
mov [fdc_irq_func], fdc_null
popa
ret
 
1703,7 → 1700,7
; now ebx=start pos, ecx=end pos, both lie inside file
sub ecx, ebx
jz .ret
call SetUserInterrupts
 
.write_loop:
; skip unmodified sectors
cmp dword [esp], 0x200
1794,7 → 1791,6
and dword [esp], 0
jmp .write_loop
.done:
mov [fdc_irq_func], fdc_null
jmp .ret
 
floppy_extend_file.zero_size:
1948,7 → 1944,6
mov al, 11
@@:
.doret:
mov [fdc_irq_func], fdc_null
ret
.expand:
push ecx
1981,7 → 1976,6
call save_flp_fat
cmp [FDC_Status], 0
jnz .device_err
call SetUserInterrupts
; now zero new data
; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code
.zero_loop:
2074,7 → 2068,7
add eax, 31
and edi, 0x1FF
jz .truncate_done
call SetUserInterrupts
 
pusha
call read_chs_sector
popa
/kernel/branches/Kolibri-acpi/fs/fat32.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 ;;
;; ;;
;; FAT32.INC ;;
58,8 → 58,7
PUSHAD_EDI equ [esp+0]
 
; Internal data for every FAT partition.
struct FAT
p PARTITION ; must be the first item
struct FAT PARTITION
fs_type db ?
fat16_root db 0 ; flag for fat16 rootdir
fat_change db 0 ; 1=fat has changed
121,6 → 120,7
iglobal
align 4
fat_user_functions:
dd free
dd (fat_user_functions_end - fat_user_functions - 4) / 4
dd fat_Read
dd fat_ReadFolder
138,10 → 138,8
; these labels are located before the main function to make
; most of jumps to these be short
fat_create_partition.free_return0:
push ebx
mov eax, ebp
call free
pop ebx
pop ebp
fat_create_partition.return0:
xor eax, eax
148,7 → 146,7
ret
fat_create_partition:
; bootsector must have been successfully read
cmp dword [esp+4], 1
cmp dword [esp+4], 0
jnz .return0
; bootsector signature must be correct
cmp word [ebx+0x1fe], 0xaa55
170,16 → 168,17
call malloc
test eax, eax
jz .return0
mov ecx, [ebp+8]
mov dword [eax+FAT.p.FirstSector], ecx
mov ecx, [ebp+12]
mov dword [eax+FAT.p.FirstSector+4], ecx
mov ecx, [ebp+16]
mov dword [eax+FAT.p.Length], ecx
mov ecx, [ebp+20]
mov dword [eax+FAT.p.Length+4], ecx
mov [eax+FAT.p.Disk], esi
mov [eax+FAT.p.FSUserFunctions], fat_user_functions
mov ecx, dword [ebp+PARTITION.FirstSector]
mov dword [eax+FAT.FirstSector], ecx
mov ecx, dword [ebp+PARTITION.FirstSector+4]
mov dword [eax+FAT.FirstSector+4], ecx
mov ecx, dword [ebp+PARTITION.Length]
mov dword [eax+FAT.Length], ecx
mov ecx, dword [ebp+PARTITION.Length+4]
mov dword [eax+FAT.Length+4], ecx
mov ecx, [ebp+PARTITION.Disk]
mov [eax+FAT.Disk], ecx
mov [eax+FAT.FSUserFunctions], fat_user_functions
or [eax+FAT.fat_in_cache], -1
mov [eax+FAT.fat_change], 0
push ebp
226,8 → 225,8
jnz @f
mov eax, [ebx+0x20] ; total sector count
@@:
mov dword [ebp+FAT.p.Length], eax
and dword [ebp+FAT.p.Length+4], 0
mov dword [ebp+FAT.Length], eax
and dword [ebp+FAT.Length+4], 0
sub eax, [ebp+FAT.DATA_START] ; eax = count of data sectors
xor edx, edx
div [ebp+FAT.SECTORS_PER_CLUSTER]
262,7 → 261,6
mov [ebp+FAT.fatEND], 0x0FFFFFF8
mov [ebp+FAT.fatMASK], 0x0FFFFFFF
mov al, 32
mov [fs_type], al
mov [ebp+FAT.fs_type], al
mov eax, ebp
pop ebp
274,7 → 272,6
mov [ebp+FAT.fatEND], 0x0000FFF8
mov [ebp+FAT.fatMASK], 0x0000FFFF
mov al, 16
mov [fs_type], al
mov [ebp+FAT.fs_type], al
mov eax, ebp
pop ebp
769,42 → 766,6
ret 4
 
;----------------------------------------------------------------
;
; fs_HdRead - LFN variant for reading hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; 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
;
;--------------------------------------------------------------
fs_HdRead:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdRead
cmp [fs_type], 2
jz ext2_HdRead
or ebx, -1
mov eax, ERROR_UNKNOWN_FS
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_Read
pop ebp
ret
 
;----------------------------------------------------------------
; fat_Read - FAT16/32 implementation of reading a file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
944,43 → 905,6
jmp .reteof
 
;----------------------------------------------------------------
;
; fs_HdReadFolder - LFN variant for reading hard disk folder
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; 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
;
;--------------------------------------------------------------
fs_HdReadFolder:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdReadFolder
cmp [fs_type], 2
jz ext2_HdReadFolder
movi eax, ERROR_UNSUPPORTED_FS
or ebx, -1
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_ReadFolder
pop ebp
ret
 
;----------------------------------------------------------------
; fat_ReadFolder - FAT16/32 implementation of reading a folder
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
1377,52 → 1301,6
pop ecx
ret
 
;----------------------------------------------------------------
;
; fs_HdRewrite - LFN variant for writing hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; 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
;
;--------------------------------------------------------------
fs_HdCreateFolder:
mov al, 1
jmp fs_HdRewrite.common
 
fs_HdRewrite:
xor eax, eax
.common:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdRewrite
cmp [fs_type], 2
jz ext2_HdRewrite
mov eax, ERROR_UNKNOWN_FS
xor ebx, ebx
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
test eax, eax
mov eax, fat_CreateFolder
jnz @f
mov eax, fat_Rewrite
@@:
call eax
pop ebp
ret
 
fshrad:
call fat_unlock
mov eax, ERROR_ACCESS_DENIED
1441,7 → 1319,7
jmp fat_Rewrite.common
 
;----------------------------------------------------------------
; fat_HdRewrite - FAT16/32 implementation of creating a new file
; fat_Rewrite - FAT16/32 implementation of creating a new file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
1988,52 → 1866,17
mov [edi-32+20], cx
jmp .writedircont
 
;----------------------------------------------------------------
;
; fs_HdWrite - LFN variant for writing to hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; 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
;
;--------------------------------------------------------------
fat_Write.access_denied:
push ERROR_ACCESS_DENIED
fs_HdWrite.ret0:
fat_Write.ret0:
pop eax
xor ebx, ebx
ret
 
fs_HdWrite.ret11:
fat_Write.ret11:
push ERROR_DEVICE
jmp fs_HdWrite.ret0
jmp fat_Write.ret0
 
fs_HdWrite:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdWrite
cmp [fs_type], 2
jz ext2_HdWrite
push ERROR_UNKNOWN_FS
jmp .ret0
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_Write
pop ebp
ret
 
;----------------------------------------------------------------
; fat_Write - FAT16/32 implementation of writing to file
; in: ebp = pointer to FAT structure
2051,7 → 1894,7
pop edi
push eax
call fat_unlock
jmp fs_HdWrite.ret0
jmp .ret0
.found:
; FAT does not support files larger than 4GB
cmp dword [ebx+8], 0
2060,7 → 1903,7
pop edi
push ERROR_END_OF_FILE
call fat_unlock
jmp fs_HdWrite.ret0
jmp .ret0
@@:
mov ecx, [ebx+12]
mov edx, [ebx+16]
2362,39 → 2205,6
ret
 
;----------------------------------------------------------------
;
; fs_HdSetFileEnd - set end of file on hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; 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
;
;--------------------------------------------------------------
fs_HdSetFileEnd:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdSetFileEnd
cmp [fs_type], 2
jz ext2_HdSetFileEnd
movi eax, ERROR_UNKNOWN_FS
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_SetFileEnd
pop ebp
ret
 
;----------------------------------------------------------------
; fat_SetFileEnd - FAT16/32 implementation of setting end-of-file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
2634,25 → 2444,6
movi eax, ERROR_FAT_TABLE
ret
 
fs_HdGetFileInfo:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdGetFileInfo
cmp [fs_type], 2
jz ext2_HdGetFileInfo
mov eax, ERROR_UNKNOWN_FS
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_GetFileInfo
pop ebp
ret
 
;----------------------------------------------------------------
; fat_GetFileInfo - FAT16/32 implementation of getting file info
; in: ebp = pointer to FAT structure
2687,25 → 2478,6
pop edi
ret
 
fs_HdSetFileInfo:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdSetFileInfo
cmp [fs_type], 2
jz ext2_HdSetFileInfo
mov eax, ERROR_UNKNOWN_FS
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_SetFileInfo
pop ebp
ret
 
;----------------------------------------------------------------
; fat_SetFileInfo - FAT16/32 implementation of setting file info
; in: ebp = pointer to FAT structure
2742,36 → 2514,6
ret
 
;----------------------------------------------------------------
;
; fs_HdDelete - delete file or empty folder from hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; esi points to filename
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_HdDelete:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdDelete
cmp [fs_type], 2
jz ext2_HdDelete
movi eax, ERROR_UNKNOWN_FS
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_Delete
pop ebp
ret
 
;----------------------------------------------------------------
; fat_Delete - FAT16/32 implementation of deleting a file/folder
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
/kernel/branches/Kolibri-acpi/fs/fs.inc
318,86 → 318,6
fs_noflpdisk:
;*****************************************************************
 
mov eax, [edi+1]
cmp eax, 'HD0 '
je fs_yesharddisk_IDE0
cmp eax, 'HD1 '
je fs_yesharddisk_IDE1
cmp eax, 'HD2 '
je fs_yesharddisk_IDE2
cmp eax, 'HD3 '
je fs_yesharddisk_IDE3
jmp old_path_harddisk
fs_yesharddisk_IDE0:
call reserve_hd1
mov [hdbase], 0x1f0
mov [hdid], 0x0
mov [hdpos], 1
jmp fs_yesharddisk_partition
fs_yesharddisk_IDE1:
call reserve_hd1
mov [hdbase], 0x1f0
mov [hdid], 0x10
mov [hdpos], 2
jmp fs_yesharddisk_partition
fs_yesharddisk_IDE2:
call reserve_hd1
mov [hdbase], 0x170
mov [hdid], 0x0
mov [hdpos], 3
jmp fs_yesharddisk_partition
fs_yesharddisk_IDE3:
call reserve_hd1
mov [hdbase], 0x170
mov [hdid], 0x10
mov [hdpos], 4
fs_yesharddisk_partition:
call reserve_hd_channel
; call choice_necessity_partition
; jmp fs_yesharddisk_all
jmp fs_for_new_semantic
 
choice_necessity_partition:
mov eax, [edi+1+12]
call StringToNumber
mov [fat32part], eax
choice_necessity_partition_1:
mov ecx, [hdpos]
xor eax, eax
mov [hd_entries], eax; entries in hd cache
mov edx, DRIVE_DATA+2
cmp ecx, 0x80
jb search_partition_array
mov ecx, 4
search_partition_array:
mov bl, [edx]
movzx ebx, bl
add eax, ebx
inc edx
loop search_partition_array
mov ecx, [hdpos]
mov edx, BiosDiskPartitions
sub ecx, 0x80
jb .s
je .f
@@:
mov ebx, [edx]
add edx, 4
add eax, ebx
loop @b
jmp .f
.s:
sub eax, ebx
.f:
add eax, [known_part]; add eax,[fat32part]
dec eax
xor edx, edx
imul eax, 100
add eax, DRIVE_DATA+0xa
mov [transfer_adress], eax
call partition_data_transfer_1
ret
 
old_path_harddisk:
mov eax, [edi+1]
cmp eax, 'HD '
416,28 → 336,8
 
fs_no_LBA_read:
 
cmp byte [edi+1+11], 0; directory read
je fs_give_dir1
call reserve_hd1
fs_for_new_semantic:
call choice_necessity_partition
 
fs_yesharddisk_all:
mov eax, 1
mov ebx, [esp+24+24]
cmp [hdpos], 0 ; is hd base set?
jz hd_err_return
cmp [fat32part], 0 ; is partition set?
jnz @f
hd_err_return:
call free_hd_channel
and [hd1_status], 0
jmp file_system_return
@@:
 
call free_hd_channel
and [hd1_status], 0
 
fs_noharddisk:
; \begin{diamond}[18.03.2006]
mov eax, 5 ; file not found
542,7 → 442,10
 
lbarl1:
 
call reserve_hd1
pushad
mov ecx, ide_mutex
call mutex_lock
popad
 
push eax
push ecx
633,6 → 536,10
mov [hd_error], 0
mov [hd1_status], 0
add esp, 2*4
pushad
mov ecx, ide_mutex
call mutex_unlock
popad
 
ret
 
/kernel/branches/Kolibri-acpi/fs/fs_lfn.inc
42,18 → 42,6
db 10,'floppydisk'
dd fs_OnFloppy
dd fs_NextFloppy
db 3,'hd0'
dd fs_OnHd0
dd fs_NextHd0
db 3,'hd1'
dd fs_OnHd1
dd fs_NextHd1
db 3,'hd2'
dd fs_OnHd2
dd fs_NextHd2
db 3,'hd3'
dd fs_OnHd3
dd fs_NextHd3
;**********************************************
db 3,'cd0'
dd fs_OnCd0
76,14 → 64,6
db 'rd',0
dd fs_HasFloppy
db 'fd',0
dd fs_HasHd0
db 'hd0',0
dd fs_HasHd1
db 'hd1',0
dd fs_HasHd2
db 'hd2',0
dd fs_HasHd3
db 'hd3',0
;**********************************************
dd fs_HasCd0
db 'cd0',0
97,7 → 77,6
dd 0
 
fs_additional_handlers:
dd biosdisk_handler, biosdisk_enum_root
dd dyndisk_handler, dyndisk_enum_root
; add new handlers here
dd 0
523,84 → 502,6
dd fs_FloppyCreateFolder
fs_NumFloppyServices = ($ - fs_FloppyServices)/4
 
fs_OnHd0:
call reserve_hd1
mov eax, [hd_address_table]
mov [hdbase], eax ;0x1F0
mov [hdid], 0
push 1
jmp fs_OnHd
fs_OnHd1:
call reserve_hd1
mov eax, [hd_address_table]
mov [hdbase], eax ;0x1F0
mov [hdid], 0x10
push 2
jmp fs_OnHd
fs_OnHd2:
call reserve_hd1
mov eax, [hd_address_table+16]
mov [hdbase], eax ;0x170
mov [hdid], 0
push 3
jmp fs_OnHd
fs_OnHd3:
call reserve_hd1
mov eax, [hd_address_table+16]
mov [hdbase], eax ;0x170
mov [hdid], 0x10
push 4
fs_OnHd:
call reserve_hd_channel
pop eax
mov [hdpos], eax
cmp ecx, 0x100
jae fs_OnHdAndBd.nf
cmp cl, [DRIVE_DATA+1+eax]
fs_OnHdAndBd:
jbe @f
.nf:
call free_hd_channel
and [hd1_status], 0
mov dword [image_of_eax], 5 ; not found
ret
@@:
mov [known_part], ecx ; mov [fat32part], ecx
push ebx esi
call choice_necessity_partition_1
pop esi ebx
mov ecx, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
mov eax, [ebx]
cmp eax, fs_NumHdServices
jae .not_impl
add ebx, 4
call dword [fs_HdServices + eax*4]
call free_hd_channel
and [hd1_status], 0
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
.not_impl:
call free_hd_channel
and [hd1_status], 0
mov dword [image_of_eax], 2 ; not implemented
ret
 
fs_HdServices:
dd fs_HdRead
dd fs_HdReadFolder
dd fs_HdRewrite
dd fs_HdWrite
dd fs_HdSetFileEnd
dd fs_HdGetFileInfo
dd fs_HdSetFileInfo
dd 0
dd fs_HdDelete
dd fs_HdCreateFolder
fs_NumHdServices = ($ - fs_HdServices)/4
 
;*******************************************************
fs_OnCd0:
call reserve_cd
691,22 → 592,6
cmp byte [DRIVE_DATA], 0
setnz al
ret
fs_HasHd0:
test byte [DRIVE_DATA+1], 01000000b
setnz al
ret
fs_HasHd1:
test byte [DRIVE_DATA+1], 00010000b
setnz al
ret
fs_HasHd2:
test byte [DRIVE_DATA+1], 00000100b
setnz al
ret
fs_HasHd3:
test byte [DRIVE_DATA+1], 00000001b
setnz al
ret
 
;*******************************************************
fs_HasCd0:
762,27 → 647,6
stc
ret
 
; on hdx, we have partitions from 1 to [0x40002+x]
fs_NextHd0:
push 0
jmp fs_NextHd
fs_NextHd1:
push 1
jmp fs_NextHd
fs_NextHd2:
push 2
jmp fs_NextHd
fs_NextHd3:
push 3
fs_NextHd:
pop ecx
movzx ecx, byte [DRIVE_DATA+2+ecx]
cmp eax, ecx
jae fs_NextFloppy.no2
inc eax
clc
ret
 
;*******************************************************
fs_NextCd:
; we always have /cdX/1
795,147 → 659,6
ret
;*******************************************************
 
; Additional FS handlers.
; This handler gets the control each time when fn 70 is called
; with unknown item of root subdirectory.
; in: esi -> name
; ebp = 0 or rest of name relative to esi
; out: if the handler processes path, he must not return in file_system_lfn,
; but instead pop return address and return directly to the caller
; otherwise simply return
 
; here we test for /bd<N>/... - BIOS disks
biosdisk_handler:
cmp [NumBiosDisks], 0
jz .ret
mov al, [esi]
or al, 20h
cmp al, 'b'
jnz .ret
mov al, [esi+1]
or al, 20h
cmp al, 'd'
jnz .ret
push esi
inc esi
inc esi
cmp byte [esi], '0'
jb .ret2
cmp byte [esi], '9'
ja .ret2
xor edx, edx
@@:
lodsb
test al, al
jz .ok
cmp al, '/'
jz .ok
sub al, '0'
cmp al, 9
ja .ret2
lea edx, [edx*5]
lea edx, [edx*2+eax]
jmp @b
.ret2:
pop esi
.ret:
ret
.ok:
cmp al, '/'
jz @f
dec esi
@@:
add dl, 80h
xor ecx, ecx
@@:
cmp dl, [BiosDisksData+ecx*4]
jz .ok2
inc ecx
cmp ecx, [NumBiosDisks]
jb @b
jmp .ret2
.ok2:
add esp, 8
test al, al
jnz @f
mov esi, fs_BdNext
jmp file_system_lfn.maindir_noesi
@@:
push ecx
push ecx
push biosdisk_cleanup
push fs_OnBd
mov edi, esp
jmp file_system_lfn.found2
 
fs_BdNext:
cmp eax, [BiosDiskPartitions+ecx*4]
inc eax
cmc
biosdisk_cleanup:
ret
 
fs_OnBd:
pop edx edx edx edx
; edx = disk number, ecx = partition number
; esi+ebp = name
call reserve_hd1
add edx, 0x80
mov [hdpos], edx
cmp ecx, [BiosDiskPartitions+(edx-0x80)*4]
jmp fs_OnHdAndBd
 
; This handler is called when virtual root is enumerated
; and must return all items which can be handled by this.
; It is called several times, first time with eax=0
; in: eax = 0 for first call, previously returned value for subsequent calls
; out: eax = 0 => no more items
; eax != 0 => buffer pointed to by edi contains name of item
 
; here we enumerate existing BIOS disks /bd<N>
biosdisk_enum_root:
cmp eax, [NumBiosDisks]
jae .end
push eax
movzx eax, byte [BiosDisksData+eax*4]
sub al, 80h
push eax
mov al, 'b'
stosb
mov al, 'd'
stosb
pop eax
cmp al, 10
jae .big
add al, '0'
stosb
mov byte [edi], 0
pop eax
inc eax
ret
.end:
xor eax, eax
ret
.big:
push ecx edx
push -'0'
mov ecx, 10
@@:
xor edx, edx
div ecx
push edx
test eax, eax
jnz @b
xchg eax, edx
@@:
pop eax
add al, '0'
stosb
jnz @b
pop edx ecx
pop eax
inc eax
ret
;-----------------------------------------------------------------------------
process_replace_file_name:
; in
/kernel/branches/Kolibri-acpi/fs/iso9660.inc
42,26 → 42,18
cmp [ChannelNumber], 1
jne .IDE_Channel_2
.IDE_Channel_1:
cli
cmp [IDE_Channel_1], 0
je .reserve_ok_1
sti
call change_task
jmp .IDE_Channel_1
.IDE_Channel_2:
cli
cmp [IDE_Channel_2], 0
je .reserve_ok_2
sti
call change_task
jmp .IDE_Channel_2
.reserve_ok_1:
pushad
mov ecx, ide_channel1_mutex
call mutex_lock
mov [IDE_Channel_1], 1
sti
popad
ret
.reserve_ok_2:
.IDE_Channel_2:
pushad
mov ecx, ide_channel2_mutex
call mutex_lock
mov [IDE_Channel_2], 1
sti
popad
ret
 
free_cd_channel:
69,11 → 61,17
jne .IDE_Channel_2
.IDE_Channel_1:
mov [IDE_Channel_1], 0
sti
pushad
mov ecx, ide_channel1_mutex
call mutex_unlock
popad
ret
.IDE_Channel_2:
mov [IDE_Channel_2], 0
sti
pushad
mov ecx, ide_channel2_mutex
call mutex_unlock
popad
ret
 
uglobal
/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