Subversion Repositories Kolibri OS

Rev

Rev 10015 | Details | Compare with Previous | Last modification | View Log | RSS feed

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