0,0 → 1,519 |
restore_usa: |
; Update Sequence Array restore |
mov bx, [di+4] |
mov cx, [di+6] |
inc bx |
add bx, di |
inc bx |
add di, 1feh |
dec cx |
@@: |
mov ax, [bx] |
stosw |
inc bx |
inc bx |
add di, 1feh |
loop @b |
ret |
|
find_attr: |
; in: di->file record, ax=attribute |
; out: di->attribute or di=0 if not found |
add di, [di+14h] |
.1: |
; attributes codes are formally dwords, but all they fit in word |
cmp word [di], -1 |
jz .notfound |
cmp word [di], ax |
jnz .continue |
; for $DATA attribute, scan only unnamed |
cmp ax, 80h |
jnz .found |
cmp byte [di+9], 0 |
jz .found |
.continue: |
add di, [di+4] |
jmp .1 |
.notfound: |
xor di, di |
.found: |
ret |
|
process_mcb_nonres: |
; in: si->attribute, es:di->buffer |
; out: di->buffer end |
add si, [si+20h] |
xor ebx, ebx |
.loop: |
lodsb |
test al, al |
jz .done |
push invalid_read_request_string |
movzx cx, al |
shr cx, 4 |
jz find_error_sp |
xchg ax, dx |
and dx, 0Fh |
jz find_error_sp |
add si, cx |
add si, dx |
pop ax |
push si |
dec si |
movsx eax, byte [si] |
dec cx |
jz .l1e |
.l1: |
dec si |
shl eax, 8 |
mov al, [si] |
loop .l1 |
.l1e: |
xchg ebp, eax |
dec si |
movsx eax, byte [si] |
mov cx, dx |
dec cx |
jz .l2e |
.l2: |
dec si |
shl eax, 8 |
mov al, byte [si] |
loop .l2 |
.l2e: |
pop si |
add ebx, ebp |
; eax=length, ebx=disk block |
stosd |
mov eax, ebx |
stosd |
jmp .loop |
.done: |
xor eax, eax |
stosd |
ret |
|
load_attr: |
; in: ax=attribute, es:bx->buffer, di->base record |
; out: bx->buffer end; CF set if not found |
push di |
push ax |
mov byte [es:bx], 1 |
inc bx |
push bx |
mov [ofs], bx |
; scan for attrubute |
add di, [di+14h] |
@@: |
call find_attr.1 |
test di, di |
jz .notfound1 |
cmp byte [di+8], 0 |
jnz .nonresident |
; resident attribute |
mov si, di |
pop di |
dec di |
mov al, 0 |
stosb |
mov ax, [si+10h] |
stosw |
xchg ax, cx |
add si, [si+14h] |
rep movsb |
mov bx, di |
pop ax |
pop di |
ret |
.nonresident: |
; nonresident attribute |
cmp dword [di+10h], 0 |
jnz @b |
; read start of data |
mov si, di |
pop di |
call process_mcb_nonres |
push di |
.notfound1: |
; $ATTRIBUTE_LIST is always in base file record |
cmp word [esp+2], 20h |
jz .nofragmented |
; scan for $ATTRIBUTE_LIST = 20h |
mov di, [esp+4] |
mov ax, 20h |
call find_attr |
test di, di |
jz .nofragmented |
; load $ATTRIBUTE_LIST itself |
push es |
mov bx, 0C000h |
mov di, [esp+6] |
push bx |
push [ofs] |
push ds |
pop es |
call load_attr |
pop [ofs] |
pop si |
mov bx, 8000h |
push bx |
push si |
call read_attr_full |
pop si |
pop bx |
add dx, bx |
mov ax, [esp+4] |
pop es |
.1: |
cmp [bx], ax |
jnz .continue1 |
; only unnamed $DATA attributes! |
cmp ax, 80h |
jnz @f |
cmp byte [bx+6], 0 |
jnz .continue1 |
@@: |
cmp dword [bx+10h], 0 |
jz .continue1 |
cmp dword [bx+8], 0 |
jnz @f |
push ax |
mov ax, [esp+2] |
cmp ax, [ofs] |
pop ax |
jnz .continue1 |
@@: |
pushad |
mov eax, [bx+10h] |
mov bx, dx |
push [ofs] |
push es |
push ds |
pop es |
call read_file_record |
pop es |
pop [ofs] |
popad |
pushad |
mov di, dx |
add di, [di+14h] |
.2: |
call find_attr.1 |
mov eax, [bx+8] |
cmp eax, [di+10h] |
jnz .2 |
mov si, di |
mov di, [esp+20h] |
sub di, 4 |
call process_mcb_nonres |
mov [esp+20h], di |
popad |
.continue1: |
add bx, [bx+4] |
cmp bx, dx |
jb .1 |
.nofragmented: |
pop bx |
pop ax |
pop di |
cmp bx, [ofs] |
jnz @f |
dec bx |
stc |
@@: |
ret |
|
read_attr_full: |
; in: si->decoded attribute data, bx->buffer |
; out: edx=length in bytes |
lodsb |
cmp al, 0 |
jnz .nonresident |
; resident |
lodsw |
movzx edx, ax |
xchg ax, cx |
mov di, bx |
rep movsb |
ret |
.nonresident: |
; nonresident :-) |
xor edx, edx |
.loop: |
lodsd |
xchg ecx, eax |
jecxz .loopend |
lodsd |
xchg edi, eax |
; read ecx clusters from cluster edi to es:bx |
.intloop: |
push ecx |
; read 1 cluster from physical cluster edi to es:bx |
mov ecx, [cluster_size] |
mov eax, edi |
mul ecx |
push bx |
call relative_read |
pop bx |
pop ecx |
inc edi |
mov eax, [cluster_size] |
add edx, eax |
shr eax, 4 |
mov bp, es |
add bp, ax |
mov es, bp |
loop .intloop |
jmp .loop |
.loopend: |
mov es, cx |
ret |
|
read_file_record: |
; in: eax=index of record, bx=buffer |
mov si, 700h |
mov ecx, [frs_size] |
mul ecx |
push bx |
push [cur_obj] |
mov [cur_obj], mft_string |
call read_attr |
pop [cur_obj] |
pop di |
call restore_usa |
ret |
read_attr: |
; in: edx:eax=offset in bytes, ecx=size in bytes, bx=buffer, si=attribute |
push invalid_read_request_string |
cmp byte [si], 0 |
jnz .nonresident |
test edx, edx |
jnz find_error_sp |
cmp eax, 10000h |
jae find_error_sp |
cmp ecx, 10000h |
jae find_error_sp |
cmp ax, [si+2] |
jae find_error_sp |
cmp cx, [si+2] |
ja find_error_sp |
add si, 3 |
add si, ax |
mov di, bx |
rep movsb |
pop ax |
ret |
.nonresident: |
mov edi, [cluster_size] |
div edi |
mov [ofs], dx |
add cx, dx |
push eax |
xchg eax, ecx |
xor edx, edx |
dec eax |
div edi |
inc eax |
xchg eax, ecx |
pop eax |
add si, 1 |
xor edx, edx |
push bx |
; eax=offset in clusters, ecx=size in clusters |
.scan: |
mov ebx, [si] |
test ebx, ebx |
jz .notfound |
add edx, ebx |
add si, 8 |
cmp eax, edx |
jae .scan |
mov edi, [si-4] |
; now edx=end of block, ebx=length of block, edi=start of block on disk |
; eax=required offset, ecx=required length |
push edx |
push edi |
sub edx, eax |
add edi, ebx |
sub edi, edx |
cmp edx, ecx |
jb @f |
mov edx, ecx |
@@: |
; read (edx) clusters from (edi=disk offset in clusters) to ([esp+8]) |
cmp [ofs], 0 |
jnz .ofs_read |
.cont: |
pushad |
movzx ebx, byte [50Dh] |
; xchg eax, edx |
; mul ebx |
xchg ax, dx |
mul bx |
xchg cx, ax |
xchg eax, edi |
mul ebx |
mov bx, [esp+8+20h] |
call relative_read |
mov [esp+8+20h], bx |
popad |
.cont2: |
add eax, edx |
sub ecx, edx |
.cont3: |
pop edi |
pop edx |
jnz .scan |
pop bx |
pop ax |
ret |
.ofs_read: |
push ecx |
movzx ecx, byte [50Dh] ; bpb_sects_per_clust |
mov eax, edi |
push edx |
mul ecx |
push 1000h |
pop es |
xor bx, bx |
call relative_read |
mov cx, bx |
push si |
push di |
mov si, [ofs] |
mov di, [esp+8+12] |
sub cx, si |
push ds |
push es |
pop ds |
pop es |
rep movsb |
mov [esp+8+12], di |
push es |
pop ds |
pop di |
pop si |
pop edx |
pop ecx |
inc edi |
mov [ofs], 0 |
inc eax |
dec ecx |
jz .cont3 |
dec edx |
jnz .cont |
jmp .cont2 |
.notfound: |
mov si, invalid_read_request_string |
jmp find_error_si |
|
ntfs_parse_dir: |
; in: eax=directory iRecord, [word sp+2]=filename |
; out: si=$DATA attribute of file |
mov bx, [free] |
mov [dir], bx |
push bx |
call read_file_record |
mov ax, word [frs_size] |
add [free], ax |
pop di |
; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP |
mov ax, 90h ; $INDEX_ROOT |
push di |
mov bx, [free] |
mov [index_root], bx |
call load_attr |
mov si, noindex_string |
jc find_error_si |
mov [free], bx |
pop di |
mov ax, 0A0h ; $INDEX_ALLOCATION |
mov bx, [free] |
mov [index_alloc], bx |
call load_attr |
jnc @f |
mov [index_alloc], 0 |
@@: |
mov [free], bx |
; search for entry |
mov si, [index_root] |
mov bx, [free] |
call read_attr_full |
mov ebp, [bx+8] ; subnode_size |
add bx, 10h |
.scan_record: |
add bx, [bx] |
.scan: |
test byte [bx+0Ch], 2 |
jnz .not_found |
mov si, [esp+2] |
movzx cx, byte [bx+50h] ; namelen |
lea di, [bx+52h] ; name |
xor ax, ax |
@@: |
lodsb |
cmp al, 'a' |
jb .notletter |
cmp al, 'z' |
ja .notletter |
or byte [di], 20h |
.notletter: |
scasw |
loopz @b |
jb .not_found |
ja @f |
cmp byte [esi], 0 |
jz .file_found |
@@: |
add bx, [bx+8] |
jmp .scan |
.not_found: |
test byte [bx+0Ch], 1 |
jz file_not_found |
cmp [index_alloc], 0 |
jz file_not_found |
add bx, [bx+8] |
mov eax, [bx-8] |
mul [cluster_size] |
mov si, [index_alloc] |
mov ecx, ebp |
mov bx, [free] |
call read_attr |
mov di, [free] |
call restore_usa |
mov bx, [free] |
add bx, 18h |
jmp .scan_record |
.file_found: |
mov si, [esp+2] |
mov [cur_obj], si |
cmp byte [esp+4], 0 |
jz .need_file |
mov si, notdir_string |
test byte [bx+48h+3], 10h |
jz find_error_si |
mov eax, [bx] |
mov bx, [dir] |
mov [free], bx |
ret 2 |
.need_file: |
mov si, directory_string |
test byte [bx+48h+3], 10h ; directory? |
jnz find_error_si |
; read entry |
mov eax, [bx] |
mov bx, [dir] |
mov [free], bx |
mov bx, 4000h |
push bx |
call read_file_record |
pop di |
mov ax, 80h |
push 2000h |
pop es |
xor bx, bx |
call load_attr |
mov si, nodata_string |
jz find_error_si |
mov [free], bx |
ret 2 |