119,7 → 119,6 |
attr_size dq ? |
attr_offs dd ? |
attr_list dd ? |
attr_iRecord dd ? |
attr_iBaseRecord dd ? |
cur_attr dd ? ; attribute type |
cur_iRecord dd ? ; number of fileRecord in MFT |
548,6 → 547,7 |
xor edx, edx |
div [ebp+NTFS.sectors_per_cluster] |
mov ebx, edx |
mov [ebp+NTFS.fragmentCount], 0 |
; eax = VCN, ebx = offset in sectors from beginning of cluster |
lea esi, [ebp+NTFS.mft_retrieval] |
sub esi, 8 |
581,6 → 581,7 |
shl edi, 9 |
add [ebp+NTFS.cur_read], edi |
add [ebp+NTFS.cur_buf], edi |
inc [ebp+NTFS.fragmentCount] |
xor eax, eax |
xor ebx, ebx |
cmp [ebp+NTFS.cur_size], eax |
603,7 → 604,6 |
; 1. Read file record. |
; N.B. This will do recursive call of read_attr for $MFT::$Data. |
mov eax, [ebp+NTFS.cur_iRecord] |
mov [ebp+NTFS.attr_iRecord], eax |
and [ebp+NTFS.attr_list], 0 |
or dword [ebp+NTFS.attr_size+4], -1 |
or [ebp+NTFS.attr_iBaseRecord], -1 |
618,7 → 618,6 |
jz @f |
mov eax, [eax+baseRecordReference] |
.beginfindattr: |
mov [ebp+NTFS.attr_iRecord], eax |
call ntfs_read_file_record |
jc .errret |
jmp @f |
1023,7 → 1022,6 |
shrd eax, edx, 9 |
shr edx, 9 |
jnz .errret |
push [ebp+NTFS.attr_iRecord] |
push [ebp+NTFS.attr_iBaseRecord] |
push [ebp+NTFS.attr_offs] |
push [ebp+NTFS.attr_list] |
1055,7 → 1053,6 |
pop [ebp+NTFS.attr_list] |
pop [ebp+NTFS.attr_offs] |
pop [ebp+NTFS.attr_iBaseRecord] |
pop [ebp+NTFS.attr_iRecord] |
jc .ret |
cmp edx, [ebp+NTFS.frs_size] |
jnz .errret |
1197,6 → 1194,7 |
jc .ret |
cmp [ebp+NTFS.cur_read], 0x20 |
jc .ret |
push esi |
pushad |
mov esi, [ebp+NTFS.cur_index_buf] |
mov eax, [esi+indexRecordSize] |
1266,6 → 1264,7 |
mov [ebp+NTFS.cur_index_size], edi |
stdcall kernel_free, edx |
popad |
pop eax |
jmp .doit2 |
|
.notfound: |
1273,6 → 1272,8 |
.err: |
popad |
stc |
.ret2: |
pop esi |
.ret: |
ret 4 |
|
1316,15 → 1317,14 |
|
.found: |
cmp byte [edi], 0 |
jz .done |
jz @f |
cmp byte [edi], '/' |
jz .next |
jz @f |
pop edi |
pop esi |
jmp .scanloopcont |
|
.done: |
.next: |
@@: |
pop esi |
pop esi |
mov eax, [esi] |
1334,11 → 1334,13 |
popad |
inc esi |
cmp byte [esi-1], 0 |
jnz .doit2 |
cmp dword [esp+4], 0 |
jz .ret |
mov esi, [esp+4] |
mov dword [esp+4], 0 |
jnz @f |
cmp dword [esp+8], 0 |
jz .ret2 |
mov esi, [esp+8] |
mov dword [esp+8], 0 |
@@: |
pop eax |
jmp .doit2 |
|
;---------------------------------------------------------------- |
2431,7 → 2433,7 |
shl eax, 1 |
add eax, 42h |
mov [edi+indexRawSize], ax |
mov eax, [ebp+NTFS.attr_iRecord] |
mov eax, [ebp+NTFS.cur_iRecord] |
mov [edi+directoryRecordReference], eax |
mov eax, [ebp+NTFS.frs_buffer] |
mov eax, [eax+reuseCounter] |
2610,9 → 2612,14 |
mov edi, [ebp+NTFS.frs_buffer] |
xor eax, eax |
rep stosd |
mov esi, [ebp+NTFS.indexPointer] |
mov eax, [ebp+NTFS.newRecord] |
mov [esi+fileRecordReference], eax |
rdtsc |
mov [esi+fileReferenceReuse], ax |
mov edi, [ebp+NTFS.frs_buffer] |
; record header |
rdtsc |
mov [edi+reuseCounter], ax |
mov [edi+2ah], ax |
mov eax, [ebp+NTFS.frs_size] |
mov [edi+recordAllocatedSize], eax |
2635,7 → 2642,6 |
mov byte [edi+attributeOffset], 18h |
add edi, 48h |
; $FileName |
mov esi, [ebp+NTFS.indexPointer] |
mov byte [edi+attributeType], 30h |
mov byte [edi+attributeID], 1 |
mov byte [edi+attributeOffset], 18h |
2743,9 → 2749,6 |
mov ecx, 1 |
xor edx, edx |
call fs_write64_sys |
mov edi, [ebp+NTFS.indexPointer] |
mov eax, [ebp+NTFS.newRecord] |
mov [edi+fileRecordReference], eax |
; 5. Write directory node |
mov ebx, [ebp+NTFS.cur_index_buf] |
mov edx, [ebp+NTFS.nodeLastRead] |
3630,9 → 3633,9 |
|
;---------------------------------------------------------------- |
ntfs_Delete: |
xor ebx, ebx |
cmp byte [esi], 0 |
jnz @f |
xor ebx, ebx |
movi eax, ERROR_ACCESS_DENIED |
ret |
|
3644,88 → 3647,113 |
jc ntfsDenied |
cmp [ebp+NTFS.fragmentCount], 1 |
jnz ntfsUnsupported ; record fragmented |
mov edx, [ebp+NTFS.cur_iRecord] |
shr edx, 3 |
cmp edx, [ebp+NTFS.mftBitmapSize] |
mov ebx, [eax+directoryRecordReference] |
mov [ebp+NTFS.newRecord], ebx |
mov bx, [eax+fileReferenceReuse] |
mov [ebp+NTFS.indexPointer], esi |
mov eax, [ebp+NTFS.cur_iRecord] |
shr eax, 3 |
cmp eax, [ebp+NTFS.mftBitmapSize] |
jnc ntfsUnsupported |
mov edx, [ebp+NTFS.secondIndexBuffer] |
mov byte [edx], 0 |
mov edx, [ebp+NTFS.LastRead] |
mov [ebp+NTFS.nodeLastRead], edx |
test byte [eax+indexFlags], 1 |
jz .deleteIndex ; no subnode |
movzx edx, word [eax+indexAllocatedSize] |
mov edi, eax |
mov eax, [eax+edx-8] |
mov edx, [ebp+NTFS.cur_size] |
push edx |
cmp edx, [ebp+NTFS.cur_subnode_size] |
jz @f |
mul [ebp+NTFS.sectors_per_cluster] |
@@: |
; examine file record |
mov [ebp+NTFS.cur_attr], 0x80 ; file? |
mov [ebp+NTFS.cur_offs], 0 |
mov [ebp+NTFS.cur_size], 0 |
call ntfs_read_attr |
jnc @f |
xor eax, eax |
push ebx eax eax eax eax |
mov [esp+12], esp |
push eax |
mov ebx, esp |
mov [ebp+NTFS.cur_attr], 0x90 ; folder? |
call ntfs_ReadFolder.doit |
mov edx, [esp+12] |
add esp, 20 |
pop ebx |
test eax, eax |
jnz .ret |
cmp edx, 2 |
jnz ntfsDenied ; folder is not empty |
mov [ebp+NTFS.cur_attr], 0xA0 |
mov [ebp+NTFS.cur_offs], eax |
push eax |
mov ebx, [ebp+NTFS.secondIndexBuffer] |
mov esi, ebx |
mov [ebp+NTFS.cur_buf], ebx |
mov [ebp+NTFS.cur_offs], 0 |
mov [ebp+NTFS.cur_size], 0 |
call ntfs_read_attr.newAttribute |
pop [ebp+NTFS.cur_offs] |
pop eax |
jc ntfsFail |
cmp dword [esi], 'INDX' |
jnz ntfsFail |
mov [ebp+NTFS.cur_size], eax |
shl eax, 9 |
call ntfs_restore_usa |
jc ntfsFail |
add esi, recordNode |
cmp byte [esi+nonLeafFlag], 0 |
jnz ntfsUnsupported ; non leaf node |
add esi, [esi+indexOffset] |
test byte [esi+indexFlags], 2 |
jnz .deleteSubnode ; empty node |
xor eax, eax |
jc .deleteFileRecord |
@@: |
mov esi, [ebp+NTFS.frs_buffer] |
cmp word [esi+baseRecordReuse], 0 |
jnz ntfsUnsupported ; auxiliary record |
cmp word [esi+reuseCounter], bx |
jnz .backToIndex ; broken index |
cmp byte [esi+recordFlags], 0 |
jz .writeBitmapMFT ; record deleted |
cmp byte [esi+hardLinkCounter], 3 |
jnc ntfsUnsupported |
mov esi, [ebp+NTFS.attr_offs] |
cmp byte [esi+nonResidentFlag], 0 |
jz .deleteFileRecord |
movzx eax, byte [esi+dataRunsOffset] |
add esi, eax |
mov ax, [esi+indexAllocatedSize] |
test byte [esi+eax+indexFlags], 2 |
xor edi, edi |
sub esp, 16 |
@@: |
call ntfs_decode_mcb_entry |
jnc @f |
cmp dword[esp+8], 0 |
jz @b |
add edi, [esp+8] |
mov ebx, [esp] |
call ntfsSpaceFree |
jnc @b |
@@: |
add esp, 16 |
.deleteFileRecord: |
mov ebx, [ebp+NTFS.frs_buffer] |
mov byte [ebx+recordFlags], 0 |
mov edx, [ebp+NTFS.mftLastRead] |
call writeRecord |
.writeBitmapMFT: |
mov eax, [ebp+NTFS.cur_iRecord] |
mov ecx, eax |
shr eax, 3 |
and ecx, 7 |
mov edi, [ebp+NTFS.mftBitmapBuffer] |
btr [edi+eax], ecx |
shr eax, 9 |
mov ebx, eax |
shl ebx, 9 |
add eax, [ebp+NTFS.mftBitmapLocation] |
add ebx, edi |
mov ecx, 1 |
xor edx, edx |
call fs_write64_sys |
.backToIndex: |
mov eax, [ebp+NTFS.newRecord] |
mov [ebp+NTFS.cur_iRecord], eax |
mov esi, [ebp+NTFS.indexPointer] |
stdcall ntfs_find_lfn.doit2, 0 |
jc ntfsFail |
mov ebx, [ebp+NTFS.secondIndexBuffer] |
mov byte [ebx], 0 |
mov ebx, [ebp+NTFS.LastRead] |
mov [ebp+NTFS.nodeLastRead], ebx |
xor ebx, ebx |
test byte [eax+indexFlags], 1 |
jz .deleteIndex ; no subnode |
mov edi, eax |
call .findSubindex |
jc ntfsFail |
movzx edx, word [edi+indexAllocatedSize] |
test esi, esi |
jz @f |
sub edx, eax |
sub edx, 8 |
@@: |
mov eax, edi |
mov ebx, esi |
mov eax, edi |
jmp @f |
|
.deleteSubnode: |
mov esi, [ebp+NTFS.attr_offs] |
add esi, [esi+sizeWithHeader] |
cmp byte [esi], 0xB0 |
jnz ntfsFail |
movzx eax, byte [esi+attributeOffset] |
add esi, eax |
mov eax, [ebp+NTFS.cur_offs] |
xor edx, edx |
div [ebp+NTFS.cur_size] |
mov edx, eax |
shr eax, 3 |
and edx, 7 |
btr [esi+eax], edx |
mov dx, [edi+indexAllocatedSize] |
mov eax, edi |
mov edi, [ebp+NTFS.secondIndexBuffer] |
mov byte [edi], 0 |
xor ebx, ebx |
mov esi, [ebp+NTFS.cur_index_buf] |
cmp dword [esi], 'INDX' |
jnz @f |
mov esi, [ebp+NTFS.frs_buffer] |
mov ecx, [esi+recordRealSize] |
shr ecx, 2 |
rep movsd |
jmp @f |
|
.deleteIndex: |
movzx edx, word [eax+indexAllocatedSize] |
mov ecx, [eax+fileRecordReference] |
3736,26 → 3764,19 |
mov edi, [ebp+NTFS.cur_index_buf] |
cmp dword [edi], 'INDX' |
jz .indexRecord |
mov esi, [ebp+NTFS.frs_buffer] ; indexRoot |
mov ecx, [esi+recordRealSize] |
shr ecx, 2 |
rep movsd |
mov esi, [ebp+NTFS.cur_index_buf] |
sub eax, edi |
mov edi, [ebp+NTFS.indexRoot] |
sub edi, [ebp+NTFS.frs_buffer] |
add edi, esi |
sub [edi+sizeWithHeader], edx |
sub [edi+sizeWithoutHeader], edx |
mov cl, [edi+attributeOffset] |
movzx ecx, byte [edi+attributeOffset] |
add edi, ecx |
add eax, edi |
sub [edi+rootNode+nodeRealSize], edx |
sub [edi+rootNode+nodeAllocatedSize], edx |
sub eax, esi |
add eax, edi |
sub [esi+recordRealSize], edx |
mov ecx, [esi+recordRealSize] |
cmp [esi+recordAllocatedSize], ecx |
jc ntfsUnsupported |
mov edi, [ebp+NTFS.frs_buffer] |
sub [edi+recordRealSize], edx |
mov ecx, [edi+recordRealSize] |
cmp [edi+recordAllocatedSize], ecx |
jmp @f |
|
.indexRecord: |
3763,10 → 3784,9 |
sub [edi+nodeRealSize], edx |
mov ecx, [edi+nodeRealSize] |
cmp [edi+nodeAllocatedSize], ecx |
@@: |
jc ntfsUnsupported |
add ecx, recordNode |
@@: |
add ecx, [ebp+NTFS.cur_index_buf] |
add ecx, edi |
sub ecx, eax |
mov esi, eax |
add esi, edx |
3786,121 → 3806,148 |
cld |
@@: |
test ebx, ebx |
jz @f |
jz .done |
; copy index from the subnode to replace deleted pointing index |
movzx ecx, word [ebx+indexAllocatedSize] |
mov edx, ecx |
test byte [ebx+indexFlags], 1 |
jz @f |
sub ecx, 8 |
movzx edi, word [ebx+edx+indexAllocatedSize] |
add edi, edx |
mov esi, [ebx+ecx] |
mov [ebx+edi-8], esi |
mov [ebx+indexAllocatedSize], cx |
@@: |
shr ecx, 2 |
mov esi, ebx |
mov edi, eax |
rep movsd |
mov edi, [ebp+NTFS.cur_index_buf] |
xchg [ebp+NTFS.secondIndexBuffer], edi |
mov [ebp+NTFS.cur_index_buf], edi |
add word [eax+indexAllocatedSize], 8 |
mov byte [eax+indexFlags], 1 |
mov eax, [ebp+NTFS.LastRead] |
xchg [ebp+NTFS.nodeLastRead], eax |
mov [ebp+NTFS.rootLastRead], eax |
mov edi, [ebp+NTFS.secondIndexBuffer] |
mov eax, ebx |
xor ebx, ebx |
jmp .indexRecord |
|
.ret: |
ret |
|
@@: ; examine file record |
mov [ebp+NTFS.cur_attr], 0x80 ; file? |
mov [ebp+NTFS.cur_offs], 0 |
mov [ebp+NTFS.cur_size], 0 |
call ntfs_read_attr |
jnc @f |
mov eax, [ebp+NTFS.cur_index_size] |
shl eax, 9 |
stdcall kernel_alloc, eax |
test eax, eax |
jz ntfsFail |
push [ebp+NTFS.cur_index_buf] |
push [ebp+NTFS.secondIndexBuffer] |
push [ebp+NTFS.cur_index_size] |
mov [ebp+NTFS.cur_index_buf], eax |
mov [ebp+NTFS.secondIndexBuffer], eax |
xor eax, eax |
push eax eax eax eax |
mov [esp+12], esp |
push eax |
mov ebx, esp |
mov [ebp+NTFS.cur_attr], 0x90 ; folder? |
call ntfs_ReadFolder.doit |
push eax |
stdcall kernel_free, [ebp+NTFS.cur_index_buf] |
pop eax |
mov edx, [esp+12] |
add esp, 20 |
pop [ebp+NTFS.cur_index_size] |
pop [ebp+NTFS.secondIndexBuffer] |
pop [ebp+NTFS.cur_index_buf] |
test eax, eax |
jnz .ret |
cmp edx, 2 |
jnz ntfsDenied ; folder is not empty |
mov [ebp+NTFS.cur_attr], 0xA0 |
mov [ebp+NTFS.cur_offs], 0 |
mov [ebp+NTFS.cur_size], 0 |
call ntfs_read_attr.newAttribute |
jc .writeBitmapMFT |
@@: |
mov esi, [ebp+NTFS.frs_buffer] |
cmp word [esi+baseRecordReuse], 0 |
jnz ntfsUnsupported ; auxiliary record |
mov esi, [ebp+NTFS.attr_offs] |
cmp byte [esi+nonResidentFlag], 0 |
jz .writeBitmapMFT |
movzx eax, byte [esi+dataRunsOffset] |
add esi, eax |
xor edi, edi |
sub esp, 16 |
@@: |
call ntfs_decode_mcb_entry |
jnc @f |
cmp dword[esp+8], 0 |
jz @b |
add edi, [esp+8] |
mov ebx, [esp] |
call ntfsSpaceFree |
jnc @b |
@@: |
add esp, 16 |
.writeBitmapMFT: ; "delete" file record |
mov eax, [ebp+NTFS.cur_iRecord] |
mov ecx, eax |
shr eax, 3 |
and ecx, 7 |
mov edi, [ebp+NTFS.mftBitmapBuffer] |
btr [edi+eax], ecx |
shr eax, 9 |
mov ebx, eax |
shl ebx, 9 |
add eax, [ebp+NTFS.mftBitmapLocation] |
add ebx, edi |
mov ecx, 1 |
xor edx, edx |
call fs_write64_sys |
.done: |
mov ebx, [ebp+NTFS.frs_buffer] |
mov byte [ebx+recordFlags], 0 |
mov edx, [ebp+NTFS.mftLastRead] |
mov edx, [ebp+NTFS.rootLastRead] |
call writeRecord |
; write directory node |
mov ebx, [ebp+NTFS.cur_index_buf] |
cmp dword [ebx], 'INDX' |
jnz @f |
mov edx, [ebp+NTFS.nodeLastRead] |
call writeRecord |
@@: |
mov ebx, [ebp+NTFS.secondIndexBuffer] |
cmp byte [ebx], 0 |
jz ntfsDone |
mov edx, [ebp+NTFS.rootLastRead] |
mov edx, [ebp+NTFS.LastRead] |
call writeRecord |
jmp ntfsDone |
|
.findSubindex: |
; in: eax -> index |
; out: |
; CF=1 -> error |
; esi=0 -> subnode deleted |
; esi -> replacement index |
; eax = index effective size |
movzx edx, word [eax+indexAllocatedSize] |
mov eax, [eax+edx-8] |
mov edx, [ebp+NTFS.cur_size] |
push edx |
cmp edx, [ebp+NTFS.cur_subnode_size] |
jz @f |
mul [ebp+NTFS.sectors_per_cluster] |
@@: |
mov [ebp+NTFS.cur_attr], 0xA0 |
mov [ebp+NTFS.cur_offs], eax |
push eax |
mov ebx, [ebp+NTFS.secondIndexBuffer] |
mov esi, ebx |
mov [ebp+NTFS.cur_buf], ebx |
call ntfs_read_attr.newAttribute |
pop [ebp+NTFS.cur_offs] |
pop eax |
jc .ret |
cmp dword [esi], 'INDX' |
stc |
jnz .ret |
mov [ebp+NTFS.cur_size], eax |
shl eax, 9 |
call ntfs_restore_usa |
jc .ret |
add esi, recordNode |
add esi, [esi+indexOffset] |
test byte [esi+indexFlags], 2 |
jnz .emptyNode |
cmp [ebp+NTFS.fragmentCount], 1 |
stc |
jnz .ret ; record fragmented |
xor eax, eax |
@@: |
add esi, eax |
mov ax, [esi+indexAllocatedSize] |
test byte [esi+eax+indexFlags], 2 |
jz @b |
test byte [esi+indexFlags], 1 |
jz .ret |
add eax, esi |
push esi |
push [ebp+NTFS.cur_offs] |
call .findSubindex |
pop [ebp+NTFS.cur_offs] |
pop edx |
jc .ret |
test esi, esi |
jnz .ret |
mov esi, edx |
mov ebx, [ebp+NTFS.secondIndexBuffer] |
mov [ebp+NTFS.cur_buf], ebx |
push [ebp+NTFS.cur_size] |
call ntfs_read_attr.continue |
pop eax |
jc .ret |
shl eax, 9 |
call ntfs_restore_usa |
jc .ret |
movzx eax, word [esi+indexAllocatedSize] |
sub eax, 8 |
.ret: |
ret |
|
.emptyNode: |
test byte [esi+indexFlags], 1 |
jz @f |
mov eax, esi |
push [ebp+NTFS.cur_offs] |
call .findSubindex |
pop [ebp+NTFS.cur_offs] |
jc .ret |
test esi, esi |
jnz .ret |
@@: ; delete node |
mov esi, [ebp+NTFS.attr_offs] |
add esi, [esi+sizeWithHeader] |
cmp byte [esi], 0xB0 |
stc |
jnz .ret |
movzx eax, byte [esi+attributeOffset] |
add esi, eax |
mov eax, [ebp+NTFS.cur_offs] |
xor edx, edx |
div [ebp+NTFS.cur_size] |
mov edx, eax |
shr eax, 3 |
and edx, 7 |
btr [esi+eax], edx |
mov esi, [ebp+NTFS.secondIndexBuffer] |
mov byte [esi], 0 |
xor esi, esi |
ret |
|
;---------------------------------------------------------------- |
ntfs_SetFileEnd: |
cmp byte [esi], 0 |