Subversion Repositories Kolibri OS

Rev

Rev 6824 | Rev 6869 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
6080 pathoswith 3
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
6462 pathoswith 4
;;  Distributed under terms of the GNU General Public License.  ;;
2288 clevermous 5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 6845 $
9
 
6462 pathoswith 10
; NTFS external functions
11
;   in:
12
; ebx -> parameter structure of sysfunc 70
13
; ebp -> NTFS structure
6471 pathoswith 14
; esi -> path string in UTF-8
6462 pathoswith 15
;   out:
16
; eax, ebx = return values for sysfunc 70
17
iglobal
18
align 4
19
ntfs_user_functions:
20
        dd      ntfs_free
21
        dd      (ntfs_user_functions_end - ntfs_user_functions - 4) / 4
22
        dd      ntfs_ReadFile
23
        dd      ntfs_ReadFolder
24
        dd      ntfs_CreateFile
25
        dd      ntfs_WriteFile
26
        dd      ntfs_SetFileEnd
27
        dd      ntfs_GetFileInfo
28
        dd      ntfs_SetFileInfo
29
        dd      0
30
        dd      ntfs_Delete
31
        dd      ntfs_CreateFolder
32
ntfs_user_functions_end:
33
endg
5954 pathoswith 34
 
35
; Basic concepts:
36
; File is a FileRecord in the $MFT.
37
; $MFT is a file, that consists of FileRecords and starts with FileRecord of itself.
38
; FileRecord (FILE) consists of a header and attributes.
39
; Attribute consists of a header and a body.
40
; Attribute's body can be inside (resident) or outside of FileRecord.
41
; File's data is a body of $Data (80h) attribute.
42
; FileRecords is a data of the $MFT file.
43
; Directory is a file, that consists of index nodes.
44
; Resident index node is always located in a body of $IndexRoot (90h) attribute.
45
; Body of $IndexAllocation (A0h) attribute is always non resident
46
;  and consists of IndexRecords.
47
; IndexRecord (INDX) consists of a header and an index node.
48
; Index node consists of a header and indexes.
49
; Index consists of a header and a copy of indexed attribute's body.
50
; Directories index $Filename (30h) attribute of all existing files.
51
; $IndexRoot and $IndexAllocation attributes of a directory has a name — $I30.
52
 
53
; Offsets:
54
    ; record header
6273 pathoswith 55
magic = 0
5954 pathoswith 56
updateSequenceOffset = 4
57
updateSequenceSize = 6
6273 pathoswith 58
    ; FileRecord header
5954 pathoswith 59
reuseCounter = 16
60
hardLinkCounter = 12h
61
attributeOffset = 14h
62
recordFlags = 16h
63
recordRealSize = 18h
64
recordAllocatedSize = 1ch
5994 pathoswith 65
baseRecordReference = 20h       ; for auxiliary records
66
baseRecordReuse = 26h
5954 pathoswith 67
newAttributeID = 28h
68
    ; attribute header
69
attributeType = 0
70
sizeWithHeader = 4
71
nonResidentFlag = 8
72
nameLength = 9
73
nameOffset = 10
6019 pathoswith 74
attributeFlags = 12
5954 pathoswith 75
attributeID = 14
6080 pathoswith 76
    ; resident attribute header
77
sizeWithoutHeader = 10h
6273 pathoswith 78
attributeOffset = 14h
6019 pathoswith 79
indexedFlag = 16h
5954 pathoswith 80
    ; non resident attribute header
6080 pathoswith 81
firstVCN = 10h
5954 pathoswith 82
lastVCN = 18h
83
dataRunsOffset = 20h
84
attributeAllocatedSize = 28h
85
attributeRealSize = 30h
86
initialDataSize = 38h
87
    ; $IndexRoot
6273 pathoswith 88
indexedAttributesType = 0
5954 pathoswith 89
collationRule = 4
90
indexRecordSize = 8
6340 pathoswith 91
indexRecordSizeClus = 12        ; in sectors if less than one cluster
6273 pathoswith 92
rootNode = 16
93
    ; IndexRecord header
94
recordVCN = 16
95
recordNode = 18h
5954 pathoswith 96
    ; node header
97
indexOffset = 0
98
nodeRealSize = 4
99
nodeAllocatedSize = 8
6273 pathoswith 100
nonLeafFlag = 12
5954 pathoswith 101
    ; $Filename index
102
fileRecordReference = 0
103
fileReferenceReuse = 6
104
indexAllocatedSize = 8
105
indexRawSize = 10
106
indexFlags = 12
107
directoryRecordReference = 16
108
directoryReferenceReuse = 16h
6297 pathoswith 109
fileCreated = 18h
110
fileModified = 20h
111
recordModified = 28h
112
fileAccessed = 30h
5954 pathoswith 113
fileAllocatedSize = 38h
114
fileRealSize = 40h
115
fileFlags = 48h
116
fileNameLength = 50h
6297 pathoswith 117
namespace = 51h
118
fileName = 52h
5954 pathoswith 119
 
3742 clevermous 120
struct NTFS PARTITION
6462 pathoswith 121
Lock                MUTEX   ; Currently operations with one partition
5954 pathoswith 122
; can not be executed in parallel since the legacy code is not ready.
6273 pathoswith 123
sectors_per_cluster dd  ?
124
mft_cluster         dd  ?   ; location
125
mftmirr_cluster     dd  ?   ; location
126
frs_size            dd  ?   ; in bytes
127
frs_buffer          dd  ?   ; MFT fileRecord buffer
128
mft_retrieval_end   dd  ?
6405 pathoswith 129
mftSize             dd  ?   ; in sectors
6273 pathoswith 130
cur_index_size      dd  ?   ; in sectors
131
cur_index_buf       dd  ?   ; index node buffer
6340 pathoswith 132
secondIndexBuffer   dd  ?
6273 pathoswith 133
BitmapBuffer        dd  ?
134
BitmapTotalSize     dd  ?   ; bytes reserved
135
BitmapSize          dd  ?   ; bytes readen
136
BitmapLocation      dd  ?   ; starting sector
137
BitmapStart         dd  ?   ; first byte after area, reserved for MFT
138
mftBitmapBuffer     dd  ?   ; one cluster
139
mftBitmapSize       dd  ?   ; bytes readen
140
mftBitmapLocation   dd  ?   ; starting sector
2288 clevermous 141
 
6405 pathoswith 142
attr_size           dq  ?
143
attr_offs           dd  ?
144
attr_list           dd  ?
145
attr_iBaseRecord    dd  ?
6273 pathoswith 146
cur_attr            dd  ?   ; attribute type
147
cur_iRecord         dd  ?   ; number of fileRecord in MFT
148
cur_offs            dd  ?   ; attribute VCN in sectors
149
cur_size            dd  ?   ; max sectors to read
150
cur_buf             dd  ?
151
cur_read            dd  ?   ; bytes readen
6405 pathoswith 152
cur_tail            dd  ?
153
cur_subnode_size    dd  ?
6273 pathoswith 154
LastRead            dd  ?   ; last readen block of sectors
6408 pathoswith 155
mftLastRead         dd  ?
6340 pathoswith 156
rootLastRead        dd  ?
157
nodeLastRead        dd  ?
158
indexRoot           dd  ?
6405 pathoswith 159
indexPointer        dd  ?
6340 pathoswith 160
newRecord           dd  ?
6273 pathoswith 161
fileDataStart       dd  ?   ; starting cluster
162
fileDataSize        dd  ?   ; in clusters
6292 pathoswith 163
fileDataBuffer      dd  ?
6273 pathoswith 164
fileRealSize        dd  ?   ; in bytes
165
fragmentCount       db  ?
166
bCanContinue        db  ?
167
bFolder             db  ?
168
bWriteAttr          db  ?   ; Warning: Don't forget to turn off!!!
3742 clevermous 169
 
6558 pathoswith 170
mft_retrieval       rb  512
171
align0  rb  1024-NTFS.align0
6405 pathoswith 172
attrlist_buf        rb  1024
173
attrlist_mft_buf    rb  1024
174
bitmap_buf          rb  1024
3742 clevermous 175
ends
176
 
2288 clevermous 177
ntfs_test_bootsec:
5954 pathoswith 178
; in: ebx -> buffer, edx = size of partition
179
; out: CF=1 -> invalid
2288 clevermous 180
; 1. Name=='NTFS    '
181
        cmp     dword [ebx+3], 'NTFS'
182
        jnz     .no
183
        cmp     dword [ebx+7], '    '
184
        jnz     .no
185
; 2. Number of bytes per sector is the same as for physical device
186
; (that is, 0x200 for hard disk)
187
        cmp     word [ebx+11], 0x200
188
        jnz     .no
189
; 3. Number of sectors per cluster must be power of 2
190
        movzx   eax, byte [ebx+13]
191
        dec     eax
192
        js      .no
193
        test    al, [ebx+13]
194
        jnz     .no
195
; 4. FAT parameters must be zero
196
        cmp     word [ebx+14], 0
197
        jnz     .no
198
        cmp     dword [ebx+16], 0
199
        jnz     .no
200
        cmp     byte [ebx+20], 0
201
        jnz     .no
202
        cmp     word [ebx+22], 0
203
        jnz     .no
204
        cmp     dword [ebx+32], 0
205
        jnz     .no
206
; 5. Number of sectors <= partition size
207
        cmp     dword [ebx+0x2C], 0
208
        ja      .no
209
        cmp     [ebx+0x28], edx
210
        ja      .no
211
; 6. $MFT and $MFTMirr clusters must be within partition
212
        cmp     dword [ebx+0x34], 0
213
        ja      .no
214
        push    edx
215
        movzx   eax, byte [ebx+13]
216
        mul     dword [ebx+0x30]
217
        test    edx, edx
218
        pop     edx
219
        jnz     .no
220
        cmp     eax, edx
221
        ja      .no
222
        cmp     dword [ebx+0x3C], 0
223
        ja      .no
224
        push    edx
225
        movzx   eax, byte [ebx+13]
226
        mul     dword [ebx+0x38]
227
        test    edx, edx
228
        pop     edx
229
        jnz     .no
230
        cmp     eax, edx
231
        ja      .no
5954 pathoswith 232
; 7. Clusters per FRS must be either power of 2 or between -31 and -9
2288 clevermous 233
        movsx   eax, byte [ebx+0x40]
234
        cmp     al, -31
235
        jl      .no
236
        cmp     al, -9
237
        jle     @f
238
        dec     eax
239
        js      .no
240
        test    [ebx+0x40], al
241
        jnz     .no
5954 pathoswith 242
@@:         ; 8. Same for clusters per IndexAllocationBuffer
2288 clevermous 243
        movsx   eax, byte [ebx+0x44]
244
        cmp     al, -31
245
        jl      .no
246
        cmp     al, -9
247
        jle     @f
248
        dec     eax
249
        js      .no
250
        test    [ebx+0x44], al
251
        jnz     .no
5954 pathoswith 252
@@:         ; OK, this is correct NTFS bootsector
2288 clevermous 253
        clc
254
        ret
5954 pathoswith 255
.no:        ; No, this bootsector isn't NTFS
2288 clevermous 256
        stc
257
        ret
258
 
6462 pathoswith 259
; Mount if it's a valid NTFS partition.
5954 pathoswith 260
ntfs_create_partition:
6462 pathoswith 261
;   in:
262
; ebp -> PARTITION structure
263
; ebx -> boot sector
264
; ebx+512 -> buffer
265
;   out:
266
; eax -> NTFS structure, 0 = not NTFS
5089 clevermous 267
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
268
        jnz     .nope
3742 clevermous 269
        mov     edx, dword [ebp+PARTITION.Length]
270
        cmp     dword [esp+4], 0
271
        jz      .boot_read_ok
272
        add     ebx, 512
273
        lea     eax, [edx-1]
274
        call    fs_read32_sys
275
        test    eax, eax
276
        jnz     @f
277
        call    ntfs_test_bootsec
278
        jnc     .ntfs_setup
279
@@:
280
        mov     eax, edx
281
        shr     eax, 1
282
        call    fs_read32_sys
283
        test    eax, eax
5954 pathoswith 284
        jnz     .nope
3742 clevermous 285
.boot_read_ok:
286
        call    ntfs_test_bootsec
287
        jnc     .ntfs_setup
288
.nope:
289
        xor     eax, eax
290
        jmp     .exit
6297 pathoswith 291
 
6405 pathoswith 292
.ntfs_setup:    ; By given bootsector, initialize some NTFS variables
293
        stdcall kernel_alloc, 1000h
3742 clevermous 294
        test    eax, eax
295
        jz      .exit
296
        mov     ecx, dword [ebp+PARTITION.FirstSector]
297
        mov     dword [eax+NTFS.FirstSector], ecx
298
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
299
        mov     dword [eax+NTFS.FirstSector+4], ecx
300
        mov     ecx, [ebp+PARTITION.Disk]
301
        mov     [eax+NTFS.Disk], ecx
302
        mov     [eax+NTFS.FSUserFunctions], ntfs_user_functions
6273 pathoswith 303
        mov     [eax+NTFS.bWriteAttr], 0
5954 pathoswith 304
 
3742 clevermous 305
        push    ebx ebp esi
306
        mov     ebp, eax
307
        lea     ecx, [ebp+NTFS.Lock]
308
        call    mutex_init
2288 clevermous 309
        movzx   eax, byte [ebx+13]
3742 clevermous 310
        mov     [ebp+NTFS.sectors_per_cluster], eax
2288 clevermous 311
        mov     eax, [ebx+0x28]
3742 clevermous 312
        mov     dword [ebp+NTFS.Length], eax
313
        and     dword [ebp+NTFS.Length+4], 0
2288 clevermous 314
        mov     eax, [ebx+0x30]
3742 clevermous 315
        mov     [ebp+NTFS.mft_cluster], eax
2288 clevermous 316
        mov     eax, [ebx+0x38]
3742 clevermous 317
        mov     [ebp+NTFS.mftmirr_cluster], eax
2288 clevermous 318
        movsx   eax, byte [ebx+0x40]
319
        test    eax, eax
5954 pathoswith 320
        js      @f
3742 clevermous 321
        mul     [ebp+NTFS.sectors_per_cluster]
2288 clevermous 322
        shl     eax, 9
5954 pathoswith 323
        jmp     .1
6297 pathoswith 324
 
5954 pathoswith 325
@@:
2288 clevermous 326
        neg     eax
327
        mov     ecx, eax
328
        mov     eax, 1
329
        shl     eax, cl
5954 pathoswith 330
.1:
3742 clevermous 331
        mov     [ebp+NTFS.frs_size], eax
5954 pathoswith 332
        stdcall kernel_alloc, eax
2288 clevermous 333
        test    eax, eax
3742 clevermous 334
        jz      .fail_free
335
        mov     [ebp+NTFS.frs_buffer], eax
2288 clevermous 336
; read $MFT disposition
3742 clevermous 337
        mov     eax, [ebp+NTFS.mft_cluster]
338
        mul     [ebp+NTFS.sectors_per_cluster]
6405 pathoswith 339
        mov     ecx, [ebp+NTFS.frs_size]
340
        shr     ecx, 9
341
        mov     ebx, [ebp+NTFS.frs_buffer]
342
        call    fs_read64_sys
3742 clevermous 343
        test    eax, eax
2288 clevermous 344
        jnz     .usemirr
345
        cmp     dword [ebx], 'FILE'
346
        jnz     .usemirr
347
        call    ntfs_restore_usa_frs
348
        jnc     .mftok
349
.usemirr:
3742 clevermous 350
        mov     eax, [ebp+NTFS.mftmirr_cluster]
351
        mul     [ebp+NTFS.sectors_per_cluster]
6405 pathoswith 352
        mov     ecx, [ebp+NTFS.frs_size]
353
        shr     ecx, 9
354
        mov     ebx, [ebp+NTFS.frs_buffer]
355
        call    fs_read64_sys
3742 clevermous 356
        test    eax, eax
5954 pathoswith 357
        jnz     .fail_free_frs
2288 clevermous 358
        cmp     dword [ebx], 'FILE'
5954 pathoswith 359
        jnz     .fail_free_frs
2288 clevermous 360
        call    ntfs_restore_usa_frs
5954 pathoswith 361
        jc      .fail_free_frs
6405 pathoswith 362
.mftok:     ; prepare $MFT retrieval information
363
; search for unnamed non-resident $DATA attribute
364
        movzx   eax, word [ebx+attributeOffset]
2288 clevermous 365
        add     eax, ebx
366
.scandata:
367
        cmp     dword [eax], -1
6405 pathoswith 368
        jz      .fail_free_frs
2288 clevermous 369
        cmp     dword [eax], 0x80
370
        jnz     @f
6405 pathoswith 371
        cmp     byte [eax+nameLength], 0
2288 clevermous 372
        jz      .founddata
373
@@:
6405 pathoswith 374
        add     eax, [eax+sizeWithHeader]
2288 clevermous 375
        jmp     .scandata
6297 pathoswith 376
 
2288 clevermous 377
.founddata:
6405 pathoswith 378
        cmp     byte [eax+nonResidentFlag], 0
379
        jz      .fail_free_frs
380
        movzx   esi, word [eax+dataRunsOffset]
2288 clevermous 381
        add     esi, eax
6405 pathoswith 382
        mov     edx, [eax+attributeAllocatedSize+4]
383
        mov     eax, [eax+attributeAllocatedSize]
384
        shrd    eax, edx, 9
385
        mov     [ebp+NTFS.mftSize], eax
2288 clevermous 386
        sub     esp, 10h
6405 pathoswith 387
        lea     ecx, [ebp+NTFS.mft_retrieval]
388
        xor     edx, edx
389
.scanmcb:   ; load descriptions of fragments
2288 clevermous 390
        call    ntfs_decode_mcb_entry
391
        jnc     .scanmcbend
6405 pathoswith 392
        mov     eax, [esp]      ; block length
393
        mov     [ecx], eax
394
        add     edx, [esp+8]    ; block addr
395
        mov     [ecx+4], edx
396
        add     ecx, 8
2288 clevermous 397
        jmp     .scanmcb
6297 pathoswith 398
 
2288 clevermous 399
.scanmcbend:
400
        add     esp, 10h
6405 pathoswith 401
        lea     eax, [ebp+NTFS.attrlist_buf]
402
        cmp     eax, ecx
403
        jc      @f
404
        mov     eax, ecx
405
@@:
406
        mov     [ebp+NTFS.mft_retrieval_end], eax
407
; allocate index buffers
6340 pathoswith 408
        stdcall kernel_alloc, 2000h
2288 clevermous 409
        test    eax, eax
6405 pathoswith 410
        jz      .fail_free_frs
3742 clevermous 411
        mov     [ebp+NTFS.cur_index_buf], eax
6340 pathoswith 412
        add     eax, 1000h
413
        mov     [ebp+NTFS.secondIndexBuffer], eax
414
        mov     [ebp+NTFS.cur_index_size], 8
5954 pathoswith 415
; reserve adress space for bitmap buffer and load some part of bitmap
416
        mov     eax, dword [ebp+NTFS.Length]
417
        xor     edx, edx
418
        div     [ebp+NTFS.sectors_per_cluster]
419
        shr     eax, 3
420
        mov     [ebp+NTFS.BitmapTotalSize], eax
421
        add     eax, 7FFFh
422
        and     eax, not 7FFFh
423
        push    eax
424
        call    alloc_kernel_space
425
        test    eax, eax
426
        jz      .failFreeIndex
427
        mov     [ebp+NTFS.BitmapBuffer], eax
6273 pathoswith 428
        mov     [ebp+NTFS.cur_buf], eax
5954 pathoswith 429
        mov     eax, [ebp+NTFS.BitmapTotalSize]
430
        add     eax, [ebp+NTFS.mft_cluster]
431
        shr     eax, 3+2        ; reserve 1/8 of partition for $MFT
432
        shl     eax, 2
433
        mov     [ebp+NTFS.BitmapStart], eax
434
        shr     eax, 15
435
        inc     eax
436
        shl     eax, 3
437
        push    eax
438
        push    eax
439
        shl     eax, 3
6273 pathoswith 440
        mov     [ebp+NTFS.cur_size], eax
5954 pathoswith 441
        call    alloc_pages
442
        test    eax, eax
443
        pop     ecx
444
        jz      .failFreeBitmap
445
        add     eax, 3
446
        mov     ebx, [ebp+NTFS.BitmapBuffer]
447
        call    commit_pages
6273 pathoswith 448
        mov     [ebp+NTFS.cur_iRecord], 6
449
        mov     [ebp+NTFS.cur_attr], 0x80
450
        mov     [ebp+NTFS.cur_offs], 0
5954 pathoswith 451
        call    ntfs_read_attr
452
        jc      .failFreeBitmap
6273 pathoswith 453
        mov     eax, [ebp+NTFS.cur_read]
5954 pathoswith 454
        mov     [ebp+NTFS.BitmapSize], eax
6273 pathoswith 455
        mov     eax, [ebp+NTFS.LastRead]
5954 pathoswith 456
        mov     [ebp+NTFS.BitmapLocation], eax
457
; read MFT $BITMAP attribute
458
        mov     eax, [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 459
        mov     [ebp+NTFS.cur_size], eax
5954 pathoswith 460
        shl     eax, 9
461
        stdcall kernel_alloc, eax
462
        test    eax, eax
463
        jz      .failFreeBitmap
464
        mov     [ebp+NTFS.mftBitmapBuffer], eax
6273 pathoswith 465
        mov     [ebp+NTFS.cur_buf], eax
466
        mov     [ebp+NTFS.cur_iRecord], 0
467
        mov     [ebp+NTFS.cur_attr], 0xB0
468
        mov     [ebp+NTFS.cur_offs], 0
5954 pathoswith 469
        call    ntfs_read_attr
6273 pathoswith 470
        mov     eax, [ebp+NTFS.cur_read]
5954 pathoswith 471
        cmp     eax, 4
472
        jc      .failFreeBitmapMFT
6273 pathoswith 473
        mov     ecx, [ebp+NTFS.attr_offs]
6107 pathoswith 474
        cmp     byte [ecx+nonResidentFlag], 1
475
        jnz     .failFreeBitmapMFT
5954 pathoswith 476
        mov     [ebp+NTFS.mftBitmapSize], eax
6273 pathoswith 477
        mov     eax, [ebp+NTFS.LastRead]
5954 pathoswith 478
        mov     [ebp+NTFS.mftBitmapLocation], eax
2288 clevermous 479
 
3742 clevermous 480
        mov     eax, ebp
5954 pathoswith 481
.pop_exit:
482
        pop     esi ebp ebx
483
.exit:
484
        cmp     dword [esp+4], 0
485
        jz      @f
486
        sub     ebx, 512
487
@@:
488
        ret
489
 
490
.failFreeBitmapMFT:
6405 pathoswith 491
        stdcall kernel_free, [ebp+NTFS.mftBitmapBuffer]
5954 pathoswith 492
.failFreeBitmap:
6405 pathoswith 493
        stdcall kernel_free, [ebp+NTFS.BitmapBuffer]
5954 pathoswith 494
.failFreeIndex:
6405 pathoswith 495
        mov     eax, [ebp+NTFS.cur_index_buf]
496
        cmp     eax, [ebp+NTFS.secondIndexBuffer]
497
        jc      @f
498
        mov     eax, [ebp+NTFS.secondIndexBuffer]
499
@@:
500
        stdcall kernel_free, eax
5954 pathoswith 501
.fail_free_frs:
502
        stdcall kernel_free, [ebp+NTFS.frs_buffer]
503
.fail_free:
6405 pathoswith 504
        stdcall kernel_free, ebp
5954 pathoswith 505
        xor     eax, eax
3742 clevermous 506
        jmp     .pop_exit
2288 clevermous 507
 
5954 pathoswith 508
ntfs_free:
3742 clevermous 509
        push    ebx
5954 pathoswith 510
        mov     ebx, eax
3742 clevermous 511
        stdcall kernel_free, [ebx+NTFS.frs_buffer]
5954 pathoswith 512
        stdcall kernel_free, [ebx+NTFS.mftBitmapBuffer]
513
        stdcall kernel_free, [ebx+NTFS.BitmapBuffer]
6405 pathoswith 514
        mov     eax, [ebx+NTFS.cur_index_buf]
515
        cmp     eax, [ebx+NTFS.secondIndexBuffer]
516
        jc      @f
517
        mov     eax, [ebx+NTFS.secondIndexBuffer]
518
@@:
519
        stdcall kernel_free, eax
520
        stdcall kernel_free, ebx
3742 clevermous 521
        pop     ebx
6405 pathoswith 522
        ret
3742 clevermous 523
 
5954 pathoswith 524
ntfs_lock:
3742 clevermous 525
        lea     ecx, [ebp+NTFS.Lock]
526
        jmp     mutex_lock
527
 
5954 pathoswith 528
ntfs_unlock:
3742 clevermous 529
        lea     ecx, [ebp+NTFS.Lock]
530
        jmp     mutex_unlock
531
 
2288 clevermous 532
ntfs_read_attr:
6273 pathoswith 533
; [ebp+NTFS.bWriteAttr]=1 -> write attribute
5954 pathoswith 534
;   in:
6273 pathoswith 535
; [ebp+NTFS.cur_iRecord] = number of fileRecord
536
; [ebp+NTFS.cur_attr] = attribute type
537
; [ebp+NTFS.cur_offs] = attribute VCN in sectors
538
; [ebp+NTFS.cur_buf] -> buffer for data
539
; [ebp+NTFS.cur_size] = max sectors to read
5954 pathoswith 540
;   out:
6273 pathoswith 541
; [ebp+NTFS.cur_read] = bytes readen
5954 pathoswith 542
; CF=1 -> failed, eax = disk error code, eax=0 -> something with FS
3742 clevermous 543
        xor     eax, eax
2288 clevermous 544
        pushad
6273 pathoswith 545
        and     [ebp+NTFS.cur_read], 0
546
        cmp     [ebp+NTFS.cur_iRecord], 0
2288 clevermous 547
        jnz     .nomft
6273 pathoswith 548
        cmp     [ebp+NTFS.cur_attr], 0x80
2288 clevermous 549
        jnz     .nomft
550
; precalculated part of $Mft $DATA
6273 pathoswith 551
        mov     eax, [ebp+NTFS.cur_offs]
2288 clevermous 552
        xor     edx, edx
3742 clevermous 553
        div     [ebp+NTFS.sectors_per_cluster]
6405 pathoswith 554
        mov     ebx, edx
6418 pathoswith 555
        mov     [ebp+NTFS.fragmentCount], 0
6405 pathoswith 556
; eax = VCN, ebx = offset in sectors from beginning of cluster
557
        lea     esi, [ebp+NTFS.mft_retrieval]
558
        sub     esi, 8
2288 clevermous 559
.mftscan:
6405 pathoswith 560
        add     esi, 8
561
        cmp     esi, [ebp+NTFS.mft_retrieval_end]
562
        jz      .nomft
563
        mov     ecx, [esi+4]
2288 clevermous 564
        sub     eax, [esi]
6405 pathoswith 565
        jnc     .mftscan
2288 clevermous 566
        add     ecx, eax
567
        add     ecx, [esi]
6405 pathoswith 568
        neg     eax
569
        mul     [ebp+NTFS.sectors_per_cluster]
570
        xchg    eax, ecx
571
        mul     [ebp+NTFS.sectors_per_cluster]
572
        sub     ecx, ebx
573
        add     eax, ebx
6273 pathoswith 574
        mov     ebx, [ebp+NTFS.cur_buf]
575
        cmp     ecx, [ebp+NTFS.cur_size]
2288 clevermous 576
        jb      @f
6273 pathoswith 577
        mov     ecx, [ebp+NTFS.cur_size]
2288 clevermous 578
@@:
6405 pathoswith 579
        mov     [ebp+NTFS.LastRead], eax
580
        mov     edi, ecx
581
        call    fs_read64_sys
3742 clevermous 582
        test    eax, eax
6405 pathoswith 583
        jnz     .errret
584
        sub     [ebp+NTFS.cur_size], edi
585
        add     [ebp+NTFS.cur_offs], edi
586
        shl     edi, 9
587
        add     [ebp+NTFS.cur_read], edi
588
        add     [ebp+NTFS.cur_buf], edi
6418 pathoswith 589
        inc     [ebp+NTFS.fragmentCount]
2288 clevermous 590
        xor     eax, eax
6405 pathoswith 591
        xor     ebx, ebx
6273 pathoswith 592
        cmp     [ebp+NTFS.cur_size], eax
2288 clevermous 593
        jz      @f
594
        jmp     .mftscan
6297 pathoswith 595
 
596
.errret2_pop:
597
        xor     eax, eax
598
.errret_pop:
599
        pop     ecx
2288 clevermous 600
        pop     ecx
601
.errret:
3742 clevermous 602
        mov     [esp+28], eax
2288 clevermous 603
        stc
6297 pathoswith 604
@@:
2288 clevermous 605
        popad
606
        ret
6297 pathoswith 607
 
2288 clevermous 608
.nomft:
609
; 1. Read file record.
610
; N.B. This will do recursive call of read_attr for $MFT::$Data.
6273 pathoswith 611
        mov     eax, [ebp+NTFS.cur_iRecord]
612
        and     [ebp+NTFS.attr_list], 0
613
        or      dword [ebp+NTFS.attr_size+4], -1
614
        or      [ebp+NTFS.attr_iBaseRecord], -1
2288 clevermous 615
        call    ntfs_read_file_record
3742 clevermous 616
        jc      .errret
2288 clevermous 617
; 2. Find required attribute.
3742 clevermous 618
        mov     eax, [ebp+NTFS.frs_buffer]
6107 pathoswith 619
; a) For auxiliary records, read base record.
620
; If base record is present, base iRecord may be 0 (for $Mft),
621
; but SequenceNumber is nonzero.
6297 pathoswith 622
        cmp     word [eax+baseRecordReuse], 0
2288 clevermous 623
        jz      @f
6297 pathoswith 624
        mov     eax, [eax+baseRecordReference]
2288 clevermous 625
.beginfindattr:
626
        call    ntfs_read_file_record
3742 clevermous 627
        jc      .errret
6107 pathoswith 628
        jmp     @f
6297 pathoswith 629
 
6107 pathoswith 630
.newAttribute:
631
        pushad
6297 pathoswith 632
        and     [ebp+NTFS.cur_read], 0
2288 clevermous 633
@@:
634
; b) Scan for required attribute and for $ATTR_LIST
3742 clevermous 635
        mov     eax, [ebp+NTFS.frs_buffer]
6297 pathoswith 636
        movzx   ecx, word [eax+attributeOffset]
2288 clevermous 637
        add     eax, ecx
6273 pathoswith 638
        mov     ecx, [ebp+NTFS.cur_attr]
639
        and     [ebp+NTFS.attr_offs], 0
2288 clevermous 640
.scanattr:
641
        cmp     dword [eax], -1
642
        jz      .scandone
643
        cmp     dword [eax], ecx
644
        jz      .okattr
6273 pathoswith 645
        cmp     [ebp+NTFS.attr_iBaseRecord], -1
2288 clevermous 646
        jnz     .scancont
647
        cmp     dword [eax], 0x20       ; $ATTR_LIST
648
        jnz     .scancont
6273 pathoswith 649
        mov     [ebp+NTFS.attr_list], eax
2288 clevermous 650
        jmp     .scancont
6297 pathoswith 651
 
2288 clevermous 652
.okattr:
653
; ignore named $DATA attributes (aka NTFS streams)
654
        cmp     ecx, 0x80
655
        jnz     @f
6297 pathoswith 656
        cmp     byte [eax+nameLength], 0
2288 clevermous 657
        jnz     .scancont
658
@@:
6273 pathoswith 659
        mov     [ebp+NTFS.attr_offs], eax
2288 clevermous 660
.scancont:
6297 pathoswith 661
        add     eax, [eax+sizeWithHeader]
2288 clevermous 662
        jmp     .scanattr
6297 pathoswith 663
 
2288 clevermous 664
.continue:
665
        pushad
6273 pathoswith 666
        and     [ebp+NTFS.cur_read], 0
2288 clevermous 667
.scandone:
668
; c) Check for required offset and length
6273 pathoswith 669
        mov     ecx, [ebp+NTFS.attr_offs]
2288 clevermous 670
        jecxz   .noattr
6273 pathoswith 671
        push    [ebp+NTFS.cur_size]
672
        push    [ebp+NTFS.cur_read]
2288 clevermous 673
        call    .doreadattr
674
        pop     edx
3742 clevermous 675
        pop     ecx
6297 pathoswith 676
        jc      .ret
6273 pathoswith 677
        cmp     [ebp+NTFS.bCanContinue], 0
6297 pathoswith 678
        jz      .ret
6273 pathoswith 679
        sub     edx, [ebp+NTFS.cur_read]
2288 clevermous 680
        neg     edx
681
        shr     edx, 9
3742 clevermous 682
        sub     ecx, edx
6273 pathoswith 683
        mov     [ebp+NTFS.cur_size], ecx
6297 pathoswith 684
        jz      .ret
2288 clevermous 685
.noattr:
6273 pathoswith 686
        cmp     [ebp+NTFS.cur_attr], 0x20
2288 clevermous 687
        jz      @f
6273 pathoswith 688
        mov     ecx, [ebp+NTFS.attr_list]
2288 clevermous 689
        test    ecx, ecx
690
        jnz     .lookattr
3742 clevermous 691
        and     dword [esp+28], 0
6297 pathoswith 692
        cmp     [ebp+NTFS.attr_offs], 1     ; define CF
693
.ret:
2288 clevermous 694
        popad
695
        ret
6297 pathoswith 696
 
2288 clevermous 697
.lookattr:
698
; required attribute or required offset was not found in base record;
699
; it may be present in auxiliary records;
700
; scan $ATTR_LIST
6273 pathoswith 701
        mov     eax, [ebp+NTFS.attr_iBaseRecord]
2288 clevermous 702
        cmp     eax, -1
703
        jz      @f
704
        call    ntfs_read_file_record
3742 clevermous 705
        jc      .errret
6273 pathoswith 706
        or      [ebp+NTFS.attr_iBaseRecord], -1
2288 clevermous 707
@@:
6273 pathoswith 708
        push    [ebp+NTFS.cur_offs]
709
        push    [ebp+NTFS.cur_size]
710
        push    [ebp+NTFS.cur_read]
711
        push    [ebp+NTFS.cur_buf]
712
        push    dword [ebp+NTFS.attr_size]
713
        push    dword [ebp+NTFS.attr_size+4]
714
        or      dword [ebp+NTFS.attr_size+4], -1
715
        and     [ebp+NTFS.cur_offs], 0
716
        mov     [ebp+NTFS.cur_size], 2
717
        and     [ebp+NTFS.cur_read], 0
718
        lea     eax, [ebp+NTFS.attrlist_buf]
719
        cmp     [ebp+NTFS.cur_iRecord], 0
2288 clevermous 720
        jnz     @f
6273 pathoswith 721
        lea     eax, [ebp+NTFS.attrlist_mft_buf]
2288 clevermous 722
@@:
6273 pathoswith 723
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 724
        push    eax
725
        call    .doreadattr
726
        pop     esi
727
        mov     edx, 1
6273 pathoswith 728
        pop     dword [ebp+NTFS.attr_size+4]
729
        pop     dword [ebp+NTFS.attr_size]
730
        mov     ecx, [ebp+NTFS.cur_read]
731
        pop     [ebp+NTFS.cur_buf]
732
        pop     [ebp+NTFS.cur_read]
733
        pop     [ebp+NTFS.cur_size]
734
        pop     [ebp+NTFS.cur_offs]
2288 clevermous 735
        jc      .errret
736
        or      edi, -1
3742 clevermous 737
        lea     ecx, [ecx+esi-1Ah]
2288 clevermous 738
.scanliststart:
3742 clevermous 739
        push    ecx
6273 pathoswith 740
        mov     eax, [ebp+NTFS.cur_attr]
2288 clevermous 741
.scanlist:
3742 clevermous 742
        cmp     esi, [esp]
2288 clevermous 743
        jae     .scanlistdone
744
        cmp     eax, [esi]
745
        jz      @f
746
.scanlistcont:
747
        movzx   ecx, word [esi+4]
748
        add     esi, ecx
749
        jmp     .scanlist
6297 pathoswith 750
 
2288 clevermous 751
@@:
752
; ignore named $DATA attributes (aka NTFS streams)
753
        cmp     eax, 0x80
754
        jnz     @f
755
        cmp     byte [esi+6], 0
756
        jnz     .scanlistcont
757
@@:
758
        push    eax
759
        mov     eax, [esi+8]
760
        test    eax, eax
761
        jnz     .testf
6407 pathoswith 762
        cmp     dword [ebp+NTFS.attr_size+4], -1
2288 clevermous 763
        jnz     .testfz
764
; if attribute is in auxiliary records, its size is defined only in first
765
        mov     eax, [esi+10h]
766
        call    ntfs_read_file_record
6297 pathoswith 767
        jc      .errret_pop
3742 clevermous 768
        mov     eax, [ebp+NTFS.frs_buffer]
2288 clevermous 769
        movzx   ecx, word [eax+14h]
770
        add     eax, ecx
6273 pathoswith 771
        mov     ecx, [ebp+NTFS.cur_attr]
2288 clevermous 772
@@:
773
        cmp     dword [eax], -1
3742 clevermous 774
        jz      .errret2_pop
2288 clevermous 775
        cmp     dword [eax], ecx
776
        jz      @f
777
.l1:
778
        add     eax, [eax+4]
779
        jmp     @b
6297 pathoswith 780
 
2288 clevermous 781
@@:
782
        cmp     eax, 0x80
783
        jnz     @f
784
        cmp     byte [eax+9], 0
785
        jnz     .l1
786
@@:
787
        cmp     byte [eax+8], 0
788
        jnz     .sdnores
789
        mov     eax, [eax+10h]
6273 pathoswith 790
        mov     dword [ebp+NTFS.attr_size], eax
791
        and     dword [ebp+NTFS.attr_size+4], 0
2288 clevermous 792
        jmp     .testfz
6297 pathoswith 793
 
2288 clevermous 794
.sdnores:
795
        mov     ecx, [eax+30h]
6273 pathoswith 796
        mov     dword [ebp+NTFS.attr_size], ecx
2288 clevermous 797
        mov     ecx, [eax+34h]
6273 pathoswith 798
        mov     dword [ebp+NTFS.attr_size+4], ecx
2288 clevermous 799
.testfz:
800
        xor     eax, eax
801
.testf:
3742 clevermous 802
        imul    eax, [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 803
        cmp     eax, [ebp+NTFS.cur_offs]
2288 clevermous 804
        pop     eax
805
        ja      @f
806
        mov     edi, [esi+10h]  ; keep previous iRecord
807
        jmp     .scanlistcont
6297 pathoswith 808
 
2288 clevermous 809
@@:
3742 clevermous 810
        pop     ecx
2288 clevermous 811
.scanlistfound:
812
        cmp     edi, -1
6297 pathoswith 813
        jz      .ret
6273 pathoswith 814
        mov     eax, [ebp+NTFS.cur_iRecord]
815
        mov     [ebp+NTFS.attr_iBaseRecord], eax
2288 clevermous 816
        mov     eax, edi
817
        jmp     .beginfindattr
6297 pathoswith 818
 
2288 clevermous 819
.scanlistdone:
3742 clevermous 820
        pop     ecx
821
        sub     ecx, ebp
6273 pathoswith 822
        sub     ecx, NTFS.attrlist_buf-1Ah
823
        cmp     [ebp+NTFS.cur_iRecord], 0
2288 clevermous 824
        jnz     @f
6273 pathoswith 825
        sub     ecx, NTFS.attrlist_mft_buf-NTFS.attrlist_buf
2288 clevermous 826
@@:
3742 clevermous 827
        cmp     ecx, 0x400
2288 clevermous 828
        jnz     .scanlistfound
829
        inc     edx
830
        push    esi edi
6273 pathoswith 831
        lea     esi, [ebp+NTFS.attrlist_buf+0x200]
832
        lea     edi, [ebp+NTFS.attrlist_buf]
833
        cmp     [ebp+NTFS.cur_iRecord], 0
2288 clevermous 834
        jnz     @f
6273 pathoswith 835
        lea     esi, [ebp+NTFS.attrlist_mft_buf+0x200]
836
        lea     edi, [ebp+NTFS.attrlist_mft_buf]
2288 clevermous 837
@@:
838
        mov     ecx, 0x200/4
839
        rep movsd
840
        mov     eax, edi
841
        pop     edi esi
842
        sub     esi, 0x200
6273 pathoswith 843
        push    [ebp+NTFS.cur_offs]
844
        push    [ebp+NTFS.cur_size]
845
        push    [ebp+NTFS.cur_read]
846
        push    [ebp+NTFS.cur_buf]
847
        push    dword [ebp+NTFS.attr_size]
848
        push    dword [ebp+NTFS.attr_size+4]
849
        or      dword [ebp+NTFS.attr_size+4], -1
850
        mov     [ebp+NTFS.cur_offs], edx
851
        mov     [ebp+NTFS.cur_size], 1
852
        and     [ebp+NTFS.cur_read], 0
853
        mov     [ebp+NTFS.cur_buf], eax
854
        mov     ecx, [ebp+NTFS.attr_list]
3742 clevermous 855
        push    esi edx edi
2288 clevermous 856
        call    .doreadattr
3742 clevermous 857
        pop     edi edx esi
6273 pathoswith 858
        mov     ecx, [ebp+NTFS.cur_read]
859
        pop     dword [ebp+NTFS.attr_size+4]
860
        pop     dword [ebp+NTFS.attr_size]
861
        pop     [ebp+NTFS.cur_buf]
862
        pop     [ebp+NTFS.cur_read]
863
        pop     [ebp+NTFS.cur_size]
864
        pop     [ebp+NTFS.cur_offs]
2288 clevermous 865
        jc      .errret
6273 pathoswith 866
        lea     ecx, [ecx+ebp+NTFS.attrlist_buf+0x200-0x1A]
867
        cmp     [ebp+NTFS.cur_iRecord], 0
2288 clevermous 868
        jnz     .scanliststart
6273 pathoswith 869
        add     ecx, NTFS.attrlist_mft_buf-NTFS.attrlist_buf
2288 clevermous 870
        jmp     .scanliststart
871
 
872
.doreadattr:
6273 pathoswith 873
        mov     [ebp+NTFS.bCanContinue], 0
6297 pathoswith 874
        cmp     byte [ecx+nonResidentFlag], 0
2288 clevermous 875
        jnz     .nonresident
6297 pathoswith 876
        mov     eax, [ecx+sizeWithoutHeader]
2288 clevermous 877
        mov     esi, eax
6273 pathoswith 878
        mov     edx, [ebp+NTFS.cur_offs]
2288 clevermous 879
        shr     eax, 9
880
        cmp     eax, edx
881
        jb      .okret
882
        shl     edx, 9
883
        sub     esi, edx
6297 pathoswith 884
        movzx   eax, word [ecx+attributeOffset]
2288 clevermous 885
        add     edx, eax
886
        add     edx, ecx        ; edx -> data
6273 pathoswith 887
        mov     eax, [ebp+NTFS.cur_size]
2288 clevermous 888
        cmp     eax, (0xFFFFFFFF shr 9)+1
889
        jbe     @f
890
        mov     eax, (0xFFFFFFFF shr 9)+1
891
@@:
892
        shl     eax, 9
893
        cmp     eax, esi
894
        jbe     @f
895
        mov     eax, esi
896
@@:
897
; eax = length, edx -> data
6273 pathoswith 898
        mov     [ebp+NTFS.cur_read], eax
2288 clevermous 899
        mov     ecx, eax
900
        mov     eax, edx
6273 pathoswith 901
        mov     ebx, [ebp+NTFS.cur_buf]
2288 clevermous 902
        call    memmove
6273 pathoswith 903
        and     [ebp+NTFS.cur_size], 0      ; CF=0
2288 clevermous 904
        ret
6297 pathoswith 905
 
2288 clevermous 906
.nonresident:
907
; Not all auxiliary records contain correct FileSize info
6273 pathoswith 908
        mov     eax, dword [ebp+NTFS.attr_size]
909
        mov     edx, dword [ebp+NTFS.attr_size+4]
6407 pathoswith 910
        cmp     edx, -1
2288 clevermous 911
        jnz     @f
6297 pathoswith 912
        mov     eax, [ecx+attributeRealSize]
913
        mov     edx, [ecx+attributeRealSize+4]
6273 pathoswith 914
        mov     dword [ebp+NTFS.attr_size], eax
915
        mov     dword [ebp+NTFS.attr_size+4], edx
2288 clevermous 916
@@:
917
        add     eax, 0x1FF
918
        adc     edx, 0
919
        shrd    eax, edx, 9
6273 pathoswith 920
        sub     eax, [ebp+NTFS.cur_offs]
2288 clevermous 921
        ja      @f
922
; return with nothing read
6273 pathoswith 923
        and     [ebp+NTFS.cur_size], 0
2288 clevermous 924
.okret:
925
        clc
926
        ret
6297 pathoswith 927
 
2288 clevermous 928
@@:
929
; reduce read length
6273 pathoswith 930
        and     [ebp+NTFS.cur_tail], 0
931
        cmp     [ebp+NTFS.cur_size], eax
2288 clevermous 932
        jb      @f
6273 pathoswith 933
        mov     [ebp+NTFS.cur_size], eax
934
        mov     eax, dword [ebp+NTFS.attr_size]
2288 clevermous 935
        and     eax, 0x1FF
6273 pathoswith 936
        mov     [ebp+NTFS.cur_tail], eax
2288 clevermous 937
@@:
6273 pathoswith 938
        mov     eax, [ebp+NTFS.cur_offs]
2288 clevermous 939
        xor     edx, edx
3742 clevermous 940
        div     [ebp+NTFS.sectors_per_cluster]
6297 pathoswith 941
        sub     eax, [ecx+firstVCN]
2288 clevermous 942
        jb      .okret
6405 pathoswith 943
        mov     ebx, edx
944
; eax = starting cluster, ebx = sector in the cluster
6273 pathoswith 945
        cmp     [ebp+NTFS.cur_attr], 0x80
5994 pathoswith 946
        jnz     .sys
6273 pathoswith 947
        cmp     [ebp+NTFS.cur_iRecord], 0
5994 pathoswith 948
        jz      .sys
949
        push    fs_read64_app
6273 pathoswith 950
        cmp     [ebp+NTFS.bWriteAttr], 1
5994 pathoswith 951
        jnz     @f
952
        mov     dword[esp], fs_write64_app
953
        jmp     @f
6297 pathoswith 954
 
5994 pathoswith 955
.sys:
956
        push    fs_read64_sys
957
@@:
2288 clevermous 958
        sub     esp, 10h
6297 pathoswith 959
        movzx   esi, word [ecx+dataRunsOffset]
2288 clevermous 960
        add     esi, ecx
3742 clevermous 961
        xor     edi, edi
6273 pathoswith 962
        mov     [ebp+NTFS.fragmentCount], 0
2288 clevermous 963
.readloop:
964
        call    ntfs_decode_mcb_entry
965
        jnc     .break
3742 clevermous 966
        add     edi, [esp+8]
2288 clevermous 967
        sub     eax, [esp]
968
        jae     .readloop
6405 pathoswith 969
        mov     ecx, edi
970
        add     ecx, eax
971
        add     ecx, [esp]
972
        neg     eax
973
        mul     [ebp+NTFS.sectors_per_cluster]
974
        xchg    eax, ecx
975
        mul     [ebp+NTFS.sectors_per_cluster]
976
        sub     ecx, ebx
977
        add     eax, ebx
978
        mov     ebx, [ebp+NTFS.cur_buf]
6273 pathoswith 979
        cmp     ecx, [ebp+NTFS.cur_size]
2288 clevermous 980
        jb      @f
6273 pathoswith 981
        mov     ecx, [ebp+NTFS.cur_size]
2288 clevermous 982
@@:
6273 pathoswith 983
        mov     [ebp+NTFS.LastRead], eax
5954 pathoswith 984
        push    ecx
6405 pathoswith 985
        call    dword[esp+14h]
5954 pathoswith 986
        pop     ecx
3742 clevermous 987
        test    eax, eax
2288 clevermous 988
        jnz     .errread2
6273 pathoswith 989
        sub     [ebp+NTFS.cur_size], ecx
990
        add     [ebp+NTFS.cur_offs], ecx
5954 pathoswith 991
        shl     ecx, 9
6273 pathoswith 992
        add     [ebp+NTFS.cur_read], ecx
993
        add     [ebp+NTFS.cur_buf], ecx
994
        inc     [ebp+NTFS.fragmentCount]
2288 clevermous 995
        xor     eax, eax
6405 pathoswith 996
        xor     ebx, ebx
6273 pathoswith 997
        cmp     [ebp+NTFS.cur_size], 0
2288 clevermous 998
        jnz     .readloop
5994 pathoswith 999
        add     esp, 14h
6273 pathoswith 1000
        mov     eax, [ebp+NTFS.cur_tail]
2288 clevermous 1001
        test    eax, eax
1002
        jz      @f
1003
        sub     eax, 0x200
6273 pathoswith 1004
        add     [ebp+NTFS.cur_read], eax
2288 clevermous 1005
@@:
1006
        clc
1007
        ret
6297 pathoswith 1008
 
2288 clevermous 1009
.errread2:
5994 pathoswith 1010
        add     esp, 14h
2288 clevermous 1011
        stc
1012
        ret
6297 pathoswith 1013
 
2288 clevermous 1014
.break:
5994 pathoswith 1015
        add     esp, 14h        ; CF=0
6273 pathoswith 1016
        mov     [ebp+NTFS.bCanContinue], 1
2288 clevermous 1017
        ret
1018
 
1019
ntfs_read_file_record:
5954 pathoswith 1020
; in: eax = iRecord
6080 pathoswith 1021
; out: [ebp+NTFS.frs_buffer] -> file record
5954 pathoswith 1022
; CF=1 -> failed, eax = disk error code, eax=0 -> something with FS
1023
    ; Read attr $DATA of $Mft, starting from eax*[ebp+NTFS.frs_size]
2288 clevermous 1024
        push    ecx edx
3742 clevermous 1025
        mov     ecx, [ebp+NTFS.frs_size]
2288 clevermous 1026
        mul     ecx
1027
        shrd    eax, edx, 9
1028
        shr     edx, 9
3742 clevermous 1029
        jnz     .errret
6273 pathoswith 1030
        push    [ebp+NTFS.attr_iBaseRecord]
1031
        push    [ebp+NTFS.attr_offs]
1032
        push    [ebp+NTFS.attr_list]
1033
        push    dword [ebp+NTFS.attr_size+4]
1034
        push    dword [ebp+NTFS.attr_size]
1035
        push    [ebp+NTFS.cur_iRecord]
1036
        push    [ebp+NTFS.cur_attr]
1037
        push    [ebp+NTFS.cur_offs]
1038
        push    [ebp+NTFS.cur_size]
1039
        push    [ebp+NTFS.cur_buf]
1040
        push    [ebp+NTFS.cur_read]
1041
        mov     [ebp+NTFS.cur_attr], 0x80   ; $DATA
1042
        and     [ebp+NTFS.cur_iRecord], 0   ; $Mft
1043
        mov     [ebp+NTFS.cur_offs], eax
2288 clevermous 1044
        shr     ecx, 9
6273 pathoswith 1045
        mov     [ebp+NTFS.cur_size], ecx
3742 clevermous 1046
        mov     eax, [ebp+NTFS.frs_buffer]
6273 pathoswith 1047
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1048
        call    ntfs_read_attr
6273 pathoswith 1049
        mov     edx, [ebp+NTFS.cur_read]
1050
        pop     [ebp+NTFS.cur_read]
1051
        pop     [ebp+NTFS.cur_buf]
1052
        pop     [ebp+NTFS.cur_size]
1053
        pop     [ebp+NTFS.cur_offs]
1054
        pop     [ebp+NTFS.cur_attr]
1055
        pop     [ebp+NTFS.cur_iRecord]
1056
        pop     dword [ebp+NTFS.attr_size]
1057
        pop     dword [ebp+NTFS.attr_size+4]
1058
        pop     [ebp+NTFS.attr_list]
1059
        pop     [ebp+NTFS.attr_offs]
1060
        pop     [ebp+NTFS.attr_iBaseRecord]
3742 clevermous 1061
        jc      .ret
1062
        cmp     edx, [ebp+NTFS.frs_size]
2288 clevermous 1063
        jnz     .errret
6408 pathoswith 1064
        mov     eax, [ebp+NTFS.LastRead]
1065
        mov     [ebp+NTFS.mftLastRead], eax
3742 clevermous 1066
        mov     eax, [ebp+NTFS.frs_buffer]
2288 clevermous 1067
        cmp     dword [eax], 'FILE'
1068
        jnz     .errret
1069
        push    ebx
1070
        mov     ebx, eax
1071
        call    ntfs_restore_usa_frs
1072
        pop     ebx
3742 clevermous 1073
        jc      .errret
2288 clevermous 1074
.ret:
3742 clevermous 1075
        pop     edx ecx
2288 clevermous 1076
        ret
6297 pathoswith 1077
 
3742 clevermous 1078
.errret:
2288 clevermous 1079
        pop     edx ecx
1080
        xor     eax, eax
3742 clevermous 1081
        stc
2288 clevermous 1082
        ret
1083
 
1084
ntfs_restore_usa_frs:
3742 clevermous 1085
        mov     eax, [ebp+NTFS.frs_size]
2288 clevermous 1086
ntfs_restore_usa:
6080 pathoswith 1087
;   in:
1088
; ebx -> record
1089
; eax = size in bytes
2288 clevermous 1090
        pushad
1091
        shr     eax, 9
1092
        mov     ecx, eax
1093
        inc     eax
6297 pathoswith 1094
        cmp     [ebx+updateSequenceSize], ax
2288 clevermous 1095
        jnz     .err
6297 pathoswith 1096
        movzx   eax, word [ebx+updateSequenceOffset]
2288 clevermous 1097
        lea     esi, [eax+ebx]
1098
        lodsw
1099
        mov     edx, eax
1100
        lea     edi, [ebx+0x1FE]
1101
@@:
1102
        cmp     [edi], dx
1103
        jnz     .err
1104
        lodsw
1105
        stosw
1106
        add     edi, 0x1FE
1107
        loop    @b
1108
        popad
1109
        clc
1110
        ret
6297 pathoswith 1111
 
2288 clevermous 1112
.err:
1113
        popad
1114
        stc
1115
        ret
1116
 
1117
ntfs_decode_mcb_entry:
6019 pathoswith 1118
;   in:
6080 pathoswith 1119
; esi -> MCB entry
6019 pathoswith 1120
; esp -> buffer (16 bytes)
1121
;   out:
6080 pathoswith 1122
; esi -> next MCB entry
6019 pathoswith 1123
; esp -> data run size
1124
; esp+8 -> cluster (delta)
6080 pathoswith 1125
; CF=0 -> MCB end
2288 clevermous 1126
        push    eax ecx edi
1127
        lea     edi, [esp+16]
1128
        xor     eax, eax
1129
        lodsb
1130
        test    al, al
1131
        jz      .end
1132
        mov     ecx, eax
1133
        and     ecx, 0xF
1134
        cmp     ecx, 8
1135
        ja      .end
1136
        push    ecx
1137
        rep movsb
1138
        pop     ecx
1139
        sub     ecx, 8
1140
        neg     ecx
1141
        cmp     byte [esi-1], 80h
1142
        jae     .end
1143
        push    eax
1144
        xor     eax, eax
1145
        rep stosb
1146
        pop     ecx
1147
        shr     ecx, 4
1148
        cmp     ecx, 8
1149
        ja      .end
1150
        push    ecx
1151
        rep movsb
1152
        pop     ecx
1153
        sub     ecx, 8
1154
        neg     ecx
1155
        cmp     byte [esi-1], 80h
1156
        cmc
1157
        sbb     eax, eax
1158
        rep stosb
1159
        stc
1160
.end:
1161
        pop     edi ecx eax
1162
        ret
1163
 
1164
ntfs_find_lfn:
6471 pathoswith 1165
; in: esi -> path string in UTF-8
5954 pathoswith 1166
;   out:
6405 pathoswith 1167
; [ebp+NTFS.cur_iRecord] = target fileRecord
6411 pathoswith 1168
; eax -> target index in the node
1169
; [ebp+NTFS.LastRead] = target node location
6405 pathoswith 1170
; [ebp+NTFS.indexPointer] -> index, that points the target subnode
6411 pathoswith 1171
; [ebp+NTFS.nodeLastRead] = branch node location
6405 pathoswith 1172
; [ebp+NTFS.indexRoot] -> attribute
6411 pathoswith 1173
; [ebp+NTFS.rootLastRead] = directory fileRecord location
6405 pathoswith 1174
; [ebp+NTFS.cur_size] = index record size in sectors
1175
; [ebp+NTFS.cur_subnode_size] = index record size in clusters or sectors
5994 pathoswith 1176
; CF=1 -> file not found, eax=0 -> error
6297 pathoswith 1177
        mov     [ebp+NTFS.cur_iRecord], 5   ; start from root directory
2288 clevermous 1178
.doit2:
6273 pathoswith 1179
        mov     [ebp+NTFS.cur_attr], 0x90   ; $INDEX_ROOT
1180
        and     [ebp+NTFS.cur_offs], 0
3742 clevermous 1181
        mov     eax, [ebp+NTFS.cur_index_size]
6273 pathoswith 1182
        mov     [ebp+NTFS.cur_size], eax
3742 clevermous 1183
        mov     eax, [ebp+NTFS.cur_index_buf]
6273 pathoswith 1184
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1185
        call    ntfs_read_attr
5994 pathoswith 1186
        mov     eax, 0
6297 pathoswith 1187
        jc      .ret
6273 pathoswith 1188
        cmp     [ebp+NTFS.cur_read], 0x20
2288 clevermous 1189
        jc      .ret
6418 pathoswith 1190
        push    esi
2288 clevermous 1191
        pushad
3742 clevermous 1192
        mov     esi, [ebp+NTFS.cur_index_buf]
6340 pathoswith 1193
        mov     eax, [esi+indexRecordSize]
1194
        shr     eax, 9
1195
        cmp     [ebp+NTFS.cur_index_size], eax
6297 pathoswith 1196
        jc      .realloc
6340 pathoswith 1197
        mov     [ebp+NTFS.cur_size], eax
1198
        mov     al, [esi+indexRecordSizeClus]
1199
        mov     [ebp+NTFS.cur_subnode_size], eax
6297 pathoswith 1200
        add     esi, rootNode
1201
        mov     eax, [esi+nodeRealSize]
1202
        add     eax, rootNode
6273 pathoswith 1203
        cmp     [ebp+NTFS.cur_read], eax
6297 pathoswith 1204
        jc      .err
6408 pathoswith 1205
        mov     eax, [ebp+NTFS.mftLastRead]
6340 pathoswith 1206
        mov     [ebp+NTFS.rootLastRead], eax
1207
        mov     eax, [ebp+NTFS.attr_offs]
1208
        mov     [ebp+NTFS.indexRoot], eax
6471 pathoswith 1209
.scanloop:  ; esi -> current index node
6297 pathoswith 1210
        add     esi, [esi+indexOffset]
2288 clevermous 1211
.scanloopint:
6471 pathoswith 1212
        push    esi
6297 pathoswith 1213
        test    byte [esi+indexFlags], 2
2288 clevermous 1214
        jnz     .subnode
6297 pathoswith 1215
        movzx   ecx, byte [esi+fileNameLength]
6471 pathoswith 1216
        lea     edi, [esi+fileName]
1217
        mov     esi, [esp+8]
2288 clevermous 1218
@@:
6471 pathoswith 1219
        call    utf8to16
1220
        cmp     ax, '/'
1221
        jz      .subnode
1222
        call    utf16toUpper
2288 clevermous 1223
        push    eax
6471 pathoswith 1224
        mov     ax, [edi]
1225
        call    utf16toUpper
1226
        cmp     [esp], ax
2288 clevermous 1227
        pop     eax
6471 pathoswith 1228
        jc      .subnode
1229
        jnz     .scanloopcont
1230
        add     edi, 2
1231
        loop    @b
1232
        call    utf8to16
1233
        cmp     ax, '/'
2288 clevermous 1234
        jz      .found
6471 pathoswith 1235
        test    ax, ax
1236
        jz      .found
1237
.scanloopcont:
2288 clevermous 1238
        pop     esi
6297 pathoswith 1239
        movzx   eax, word [esi+indexAllocatedSize]
2288 clevermous 1240
        add     esi, eax
1241
        jmp     .scanloopint
6297 pathoswith 1242
 
1243
.realloc:
6340 pathoswith 1244
        mov     edi, eax
1245
        mov     eax, [esi+indexRecordSize]
1246
        shl     eax, 1
1247
        stdcall kernel_alloc, eax
6297 pathoswith 1248
        test    eax, eax
1249
        jz      .err
6405 pathoswith 1250
        mov     edx, [ebp+NTFS.cur_index_buf]
1251
        cmp     edx, [ebp+NTFS.secondIndexBuffer]
1252
        jc      @f
1253
        mov     edx, [ebp+NTFS.secondIndexBuffer]
1254
@@:
6297 pathoswith 1255
        mov     [ebp+NTFS.cur_index_buf], eax
6340 pathoswith 1256
        add     eax, [esi+indexRecordSize]
1257
        mov     [ebp+NTFS.secondIndexBuffer], eax
1258
        mov     [ebp+NTFS.cur_index_size], edi
6405 pathoswith 1259
        stdcall kernel_free, edx
6297 pathoswith 1260
        popad
6418 pathoswith 1261
        pop     eax
6297 pathoswith 1262
        jmp     .doit2
1263
 
1264
.notfound:
6471 pathoswith 1265
        mov     [esp+28], esi
6297 pathoswith 1266
.err:
1267
        popad
1268
        stc
6418 pathoswith 1269
.ret2:
1270
        pop     esi
6297 pathoswith 1271
.ret:
6468 pathoswith 1272
        ret
6297 pathoswith 1273
 
6471 pathoswith 1274
.subnode:
2288 clevermous 1275
        pop     esi
6297 pathoswith 1276
        test    byte [esi+indexFlags], 1
2288 clevermous 1277
        jz      .notfound
6411 pathoswith 1278
        mov     eax, [ebp+NTFS.LastRead]
1279
        mov     [ebp+NTFS.nodeLastRead], eax
1280
        mov     [ebp+NTFS.indexPointer], esi
6297 pathoswith 1281
        movzx   eax, word [esi+indexAllocatedSize]
2288 clevermous 1282
        mov     eax, [esi+eax-8]
6340 pathoswith 1283
        mov     edx, [ebp+NTFS.cur_size]
1284
        push    edx
1285
        cmp     edx, [ebp+NTFS.cur_subnode_size]
1286
        jz      @f
1287
        mul     [ebp+NTFS.sectors_per_cluster]
1288
@@:
1289
        mov     esi, [ebp+NTFS.cur_index_buf]
1290
        xchg    [ebp+NTFS.secondIndexBuffer], esi
1291
        mov     [ebp+NTFS.cur_index_buf], esi
1292
        mov     [ebp+NTFS.cur_buf], esi
1293
        mov     [ebp+NTFS.cur_attr], 0xA0   ; $INDEX_ALLOCATION
6273 pathoswith 1294
        mov     [ebp+NTFS.cur_offs], eax
6297 pathoswith 1295
        call    ntfs_read_attr.newAttribute
6340 pathoswith 1296
        pop     eax
1297
        mov     [ebp+NTFS.cur_size], eax
2288 clevermous 1298
        shl     eax, 9
6273 pathoswith 1299
        cmp     [ebp+NTFS.cur_read], eax
5954 pathoswith 1300
        jnz     .err
2288 clevermous 1301
        cmp     dword [esi], 'INDX'
5954 pathoswith 1302
        jnz     .err
2288 clevermous 1303
        mov     ebx, esi
1304
        call    ntfs_restore_usa
5954 pathoswith 1305
        jc      .err
6297 pathoswith 1306
        add     esi, recordNode
2288 clevermous 1307
        jmp     .scanloop
6297 pathoswith 1308
 
2288 clevermous 1309
.found:
6471 pathoswith 1310
        mov     [esp+8], esi
1311
        pop     eax
1312
        mov     [esp+28], eax
1313
        mov     eax, [eax+fileRecordReference]
6273 pathoswith 1314
        mov     [ebp+NTFS.cur_iRecord], eax
2288 clevermous 1315
        popad
6471 pathoswith 1316
        cmp     byte [esi-1], 0
6468 pathoswith 1317
        jz      .ret2
6418 pathoswith 1318
        pop     eax
2288 clevermous 1319
        jmp     .doit2
1320
 
1321
;----------------------------------------------------------------
5954 pathoswith 1322
ntfs_ReadFile:
3742 clevermous 1323
        call    ntfs_lock
6468 pathoswith 1324
        call    ntfs_find_lfn
6845 pathoswith 1325
        jc      ntfsNotFound
6273 pathoswith 1326
        mov     [ebp+NTFS.cur_attr], 0x80   ; $DATA
1327
        and     [ebp+NTFS.cur_offs], 0
1328
        and     [ebp+NTFS.cur_size], 0
2288 clevermous 1329
        call    ntfs_read_attr
6845 pathoswith 1330
        jc      ntfsDenied
2288 clevermous 1331
        xor     eax, eax
6845 pathoswith 1332
        push    eax
3742 clevermous 1333
        cmp     dword [ebx+8], 0x200
6845 pathoswith 1334
        jnc     .eof
3742 clevermous 1335
        mov     ecx, [ebx+12]
1336
        mov     edx, [ebx+16]
1337
        mov     eax, [ebx+4]
2288 clevermous 1338
        test    eax, 0x1FF
1339
        jz      .alignedstart
1340
        push    edx
3742 clevermous 1341
        mov     edx, [ebx+8]
2288 clevermous 1342
        shrd    eax, edx, 9
1400 turbanoff 1343
        pop     edx
6273 pathoswith 1344
        mov     [ebp+NTFS.cur_offs], eax
1345
        mov     [ebp+NTFS.cur_size], 1
1346
        lea     eax, [ebp+NTFS.bitmap_buf]
1347
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1348
        call    ntfs_read_attr.continue
3742 clevermous 1349
        mov     eax, [ebx+4]
2288 clevermous 1350
        and     eax, 0x1FF
6273 pathoswith 1351
        lea     esi, [ebp+NTFS.bitmap_buf+eax]
1352
        sub     eax, [ebp+NTFS.cur_read]
6845 pathoswith 1353
        jae     .eof
2288 clevermous 1354
        neg     eax
1355
        push    ecx
1356
        cmp     ecx, eax
1357
        jb      @f
1358
        mov     ecx, eax
1359
@@:
6845 pathoswith 1360
        mov     [esp+4], ecx
2288 clevermous 1361
        mov     edi, edx
1362
        rep movsb
1363
        mov     edx, edi
1364
        pop     ecx
6845 pathoswith 1365
        sub     ecx, [esp]
1366
        jz      .retok
6273 pathoswith 1367
        cmp     [ebp+NTFS.cur_read], 0x200
6845 pathoswith 1368
        jnz     .eof
2288 clevermous 1369
.alignedstart:
3742 clevermous 1370
        mov     eax, [ebx+4]
2288 clevermous 1371
        push    edx
3742 clevermous 1372
        mov     edx, [ebx+8]
2288 clevermous 1373
        add     eax, 511
1374
        adc     edx, 0
1375
        shrd    eax, edx, 9
1376
        pop     edx
6273 pathoswith 1377
        mov     [ebp+NTFS.cur_offs], eax
1378
        mov     [ebp+NTFS.cur_buf], edx
2288 clevermous 1379
        mov     eax, ecx
1380
        shr     eax, 9
6273 pathoswith 1381
        mov     [ebp+NTFS.cur_size], eax
1382
        add     eax, [ebp+NTFS.cur_offs]
2288 clevermous 1383
        push    eax
1384
        call    ntfs_read_attr.continue
6273 pathoswith 1385
        pop     [ebp+NTFS.cur_offs]
1386
        mov     eax, [ebp+NTFS.cur_read]
6845 pathoswith 1387
        add     [esp], eax
2288 clevermous 1388
        mov     eax, ecx
1389
        and     eax, not 0x1FF
6273 pathoswith 1390
        cmp     [ebp+NTFS.cur_read], eax
6845 pathoswith 1391
        jnz     .eof
2288 clevermous 1392
        and     ecx, 0x1FF
1393
        jz      .retok
6273 pathoswith 1394
        add     edx, [ebp+NTFS.cur_read]
1395
        mov     [ebp+NTFS.cur_size], 1
1396
        lea     eax, [ebp+NTFS.bitmap_buf]
1397
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1398
        call    ntfs_read_attr.continue
6273 pathoswith 1399
        cmp     [ebp+NTFS.cur_read], ecx
2288 clevermous 1400
        jb      @f
6273 pathoswith 1401
        mov     [ebp+NTFS.cur_read], ecx
2288 clevermous 1402
@@:
6273 pathoswith 1403
        xchg    ecx, [ebp+NTFS.cur_read]
2288 clevermous 1404
        push    ecx
1405
        mov     edi, edx
6273 pathoswith 1406
        lea     esi, [ebp+NTFS.bitmap_buf]
6845 pathoswith 1407
        add     [esp+4], ecx
2288 clevermous 1408
        rep movsb
1409
        pop     ecx
6273 pathoswith 1410
        cmp     ecx, [ebp+NTFS.cur_read]
6845 pathoswith 1411
        jnz     .eof
1412
.retok:
1413
        pushd   0
1414
.ret:
3742 clevermous 1415
        call    ntfs_unlock
6845 pathoswith 1416
        pop     eax ebx
2288 clevermous 1417
        ret
1400 turbanoff 1418
 
6845 pathoswith 1419
.eof:
1420
        push    ERROR_END_OF_FILE
1421
        jmp     .ret
1422
 
2288 clevermous 1423
;----------------------------------------------------------------
3742 clevermous 1424
ntfs_ReadFolder:
1425
        call    ntfs_lock
6297 pathoswith 1426
        mov     [ebp+NTFS.cur_iRecord], 5   ; root directory
2288 clevermous 1427
        cmp     byte [esi], 0
6297 pathoswith 1428
        jz      @f
6468 pathoswith 1429
        call    ntfs_find_lfn
6297 pathoswith 1430
        jc      ntfsNotFound
1431
@@:
6273 pathoswith 1432
        mov     [ebp+NTFS.cur_attr], 0x10   ; $STANDARD_INFORMATION
1433
        and     [ebp+NTFS.cur_offs], 0
1434
        mov     [ebp+NTFS.cur_size], 1
1435
        lea     eax, [ebp+NTFS.bitmap_buf]
1436
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1437
        call    ntfs_read_attr
6297 pathoswith 1438
        jc      ntfsFail
6273 pathoswith 1439
        mov     [ebp+NTFS.cur_attr], 0x90   ; $INDEX_ROOT
6297 pathoswith 1440
.doit:
3742 clevermous 1441
        mov     eax, [ebp+NTFS.cur_index_size]
6273 pathoswith 1442
        mov     [ebp+NTFS.cur_size], eax
3742 clevermous 1443
        mov     eax, [ebp+NTFS.cur_index_buf]
6273 pathoswith 1444
        mov     [ebp+NTFS.cur_buf], eax
6297 pathoswith 1445
        call    ntfs_read_attr.newAttribute
1446
        jc      ntfsFail
6273 pathoswith 1447
        cmp     [ebp+NTFS.cur_read], 0x20
6297 pathoswith 1448
        jc      ntfsFail
3742 clevermous 1449
        mov     esi, [ebp+NTFS.cur_index_buf]
6340 pathoswith 1450
        mov     eax, [esi+indexRecordSize]
1451
        shr     eax, 9
1452
        cmp     [ebp+NTFS.cur_index_size], eax
6297 pathoswith 1453
        jc      .realloc
6340 pathoswith 1454
        mov     [ebp+NTFS.cur_subnode_size], eax
6297 pathoswith 1455
        add     esi, rootNode
1456
        mov     eax, [esi+nodeRealSize]
1457
        add     eax, rootNode
1458
        cmp     [ebp+NTFS.cur_read], eax
6408 pathoswith 1459
        jc      ntfsFail
1460
        mov     edi, [ebx+16]
1461
        mov     ecx, [ebx+12]
1462
        pushd   [ebx]
1463
        pushd   [ebx+8]     ; read ANSI/UNICODE name
1464
        push    edi
1465
        mov     edx, esp
1466
        mov     ebx, [ebx+4]
2288 clevermous 1467
; init header
1468
        xor     eax, eax
6408 pathoswith 1469
        mov     [edi+8], eax
1470
        mov     [edi+4], eax
1471
        inc     eax
1472
        mov     [edi], eax      ; version
1473
        add     edi, 32
3742 clevermous 1474
; edi -> BDFE, esi -> current index data, ebx = first wanted block,
2288 clevermous 1475
; ecx = number of blocks to read
1476
; edx -> parameters block: dd , dd 
6273 pathoswith 1477
        cmp     [ebp+NTFS.cur_iRecord], 5
2288 clevermous 1478
        jz      .skip_specials
1479
; dot and dotdot entries
1480
        push    esi
1481
        xor     esi, esi
1482
        call    .add_special_entry
1483
        inc     esi
1484
        call    .add_special_entry
1485
        pop     esi
1486
.skip_specials:
1487
; at first, dump index root
6297 pathoswith 1488
        add     esi, [esi+indexOffset]
2288 clevermous 1489
.dump_root:
6297 pathoswith 1490
        test    byte [esi+indexFlags], 2
2288 clevermous 1491
        jnz     .dump_root_done
1492
        call    .add_entry
6297 pathoswith 1493
        movzx   eax, word [esi+indexAllocatedSize]
2288 clevermous 1494
        add     esi, eax
1495
        jmp     .dump_root
6297 pathoswith 1496
 
1497
.realloc:
6340 pathoswith 1498
        mov     edi, eax
1499
        mov     eax, [esi+indexRecordSize]
1500
        shl     eax, 1
1501
        stdcall kernel_alloc, eax
6297 pathoswith 1502
        test    eax, eax
6408 pathoswith 1503
        jz      ntfsFail
6405 pathoswith 1504
        mov     edx, [ebp+NTFS.cur_index_buf]
1505
        cmp     edx, [ebp+NTFS.secondIndexBuffer]
1506
        jc      @f
1507
        mov     edx, [ebp+NTFS.secondIndexBuffer]
1508
@@:
6297 pathoswith 1509
        mov     [ebp+NTFS.cur_index_buf], eax
6340 pathoswith 1510
        add     eax, [esi+indexRecordSize]
1511
        mov     [ebp+NTFS.secondIndexBuffer], eax
1512
        mov     [ebp+NTFS.cur_index_size], edi
6405 pathoswith 1513
        stdcall kernel_free, edx
6297 pathoswith 1514
        jmp     .doit
1515
 
2288 clevermous 1516
.dump_root_done:
1517
; now dump all subnodes
1518
        push    ecx edi
6273 pathoswith 1519
        lea     edi, [ebp+NTFS.bitmap_buf]
1520
        mov     [ebp+NTFS.cur_buf], edi
2288 clevermous 1521
        mov     ecx, 0x400/4
1522
        xor     eax, eax
1523
        rep stosd
6273 pathoswith 1524
        mov     [ebp+NTFS.cur_attr], 0xB0   ; $BITMAP
1525
        and     [ebp+NTFS.cur_offs], 0
1526
        mov     [ebp+NTFS.cur_size], 2
6297 pathoswith 1527
        call    ntfs_read_attr.newAttribute
2288 clevermous 1528
        pop     edi ecx
1529
        push    0       ; save offset in $BITMAP attribute
6273 pathoswith 1530
        and     [ebp+NTFS.cur_offs], 0
2288 clevermous 1531
.dumploop:
6273 pathoswith 1532
        mov     [ebp+NTFS.cur_attr], 0xA0
3742 clevermous 1533
        mov     eax, [ebp+NTFS.cur_subnode_size]
6273 pathoswith 1534
        mov     [ebp+NTFS.cur_size], eax
6297 pathoswith 1535
        mov     esi, [ebp+NTFS.cur_index_buf]
1536
        mov     [ebp+NTFS.cur_buf], esi
6273 pathoswith 1537
        mov     eax, [ebp+NTFS.cur_offs]
6297 pathoswith 1538
        push    eax
3742 clevermous 1539
        imul    eax, [ebp+NTFS.cur_subnode_size]
6273 pathoswith 1540
        mov     [ebp+NTFS.cur_offs], eax
6297 pathoswith 1541
        call    ntfs_read_attr.newAttribute
6273 pathoswith 1542
        pop     [ebp+NTFS.cur_offs]
3742 clevermous 1543
        mov     eax, [ebp+NTFS.cur_subnode_size]
2288 clevermous 1544
        shl     eax, 9
6273 pathoswith 1545
        cmp     [ebp+NTFS.cur_read], eax
2288 clevermous 1546
        jnz     .done
1547
        push    eax
6273 pathoswith 1548
        mov     eax, [ebp+NTFS.cur_offs]
2288 clevermous 1549
        and     eax, 0x400*8-1
6273 pathoswith 1550
        bt      dword [ebp+NTFS.bitmap_buf], eax
2288 clevermous 1551
        pop     eax
1552
        jnc     .dump_subnode_done
1553
        cmp     dword [esi], 'INDX'
1554
        jnz     .dump_subnode_done
1555
        push    ebx
1556
        mov     ebx, esi
1557
        call    ntfs_restore_usa
1558
        pop     ebx
1559
        jc      .dump_subnode_done
6297 pathoswith 1560
        add     esi, recordNode
1561
        add     esi, [esi+indexOffset]
2288 clevermous 1562
.dump_subnode:
6297 pathoswith 1563
        test    byte [esi+indexFlags], 2
2288 clevermous 1564
        jnz     .dump_subnode_done
1565
        call    .add_entry
6297 pathoswith 1566
        movzx   eax, word [esi+indexAllocatedSize]
2288 clevermous 1567
        add     esi, eax
1568
        jmp     .dump_subnode
6297 pathoswith 1569
 
2288 clevermous 1570
.dump_subnode_done:
6273 pathoswith 1571
        inc     [ebp+NTFS.cur_offs]
1572
        test    [ebp+NTFS.cur_offs], 0x400*8-1
2288 clevermous 1573
        jnz     .dumploop
6273 pathoswith 1574
        mov     [ebp+NTFS.cur_attr], 0xB0
2288 clevermous 1575
        push    ecx edi
6273 pathoswith 1576
        lea     edi, [ebp+NTFS.bitmap_buf]
1577
        mov     [ebp+NTFS.cur_buf], edi
2288 clevermous 1578
        mov     ecx, 0x400/4
1579
        xor     eax, eax
1580
        rep stosd
1581
        pop     edi ecx
1582
        pop     eax
6273 pathoswith 1583
        push    [ebp+NTFS.cur_offs]
2288 clevermous 1584
        inc     eax
6273 pathoswith 1585
        mov     [ebp+NTFS.cur_offs], eax
1586
        mov     [ebp+NTFS.cur_size], 2
2288 clevermous 1587
        push    eax
6297 pathoswith 1588
        call    ntfs_read_attr.newAttribute
2288 clevermous 1589
        pop     eax
6273 pathoswith 1590
        pop     [ebp+NTFS.cur_offs]
2288 clevermous 1591
        push    eax
1592
        jmp     .dumploop
6297 pathoswith 1593
 
2288 clevermous 1594
.done:
1595
        pop     eax
6408 pathoswith 1596
        pop     eax
1597
        mov     ebx, [eax+4]
1598
        pop     eax
1599
        pop     eax
1600
        test    eax, eax
1601
        jz      .ret
2288 clevermous 1602
        xor     eax, eax
1603
        dec     ecx
1604
        js      @f
1605
        mov     al, ERROR_END_OF_FILE
1606
@@:
6408 pathoswith 1607
        push    eax
3742 clevermous 1608
        call    ntfs_unlock
6408 pathoswith 1609
        pop     eax
2288 clevermous 1610
        ret
1611
 
1612
.add_special_entry:
1613
        mov     eax, [edx]
1614
        inc     dword [eax+8]   ; new file found
1615
        dec     ebx
1616
        jns     .ret
1617
        dec     ecx
1618
        js      .ret
1619
        inc     dword [eax+4]   ; new file block copied
1620
        mov     eax, [edx+4]
1621
        mov     [edi+4], eax
1622
        mov     eax, 0x10
1623
        stosd
1624
        scasd
6462 pathoswith 1625
        push    ebx ecx edx
6273 pathoswith 1626
        mov     eax, dword [ebp+NTFS.bitmap_buf]
1627
        mov     edx, dword [ebp+NTFS.bitmap_buf+4]
2288 clevermous 1628
        call    ntfs_datetime_to_bdfe
6273 pathoswith 1629
        mov     eax, dword [ebp+NTFS.bitmap_buf+0x18]
1630
        mov     edx, dword [ebp+NTFS.bitmap_buf+0x1C]
2288 clevermous 1631
        call    ntfs_datetime_to_bdfe
6273 pathoswith 1632
        mov     eax, dword [ebp+NTFS.bitmap_buf+8]
1633
        mov     edx, dword [ebp+NTFS.bitmap_buf+0xC]
2288 clevermous 1634
        call    ntfs_datetime_to_bdfe
6462 pathoswith 1635
        pop     edx ecx ebx
2288 clevermous 1636
        xor     eax, eax
1637
        stosd
1638
        stosd
1639
        mov     al, '.'
1640
        push    edi ecx
1641
        lea     ecx, [esi+1]
6798 pathoswith 1642
        cmp     dword[edi-36], 2
1643
        jz      .utf16sp
1644
        rep stosb
1645
        mov     byte [edi], 0
1646
        pop     ecx edi
1647
        cmp     dword[edi-36], 3
2288 clevermous 1648
        jz      @f
6798 pathoswith 1649
        add     edi, 264
2288 clevermous 1650
        ret
6297 pathoswith 1651
 
6798 pathoswith 1652
.utf16sp:
1653
        rep stosw
1654
        mov     word [edi], 0
1655
        pop     ecx edi
2288 clevermous 1656
@@:
6798 pathoswith 1657
        add     edi, 520
2288 clevermous 1658
.ret:
1659
        ret
1660
 
1661
.add_entry:
1662
; do not return DOS 8.3 names
6297 pathoswith 1663
        cmp     byte [esi+namespace], 2
2288 clevermous 1664
        jz      .ret
1665
; do not return system files
6798 pathoswith 1666
        cmp     dword[esi+fileRecordReference], 16
2288 clevermous 1667
        jb      .ret
6798 pathoswith 1668
        cmp     byte [esi+fileNameLength], 0
1669
        jz      .ret
2288 clevermous 1670
        mov     eax, [edx]
1671
        inc     dword [eax+8]   ; new file found
1672
        dec     ebx
1673
        jns     .ret
1674
        dec     ecx
1675
        js      .ret
1676
        inc     dword [eax+4]   ; new file block copied
1677
        mov     eax, [edx+4]    ; flags
1678
        call    ntfs_direntry_to_bdfe
1679
        push    ecx esi edi
6297 pathoswith 1680
        movzx   ecx, byte [esi+fileNameLength]
1681
        add     esi, fileName
6798 pathoswith 1682
        cmp     dword[edi-36], 2
1683
        jz      .utf16
1684
        cmp     dword[edi-36], 3
1685
        jz      .utf8
2288 clevermous 1686
@@:
1687
        lodsw
1688
        call    uni2ansi_char
1689
        stosb
1690
        loop    @b
6798 pathoswith 1691
        mov     byte [edi], 0
1692
        pop     edi esi ecx
2288 clevermous 1693
        add     edi, 264
1694
        ret
1695
 
6798 pathoswith 1696
.utf8:
1697
        push    ecx
1698
        mov     cx, 519
1699
@@:
1700
        lodsw
1701
        call    UTF16to8
1702
        js      @f
1703
        dec     dword[esp]
1704
        jnz     @b
1705
@@:
1706
        mov     byte [edi], 0
1707
        pop     edi
1708
@@:
1709
        pop     edi esi ecx
1710
        add     edi, 520
1711
        ret
1712
 
1713
.utf16:
1714
        rep movsw
1715
        mov     word [edi], 0
1716
        jmp     @b
1717
 
2288 clevermous 1718
ntfs_direntry_to_bdfe:
1719
        mov     [edi+4], eax    ; ANSI/UNICODE name
6297 pathoswith 1720
        mov     eax, [esi+fileFlags]
2288 clevermous 1721
        test    eax, 0x10000000
1722
        jz      @f
1723
        and     eax, not 0x10000000
1724
        or      al, 0x10
1725
@@:
1726
        stosd
1727
        scasd
6462 pathoswith 1728
        push    ebx ecx edx
6297 pathoswith 1729
        mov     eax, [esi+fileCreated]
1730
        mov     edx, [esi+fileCreated+4]
2288 clevermous 1731
        call    ntfs_datetime_to_bdfe
6297 pathoswith 1732
        mov     eax, [esi+fileAccessed]
1733
        mov     edx, [esi+fileAccessed+4]
2288 clevermous 1734
        call    ntfs_datetime_to_bdfe
6297 pathoswith 1735
        mov     eax, [esi+fileModified]
1736
        mov     edx, [esi+fileModified+4]
2288 clevermous 1737
        call    ntfs_datetime_to_bdfe
6462 pathoswith 1738
        pop     edx ecx ebx
6297 pathoswith 1739
        mov     eax, [esi+fileRealSize]
2288 clevermous 1740
        stosd
6297 pathoswith 1741
        mov     eax, [esi+fileRealSize+4]
2288 clevermous 1742
        stosd
1743
        ret
1744
 
1745
ntfs_datetime_to_bdfe:
6462 pathoswith 1746
; in: edx:eax = seconds since 01.01.1601 x10000000
1747
; edi -> data block
1748
; out: edi = edi+8
1749
        sub     eax, 3365781504
1750
        sbb     edx, 29389701
6297 pathoswith 1751
        mov     ecx, 10000000
6462 pathoswith 1752
        cmp     edx, ecx
1753
        jc      @f
2288 clevermous 1754
        xor     edx, edx
6462 pathoswith 1755
@@:
6297 pathoswith 1756
        div     ecx
6462 pathoswith 1757
        jmp     fsTime2bdfe
2288 clevermous 1758
 
1759
;----------------------------------------------------------------
6420 pathoswith 1760
ntfs_GetFileInfo:
6426 pathoswith 1761
        call    ntfs_lock
1762
        mov     edi, [ebx+16]
6420 pathoswith 1763
        cmp     byte [esi], 0
6426 pathoswith 1764
        jz      .volume
6468 pathoswith 1765
        call    ntfs_find_lfn
6420 pathoswith 1766
        jnc     .found
1767
        test    eax, eax
1768
        jz      ntfsFail
1769
        jmp     ntfsNotFound
1770
 
1771
.found:
1772
        mov     esi, eax
1773
        xor     eax, eax
1774
        call    ntfs_direntry_to_bdfe
6426 pathoswith 1775
.end:
6420 pathoswith 1776
        call    ntfs_unlock
1777
        xor     eax, eax
1778
        ret
1779
 
6426 pathoswith 1780
.volume:
1781
        mov     byte [edi], 8
1782
        mov     eax, [ebx+8]
1783
        mov     [edi+4], eax
1784
        mov     eax, dword [ebp+NTFS.Length]
1785
        mov     edx, dword [ebp+NTFS.Length+4]
1786
        shld    edx, eax, 9
1787
        shl     eax, 9
1788
        mov     [edi+36], edx
1789
        mov     [edi+32], eax
1790
        add     edi, 40
1791
        mov     [ebp+NTFS.cur_buf], edi
1792
        mov     [ebp+NTFS.cur_iRecord], 3
1793
        mov     [ebp+NTFS.cur_attr], 0x60
1794
        mov     [ebp+NTFS.cur_offs], 0
1795
        mov     [ebp+NTFS.cur_size], 1
1796
        call    ntfs_read_attr
1797
        jc      ntfsFail
1798
        mov     ecx, [ebp+NTFS.cur_read]
1799
        mov     [edi+ecx], ax
1800
        cmp     [ebx+8], eax
1801
        jnz     .end
1802
        mov     esi, edi
1803
        shr     ecx, 1
6428 pathoswith 1804
        jz      .end
6426 pathoswith 1805
@@:
1806
        lodsw
1807
        call    uni2ansi_char
1808
        stosb
6471 pathoswith 1809
        loop    @b
6426 pathoswith 1810
        mov     byte [edi], 0
1811
        jmp     .end
1812
 
6420 pathoswith 1813
;----------------------------------------------------------------
3742 clevermous 1814
ntfs_CreateFolder:
6273 pathoswith 1815
        mov     [ebp+NTFS.bFolder], 1
5954 pathoswith 1816
        jmp     @f
5994 pathoswith 1817
 
5954 pathoswith 1818
ntfs_CreateFile:
6273 pathoswith 1819
        mov     [ebp+NTFS.bFolder], 0
5954 pathoswith 1820
@@: ; 1. Search file
1821
        call    ntfs_lock
6468 pathoswith 1822
        call    ntfs_find_lfn
6080 pathoswith 1823
        jc      .notFound
1824
; found, rewrite
6273 pathoswith 1825
        cmp     [ebp+NTFS.cur_iRecord], 16
6019 pathoswith 1826
        jc      ntfsDenied
6273 pathoswith 1827
        cmp     [ebp+NTFS.bFolder], 1
6080 pathoswith 1828
        jz      .folder
6420 pathoswith 1829
        test    byte [eax+fileFlags], 1
1830
        jnz     ntfsDenied
6273 pathoswith 1831
        cmp     [ebp+NTFS.fragmentCount], 1
6080 pathoswith 1832
        jnz     ntfsUnsupported     ; record fragmented
6151 pathoswith 1833
; edit directory node
6080 pathoswith 1834
        mov     edi, [ebp+NTFS.cur_index_buf]
1835
        cmp     dword [edi], 'INDX'
1836
        jz      @f
1837
        mov     esi, [ebp+NTFS.frs_buffer]
1838
        mov     ecx, [esi+recordRealSize]
1839
        shr     ecx, 2
1840
        rep movsd
6273 pathoswith 1841
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 1842
        mov     cl, [esi+attributeOffset]
1843
        sub     esi, [ebp+NTFS.frs_buffer]
1844
        add     eax, ecx
1845
        add     eax, esi
1846
@@:
6420 pathoswith 1847
        mov     edi, eax
1848
        mov     eax, [ebx+12]
1849
        mov     [edi+fileRealSize], eax
1850
        mov     dword [edi+fileRealSize+4], 0
1851
        push    ebx eax
1852
        call    ntfsGetTime
1853
        mov     [edi+fileModified], eax
1854
        mov     [edi+fileModified+4], edx
1855
        mov     [edi+recordModified], eax
1856
        mov     [edi+recordModified+4], edx
1857
        mov     [edi+fileAccessed], eax
1858
        mov     [edi+fileAccessed+4], edx
1859
        pop     edx ebx
6273 pathoswith 1860
        mov     eax, [ebp+NTFS.LastRead]
6080 pathoswith 1861
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 1862
        mov     [ebp+NTFS.cur_attr], 0x80
1863
        mov     [ebp+NTFS.cur_offs], 0
1864
        mov     [ebp+NTFS.cur_size], 0
5994 pathoswith 1865
        call    ntfs_read_attr
6080 pathoswith 1866
        jc      ntfsFail
6420 pathoswith 1867
        mov     esi, edi
1868
        mov     edi, [ebp+NTFS.frs_buffer]
1869
        cmp     word [edi+baseRecordReuse], 0
1870
        jnz     ntfsUnsupported     ; auxiliary record
1871
        mov     al, [edi+attributeOffset]
1872
        add     edi, eax
1873
        mov     al, [edi+attributeOffset]
1874
        add     edi, eax
1875
        mov     ecx, 6
1876
        add     esi, fileModified
1877
        add     edi, 8
1878
        rep movsd
6080 pathoswith 1879
        mov     eax, edx
1880
        xor     edx, edx
6273 pathoswith 1881
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 1882
        cmp     word [ecx+attributeFlags], 0
1883
        jnz     ntfsUnsupported
1884
        push    ebx
1885
        cmp     byte [ecx+nonResidentFlag], 0
1886
        jz      @f
6080 pathoswith 1887
        cmp     [ecx+attributeRealSize+4], edx
1888
        jnz     @f
5994 pathoswith 1889
        cmp     [ecx+attributeRealSize], eax
6080 pathoswith 1890
        jz      ntfs_WriteFile.writeNode
1891
@@:
1892
        jmp     ntfs_WriteFile.resizeAttribute
5994 pathoswith 1893
 
6080 pathoswith 1894
.folder:
1895
        bt      dword [eax+fileFlags], 28
1896
        jnc     ntfsDenied
1897
        push    0
1898
        jmp     ntfsOut
1899
 
1900
.notFound:  ; create
1901
        test    eax, eax
1902
        jz      ntfsFail
6273 pathoswith 1903
        cmp     [ebp+NTFS.fragmentCount], 1
6080 pathoswith 1904
        jnz     ntfsUnsupported     ; record fragmented
6019 pathoswith 1905
; 2. Prepare directory record
6471 pathoswith 1906
        mov     edi, esi
1907
        mov     edx, eax
1908
        xor     ecx, ecx
5954 pathoswith 1909
@@:         ; count characters
6471 pathoswith 1910
        call    utf8to16
1911
        cmp     ax, '/'
1912
        jz      ntfsNotFound    ; path folder not found
5954 pathoswith 1913
        inc     ecx
6471 pathoswith 1914
        test    ax, ax
5954 pathoswith 1915
        jnz     @b
6471 pathoswith 1916
        dec     ecx
1917
        push    ecx     ; name length in chars
1918
        push    edi
6297 pathoswith 1919
        shl     ecx, 1
1920
        add     ecx, fileName+7
1921
        and     ecx, not 7
5954 pathoswith 1922
        mov     edi, [ebp+NTFS.cur_index_buf]
6471 pathoswith 1923
        mov     eax, [ebx+12]
1924
        mov     [ebp+NTFS.fileRealSize], eax
1925
        mov     eax, [ebx+16]
1926
        mov     [ebp+NTFS.fileDataBuffer], eax
6297 pathoswith 1927
        push    ecx     ; index length
6471 pathoswith 1928
        mov     eax, edx
6292 pathoswith 1929
        mov     edx, ecx
6019 pathoswith 1930
        cmp     dword [edi], 'INDX'
5954 pathoswith 1931
        jz      .indexRecord
6019 pathoswith 1932
        mov     esi, [ebp+NTFS.frs_buffer]  ; indexRoot
6292 pathoswith 1933
        mov     ecx, [esi+recordRealSize]
5954 pathoswith 1934
        add     edx, ecx
1935
        cmp     [esi+recordAllocatedSize], edx
6292 pathoswith 1936
        jc      .growTree
5954 pathoswith 1937
        mov     [esi+recordRealSize], edx
1938
        shr     ecx, 2
1939
        rep movsd
6407 pathoswith 1940
        mov     edi, [ebp+NTFS.indexRoot]
5954 pathoswith 1941
        sub     edi, [ebp+NTFS.frs_buffer]
1942
        add     edi, [ebp+NTFS.cur_index_buf]
1943
        mov     esi, [esp]
1944
        add     [edi+sizeWithHeader], esi
1945
        add     [edi+sizeWithoutHeader], esi
6019 pathoswith 1946
        mov     cl, [edi+attributeOffset]
5954 pathoswith 1947
        add     edi, ecx
6273 pathoswith 1948
        add     [edi+rootNode+nodeRealSize], esi
1949
        add     [edi+rootNode+nodeAllocatedSize], esi
5954 pathoswith 1950
        sub     eax, [ebp+NTFS.cur_index_buf]
1951
        add     eax, edi
1952
        mov     edi, [ebp+NTFS.cur_index_buf]
1953
        jmp     .common
2288 clevermous 1954
 
6411 pathoswith 1955
.growTree:  ; create indexRecord
1956
        mov     edi, [ebp+NTFS.cur_index_buf]
6292 pathoswith 1957
        mov     ecx, 10
1958
        xor     eax, eax
1959
        rep stosd
6407 pathoswith 1960
        mov     esi, [ebp+NTFS.indexRoot]
6340 pathoswith 1961
        mov     al, [esi+attributeOffset]
1962
        add     esi, eax
6292 pathoswith 1963
        rdtsc
1964
        stosw
1965
        mov     eax, [esi+indexRecordSize]
1966
        cmp     eax, [ebp+NTFS.frs_size]
6407 pathoswith 1967
        jc      .errorPop3
6292 pathoswith 1968
        shr     eax, 9
1969
        inc     eax
1970
        mov     edi, [ebp+NTFS.cur_index_buf]
1971
        mov     dword[edi], 'INDX'
1972
        mov     byte [edi+updateSequenceOffset], 28h
1973
        mov     [edi+updateSequenceSize], al
1974
        add     edi, recordNode
1975
        shl     eax, 1
1976
        add     eax, 28h-recordNode+7
1977
        and     eax, not 7
1978
        mov     [edi+indexOffset], eax
1979
        mov     ecx, [esi+indexRecordSize]
1980
        sub     ecx, recordNode
1981
        mov     [edi+nodeAllocatedSize], ecx
1982
        add     esi, rootNode
1983
        push    esi
1984
        mov     ecx, [esi+nodeRealSize]
1985
        sub     ecx, [esi+indexOffset]
1986
        add     eax, ecx
1987
        mov     [edi+nodeRealSize], eax
6411 pathoswith 1988
        mov     eax, [esi+nonLeafFlag]
1989
        mov     [edi+nonLeafFlag], eax
6292 pathoswith 1990
        shr     ecx, 2
1991
        add     esi, [esi+indexOffset]
1992
        add     edi, [edi+indexOffset]
1993
        rep movsd       ; copy root indexes
1994
; clear root node
1995
        mov     cl, 10
1996
        mov     edi, [esp]
1997
        xor     eax, eax
1998
        rep stosd
1999
        pop     edi
2000
        mov     byte [edi+indexOffset], 16
2001
        mov     byte [edi+nodeRealSize], 28h
2002
        mov     byte [edi+nodeAllocatedSize], 28h
2003
        mov     byte [edi+nonLeafFlag], 1
2004
        mov     byte [edi+16+indexAllocatedSize], 18h
2005
        mov     byte [edi+16+indexFlags], 3
6407 pathoswith 2006
        mov     esi, [ebp+NTFS.indexRoot]
6292 pathoswith 2007
        add     edi, 28h
2008
        mov     eax, edi
2009
        sub     eax, esi
2010
        mov     word [esi+sizeWithoutHeader], 38h
2011
        xchg    [esi+sizeWithHeader], eax
6407 pathoswith 2012
        add     esi, eax
2013
        mov     [ebp+NTFS.attr_offs], edi
2014
        cmp     byte [esi], 0xA0
2015
        jnz     @f
2016
        cmp     dword [esi+attributeAllocatedSize], 0
2017
        jz      @f
2018
        mov     eax, [ebp+NTFS.frs_buffer]
2019
        mov     ecx, eax
2020
        add     ecx, [eax+recordRealSize]
2021
        sub     ecx, esi
2022
        shr     ecx, 2
2023
        rep movsd
2024
        sub     edi, eax
2025
        mov     [eax+recordRealSize], edi
2026
        call    .ntfsNodeAlloc
2027
        jc      ntfsErrorPop3
2028
        mov     eax, [ebp+NTFS.newRecord]
2029
        mov     edi, [ebp+NTFS.cur_index_buf]
2030
        mov     [edi+recordVCN], eax
2031
        mov     edi, [ebp+NTFS.attr_offs]
2032
        mov     [edi-8], eax
2033
        jmp     .refresh
2034
 
2035
@@:
6292 pathoswith 2036
        mov     cl, 32
2037
        xor     eax, eax
2038
        rep stosd
6407 pathoswith 2039
        mov     eax, [ebp+NTFS.cur_subnode_size]
2040
        cmp     eax, [ebp+NTFS.cur_size]
2041
        jnz     @f
6824 pathoswith 2042
        cmp     [ebp+NTFS.sectors_per_cluster], 1
2043
        jz      @f
6407 pathoswith 2044
        mov     al, 1
2045
@@:
2046
        mov     [ebp+NTFS.fileDataSize], eax
6292 pathoswith 2047
        mov     edi, [ebp+NTFS.BitmapStart]
2048
        call    ntfsSpaceAlloc
6407 pathoswith 2049
        movi    eax, ERROR_DISK_FULL
2050
        jc      ntfsErrorPop3
2051
; create $IndexAllocation
2052
        mov     edi, [ebp+NTFS.attr_offs]
6292 pathoswith 2053
        mov     byte [edi+attributeType], 0xA0
2054
        mov     byte [edi+nonResidentFlag], 1
2055
        mov     byte [edi+nameLength], 4
2056
        mov     byte [edi+nameOffset], 40h
2057
        mov     byte [edi+dataRunsOffset], 48h
2058
        mov     byte [edi+sizeWithHeader], 50h
2059
        mov     eax, [ebp+NTFS.fileDataSize]
2060
        dec     eax
2061
        mov     [edi+lastVCN], eax
2062
        inc     eax
2063
        mul     [ebp+NTFS.sectors_per_cluster]
2064
        shl     eax, 9
2065
        mov     [edi+attributeAllocatedSize], eax
2066
        mov     [edi+attributeRealSize], eax
2067
        mov     [edi+initialDataSize], eax
2068
        mov     dword[edi+40h], 490024h     ; unicode $I30
2069
        mov     dword[edi+40h+4], 300033h
2070
        push    edi
2071
        mov     esi, edi
2072
        add     edi, 48h
2073
        call    createMcbEntry
2074
        mov     esi, [ebp+NTFS.frs_buffer]
2075
        pop     edi
2076
        mov     al, [esi+newAttributeID]
2077
        mov     [edi+attributeID], al
2078
        add     edi, 50h
2079
        inc     eax
2080
; create $Bitmap
2081
        mov     [edi+attributeID], al
2082
        inc     eax
2083
        mov     [esi+newAttributeID], al
2084
        mov     byte [edi+attributeType], 0xB0
2085
        mov     byte [edi+nameLength], 4
2086
        mov     byte [edi+nameOffset], 18h
2087
        mov     byte [edi+attributeOffset], 20h
2088
        mov     byte [edi+sizeWithoutHeader], 8
2089
        mov     byte [edi+sizeWithHeader], 28h
2090
        mov     dword[edi+18h], 490024h     ; unicode $I30
2091
        mov     dword[edi+18h+4], 300033h
2092
        mov     byte [edi+20h], 1
2093
        mov     dword[edi+28h], -1
2094
        add     edi, 30h
2095
        sub     edi, esi
2096
        mov     [esi+recordRealSize], edi
2097
        mov     eax, [ebp+NTFS.fileDataStart]
2098
        mul     [ebp+NTFS.sectors_per_cluster]
6408 pathoswith 2099
        mov     edx, eax
6407 pathoswith 2100
        jmp     @f
2101
 
2102
.refresh:
2103
        mov     [ebp+NTFS.cur_size], 0
2104
        call    ntfs_read_attr.continue
2105
        movi    eax, ERROR_FS_FAIL
2106
        jc      ntfsErrorPop3
6408 pathoswith 2107
        mov     edx, [ebp+NTFS.LastRead]
6407 pathoswith 2108
@@:
6408 pathoswith 2109
        mov     ebx, [ebp+NTFS.cur_index_buf]
6407 pathoswith 2110
        call    writeRecord
6408 pathoswith 2111
        mov     ebx, [ebp+NTFS.frs_buffer]
2112
        mov     edx, [ebp+NTFS.rootLastRead]
6407 pathoswith 2113
        call    writeRecord
2114
        mov     esi, [esp+4]
6468 pathoswith 2115
        call    ntfs_find_lfn.doit2
6407 pathoswith 2116
        test    eax, eax
2117
        jz      .errorPop3
6292 pathoswith 2118
        mov     edi, [ebp+NTFS.cur_index_buf]
2119
        mov     edx, [esp]
5954 pathoswith 2120
.indexRecord:
6273 pathoswith 2121
        add     edi, recordNode
6292 pathoswith 2122
        add     edx, [edi+nodeRealSize]
6273 pathoswith 2123
        cmp     [edi+nodeAllocatedSize], edx
6340 pathoswith 2124
        jc      .arborizeTree
2125
        mov     [edi+nodeRealSize], edx
2126
        jmp     .common
2127
 
2128
.errorPop3:
5954 pathoswith 2129
        add     esp, 12
6340 pathoswith 2130
        jmp     ntfsUnsupported
6292 pathoswith 2131
 
6407 pathoswith 2132
.ntfsNodeAlloc:
2133
; in: [ebp+NTFS.attr_offs] -> $IndexAllocation
2134
;   out:
2135
; [ebp+NTFS.newRecord] = node VCN
2136
; [ebp+NTFS.cur_offs]
2137
; CF=1 -> eax = error code
6340 pathoswith 2138
        mov     esi, [ebp+NTFS.attr_offs]
2139
        add     esi, [esi+sizeWithHeader]
2140
        cmp     byte [esi], 0xB0
6407 pathoswith 2141
        jnz     .ret
6414 pathoswith 2142
        movzx   ecx, word [esi+sizeWithoutHeader]
2143
        shr     ecx, 2
2144
        movzx   edi, byte [esi+attributeOffset]
2145
        add     edi, esi
2146
        mov     edx, edi
2147
        or      eax, -1
2148
        repz scasd
2149
        jnz     @f
2150
        cmp     [edi], eax
2151
        jnz     .ret
2152
; extend folder $Bitmap
2153
        add     word [esi+sizeWithHeader], 8
2154
        add     word [esi+sizeWithoutHeader], 8
2155
        mov     esi, [ebp+NTFS.frs_buffer]
2156
        mov     eax, [esi+recordRealSize]
2157
        add     eax, 8
2158
        cmp     [esi+recordAllocatedSize], eax
2159
        jc      .ret
2160
        mov     [esi+recordRealSize], eax
2161
        xor     eax, eax
2162
        stosd
2163
        mov     [edi], eax
2164
        mov     [edi+8], eax
2165
        dec     eax
2166
        mov     [edi+4], eax
2167
@@:
2168
        sub     edi, 4
2169
        mov     eax, [edi]
6340 pathoswith 2170
        not     eax
2171
        bsf     eax, eax
6414 pathoswith 2172
        bts     [edi], eax
2173
        sub     edi, edx
2174
        shl     edi, 3
2175
        add     eax, edi
6340 pathoswith 2176
        mul     [ebp+NTFS.cur_subnode_size]
2177
        mov     [ebp+NTFS.newRecord], eax
6407 pathoswith 2178
        mov     ecx, [ebp+NTFS.cur_size]
2179
        cmp     ecx, [ebp+NTFS.cur_subnode_size]
2180
        jz      @f
2181
        mul     [ebp+NTFS.sectors_per_cluster]
2182
@@:
2183
        mov     [ebp+NTFS.cur_offs], eax
2184
        add     eax, ecx
2185
        shl     eax, 9
2186
        mov     esi, [ebp+NTFS.attr_offs]
2187
        cmp     [esi+attributeAllocatedSize], eax
2188
        jnc     @f
2189
        xor     edx, edx
2190
        jmp     resizeAttribute
2191
 
2192
.ret:
2193
        movi    eax, ERROR_UNSUPPORTED_FS
2194
        stc
2195
@@:
2196
        ret
2197
 
2198
.arborizeTree:      ; find median index
6340 pathoswith 2199
        mov     ecx, [edi+nodeRealSize]
2200
        sub     ecx, [edi+indexOffset]
2201
        shr     ecx, 1
2202
        add     edi, [edi+indexOffset]
2203
        xor     eax, eax
2204
@@:
2205
        add     edi, eax
2206
        mov     ax, [edi+indexAllocatedSize]
2207
        sub     ecx, eax
2208
        jnc     @b
6407 pathoswith 2209
        add     eax, 8
6340 pathoswith 2210
        mov     esi, [ebp+NTFS.secondIndexBuffer]
2211
        cmp     dword [esi], 'INDX'
6411 pathoswith 2212
        jz      @f
6340 pathoswith 2213
; move index to the root node
2214
        mov     esi, [ebp+NTFS.frs_buffer]
6407 pathoswith 2215
        mov     ecx, eax
2216
        add     ecx, 8
2217
        add     ecx, [esi+recordRealSize]
6340 pathoswith 2218
        cmp     [esi+recordAllocatedSize], ecx
6411 pathoswith 2219
        jc      .growTree
6409 pathoswith 2220
        push    edi eax
6407 pathoswith 2221
        call    .ntfsNodeAlloc
6414 pathoswith 2222
        jc      ntfsErrorPop5
2223
        pop     eax
6340 pathoswith 2224
        mov     edi, [ebp+NTFS.indexRoot]
2225
        add     [ebp+NTFS.attr_offs], eax
2226
        add     [edi+sizeWithHeader], eax
2227
        add     [edi+sizeWithoutHeader], eax
2228
        movzx   ecx, byte [edi+attributeOffset]
2229
        add     ecx, edi
2230
        add     [ecx+rootNode+nodeRealSize], eax
2231
        add     [ecx+rootNode+nodeAllocatedSize], eax
6405 pathoswith 2232
        add     ecx, [ebp+NTFS.indexPointer]
6340 pathoswith 2233
        sub     ecx, [ebp+NTFS.secondIndexBuffer]
6409 pathoswith 2234
        mov     esi, [ebp+NTFS.frs_buffer]
2235
        add     [esi+recordRealSize], eax
2236
        add     esi, [esi+recordRealSize]
6340 pathoswith 2237
        mov     edi, esi
2238
        sub     esi, eax
2239
        neg     ecx
2240
        add     ecx, esi
2241
        shr     ecx, 2
2242
        sub     esi, 4
2243
        sub     edi, 4
2244
        std
2245
        rep movsd   ; make space
2246
        mov     [edi], ecx
2247
        mov     edi, esi
2248
        add     edi, 4
2249
        mov     esi, [esp]
2250
        add     word [esi+indexAllocatedSize], 8
2251
        mov     byte [esi+indexFlags], 1
2252
        mov     ecx, eax
2253
        sub     ecx, 8
2254
        shr     ecx, 2
2255
        cld
2256
        rep movsd   ; insert index
2257
        mov     eax, [ebp+NTFS.newRecord]
2258
        stosd
6411 pathoswith 2259
        jmp     .splitNode
2260
 
6414 pathoswith 2261
.growBranch:    ; move node and replace it with empty one
2262
        mov     esi, [ebp+NTFS.cur_index_buf]
2263
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2264
        mov     eax, [esi+recordVCN]
2265
        mov     [edi+recordVCN], eax
2266
        add     edi, recordNode
2267
        mov     eax, [edi+indexOffset]
2268
        add     eax, 18h
2269
        mov     [edi+nodeRealSize], eax
2270
        add     edi, [edi+indexOffset]
2271
        mov     ecx, 6
2272
        xor     eax, eax
2273
        mov     [ebp+NTFS.indexPointer], edi
2274
        push    edi
2275
        rep stosd
2276
        pop     edi
2277
        mov     eax, [ebp+NTFS.newRecord]
2278
        mov     byte [edi+indexAllocatedSize], 18h
2279
        mov     byte [edi+indexFlags], 3
2280
        mov     [edi+16], eax
2281
        mov     [esi+recordVCN], eax
2282
        mov     eax, [ebp+NTFS.LastRead]
2283
        mov     [ebp+NTFS.nodeLastRead], eax
2284
        push    [ebp+NTFS.cur_size]
2285
        mov     [ebp+NTFS.cur_size], 0
2286
        call    ntfs_read_attr.continue
2287
        pop     [ebp+NTFS.cur_size]
2288
        movi    eax, ERROR_FS_FAIL
2289
        jc      ntfsErrorPop5
2290
        pop     eax edi
6411 pathoswith 2291
@@:         ; move index to the branch node
6414 pathoswith 2292
        push    edi eax
2293
        call    .ntfsNodeAlloc
2294
        jc      ntfsErrorPop5
2295
        mov     eax, [esp]
2296
        mov     esi, [ebp+NTFS.secondIndexBuffer]
6411 pathoswith 2297
        add     esi, recordNode
2298
        mov     ecx, [esi+nodeRealSize]
2299
        add     eax, ecx
2300
        cmp     [esi+nodeAllocatedSize], eax
6414 pathoswith 2301
        jc      .growBranch
6411 pathoswith 2302
        mov     [esi+nodeRealSize], eax
2303
        lea     edi, [esi+eax-4]
2304
        add     esi, ecx
2305
        mov     ecx, esi
2306
        sub     ecx, [ebp+NTFS.indexPointer]
2307
        shr     ecx, 2
2308
        sub     esi, 4
2309
        std
2310
        rep movsd   ; make space
2311
        mov     [edi], ecx
6414 pathoswith 2312
        pop     ecx
2313
        sub     ecx, 8
2314
        shr     ecx, 2
6411 pathoswith 2315
        mov     edi, esi
2316
        add     edi, 4
2317
        mov     esi, [esp]
2318
        add     word [esi+indexAllocatedSize], 8
2319
        mov     byte [esi+indexFlags], 1
2320
        cld
2321
        rep movsd   ; insert index
2322
        mov     eax, [ebp+NTFS.newRecord]
2323
        stosd
2324
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2325
        mov     edx, [ebp+NTFS.nodeLastRead]
2326
        push    esi
2327
        call    writeRecord
2328
        pop     esi
2329
.splitNode:
6340 pathoswith 2330
        mov     edi, [ebp+NTFS.cur_index_buf]
2331
        mov     eax, edi
2332
        add     eax, recordNode
2333
        add     eax, [edi+recordNode+nodeRealSize]
2334
        sub     eax, esi
2335
        push    eax
2336
        mov     ecx, [edi+recordNode+indexOffset]
2337
        add     eax, ecx
2338
        add     ecx, recordNode
2339
        shr     ecx, 2
2340
        push    esi
2341
        mov     esi, edi
2342
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2343
        rep movsd
2344
        pop     esi
2345
        pop     ecx
2346
        shr     ecx, 2
2347
        rep movsd
2348
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2349
        mov     [edi+recordNode+nodeRealSize], eax
2350
        pop     edi
2351
        mov     cl, 4
2352
        xor     eax, eax
2353
        mov     esi, edi
2354
        rep stosd
2355
        mov     byte [esi+indexAllocatedSize], 16
2356
        mov     byte [esi+indexFlags], 2
2357
        mov     esi, [ebp+NTFS.cur_index_buf]
2358
        mov     eax, [ebp+NTFS.newRecord]
2359
        mov     [esi+recordVCN], eax
2360
        add     esi, recordNode
2361
        sub     edi, esi
2362
        mov     [esi+nodeRealSize], edi
6408 pathoswith 2363
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2364
        mov     edx, [ebp+NTFS.LastRead]
6340 pathoswith 2365
        call    writeRecord
6407 pathoswith 2366
        jmp     .refresh
6340 pathoswith 2367
 
6292 pathoswith 2368
.common:
6273 pathoswith 2369
        add     edi, edx
2370
        sub     edi, 4
5954 pathoswith 2371
        mov     esi, edi
2372
        sub     esi, [esp]
2373
        mov     ecx, esi
6292 pathoswith 2374
        sub     ecx, eax    ; eax = pointer in the record
5954 pathoswith 2375
        shr     ecx, 2
2376
        inc     ecx
2377
        std
2378
        rep movsd           ; move forward, make space
2379
        mov     ecx, [esp]
2380
        shr     ecx, 2
2381
        xor     eax, eax
2382
        rep stosd
2383
        cld
2384
        add     edi, 4
6420 pathoswith 2385
        call    ntfsGetTime
2386
        mov     [edi+fileCreated], eax
2387
        mov     [edi+fileCreated+4], edx
2388
        mov     [edi+fileModified], eax
2389
        mov     [edi+fileModified+4], edx
2390
        mov     [edi+recordModified], eax
2391
        mov     [edi+recordModified+4], edx
2392
        mov     [edi+fileAccessed], eax
2393
        mov     [edi+fileAccessed+4], edx
6151 pathoswith 2394
        pop     ecx
5954 pathoswith 2395
        pop     esi
6151 pathoswith 2396
        mov     [edi+indexAllocatedSize], cx    ; fill index with data
5954 pathoswith 2397
        mov     eax, [esp]
6080 pathoswith 2398
        shl     eax, 1
2399
        add     eax, 42h
5954 pathoswith 2400
        mov     [edi+indexRawSize], ax
6418 pathoswith 2401
        mov     eax, [ebp+NTFS.cur_iRecord]
5954 pathoswith 2402
        mov     [edi+directoryRecordReference], eax
2403
        mov     eax, [ebp+NTFS.frs_buffer]
2404
        mov     eax, [eax+reuseCounter]
2405
        mov     [edi+directoryReferenceReuse], ax
6292 pathoswith 2406
        mov     eax, [ebp+NTFS.frs_size]
2407
        shr     eax, 8
6151 pathoswith 2408
        add     ecx, 30h+48h+8+18h+8
2409
        add     ecx, eax
6292 pathoswith 2410
        mov     eax, [ebp+NTFS.fileRealSize]
2411
        add     ecx, eax
5954 pathoswith 2412
        mov     [edi+fileRealSize], eax
6151 pathoswith 2413
        cmp     [ebp+NTFS.frs_size], ecx
2414
        jc      @f
2415
        xor     eax, eax
2416
@@:
5954 pathoswith 2417
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2418
        shl     ecx, 9
2419
        add     eax, ecx
2420
        dec     eax
2421
        xor     edx, edx
2422
        div     ecx
2423
        mov     [ebp+NTFS.fileDataSize], eax
2424
        mul     ecx
2425
        mov     [edi+fileAllocatedSize], eax
2426
        pop     ecx
6405 pathoswith 2427
        mov     [ebp+NTFS.indexPointer], edi
5954 pathoswith 2428
        mov     [edi+fileNameLength], cl
6297 pathoswith 2429
        add     edi, fileName
5954 pathoswith 2430
@@:         ; record filename
6471 pathoswith 2431
        call    utf8to16
5954 pathoswith 2432
        stosw
6471 pathoswith 2433
        loop    @b
6273 pathoswith 2434
        mov     eax, [ebp+NTFS.LastRead]
5954 pathoswith 2435
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 2436
        cmp     [ebp+NTFS.bFolder], 0
5954 pathoswith 2437
        jz      @f
6405 pathoswith 2438
        mov     edi, [ebp+NTFS.indexPointer]
6080 pathoswith 2439
        bts     dword [edi+fileFlags], 28
5954 pathoswith 2440
        jmp     .mftBitmap
2441
 
2442
@@: ; 3. File data
6151 pathoswith 2443
        cmp     [ebp+NTFS.fileDataSize], 0
5954 pathoswith 2444
        jz      .mftBitmap
6080 pathoswith 2445
        mov     edi, [ebp+NTFS.BitmapStart]
2446
        call    ntfsSpaceAlloc
2447
        jc      ntfsDiskFull
6292 pathoswith 2448
        mov     eax, [ebp+NTFS.fileDataStart]
5954 pathoswith 2449
        mul     [ebp+NTFS.sectors_per_cluster]
2450
        mov     ecx, [ebp+NTFS.fileRealSize]
2451
        add     ecx, 511
2452
        shr     ecx, 9
6292 pathoswith 2453
        mov     ebx, [ebp+NTFS.fileDataBuffer]
5954 pathoswith 2454
        call    fs_write64_app
2455
        test    eax, eax
6019 pathoswith 2456
        jnz     ntfsDevice
5954 pathoswith 2457
    ; 4. MFT record
2458
.mftBitmap: ; search for free record
2459
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2460
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2461
        mov     al, -1
2462
        add     edi, 3
2463
        sub     ecx, 3
2464
        repz scasb
2465
        dec     edi
2466
        movzx   eax, byte [edi]
2467
        not     al
2468
        bsf     ecx, eax
6107 pathoswith 2469
        jz      .extendBitmapMFT    ; no free records
6019 pathoswith 2470
        bts     [edi], ecx
2471
; get record location
5954 pathoswith 2472
        sub     edi, [ebp+NTFS.mftBitmapBuffer]
2473
        shl     edi, 3
2474
        add     edi, ecx
6340 pathoswith 2475
        mov     [ebp+NTFS.newRecord], edi
5954 pathoswith 2476
        mov     eax, [ebp+NTFS.frs_size]
2477
        shr     eax, 9
2478
        mul     edi
6273 pathoswith 2479
        mov     [ebp+NTFS.cur_iRecord], 0
2480
        mov     [ebp+NTFS.cur_attr], 0x80
2481
        mov     [ebp+NTFS.cur_offs], eax
6405 pathoswith 2482
        push    eax
2483
        mov     [ebp+NTFS.cur_size], 0
5954 pathoswith 2484
        mov     eax, [ebp+NTFS.frs_buffer]
6273 pathoswith 2485
        mov     [ebp+NTFS.cur_buf], eax
5954 pathoswith 2486
        call    ntfs_read_attr
6405 pathoswith 2487
        pop     eax
2488
        jc      ntfsFail
2489
        cmp     eax, [ebp+NTFS.mftSize]
2490
        jnc     .extendMFT
6107 pathoswith 2491
        jmp     .mftRecord
2492
 
2493
.extendBitmapMFT:
2494
        mov     eax, [ebp+NTFS.sectors_per_cluster]
6405 pathoswith 2495
        mov     [ebp+NTFS.cur_offs], eax
6107 pathoswith 2496
        shl     eax, 9
2497
        cmp     [ebp+NTFS.mftBitmapSize], eax
2498
        jnc     ntfsUnsupported
6273 pathoswith 2499
        mov     [ebp+NTFS.cur_iRecord], 0
2500
        mov     [ebp+NTFS.cur_attr], 0xB0
2501
        mov     [ebp+NTFS.cur_size], 0
6107 pathoswith 2502
        call    ntfs_read_attr
2503
        jc      ntfsFail
5954 pathoswith 2504
        mov     eax, [ebp+NTFS.mft_cluster]
2505
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 2506
        cmp     eax, [ebp+NTFS.LastRead]
6019 pathoswith 2507
        jnz     ntfsUnsupported     ; auxiliary record
6107 pathoswith 2508
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2509
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2510
        add     edi, ecx
2511
        mov     eax, ecx
6273 pathoswith 2512
        mov     edx, [ebp+NTFS.attr_offs]
6107 pathoswith 2513
        add     ecx, 8
2514
        mov     [edx+attributeRealSize], ecx
2515
        mov     [edx+initialDataSize], ecx
2516
        shl     eax, 3
6340 pathoswith 2517
        mov     [ebp+NTFS.newRecord], eax
6107 pathoswith 2518
        mov     dword [edi], 1
2519
        mov     dword [edi+4], 0
6273 pathoswith 2520
        mov     [ebp+NTFS.cur_attr], 0x80
6405 pathoswith 2521
        mov     [ebp+NTFS.cur_offs], 0
6107 pathoswith 2522
        call    ntfs_read_attr.newAttribute
2523
        jc      ntfsFail
2524
        mov     [ebp+NTFS.mftBitmapSize], ecx
2525
.extendMFT:
2526
        mov     eax, [ebp+NTFS.mft_cluster]
5954 pathoswith 2527
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 2528
        cmp     eax, [ebp+NTFS.LastRead]
6107 pathoswith 2529
        jnz     ntfsUnsupported     ; auxiliary record
6273 pathoswith 2530
        mov     ecx, [ebp+NTFS.attr_offs]
6107 pathoswith 2531
        mov     eax, [ecx+attributeRealSize]
2532
        mov     edx, [ecx+attributeRealSize+4]
2533
        xor     ax, ax
2534
        add     eax, 10000h
2535
        adc     edx, 0
2536
        push    [ebp+NTFS.fileDataStart]
2537
        push    [ebp+NTFS.fileDataSize]
2538
        call    resizeAttribute
2539
        jc      ntfsErrorPop2
6408 pathoswith 2540
        mov     ebx, [ebp+NTFS.frs_buffer]
2541
        mov     edx, [ebp+NTFS.LastRead]
5954 pathoswith 2542
        call    writeRecord     ; $MFT
2543
        mov     eax, [ebp+NTFS.mftmirr_cluster]
2544
        mul     [ebp+NTFS.sectors_per_cluster]
6408 pathoswith 2545
        mov     ecx, [ebp+NTFS.frs_size]
2546
        shr     ecx, 9
5954 pathoswith 2547
        call    fs_write64_sys  ; $MFTMirr
6405 pathoswith 2548
; update $MFT retrieval information
2549
        mov     edi, [ebp+NTFS.mft_retrieval_end]
2550
        mov     eax, [edi-4]
2551
        add     eax, [edi-8]
2552
        mov     edx, [ebp+NTFS.fileDataSize]
2553
        cmp     eax, [ebp+NTFS.fileDataStart]
2554
        jnz     .newFragment
2555
        add     [edi-8], edx
2556
        jmp     @f
2557
.newFragment:
2558
        lea     eax, [ebp+NTFS.attrlist_buf]
2559
        cmp     eax, edi
2560
        jz      @f
2561
        mov     [edi], edx
2562
        mov     eax, [ebp+NTFS.fileDataStart]
2563
        mov     [edi+4], eax
2564
        add     [ebp+NTFS.mft_retrieval_end], 8
2565
@@:
2566
        mov     eax, [ebp+NTFS.fileDataSize]
2567
        mul     [ebp+NTFS.sectors_per_cluster]
2568
        add     [ebp+NTFS.mftSize], eax
6107 pathoswith 2569
        call    ntfsSpaceClean
2570
        pop     [ebp+NTFS.fileDataSize]
2571
        pop     [ebp+NTFS.fileDataStart]
5954 pathoswith 2572
.mftRecord:
6151 pathoswith 2573
        mov     ecx, [ebp+NTFS.frs_size]
2574
        shr     ecx, 2
5954 pathoswith 2575
        mov     edi, [ebp+NTFS.frs_buffer]
2576
        xor     eax, eax
2577
        rep stosd
6418 pathoswith 2578
        mov     esi, [ebp+NTFS.indexPointer]
2579
        mov     eax, [ebp+NTFS.newRecord]
2580
        mov     [esi+fileRecordReference], eax
2581
        rdtsc
2582
        mov     [esi+fileReferenceReuse], ax
5954 pathoswith 2583
        mov     edi, [ebp+NTFS.frs_buffer]
6019 pathoswith 2584
; record header
6418 pathoswith 2585
        mov     [edi+reuseCounter], ax
6292 pathoswith 2586
        mov     [edi+2ah], ax
6151 pathoswith 2587
        mov     eax, [ebp+NTFS.frs_size]
2588
        mov     [edi+recordAllocatedSize], eax
2589
        shr     eax, 9
2590
        inc     eax
2591
        mov     [edi+updateSequenceSize], al
6292 pathoswith 2592
        shl     eax, 1
2593
        add     eax, 2ah+7
2594
        and     eax, not 7
5954 pathoswith 2595
        mov     dword[edi], 'FILE'
2596
        mov     byte [edi+updateSequenceOffset], 2ah
2597
        mov     byte [edi+hardLinkCounter], 1
2598
        mov     byte [edi+newAttributeID], 3
6292 pathoswith 2599
        mov     [edi+attributeOffset], al
2600
        add     edi, eax
6019 pathoswith 2601
; $StandardInformation
5954 pathoswith 2602
        mov     byte [edi+attributeType], 10h
2603
        mov     byte [edi+sizeWithHeader], 48h
2604
        mov     byte [edi+sizeWithoutHeader], 30h
2605
        mov     byte [edi+attributeOffset], 18h
6420 pathoswith 2606
        mov     cl, 8
2607
        add     esi, fileCreated
2608
        add     edi, 18h
2609
        rep movsd
2610
        add     edi, 16
2611
        mov     esi, [ebp+NTFS.indexPointer]
6019 pathoswith 2612
; $FileName
5954 pathoswith 2613
        mov     byte [edi+attributeType], 30h
2614
        mov     byte [edi+attributeID], 1
6151 pathoswith 2615
        mov     byte [edi+attributeOffset], 18h
2616
        mov     byte [edi+indexedFlag], 1
5954 pathoswith 2617
        mov     cx, [esi+indexRawSize]
2618
        mov     [edi+sizeWithoutHeader], ecx
2619
        mov     cx, [esi+indexAllocatedSize]
2620
        add     ecx, 8
2621
        mov     [edi+sizeWithHeader], ecx
2622
        add     edi, 18h
2623
        add     esi, 16
2624
        sub     ecx, 18h
2625
        shr     ecx, 2
2626
        rep movsd
6080 pathoswith 2627
        mov     byte [edi+sizeWithHeader], 50h
2628
        mov     byte [edi+attributeID], 2
6273 pathoswith 2629
        cmp     [ebp+NTFS.bFolder], 1
6151 pathoswith 2630
        jz      .indexRoot
6019 pathoswith 2631
; $Data
5954 pathoswith 2632
        mov     byte [edi+attributeType], 80h
6151 pathoswith 2633
        mov     eax, [ebp+NTFS.fileDataSize]
2634
        test    eax, eax
2635
        jz      .resident
6405 pathoswith 2636
        mov     esi, [ebp+NTFS.indexPointer]
6080 pathoswith 2637
        dec     eax
2638
        mov     [edi+lastVCN], eax
5954 pathoswith 2639
        mov     byte [edi+nonResidentFlag], 1
2640
        mov     byte [edi+dataRunsOffset], 40h
2641
        mov     eax, [esi+fileAllocatedSize]
2642
        mov     [edi+attributeAllocatedSize], eax
2643
        mov     eax, [esi+fileRealSize]
2644
        mov     [edi+attributeRealSize], eax
2645
        mov     [edi+initialDataSize], eax
6151 pathoswith 2646
        push    edi
6080 pathoswith 2647
        mov     esi, edi
2648
        add     edi, 40h
2649
        call    createMcbEntry
6151 pathoswith 2650
        inc     edi
2651
        jmp     @f
5954 pathoswith 2652
 
6151 pathoswith 2653
.resident:
2654
        mov     ecx, [ebp+NTFS.fileRealSize]
2655
        mov     [edi+sizeWithoutHeader], ecx
5954 pathoswith 2656
        mov     byte [edi+attributeOffset], 18h
6151 pathoswith 2657
        push    edi
6292 pathoswith 2658
        mov     esi, [ebp+NTFS.fileDataBuffer]
6151 pathoswith 2659
        add     edi, 18h
2660
        rep movsb
2661
@@:
2662
        mov     eax, edi
2663
        pop     edi
2664
        sub     eax, edi
2665
        add     eax, 7
2666
        and     eax, not 7
2667
        mov     [edi+sizeWithHeader], eax
2668
        add     edi, eax
5954 pathoswith 2669
        mov     al, 1
6292 pathoswith 2670
        jmp     .end
5954 pathoswith 2671
 
6151 pathoswith 2672
.indexRoot:
5954 pathoswith 2673
        mov     byte [edi+attributeType], 90h
2674
        mov     byte [edi+nameLength], 4
2675
        mov     byte [edi+nameOffset], 18h
2676
        mov     byte [edi+sizeWithoutHeader], 30h
2677
        mov     byte [edi+attributeOffset], 20h
2678
        mov     dword[edi+18h], 490024h     ; unicode $I30
2679
        mov     dword[edi+18h+4], 300033h
6273 pathoswith 2680
        mov     byte [edi+20h+indexedAttributesType], 30h
6019 pathoswith 2681
        mov     byte [edi+20h+collationRule], 1
5954 pathoswith 2682
        mov     eax, [ebp+NTFS.sectors_per_cluster]
6292 pathoswith 2683
        mov     dl, 1
2684
        shl     eax, 8
2685
@@:
2686
        shl     eax, 1
2687
        shl     edx, 1
2688
        cmp     eax, [ebp+NTFS.frs_size]
2689
        jc      @b
2690
        shr     edx, 1
6019 pathoswith 2691
        mov     [edi+20h+indexRecordSize], eax
6292 pathoswith 2692
        mov     [edi+20h+indexRecordSizeClus], dl
6019 pathoswith 2693
        mov     byte [edi+30h+indexOffset], 16
2694
        mov     byte [edi+30h+nodeRealSize], 32
2695
        mov     byte [edi+30h+nodeAllocatedSize], 32
2696
        mov     byte [edi+40h+indexAllocatedSize], 16
2697
        mov     byte [edi+40h+indexFlags], 2
6151 pathoswith 2698
        add     edi, 50h
5954 pathoswith 2699
        mov     al, 3
6292 pathoswith 2700
.end:
6408 pathoswith 2701
        mov     ebx, [ebp+NTFS.frs_buffer]
6151 pathoswith 2702
        mov     dword [edi], -1
2703
        mov     dword [edi+4], 0
2704
        add     edi, 8
6408 pathoswith 2705
        sub     edi, ebx
2706
        mov     [ebx+recordFlags], al
2707
        mov     [ebx+recordRealSize], edi
2708
        mov     edx, [ebp+NTFS.LastRead]
5954 pathoswith 2709
        call    writeRecord
6019 pathoswith 2710
; write MFT bitmap
6340 pathoswith 2711
        mov     eax, [ebp+NTFS.newRecord]
5954 pathoswith 2712
        shr     eax, 3+9
2713
        mov     ebx, eax
2714
        shl     ebx, 9
2715
        add     eax, [ebp+NTFS.mftBitmapLocation]
2716
        add     ebx, [ebp+NTFS.mftBitmapBuffer]
2717
        mov     ecx, 1
2718
        xor     edx, edx
2719
        call    fs_write64_sys
6292 pathoswith 2720
; 5. Write directory node
6408 pathoswith 2721
        mov     ebx, [ebp+NTFS.cur_index_buf]
2722
        mov     edx, [ebp+NTFS.nodeLastRead]
5954 pathoswith 2723
        call    writeRecord
6019 pathoswith 2724
        mov     ebx, [ebp+NTFS.fileRealSize]
2725
ntfsDone:
5954 pathoswith 2726
        mov     esi, [ebp+PARTITION.Disk]
2727
        call    disk_sync
2728
        call    ntfs_unlock
6019 pathoswith 2729
        xor     eax, eax
5954 pathoswith 2730
        ret
2731
 
2732
writeRecord:
6080 pathoswith 2733
; make updateSequence and write to disk
5954 pathoswith 2734
;   in:
6408 pathoswith 2735
; ebx -> record
2736
; edx = partition sector
2737
        mov     esi, ebx
2738
        mov     edi, ebx
5954 pathoswith 2739
        movzx   ecx, word [esi+updateSequenceOffset]
2740
        add     edi, ecx
2741
        mov     ax, [edi]
6080 pathoswith 2742
        inc     ax
2743
        stosw
5954 pathoswith 2744
        mov     cx, [esi+updateSequenceSize]
2745
        dec     ecx
2746
        push    ecx
2747
@@:
2748
        add     esi, 510
2749
        movsw
2750
        mov     [esi-2], ax
6471 pathoswith 2751
        loop    @b
6408 pathoswith 2752
        mov     eax, edx
2753
        xor     edx, edx
5954 pathoswith 2754
        pop     ecx
2755
        jmp     fs_write64_sys
2756
 
6080 pathoswith 2757
createMcbEntry:
2758
;   in:
2759
; [ebp+NTFS.fileDataStart] = position value
2760
; [ebp+NTFS.fileDataSize] = size value
2761
; edi -> destination
2762
; esi -> attribute header
2763
        mov     eax, [ebp+NTFS.fileDataStart]
2764
        xor     edx, edx
2765
        shl     eax, 1
2766
        jnc     @f
2767
        not     eax
2768
@@:
2769
        inc     edx
2770
        shr     eax, 8
2771
        jnz     @b
2772
        mov     eax, [ebp+NTFS.fileDataSize]
2773
        shl     eax, 1
2774
        xor     ecx, ecx
2775
@@:
2776
        inc     ecx
2777
        shr     eax, 8
2778
        jnz     @b
2779
        lea     eax, [edi+edx+1]
2780
        add     eax, ecx
2781
        sub     eax, esi
6151 pathoswith 2782
        sub     eax, [esi+sizeWithHeader]
6080 pathoswith 2783
        jc      @f
2784
        add     word [esi+sizeWithHeader], 8    ; extend attribute
2785
        mov     esi, [ebp+NTFS.frs_buffer]
2786
        mov     eax, [esi+recordRealSize]
2787
        add     eax, 8
2788
        cmp     [esi+recordAllocatedSize], eax
2789
        jc      .end    ; no space in the record
2790
        mov     [esi+recordRealSize], eax
2791
        push    ecx edi
2792
        add     esi, eax
2793
        mov     ecx, esi
2794
        sub     ecx, edi
2795
        sub     ecx, 8
2796
        shr     ecx, 2
2797
        mov     edi, esi
2798
        sub     edi, 4
2799
        sub     esi, 12
2800
        std
2801
        rep movsd
2802
        cld
2803
        pop     edi ecx
2804
@@:
2805
        mov     eax, edx
2806
        shl     eax, 4
2807
        add     eax, ecx
2808
        stosb
2809
        lea     esi, [ebp+NTFS.fileDataSize]
2810
        rep movsb
2811
        lea     esi, [ebp+NTFS.fileDataStart]
2812
        mov     ecx, edx
2813
        rep movsb
6151 pathoswith 2814
        mov     [edi], cl
6080 pathoswith 2815
.end:
2816
        ret
2817
 
2818
resizeAttribute:
2819
;   in:
2820
; [ebp+NTFS.frs_buffer] -> file record
6273 pathoswith 2821
; [ebp+NTFS.attr_offs] -> attribute
6080 pathoswith 2822
; edx:eax = new size
2823
;   out:
6107 pathoswith 2824
; [ebp+NTFS.fileDataSize] = clusters added (positive)
2825
; [ebp+NTFS.fileDataStart] = added block
6080 pathoswith 2826
; CF=1 -> eax = error code
6273 pathoswith 2827
        mov     esi, [ebp+NTFS.attr_offs]
2828
        mov     dword [ebp+NTFS.attr_size], eax
2829
        mov     dword [ebp+NTFS.attr_size+4], edx
6151 pathoswith 2830
        cmp     byte [esi+nonResidentFlag], 0
2831
        jz      .resident
6080 pathoswith 2832
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2833
        shl     ecx, 9
2834
        mov     [esi+attributeRealSize], eax
2835
        mov     [esi+attributeRealSize+4], edx
2836
        mov     [esi+initialDataSize], eax
2837
        mov     [esi+initialDataSize+4], edx
2838
        sub     eax, 1
2839
        sbb     edx, 0
6151 pathoswith 2840
        jc      .makeResident
6080 pathoswith 2841
        div     ecx
2842
        mov     edi, eax
2843
        inc     eax
2844
        mul     ecx
2845
        mov     [esi+attributeAllocatedSize], eax
2846
        mov     [esi+attributeAllocatedSize+4], edx
2847
        mov     ecx, [esi+lastVCN]
2848
        mov     [esi+lastVCN], edi
2849
        movzx   eax, byte [esi+dataRunsOffset]
2850
        sub     edi, ecx
6107 pathoswith 2851
        mov     [ebp+NTFS.fileDataSize], edi
6080 pathoswith 2852
        jz      .done
2853
        jc      .shrinkAttribute
2854
; extend attribute
2855
        xor     edi, edi
2856
        add     esi, eax
2857
        push    edi edi edi edi
2858
@@:
2859
        mov     edx, eax
2860
        mov     eax, esi
2861
        add     edi, [esp+8]
2862
        call    ntfs_decode_mcb_entry
2863
        jc      @b
2864
        mov     [esp+4], edx
2865
        mov     [esp+12], edi
2866
        add     edi, [esp]
2867
        push    edi
2868
        shr     edi, 5
2869
        shl     edi, 2
2870
        push    eax
6820 pathoswith 2871
        cmp     edi, [ebp+NTFS.BitmapStart]
2872
        jnc     @f
6273 pathoswith 2873
        cmp     [ebp+NTFS.cur_iRecord], 0
6107 pathoswith 2874
        jz      @f
6820 pathoswith 2875
        mov     edi, [ebp+NTFS.BitmapStart]
6107 pathoswith 2876
@@:
6080 pathoswith 2877
        call    ntfsSpaceAlloc
2878
        jc      .err1
6292 pathoswith 2879
        mov     eax, [ebp+NTFS.fileDataStart]
6080 pathoswith 2880
        pop     edi
2881
        pop     edx
2882
        cmp     edx, eax
2883
        jnz     .newEntry
2884
        pop     edx
2885
        pop     edi
2886
        pop     [ebp+NTFS.fileDataStart]
2887
        mov     [esp], eax
2888
        push    [ebp+NTFS.fileDataSize]
2889
        add     [ebp+NTFS.fileDataSize], edx
2890
        jmp     @f
2891
 
2892
.newEntry:
2893
        add     esp, 12
2894
        pop     edx
2895
        push    eax
2896
        push    [ebp+NTFS.fileDataSize]
2897
        sub     eax, edx
2898
        mov     [ebp+NTFS.fileDataStart], eax
2899
@@:
6273 pathoswith 2900
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 2901
        call    createMcbEntry
6292 pathoswith 2902
        pop     [ebp+NTFS.fileDataSize]
2903
        pop     [ebp+NTFS.fileDataStart]
2904
        movi    eax, ERROR_UNSUPPORTED_FS
6151 pathoswith 2905
.done:
2906
        ret
2907
 
6080 pathoswith 2908
.err1:
2909
        add     esp, 24
2910
        stc
6292 pathoswith 2911
.err2:
6151 pathoswith 2912
        movi    eax, ERROR_DISK_FULL
6080 pathoswith 2913
        ret
2914
 
6292 pathoswith 2915
.err3:
2916
        movi    eax, ERROR_FS_FAIL
2917
        add     esp, 20
2918
        stc
6080 pathoswith 2919
        ret
2920
 
2921
.shrinkAttribute:
2922
        add     ecx, edi
2923
        inc     ecx
2924
        add     esi, eax
2925
        xor     edi, edi
2926
        sub     esp, 20
2927
@@:
2928
        mov     [esp+16], esi
2929
        call    ntfs_decode_mcb_entry
2930
        jnc     .err3
2931
        add     edi, [esp+8]
2932
        sub     ecx, [esp]
2933
        jnc     @b
2934
        mov     ebx, ecx
2935
        add     ecx, [esp]
2936
        mov     eax, [esp+8]
2937
        mov     [ebp+NTFS.fileDataSize], ecx
2938
        mov     [ebp+NTFS.fileDataStart], eax
2939
        push    edi
2940
        add     edi, ecx
2941
        neg     ebx
2942
        call    ntfsSpaceFree
2943
        pop     edi
2944
        jc      .end
2945
@@:
2946
        call    ntfs_decode_mcb_entry
2947
        jnc     .end
2948
        cmp     dword[esp+8], 0
2949
        jz      @b
2950
        add     edi, [esp+8]
2951
        mov     ebx, [esp]
2952
        call    ntfsSpaceFree
2953
        jnc     @b
2954
.end:
2955
        add     esp, 16
2956
        pop     edi
2957
        cmp     [ebp+NTFS.fileDataSize], 0
2958
        jz      @f
6273 pathoswith 2959
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 2960
        call    createMcbEntry
6107 pathoswith 2961
        mov     [ebp+NTFS.fileDataSize], 0
6080 pathoswith 2962
@@:
2963
        ret
2964
 
6151 pathoswith 2965
.resident:
2966
        test    edx, edx
2967
        jnz     .nonResident
2968
        cmp     eax, 8000h
2969
        jnc     .nonResident
2970
        add     ax, [esi+attributeOffset]
2971
        sub     eax, [esi+sizeWithHeader]
2972
        jc      @f
2973
        mov     edi, [ebp+NTFS.frs_buffer]
2974
        mov     ecx, eax
2975
        add     ecx, [edi+recordRealSize]
2976
        cmp     [edi+recordAllocatedSize], ecx
2977
        jc      .nonResident
2978
        add     eax, 7
2979
        and     eax, not 7
2980
        add     [edi+recordRealSize], eax
2981
        add     edi, [edi+recordRealSize]
2982
        add     [esi+sizeWithHeader], eax
2983
        add     esi, [esi+sizeWithHeader]
2984
        mov     ecx, edi
2985
        sub     ecx, esi
2986
        shr     ecx, 2
2987
        sub     edi, 4
2988
        mov     esi, edi
2989
        sub     esi, eax
2990
        std
2991
        rep movsd
2992
        mov     ecx, eax
2993
        shr     ecx, 2
2994
        xor     eax, eax
2995
        rep stosd
2996
        cld
6273 pathoswith 2997
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 2998
@@:
6273 pathoswith 2999
        mov     eax, dword [ebp+NTFS.attr_size]
6151 pathoswith 3000
        mov     [esi+sizeWithoutHeader], eax
3001
        mov     [ebp+NTFS.fileDataSize], 0
3002
        clc
3003
        ret
3004
 
3005
.nonResident:   ; convert resident to non-resident
6273 pathoswith 3006
        mov     eax, dword [ebp+NTFS.attr_size]
6151 pathoswith 3007
        sub     eax, 1
3008
        sbb     edx, 0
3009
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3010
        shl     ecx, 9
3011
        div     ecx
3012
        inc     eax
3013
        mov     [ebp+NTFS.fileDataSize], eax
3014
        mov     edi, [ebp+NTFS.BitmapStart]
3015
        push    ecx
3016
        call    ntfsSpaceAlloc
3017
        pop     ecx
6292 pathoswith 3018
        jc      .err2
6273 pathoswith 3019
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 3020
        xor     eax, eax
3021
        xor     edx, edx
3022
@@:
3023
        add     eax, ecx
3024
        inc     edx
3025
        cmp     eax, [esi+sizeWithoutHeader]
3026
        jc      @b
3027
        push    edx
3028
        push    eax
3029
        stdcall kernel_alloc, eax
3030
        mov     ecx, [esp]
3031
        shr     ecx, 2
3032
        mov     edi, eax
3033
        mov     ebx, eax
3034
        xor     eax, eax
3035
        rep stosd
3036
        mov     al, [esi+attributeOffset]
3037
        mov     ecx, [esi+sizeWithoutHeader]
3038
        add     esi, eax
3039
        mov     edi, ebx
3040
        rep movsb
3041
        mov     eax, [ebp+NTFS.fileDataStart]
3042
        mul     [ebp+NTFS.sectors_per_cluster]
3043
        pop     ecx
3044
        shr     ecx, 9
3045
        call    fs_write64_app
6292 pathoswith 3046
        stdcall kernel_free, ebx
6273 pathoswith 3047
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 3048
        add     esi, [esi+sizeWithHeader]
3049
        mov     ecx, [ebp+NTFS.frs_buffer]
3050
        add     ecx, [ecx+recordRealSize]
3051
        sub     ecx, esi
3052
        shr     ecx, 2
6273 pathoswith 3053
        lea     edi, [ebp+NTFS.bitmap_buf]
6151 pathoswith 3054
        push    ecx
3055
        rep movsd
6273 pathoswith 3056
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 3057
        add     edi, 16
3058
        mov     cl, 6
3059
        xor     eax, eax
3060
        rep stosd
6273 pathoswith 3061
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 3062
        mov     eax, [ebp+NTFS.fileDataSize]
3063
        dec     eax
3064
        mov     [edi+lastVCN], eax
3065
        inc     eax
3066
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3067
        shl     ecx, 9
3068
        mul     ecx
3069
        mov     byte [edi+sizeWithHeader], 50h
3070
        mov     byte [edi+nonResidentFlag], 1
3071
        mov     byte [edi+dataRunsOffset], 40h
3072
        mov     [edi+attributeAllocatedSize], eax
3073
        mov     [edi+attributeAllocatedSize+4], edx
6273 pathoswith 3074
        mov     eax, dword [ebp+NTFS.attr_size]
3075
        mov     edx, dword [ebp+NTFS.attr_size+4]
6151 pathoswith 3076
        mov     [edi+attributeRealSize], eax
3077
        mov     [edi+attributeRealSize+4], edx
3078
        mov     [edi+initialDataSize], eax
3079
        mov     [edi+initialDataSize+4], edx
3080
        mov     esi, edi
3081
        add     edi, 40h
3082
        call    createMcbEntry
3083
        mov     eax, edi
6273 pathoswith 3084
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 3085
        sub     eax, edi
3086
        add     eax, 8
3087
        and     eax, not 7
3088
        mov     [edi+sizeWithHeader], eax
3089
        pop     ecx
6273 pathoswith 3090
        lea     esi, [ebp+NTFS.bitmap_buf]
6151 pathoswith 3091
        add     edi, eax
3092
        rep movsd
3093
        mov     esi, [ebp+NTFS.frs_buffer]
3094
        sub     edi, esi
3095
        mov     [esi+recordRealSize], edi
3096
        pop     edx
3097
        sub     [ebp+NTFS.fileDataSize], edx
3098
        add     [ebp+NTFS.fileDataStart], edx
6292 pathoswith 3099
        ret
6151 pathoswith 3100
 
3101
.makeResident:  ; convert non-resident to empty resident
3102
        movzx   eax, byte [esi+dataRunsOffset]
3103
        mov     byte [esi+nonResidentFlag], 0
3104
        mov     dword [esi+sizeWithoutHeader], 0
3105
        mov     dword [esi+attributeOffset], 18h
3106
        add     esi, eax
3107
        xor     edi, edi
3108
        sub     esp, 16
3109
@@:
3110
        call    ntfs_decode_mcb_entry
3111
        jnc     @f
3112
        cmp     dword[esp+8], 0
3113
        jz      @b
3114
        add     edi, [esp+8]
3115
        mov     ebx, [esp]
3116
        call    ntfsSpaceFree
3117
        jnc     @b
3118
@@:
3119
        add     esp, 16
3120
        mov     [ebp+NTFS.fileDataSize], 0
3121
        ret
3122
 
6107 pathoswith 3123
ntfsSpaceClean:
3124
; clean up to 16 Mb of disk space
3125
;   in:
3126
; [ebp+NTFS.fileDataStart] = block to clean
3127
; [ebp+NTFS.fileDataSize] = block size
3128
        mov     eax, [ebp+NTFS.fileDataSize]
3129
        test    eax, eax
3130
        jz      @f
3131
        mul     [ebp+NTFS.sectors_per_cluster]
3132
        cmp     eax, 8001h
3133
        jnc     @f
3134
        push    eax
3135
        shl     eax, 9
3136
        stdcall kernel_alloc, eax
3137
        pop     ecx
3138
        test    eax, eax
3139
        jz      @f
3140
        push    ecx
3141
        shl     ecx, 7
3142
        mov     edi, eax
3143
        mov     ebx, eax
3144
        xor     eax, eax
3145
        rep stosd
3146
        mov     eax, [ebp+NTFS.fileDataStart]
3147
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 3148
        mov     [ebp+NTFS.LastRead], eax
6107 pathoswith 3149
        pop     ecx
3150
        call    fs_write64_app
3151
        stdcall kernel_free, ebx
3152
@@:
3153
        ret
3154
 
6080 pathoswith 3155
ntfsSpaceAlloc:
6292 pathoswith 3156
; allocate disk space
6080 pathoswith 3157
;   in:
3158
; edi = offset in bitmap to start search from
3159
; [ebp+NTFS.fileDataSize] = block size in clusters
3160
;   out:
6292 pathoswith 3161
; [ebp+NTFS.fileDataStart] = allocated block starting cluster
6080 pathoswith 3162
; CF=1 -> disk full
3163
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3164
        add     edi, ecx
3165
        add     ecx, [ebp+NTFS.BitmapSize]
3166
        sub     ecx, edi
6781 pathoswith 3167
        ja      @f
3168
        push    eax
6080 pathoswith 3169
        call    bitmapBuffering
6781 pathoswith 3170
        pop     eax
6080 pathoswith 3171
        shl     ecx, 2
3172
@@:
3173
        shr     ecx, 2
6781 pathoswith 3174
        push    ecx
6080 pathoswith 3175
        mov     eax, [ebp+NTFS.fileDataSize]
3176
        shr     eax, 5
3177
        jz      .small
6292 pathoswith 3178
        mov     ebx, eax    ; bitmap dwords
6080 pathoswith 3179
.start:
3180
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3181
        add     ecx, [ebp+NTFS.BitmapSize]
3182
        sub     ecx, edi
3183
        shr     ecx, 2
3184
@@:
3185
        xor     eax, eax
3186
        repnz scasd         ; search for empty dword
3187
        jz      @f
3188
        call    bitmapBuffering
3189
        jmp     @b
3190
@@:
6292 pathoswith 3191
        cmp     ecx, ebx
6080 pathoswith 3192
        jnc     @f
3193
        call    bitmapBuffering
3194
        jmp     @b
3195
@@:
3196
        sub     edi, 4
6292 pathoswith 3197
        mov     ecx, ebx
6080 pathoswith 3198
        mov     esi, edi
3199
        xor     eax, eax
3200
        repz scasd          ; check following dwords
3201
        jnz     .start
3202
        sub     esi, 4
3203
        mov     eax, [esi]
3204
        xor     edx, edx
3205
        bsr     edx, eax
3206
        inc     edx
3207
        push    edx         ; starting bit
3208
        push    esi         ; starting dword
3209
        add     esi, 4
3210
        neg     edx
3211
        add     edx, 32
3212
        mov     eax, [ebp+NTFS.fileDataSize]
3213
        sub     eax, edx
3214
        mov     edx, eax
3215
        shr     eax, 5
3216
        shl     eax, 2
3217
        add     esi, eax
3218
        mov     eax, [esi]
3219
        bsf     ecx, eax    ; check last dword
3220
        jz      .done
3221
        and     edx, 31
3222
        cmp     ecx, edx
3223
        jnc     .done
3224
        add     esp, 8
3225
        jmp     .start
3226
 
3227
@@:
3228
        sub     edi, 4
6781 pathoswith 3229
        call    bitmapBuffering
3230
        push    ecx
3231
.small:     ; less than 32 clusters
3232
        pop     ecx
3233
        or      eax, -1
3234
        repz scasd
3235
        jecxz   @b
3236
        push    ecx
3237
        mov     eax, [edi-4]
6080 pathoswith 3238
        not     eax
3239
@@:
6781 pathoswith 3240
        bsf     ecx, eax    ; first 0
3241
        jz      .small
6080 pathoswith 3242
        not     eax
3243
        shr     eax, cl
3244
        shl     eax, cl
3245
        bsf     edx, eax    ; next 1
3246
        jz      @f
6781 pathoswith 3247
        sub     edx, ecx
6080 pathoswith 3248
        cmp     edx, [ebp+NTFS.fileDataSize]
3249
        jnc     .got        ; fits inside
6781 pathoswith 3250
        bsf     ecx, eax
6080 pathoswith 3251
        not     eax
3252
        shr     eax, cl
3253
        shl     eax, cl
3254
        jmp     @b
6781 pathoswith 3255
 
6080 pathoswith 3256
@@:         ; next dword
6781 pathoswith 3257
        mov     eax, [edi]
6080 pathoswith 3258
        bsf     edx, eax
3259
        jz      .got        ; empty
3260
        add     edx, 32
6781 pathoswith 3261
        sub     edx, ecx
6080 pathoswith 3262
        cmp     edx, [ebp+NTFS.fileDataSize]
6781 pathoswith 3263
        jc      .small
6080 pathoswith 3264
.got:
6781 pathoswith 3265
        sub     edi, 4
3266
        push    ecx         ; starting bit
6080 pathoswith 3267
        push    edi         ; starting dword
3268
.done:      ; mark space
6781 pathoswith 3269
        pop     edi ecx
6080 pathoswith 3270
        cmp     ecx, 32
3271
        jc      @f
3272
        xor     ecx, ecx
6781 pathoswith 3273
        add     edi, 4
6080 pathoswith 3274
@@:
6781 pathoswith 3275
        push    ecx edi
3276
        or      eax, -1
6080 pathoswith 3277
        shr     eax, cl
3278
        shl     eax, cl
3279
        neg     ecx
3280
        add     ecx, 32
3281
        sub     ecx, [ebp+NTFS.fileDataSize]
3282
        jc      @f
3283
        shl     eax, cl     ; fits inside dword
3284
        shr     eax, cl
3285
        or      [edi], eax
3286
        jmp     .end
3287
 
3288
@@:
3289
        or      [edi], eax
3290
        neg     ecx
3291
        push    ecx
3292
        shr     ecx, 5
3293
        add     edi, 4
6781 pathoswith 3294
        or      eax, -1
6080 pathoswith 3295
        rep stosd
3296
        pop     ecx
3297
        and     ecx, 31
3298
        shr     eax, cl
3299
        shl     eax, cl
3300
        not     eax
3301
        or      [edi], eax
3302
.end:
3303
        pop     eax
6292 pathoswith 3304
        pop     ecx
6080 pathoswith 3305
        sub     eax, [ebp+NTFS.BitmapBuffer]
3306
        shl     eax, 3
6292 pathoswith 3307
        add     eax, ecx
3308
        pop     ecx
3309
        mov     ecx, [ebp+NTFS.fileDataSize]
3310
        mov     [ebp+NTFS.fileDataStart], eax
3311
        add     ecx, eax
3312
        add     ecx, 4095
3313
        shr     ecx, 3+9
3314
        shr     eax, 3+9
3315
        sub     ecx, eax
3316
        mov     ebx, eax
3317
        shl     ebx, 9
3318
        add     eax, [ebp+NTFS.BitmapLocation]
3319
        add     ebx, [ebp+NTFS.BitmapBuffer]
3320
        xor     edx, edx
3321
        jmp     fs_write64_app
6080 pathoswith 3322
 
3323
ntfsSpaceFree:
3324
; free disk space
3325
;   in:
3326
; edi = starting cluster
3327
; ebx = size in clusters
3328
        mov     eax, edi
3329
        add     eax, ebx
3330
        shr     eax, 3
3331
        cmp     eax, [ebp+NTFS.BitmapSize]
3332
        jc      @f
3333
        add     eax, [ebp+NTFS.BitmapBuffer]
3334
        push    edi
3335
        mov     edi, eax
3336
        call    bitmapBuffering
3337
        pop     edi
3338
@@:
3339
        push    edi
3340
        mov     ecx, edi
3341
        shr     edi, 5
3342
        shl     edi, 2
3343
        add     edi, [ebp+NTFS.BitmapBuffer]
3344
        and     ecx, 31
3345
        xor     eax, eax
3346
        dec     eax
3347
        shr     eax, cl
3348
        shl     eax, cl
3349
        neg     ecx
3350
        add     ecx, 32
3351
        sub     ecx, ebx
3352
        jc      @f
3353
        shl     eax, cl     ; fits inside dword
3354
        shr     eax, cl
3355
        not     eax
3356
        and     [edi], eax
3357
        jmp     .writeBitmap
3358
 
3359
@@:
3360
        not     eax
3361
        and     [edi], eax
3362
        neg     ecx
3363
        push    ecx
3364
        shr     ecx, 5
3365
        add     edi, 4
3366
        xor     eax, eax
3367
        rep stosd
3368
        pop     ecx
3369
        and     ecx, 31
3370
        dec     eax
3371
        shr     eax, cl
3372
        shl     eax, cl
3373
        and     [edi], eax
3374
.writeBitmap:
3375
        pop     eax
3376
        mov     edi, eax
3377
        lea     ecx, [eax+ebx+4095]
3378
        shr     eax, 3+9
3379
        shr     ecx, 3+9
3380
        sub     ecx, eax
3381
        mov     ebx, eax
3382
        shl     ebx, 9
3383
        add     eax, [ebp+NTFS.BitmapLocation]
3384
        add     ebx, [ebp+NTFS.BitmapBuffer]
3385
        xor     edx, edx
3386
        jmp     fs_write64_app
3387
 
5954 pathoswith 3388
bitmapBuffering:
3389
; Extend BitmapBuffer and read next 32kb of bitmap
3390
; Warning: $Bitmap fragmentation is not foreseen
6080 pathoswith 3391
; in: edi -> position in bitmap buffer
3392
; out: ecx = number of buffered dwords left
5954 pathoswith 3393
        push    ebx
3394
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3395
        cmp     eax, [ebp+NTFS.BitmapSize]
3396
        jz      .end
3397
        stdcall alloc_pages, 8
3398
        test    eax, eax
3399
        jz      .end
3400
        add     eax, 3
3401
        mov     ebx, [ebp+NTFS.BitmapBuffer]
3402
        add     ebx, [ebp+NTFS.BitmapSize]
3403
        push    ebx
3404
        mov     ecx, 8
3405
        call    commit_pages
3406
        mov     eax, [ebp+NTFS.BitmapSize]
3407
        shr     eax, 9
3408
        add     eax, [ebp+NTFS.BitmapLocation]
3409
        pop     ebx
3410
        mov     ecx, 64
3411
        xor     edx, edx
3412
        call    fs_read64_app
3413
        test    eax, eax
3414
        jnz     .err
6781 pathoswith 3415
        mov     eax, [ebp+NTFS.BitmapSize]
3416
        add     eax, 8000h
3417
        cmp     [ebp+NTFS.BitmapTotalSize], eax
3418
        jnc     @f
5954 pathoswith 3419
        mov     eax, [ebp+NTFS.BitmapTotalSize]
6781 pathoswith 3420
@@:
5954 pathoswith 3421
        mov     [ebp+NTFS.BitmapSize], eax
6080 pathoswith 3422
        pop     ebx
3423
        mov     ecx, [ebp+NTFS.BitmapBuffer]
6781 pathoswith 3424
        add     ecx, eax
6019 pathoswith 3425
        sub     ecx, edi
6781 pathoswith 3426
        jbe     bitmapBuffering
5954 pathoswith 3427
        shr     ecx, 2
3428
        ret
3429
 
3430
.err:
3431
        mov     eax, [ebp+NTFS.BitmapBuffer]
3432
        add     eax, [ebp+NTFS.BitmapSize]
3433
        mov     ecx, 8
3434
        call    release_pages
3435
.end:
6292 pathoswith 3436
        add     esp, 12     ; ret
6080 pathoswith 3437
        stc
3438
        ret
5954 pathoswith 3439
 
2288 clevermous 3440
;----------------------------------------------------------------
5994 pathoswith 3441
ntfs_WriteFile:
3442
        call    ntfs_lock
6468 pathoswith 3443
        call    ntfs_find_lfn
6019 pathoswith 3444
        jc      ntfsNotFound
6273 pathoswith 3445
        cmp     [ebp+NTFS.cur_iRecord], 16
6019 pathoswith 3446
        jc      ntfsDenied
6420 pathoswith 3447
        test    dword [eax+fileFlags], 10000001h
3448
        jnz     ntfsDenied
6273 pathoswith 3449
        cmp     [ebp+NTFS.fragmentCount], 1
6080 pathoswith 3450
        jnz     ntfsUnsupported     ; record fragmented
6151 pathoswith 3451
; edit directory node
6080 pathoswith 3452
        mov     edi, [ebp+NTFS.cur_index_buf]
3453
        cmp     dword [edi], 'INDX'
3454
        jz      @f
3455
        mov     esi, [ebp+NTFS.frs_buffer]
3456
        mov     ecx, [esi+recordRealSize]
3457
        shr     ecx, 2
3458
        rep movsd
6273 pathoswith 3459
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 3460
        mov     cl, [esi+attributeOffset]
3461
        sub     esi, [ebp+NTFS.frs_buffer]
6151 pathoswith 3462
        add     eax, ecx
3463
        add     eax, esi
6080 pathoswith 3464
@@:
6420 pathoswith 3465
        mov     edi, eax
3466
        mov     eax, [ebx+4]
6151 pathoswith 3467
        mov     edx, [ebx+8]
6420 pathoswith 3468
        add     eax, [ebx+12]
6151 pathoswith 3469
        adc     edx, 0
6420 pathoswith 3470
        mov     [edi+fileRealSize], eax
3471
        mov     [edi+fileRealSize+4], edx
3472
        push    edx eax ebx
3473
        call    ntfsGetTime
3474
        mov     [edi+fileModified], eax
3475
        mov     [edi+fileModified+4], edx
3476
        mov     [edi+recordModified], eax
3477
        mov     [edi+recordModified+4], edx
3478
        mov     [edi+fileAccessed], eax
3479
        mov     [edi+fileAccessed+4], edx
3480
        pop     ebx ecx edx
6273 pathoswith 3481
        mov     eax, [ebp+NTFS.LastRead]
6151 pathoswith 3482
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 3483
        mov     [ebp+NTFS.cur_attr], 0x80
3484
        mov     [ebp+NTFS.cur_offs], 0
3485
        mov     [ebp+NTFS.cur_size], 0
5994 pathoswith 3486
        call    ntfs_read_attr
6080 pathoswith 3487
        jc      ntfsFail
6420 pathoswith 3488
        mov     esi, edi
3489
        mov     edi, [ebp+NTFS.frs_buffer]
3490
        cmp     word [edi+baseRecordReuse], 0
3491
        jnz     ntfsUnsupported     ; auxiliary record
3492
        mov     al, [edi+attributeOffset]
3493
        add     edi, eax
3494
        mov     al, [edi+attributeOffset]
3495
        add     edi, eax
6151 pathoswith 3496
        mov     eax, ecx
6420 pathoswith 3497
        mov     ecx, 6
3498
        add     esi, fileModified
3499
        add     edi, 8
3500
        rep movsd
6273 pathoswith 3501
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3502
        cmp     word [ecx+attributeFlags], 0
3503
        jnz     ntfsUnsupported
3504
        push    ebx
3505
        cmp     byte [ecx+nonResidentFlag], 0
3506
        jz      .resizeAttribute
5994 pathoswith 3507
        cmp     edx, [ecx+attributeRealSize+4]
6080 pathoswith 3508
        jc      .writeNode
3509
        jnz     .resizeAttribute
5994 pathoswith 3510
        cmp     [ecx+attributeRealSize], eax
6080 pathoswith 3511
        jnc     .writeNode
3512
.resizeAttribute:
3513
        call    resizeAttribute
6107 pathoswith 3514
        jc      ntfsErrorPop
6273 pathoswith 3515
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3516
        cmp     byte [ecx+nonResidentFlag], 1
3517
        jz      @f
3518
        mov     ebx, [esp]
3519
        movzx   edi, byte [ecx+attributeOffset]
3520
        add     edi, ecx
3521
        add     edi, [ebx+4]
3522
        mov     ecx, [ebx+12]
3523
        mov     esi, [ebx+16]
3524
        rep movsb
3525
@@:
6408 pathoswith 3526
        mov     ebx, [ebp+NTFS.frs_buffer]
3527
        mov     edx, [ebp+NTFS.mftLastRead]
6080 pathoswith 3528
        call    writeRecord     ; file
3529
        call    ntfs_restore_usa_frs
3530
.writeNode:
6408 pathoswith 3531
        mov     ebx, [ebp+NTFS.cur_index_buf]
3532
        mov     edx, [ebp+NTFS.nodeLastRead]
6080 pathoswith 3533
        call    writeRecord     ; directory
3534
        pop     ebx
6273 pathoswith 3535
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3536
        cmp     byte [ecx+nonResidentFlag], 0
3537
        jz      .done
3538
        mov     ecx, [ebx+12]
3539
        test    ecx, ecx
3540
        jz      .done
5994 pathoswith 3541
        mov     eax, [ebx+4]
3542
        mov     edx, [ebx+8]
3543
        mov     esi, [ebx+16]
3544
        shrd    eax, edx, 9
3545
        test    dword[ebx+4], 1FFh
3546
        jz      .aligned
6273 pathoswith 3547
        mov     [ebp+NTFS.cur_offs], eax
3548
        mov     [ebp+NTFS.cur_size], 1
3549
        lea     edi, [ebp+NTFS.bitmap_buf]
3550
        mov     [ebp+NTFS.cur_buf], edi
5994 pathoswith 3551
        call    ntfs_read_attr.continue
6019 pathoswith 3552
        jc      ntfsDevice
5994 pathoswith 3553
        mov     eax, [ebx+4]
3554
        and     eax, 1FFh
3555
        add     edi, eax
6273 pathoswith 3556
        sub     eax, [ebp+NTFS.cur_read]
5994 pathoswith 3557
        neg     eax
3558
        push    ecx
3559
        cmp     ecx, eax
3560
        jb      @f
3561
        mov     ecx, eax
3562
@@:
3563
        sub     [esp], ecx
3564
        rep movsb
3565
        push    ebx
6273 pathoswith 3566
        mov     eax, [ebp+NTFS.LastRead]
3567
        lea     ebx, [ebp+NTFS.bitmap_buf]
5994 pathoswith 3568
        mov     ecx, 1
3569
        xor     edx, edx
3570
        call    fs_write64_app
3571
        pop     ebx
3572
        pop     ecx
3573
        test    ecx, ecx
6151 pathoswith 3574
        jz      .done
5994 pathoswith 3575
        mov     eax, [ebx+4]
3576
        mov     edx, [ebx+8]
3577
        shrd    eax, edx, 9
3578
        inc     eax
3579
.aligned:
3580
        push    ecx
3581
        shr     ecx, 9
6273 pathoswith 3582
        mov     [ebp+NTFS.cur_offs], eax
3583
        mov     [ebp+NTFS.cur_size], ecx
3584
        mov     [ebp+NTFS.cur_buf], esi
5994 pathoswith 3585
        add     eax, ecx
3586
        push    eax
6273 pathoswith 3587
        mov     [ebp+NTFS.bWriteAttr], 1
5994 pathoswith 3588
        call    ntfs_read_attr.continue
6273 pathoswith 3589
        mov     [ebp+NTFS.bWriteAttr], 0
3590
        pop     [ebp+NTFS.cur_offs]
5994 pathoswith 3591
        pop     ecx
6019 pathoswith 3592
        jc      ntfsDevice
5994 pathoswith 3593
        and     ecx, 1FFh
6151 pathoswith 3594
        jz      .done
6273 pathoswith 3595
        add     esi, [ebp+NTFS.cur_read]
3596
        mov     [ebp+NTFS.cur_size], 1
3597
        lea     edi, [ebp+NTFS.bitmap_buf]
3598
        mov     [ebp+NTFS.cur_buf], edi
5994 pathoswith 3599
        call    ntfs_read_attr.continue
6019 pathoswith 3600
        jc      ntfsDevice
5994 pathoswith 3601
        rep movsb
3602
        push    ebx
6273 pathoswith 3603
        mov     eax, [ebp+NTFS.LastRead]
3604
        lea     ebx, [ebp+NTFS.bitmap_buf]
5994 pathoswith 3605
        mov     ecx, 1
3606
        xor     edx, edx
3607
        call    fs_write64_app
3608
        pop     ebx
6151 pathoswith 3609
.done:
5994 pathoswith 3610
        mov     ebx, [ebx+12]
6019 pathoswith 3611
        jmp     ntfsDone
3612
 
3613
;----------------------------------------------------------------
3614
ntfs_Delete:
3615
        call    ntfs_lock
6468 pathoswith 3616
        call    ntfs_find_lfn
6019 pathoswith 3617
        jc      ntfsNotFound
6273 pathoswith 3618
        cmp     [ebp+NTFS.cur_iRecord], 16
6019 pathoswith 3619
        jc      ntfsDenied
6420 pathoswith 3620
        test    byte [eax+fileFlags], 1
3621
        jnz     ntfsDenied
6273 pathoswith 3622
        cmp     [ebp+NTFS.fragmentCount], 1
6019 pathoswith 3623
        jnz     ntfsUnsupported     ; record fragmented
6418 pathoswith 3624
        mov     ebx, [eax+directoryRecordReference]
3625
        mov     [ebp+NTFS.newRecord], ebx
3626
        mov     bx, [eax+fileReferenceReuse]
3627
        mov     [ebp+NTFS.indexPointer], esi
3628
        mov     eax, [ebp+NTFS.cur_iRecord]
3629
        shr     eax, 3
3630
        cmp     eax, [ebp+NTFS.mftBitmapSize]
6019 pathoswith 3631
        jnc     ntfsUnsupported
6418 pathoswith 3632
; examine file record
3633
        mov     [ebp+NTFS.cur_attr], 0x80   ; file?
3634
        mov     [ebp+NTFS.cur_offs], 0
3635
        mov     [ebp+NTFS.cur_size], 0
3636
        call    ntfs_read_attr
3637
        jnc     @f
3638
        xor     eax, eax
3639
        push    ebx eax eax eax eax
3640
        mov     [esp+12], esp
3641
        push    eax
3642
        mov     ebx, esp
3643
        mov     [ebp+NTFS.cur_attr], 0x90   ; folder?
3644
        call    ntfs_ReadFolder.doit
3645
        mov     edx, [esp+12]
3646
        add     esp, 20
3647
        pop     ebx
3648
        test    eax, eax
3649
        jnz     .ret
3650
        cmp     edx, 2
3651
        jnz     ntfsDenied      ; folder is not empty
6401 pathoswith 3652
        mov     [ebp+NTFS.cur_attr], 0xA0
6418 pathoswith 3653
        mov     [ebp+NTFS.cur_offs], 0
3654
        mov     [ebp+NTFS.cur_size], 0
6401 pathoswith 3655
        call    ntfs_read_attr.newAttribute
6418 pathoswith 3656
        jc      .deleteFileRecord
6401 pathoswith 3657
@@:
6418 pathoswith 3658
        mov     esi, [ebp+NTFS.frs_buffer]
3659
        cmp     word [esi+baseRecordReuse], 0
3660
        jnz     ntfsUnsupported     ; auxiliary record
3661
        cmp     word [esi+reuseCounter], bx
3662
        jnz     .backToIndex        ; broken index
6420 pathoswith 3663
        test    byte [esi+recordFlags], 1
6418 pathoswith 3664
        jz      .writeBitmapMFT     ; record deleted
3665
        cmp     byte [esi+hardLinkCounter], 3
3666
        jnc     ntfsUnsupported
3667
        mov     esi, [ebp+NTFS.attr_offs]
3668
        cmp     byte [esi+nonResidentFlag], 0
3669
        jz      .deleteFileRecord
3670
        movzx   eax, byte [esi+dataRunsOffset]
6401 pathoswith 3671
        add     esi, eax
6418 pathoswith 3672
        xor     edi, edi
3673
        sub     esp, 16
3674
@@:
3675
        call    ntfs_decode_mcb_entry
3676
        jnc     @f
3677
        cmp     dword[esp+8], 0
6401 pathoswith 3678
        jz      @b
6418 pathoswith 3679
        add     edi, [esp+8]
3680
        mov     ebx, [esp]
3681
        call    ntfsSpaceFree
3682
        jnc     @b
3683
@@:
3684
        add     esp, 16
3685
.deleteFileRecord:
3686
        mov     ebx, [ebp+NTFS.frs_buffer]
3687
        mov     byte [ebx+recordFlags], 0
3688
        mov     edx, [ebp+NTFS.mftLastRead]
3689
        call    writeRecord
3690
.writeBitmapMFT:
3691
        mov     eax, [ebp+NTFS.cur_iRecord]
3692
        mov     ecx, eax
3693
        shr     eax, 3
3694
        and     ecx, 7
3695
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
3696
        btr     [edi+eax], ecx
3697
        shr     eax, 9
3698
        mov     ebx, eax
3699
        shl     ebx, 9
3700
        add     eax, [ebp+NTFS.mftBitmapLocation]
3701
        add     ebx, edi
3702
        mov     ecx, 1
3703
        xor     edx, edx
3704
        call    fs_write64_sys
3705
.backToIndex:
3706
        mov     eax, [ebp+NTFS.newRecord]
3707
        mov     [ebp+NTFS.cur_iRecord], eax
3708
        mov     esi, [ebp+NTFS.indexPointer]
6468 pathoswith 3709
        call    ntfs_find_lfn.doit2
6418 pathoswith 3710
        jc      ntfsFail
3711
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3712
        mov     byte [ebx], 0
3713
        mov     ebx, [ebp+NTFS.LastRead]
3714
        mov     [ebp+NTFS.nodeLastRead], ebx
3715
        xor     ebx, ebx
3716
        test    byte [eax+indexFlags], 1
3717
        jz      .deleteIndex    ; no subnode
3718
        mov     edi, eax
3719
        call    .findSubindex
3720
        jc      ntfsFail
6401 pathoswith 3721
        movzx   edx, word [edi+indexAllocatedSize]
6418 pathoswith 3722
        test    esi, esi
3723
        jz      @f
6401 pathoswith 3724
        sub     edx, eax
3725
        sub     edx, 8
6418 pathoswith 3726
@@:
3727
        mov     eax, edi
6401 pathoswith 3728
        mov     ebx, esi
3729
        jmp     @f
3730
 
3731
.deleteIndex:
3732
        movzx   edx, word [eax+indexAllocatedSize]
6107 pathoswith 3733
        mov     ecx, [eax+fileRecordReference]
3734
        cmp     [eax+edx+fileRecordReference], ecx
3735
        jnz     @f
3736
        add     dx, [eax+edx+indexAllocatedSize]
3737
@@:
6019 pathoswith 3738
        mov     edi, [ebp+NTFS.cur_index_buf]
3739
        cmp     dword [edi], 'INDX'
3740
        jz      .indexRecord
6418 pathoswith 3741
        sub     eax, edi
6401 pathoswith 3742
        mov     edi, [ebp+NTFS.indexRoot]
6019 pathoswith 3743
        sub     [edi+sizeWithHeader], edx
3744
        sub     [edi+sizeWithoutHeader], edx
6418 pathoswith 3745
        movzx   ecx, byte [edi+attributeOffset]
6019 pathoswith 3746
        add     edi, ecx
6418 pathoswith 3747
        add     eax, edi
6273 pathoswith 3748
        sub     [edi+rootNode+nodeRealSize], edx
3749
        sub     [edi+rootNode+nodeAllocatedSize], edx
6418 pathoswith 3750
        mov     edi, [ebp+NTFS.frs_buffer]
3751
        sub     [edi+recordRealSize], edx
3752
        mov     ecx, [edi+recordRealSize]
3753
        cmp     [edi+recordAllocatedSize], ecx
6019 pathoswith 3754
        jmp     @f
2288 clevermous 3755
 
6019 pathoswith 3756
.indexRecord:
6401 pathoswith 3757
        add     edi, recordNode
3758
        sub     [edi+nodeRealSize], edx
3759
        mov     ecx, [edi+nodeRealSize]
3760
        cmp     [edi+nodeAllocatedSize], ecx
6418 pathoswith 3761
@@:
6401 pathoswith 3762
        jc      ntfsUnsupported
6418 pathoswith 3763
        add     ecx, edi
6019 pathoswith 3764
        sub     ecx, eax
3765
        mov     esi, eax
3766
        add     esi, edx
3767
        mov     edi, eax
6401 pathoswith 3768
        test    edx, edx
3769
        jns     @f
3770
        neg     edx
3771
        add     edx, ecx
3772
        sub     edx, 4
3773
        add     esi, edx
3774
        add     edi, edx
3775
        std
3776
@@:
3777
        jz      @f
3778
        shr     ecx, 2
6019 pathoswith 3779
        rep movsd
6401 pathoswith 3780
        cld
3781
@@:
3782
        test    ebx, ebx
6418 pathoswith 3783
        jz      .done
6401 pathoswith 3784
; copy index from the subnode to replace deleted pointing index
3785
        movzx   ecx, word [ebx+indexAllocatedSize]
3786
        mov     edx, ecx
6418 pathoswith 3787
        test    byte [ebx+indexFlags], 1
3788
        jz      @f
3789
        sub     ecx, 8
3790
        movzx   edi, word [ebx+edx+indexAllocatedSize]
3791
        add     edi, edx
3792
        mov     esi, [ebx+ecx]
3793
        mov     [ebx+edi-8], esi
3794
        mov     [ebx+indexAllocatedSize], cx
3795
@@:
6401 pathoswith 3796
        shr     ecx, 2
3797
        mov     esi, ebx
3798
        mov     edi, eax
3799
        rep movsd
3800
        add     word [eax+indexAllocatedSize], 8
3801
        mov     byte [eax+indexFlags], 1
6418 pathoswith 3802
        mov     edi, [ebp+NTFS.secondIndexBuffer]
6401 pathoswith 3803
        mov     eax, ebx
3804
        xor     ebx, ebx
3805
        jmp     .indexRecord
3806
 
6418 pathoswith 3807
.done:
6408 pathoswith 3808
        mov     ebx, [ebp+NTFS.frs_buffer]
6418 pathoswith 3809
        mov     edx, [ebp+NTFS.rootLastRead]
6019 pathoswith 3810
        call    writeRecord
6408 pathoswith 3811
        mov     ebx, [ebp+NTFS.cur_index_buf]
6418 pathoswith 3812
        cmp     dword [ebx], 'INDX'
3813
        jnz     @f
6408 pathoswith 3814
        mov     edx, [ebp+NTFS.nodeLastRead]
6401 pathoswith 3815
        call    writeRecord
6418 pathoswith 3816
@@:
6408 pathoswith 3817
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3818
        cmp     byte [ebx], 0
6401 pathoswith 3819
        jz      ntfsDone
6418 pathoswith 3820
        mov     edx, [ebp+NTFS.LastRead]
6019 pathoswith 3821
        call    writeRecord
6080 pathoswith 3822
        jmp     ntfsDone
6019 pathoswith 3823
 
6418 pathoswith 3824
.findSubindex:
3825
; in: eax -> index
3826
;   out:
3827
; CF=1 -> error
3828
; esi=0 -> subnode deleted
3829
; esi -> replacement index
3830
; eax = index effective size
3831
        movzx   edx, word [eax+indexAllocatedSize]
3832
        mov     eax, [eax+edx-8]
3833
        mov     edx, [ebp+NTFS.cur_size]
3834
        push    edx
3835
        cmp     edx, [ebp+NTFS.cur_subnode_size]
3836
        jz      @f
3837
        mul     [ebp+NTFS.sectors_per_cluster]
3838
@@:
3839
        mov     [ebp+NTFS.cur_attr], 0xA0
3840
        mov     [ebp+NTFS.cur_offs], eax
3841
        push    eax
3842
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3843
        mov     esi, ebx
3844
        mov     [ebp+NTFS.cur_buf], ebx
3845
        call    ntfs_read_attr.newAttribute
3846
        pop     [ebp+NTFS.cur_offs]
3847
        pop     eax
3848
        jc      .ret
3849
        cmp     dword [esi], 'INDX'
3850
        stc
3851
        jnz     .ret
3852
        mov     [ebp+NTFS.cur_size], eax
3853
        shl     eax, 9
3854
        call    ntfs_restore_usa
3855
        jc      .ret
3856
        add     esi, recordNode
3857
        add     esi, [esi+indexOffset]
3858
        test    byte [esi+indexFlags], 2
3859
        jnz     .emptyNode
3860
        cmp     [ebp+NTFS.fragmentCount], 1
3861
        stc
3862
        jnz     .ret    ; record fragmented
3863
        xor     eax, eax
3864
@@:
3865
        add     esi, eax
3866
        mov     ax, [esi+indexAllocatedSize]
3867
        test    byte [esi+eax+indexFlags], 2
3868
        jz      @b
3869
        test    byte [esi+indexFlags], 1
3870
        jz      .ret
3871
        add     eax, esi
3872
        push    esi
3873
        push    [ebp+NTFS.cur_offs]
3874
        call    .findSubindex
3875
        pop     [ebp+NTFS.cur_offs]
3876
        pop     edx
3877
        jc      .ret
3878
        test    esi, esi
3879
        jnz     .ret
3880
        mov     esi, edx
3881
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3882
        mov     [ebp+NTFS.cur_buf], ebx
3883
        push    [ebp+NTFS.cur_size]
3884
        call    ntfs_read_attr.continue
3885
        pop     eax
3886
        jc      .ret
3887
        shl     eax, 9
3888
        call    ntfs_restore_usa
3889
        jc      .ret
3890
        movzx   eax, word [esi+indexAllocatedSize]
3891
        sub     eax, 8
3892
.ret:
3893
        ret
3894
 
3895
.emptyNode:
3896
        test    byte [esi+indexFlags], 1
3897
        jz      @f
3898
        mov     eax, esi
3899
        push    [ebp+NTFS.cur_offs]
3900
        call    .findSubindex
3901
        pop     [ebp+NTFS.cur_offs]
3902
        jc      .ret
3903
        test    esi, esi
3904
        jnz     .ret
3905
@@:         ; delete node
3906
        mov     esi, [ebp+NTFS.attr_offs]
3907
        add     esi, [esi+sizeWithHeader]
3908
        cmp     byte [esi], 0xB0
3909
        stc
3910
        jnz     .ret
3911
        movzx   eax, byte [esi+attributeOffset]
3912
        add     esi, eax
3913
        mov     eax, [ebp+NTFS.cur_offs]
3914
        xor     edx, edx
3915
        div     [ebp+NTFS.cur_size]
3916
        mov     edx, eax
3917
        shr     eax, 3
3918
        and     edx, 7
3919
        btr     [esi+eax], edx
3920
        mov     esi, [ebp+NTFS.secondIndexBuffer]
3921
        mov     byte [esi], 0
3922
        xor     esi, esi
3923
        ret
3924
 
5954 pathoswith 3925
;----------------------------------------------------------------
3742 clevermous 3926
ntfs_SetFileEnd:
6107 pathoswith 3927
        call    ntfs_lock
6468 pathoswith 3928
        call    ntfs_find_lfn
6107 pathoswith 3929
        jc      ntfsNotFound
6273 pathoswith 3930
        cmp     [ebp+NTFS.cur_iRecord], 16
6107 pathoswith 3931
        jc      ntfsDenied
6420 pathoswith 3932
        test    dword [eax+fileFlags], 10000001h
3933
        jnz     ntfsDenied
6273 pathoswith 3934
        cmp     [ebp+NTFS.fragmentCount], 1
6107 pathoswith 3935
        jnz     ntfsUnsupported     ; record fragmented
6151 pathoswith 3936
; edit directory node
6107 pathoswith 3937
        mov     edi, [ebp+NTFS.cur_index_buf]
3938
        cmp     dword [edi], 'INDX'
3939
        jz      @f
3940
        mov     esi, [ebp+NTFS.frs_buffer]
3941
        mov     ecx, [esi+recordRealSize]
3942
        shr     ecx, 2
3943
        rep movsd
6273 pathoswith 3944
        mov     esi, [ebp+NTFS.attr_offs]
6107 pathoswith 3945
        mov     cl, [esi+attributeOffset]
3946
        sub     esi, [ebp+NTFS.frs_buffer]
3947
        add     eax, ecx
3948
        add     eax, esi
3949
@@:
6420 pathoswith 3950
        mov     edi, eax
3951
        mov     eax, [ebx+4]
6107 pathoswith 3952
        mov     edx, [ebx+8]
6420 pathoswith 3953
        mov     [edi+fileRealSize], eax
3954
        mov     [edi+fileRealSize+4], edx
3955
        push    edx eax ebx
3956
        call    ntfsGetTime
3957
        mov     [edi+fileModified], eax
3958
        mov     [edi+fileModified+4], edx
3959
        mov     [edi+recordModified], eax
3960
        mov     [edi+recordModified+4], edx
3961
        mov     [edi+fileAccessed], eax
3962
        mov     [edi+fileAccessed+4], edx
3963
        pop     ebx ecx edx
6273 pathoswith 3964
        mov     eax, [ebp+NTFS.LastRead]
6107 pathoswith 3965
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 3966
        mov     [ebp+NTFS.cur_attr], 0x80
3967
        mov     [ebp+NTFS.cur_offs], 0
3968
        mov     [ebp+NTFS.cur_size], 0
6107 pathoswith 3969
        call    ntfs_read_attr
3970
        jc      ntfsFail
6420 pathoswith 3971
        mov     esi, edi
3972
        mov     edi, [ebp+NTFS.frs_buffer]
3973
        cmp     word [edi+baseRecordReuse], 0
3974
        jnz     ntfsUnsupported     ; auxiliary record
3975
        mov     al, [edi+attributeOffset]
3976
        add     edi, eax
3977
        mov     al, [edi+attributeOffset]
3978
        add     edi, eax
6107 pathoswith 3979
        mov     eax, ecx
6420 pathoswith 3980
        mov     ecx, 6
3981
        add     esi, fileModified
3982
        add     edi, 8
3983
        rep movsd
6273 pathoswith 3984
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3985
        cmp     word [ecx+attributeFlags], 0
3986
        jnz     ntfsUnsupported
3987
        cmp     byte [ecx+nonResidentFlag], 0
3988
        jz      .resizeAttribute
6107 pathoswith 3989
        cmp     [ecx+attributeRealSize+4], edx
3990
        jnz     .resizeAttribute
3991
        cmp     [ecx+attributeRealSize], eax
3992
        jnc     .resizeAttribute
3993
        mov     eax, [ecx+attributeRealSize]
3994
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 3995
        mov     [ebp+NTFS.cur_size], ecx
6107 pathoswith 3996
        shl     ecx, 9
3997
        div     ecx
3998
        test    edx, edx
3999
        jz      .aligned
4000
        push    edx
4001
        push    ecx
4002
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 4003
        mov     [ebp+NTFS.cur_offs], eax
6107 pathoswith 4004
        stdcall kernel_alloc, ecx
4005
        pop     ecx
4006
        pop     edi
6405 pathoswith 4007
        mov     esi, eax
6107 pathoswith 4008
        sub     ecx, edi
4009
        add     edi, eax
6273 pathoswith 4010
        mov     [ebp+NTFS.cur_buf], eax
6107 pathoswith 4011
        call    ntfs_read_attr.continue
4012
        jc      @f
4013
        xor     eax, eax
4014
        rep stosb
4015
        push    ebx
6273 pathoswith 4016
        mov     eax, [ebp+NTFS.LastRead]
6405 pathoswith 4017
        mov     ebx, esi
6107 pathoswith 4018
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
4019
        xor     edx, edx
4020
        call    fs_write64_app
4021
        pop     ebx
4022
@@:
6405 pathoswith 4023
        stdcall kernel_free, esi
6107 pathoswith 4024
.aligned:
4025
        mov     eax, [ebx+4]
4026
        mov     edx, [ebx+8]
4027
.resizeAttribute:
4028
        call    resizeAttribute
4029
        jc      ntfsError
6408 pathoswith 4030
        mov     ebx, [ebp+NTFS.frs_buffer]
4031
        mov     edx, [ebp+NTFS.mftLastRead]
6107 pathoswith 4032
        call    writeRecord     ; file
6408 pathoswith 4033
        mov     ebx, [ebp+NTFS.cur_index_buf]
4034
        mov     edx, [ebp+NTFS.nodeLastRead]
6107 pathoswith 4035
        call    writeRecord     ; directory
4036
        call    ntfsSpaceClean
4037
        jmp     ntfsDone
4038
 
6462 pathoswith 4039
ntfsGetTime:
4040
        call    fsGetTime
4041
        jmp     @f
2288 clevermous 4042
 
6420 pathoswith 4043
ntfsCalculateTime:
4044
; in: esi -> data block
6462 pathoswith 4045
; out: edx:eax = seconds since 01.01.1601 x10000000
4046
        call    fsCalculateTime
6420 pathoswith 4047
@@:
6462 pathoswith 4048
        mov     edx, 10000000
6420 pathoswith 4049
        mul     edx
6462 pathoswith 4050
        add     eax, 3365781504
4051
        adc     edx, 29389701
6420 pathoswith 4052
        ret
4053
 
3742 clevermous 4054
;----------------------------------------------------------------
6420 pathoswith 4055
ntfs_SetFileInfo:
3742 clevermous 4056
        call    ntfs_lock
6468 pathoswith 4057
        call    ntfs_find_lfn
6420 pathoswith 4058
        jnc     @f
3742 clevermous 4059
        test    eax, eax
6019 pathoswith 4060
        jz      ntfsFail
4061
        jmp     ntfsNotFound
2288 clevermous 4062
 
6420 pathoswith 4063
@@:
4064
        cmp     [ebp+NTFS.fragmentCount], 1
4065
        jnz     ntfsUnsupported     ; record fragmented
4066
        mov     esi, [ebp+NTFS.cur_index_buf]
4067
        cmp     dword [esi], 'INDX'
4068
        jz      @f
4069
        sub     eax, esi
4070
        mov     esi, [ebp+NTFS.indexRoot]
4071
        movzx   edx, byte [esi+attributeOffset]
4072
        add     eax, esi
4073
        add     eax, edx
4074
@@:
4075
        mov     esi, [ebx+16]
4076
        mov     edi, eax
4077
        mov     eax, [esi]
4078
        and     eax, 27h
4079
        and     byte [edi+fileFlags], -28h
4080
        or      [edi+fileFlags], al
4081
        add     esi, 8
4082
        call    ntfsCalculateTime
4083
        mov     [edi+fileCreated], eax
4084
        mov     [edi+fileCreated+4], edx
4085
        add     esi, 8
4086
        call    ntfsCalculateTime
4087
        mov     [edi+fileAccessed], eax
4088
        mov     [edi+fileAccessed+4], edx
4089
        add     esi, 8
4090
        call    ntfsCalculateTime
4091
        mov     [edi+fileModified], eax
4092
        mov     [edi+fileModified+4], edx
4093
        mov     ebx, [ebp+NTFS.cur_index_buf]
4094
        cmp     dword [ebx], 'INDX'
4095
        jz      @f
4096
        mov     ebx, [ebp+NTFS.frs_buffer]
4097
@@:
4098
        mov     edx, [ebp+NTFS.LastRead]
4099
        call    writeRecord
4100
        jmp     ntfsDone
4101
 
6019 pathoswith 4102
ntfsUnsupported:
4103
        push    ERROR_UNSUPPORTED_FS
6080 pathoswith 4104
        jmp     ntfsOut
6019 pathoswith 4105
ntfsDevice:
4106
        push    ERROR_DEVICE
4107
        jmp     ntfsOut
4108
ntfsNotFound:
4109
        push    ERROR_FILE_NOT_FOUND
4110
        jmp     ntfsOut
4111
ntfsDenied:
4112
        push    ERROR_ACCESS_DENIED
4113
        jmp     ntfsOut
4114
ntfsFail:
4115
        push    ERROR_FS_FAIL
4116
        jmp     ntfsOut
6080 pathoswith 4117
ntfsDiskFull:
4118
        push    ERROR_DISK_FULL
4119
        jmp     ntfsOut
6414 pathoswith 4120
ntfsErrorPop5:
4121
        pop     ebx
4122
        pop     ebx
6340 pathoswith 4123
ntfsErrorPop3:
4124
        pop     ebx
6107 pathoswith 4125
ntfsErrorPop2:
4126
        pop     ebx
4127
ntfsErrorPop:
4128
        pop     ebx
6080 pathoswith 4129
ntfsError:
4130
        push    eax
4131
ntfsOut:
4132
        call    ntfs_unlock
4133
        xor     ebx, ebx
4134
        pop     eax
4135
        ret