Subversion Repositories Kolibri OS

Rev

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

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