65,7 → 65,7 |
indexedAttributesType = 0 |
collationRule = 4 |
indexRecordSize = 8 |
indexRecordSizeClus = 12 |
indexRecordSizeClus = 12 ; in sectors if less than one cluster |
rootNode = 16 |
; IndexRecord header |
recordVCN = 16 |
108,6 → 108,7 |
mft_retrieval_end dd ? |
cur_index_size dd ? ; in sectors |
cur_index_buf dd ? ; index node buffer |
secondIndexBuffer dd ? |
BitmapBuffer dd ? |
BitmapTotalSize dd ? ; bytes reserved |
BitmapSize dd ? ; bytes readen |
124,13 → 125,16 |
cur_buf dd ? |
cur_read dd ? ; bytes readen |
LastRead dd ? ; last readen block of sectors |
newMftRecord dd ? ; number of fileRecord in MFT |
rootLastRead dd ? |
nodeLastRead dd ? |
indexRoot dd ? |
pointingIndex dd ? |
newRecord dd ? |
fileDataStart dd ? ; starting cluster |
fileDataSize dd ? ; in clusters |
fileDataBuffer dd ? |
fileRealSize dd ? ; in bytes |
indexOffset dd ? |
nodeLastRead dd ? |
fragmentCount db ? |
bCanContinue db ? |
bFolder db ? |
398,11 → 402,13 |
add esp, 10h |
; there may be other portions of $DATA attribute in auxiliary records; |
; if they will be needed, they will be loaded later |
mov [ebp+NTFS.cur_index_size], 0x1000/0x200 |
stdcall kernel_alloc, 0x1000 |
stdcall kernel_alloc, 2000h |
test eax, eax |
jz .fail_free_mft |
mov [ebp+NTFS.cur_index_buf], eax |
add eax, 1000h |
mov [ebp+NTFS.secondIndexBuffer], eax |
mov [ebp+NTFS.cur_index_size], 8 |
; reserve adress space for bitmap buffer and load some part of bitmap |
mov eax, dword [ebp+NTFS.Length] |
xor edx, edx |
484,6 → 490,7 |
stdcall kernel_free, [ebx+NTFS.BitmapBuffer] |
.failFreeIndex: |
stdcall kernel_free, [ebp+NTFS.cur_index_buf] |
stdcall kernel_free, [ebp+NTFS.secondIndexBuffer] |
.fail_free_mft: |
stdcall kernel_free, [ebp+NTFS.mft_retrieval] |
.fail_free_frs: |
532,6 → 539,7 |
stdcall kernel_free, [ebx+NTFS.frs_buffer] |
stdcall kernel_free, [ebx+NTFS.mft_retrieval] |
stdcall kernel_free, [ebx+NTFS.cur_index_buf] |
stdcall kernel_free, [ebp+NTFS.secondIndexBuffer] |
stdcall kernel_free, [ebx+NTFS.mftBitmapBuffer] |
stdcall kernel_free, [ebx+NTFS.BitmapBuffer] |
mov eax, ebx |
1280,10 → 1288,13 |
jc .ret |
pushad |
mov esi, [ebp+NTFS.cur_index_buf] |
mov edx, [esi+indexRecordSize] |
shr edx, 9 |
cmp [ebp+NTFS.cur_index_size], edx |
mov eax, [esi+indexRecordSize] |
shr eax, 9 |
cmp [ebp+NTFS.cur_index_size], eax |
jc .realloc |
mov [ebp+NTFS.cur_size], eax |
mov al, [esi+indexRecordSizeClus] |
mov [ebp+NTFS.cur_subnode_size], eax |
add esi, rootNode |
mov eax, [esi+nodeRealSize] |
add eax, rootNode |
1290,7 → 1301,11 |
cmp [ebp+NTFS.cur_read], eax |
jc .err |
mov edi, [esp+4] |
; edi -> name, esi -> current index node, edx = subnode size |
mov eax, [ebp+NTFS.LastRead] |
mov [ebp+NTFS.rootLastRead], eax |
mov eax, [ebp+NTFS.attr_offs] |
mov [ebp+NTFS.indexRoot], eax |
; edi -> name, esi -> current index node |
.scanloop: |
add esi, [esi+indexOffset] |
.scanloopint: |
1323,14 → 1338,20 |
jmp .scanloopint |
|
.realloc: |
mov edi, edx |
stdcall kernel_alloc, [esi+indexRecordSize] |
mov edi, eax |
mov eax, [esi+indexRecordSize] |
shl eax, 1 |
stdcall kernel_alloc, eax |
test eax, eax |
jz .err |
push [ebp+NTFS.secondIndexBuffer] |
push [ebp+NTFS.cur_index_buf] |
mov [ebp+NTFS.cur_index_buf], eax |
add eax, [esi+indexRecordSize] |
mov [ebp+NTFS.secondIndexBuffer], eax |
mov [ebp+NTFS.cur_index_size], edi |
call kernel_free |
mov [ebp+NTFS.cur_index_size], edi |
call kernel_free |
popad |
jmp .doit2 |
|
1351,21 → 1372,27 |
jz .notfound |
movzx eax, word [esi+indexAllocatedSize] |
mov eax, [esi+eax-8] |
imul eax, [ebp+NTFS.sectors_per_cluster] |
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.pointingIndex], esi |
mov esi, [ebp+NTFS.cur_index_buf] |
xchg [ebp+NTFS.secondIndexBuffer], esi |
mov [ebp+NTFS.cur_index_buf], esi |
mov [ebp+NTFS.cur_buf], esi |
mov [ebp+NTFS.cur_attr], 0xA0 ; $INDEX_ALLOCATION |
mov [ebp+NTFS.cur_offs], eax |
mov [ebp+NTFS.cur_attr], 0xA0 ; $INDEX_ALLOCATION |
mov [ebp+NTFS.cur_size], edx |
mov eax, [ebp+NTFS.cur_index_buf] |
mov esi, eax |
mov [ebp+NTFS.cur_buf], eax |
call ntfs_read_attr.newAttribute |
mov eax, edx |
pop eax |
mov [ebp+NTFS.cur_size], eax |
shl eax, 9 |
cmp [ebp+NTFS.cur_read], eax |
jnz .err |
cmp dword [esi], 'INDX' |
jnz .err |
mov [ebp+NTFS.cur_buf], esi |
mov ebx, esi |
call ntfs_restore_usa |
jc .err |
1566,11 → 1593,11 |
jc ntfsFail |
pushad |
mov esi, [ebp+NTFS.cur_index_buf] |
mov edx, [esi+indexRecordSize] |
shr edx, 9 |
cmp [ebp+NTFS.cur_index_size], edx |
mov eax, [esi+indexRecordSize] |
shr eax, 9 |
cmp [ebp+NTFS.cur_index_size], eax |
jc .realloc |
mov [ebp+NTFS.cur_subnode_size], edx |
mov [ebp+NTFS.cur_subnode_size], eax |
add esi, rootNode |
mov eax, [esi+nodeRealSize] |
add eax, rootNode |
1612,14 → 1639,20 |
jmp .dump_root |
|
.realloc: |
mov edi, edx |
stdcall kernel_alloc, [esi+indexRecordSize] |
mov edi, eax |
mov eax, [esi+indexRecordSize] |
shl eax, 1 |
stdcall kernel_alloc, eax |
test eax, eax |
jz .err |
push [ebp+NTFS.secondIndexBuffer] |
push [ebp+NTFS.cur_index_buf] |
mov [ebp+NTFS.cur_index_buf], eax |
add eax, [esi+indexRecordSize] |
mov [ebp+NTFS.secondIndexBuffer], eax |
mov [ebp+NTFS.cur_index_size], edi |
call kernel_free |
mov [ebp+NTFS.cur_index_size], edi |
call kernel_free |
popad |
jmp .doit |
|
2048,30 → 2081,27 |
mov edi, [ebp+NTFS.cur_index_buf] |
jmp .common |
|
@@: |
add esp, 16 |
jmp ntfsUnsupported |
|
.growTree: |
sub eax, edi |
sub eax, rootNode |
sub eax, [edi+rootNode+indexOffset] |
push eax |
xchg [ebp+NTFS.secondIndexBuffer], edi |
mov [ebp+NTFS.cur_index_buf], edi |
; create indexRecord |
mov ecx, 10 |
xor eax, eax |
rep stosd |
mov esi, [ebp+NTFS.attr_offs] |
mov al, [esi+attributeOffset] |
add esi, eax |
mov al, [esi+indexRecordSizeClus] |
mov [ebp+NTFS.fileDataSize], eax |
rdtsc |
stosw |
mov esi, [ebp+NTFS.attr_offs] |
mov cl, [esi+attributeOffset] |
add esi, ecx |
mov eax, [esi+indexRecordSizeClus] |
cmp eax, 129 |
jnc @b |
mov [ebp+NTFS.fileDataSize], eax |
mov eax, [esi+indexRecordSize] |
cmp eax, [ebp+NTFS.frs_size] |
jc @b |
jc .errorPop4 |
shr eax, 9 |
inc eax |
mov edi, [ebp+NTFS.cur_index_buf] |
2115,7 → 2145,7 |
mov word [esi+sizeWithoutHeader], 38h |
xchg [esi+sizeWithHeader], eax |
cmp byte [esi+eax], -1 |
jnz @b |
jnz .errorPop4 |
mov cl, 32 |
xor eax, eax |
push edi |
2128,6 → 2158,7 |
|
@@: ; create $IndexAllocation |
pop edi |
mov [ebp+NTFS.attr_offs], edi |
mov byte [edi+attributeType], 0xA0 |
mov byte [edi+nonResidentFlag], 1 |
mov byte [edi+nameLength], 4 |
2181,7 → 2212,7 |
mov [ebp+NTFS.cur_buf], eax |
call writeRecord ; indexRecord |
mov ebx, [ebp+NTFS.cur_index_buf] |
mov ax, [ebx+6] |
mov ax, [ebx+updateSequenceSize] |
dec eax |
shl eax, 9 |
call ntfs_restore_usa |
2188,6 → 2219,7 |
mov edi, [ebp+NTFS.cur_index_buf] |
pop eax |
add eax, recordNode |
add eax, edi |
add eax, [edi+recordNode+indexOffset] |
mov edx, [esp] |
.indexRecord: |
2194,12 → 2226,157 |
add edi, recordNode |
add edx, [edi+nodeRealSize] |
cmp [edi+nodeAllocatedSize], edx |
jnc @f |
jc .arborizeTree |
mov [edi+nodeRealSize], edx |
jmp .common |
|
.errorPop4: |
pop eax |
.errorPop3: |
add esp, 12 |
jmp ntfsUnsupported ; new node required |
jmp ntfsUnsupported |
|
@@: ; index fits in the node |
mov [edi+nodeRealSize], edx |
.arborizeTree: |
; directory bitmap |
mov esi, [ebp+NTFS.attr_offs] |
add esi, [esi+sizeWithHeader] |
cmp byte [esi], 0xB0 |
jnz .errorPop3 |
movzx eax, byte [esi+attributeOffset] |
add esi, eax |
mov eax, [esi] |
not eax |
bsf eax, eax |
jz .errorPop3 |
bts [esi], eax |
mul [ebp+NTFS.cur_subnode_size] |
mov [ebp+NTFS.newRecord], eax |
; find median index |
mov ecx, [edi+nodeRealSize] |
sub ecx, [edi+indexOffset] |
shr ecx, 1 |
add edi, [edi+indexOffset] |
xor eax, eax |
@@: |
add edi, eax |
mov ax, [edi+indexAllocatedSize] |
sub ecx, eax |
jnc @b |
mov esi, [ebp+NTFS.secondIndexBuffer] |
cmp dword [esi], 'INDX' |
jz .errorPop3 ; move index to the branch node |
; move index to the root node |
mov esi, [ebp+NTFS.frs_buffer] |
mov ecx, [esi+recordRealSize] |
add eax, 8 |
add ecx, eax |
cmp [esi+recordAllocatedSize], ecx |
jc .errorPop3 ; tree grow required |
mov [esi+recordRealSize], ecx |
add esi, ecx |
push edi |
mov edi, [ebp+NTFS.indexRoot] |
add [ebp+NTFS.attr_offs], eax |
add [edi+sizeWithHeader], eax |
add [edi+sizeWithoutHeader], eax |
movzx ecx, byte [edi+attributeOffset] |
add ecx, edi |
add [ecx+rootNode+nodeRealSize], eax |
add [ecx+rootNode+nodeAllocatedSize], eax |
add ecx, [ebp+NTFS.pointingIndex] |
sub ecx, [ebp+NTFS.secondIndexBuffer] |
mov edi, esi |
sub esi, eax |
neg ecx |
add ecx, esi |
shr ecx, 2 |
sub esi, 4 |
sub edi, 4 |
std |
rep movsd ; make space |
mov [edi], ecx |
mov edi, esi |
add edi, 4 |
mov esi, [esp] |
add word [esi+indexAllocatedSize], 8 |
mov byte [esi+indexFlags], 1 |
mov ecx, eax |
sub ecx, 8 |
shr ecx, 2 |
cld |
rep movsd ; insert index |
mov eax, [ebp+NTFS.newRecord] |
stosd |
; split node |
mov edi, [ebp+NTFS.cur_index_buf] |
mov eax, edi |
add eax, recordNode |
add eax, [edi+recordNode+nodeRealSize] |
sub eax, esi |
push eax |
mov ecx, [edi+recordNode+indexOffset] |
add eax, ecx |
add ecx, recordNode |
shr ecx, 2 |
push esi |
mov esi, edi |
mov edi, [ebp+NTFS.secondIndexBuffer] |
rep movsd |
pop esi |
pop ecx |
shr ecx, 2 |
rep movsd |
mov edi, [ebp+NTFS.secondIndexBuffer] |
mov [edi+recordNode+nodeRealSize], eax |
pop edi |
mov cl, 4 |
xor eax, eax |
mov esi, edi |
rep stosd |
mov byte [esi+indexAllocatedSize], 16 |
mov byte [esi+indexFlags], 2 |
mov esi, [ebp+NTFS.cur_index_buf] |
mov eax, [ebp+NTFS.newRecord] |
movzx edx, word [esi+updateSequenceSize] |
dec edx |
mov [esi+recordVCN], eax |
add esi, recordNode |
sub edi, esi |
mov [esi+nodeRealSize], edi |
; allocate new node |
add eax, [ebp+NTFS.cur_subnode_size] |
cmp edx, [ebp+NTFS.cur_subnode_size] |
jz @f |
mul [ebp+NTFS.sectors_per_cluster] |
@@: |
shl eax, 9 |
mov esi, [ebp+NTFS.attr_offs] |
cmp [esi+attributeAllocatedSize], eax |
jnc .errorPop3 |
call resizeAttribute |
jc ntfsErrorPop3 |
mov eax, [ebp+NTFS.secondIndexBuffer] |
mov [ebp+NTFS.cur_buf], eax |
call writeRecord |
mov eax, [ebp+NTFS.fileDataStart] |
mul [ebp+NTFS.sectors_per_cluster] |
mov [ebp+NTFS.LastRead], eax |
mov eax, [ebp+NTFS.cur_index_buf] |
mov [ebp+NTFS.cur_buf], eax |
call writeRecord |
mov eax, [ebp+NTFS.rootLastRead] |
mov [ebp+NTFS.LastRead], eax |
mov eax, [ebp+NTFS.frs_buffer] |
mov [ebp+NTFS.cur_buf], eax |
call writeRecord |
mov esi, [esp+4] |
stdcall ntfs_find_lfn.doit2, 0 |
test eax, eax |
jz .errorPop3 |
mov edi, [ebp+NTFS.cur_index_buf] |
mov edx, [esp] |
jmp .indexRecord |
|
.common: |
add edi, edx |
sub edi, 4 |
2300,7 → 2477,7 |
sub edi, [ebp+NTFS.mftBitmapBuffer] |
shl edi, 3 |
add edi, ecx |
mov [ebp+NTFS.newMftRecord], edi |
mov [ebp+NTFS.newRecord], edi |
mov eax, [ebp+NTFS.frs_size] |
shr eax, 9 |
mul edi |
2339,7 → 2516,7 |
mov [edx+attributeRealSize], ecx |
mov [edx+initialDataSize], ecx |
shl eax, 3 |
mov [ebp+NTFS.newMftRecord], eax |
mov [ebp+NTFS.newRecord], eax |
mov dword [edi], 1 |
mov dword [edi+4], 0 |
mov [ebp+NTFS.cur_attr], 0x80 |
2503,7 → 2680,7 |
mov [esi+recordRealSize], edi |
call writeRecord |
; write MFT bitmap |
mov eax, [ebp+NTFS.newMftRecord] |
mov eax, [ebp+NTFS.newRecord] |
shr eax, 3+9 |
mov ebx, eax |
shl ebx, 9 |
2513,7 → 2690,7 |
xor edx, edx |
call fs_write64_sys |
mov edi, [ebp+NTFS.indexOffset] |
mov eax, [ebp+NTFS.newMftRecord] |
mov eax, [ebp+NTFS.newRecord] |
mov [edi+fileRecordReference], eax |
; 5. Write directory node |
mov eax, [ebp+NTFS.nodeLastRead] |
3687,6 → 3864,8 |
ntfsDiskFull: |
push ERROR_DISK_FULL |
jmp ntfsOut |
ntfsErrorPop3: |
pop ebx |
ntfsErrorPop2: |
pop ebx |
ntfsErrorPop: |