NTFS: limited support of deleting files and folders

git-svn-id: svn://kolibrios.org@6019 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
pathoswithin 2015-12-31 17:29:37 +00:00
parent c9cedace09
commit 40159abb43

View File

@ -46,9 +46,10 @@ sizeWithHeader = 4
nonResidentFlag = 8 nonResidentFlag = 8
nameLength = 9 nameLength = 9
nameOffset = 10 nameOffset = 10
attributeFlags = 12
attributeID = 14 attributeID = 14
sizeWithoutHeader = 16 sizeWithoutHeader = 16
attributeFlags = 16h indexedFlag = 16h
; non resident attribute header ; non resident attribute header
lastVCN = 18h lastVCN = 18h
dataRunsOffset = 20h dataRunsOffset = 20h
@ -272,10 +273,6 @@ ntfs_create_partition:
mov dword [eax+NTFS.FirstSector], ecx mov dword [eax+NTFS.FirstSector], ecx
mov ecx, dword [ebp+PARTITION.FirstSector+4] mov ecx, dword [ebp+PARTITION.FirstSector+4]
mov dword [eax+NTFS.FirstSector+4], ecx 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 ecx, [ebp+PARTITION.Disk]
mov [eax+NTFS.Disk], ecx mov [eax+NTFS.Disk], ecx
mov [eax+NTFS.FSUserFunctions], ntfs_user_functions mov [eax+NTFS.FSUserFunctions], ntfs_user_functions
@ -1165,6 +1162,14 @@ ntfs_restore_usa:
ret ret
ntfs_decode_mcb_entry: ntfs_decode_mcb_entry:
; in:
; esi -> mcb entry
; esp -> buffer (16 bytes)
; out:
; esi -> next mcb entry
; esp -> data run size
; esp+8 -> cluster (delta)
; CF=0 -> mcb end
push eax ecx edi push eax ecx edi
lea edi, [esp+16] lea edi, [esp+16]
xor eax, eax xor eax, eax
@ -1989,64 +1994,57 @@ ntfs_CreateFile:
cmp byte [esi], 0 cmp byte [esi], 0
jnz @f jnz @f
xor ebx, ebx xor ebx, ebx
movi eax, ERROR_ACCESS_DENIED ; root directory itself movi eax, ERROR_ACCESS_DENIED
ret ret
@@: ; 1. Search file @@: ; 1. Search file
call ntfs_lock call ntfs_lock
stdcall ntfs_find_lfn, [esp+4] stdcall ntfs_find_lfn, [esp+4]
jnc .found jnc .found
cmp [ebp+NTFS.ntfsFragmentCount], 1 cmp [ebp+NTFS.ntfsFragmentCount], 1
jnz @f ; record fragmented jnz ntfsUnsupported ; record fragmented
test eax, eax test eax, eax
jnz .notFound jz ntfsFail
push ERROR_FS_FAIL jmp .notFound
jmp ntfsError
@@:
push ERROR_UNSUPPORTED_FS
jmp ntfsError
.found: ; rewrite .found: ; rewrite
cmp [ebp+NTFS.ntfs_cur_iRecord], 16
jc ntfsDenied
cmp [ebp+NTFS.ntfsFolder], 1
jz ntfsDenied
mov [ebp+NTFS.ntfs_cur_attr], 0x80 mov [ebp+NTFS.ntfs_cur_attr], 0x80
mov [ebp+NTFS.ntfs_cur_offs], 0 mov [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 0 mov [ebp+NTFS.ntfs_cur_size], 0
call ntfs_read_attr call ntfs_read_attr
jnc @f jc ntfsDenied
push ERROR_ACCESS_DENIED
jmp ntfsError
@@:
push ERROR_UNSUPPORTED_FS
mov eax, [ebp+NTFS.frs_buffer] mov eax, [ebp+NTFS.frs_buffer]
cmp word [eax+baseRecordReuse], 0 cmp word [eax+baseRecordReuse], 0
jnz ntfsError ; auxiliary record jnz ntfsUnsupported ; auxiliary record
cmp byte [eax+hardLinkCounter], 1 cmp byte [eax+hardLinkCounter], 1
jnz ntfsError ; file copying required jnz ntfsUnsupported ; file copying required
mov ecx, [ebp+NTFS.ntfs_attr_offs] mov ecx, [ebp+NTFS.ntfs_attr_offs]
cmp byte [ecx+nonResidentFlag], 1 cmp byte [ecx+nonResidentFlag], 1
jnz ntfsError ; resident $DATA jnz ntfsUnsupported ; resident $DATA
mov eax, [ebx+4] mov eax, [ebx+4]
mov edx, [ebx+8] mov edx, [ebx+8]
add eax, [ebx+12] add eax, [ebx+12]
adc edx, 0 adc edx, 0
cmp edx, [ecx+attributeRealSize+4] cmp edx, [ecx+attributeRealSize+4]
jnz ntfsError jnz ntfsUnsupported
cmp [ecx+attributeRealSize], eax cmp [ecx+attributeRealSize], eax
jnz ntfsError jnz ntfsUnsupported
jmp ntfs_WriteFile.write jmp ntfs_WriteFile.write
.notFound: ; create; check name .notFound: ; create; check path folders
cmp dword [esp+4], 0 cmp dword [esp+4], 0
jnz .bad jnz ntfsNotFound
cmp byte [esi], 0 cmp byte [esi], 0
jnz @f jz ntfsNotFound
.bad: ; path folder not found ; 2. Prepare directory record
push ERROR_FILE_NOT_FOUND
jmp ntfsError
@@: ; 2. Prepair directory record
mov ecx, esi mov ecx, esi
@@: ; count characters @@: ; count characters
inc ecx inc ecx
cmp byte [ecx], '/' cmp byte [ecx], '/'
jz .bad jz ntfsNotFound
cmp byte [ecx], 0 cmp byte [ecx], 0
jnz @b jnz @b
sub ecx, esi sub ecx, esi
@ -2057,16 +2055,15 @@ ntfs_CreateFile:
mov edi, [ebp+NTFS.cur_index_buf] mov edi, [ebp+NTFS.cur_index_buf]
push esi push esi
push ecx push ecx
cmp dword [edi], 'INDX' ; where are we? cmp dword [edi], 'INDX'
jz .indexRecord jz .indexRecord
mov esi, [ebp+NTFS.frs_buffer] ; mftRecord mov esi, [ebp+NTFS.frs_buffer] ; indexRoot
mov edx, [esi+recordRealSize] mov edx, [esi+recordRealSize]
add edx, ecx add edx, ecx
cmp [esi+recordAllocatedSize], edx cmp [esi+recordAllocatedSize], edx
jnc @f jnc @f
add esp, 12 add esp, 12
push ERROR_UNSUPPORTED_FS ; indexAllocation required jmp ntfsUnsupported ; indexAllocation required
jmp ntfsError
@@: ; index fits in the indexRoot @@: ; index fits in the indexRoot
mov [esi+recordRealSize], edx mov [esi+recordRealSize], edx
mov ecx, edx mov ecx, edx
@ -2078,7 +2075,7 @@ ntfs_CreateFile:
mov esi, [esp] mov esi, [esp]
add [edi+sizeWithHeader], esi add [edi+sizeWithHeader], esi
add [edi+sizeWithoutHeader], esi add [edi+sizeWithoutHeader], esi
mov cx, [edi+attributeOffset] mov cl, [edi+attributeOffset]
add edi, ecx add edi, ecx
add [edi+16+nodeRealSize], esi add [edi+16+nodeRealSize], esi
add [edi+16+nodeAllocatedSize], esi add [edi+16+nodeAllocatedSize], esi
@ -2090,16 +2087,15 @@ ntfs_CreateFile:
jmp .common jmp .common
.indexRecord: .indexRecord:
mov edx, [edi+1ch] mov edx, [edi+28]
add edx, ecx add edx, ecx
cmp [edi+20h], edx cmp [edi+32], edx
jnc @f jnc @f
add esp, 12 add esp, 12
push ERROR_UNSUPPORTED_FS ; new node required jmp ntfsUnsupported ; new node required
jmp ntfsError
@@: ; index fits in the node @@: ; index fits in the node
mov [edi+1ch], edx mov [edi+28], edx
lea edi, [edi+edx+14h] lea edi, [edi+edx+24-4]
.common: .common:
mov esi, edi mov esi, edi
sub esi, [esp] sub esi, [esp]
@ -2159,7 +2155,7 @@ ntfs_CreateFile:
@@: ; 3. File data @@: ; 3. File data
cmp [ebp+NTFS.fileRealSize], 0 cmp [ebp+NTFS.fileRealSize], 0
jz .mftBitmap jz .mftBitmap
; One piece free space bitmap search engine ; One piece free space bitmap search engine
mov edi, [ebp+NTFS.BitmapBuffer] mov edi, [ebp+NTFS.BitmapBuffer]
add edi, [ebp+NTFS.BitmapStart] add edi, [ebp+NTFS.BitmapStart]
mov eax, [ebp+NTFS.fileDataSize] mov eax, [ebp+NTFS.fileDataSize]
@ -2167,12 +2163,10 @@ ntfs_CreateFile:
jz .small jz .small
push eax ; bitmap dwords push eax ; bitmap dwords
add edi, 4 add edi, 4
xor edx, edx
.start: .start:
mov ecx, [ebp+NTFS.BitmapSize] mov ecx, [ebp+NTFS.BitmapSize]
mov eax, edi add ecx, [ebp+NTFS.BitmapBuffer]
sub eax, [ebp+NTFS.BitmapBuffer] sub ecx, edi
sub ecx, eax
shr ecx, 2 shr ecx, 2
@@: @@:
xor eax, eax xor eax, eax
@ -2194,6 +2188,7 @@ ntfs_CreateFile:
jnz .start jnz .start
sub esi, 4 sub esi, 4
mov eax, [esi] mov eax, [esi]
xor edx, edx
bsr edx, eax bsr edx, eax
inc edx inc edx
push edx ; starting bit push edx ; starting bit
@ -2274,36 +2269,34 @@ ntfs_CreateFile:
mov [esp+4], ecx mov [esp+4], ecx
@@: @@:
mov edi, [esp] mov edi, [esp]
mov esi, [ebp+NTFS.fileDataSize] xor eax, eax
mov edx, [edi] dec eax
ror edx, cl shr eax, cl
shl eax, cl
neg ecx neg ecx
add ecx, 32 add ecx, 32
mov eax, -1 sub ecx, [ebp+NTFS.fileDataSize]
sub esi, ecx jc @f
jnc @f shl eax, cl ; fits inside dword
mov esi, ecx ; fits inside shr eax, cl
mov ecx, [ebp+NTFS.fileDataSize] or [edi], eax
shrd edx, eax, cl
sub esi, ecx
mov ecx, esi
ror edx, cl
mov [edi], edx
jmp .writeData jmp .writeData
@@: @@:
shrd edx, eax, cl or [edi], eax
mov [edi], edx neg ecx
mov ecx, esi push ecx
shr ecx, 5 shr ecx, 5
add edi, 4 add edi, 4
xor eax, eax
dec eax
rep stosd rep stosd
mov ecx, esi pop ecx
and ecx, 31 and ecx, 31
mov edx, [edi] shr eax, cl
shr edx, cl shl eax, cl
shld edx, eax, cl not eax
mov [edi], edx or [edi], eax
.writeData: .writeData:
pop edx pop edx
sub edx, [ebp+NTFS.BitmapBuffer] sub edx, [ebp+NTFS.BitmapBuffer]
@ -2319,10 +2312,7 @@ ntfs_CreateFile:
mov ebx, [ebx+16] mov ebx, [ebx+16]
call fs_write64_app call fs_write64_app
test eax, eax test eax, eax
jz .mftBitmap jnz ntfsDevice
push ERROR_DEVICE
jmp ntfsError
; 4. MFT record ; 4. MFT record
.mftBitmap: ; search for free record .mftBitmap: ; search for free record
mov edi, [ebp+NTFS.mftBitmapBuffer] mov edi, [ebp+NTFS.mftBitmapBuffer]
@ -2335,14 +2325,9 @@ ntfs_CreateFile:
movzx eax, byte [edi] movzx eax, byte [edi]
not al not al
bsf ecx, eax bsf ecx, eax
jnz @f jz ntfsUnsupported ; no free records
push ERROR_UNSUPPORTED_FS ; no free records bts [edi], ecx
jmp ntfsError ; get record location
@@: ; mark record
mov al, [edi]
bts eax, ecx
mov [edi], al
; get record location
sub edi, [ebp+NTFS.mftBitmapBuffer] sub edi, [ebp+NTFS.mftBitmapBuffer]
shl edi, 3 shl edi, 3
add edi, ecx add edi, ecx
@ -2359,12 +2344,11 @@ ntfs_CreateFile:
call ntfs_read_attr call ntfs_read_attr
cmp [ebp+NTFS.ntfs_cur_read], 0 cmp [ebp+NTFS.ntfs_cur_read], 0
jnz .mftRecord jnz .mftRecord
; extend MFT $DATA ; extend MFT $DATA
mov eax, [ebp+NTFS.mft_cluster] mov eax, [ebp+NTFS.mft_cluster]
mul [ebp+NTFS.sectors_per_cluster] mul [ebp+NTFS.sectors_per_cluster]
push ERROR_UNSUPPORTED_FS
cmp eax, [ebp+NTFS.ntfsLastRead] cmp eax, [ebp+NTFS.ntfsLastRead]
jnz ntfsError ; auxiliary record jnz ntfsUnsupported ; auxiliary record
mov edi, [ebp+NTFS.ntfs_attr_offs] mov edi, [ebp+NTFS.ntfs_attr_offs]
mov ebx, [ebp+NTFS.sectors_per_cluster] mov ebx, [ebp+NTFS.sectors_per_cluster]
shl ebx, 9+3 shl ebx, 9+3
@ -2375,8 +2359,9 @@ ntfs_CreateFile:
adc byte [edi+attributeRealSize+4], 0 adc byte [edi+attributeRealSize+4], 0
add [edi+initialDataSize], ebx add [edi+initialDataSize], ebx
adc byte [edi+initialDataSize+4], 0 adc byte [edi+initialDataSize+4], 0
add edi, [edi+dataRunsOffset] movzx eax, byte [edi+dataRunsOffset]
movzx eax, byte [edi] add edi, eax
mov al, [edi]
inc edi inc edi
shl eax, 4 shl eax, 4
shr al, 4 shr al, 4
@ -2386,13 +2371,13 @@ ntfs_CreateFile:
add ah, al add ah, al
shr eax, 8 shr eax, 8
cmp byte [edi+eax], 0 cmp byte [edi+eax], 0
jnz ntfsError ; $MFT fragmented jnz ntfsUnsupported ; $MFT fragmented
mov al, 8 mov al, 8
mov edx, [edi] mov edx, [edi]
rol eax, cl rol eax, cl
rol edx, cl rol edx, cl
add eax, edx add eax, edx
jc ntfsError jc ntfsUnsupported
ror eax, cl ror eax, cl
shr edx, cl shr edx, cl
mov [edi], eax mov [edi], eax
@ -2405,15 +2390,13 @@ ntfs_CreateFile:
mov ax, [edx] mov ax, [edx]
shr ax, cl shr ax, cl
test al, al test al, al
jnz ntfsError jnz ntfsUnsupported
dec al dec al
xchg [edx], al xchg [edx], al
mov [edx+1], al mov [edx+1], al
pop eax
push ERROR_OUT_OF_MEMORY
stdcall kernel_alloc, ebx stdcall kernel_alloc, ebx
test eax, eax test eax, eax
jz ntfsError jz ntfsNoMemory
mov ecx, ebx mov ecx, ebx
shr ecx, 2 shr ecx, 2
mov edi, eax mov edi, eax
@ -2427,8 +2410,6 @@ ntfs_CreateFile:
shr ecx, 9 shr ecx, 9
call fs_write64_sys ; clear new records call fs_write64_sys ; clear new records
stdcall kernel_free, ebx stdcall kernel_free, ebx
pop eax
push ERROR_DEVICE
mov eax, esi mov eax, esi
shr eax, 3+9 shr eax, 3+9
mov ebx, eax mov ebx, eax
@ -2439,12 +2420,12 @@ ntfs_CreateFile:
xor edx, edx xor edx, edx
call fs_write64_app ; partition bitmap call fs_write64_app ; partition bitmap
test eax, eax test eax, eax
jnz ntfsError jnz ntfsDevice
mov eax, [ebp+NTFS.frs_buffer] mov eax, [ebp+NTFS.frs_buffer]
mov [ebp+NTFS.ntfs_cur_buf], eax mov [ebp+NTFS.ntfs_cur_buf], eax
call writeRecord ; $MFT call writeRecord ; $MFT
test eax, eax test eax, eax
jnz ntfsError jnz ntfsDevice
mov eax, [ebp+NTFS.mftmirr_cluster] mov eax, [ebp+NTFS.mftmirr_cluster]
mul [ebp+NTFS.sectors_per_cluster] mul [ebp+NTFS.sectors_per_cluster]
mov ebx, [ebp+NTFS.frs_buffer] mov ebx, [ebp+NTFS.frs_buffer]
@ -2452,8 +2433,7 @@ ntfs_CreateFile:
dec ecx dec ecx
call fs_write64_sys ; $MFTMirr call fs_write64_sys ; $MFTMirr
test eax, eax test eax, eax
jnz ntfsError jnz ntfsDevice
pop eax
mov eax, [ebp+NTFS.ntfs_cur_offs] mov eax, [ebp+NTFS.ntfs_cur_offs]
add [ebp+NTFS.ntfsLastRead], eax add [ebp+NTFS.ntfsLastRead], eax
.mftRecord: .mftRecord:
@ -2466,7 +2446,7 @@ ntfs_CreateFile:
shr ecx, 2 shr ecx, 2
rep stosd rep stosd
mov edi, [ebp+NTFS.frs_buffer] mov edi, [ebp+NTFS.frs_buffer]
; record header ; record header
mov dword[edi], 'FILE' mov dword[edi], 'FILE'
mov byte [edi+updateSequenceOffset], 2ah mov byte [edi+updateSequenceOffset], 2ah
mov byte [edi+updateSequenceSize], 3 mov byte [edi+updateSequenceSize], 3
@ -2478,13 +2458,13 @@ ntfs_CreateFile:
rdtsc rdtsc
mov [edi+2ah], ax mov [edi+2ah], ax
add edi, 30h add edi, 30h
; $StandardInformation ; $StandardInformation
mov byte [edi+attributeType], 10h mov byte [edi+attributeType], 10h
mov byte [edi+sizeWithHeader], 48h mov byte [edi+sizeWithHeader], 48h
mov byte [edi+sizeWithoutHeader], 30h mov byte [edi+sizeWithoutHeader], 30h
mov byte [edi+attributeOffset], 18h mov byte [edi+attributeOffset], 18h
add edi, 48h add edi, 48h
; $FileName ; $FileName
mov byte [edi+attributeType], 30h mov byte [edi+attributeType], 30h
mov byte [edi+attributeID], 1 mov byte [edi+attributeID], 1
mov cx, [esi+indexRawSize] mov cx, [esi+indexRawSize]
@ -2493,7 +2473,7 @@ ntfs_CreateFile:
add ecx, 8 add ecx, 8
mov [edi+sizeWithHeader], ecx mov [edi+sizeWithHeader], ecx
mov byte [edi+attributeOffset], 18h mov byte [edi+attributeOffset], 18h
mov byte [edi+attributeFlags], 1 mov byte [edi+indexedFlag], 1
add edi, 18h add edi, 18h
add esi, 16 add esi, 16
sub ecx, 18h sub ecx, 18h
@ -2501,7 +2481,7 @@ ntfs_CreateFile:
rep movsd rep movsd
cmp [ebp+NTFS.ntfsFolder], 0 cmp [ebp+NTFS.ntfsFolder], 0
jnz @f jnz @f
; $Data ; $Data
mov byte [edi+attributeType], 80h mov byte [edi+attributeType], 80h
cmp [ebp+NTFS.fileRealSize], 0 cmp [ebp+NTFS.fileRealSize], 0
jz .zeroSize jz .zeroSize
@ -2536,19 +2516,17 @@ ntfs_CreateFile:
mov byte [edi+attributeOffset], 20h mov byte [edi+attributeOffset], 20h
mov dword[edi+18h], 490024h ; unicode $I30 mov dword[edi+18h], 490024h ; unicode $I30
mov dword[edi+18h+4], 300033h mov dword[edi+18h+4], 300033h
add edi, 20h mov byte [edi+20h+attributeType], 30h
mov byte [edi+attributeType], 30h mov byte [edi+20h+collationRule], 1
mov byte [edi+collationRule], 1
mov eax, [ebp+NTFS.sectors_per_cluster] mov eax, [ebp+NTFS.sectors_per_cluster]
shl eax, 9 shl eax, 9
mov [edi+indexRecordSize], eax mov [edi+20h+indexRecordSize], eax
mov byte [edi+indexRecordSizeClus], 1 mov byte [edi+20h+indexRecordSizeClus], 1
mov byte [edi+16+indexOffset], 16 mov byte [edi+30h+indexOffset], 16
mov byte [edi+16+nodeRealSize], 32 mov byte [edi+30h+nodeRealSize], 32
mov byte [edi+16+nodeAllocatedSize], 32 mov byte [edi+30h+nodeAllocatedSize], 32
mov byte [edi+32+indexAllocatedSize], 16 mov byte [edi+40h+indexAllocatedSize], 16
mov byte [edi+32+indexFlags], 2 mov byte [edi+40h+indexFlags], 2
sub edi, 20h
mov al, 3 mov al, 3
.writeMftRecord: .writeMftRecord:
mov byte [edi+sizeWithHeader], 50h mov byte [edi+sizeWithHeader], 50h
@ -2559,13 +2537,10 @@ ntfs_CreateFile:
mov [ebp+NTFS.ntfs_cur_buf], edi mov [ebp+NTFS.ntfs_cur_buf], edi
call writeRecord call writeRecord
test eax, eax test eax, eax
jz @f jnz ntfsDevice
push ERROR_DEVICE
jmp ntfsError
@@:
mov esi, [ebp+PARTITION.Disk] mov esi, [ebp+PARTITION.Disk]
call disk_sync call disk_sync
; write MFT bitmap ; write MFT bitmap
mov eax, [ebp+NTFS.newMftRecord] mov eax, [ebp+NTFS.newMftRecord]
shr eax, 3+9 shr eax, 3+9
mov ebx, eax mov ebx, eax
@ -2576,10 +2551,8 @@ ntfs_CreateFile:
xor edx, edx xor edx, edx
call fs_write64_sys call fs_write64_sys
test eax, eax test eax, eax
jz @f jnz ntfsDevice
push ERROR_DEVICE ; 5. Write partition bitmap
jmp ntfsError
@@: ; 5. Write partition bitmap
cmp [ebp+NTFS.ntfsFolder], 0 cmp [ebp+NTFS.ntfsFolder], 0
jnz @f jnz @f
cmp [ebp+NTFS.fileRealSize], 0 cmp [ebp+NTFS.fileRealSize], 0
@ -2598,27 +2571,27 @@ ntfs_CreateFile:
xor edx, edx xor edx, edx
call fs_write64_app call fs_write64_app
test eax, eax test eax, eax
jz @f jnz ntfsDevice
push ERROR_DEVICE
jmp ntfsError
@@: @@:
mov esi, [ebp+PARTITION.Disk] mov esi, [ebp+PARTITION.Disk]
call disk_sync call disk_sync
mov edi, [ebp+NTFS.indexOffset] mov edi, [ebp+NTFS.indexOffset]
mov eax, [ebp+NTFS.newMftRecord] mov eax, [ebp+NTFS.newMftRecord]
mov [edi+fileRecordReference], eax mov [edi+fileRecordReference], eax
; 6. Write directory node ; 6. Write directory node
mov eax, [ebp+NTFS.nodeLastRead] mov eax, [ebp+NTFS.nodeLastRead]
mov [ebp+NTFS.ntfsLastRead], eax mov [ebp+NTFS.ntfsLastRead], eax
mov eax, [ebp+NTFS.cur_index_buf] mov eax, [ebp+NTFS.cur_index_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax mov [ebp+NTFS.ntfs_cur_buf], eax
call writeRecord call writeRecord
push eax test eax, eax
jnz ntfsDevice
mov ebx, [ebp+NTFS.fileRealSize]
ntfsDone:
mov esi, [ebp+PARTITION.Disk] mov esi, [ebp+PARTITION.Disk]
call disk_sync call disk_sync
call ntfs_unlock call ntfs_unlock
pop eax xor eax, eax
mov ebx, [ebp+NTFS.fileRealSize]
ret ret
writeRecord: writeRecord:
@ -2641,7 +2614,7 @@ writeRecord:
mov [esi-2], ax mov [esi-2], ax
dec ecx dec ecx
jnz @b jnz @b
; writing to disk ; writing to disk
mov eax, [ebp+NTFS.ntfsLastRead] mov eax, [ebp+NTFS.ntfsLastRead]
mov ebx, [ebp+NTFS.ntfs_cur_buf] mov ebx, [ebp+NTFS.ntfs_cur_buf]
pop ecx pop ecx
@ -2651,6 +2624,8 @@ writeRecord:
bitmapBuffering: bitmapBuffering:
; Extend BitmapBuffer and read next 32kb of bitmap ; Extend BitmapBuffer and read next 32kb of bitmap
; Warning: $Bitmap fragmentation is not foreseen ; Warning: $Bitmap fragmentation is not foreseen
; if edi -> position in bitmap buffer,
; then ecx = number of buffered dwords left
push ebx push ebx
mov eax, [ebp+NTFS.BitmapTotalSize] mov eax, [ebp+NTFS.BitmapTotalSize]
cmp eax, [ebp+NTFS.BitmapSize] cmp eax, [ebp+NTFS.BitmapSize]
@ -2680,9 +2655,8 @@ bitmapBuffering:
mov [ebp+NTFS.BitmapSize], eax mov [ebp+NTFS.BitmapSize], eax
@@: @@:
mov ecx, [ebp+NTFS.BitmapSize] mov ecx, [ebp+NTFS.BitmapSize]
mov eax, edi add ecx, [ebp+NTFS.BitmapBuffer]
sub eax, [ebp+NTFS.BitmapBuffer] sub ecx, edi
sub ecx, eax
shr ecx, 2 shr ecx, 2
pop ebx pop ebx
ret ret
@ -2695,7 +2669,7 @@ bitmapBuffering:
.end: .end:
add esp, 12 ; double ret add esp, 12 ; double ret
push ERROR_DISK_FULL push ERROR_DISK_FULL
jmp ntfsError jmp ntfsOut
;---------------------------------------------------------------- ;----------------------------------------------------------------
ntfs_WriteFile: ntfs_WriteFile:
@ -2707,39 +2681,34 @@ ntfs_WriteFile:
@@: @@:
call ntfs_lock call ntfs_lock
stdcall ntfs_find_lfn, [esp+4] stdcall ntfs_find_lfn, [esp+4]
jnc .found jc ntfsNotFound
push ERROR_FILE_NOT_FOUND cmp [ebp+NTFS.ntfs_cur_iRecord], 16
jmp ntfsError jc ntfsDenied
.found:
mov [ebp+NTFS.ntfs_cur_attr], 0x80 mov [ebp+NTFS.ntfs_cur_attr], 0x80
mov [ebp+NTFS.ntfs_cur_offs], 0 mov [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 0 mov [ebp+NTFS.ntfs_cur_size], 0
call ntfs_read_attr call ntfs_read_attr
jnc @f jc ntfsDenied
push ERROR_ACCESS_DENIED
jmp ntfsError
@@:
push ERROR_UNSUPPORTED_FS
mov eax, [ebp+NTFS.frs_buffer] mov eax, [ebp+NTFS.frs_buffer]
cmp word [eax+baseRecordReuse], 0 cmp word [eax+baseRecordReuse], 0
jnz ntfsError ; auxiliary record jnz ntfsUnsupported ; auxiliary record
cmp byte [eax+hardLinkCounter], 1 cmp byte [eax+hardLinkCounter], 1
jnz ntfsError ; file copying required jnz ntfsUnsupported ; file copying required
mov ecx, [ebp+NTFS.ntfs_attr_offs] mov ecx, [ebp+NTFS.ntfs_attr_offs]
cmp byte [ecx+nonResidentFlag], 1 cmp byte [ecx+nonResidentFlag], 1
jnz ntfsError ; resident $DATA jnz ntfsUnsupported ; resident $DATA
cmp word [ecx+attributeFlags], 0
jnz ntfsUnsupported
mov eax, [ebx+4] mov eax, [ebx+4]
mov edx, [ebx+8] mov edx, [ebx+8]
add eax, [ebx+12] add eax, [ebx+12]
adc edx, 0 adc edx, 0
cmp edx, [ecx+attributeRealSize+4] cmp edx, [ecx+attributeRealSize+4]
jc .write jc .write
jnz ntfsError ; end of file jnz ntfsUnsupported ; end of file
cmp [ecx+attributeRealSize], eax cmp [ecx+attributeRealSize], eax
jc ntfsError jc ntfsUnsupported
.write: .write:
pop eax
push ERROR_DEVICE
mov eax, [ebx+4] mov eax, [ebx+4]
mov edx, [ebx+8] mov edx, [ebx+8]
mov ecx, [ebx+12] mov ecx, [ebx+12]
@ -2752,7 +2721,7 @@ ntfs_WriteFile:
lea edi, [ebp+NTFS.ntfs_bitmap_buf] lea edi, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], edi mov [ebp+NTFS.ntfs_cur_buf], edi
call ntfs_read_attr.continue call ntfs_read_attr.continue
jc ntfsError jc ntfsDevice
mov eax, [ebx+4] mov eax, [ebx+4]
and eax, 1FFh and eax, 1FFh
add edi, eax add edi, eax
@ -2774,7 +2743,7 @@ ntfs_WriteFile:
pop ebx pop ebx
pop ecx pop ecx
test eax, eax test eax, eax
jnz ntfsError jnz ntfsDevice
test ecx, ecx test ecx, ecx
jz @f jz @f
mov eax, [ebx+4] mov eax, [ebx+4]
@ -2794,7 +2763,7 @@ ntfs_WriteFile:
mov [ebp+NTFS.ntfsWriteAttr], 0 mov [ebp+NTFS.ntfsWriteAttr], 0
pop [ebp+NTFS.ntfs_cur_offs] pop [ebp+NTFS.ntfs_cur_offs]
pop ecx pop ecx
jc ntfsError jc ntfsDevice
and ecx, 1FFh and ecx, 1FFh
jz @f jz @f
add esi, [ebp+NTFS.ntfs_cur_read] add esi, [ebp+NTFS.ntfs_cur_read]
@ -2802,7 +2771,7 @@ ntfs_WriteFile:
lea edi, [ebp+NTFS.ntfs_bitmap_buf] lea edi, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], edi mov [ebp+NTFS.ntfs_cur_buf], edi
call ntfs_read_attr.continue call ntfs_read_attr.continue
jc ntfsError jc ntfsDevice
rep movsb rep movsb
push ebx push ebx
mov eax, [ebp+NTFS.ntfsLastRead] mov eax, [ebp+NTFS.ntfsLastRead]
@ -2811,20 +2780,216 @@ ntfs_WriteFile:
xor edx, edx xor edx, edx
call fs_write64_app call fs_write64_app
pop ebx pop ebx
test eax, eax
jnz ntfsDevice
@@: @@:
mov esi, [ebp+PARTITION.Disk]
call disk_sync
call ntfs_unlock
pop eax
xor eax, eax
mov ebx, [ebx+12] mov ebx, [ebx+12]
jmp ntfsDone
;----------------------------------------------------------------
ntfs_Delete:
cmp byte [esi], 0
jnz @f
xor ebx, ebx
movi eax, ERROR_ACCESS_DENIED
ret ret
@@:
call ntfs_lock
stdcall ntfs_find_lfn, [esp+4]
jc ntfsNotFound
cmp [ebp+NTFS.ntfs_cur_iRecord], 16
jc ntfsDenied
cmp [ebp+NTFS.ntfsFragmentCount], 1
jnz ntfsUnsupported ; record fragmented
test byte [eax+indexFlags], 1
jnz ntfsUnsupported ; index has a subnode
mov edx, [ebp+NTFS.ntfs_cur_iRecord]
shr edx, 3
cmp edx, [ebp+NTFS.mftBitmapSize]
jnc ntfsUnsupported
; delete index from the node
movzx edx, word [eax+indexAllocatedSize]
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]
mov edi, [ebp+NTFS.ntfs_attr_offs]
sub edi, [ebp+NTFS.frs_buffer]
add edi, esi
sub [edi+sizeWithHeader], edx
sub [edi+sizeWithoutHeader], edx
mov cl, [edi+attributeOffset]
add edi, ecx
sub [edi+16+nodeRealSize], edx
sub [edi+16+nodeAllocatedSize], edx
sub eax, esi
add eax, edi
sub [esi+recordRealSize], edx
mov ecx, [esi+recordRealSize]
jmp @f
.indexRecord:
sub [edi+28], edx
mov ecx, [edi+28]
add ecx, 24
@@:
add ecx, [ebp+NTFS.cur_index_buf]
sub ecx, eax
shr ecx, 2
mov esi, eax
add esi, edx
mov edi, eax
rep movsd
mov eax, [ebp+NTFS.ntfsLastRead]
mov [ebp+NTFS.nodeLastRead], eax
; examine file record
mov [ebp+NTFS.ntfs_cur_attr], 0x80
mov [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 0
call ntfs_read_attr
jc .folder
mov esi, [ebp+NTFS.frs_buffer]
cmp word [esi+baseRecordReuse], 0
jnz ntfsUnsupported ; auxiliary record
cmp byte [esi+hardLinkCounter], 2
jnc .writeFileRecord ; delete hard link
mov esi, [ebp+NTFS.ntfs_attr_offs]
cmp byte [esi+nonResidentFlag], 0
jz .writeBitmapMFT
movzx eax, byte [esi+dataRunsOffset]
add esi, eax
xor edi, edi
sub esp, 16
.clearBitmap: ; "delete" file data
call ntfs_decode_mcb_entry
jnc .mcbEnd
cmp dword[esp+8], 0
jz .clearBitmap
add edi, [esp+8]
mov ebx, [esp]
mov eax, edi
add eax, ebx
shr eax, 3
inc eax
cmp eax, [ebp+NTFS.BitmapSize]
jc .buffered
add eax, [ebp+NTFS.BitmapBuffer]
add esp, 16
push edi
mov edi, eax
@@:
call bitmapBuffering
shl ecx, 2
js @b
pop edi
sub esp, 16
.buffered:
push edi
mov ecx, edi
shr edi, 5
shl edi, 2
add edi, [ebp+NTFS.BitmapBuffer]
and ecx, 31
xor eax, eax
dec eax
shr eax, cl
shl eax, cl
neg ecx
add ecx, 32
sub ecx, ebx
jc @f
shl eax, cl ; fits inside dword
shr eax, cl
not eax
and [edi], eax
jmp .writeBitmap
@@:
not eax
and [edi], eax
neg ecx
push ecx
shr ecx, 5
add edi, 4
xor eax, eax
rep stosd
pop ecx
and ecx, 31
dec eax
shr eax, cl
shl eax, cl
and [edi], eax
.writeBitmap:
pop edi
mov ecx, edi
add ecx, ebx
add ecx, 4095
shr ecx, 3+9
mov eax, edi
shr eax, 3+9
sub ecx, eax
mov ebx, eax
shl ebx, 9
add eax, [ebp+NTFS.BitmapLocation]
add ebx, [ebp+NTFS.BitmapBuffer]
xor edx, edx
call fs_write64_app
jmp .clearBitmap
.mcbEnd:
add esp, 16
jmp .writeBitmapMFT
.folder: ; empty?
lea esi, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], esi
mov [ebp+NTFS.ntfs_cur_attr], 0x90
mov [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 1
call ntfs_read_attr
cmp [ebp+NTFS.ntfs_cur_read], 48
jnz ntfsDenied
test byte [esi+32+indexFlags], 1
jnz ntfsDenied
.writeBitmapMFT: ; "delete" file record
mov eax, [ebp+NTFS.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
mov esi, [ebp+NTFS.frs_buffer]
mov byte [esi+recordFlags], 0
.writeFileRecord:
dec byte [esi+hardLinkCounter]
mov [ebp+NTFS.ntfs_cur_buf], esi
call writeRecord
; write directory node
mov eax, [ebp+NTFS.nodeLastRead]
mov [ebp+NTFS.ntfsLastRead], eax
mov eax, [ebp+NTFS.cur_index_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax
call writeRecord
test eax, eax
jz ntfsDone
jmp ntfsDevice
;---------------------------------------------------------------- ;----------------------------------------------------------------
ntfs_SetFileEnd: ntfs_SetFileEnd:
ntfs_SetFileInfo: ntfs_SetFileInfo:
ntfs_Delete: movi eax, ERROR_UNSUPPORTED_FS
mov eax, ERROR_UNSUPPORTED_FS
ret ret
;---------------------------------------------------------------- ;----------------------------------------------------------------
@ -2837,12 +3002,9 @@ ntfs_GetFileInfo:
call ntfs_lock call ntfs_lock
stdcall ntfs_find_lfn, [esp+4] stdcall ntfs_find_lfn, [esp+4]
jnc .found jnc .found
push ERROR_FILE_NOT_FOUND
test eax, eax test eax, eax
jnz ntfsError jz ntfsFail
pop eax jmp ntfsNotFound
push ERROR_FS_FAIL
jmp ntfsError
.found: .found:
push esi edi push esi edi
mov esi, eax mov esi, eax
@ -2854,8 +3016,25 @@ ntfs_GetFileInfo:
xor eax, eax xor eax, eax
ret ret
ntfsError: ntfsUnsupported:
push ERROR_UNSUPPORTED_FS
ntfsOut:
call ntfs_unlock call ntfs_unlock
xor ebx, ebx xor ebx, ebx
pop eax pop eax
ret ret
ntfsDevice:
push ERROR_DEVICE
jmp ntfsOut
ntfsNotFound:
push ERROR_FILE_NOT_FOUND
jmp ntfsOut
ntfsDenied:
push ERROR_ACCESS_DENIED
jmp ntfsOut
ntfsFail:
push ERROR_FS_FAIL
jmp ntfsOut
ntfsNoMemory:
push ERROR_OUT_OF_MEMORY
jmp ntfsOut