Subversion Repositories Kolibri OS

Rev

Rev 6428 | Rev 6468 | 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: 6462 $
9
 
6462 pathoswith 10
; NTFS external functions
11
;   in:
12
; ebx -> parameter structure of sysfunc 70
13
; ebp -> NTFS structure
14
; [esi]+[[esp+4]] = name
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
 
6405 pathoswith 170
align 256
171
mft_retrieval       rb  768
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
unichar_toupper:
1165
        push    eax
1166
        call    uni2ansi_char
1167
        cmp     al, '_'
1168
        jz      .unk
1169
        add     esp, 4
1504 diamond 1170
        call    char_toupper
1171
        jmp     ansi2uni_char
1172
.unk:
1173
        pop     eax
1174
        ret
2288 clevermous 1175
 
1176
ntfs_find_lfn:
5954 pathoswith 1177
; in: [esi]+[esp+4] = name
1178
;   out:
6405 pathoswith 1179
; [ebp+NTFS.cur_iRecord] = target fileRecord
6411 pathoswith 1180
; eax -> target index in the node
1181
; [ebp+NTFS.LastRead] = target node location
6405 pathoswith 1182
; [ebp+NTFS.indexPointer] -> index, that points the target subnode
6411 pathoswith 1183
; [ebp+NTFS.nodeLastRead] = branch node location
6405 pathoswith 1184
; [ebp+NTFS.indexRoot] -> attribute
6411 pathoswith 1185
; [ebp+NTFS.rootLastRead] = directory fileRecord location
6405 pathoswith 1186
; [ebp+NTFS.cur_size] = index record size in sectors
1187
; [ebp+NTFS.cur_subnode_size] = index record size in clusters or sectors
5994 pathoswith 1188
; CF=1 -> file not found, eax=0 -> error
6297 pathoswith 1189
        mov     [ebp+NTFS.cur_iRecord], 5   ; start from root directory
2288 clevermous 1190
.doit2:
6273 pathoswith 1191
        mov     [ebp+NTFS.cur_attr], 0x90   ; $INDEX_ROOT
1192
        and     [ebp+NTFS.cur_offs], 0
3742 clevermous 1193
        mov     eax, [ebp+NTFS.cur_index_size]
6273 pathoswith 1194
        mov     [ebp+NTFS.cur_size], eax
3742 clevermous 1195
        mov     eax, [ebp+NTFS.cur_index_buf]
6273 pathoswith 1196
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1197
        call    ntfs_read_attr
5994 pathoswith 1198
        mov     eax, 0
6297 pathoswith 1199
        jc      .ret
6273 pathoswith 1200
        cmp     [ebp+NTFS.cur_read], 0x20
2288 clevermous 1201
        jc      .ret
6418 pathoswith 1202
        push    esi
2288 clevermous 1203
        pushad
3742 clevermous 1204
        mov     esi, [ebp+NTFS.cur_index_buf]
6340 pathoswith 1205
        mov     eax, [esi+indexRecordSize]
1206
        shr     eax, 9
1207
        cmp     [ebp+NTFS.cur_index_size], eax
6297 pathoswith 1208
        jc      .realloc
6340 pathoswith 1209
        mov     [ebp+NTFS.cur_size], eax
1210
        mov     al, [esi+indexRecordSizeClus]
1211
        mov     [ebp+NTFS.cur_subnode_size], eax
6297 pathoswith 1212
        add     esi, rootNode
1213
        mov     eax, [esi+nodeRealSize]
1214
        add     eax, rootNode
6273 pathoswith 1215
        cmp     [ebp+NTFS.cur_read], eax
6297 pathoswith 1216
        jc      .err
2288 clevermous 1217
        mov     edi, [esp+4]
6408 pathoswith 1218
        mov     eax, [ebp+NTFS.mftLastRead]
6340 pathoswith 1219
        mov     [ebp+NTFS.rootLastRead], eax
1220
        mov     eax, [ebp+NTFS.attr_offs]
1221
        mov     [ebp+NTFS.indexRoot], eax
1222
; edi -> name, esi -> current index node
2288 clevermous 1223
.scanloop:
6297 pathoswith 1224
        add     esi, [esi+indexOffset]
2288 clevermous 1225
.scanloopint:
6297 pathoswith 1226
        test    byte [esi+indexFlags], 2
2288 clevermous 1227
        jnz     .subnode
1228
        push    esi
6297 pathoswith 1229
        movzx   ecx, byte [esi+fileNameLength]
1230
        add     esi, fileName
2288 clevermous 1231
        push    edi
1232
@@:
1233
        lodsw
1234
        call    unichar_toupper
1235
        push    eax
1236
        mov     al, [edi]
1237
        inc     edi
1238
        cmp     al, '/'
1239
        jz      .slash
1240
        call    char_toupper
1241
        call    ansi2uni_char
1242
        cmp     ax, [esp]
1243
        pop     eax
1244
        loopz   @b
1245
        jz      .found
1246
        pop     edi
1247
        pop     esi
1248
        jb      .subnode
1249
.scanloopcont:
6297 pathoswith 1250
        movzx   eax, word [esi+indexAllocatedSize]
2288 clevermous 1251
        add     esi, eax
1252
        jmp     .scanloopint
6297 pathoswith 1253
 
1254
.realloc:
6340 pathoswith 1255
        mov     edi, eax
1256
        mov     eax, [esi+indexRecordSize]
1257
        shl     eax, 1
1258
        stdcall kernel_alloc, eax
6297 pathoswith 1259
        test    eax, eax
1260
        jz      .err
6405 pathoswith 1261
        mov     edx, [ebp+NTFS.cur_index_buf]
1262
        cmp     edx, [ebp+NTFS.secondIndexBuffer]
1263
        jc      @f
1264
        mov     edx, [ebp+NTFS.secondIndexBuffer]
1265
@@:
6297 pathoswith 1266
        mov     [ebp+NTFS.cur_index_buf], eax
6340 pathoswith 1267
        add     eax, [esi+indexRecordSize]
1268
        mov     [ebp+NTFS.secondIndexBuffer], eax
1269
        mov     [ebp+NTFS.cur_index_size], edi
6405 pathoswith 1270
        stdcall kernel_free, edx
6297 pathoswith 1271
        popad
6418 pathoswith 1272
        pop     eax
6297 pathoswith 1273
        jmp     .doit2
1274
 
1275
.notfound:
1276
        mov     [esp+1Ch], esi
1277
.err:
1278
        popad
1279
        stc
6418 pathoswith 1280
.ret2:
1281
        pop     esi
6297 pathoswith 1282
.ret:
1283
        ret     4
1284
 
2288 clevermous 1285
.slash:
1286
        pop     eax
1287
        pop     edi
1288
        pop     esi
1289
.subnode:
6297 pathoswith 1290
        test    byte [esi+indexFlags], 1
2288 clevermous 1291
        jz      .notfound
6411 pathoswith 1292
        mov     eax, [ebp+NTFS.LastRead]
1293
        mov     [ebp+NTFS.nodeLastRead], eax
1294
        mov     [ebp+NTFS.indexPointer], esi
6297 pathoswith 1295
        movzx   eax, word [esi+indexAllocatedSize]
2288 clevermous 1296
        mov     eax, [esi+eax-8]
6340 pathoswith 1297
        mov     edx, [ebp+NTFS.cur_size]
1298
        push    edx
1299
        cmp     edx, [ebp+NTFS.cur_subnode_size]
1300
        jz      @f
1301
        mul     [ebp+NTFS.sectors_per_cluster]
1302
@@:
1303
        mov     esi, [ebp+NTFS.cur_index_buf]
1304
        xchg    [ebp+NTFS.secondIndexBuffer], esi
1305
        mov     [ebp+NTFS.cur_index_buf], esi
1306
        mov     [ebp+NTFS.cur_buf], esi
1307
        mov     [ebp+NTFS.cur_attr], 0xA0   ; $INDEX_ALLOCATION
6273 pathoswith 1308
        mov     [ebp+NTFS.cur_offs], eax
6297 pathoswith 1309
        call    ntfs_read_attr.newAttribute
6340 pathoswith 1310
        pop     eax
1311
        mov     [ebp+NTFS.cur_size], eax
2288 clevermous 1312
        shl     eax, 9
6273 pathoswith 1313
        cmp     [ebp+NTFS.cur_read], eax
5954 pathoswith 1314
        jnz     .err
2288 clevermous 1315
        cmp     dword [esi], 'INDX'
5954 pathoswith 1316
        jnz     .err
2288 clevermous 1317
        mov     ebx, esi
1318
        call    ntfs_restore_usa
5954 pathoswith 1319
        jc      .err
6297 pathoswith 1320
        add     esi, recordNode
2288 clevermous 1321
        jmp     .scanloop
6297 pathoswith 1322
 
2288 clevermous 1323
.found:
1324
        cmp     byte [edi], 0
6418 pathoswith 1325
        jz      @f
2288 clevermous 1326
        cmp     byte [edi], '/'
6418 pathoswith 1327
        jz      @f
2288 clevermous 1328
        pop     edi
1329
        pop     esi
1330
        jmp     .scanloopcont
6297 pathoswith 1331
 
6418 pathoswith 1332
@@:
2288 clevermous 1333
        pop     esi
1334
        pop     esi
1335
        mov     eax, [esi]
6273 pathoswith 1336
        mov     [ebp+NTFS.cur_iRecord], eax
2288 clevermous 1337
        mov     [esp+1Ch], esi
1338
        mov     [esp+4], edi
1339
        popad
1340
        inc     esi
1341
        cmp     byte [esi-1], 0
6418 pathoswith 1342
        jnz     @f
1343
        cmp     dword [esp+8], 0
1344
        jz      .ret2
1345
        mov     esi, [esp+8]
1346
        mov     dword [esp+8], 0
1347
@@:
1348
        pop     eax
2288 clevermous 1349
        jmp     .doit2
1350
 
1351
;----------------------------------------------------------------
5954 pathoswith 1352
ntfs_ReadFile:
2288 clevermous 1353
        cmp     byte [esi], 0
1354
        jnz     @f
1355
        or      ebx, -1
3598 clevermous 1356
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 1357
        ret
6297 pathoswith 1358
 
2288 clevermous 1359
@@:
3742 clevermous 1360
        call    ntfs_lock
1361
        stdcall ntfs_find_lfn, [esp+4]
2288 clevermous 1362
        jnc     .found
3742 clevermous 1363
        call    ntfs_unlock
2288 clevermous 1364
        or      ebx, -1
3598 clevermous 1365
        movi    eax, ERROR_FILE_NOT_FOUND
2288 clevermous 1366
        ret
6297 pathoswith 1367
 
2288 clevermous 1368
.found:
6273 pathoswith 1369
        mov     [ebp+NTFS.cur_attr], 0x80   ; $DATA
1370
        and     [ebp+NTFS.cur_offs], 0
1371
        and     [ebp+NTFS.cur_size], 0
2288 clevermous 1372
        call    ntfs_read_attr
1373
        jnc     @f
3742 clevermous 1374
        call    ntfs_unlock
2288 clevermous 1375
        or      ebx, -1
3598 clevermous 1376
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 1377
        ret
6297 pathoswith 1378
 
2288 clevermous 1379
@@:
1380
        pushad
1381
        and     dword [esp+10h], 0
1382
        xor     eax, eax
3742 clevermous 1383
        cmp     dword [ebx+8], 0x200
2288 clevermous 1384
        jb      @f
1385
.eof0:
1386
        popad
1387
        xor     ebx, ebx
1388
.eof:
3742 clevermous 1389
        call    ntfs_unlock
6297 pathoswith 1390
        movi    eax, ERROR_END_OF_FILE
2288 clevermous 1391
        ret
6297 pathoswith 1392
 
2288 clevermous 1393
@@:
3742 clevermous 1394
        mov     ecx, [ebx+12]
1395
        mov     edx, [ebx+16]
1396
        mov     eax, [ebx+4]
2288 clevermous 1397
        test    eax, 0x1FF
1398
        jz      .alignedstart
1399
        push    edx
3742 clevermous 1400
        mov     edx, [ebx+8]
2288 clevermous 1401
        shrd    eax, edx, 9
1400 turbanoff 1402
        pop     edx
6273 pathoswith 1403
        mov     [ebp+NTFS.cur_offs], eax
1404
        mov     [ebp+NTFS.cur_size], 1
1405
        lea     eax, [ebp+NTFS.bitmap_buf]
1406
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1407
        call    ntfs_read_attr.continue
3742 clevermous 1408
        mov     eax, [ebx+4]
2288 clevermous 1409
        and     eax, 0x1FF
6273 pathoswith 1410
        lea     esi, [ebp+NTFS.bitmap_buf+eax]
1411
        sub     eax, [ebp+NTFS.cur_read]
2288 clevermous 1412
        jae     .eof0
1413
        neg     eax
1414
        push    ecx
1415
        cmp     ecx, eax
1416
        jb      @f
1417
        mov     ecx, eax
1418
@@:
1419
        mov     [esp+10h+4], ecx
1420
        mov     edi, edx
1421
        rep movsb
1422
        mov     edx, edi
1423
        pop     ecx
1424
        sub     ecx, [esp+10h]
1425
        jnz     @f
1426
.retok:
1427
        popad
3742 clevermous 1428
        call    ntfs_unlock
2288 clevermous 1429
        xor     eax, eax
1400 turbanoff 1430
        ret
6297 pathoswith 1431
 
2288 clevermous 1432
@@:
6273 pathoswith 1433
        cmp     [ebp+NTFS.cur_read], 0x200
2288 clevermous 1434
        jz      .alignedstart
1435
.eof_ebx:
1436
        popad
1437
        jmp     .eof
6297 pathoswith 1438
 
2288 clevermous 1439
.alignedstart:
3742 clevermous 1440
        mov     eax, [ebx+4]
2288 clevermous 1441
        push    edx
3742 clevermous 1442
        mov     edx, [ebx+8]
2288 clevermous 1443
        add     eax, 511
1444
        adc     edx, 0
1445
        shrd    eax, edx, 9
1446
        pop     edx
6273 pathoswith 1447
        mov     [ebp+NTFS.cur_offs], eax
1448
        mov     [ebp+NTFS.cur_buf], edx
2288 clevermous 1449
        mov     eax, ecx
1450
        shr     eax, 9
6273 pathoswith 1451
        mov     [ebp+NTFS.cur_size], eax
1452
        add     eax, [ebp+NTFS.cur_offs]
2288 clevermous 1453
        push    eax
1454
        call    ntfs_read_attr.continue
6273 pathoswith 1455
        pop     [ebp+NTFS.cur_offs]
1456
        mov     eax, [ebp+NTFS.cur_read]
2288 clevermous 1457
        add     [esp+10h], eax
1458
        mov     eax, ecx
1459
        and     eax, not 0x1FF
6273 pathoswith 1460
        cmp     [ebp+NTFS.cur_read], eax
2288 clevermous 1461
        jnz     .eof_ebx
1462
        and     ecx, 0x1FF
1463
        jz      .retok
6273 pathoswith 1464
        add     edx, [ebp+NTFS.cur_read]
1465
        mov     [ebp+NTFS.cur_size], 1
1466
        lea     eax, [ebp+NTFS.bitmap_buf]
1467
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1468
        call    ntfs_read_attr.continue
6273 pathoswith 1469
        cmp     [ebp+NTFS.cur_read], ecx
2288 clevermous 1470
        jb      @f
6273 pathoswith 1471
        mov     [ebp+NTFS.cur_read], ecx
2288 clevermous 1472
@@:
6273 pathoswith 1473
        xchg    ecx, [ebp+NTFS.cur_read]
2288 clevermous 1474
        push    ecx
1475
        mov     edi, edx
6273 pathoswith 1476
        lea     esi, [ebp+NTFS.bitmap_buf]
2288 clevermous 1477
        add     [esp+10h+4], ecx
1478
        rep movsb
1479
        pop     ecx
1480
        xor     eax, eax
6273 pathoswith 1481
        cmp     ecx, [ebp+NTFS.cur_read]
2288 clevermous 1482
        jz      @f
1483
        mov     al, ERROR_END_OF_FILE
1484
@@:
1485
        mov     [esp+1Ch], eax
3742 clevermous 1486
        call    ntfs_unlock
2288 clevermous 1487
        popad
1488
        ret
1400 turbanoff 1489
 
2288 clevermous 1490
;----------------------------------------------------------------
3742 clevermous 1491
ntfs_ReadFolder:
1492
        call    ntfs_lock
6297 pathoswith 1493
        mov     [ebp+NTFS.cur_iRecord], 5   ; root directory
2288 clevermous 1494
        cmp     byte [esi], 0
6297 pathoswith 1495
        jz      @f
3742 clevermous 1496
        stdcall ntfs_find_lfn, [esp+4]
6297 pathoswith 1497
        jc      ntfsNotFound
1498
@@:
6273 pathoswith 1499
        mov     [ebp+NTFS.cur_attr], 0x10   ; $STANDARD_INFORMATION
1500
        and     [ebp+NTFS.cur_offs], 0
1501
        mov     [ebp+NTFS.cur_size], 1
1502
        lea     eax, [ebp+NTFS.bitmap_buf]
1503
        mov     [ebp+NTFS.cur_buf], eax
2288 clevermous 1504
        call    ntfs_read_attr
6297 pathoswith 1505
        jc      ntfsFail
6273 pathoswith 1506
        mov     [ebp+NTFS.cur_attr], 0x90   ; $INDEX_ROOT
6297 pathoswith 1507
.doit:
3742 clevermous 1508
        mov     eax, [ebp+NTFS.cur_index_size]
6273 pathoswith 1509
        mov     [ebp+NTFS.cur_size], eax
3742 clevermous 1510
        mov     eax, [ebp+NTFS.cur_index_buf]
6273 pathoswith 1511
        mov     [ebp+NTFS.cur_buf], eax
6297 pathoswith 1512
        call    ntfs_read_attr.newAttribute
1513
        jc      ntfsFail
6273 pathoswith 1514
        cmp     [ebp+NTFS.cur_read], 0x20
6297 pathoswith 1515
        jc      ntfsFail
3742 clevermous 1516
        mov     esi, [ebp+NTFS.cur_index_buf]
6340 pathoswith 1517
        mov     eax, [esi+indexRecordSize]
1518
        shr     eax, 9
1519
        cmp     [ebp+NTFS.cur_index_size], eax
6297 pathoswith 1520
        jc      .realloc
6340 pathoswith 1521
        mov     [ebp+NTFS.cur_subnode_size], eax
6297 pathoswith 1522
        add     esi, rootNode
1523
        mov     eax, [esi+nodeRealSize]
1524
        add     eax, rootNode
1525
        cmp     [ebp+NTFS.cur_read], eax
6408 pathoswith 1526
        jc      ntfsFail
1527
        mov     edi, [ebx+16]
1528
        mov     ecx, [ebx+12]
1529
        pushd   [ebx]
1530
        pushd   [ebx+8]     ; read ANSI/UNICODE name
1531
        push    edi
1532
        mov     edx, esp
1533
        mov     ebx, [ebx+4]
2288 clevermous 1534
; init header
1535
        xor     eax, eax
6408 pathoswith 1536
        mov     [edi+8], eax
1537
        mov     [edi+4], eax
1538
        inc     eax
1539
        mov     [edi], eax      ; version
1540
        add     edi, 32
3742 clevermous 1541
; edi -> BDFE, esi -> current index data, ebx = first wanted block,
2288 clevermous 1542
; ecx = number of blocks to read
1543
; edx -> parameters block: dd , dd 
6273 pathoswith 1544
        cmp     [ebp+NTFS.cur_iRecord], 5
2288 clevermous 1545
        jz      .skip_specials
1546
; dot and dotdot entries
1547
        push    esi
1548
        xor     esi, esi
1549
        call    .add_special_entry
1550
        inc     esi
1551
        call    .add_special_entry
1552
        pop     esi
1553
.skip_specials:
1554
; at first, dump index root
6297 pathoswith 1555
        add     esi, [esi+indexOffset]
2288 clevermous 1556
.dump_root:
6297 pathoswith 1557
        test    byte [esi+indexFlags], 2
2288 clevermous 1558
        jnz     .dump_root_done
1559
        call    .add_entry
6297 pathoswith 1560
        movzx   eax, word [esi+indexAllocatedSize]
2288 clevermous 1561
        add     esi, eax
1562
        jmp     .dump_root
6297 pathoswith 1563
 
1564
.realloc:
6340 pathoswith 1565
        mov     edi, eax
1566
        mov     eax, [esi+indexRecordSize]
1567
        shl     eax, 1
1568
        stdcall kernel_alloc, eax
6297 pathoswith 1569
        test    eax, eax
6408 pathoswith 1570
        jz      ntfsFail
6405 pathoswith 1571
        mov     edx, [ebp+NTFS.cur_index_buf]
1572
        cmp     edx, [ebp+NTFS.secondIndexBuffer]
1573
        jc      @f
1574
        mov     edx, [ebp+NTFS.secondIndexBuffer]
1575
@@:
6297 pathoswith 1576
        mov     [ebp+NTFS.cur_index_buf], eax
6340 pathoswith 1577
        add     eax, [esi+indexRecordSize]
1578
        mov     [ebp+NTFS.secondIndexBuffer], eax
1579
        mov     [ebp+NTFS.cur_index_size], edi
6405 pathoswith 1580
        stdcall kernel_free, edx
6297 pathoswith 1581
        jmp     .doit
1582
 
2288 clevermous 1583
.dump_root_done:
1584
; now dump all subnodes
1585
        push    ecx edi
6273 pathoswith 1586
        lea     edi, [ebp+NTFS.bitmap_buf]
1587
        mov     [ebp+NTFS.cur_buf], edi
2288 clevermous 1588
        mov     ecx, 0x400/4
1589
        xor     eax, eax
1590
        rep stosd
6273 pathoswith 1591
        mov     [ebp+NTFS.cur_attr], 0xB0   ; $BITMAP
1592
        and     [ebp+NTFS.cur_offs], 0
1593
        mov     [ebp+NTFS.cur_size], 2
6297 pathoswith 1594
        call    ntfs_read_attr.newAttribute
2288 clevermous 1595
        pop     edi ecx
1596
        push    0       ; save offset in $BITMAP attribute
6273 pathoswith 1597
        and     [ebp+NTFS.cur_offs], 0
2288 clevermous 1598
.dumploop:
6273 pathoswith 1599
        mov     [ebp+NTFS.cur_attr], 0xA0
3742 clevermous 1600
        mov     eax, [ebp+NTFS.cur_subnode_size]
6273 pathoswith 1601
        mov     [ebp+NTFS.cur_size], eax
6297 pathoswith 1602
        mov     esi, [ebp+NTFS.cur_index_buf]
1603
        mov     [ebp+NTFS.cur_buf], esi
6273 pathoswith 1604
        mov     eax, [ebp+NTFS.cur_offs]
6297 pathoswith 1605
        push    eax
3742 clevermous 1606
        imul    eax, [ebp+NTFS.cur_subnode_size]
6273 pathoswith 1607
        mov     [ebp+NTFS.cur_offs], eax
6297 pathoswith 1608
        call    ntfs_read_attr.newAttribute
6273 pathoswith 1609
        pop     [ebp+NTFS.cur_offs]
3742 clevermous 1610
        mov     eax, [ebp+NTFS.cur_subnode_size]
2288 clevermous 1611
        shl     eax, 9
6273 pathoswith 1612
        cmp     [ebp+NTFS.cur_read], eax
2288 clevermous 1613
        jnz     .done
1614
        push    eax
6273 pathoswith 1615
        mov     eax, [ebp+NTFS.cur_offs]
2288 clevermous 1616
        and     eax, 0x400*8-1
6273 pathoswith 1617
        bt      dword [ebp+NTFS.bitmap_buf], eax
2288 clevermous 1618
        pop     eax
1619
        jnc     .dump_subnode_done
1620
        cmp     dword [esi], 'INDX'
1621
        jnz     .dump_subnode_done
1622
        push    ebx
1623
        mov     ebx, esi
1624
        call    ntfs_restore_usa
1625
        pop     ebx
1626
        jc      .dump_subnode_done
6297 pathoswith 1627
        add     esi, recordNode
1628
        add     esi, [esi+indexOffset]
2288 clevermous 1629
.dump_subnode:
6297 pathoswith 1630
        test    byte [esi+indexFlags], 2
2288 clevermous 1631
        jnz     .dump_subnode_done
1632
        call    .add_entry
6297 pathoswith 1633
        movzx   eax, word [esi+indexAllocatedSize]
2288 clevermous 1634
        add     esi, eax
1635
        jmp     .dump_subnode
6297 pathoswith 1636
 
2288 clevermous 1637
.dump_subnode_done:
6273 pathoswith 1638
        inc     [ebp+NTFS.cur_offs]
1639
        test    [ebp+NTFS.cur_offs], 0x400*8-1
2288 clevermous 1640
        jnz     .dumploop
6273 pathoswith 1641
        mov     [ebp+NTFS.cur_attr], 0xB0
2288 clevermous 1642
        push    ecx edi
6273 pathoswith 1643
        lea     edi, [ebp+NTFS.bitmap_buf]
1644
        mov     [ebp+NTFS.cur_buf], edi
2288 clevermous 1645
        mov     ecx, 0x400/4
1646
        xor     eax, eax
1647
        rep stosd
1648
        pop     edi ecx
1649
        pop     eax
6273 pathoswith 1650
        push    [ebp+NTFS.cur_offs]
2288 clevermous 1651
        inc     eax
6273 pathoswith 1652
        mov     [ebp+NTFS.cur_offs], eax
1653
        mov     [ebp+NTFS.cur_size], 2
2288 clevermous 1654
        push    eax
6297 pathoswith 1655
        call    ntfs_read_attr.newAttribute
2288 clevermous 1656
        pop     eax
6273 pathoswith 1657
        pop     [ebp+NTFS.cur_offs]
2288 clevermous 1658
        push    eax
1659
        jmp     .dumploop
6297 pathoswith 1660
 
2288 clevermous 1661
.done:
1662
        pop     eax
6408 pathoswith 1663
        pop     eax
1664
        mov     ebx, [eax+4]
1665
        pop     eax
1666
        pop     eax
1667
        test    eax, eax
1668
        jz      .ret
2288 clevermous 1669
        xor     eax, eax
1670
        dec     ecx
1671
        js      @f
1672
        mov     al, ERROR_END_OF_FILE
1673
@@:
6408 pathoswith 1674
        push    eax
3742 clevermous 1675
        call    ntfs_unlock
6408 pathoswith 1676
        pop     eax
2288 clevermous 1677
        ret
1678
 
1679
.add_special_entry:
1680
        mov     eax, [edx]
1681
        inc     dword [eax+8]   ; new file found
1682
        dec     ebx
1683
        jns     .ret
1684
        dec     ecx
1685
        js      .ret
1686
        inc     dword [eax+4]   ; new file block copied
1687
        mov     eax, [edx+4]
1688
        mov     [edi+4], eax
1689
        mov     eax, 0x10
1690
        stosd
1691
        scasd
6462 pathoswith 1692
        push    ebx ecx edx
6273 pathoswith 1693
        mov     eax, dword [ebp+NTFS.bitmap_buf]
1694
        mov     edx, dword [ebp+NTFS.bitmap_buf+4]
2288 clevermous 1695
        call    ntfs_datetime_to_bdfe
6273 pathoswith 1696
        mov     eax, dword [ebp+NTFS.bitmap_buf+0x18]
1697
        mov     edx, dword [ebp+NTFS.bitmap_buf+0x1C]
2288 clevermous 1698
        call    ntfs_datetime_to_bdfe
6273 pathoswith 1699
        mov     eax, dword [ebp+NTFS.bitmap_buf+8]
1700
        mov     edx, dword [ebp+NTFS.bitmap_buf+0xC]
2288 clevermous 1701
        call    ntfs_datetime_to_bdfe
6462 pathoswith 1702
        pop     edx ecx ebx
2288 clevermous 1703
        xor     eax, eax
1704
        stosd
1705
        stosd
1706
        mov     al, '.'
1707
        push    edi ecx
1708
        lea     ecx, [esi+1]
1709
        test    byte [edi-0x24], 1
1710
        jz      @f
1711
        rep stosw
1712
        pop     ecx
1713
        xor     eax, eax
1714
        stosw
1715
        pop     edi
1716
        add     edi, 520
1717
        ret
6297 pathoswith 1718
 
2288 clevermous 1719
@@:
1720
        rep stosb
1721
        pop     ecx
1722
        xor     eax, eax
1723
        stosb
1724
        pop     edi
1725
        add     edi, 264
1726
.ret:
1727
        ret
1728
 
1729
.add_entry:
1730
; do not return DOS 8.3 names
6297 pathoswith 1731
        cmp     byte [esi+namespace], 2
2288 clevermous 1732
        jz      .ret
1733
; do not return system files
1734
; ... note that there will be no bad effects if system files also were reported ...
6297 pathoswith 1735
        cmp     dword [esi+fileRecordReference], 0x10
2288 clevermous 1736
        jb      .ret
1737
        mov     eax, [edx]
1738
        inc     dword [eax+8]   ; new file found
1739
        dec     ebx
1740
        jns     .ret
1741
        dec     ecx
1742
        js      .ret
1743
        inc     dword [eax+4]   ; new file block copied
1744
        mov     eax, [edx+4]    ; flags
1745
        call    ntfs_direntry_to_bdfe
1746
        push    ecx esi edi
6297 pathoswith 1747
        movzx   ecx, byte [esi+fileNameLength]
1748
        add     esi, fileName
2288 clevermous 1749
        test    byte [edi-0x24], 1
1750
        jz      .ansi
1751
        shr     ecx, 1
1752
        rep movsd
1753
        adc     ecx, ecx
1754
        rep movsw
1755
        and     word [edi], 0
1756
        pop     edi
1757
        add     edi, 520
1758
        pop     esi ecx
1759
        ret
6297 pathoswith 1760
 
2288 clevermous 1761
.ansi:
1762
        jecxz   .skip
1763
@@:
1764
        lodsw
1765
        call    uni2ansi_char
1766
        stosb
1767
        loop    @b
1768
.skip:
1769
        xor     al, al
1770
        stosb
1771
        pop     edi
1772
        add     edi, 264
1773
        pop     esi ecx
1774
        ret
1775
 
1776
ntfs_direntry_to_bdfe:
1777
        mov     [edi+4], eax    ; ANSI/UNICODE name
6297 pathoswith 1778
        mov     eax, [esi+fileFlags]
2288 clevermous 1779
        test    eax, 0x10000000
1780
        jz      @f
1781
        and     eax, not 0x10000000
1782
        or      al, 0x10
1783
@@:
1784
        stosd
1785
        scasd
6462 pathoswith 1786
        push    ebx ecx edx
6297 pathoswith 1787
        mov     eax, [esi+fileCreated]
1788
        mov     edx, [esi+fileCreated+4]
2288 clevermous 1789
        call    ntfs_datetime_to_bdfe
6297 pathoswith 1790
        mov     eax, [esi+fileAccessed]
1791
        mov     edx, [esi+fileAccessed+4]
2288 clevermous 1792
        call    ntfs_datetime_to_bdfe
6297 pathoswith 1793
        mov     eax, [esi+fileModified]
1794
        mov     edx, [esi+fileModified+4]
2288 clevermous 1795
        call    ntfs_datetime_to_bdfe
6462 pathoswith 1796
        pop     edx ecx ebx
6297 pathoswith 1797
        mov     eax, [esi+fileRealSize]
2288 clevermous 1798
        stosd
6297 pathoswith 1799
        mov     eax, [esi+fileRealSize+4]
2288 clevermous 1800
        stosd
1801
        ret
1802
 
1803
ntfs_datetime_to_bdfe:
6462 pathoswith 1804
; in: edx:eax = seconds since 01.01.1601 x10000000
1805
; edi -> data block
1806
; out: edi = edi+8
1807
        sub     eax, 3365781504
1808
        sbb     edx, 29389701
6297 pathoswith 1809
        mov     ecx, 10000000
6462 pathoswith 1810
        cmp     edx, ecx
1811
        jc      @f
2288 clevermous 1812
        xor     edx, edx
6462 pathoswith 1813
@@:
6297 pathoswith 1814
        div     ecx
6462 pathoswith 1815
        jmp     fsTime2bdfe
2288 clevermous 1816
 
1817
;----------------------------------------------------------------
6420 pathoswith 1818
ntfs_GetFileInfo:
6426 pathoswith 1819
        call    ntfs_lock
1820
        mov     edi, [ebx+16]
6420 pathoswith 1821
        cmp     byte [esi], 0
6426 pathoswith 1822
        jz      .volume
6420 pathoswith 1823
        stdcall ntfs_find_lfn, [esp+4]
1824
        jnc     .found
1825
        test    eax, eax
1826
        jz      ntfsFail
1827
        jmp     ntfsNotFound
1828
 
1829
.found:
1830
        mov     esi, eax
1831
        xor     eax, eax
1832
        call    ntfs_direntry_to_bdfe
6426 pathoswith 1833
.end:
6420 pathoswith 1834
        call    ntfs_unlock
1835
        xor     eax, eax
1836
        ret
1837
 
6426 pathoswith 1838
.volume:
1839
        mov     byte [edi], 8
1840
        mov     eax, [ebx+8]
1841
        mov     [edi+4], eax
1842
        mov     eax, dword [ebp+NTFS.Length]
1843
        mov     edx, dword [ebp+NTFS.Length+4]
1844
        shld    edx, eax, 9
1845
        shl     eax, 9
1846
        mov     [edi+36], edx
1847
        mov     [edi+32], eax
1848
        add     edi, 40
1849
        mov     [ebp+NTFS.cur_buf], edi
1850
        mov     [ebp+NTFS.cur_iRecord], 3
1851
        mov     [ebp+NTFS.cur_attr], 0x60
1852
        mov     [ebp+NTFS.cur_offs], 0
1853
        mov     [ebp+NTFS.cur_size], 1
1854
        call    ntfs_read_attr
1855
        jc      ntfsFail
1856
        mov     ecx, [ebp+NTFS.cur_read]
1857
        mov     [edi+ecx], ax
1858
        cmp     [ebx+8], eax
1859
        jnz     .end
1860
        mov     esi, edi
1861
        shr     ecx, 1
6428 pathoswith 1862
        jz      .end
6426 pathoswith 1863
@@:
1864
        lodsw
1865
        call    uni2ansi_char
1866
        stosb
1867
        dec     ecx
1868
        jnz     @b
1869
        mov     byte [edi], 0
1870
        jmp     .end
1871
 
6420 pathoswith 1872
;----------------------------------------------------------------
3742 clevermous 1873
ntfs_CreateFolder:
6273 pathoswith 1874
        mov     [ebp+NTFS.bFolder], 1
5954 pathoswith 1875
        jmp     @f
5994 pathoswith 1876
 
5954 pathoswith 1877
ntfs_CreateFile:
6273 pathoswith 1878
        mov     [ebp+NTFS.bFolder], 0
5954 pathoswith 1879
@@:
1880
        cmp     byte [esi], 0
1881
        jnz     @f
2288 clevermous 1882
        xor     ebx, ebx
6019 pathoswith 1883
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 1884
        ret
6297 pathoswith 1885
 
5954 pathoswith 1886
@@: ; 1. Search file
1887
        call    ntfs_lock
1888
        stdcall ntfs_find_lfn, [esp+4]
6080 pathoswith 1889
        jc      .notFound
1890
; found, rewrite
6273 pathoswith 1891
        cmp     [ebp+NTFS.cur_iRecord], 16
6019 pathoswith 1892
        jc      ntfsDenied
6273 pathoswith 1893
        cmp     [ebp+NTFS.bFolder], 1
6080 pathoswith 1894
        jz      .folder
6420 pathoswith 1895
        test    byte [eax+fileFlags], 1
1896
        jnz     ntfsDenied
6273 pathoswith 1897
        cmp     [ebp+NTFS.fragmentCount], 1
6080 pathoswith 1898
        jnz     ntfsUnsupported     ; record fragmented
6151 pathoswith 1899
; edit directory node
6080 pathoswith 1900
        mov     edi, [ebp+NTFS.cur_index_buf]
1901
        cmp     dword [edi], 'INDX'
1902
        jz      @f
1903
        mov     esi, [ebp+NTFS.frs_buffer]
1904
        mov     ecx, [esi+recordRealSize]
1905
        shr     ecx, 2
1906
        rep movsd
6273 pathoswith 1907
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 1908
        mov     cl, [esi+attributeOffset]
1909
        sub     esi, [ebp+NTFS.frs_buffer]
1910
        add     eax, ecx
1911
        add     eax, esi
1912
@@:
6420 pathoswith 1913
        mov     edi, eax
1914
        mov     eax, [ebx+12]
1915
        mov     [edi+fileRealSize], eax
1916
        mov     dword [edi+fileRealSize+4], 0
1917
        push    ebx eax
1918
        call    ntfsGetTime
1919
        mov     [edi+fileModified], eax
1920
        mov     [edi+fileModified+4], edx
1921
        mov     [edi+recordModified], eax
1922
        mov     [edi+recordModified+4], edx
1923
        mov     [edi+fileAccessed], eax
1924
        mov     [edi+fileAccessed+4], edx
1925
        pop     edx ebx
6273 pathoswith 1926
        mov     eax, [ebp+NTFS.LastRead]
6080 pathoswith 1927
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 1928
        mov     [ebp+NTFS.cur_attr], 0x80
1929
        mov     [ebp+NTFS.cur_offs], 0
1930
        mov     [ebp+NTFS.cur_size], 0
5994 pathoswith 1931
        call    ntfs_read_attr
6080 pathoswith 1932
        jc      ntfsFail
6420 pathoswith 1933
        mov     esi, edi
1934
        mov     edi, [ebp+NTFS.frs_buffer]
1935
        cmp     word [edi+baseRecordReuse], 0
1936
        jnz     ntfsUnsupported     ; auxiliary record
1937
        mov     al, [edi+attributeOffset]
1938
        add     edi, eax
1939
        mov     al, [edi+attributeOffset]
1940
        add     edi, eax
1941
        mov     ecx, 6
1942
        add     esi, fileModified
1943
        add     edi, 8
1944
        rep movsd
6080 pathoswith 1945
        mov     eax, edx
1946
        xor     edx, edx
6273 pathoswith 1947
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 1948
        cmp     word [ecx+attributeFlags], 0
1949
        jnz     ntfsUnsupported
1950
        push    ebx
1951
        cmp     byte [ecx+nonResidentFlag], 0
1952
        jz      @f
6080 pathoswith 1953
        cmp     [ecx+attributeRealSize+4], edx
1954
        jnz     @f
5994 pathoswith 1955
        cmp     [ecx+attributeRealSize], eax
6080 pathoswith 1956
        jz      ntfs_WriteFile.writeNode
1957
@@:
1958
        jmp     ntfs_WriteFile.resizeAttribute
5994 pathoswith 1959
 
6080 pathoswith 1960
.folder:
1961
        bt      dword [eax+fileFlags], 28
1962
        jnc     ntfsDenied
1963
        push    0
1964
        jmp     ntfsOut
1965
 
1966
.notFound:  ; create
1967
        test    eax, eax
1968
        jz      ntfsFail
6273 pathoswith 1969
        cmp     [ebp+NTFS.fragmentCount], 1
6080 pathoswith 1970
        jnz     ntfsUnsupported     ; record fragmented
6019 pathoswith 1971
; 2. Prepare directory record
5954 pathoswith 1972
        mov     ecx, esi
1973
@@:         ; count characters
1974
        inc     ecx
1975
        cmp     byte [ecx], '/'
6080 pathoswith 1976
        jz      ntfsNotFound    ; path folder not found
5954 pathoswith 1977
        cmp     byte [ecx], 0
1978
        jnz     @b
1979
        sub     ecx, esi
6297 pathoswith 1980
        push    ecx     ; name length
1981
        shl     ecx, 1
1982
        add     ecx, fileName+7
1983
        and     ecx, not 7
5954 pathoswith 1984
        mov     edi, [ebp+NTFS.cur_index_buf]
6292 pathoswith 1985
        mov     edx, [ebx+12]
1986
        mov     [ebp+NTFS.fileRealSize], edx
1987
        mov     edx, [ebx+16]
1988
        mov     [ebp+NTFS.fileDataBuffer], edx
6297 pathoswith 1989
        push    esi
1990
        push    ecx     ; index length
6292 pathoswith 1991
        mov     edx, ecx
6019 pathoswith 1992
        cmp     dword [edi], 'INDX'
5954 pathoswith 1993
        jz      .indexRecord
6019 pathoswith 1994
        mov     esi, [ebp+NTFS.frs_buffer]  ; indexRoot
6292 pathoswith 1995
        mov     ecx, [esi+recordRealSize]
5954 pathoswith 1996
        add     edx, ecx
1997
        cmp     [esi+recordAllocatedSize], edx
6292 pathoswith 1998
        jc      .growTree
5954 pathoswith 1999
        mov     [esi+recordRealSize], edx
2000
        shr     ecx, 2
2001
        rep movsd
6407 pathoswith 2002
        mov     edi, [ebp+NTFS.indexRoot]
5954 pathoswith 2003
        sub     edi, [ebp+NTFS.frs_buffer]
2004
        add     edi, [ebp+NTFS.cur_index_buf]
2005
        mov     esi, [esp]
2006
        add     [edi+sizeWithHeader], esi
2007
        add     [edi+sizeWithoutHeader], esi
6019 pathoswith 2008
        mov     cl, [edi+attributeOffset]
5954 pathoswith 2009
        add     edi, ecx
6273 pathoswith 2010
        add     [edi+rootNode+nodeRealSize], esi
2011
        add     [edi+rootNode+nodeAllocatedSize], esi
5954 pathoswith 2012
        sub     eax, [ebp+NTFS.cur_index_buf]
2013
        add     eax, edi
2014
        mov     edi, [ebp+NTFS.cur_index_buf]
2015
        jmp     .common
2288 clevermous 2016
 
6411 pathoswith 2017
.growTree:  ; create indexRecord
2018
        mov     edi, [ebp+NTFS.cur_index_buf]
6292 pathoswith 2019
        mov     ecx, 10
2020
        xor     eax, eax
2021
        rep stosd
6407 pathoswith 2022
        mov     esi, [ebp+NTFS.indexRoot]
6340 pathoswith 2023
        mov     al, [esi+attributeOffset]
2024
        add     esi, eax
6292 pathoswith 2025
        rdtsc
2026
        stosw
2027
        mov     eax, [esi+indexRecordSize]
2028
        cmp     eax, [ebp+NTFS.frs_size]
6407 pathoswith 2029
        jc      .errorPop3
6292 pathoswith 2030
        shr     eax, 9
2031
        inc     eax
2032
        mov     edi, [ebp+NTFS.cur_index_buf]
2033
        mov     dword[edi], 'INDX'
2034
        mov     byte [edi+updateSequenceOffset], 28h
2035
        mov     [edi+updateSequenceSize], al
2036
        add     edi, recordNode
2037
        shl     eax, 1
2038
        add     eax, 28h-recordNode+7
2039
        and     eax, not 7
2040
        mov     [edi+indexOffset], eax
2041
        mov     ecx, [esi+indexRecordSize]
2042
        sub     ecx, recordNode
2043
        mov     [edi+nodeAllocatedSize], ecx
2044
        add     esi, rootNode
2045
        push    esi
2046
        mov     ecx, [esi+nodeRealSize]
2047
        sub     ecx, [esi+indexOffset]
2048
        add     eax, ecx
2049
        mov     [edi+nodeRealSize], eax
6411 pathoswith 2050
        mov     eax, [esi+nonLeafFlag]
2051
        mov     [edi+nonLeafFlag], eax
6292 pathoswith 2052
        shr     ecx, 2
2053
        add     esi, [esi+indexOffset]
2054
        add     edi, [edi+indexOffset]
2055
        rep movsd       ; copy root indexes
2056
; clear root node
2057
        mov     cl, 10
2058
        mov     edi, [esp]
2059
        xor     eax, eax
2060
        rep stosd
2061
        pop     edi
2062
        mov     byte [edi+indexOffset], 16
2063
        mov     byte [edi+nodeRealSize], 28h
2064
        mov     byte [edi+nodeAllocatedSize], 28h
2065
        mov     byte [edi+nonLeafFlag], 1
2066
        mov     byte [edi+16+indexAllocatedSize], 18h
2067
        mov     byte [edi+16+indexFlags], 3
6407 pathoswith 2068
        mov     esi, [ebp+NTFS.indexRoot]
6292 pathoswith 2069
        add     edi, 28h
2070
        mov     eax, edi
2071
        sub     eax, esi
2072
        mov     word [esi+sizeWithoutHeader], 38h
2073
        xchg    [esi+sizeWithHeader], eax
6407 pathoswith 2074
        add     esi, eax
2075
        mov     [ebp+NTFS.attr_offs], edi
2076
        cmp     byte [esi], 0xA0
2077
        jnz     @f
2078
        cmp     dword [esi+attributeAllocatedSize], 0
2079
        jz      @f
2080
        mov     eax, [ebp+NTFS.frs_buffer]
2081
        mov     ecx, eax
2082
        add     ecx, [eax+recordRealSize]
2083
        sub     ecx, esi
2084
        shr     ecx, 2
2085
        rep movsd
2086
        sub     edi, eax
2087
        mov     [eax+recordRealSize], edi
2088
        call    .ntfsNodeAlloc
2089
        jc      ntfsErrorPop3
2090
        mov     eax, [ebp+NTFS.newRecord]
2091
        mov     edi, [ebp+NTFS.cur_index_buf]
2092
        mov     [edi+recordVCN], eax
2093
        mov     edi, [ebp+NTFS.attr_offs]
2094
        mov     [edi-8], eax
2095
        jmp     .refresh
2096
 
2097
@@:
6292 pathoswith 2098
        mov     cl, 32
2099
        xor     eax, eax
2100
        rep stosd
6407 pathoswith 2101
        mov     eax, [ebp+NTFS.cur_subnode_size]
2102
        cmp     eax, [ebp+NTFS.cur_size]
2103
        jnz     @f
2104
        mov     al, 1
2105
@@:
2106
        mov     [ebp+NTFS.fileDataSize], eax
6292 pathoswith 2107
        mov     edi, [ebp+NTFS.BitmapStart]
2108
        call    ntfsSpaceAlloc
6407 pathoswith 2109
        movi    eax, ERROR_DISK_FULL
2110
        jc      ntfsErrorPop3
2111
; create $IndexAllocation
2112
        mov     edi, [ebp+NTFS.attr_offs]
6292 pathoswith 2113
        mov     byte [edi+attributeType], 0xA0
2114
        mov     byte [edi+nonResidentFlag], 1
2115
        mov     byte [edi+nameLength], 4
2116
        mov     byte [edi+nameOffset], 40h
2117
        mov     byte [edi+dataRunsOffset], 48h
2118
        mov     byte [edi+sizeWithHeader], 50h
2119
        mov     eax, [ebp+NTFS.fileDataSize]
2120
        dec     eax
2121
        mov     [edi+lastVCN], eax
2122
        inc     eax
2123
        mul     [ebp+NTFS.sectors_per_cluster]
2124
        shl     eax, 9
2125
        mov     [edi+attributeAllocatedSize], eax
2126
        mov     [edi+attributeRealSize], eax
2127
        mov     [edi+initialDataSize], eax
2128
        mov     dword[edi+40h], 490024h     ; unicode $I30
2129
        mov     dword[edi+40h+4], 300033h
2130
        push    edi
2131
        mov     esi, edi
2132
        add     edi, 48h
2133
        call    createMcbEntry
2134
        mov     esi, [ebp+NTFS.frs_buffer]
2135
        pop     edi
2136
        mov     al, [esi+newAttributeID]
2137
        mov     [edi+attributeID], al
2138
        add     edi, 50h
2139
        inc     eax
2140
; create $Bitmap
2141
        mov     [edi+attributeID], al
2142
        inc     eax
2143
        mov     [esi+newAttributeID], al
2144
        mov     byte [edi+attributeType], 0xB0
2145
        mov     byte [edi+nameLength], 4
2146
        mov     byte [edi+nameOffset], 18h
2147
        mov     byte [edi+attributeOffset], 20h
2148
        mov     byte [edi+sizeWithoutHeader], 8
2149
        mov     byte [edi+sizeWithHeader], 28h
2150
        mov     dword[edi+18h], 490024h     ; unicode $I30
2151
        mov     dword[edi+18h+4], 300033h
2152
        mov     byte [edi+20h], 1
2153
        mov     dword[edi+28h], -1
2154
        add     edi, 30h
2155
        sub     edi, esi
2156
        mov     [esi+recordRealSize], edi
2157
        mov     eax, [ebp+NTFS.fileDataStart]
2158
        mul     [ebp+NTFS.sectors_per_cluster]
6408 pathoswith 2159
        mov     edx, eax
6407 pathoswith 2160
        jmp     @f
2161
 
2162
.refresh:
2163
        mov     [ebp+NTFS.cur_size], 0
2164
        call    ntfs_read_attr.continue
2165
        movi    eax, ERROR_FS_FAIL
2166
        jc      ntfsErrorPop3
6408 pathoswith 2167
        mov     edx, [ebp+NTFS.LastRead]
6407 pathoswith 2168
@@:
6408 pathoswith 2169
        mov     ebx, [ebp+NTFS.cur_index_buf]
6407 pathoswith 2170
        call    writeRecord
6408 pathoswith 2171
        mov     ebx, [ebp+NTFS.frs_buffer]
2172
        mov     edx, [ebp+NTFS.rootLastRead]
6407 pathoswith 2173
        call    writeRecord
2174
        mov     esi, [esp+4]
2175
        stdcall ntfs_find_lfn.doit2, 0
2176
        test    eax, eax
2177
        jz      .errorPop3
6292 pathoswith 2178
        mov     edi, [ebp+NTFS.cur_index_buf]
2179
        mov     edx, [esp]
5954 pathoswith 2180
.indexRecord:
6273 pathoswith 2181
        add     edi, recordNode
6292 pathoswith 2182
        add     edx, [edi+nodeRealSize]
6273 pathoswith 2183
        cmp     [edi+nodeAllocatedSize], edx
6340 pathoswith 2184
        jc      .arborizeTree
2185
        mov     [edi+nodeRealSize], edx
2186
        jmp     .common
2187
 
2188
.errorPop3:
5954 pathoswith 2189
        add     esp, 12
6340 pathoswith 2190
        jmp     ntfsUnsupported
6292 pathoswith 2191
 
6407 pathoswith 2192
.ntfsNodeAlloc:
2193
; in: [ebp+NTFS.attr_offs] -> $IndexAllocation
2194
;   out:
2195
; [ebp+NTFS.newRecord] = node VCN
2196
; [ebp+NTFS.cur_offs]
2197
; CF=1 -> eax = error code
6340 pathoswith 2198
        mov     esi, [ebp+NTFS.attr_offs]
2199
        add     esi, [esi+sizeWithHeader]
2200
        cmp     byte [esi], 0xB0
6407 pathoswith 2201
        jnz     .ret
6414 pathoswith 2202
        movzx   ecx, word [esi+sizeWithoutHeader]
2203
        shr     ecx, 2
2204
        movzx   edi, byte [esi+attributeOffset]
2205
        add     edi, esi
2206
        mov     edx, edi
2207
        or      eax, -1
2208
        repz scasd
2209
        jnz     @f
2210
        cmp     [edi], eax
2211
        jnz     .ret
2212
; extend folder $Bitmap
2213
        add     word [esi+sizeWithHeader], 8
2214
        add     word [esi+sizeWithoutHeader], 8
2215
        mov     esi, [ebp+NTFS.frs_buffer]
2216
        mov     eax, [esi+recordRealSize]
2217
        add     eax, 8
2218
        cmp     [esi+recordAllocatedSize], eax
2219
        jc      .ret
2220
        mov     [esi+recordRealSize], eax
2221
        xor     eax, eax
2222
        stosd
2223
        mov     [edi], eax
2224
        mov     [edi+8], eax
2225
        dec     eax
2226
        mov     [edi+4], eax
2227
@@:
2228
        sub     edi, 4
2229
        mov     eax, [edi]
6340 pathoswith 2230
        not     eax
2231
        bsf     eax, eax
6414 pathoswith 2232
        bts     [edi], eax
2233
        sub     edi, edx
2234
        shl     edi, 3
2235
        add     eax, edi
6340 pathoswith 2236
        mul     [ebp+NTFS.cur_subnode_size]
2237
        mov     [ebp+NTFS.newRecord], eax
6407 pathoswith 2238
        mov     ecx, [ebp+NTFS.cur_size]
2239
        cmp     ecx, [ebp+NTFS.cur_subnode_size]
2240
        jz      @f
2241
        mul     [ebp+NTFS.sectors_per_cluster]
2242
@@:
2243
        mov     [ebp+NTFS.cur_offs], eax
2244
        add     eax, ecx
2245
        shl     eax, 9
2246
        mov     esi, [ebp+NTFS.attr_offs]
2247
        cmp     [esi+attributeAllocatedSize], eax
2248
        jnc     @f
2249
        xor     edx, edx
2250
        jmp     resizeAttribute
2251
 
2252
.ret:
2253
        movi    eax, ERROR_UNSUPPORTED_FS
2254
        stc
2255
@@:
2256
        ret
2257
 
2258
.arborizeTree:      ; find median index
6340 pathoswith 2259
        mov     ecx, [edi+nodeRealSize]
2260
        sub     ecx, [edi+indexOffset]
2261
        shr     ecx, 1
2262
        add     edi, [edi+indexOffset]
2263
        xor     eax, eax
2264
@@:
2265
        add     edi, eax
2266
        mov     ax, [edi+indexAllocatedSize]
2267
        sub     ecx, eax
2268
        jnc     @b
6407 pathoswith 2269
        add     eax, 8
6340 pathoswith 2270
        mov     esi, [ebp+NTFS.secondIndexBuffer]
2271
        cmp     dword [esi], 'INDX'
6411 pathoswith 2272
        jz      @f
6340 pathoswith 2273
; move index to the root node
2274
        mov     esi, [ebp+NTFS.frs_buffer]
6407 pathoswith 2275
        mov     ecx, eax
2276
        add     ecx, 8
2277
        add     ecx, [esi+recordRealSize]
6340 pathoswith 2278
        cmp     [esi+recordAllocatedSize], ecx
6411 pathoswith 2279
        jc      .growTree
6409 pathoswith 2280
        push    edi eax
6407 pathoswith 2281
        call    .ntfsNodeAlloc
6414 pathoswith 2282
        jc      ntfsErrorPop5
2283
        pop     eax
6340 pathoswith 2284
        mov     edi, [ebp+NTFS.indexRoot]
2285
        add     [ebp+NTFS.attr_offs], eax
2286
        add     [edi+sizeWithHeader], eax
2287
        add     [edi+sizeWithoutHeader], eax
2288
        movzx   ecx, byte [edi+attributeOffset]
2289
        add     ecx, edi
2290
        add     [ecx+rootNode+nodeRealSize], eax
2291
        add     [ecx+rootNode+nodeAllocatedSize], eax
6405 pathoswith 2292
        add     ecx, [ebp+NTFS.indexPointer]
6340 pathoswith 2293
        sub     ecx, [ebp+NTFS.secondIndexBuffer]
6409 pathoswith 2294
        mov     esi, [ebp+NTFS.frs_buffer]
2295
        add     [esi+recordRealSize], eax
2296
        add     esi, [esi+recordRealSize]
6340 pathoswith 2297
        mov     edi, esi
2298
        sub     esi, eax
2299
        neg     ecx
2300
        add     ecx, esi
2301
        shr     ecx, 2
2302
        sub     esi, 4
2303
        sub     edi, 4
2304
        std
2305
        rep movsd   ; make space
2306
        mov     [edi], ecx
2307
        mov     edi, esi
2308
        add     edi, 4
2309
        mov     esi, [esp]
2310
        add     word [esi+indexAllocatedSize], 8
2311
        mov     byte [esi+indexFlags], 1
2312
        mov     ecx, eax
2313
        sub     ecx, 8
2314
        shr     ecx, 2
2315
        cld
2316
        rep movsd   ; insert index
2317
        mov     eax, [ebp+NTFS.newRecord]
2318
        stosd
6411 pathoswith 2319
        jmp     .splitNode
2320
 
6414 pathoswith 2321
.growBranch:    ; move node and replace it with empty one
2322
        mov     esi, [ebp+NTFS.cur_index_buf]
2323
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2324
        mov     eax, [esi+recordVCN]
2325
        mov     [edi+recordVCN], eax
2326
        add     edi, recordNode
2327
        mov     eax, [edi+indexOffset]
2328
        add     eax, 18h
2329
        mov     [edi+nodeRealSize], eax
2330
        add     edi, [edi+indexOffset]
2331
        mov     ecx, 6
2332
        xor     eax, eax
2333
        mov     [ebp+NTFS.indexPointer], edi
2334
        push    edi
2335
        rep stosd
2336
        pop     edi
2337
        mov     eax, [ebp+NTFS.newRecord]
2338
        mov     byte [edi+indexAllocatedSize], 18h
2339
        mov     byte [edi+indexFlags], 3
2340
        mov     [edi+16], eax
2341
        mov     [esi+recordVCN], eax
2342
        mov     eax, [ebp+NTFS.LastRead]
2343
        mov     [ebp+NTFS.nodeLastRead], eax
2344
        push    [ebp+NTFS.cur_size]
2345
        mov     [ebp+NTFS.cur_size], 0
2346
        call    ntfs_read_attr.continue
2347
        pop     [ebp+NTFS.cur_size]
2348
        movi    eax, ERROR_FS_FAIL
2349
        jc      ntfsErrorPop5
2350
        pop     eax edi
6411 pathoswith 2351
@@:         ; move index to the branch node
6414 pathoswith 2352
        push    edi eax
2353
        call    .ntfsNodeAlloc
2354
        jc      ntfsErrorPop5
2355
        mov     eax, [esp]
2356
        mov     esi, [ebp+NTFS.secondIndexBuffer]
6411 pathoswith 2357
        add     esi, recordNode
2358
        mov     ecx, [esi+nodeRealSize]
2359
        add     eax, ecx
2360
        cmp     [esi+nodeAllocatedSize], eax
6414 pathoswith 2361
        jc      .growBranch
6411 pathoswith 2362
        mov     [esi+nodeRealSize], eax
2363
        lea     edi, [esi+eax-4]
2364
        add     esi, ecx
2365
        mov     ecx, esi
2366
        sub     ecx, [ebp+NTFS.indexPointer]
2367
        shr     ecx, 2
2368
        sub     esi, 4
2369
        std
2370
        rep movsd   ; make space
2371
        mov     [edi], ecx
6414 pathoswith 2372
        pop     ecx
2373
        sub     ecx, 8
2374
        shr     ecx, 2
6411 pathoswith 2375
        mov     edi, esi
2376
        add     edi, 4
2377
        mov     esi, [esp]
2378
        add     word [esi+indexAllocatedSize], 8
2379
        mov     byte [esi+indexFlags], 1
2380
        cld
2381
        rep movsd   ; insert index
2382
        mov     eax, [ebp+NTFS.newRecord]
2383
        stosd
2384
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2385
        mov     edx, [ebp+NTFS.nodeLastRead]
2386
        push    esi
2387
        call    writeRecord
2388
        pop     esi
2389
.splitNode:
6340 pathoswith 2390
        mov     edi, [ebp+NTFS.cur_index_buf]
2391
        mov     eax, edi
2392
        add     eax, recordNode
2393
        add     eax, [edi+recordNode+nodeRealSize]
2394
        sub     eax, esi
2395
        push    eax
2396
        mov     ecx, [edi+recordNode+indexOffset]
2397
        add     eax, ecx
2398
        add     ecx, recordNode
2399
        shr     ecx, 2
2400
        push    esi
2401
        mov     esi, edi
2402
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2403
        rep movsd
2404
        pop     esi
2405
        pop     ecx
2406
        shr     ecx, 2
2407
        rep movsd
2408
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2409
        mov     [edi+recordNode+nodeRealSize], eax
2410
        pop     edi
2411
        mov     cl, 4
2412
        xor     eax, eax
2413
        mov     esi, edi
2414
        rep stosd
2415
        mov     byte [esi+indexAllocatedSize], 16
2416
        mov     byte [esi+indexFlags], 2
2417
        mov     esi, [ebp+NTFS.cur_index_buf]
2418
        mov     eax, [ebp+NTFS.newRecord]
2419
        mov     [esi+recordVCN], eax
2420
        add     esi, recordNode
2421
        sub     edi, esi
2422
        mov     [esi+nodeRealSize], edi
6408 pathoswith 2423
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2424
        mov     edx, [ebp+NTFS.LastRead]
6340 pathoswith 2425
        call    writeRecord
6407 pathoswith 2426
        jmp     .refresh
6340 pathoswith 2427
 
6292 pathoswith 2428
.common:
6273 pathoswith 2429
        add     edi, edx
2430
        sub     edi, 4
5954 pathoswith 2431
        mov     esi, edi
2432
        sub     esi, [esp]
2433
        mov     ecx, esi
6292 pathoswith 2434
        sub     ecx, eax    ; eax = pointer in the record
5954 pathoswith 2435
        shr     ecx, 2
2436
        inc     ecx
2437
        std
2438
        rep movsd           ; move forward, make space
2439
        mov     ecx, [esp]
2440
        shr     ecx, 2
2441
        xor     eax, eax
2442
        rep stosd
2443
        cld
2444
        add     edi, 4
6420 pathoswith 2445
        call    ntfsGetTime
2446
        mov     [edi+fileCreated], eax
2447
        mov     [edi+fileCreated+4], edx
2448
        mov     [edi+fileModified], eax
2449
        mov     [edi+fileModified+4], edx
2450
        mov     [edi+recordModified], eax
2451
        mov     [edi+recordModified+4], edx
2452
        mov     [edi+fileAccessed], eax
2453
        mov     [edi+fileAccessed+4], edx
6151 pathoswith 2454
        pop     ecx
5954 pathoswith 2455
        pop     esi
6151 pathoswith 2456
        mov     [edi+indexAllocatedSize], cx    ; fill index with data
5954 pathoswith 2457
        mov     eax, [esp]
6080 pathoswith 2458
        shl     eax, 1
2459
        add     eax, 42h
5954 pathoswith 2460
        mov     [edi+indexRawSize], ax
6418 pathoswith 2461
        mov     eax, [ebp+NTFS.cur_iRecord]
5954 pathoswith 2462
        mov     [edi+directoryRecordReference], eax
2463
        mov     eax, [ebp+NTFS.frs_buffer]
2464
        mov     eax, [eax+reuseCounter]
2465
        mov     [edi+directoryReferenceReuse], ax
6292 pathoswith 2466
        mov     eax, [ebp+NTFS.frs_size]
2467
        shr     eax, 8
6151 pathoswith 2468
        add     ecx, 30h+48h+8+18h+8
2469
        add     ecx, eax
6292 pathoswith 2470
        mov     eax, [ebp+NTFS.fileRealSize]
2471
        add     ecx, eax
5954 pathoswith 2472
        mov     [edi+fileRealSize], eax
6151 pathoswith 2473
        cmp     [ebp+NTFS.frs_size], ecx
2474
        jc      @f
2475
        xor     eax, eax
2476
@@:
5954 pathoswith 2477
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2478
        shl     ecx, 9
2479
        add     eax, ecx
2480
        dec     eax
2481
        xor     edx, edx
2482
        div     ecx
2483
        mov     [ebp+NTFS.fileDataSize], eax
2484
        mul     ecx
2485
        mov     [edi+fileAllocatedSize], eax
2486
        pop     ecx
6405 pathoswith 2487
        mov     [ebp+NTFS.indexPointer], edi
5954 pathoswith 2488
        mov     [edi+fileNameLength], cl
6297 pathoswith 2489
        add     edi, fileName
5954 pathoswith 2490
@@:         ; record filename
2491
        lodsb
2492
        call    ansi2uni_char
2493
        stosw
2494
        dec     ecx
2495
        jnz     @b
6273 pathoswith 2496
        mov     eax, [ebp+NTFS.LastRead]
5954 pathoswith 2497
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 2498
        cmp     [ebp+NTFS.bFolder], 0
5954 pathoswith 2499
        jz      @f
6405 pathoswith 2500
        mov     edi, [ebp+NTFS.indexPointer]
6080 pathoswith 2501
        bts     dword [edi+fileFlags], 28
5954 pathoswith 2502
        jmp     .mftBitmap
2503
 
2504
@@: ; 3. File data
6151 pathoswith 2505
        cmp     [ebp+NTFS.fileDataSize], 0
5954 pathoswith 2506
        jz      .mftBitmap
6080 pathoswith 2507
        mov     edi, [ebp+NTFS.BitmapStart]
2508
        call    ntfsSpaceAlloc
2509
        jc      ntfsDiskFull
6292 pathoswith 2510
        mov     eax, [ebp+NTFS.fileDataStart]
5954 pathoswith 2511
        mul     [ebp+NTFS.sectors_per_cluster]
2512
        mov     ecx, [ebp+NTFS.fileRealSize]
2513
        add     ecx, 511
2514
        shr     ecx, 9
6292 pathoswith 2515
        mov     ebx, [ebp+NTFS.fileDataBuffer]
5954 pathoswith 2516
        call    fs_write64_app
2517
        test    eax, eax
6019 pathoswith 2518
        jnz     ntfsDevice
5954 pathoswith 2519
    ; 4. MFT record
2520
.mftBitmap: ; search for free record
2521
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2522
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2523
        mov     al, -1
2524
        add     edi, 3
2525
        sub     ecx, 3
2526
        repz scasb
2527
        dec     edi
2528
        movzx   eax, byte [edi]
2529
        not     al
2530
        bsf     ecx, eax
6107 pathoswith 2531
        jz      .extendBitmapMFT    ; no free records
6019 pathoswith 2532
        bts     [edi], ecx
2533
; get record location
5954 pathoswith 2534
        sub     edi, [ebp+NTFS.mftBitmapBuffer]
2535
        shl     edi, 3
2536
        add     edi, ecx
6340 pathoswith 2537
        mov     [ebp+NTFS.newRecord], edi
5954 pathoswith 2538
        mov     eax, [ebp+NTFS.frs_size]
2539
        shr     eax, 9
2540
        mul     edi
6273 pathoswith 2541
        mov     [ebp+NTFS.cur_iRecord], 0
2542
        mov     [ebp+NTFS.cur_attr], 0x80
2543
        mov     [ebp+NTFS.cur_offs], eax
6405 pathoswith 2544
        push    eax
2545
        mov     [ebp+NTFS.cur_size], 0
5954 pathoswith 2546
        mov     eax, [ebp+NTFS.frs_buffer]
6273 pathoswith 2547
        mov     [ebp+NTFS.cur_buf], eax
5954 pathoswith 2548
        call    ntfs_read_attr
6405 pathoswith 2549
        pop     eax
2550
        jc      ntfsFail
2551
        cmp     eax, [ebp+NTFS.mftSize]
2552
        jnc     .extendMFT
6107 pathoswith 2553
        jmp     .mftRecord
2554
 
2555
.extendBitmapMFT:
2556
        mov     eax, [ebp+NTFS.sectors_per_cluster]
6405 pathoswith 2557
        mov     [ebp+NTFS.cur_offs], eax
6107 pathoswith 2558
        shl     eax, 9
2559
        cmp     [ebp+NTFS.mftBitmapSize], eax
2560
        jnc     ntfsUnsupported
6273 pathoswith 2561
        mov     [ebp+NTFS.cur_iRecord], 0
2562
        mov     [ebp+NTFS.cur_attr], 0xB0
2563
        mov     [ebp+NTFS.cur_size], 0
6107 pathoswith 2564
        call    ntfs_read_attr
2565
        jc      ntfsFail
5954 pathoswith 2566
        mov     eax, [ebp+NTFS.mft_cluster]
2567
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 2568
        cmp     eax, [ebp+NTFS.LastRead]
6019 pathoswith 2569
        jnz     ntfsUnsupported     ; auxiliary record
6107 pathoswith 2570
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2571
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2572
        add     edi, ecx
2573
        mov     eax, ecx
6273 pathoswith 2574
        mov     edx, [ebp+NTFS.attr_offs]
6107 pathoswith 2575
        add     ecx, 8
2576
        mov     [edx+attributeRealSize], ecx
2577
        mov     [edx+initialDataSize], ecx
2578
        shl     eax, 3
6340 pathoswith 2579
        mov     [ebp+NTFS.newRecord], eax
6107 pathoswith 2580
        mov     dword [edi], 1
2581
        mov     dword [edi+4], 0
6273 pathoswith 2582
        mov     [ebp+NTFS.cur_attr], 0x80
6405 pathoswith 2583
        mov     [ebp+NTFS.cur_offs], 0
6107 pathoswith 2584
        call    ntfs_read_attr.newAttribute
2585
        jc      ntfsFail
2586
        mov     [ebp+NTFS.mftBitmapSize], ecx
2587
.extendMFT:
2588
        mov     eax, [ebp+NTFS.mft_cluster]
5954 pathoswith 2589
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 2590
        cmp     eax, [ebp+NTFS.LastRead]
6107 pathoswith 2591
        jnz     ntfsUnsupported     ; auxiliary record
6273 pathoswith 2592
        mov     ecx, [ebp+NTFS.attr_offs]
6107 pathoswith 2593
        mov     eax, [ecx+attributeRealSize]
2594
        mov     edx, [ecx+attributeRealSize+4]
2595
        xor     ax, ax
2596
        add     eax, 10000h
2597
        adc     edx, 0
2598
        push    [ebp+NTFS.fileDataStart]
2599
        push    [ebp+NTFS.fileDataSize]
2600
        call    resizeAttribute
2601
        jc      ntfsErrorPop2
6408 pathoswith 2602
        mov     ebx, [ebp+NTFS.frs_buffer]
2603
        mov     edx, [ebp+NTFS.LastRead]
5954 pathoswith 2604
        call    writeRecord     ; $MFT
2605
        mov     eax, [ebp+NTFS.mftmirr_cluster]
2606
        mul     [ebp+NTFS.sectors_per_cluster]
6408 pathoswith 2607
        mov     ecx, [ebp+NTFS.frs_size]
2608
        shr     ecx, 9
5954 pathoswith 2609
        call    fs_write64_sys  ; $MFTMirr
6405 pathoswith 2610
; update $MFT retrieval information
2611
        mov     edi, [ebp+NTFS.mft_retrieval_end]
2612
        mov     eax, [edi-4]
2613
        add     eax, [edi-8]
2614
        mov     edx, [ebp+NTFS.fileDataSize]
2615
        cmp     eax, [ebp+NTFS.fileDataStart]
2616
        jnz     .newFragment
2617
        add     [edi-8], edx
2618
        jmp     @f
2619
.newFragment:
2620
        lea     eax, [ebp+NTFS.attrlist_buf]
2621
        cmp     eax, edi
2622
        jz      @f
2623
        mov     [edi], edx
2624
        mov     eax, [ebp+NTFS.fileDataStart]
2625
        mov     [edi+4], eax
2626
        add     [ebp+NTFS.mft_retrieval_end], 8
2627
@@:
2628
        mov     eax, [ebp+NTFS.fileDataSize]
2629
        mul     [ebp+NTFS.sectors_per_cluster]
2630
        add     [ebp+NTFS.mftSize], eax
6107 pathoswith 2631
        call    ntfsSpaceClean
2632
        pop     [ebp+NTFS.fileDataSize]
2633
        pop     [ebp+NTFS.fileDataStart]
5954 pathoswith 2634
.mftRecord:
6151 pathoswith 2635
        mov     ecx, [ebp+NTFS.frs_size]
2636
        shr     ecx, 2
5954 pathoswith 2637
        mov     edi, [ebp+NTFS.frs_buffer]
2638
        xor     eax, eax
2639
        rep stosd
6418 pathoswith 2640
        mov     esi, [ebp+NTFS.indexPointer]
2641
        mov     eax, [ebp+NTFS.newRecord]
2642
        mov     [esi+fileRecordReference], eax
2643
        rdtsc
2644
        mov     [esi+fileReferenceReuse], ax
5954 pathoswith 2645
        mov     edi, [ebp+NTFS.frs_buffer]
6019 pathoswith 2646
; record header
6418 pathoswith 2647
        mov     [edi+reuseCounter], ax
6292 pathoswith 2648
        mov     [edi+2ah], ax
6151 pathoswith 2649
        mov     eax, [ebp+NTFS.frs_size]
2650
        mov     [edi+recordAllocatedSize], eax
2651
        shr     eax, 9
2652
        inc     eax
2653
        mov     [edi+updateSequenceSize], al
6292 pathoswith 2654
        shl     eax, 1
2655
        add     eax, 2ah+7
2656
        and     eax, not 7
5954 pathoswith 2657
        mov     dword[edi], 'FILE'
2658
        mov     byte [edi+updateSequenceOffset], 2ah
2659
        mov     byte [edi+hardLinkCounter], 1
2660
        mov     byte [edi+newAttributeID], 3
6292 pathoswith 2661
        mov     [edi+attributeOffset], al
2662
        add     edi, eax
6019 pathoswith 2663
; $StandardInformation
5954 pathoswith 2664
        mov     byte [edi+attributeType], 10h
2665
        mov     byte [edi+sizeWithHeader], 48h
2666
        mov     byte [edi+sizeWithoutHeader], 30h
2667
        mov     byte [edi+attributeOffset], 18h
6420 pathoswith 2668
        mov     cl, 8
2669
        add     esi, fileCreated
2670
        add     edi, 18h
2671
        rep movsd
2672
        add     edi, 16
2673
        mov     esi, [ebp+NTFS.indexPointer]
6019 pathoswith 2674
; $FileName
5954 pathoswith 2675
        mov     byte [edi+attributeType], 30h
2676
        mov     byte [edi+attributeID], 1
6151 pathoswith 2677
        mov     byte [edi+attributeOffset], 18h
2678
        mov     byte [edi+indexedFlag], 1
5954 pathoswith 2679
        mov     cx, [esi+indexRawSize]
2680
        mov     [edi+sizeWithoutHeader], ecx
2681
        mov     cx, [esi+indexAllocatedSize]
2682
        add     ecx, 8
2683
        mov     [edi+sizeWithHeader], ecx
2684
        add     edi, 18h
2685
        add     esi, 16
2686
        sub     ecx, 18h
2687
        shr     ecx, 2
2688
        rep movsd
6080 pathoswith 2689
        mov     byte [edi+sizeWithHeader], 50h
2690
        mov     byte [edi+attributeID], 2
6273 pathoswith 2691
        cmp     [ebp+NTFS.bFolder], 1
6151 pathoswith 2692
        jz      .indexRoot
6019 pathoswith 2693
; $Data
5954 pathoswith 2694
        mov     byte [edi+attributeType], 80h
6151 pathoswith 2695
        mov     eax, [ebp+NTFS.fileDataSize]
2696
        test    eax, eax
2697
        jz      .resident
6405 pathoswith 2698
        mov     esi, [ebp+NTFS.indexPointer]
6080 pathoswith 2699
        dec     eax
2700
        mov     [edi+lastVCN], eax
5954 pathoswith 2701
        mov     byte [edi+nonResidentFlag], 1
2702
        mov     byte [edi+dataRunsOffset], 40h
2703
        mov     eax, [esi+fileAllocatedSize]
2704
        mov     [edi+attributeAllocatedSize], eax
2705
        mov     eax, [esi+fileRealSize]
2706
        mov     [edi+attributeRealSize], eax
2707
        mov     [edi+initialDataSize], eax
6151 pathoswith 2708
        push    edi
6080 pathoswith 2709
        mov     esi, edi
2710
        add     edi, 40h
2711
        call    createMcbEntry
6151 pathoswith 2712
        inc     edi
2713
        jmp     @f
5954 pathoswith 2714
 
6151 pathoswith 2715
.resident:
2716
        mov     ecx, [ebp+NTFS.fileRealSize]
2717
        mov     [edi+sizeWithoutHeader], ecx
5954 pathoswith 2718
        mov     byte [edi+attributeOffset], 18h
6151 pathoswith 2719
        push    edi
6292 pathoswith 2720
        mov     esi, [ebp+NTFS.fileDataBuffer]
6151 pathoswith 2721
        add     edi, 18h
2722
        rep movsb
2723
@@:
2724
        mov     eax, edi
2725
        pop     edi
2726
        sub     eax, edi
2727
        add     eax, 7
2728
        and     eax, not 7
2729
        mov     [edi+sizeWithHeader], eax
2730
        add     edi, eax
5954 pathoswith 2731
        mov     al, 1
6292 pathoswith 2732
        jmp     .end
5954 pathoswith 2733
 
6151 pathoswith 2734
.indexRoot:
5954 pathoswith 2735
        mov     byte [edi+attributeType], 90h
2736
        mov     byte [edi+nameLength], 4
2737
        mov     byte [edi+nameOffset], 18h
2738
        mov     byte [edi+sizeWithoutHeader], 30h
2739
        mov     byte [edi+attributeOffset], 20h
2740
        mov     dword[edi+18h], 490024h     ; unicode $I30
2741
        mov     dword[edi+18h+4], 300033h
6273 pathoswith 2742
        mov     byte [edi+20h+indexedAttributesType], 30h
6019 pathoswith 2743
        mov     byte [edi+20h+collationRule], 1
5954 pathoswith 2744
        mov     eax, [ebp+NTFS.sectors_per_cluster]
6292 pathoswith 2745
        mov     dl, 1
2746
        shl     eax, 8
2747
@@:
2748
        shl     eax, 1
2749
        shl     edx, 1
2750
        cmp     eax, [ebp+NTFS.frs_size]
2751
        jc      @b
2752
        shr     edx, 1
6019 pathoswith 2753
        mov     [edi+20h+indexRecordSize], eax
6292 pathoswith 2754
        mov     [edi+20h+indexRecordSizeClus], dl
6019 pathoswith 2755
        mov     byte [edi+30h+indexOffset], 16
2756
        mov     byte [edi+30h+nodeRealSize], 32
2757
        mov     byte [edi+30h+nodeAllocatedSize], 32
2758
        mov     byte [edi+40h+indexAllocatedSize], 16
2759
        mov     byte [edi+40h+indexFlags], 2
6151 pathoswith 2760
        add     edi, 50h
5954 pathoswith 2761
        mov     al, 3
6292 pathoswith 2762
.end:
6408 pathoswith 2763
        mov     ebx, [ebp+NTFS.frs_buffer]
6151 pathoswith 2764
        mov     dword [edi], -1
2765
        mov     dword [edi+4], 0
2766
        add     edi, 8
6408 pathoswith 2767
        sub     edi, ebx
2768
        mov     [ebx+recordFlags], al
2769
        mov     [ebx+recordRealSize], edi
2770
        mov     edx, [ebp+NTFS.LastRead]
5954 pathoswith 2771
        call    writeRecord
6019 pathoswith 2772
; write MFT bitmap
6340 pathoswith 2773
        mov     eax, [ebp+NTFS.newRecord]
5954 pathoswith 2774
        shr     eax, 3+9
2775
        mov     ebx, eax
2776
        shl     ebx, 9
2777
        add     eax, [ebp+NTFS.mftBitmapLocation]
2778
        add     ebx, [ebp+NTFS.mftBitmapBuffer]
2779
        mov     ecx, 1
2780
        xor     edx, edx
2781
        call    fs_write64_sys
6292 pathoswith 2782
; 5. Write directory node
6408 pathoswith 2783
        mov     ebx, [ebp+NTFS.cur_index_buf]
2784
        mov     edx, [ebp+NTFS.nodeLastRead]
5954 pathoswith 2785
        call    writeRecord
6019 pathoswith 2786
        mov     ebx, [ebp+NTFS.fileRealSize]
2787
ntfsDone:
5954 pathoswith 2788
        mov     esi, [ebp+PARTITION.Disk]
2789
        call    disk_sync
2790
        call    ntfs_unlock
6019 pathoswith 2791
        xor     eax, eax
5954 pathoswith 2792
        ret
2793
 
2794
writeRecord:
6080 pathoswith 2795
; make updateSequence and write to disk
5954 pathoswith 2796
;   in:
6408 pathoswith 2797
; ebx -> record
2798
; edx = partition sector
2799
        mov     esi, ebx
2800
        mov     edi, ebx
5954 pathoswith 2801
        movzx   ecx, word [esi+updateSequenceOffset]
2802
        add     edi, ecx
2803
        mov     ax, [edi]
6080 pathoswith 2804
        inc     ax
2805
        stosw
5954 pathoswith 2806
        mov     cx, [esi+updateSequenceSize]
2807
        dec     ecx
2808
        push    ecx
2809
@@:
2810
        add     esi, 510
2811
        movsw
2812
        mov     [esi-2], ax
2813
        dec     ecx
2814
        jnz     @b
6408 pathoswith 2815
        mov     eax, edx
2816
        xor     edx, edx
5954 pathoswith 2817
        pop     ecx
2818
        jmp     fs_write64_sys
2819
 
6080 pathoswith 2820
createMcbEntry:
2821
;   in:
2822
; [ebp+NTFS.fileDataStart] = position value
2823
; [ebp+NTFS.fileDataSize] = size value
2824
; edi -> destination
2825
; esi -> attribute header
2826
        mov     eax, [ebp+NTFS.fileDataStart]
2827
        xor     edx, edx
2828
        shl     eax, 1
2829
        jnc     @f
2830
        not     eax
2831
@@:
2832
        inc     edx
2833
        shr     eax, 8
2834
        jnz     @b
2835
        mov     eax, [ebp+NTFS.fileDataSize]
2836
        shl     eax, 1
2837
        xor     ecx, ecx
2838
@@:
2839
        inc     ecx
2840
        shr     eax, 8
2841
        jnz     @b
2842
        lea     eax, [edi+edx+1]
2843
        add     eax, ecx
2844
        sub     eax, esi
6151 pathoswith 2845
        sub     eax, [esi+sizeWithHeader]
6080 pathoswith 2846
        jc      @f
2847
        add     word [esi+sizeWithHeader], 8    ; extend attribute
2848
        mov     esi, [ebp+NTFS.frs_buffer]
2849
        mov     eax, [esi+recordRealSize]
2850
        add     eax, 8
2851
        cmp     [esi+recordAllocatedSize], eax
2852
        jc      .end    ; no space in the record
2853
        mov     [esi+recordRealSize], eax
2854
        push    ecx edi
2855
        add     esi, eax
2856
        mov     ecx, esi
2857
        sub     ecx, edi
2858
        sub     ecx, 8
2859
        shr     ecx, 2
2860
        mov     edi, esi
2861
        sub     edi, 4
2862
        sub     esi, 12
2863
        std
2864
        rep movsd
2865
        cld
2866
        pop     edi ecx
2867
@@:
2868
        mov     eax, edx
2869
        shl     eax, 4
2870
        add     eax, ecx
2871
        stosb
2872
        lea     esi, [ebp+NTFS.fileDataSize]
2873
        rep movsb
2874
        lea     esi, [ebp+NTFS.fileDataStart]
2875
        mov     ecx, edx
2876
        rep movsb
6151 pathoswith 2877
        mov     [edi], cl
6080 pathoswith 2878
.end:
2879
        ret
2880
 
2881
resizeAttribute:
2882
;   in:
2883
; [ebp+NTFS.frs_buffer] -> file record
6273 pathoswith 2884
; [ebp+NTFS.attr_offs] -> attribute
6080 pathoswith 2885
; edx:eax = new size
2886
;   out:
6107 pathoswith 2887
; [ebp+NTFS.fileDataSize] = clusters added (positive)
2888
; [ebp+NTFS.fileDataStart] = added block
6080 pathoswith 2889
; CF=1 -> eax = error code
6273 pathoswith 2890
        mov     esi, [ebp+NTFS.attr_offs]
2891
        mov     dword [ebp+NTFS.attr_size], eax
2892
        mov     dword [ebp+NTFS.attr_size+4], edx
6151 pathoswith 2893
        cmp     byte [esi+nonResidentFlag], 0
2894
        jz      .resident
6080 pathoswith 2895
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2896
        shl     ecx, 9
2897
        mov     [esi+attributeRealSize], eax
2898
        mov     [esi+attributeRealSize+4], edx
2899
        mov     [esi+initialDataSize], eax
2900
        mov     [esi+initialDataSize+4], edx
2901
        sub     eax, 1
2902
        sbb     edx, 0
6151 pathoswith 2903
        jc      .makeResident
6080 pathoswith 2904
        div     ecx
2905
        mov     edi, eax
2906
        inc     eax
2907
        mul     ecx
2908
        mov     [esi+attributeAllocatedSize], eax
2909
        mov     [esi+attributeAllocatedSize+4], edx
2910
        mov     ecx, [esi+lastVCN]
2911
        mov     [esi+lastVCN], edi
2912
        movzx   eax, byte [esi+dataRunsOffset]
2913
        sub     edi, ecx
6107 pathoswith 2914
        mov     [ebp+NTFS.fileDataSize], edi
6080 pathoswith 2915
        jz      .done
2916
        jc      .shrinkAttribute
2917
; extend attribute
2918
        xor     edi, edi
2919
        add     esi, eax
2920
        push    edi edi edi edi
2921
@@:
2922
        mov     edx, eax
2923
        mov     eax, esi
2924
        add     edi, [esp+8]
2925
        call    ntfs_decode_mcb_entry
2926
        jc      @b
2927
        mov     [esp+4], edx
2928
        mov     [esp+12], edi
2929
        add     edi, [esp]
2930
        push    edi
2931
        shr     edi, 5
2932
        shl     edi, 2
2933
        push    eax
6273 pathoswith 2934
        cmp     [ebp+NTFS.cur_iRecord], 0
6107 pathoswith 2935
        jz      @f
6080 pathoswith 2936
        cmp     edi, [ebp+NTFS.BitmapStart]
2937
        jc      .err1
6107 pathoswith 2938
@@:
6080 pathoswith 2939
        call    ntfsSpaceAlloc
2940
        jc      .err1
6292 pathoswith 2941
        mov     eax, [ebp+NTFS.fileDataStart]
6080 pathoswith 2942
        pop     edi
2943
        pop     edx
2944
        cmp     edx, eax
2945
        jnz     .newEntry
2946
        pop     edx
2947
        pop     edi
2948
        pop     [ebp+NTFS.fileDataStart]
2949
        mov     [esp], eax
2950
        push    [ebp+NTFS.fileDataSize]
2951
        add     [ebp+NTFS.fileDataSize], edx
2952
        jmp     @f
2953
 
2954
.newEntry:
2955
        add     esp, 12
2956
        pop     edx
2957
        push    eax
2958
        push    [ebp+NTFS.fileDataSize]
2959
        sub     eax, edx
2960
        mov     [ebp+NTFS.fileDataStart], eax
2961
@@:
6273 pathoswith 2962
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 2963
        call    createMcbEntry
6292 pathoswith 2964
        pop     [ebp+NTFS.fileDataSize]
2965
        pop     [ebp+NTFS.fileDataStart]
2966
        movi    eax, ERROR_UNSUPPORTED_FS
6151 pathoswith 2967
.done:
2968
        ret
2969
 
6080 pathoswith 2970
.err1:
2971
        add     esp, 24
2972
        stc
6292 pathoswith 2973
.err2:
6151 pathoswith 2974
        movi    eax, ERROR_DISK_FULL
6080 pathoswith 2975
        ret
2976
 
6292 pathoswith 2977
.err3:
2978
        movi    eax, ERROR_FS_FAIL
2979
        add     esp, 20
2980
        stc
6080 pathoswith 2981
        ret
2982
 
2983
.shrinkAttribute:
2984
        add     ecx, edi
2985
        inc     ecx
2986
        add     esi, eax
2987
        xor     edi, edi
2988
        sub     esp, 20
2989
@@:
2990
        mov     [esp+16], esi
2991
        call    ntfs_decode_mcb_entry
2992
        jnc     .err3
2993
        add     edi, [esp+8]
2994
        sub     ecx, [esp]
2995
        jnc     @b
2996
        mov     ebx, ecx
2997
        add     ecx, [esp]
2998
        mov     eax, [esp+8]
2999
        mov     [ebp+NTFS.fileDataSize], ecx
3000
        mov     [ebp+NTFS.fileDataStart], eax
3001
        push    edi
3002
        add     edi, ecx
3003
        neg     ebx
3004
        call    ntfsSpaceFree
3005
        pop     edi
3006
        jc      .end
3007
@@:
3008
        call    ntfs_decode_mcb_entry
3009
        jnc     .end
3010
        cmp     dword[esp+8], 0
3011
        jz      @b
3012
        add     edi, [esp+8]
3013
        mov     ebx, [esp]
3014
        call    ntfsSpaceFree
3015
        jnc     @b
3016
.end:
3017
        add     esp, 16
3018
        pop     edi
3019
        cmp     [ebp+NTFS.fileDataSize], 0
3020
        jz      @f
6273 pathoswith 3021
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 3022
        call    createMcbEntry
6107 pathoswith 3023
        mov     [ebp+NTFS.fileDataSize], 0
6080 pathoswith 3024
@@:
3025
        ret
3026
 
6151 pathoswith 3027
.resident:
3028
        test    edx, edx
3029
        jnz     .nonResident
3030
        cmp     eax, 8000h
3031
        jnc     .nonResident
3032
        add     ax, [esi+attributeOffset]
3033
        sub     eax, [esi+sizeWithHeader]
3034
        jc      @f
3035
        mov     edi, [ebp+NTFS.frs_buffer]
3036
        mov     ecx, eax
3037
        add     ecx, [edi+recordRealSize]
3038
        cmp     [edi+recordAllocatedSize], ecx
3039
        jc      .nonResident
3040
        add     eax, 7
3041
        and     eax, not 7
3042
        add     [edi+recordRealSize], eax
3043
        add     edi, [edi+recordRealSize]
3044
        add     [esi+sizeWithHeader], eax
3045
        add     esi, [esi+sizeWithHeader]
3046
        mov     ecx, edi
3047
        sub     ecx, esi
3048
        shr     ecx, 2
3049
        sub     edi, 4
3050
        mov     esi, edi
3051
        sub     esi, eax
3052
        std
3053
        rep movsd
3054
        mov     ecx, eax
3055
        shr     ecx, 2
3056
        xor     eax, eax
3057
        rep stosd
3058
        cld
6273 pathoswith 3059
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 3060
@@:
6273 pathoswith 3061
        mov     eax, dword [ebp+NTFS.attr_size]
6151 pathoswith 3062
        mov     [esi+sizeWithoutHeader], eax
3063
        mov     [ebp+NTFS.fileDataSize], 0
3064
        clc
3065
        ret
3066
 
3067
.nonResident:   ; convert resident to non-resident
6273 pathoswith 3068
        mov     eax, dword [ebp+NTFS.attr_size]
6151 pathoswith 3069
        sub     eax, 1
3070
        sbb     edx, 0
3071
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3072
        shl     ecx, 9
3073
        div     ecx
3074
        inc     eax
3075
        mov     [ebp+NTFS.fileDataSize], eax
3076
        mov     edi, [ebp+NTFS.BitmapStart]
3077
        push    ecx
3078
        call    ntfsSpaceAlloc
3079
        pop     ecx
6292 pathoswith 3080
        jc      .err2
6273 pathoswith 3081
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 3082
        xor     eax, eax
3083
        xor     edx, edx
3084
@@:
3085
        add     eax, ecx
3086
        inc     edx
3087
        cmp     eax, [esi+sizeWithoutHeader]
3088
        jc      @b
3089
        push    edx
3090
        push    eax
3091
        stdcall kernel_alloc, eax
3092
        mov     ecx, [esp]
3093
        shr     ecx, 2
3094
        mov     edi, eax
3095
        mov     ebx, eax
3096
        xor     eax, eax
3097
        rep stosd
3098
        mov     al, [esi+attributeOffset]
3099
        mov     ecx, [esi+sizeWithoutHeader]
3100
        add     esi, eax
3101
        mov     edi, ebx
3102
        rep movsb
3103
        mov     eax, [ebp+NTFS.fileDataStart]
3104
        mul     [ebp+NTFS.sectors_per_cluster]
3105
        pop     ecx
3106
        shr     ecx, 9
3107
        call    fs_write64_app
6292 pathoswith 3108
        stdcall kernel_free, ebx
6273 pathoswith 3109
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 3110
        add     esi, [esi+sizeWithHeader]
3111
        mov     ecx, [ebp+NTFS.frs_buffer]
3112
        add     ecx, [ecx+recordRealSize]
3113
        sub     ecx, esi
3114
        shr     ecx, 2
6273 pathoswith 3115
        lea     edi, [ebp+NTFS.bitmap_buf]
6151 pathoswith 3116
        push    ecx
3117
        rep movsd
6273 pathoswith 3118
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 3119
        add     edi, 16
3120
        mov     cl, 6
3121
        xor     eax, eax
3122
        rep stosd
6273 pathoswith 3123
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 3124
        mov     eax, [ebp+NTFS.fileDataSize]
3125
        dec     eax
3126
        mov     [edi+lastVCN], eax
3127
        inc     eax
3128
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3129
        shl     ecx, 9
3130
        mul     ecx
3131
        mov     byte [edi+sizeWithHeader], 50h
3132
        mov     byte [edi+nonResidentFlag], 1
3133
        mov     byte [edi+dataRunsOffset], 40h
3134
        mov     [edi+attributeAllocatedSize], eax
3135
        mov     [edi+attributeAllocatedSize+4], edx
6273 pathoswith 3136
        mov     eax, dword [ebp+NTFS.attr_size]
3137
        mov     edx, dword [ebp+NTFS.attr_size+4]
6151 pathoswith 3138
        mov     [edi+attributeRealSize], eax
3139
        mov     [edi+attributeRealSize+4], edx
3140
        mov     [edi+initialDataSize], eax
3141
        mov     [edi+initialDataSize+4], edx
3142
        mov     esi, edi
3143
        add     edi, 40h
3144
        call    createMcbEntry
3145
        mov     eax, edi
6273 pathoswith 3146
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 3147
        sub     eax, edi
3148
        add     eax, 8
3149
        and     eax, not 7
3150
        mov     [edi+sizeWithHeader], eax
3151
        pop     ecx
6273 pathoswith 3152
        lea     esi, [ebp+NTFS.bitmap_buf]
6151 pathoswith 3153
        add     edi, eax
3154
        rep movsd
3155
        mov     esi, [ebp+NTFS.frs_buffer]
3156
        sub     edi, esi
3157
        mov     [esi+recordRealSize], edi
3158
        pop     edx
3159
        sub     [ebp+NTFS.fileDataSize], edx
3160
        add     [ebp+NTFS.fileDataStart], edx
6292 pathoswith 3161
        ret
6151 pathoswith 3162
 
3163
.makeResident:  ; convert non-resident to empty resident
3164
        movzx   eax, byte [esi+dataRunsOffset]
3165
        mov     byte [esi+nonResidentFlag], 0
3166
        mov     dword [esi+sizeWithoutHeader], 0
3167
        mov     dword [esi+attributeOffset], 18h
3168
        add     esi, eax
3169
        xor     edi, edi
3170
        sub     esp, 16
3171
@@:
3172
        call    ntfs_decode_mcb_entry
3173
        jnc     @f
3174
        cmp     dword[esp+8], 0
3175
        jz      @b
3176
        add     edi, [esp+8]
3177
        mov     ebx, [esp]
3178
        call    ntfsSpaceFree
3179
        jnc     @b
3180
@@:
3181
        add     esp, 16
3182
        mov     [ebp+NTFS.fileDataSize], 0
3183
        ret
3184
 
6107 pathoswith 3185
ntfsSpaceClean:
3186
; clean up to 16 Mb of disk space
3187
;   in:
3188
; [ebp+NTFS.fileDataStart] = block to clean
3189
; [ebp+NTFS.fileDataSize] = block size
3190
        mov     eax, [ebp+NTFS.fileDataSize]
3191
        test    eax, eax
3192
        jz      @f
3193
        mul     [ebp+NTFS.sectors_per_cluster]
3194
        cmp     eax, 8001h
3195
        jnc     @f
3196
        push    eax
3197
        shl     eax, 9
3198
        stdcall kernel_alloc, eax
3199
        pop     ecx
3200
        test    eax, eax
3201
        jz      @f
3202
        push    ecx
3203
        shl     ecx, 7
3204
        mov     edi, eax
3205
        mov     ebx, eax
3206
        xor     eax, eax
3207
        rep stosd
3208
        mov     eax, [ebp+NTFS.fileDataStart]
3209
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 3210
        mov     [ebp+NTFS.LastRead], eax
6107 pathoswith 3211
        pop     ecx
3212
        call    fs_write64_app
3213
        stdcall kernel_free, ebx
3214
@@:
3215
        ret
3216
 
6080 pathoswith 3217
ntfsSpaceAlloc:
6292 pathoswith 3218
; allocate disk space
6080 pathoswith 3219
;   in:
3220
; edi = offset in bitmap to start search from
3221
; [ebp+NTFS.fileDataSize] = block size in clusters
3222
;   out:
6292 pathoswith 3223
; [ebp+NTFS.fileDataStart] = allocated block starting cluster
6080 pathoswith 3224
; CF=1 -> disk full
6292 pathoswith 3225
        push    eax
6080 pathoswith 3226
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3227
        add     edi, ecx
3228
        add     ecx, [ebp+NTFS.BitmapSize]
3229
        sub     ecx, edi
3230
        jnc     @f
3231
        call    bitmapBuffering
3232
        shl     ecx, 2
3233
@@:
3234
        shr     ecx, 2
3235
        mov     eax, [ebp+NTFS.fileDataSize]
3236
        shr     eax, 5
3237
        jz      .small
6292 pathoswith 3238
        mov     ebx, eax    ; bitmap dwords
6080 pathoswith 3239
.start:
3240
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3241
        add     ecx, [ebp+NTFS.BitmapSize]
3242
        sub     ecx, edi
3243
        shr     ecx, 2
3244
@@:
3245
        xor     eax, eax
3246
        repnz scasd         ; search for empty dword
3247
        jz      @f
3248
        call    bitmapBuffering
3249
        jmp     @b
3250
@@:
6292 pathoswith 3251
        cmp     ecx, ebx
6080 pathoswith 3252
        jnc     @f
3253
        call    bitmapBuffering
3254
        jmp     @b
3255
@@:
3256
        sub     edi, 4
6292 pathoswith 3257
        mov     ecx, ebx
6080 pathoswith 3258
        mov     esi, edi
3259
        xor     eax, eax
3260
        repz scasd          ; check following dwords
3261
        jnz     .start
3262
        sub     esi, 4
3263
        mov     eax, [esi]
3264
        xor     edx, edx
3265
        bsr     edx, eax
3266
        inc     edx
3267
        push    edx         ; starting bit
3268
        push    esi         ; starting dword
3269
        add     esi, 4
3270
        neg     edx
3271
        add     edx, 32
3272
        mov     eax, [ebp+NTFS.fileDataSize]
3273
        sub     eax, edx
3274
        mov     edx, eax
3275
        shr     eax, 5
3276
        shl     eax, 2
3277
        add     esi, eax
3278
        mov     eax, [esi]
3279
        bsf     ecx, eax    ; check last dword
3280
        jz      .done
3281
        and     edx, 31
3282
        cmp     ecx, edx
3283
        jnc     .done
3284
        add     esp, 8
3285
        jmp     .start
3286
 
3287
.small:     ; less than 32 clusters
3288
        mov     eax, -1
3289
        repz scasd          ; search for zero bits
3290
        test    ecx, ecx
3291
        jnz     @f
3292
        call    bitmapBuffering
3293
        jmp     .small
3294
@@:
3295
        sub     edi, 4
3296
        mov     eax, [edi]
3297
        not     eax
3298
@@:
6292 pathoswith 3299
        bsf     ebx, eax    ; first 0
6080 pathoswith 3300
        jz      .again
3301
        not     eax
3302
        shr     eax, cl
3303
        shl     eax, cl
3304
        bsf     edx, eax    ; next 1
3305
        jz      @f
6292 pathoswith 3306
        sub     edx, ebx
6080 pathoswith 3307
        cmp     edx, [ebp+NTFS.fileDataSize]
3308
        jnc     .got        ; fits inside
6292 pathoswith 3309
        bsf     ebx, eax
6080 pathoswith 3310
        not     eax
3311
        shr     eax, cl
3312
        shl     eax, cl
3313
        jmp     @b
3314
@@:         ; next dword
3315
        mov     eax, [edi+4]
3316
        bsf     edx, eax
3317
        jz      .got        ; empty
3318
        add     edx, 32
6292 pathoswith 3319
        sub     edx, ebx
6080 pathoswith 3320
        cmp     edx, [ebp+NTFS.fileDataSize]
3321
        jnc     .got        ; share between dwords
3322
.again:
3323
        add     edi, 4
3324
        jmp     .small
3325
 
3326
.got:
6292 pathoswith 3327
        push    ebx         ; starting bit
6080 pathoswith 3328
        push    edi         ; starting dword
3329
.done:      ; mark space
3330
        mov     ecx, [esp+4]
3331
        cmp     ecx, 32
3332
        jc      @f
3333
        xor     ecx, ecx
3334
        add     dword [esp], 4
3335
        mov     [esp+4], ecx
3336
@@:
3337
        mov     edi, [esp]
3338
        xor     eax, eax
3339
        dec     eax
3340
        shr     eax, cl
3341
        shl     eax, cl
3342
        neg     ecx
3343
        add     ecx, 32
3344
        sub     ecx, [ebp+NTFS.fileDataSize]
3345
        jc      @f
3346
        shl     eax, cl     ; fits inside dword
3347
        shr     eax, cl
3348
        or      [edi], eax
3349
        jmp     .end
3350
 
3351
@@:
3352
        or      [edi], eax
3353
        neg     ecx
3354
        push    ecx
3355
        shr     ecx, 5
3356
        add     edi, 4
3357
        xor     eax, eax
3358
        dec     eax
3359
        rep stosd
3360
        pop     ecx
3361
        and     ecx, 31
3362
        shr     eax, cl
3363
        shl     eax, cl
3364
        not     eax
3365
        or      [edi], eax
3366
.end:
3367
        pop     eax
6292 pathoswith 3368
        pop     ecx
6080 pathoswith 3369
        sub     eax, [ebp+NTFS.BitmapBuffer]
3370
        shl     eax, 3
6292 pathoswith 3371
        add     eax, ecx
3372
        pop     ecx
3373
        mov     ecx, [ebp+NTFS.fileDataSize]
3374
        mov     [ebp+NTFS.fileDataStart], eax
3375
        add     ecx, eax
3376
        add     ecx, 4095
3377
        shr     ecx, 3+9
3378
        shr     eax, 3+9
3379
        sub     ecx, eax
3380
        mov     ebx, eax
3381
        shl     ebx, 9
3382
        add     eax, [ebp+NTFS.BitmapLocation]
3383
        add     ebx, [ebp+NTFS.BitmapBuffer]
3384
        xor     edx, edx
3385
        jmp     fs_write64_app
6080 pathoswith 3386
 
3387
ntfsSpaceFree:
3388
; free disk space
3389
;   in:
3390
; edi = starting cluster
3391
; ebx = size in clusters
3392
        mov     eax, edi
3393
        add     eax, ebx
3394
        shr     eax, 3
3395
        inc     eax
3396
        cmp     eax, [ebp+NTFS.BitmapSize]
3397
        jc      @f
3398
        add     eax, [ebp+NTFS.BitmapBuffer]
3399
        push    edi
3400
        mov     edi, eax
3401
        call    bitmapBuffering
3402
        pop     edi
3403
@@:
3404
        push    edi
3405
        mov     ecx, edi
3406
        shr     edi, 5
3407
        shl     edi, 2
3408
        add     edi, [ebp+NTFS.BitmapBuffer]
3409
        and     ecx, 31
3410
        xor     eax, eax
3411
        dec     eax
3412
        shr     eax, cl
3413
        shl     eax, cl
3414
        neg     ecx
3415
        add     ecx, 32
3416
        sub     ecx, ebx
3417
        jc      @f
3418
        shl     eax, cl     ; fits inside dword
3419
        shr     eax, cl
3420
        not     eax
3421
        and     [edi], eax
3422
        jmp     .writeBitmap
3423
 
3424
@@:
3425
        not     eax
3426
        and     [edi], eax
3427
        neg     ecx
3428
        push    ecx
3429
        shr     ecx, 5
3430
        add     edi, 4
3431
        xor     eax, eax
3432
        rep stosd
3433
        pop     ecx
3434
        and     ecx, 31
3435
        dec     eax
3436
        shr     eax, cl
3437
        shl     eax, cl
3438
        and     [edi], eax
3439
.writeBitmap:
3440
        pop     eax
3441
        mov     edi, eax
3442
        lea     ecx, [eax+ebx+4095]
3443
        shr     eax, 3+9
3444
        shr     ecx, 3+9
3445
        sub     ecx, eax
3446
        mov     ebx, eax
3447
        shl     ebx, 9
3448
        add     eax, [ebp+NTFS.BitmapLocation]
3449
        add     ebx, [ebp+NTFS.BitmapBuffer]
3450
        xor     edx, edx
3451
        jmp     fs_write64_app
3452
 
5954 pathoswith 3453
bitmapBuffering:
3454
; Extend BitmapBuffer and read next 32kb of bitmap
3455
; Warning: $Bitmap fragmentation is not foreseen
6080 pathoswith 3456
; in: edi -> position in bitmap buffer
3457
; out: ecx = number of buffered dwords left
5954 pathoswith 3458
        push    ebx
3459
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3460
        cmp     eax, [ebp+NTFS.BitmapSize]
3461
        jz      .end
3462
        stdcall alloc_pages, 8
3463
        test    eax, eax
3464
        jz      .end
3465
        add     eax, 3
3466
        mov     ebx, [ebp+NTFS.BitmapBuffer]
3467
        add     ebx, [ebp+NTFS.BitmapSize]
3468
        push    ebx
3469
        mov     ecx, 8
3470
        call    commit_pages
3471
        mov     eax, [ebp+NTFS.BitmapSize]
3472
        shr     eax, 9
3473
        add     eax, [ebp+NTFS.BitmapLocation]
3474
        pop     ebx
3475
        mov     ecx, 64
3476
        xor     edx, edx
3477
        call    fs_read64_app
3478
        test    eax, eax
3479
        jnz     .err
3480
        add     [ebp+NTFS.BitmapSize], 8000h
3481
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3482
        cmp     eax, [ebp+NTFS.BitmapSize]
3483
        jnc     @f
3484
        mov     [ebp+NTFS.BitmapSize], eax
3485
@@:
6080 pathoswith 3486
        pop     ebx
3487
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3488
        add     ecx, [ebp+NTFS.BitmapSize]
6019 pathoswith 3489
        sub     ecx, edi
6080 pathoswith 3490
        jc      bitmapBuffering
5954 pathoswith 3491
        shr     ecx, 2
3492
        ret
3493
 
3494
.err:
3495
        mov     eax, [ebp+NTFS.BitmapBuffer]
3496
        add     eax, [ebp+NTFS.BitmapSize]
3497
        mov     ecx, 8
3498
        call    release_pages
3499
.end:
6292 pathoswith 3500
        add     esp, 12     ; ret
6080 pathoswith 3501
        stc
3502
        ret
5954 pathoswith 3503
 
2288 clevermous 3504
;----------------------------------------------------------------
5994 pathoswith 3505
ntfs_WriteFile:
3506
        cmp     byte [esi], 0
3507
        jnz     @f
2288 clevermous 3508
        xor     ebx, ebx
5994 pathoswith 3509
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 3510
        ret
5994 pathoswith 3511
@@:
3512
        call    ntfs_lock
3513
        stdcall ntfs_find_lfn, [esp+4]
6019 pathoswith 3514
        jc      ntfsNotFound
6273 pathoswith 3515
        cmp     [ebp+NTFS.cur_iRecord], 16
6019 pathoswith 3516
        jc      ntfsDenied
6420 pathoswith 3517
        test    dword [eax+fileFlags], 10000001h
3518
        jnz     ntfsDenied
6273 pathoswith 3519
        cmp     [ebp+NTFS.fragmentCount], 1
6080 pathoswith 3520
        jnz     ntfsUnsupported     ; record fragmented
6151 pathoswith 3521
; edit directory node
6080 pathoswith 3522
        mov     edi, [ebp+NTFS.cur_index_buf]
3523
        cmp     dword [edi], 'INDX'
3524
        jz      @f
3525
        mov     esi, [ebp+NTFS.frs_buffer]
3526
        mov     ecx, [esi+recordRealSize]
3527
        shr     ecx, 2
3528
        rep movsd
6273 pathoswith 3529
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 3530
        mov     cl, [esi+attributeOffset]
3531
        sub     esi, [ebp+NTFS.frs_buffer]
6151 pathoswith 3532
        add     eax, ecx
3533
        add     eax, esi
6080 pathoswith 3534
@@:
6420 pathoswith 3535
        mov     edi, eax
3536
        mov     eax, [ebx+4]
6151 pathoswith 3537
        mov     edx, [ebx+8]
6420 pathoswith 3538
        add     eax, [ebx+12]
6151 pathoswith 3539
        adc     edx, 0
6420 pathoswith 3540
        mov     [edi+fileRealSize], eax
3541
        mov     [edi+fileRealSize+4], edx
3542
        push    edx eax ebx
3543
        call    ntfsGetTime
3544
        mov     [edi+fileModified], eax
3545
        mov     [edi+fileModified+4], edx
3546
        mov     [edi+recordModified], eax
3547
        mov     [edi+recordModified+4], edx
3548
        mov     [edi+fileAccessed], eax
3549
        mov     [edi+fileAccessed+4], edx
3550
        pop     ebx ecx edx
6273 pathoswith 3551
        mov     eax, [ebp+NTFS.LastRead]
6151 pathoswith 3552
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 3553
        mov     [ebp+NTFS.cur_attr], 0x80
3554
        mov     [ebp+NTFS.cur_offs], 0
3555
        mov     [ebp+NTFS.cur_size], 0
5994 pathoswith 3556
        call    ntfs_read_attr
6080 pathoswith 3557
        jc      ntfsFail
6420 pathoswith 3558
        mov     esi, edi
3559
        mov     edi, [ebp+NTFS.frs_buffer]
3560
        cmp     word [edi+baseRecordReuse], 0
3561
        jnz     ntfsUnsupported     ; auxiliary record
3562
        mov     al, [edi+attributeOffset]
3563
        add     edi, eax
3564
        mov     al, [edi+attributeOffset]
3565
        add     edi, eax
6151 pathoswith 3566
        mov     eax, ecx
6420 pathoswith 3567
        mov     ecx, 6
3568
        add     esi, fileModified
3569
        add     edi, 8
3570
        rep movsd
6273 pathoswith 3571
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3572
        cmp     word [ecx+attributeFlags], 0
3573
        jnz     ntfsUnsupported
3574
        push    ebx
3575
        cmp     byte [ecx+nonResidentFlag], 0
3576
        jz      .resizeAttribute
5994 pathoswith 3577
        cmp     edx, [ecx+attributeRealSize+4]
6080 pathoswith 3578
        jc      .writeNode
3579
        jnz     .resizeAttribute
5994 pathoswith 3580
        cmp     [ecx+attributeRealSize], eax
6080 pathoswith 3581
        jnc     .writeNode
3582
.resizeAttribute:
3583
        call    resizeAttribute
6107 pathoswith 3584
        jc      ntfsErrorPop
6273 pathoswith 3585
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3586
        cmp     byte [ecx+nonResidentFlag], 1
3587
        jz      @f
3588
        mov     ebx, [esp]
3589
        movzx   edi, byte [ecx+attributeOffset]
3590
        add     edi, ecx
3591
        add     edi, [ebx+4]
3592
        mov     ecx, [ebx+12]
3593
        mov     esi, [ebx+16]
3594
        rep movsb
3595
@@:
6408 pathoswith 3596
        mov     ebx, [ebp+NTFS.frs_buffer]
3597
        mov     edx, [ebp+NTFS.mftLastRead]
6080 pathoswith 3598
        call    writeRecord     ; file
3599
        call    ntfs_restore_usa_frs
3600
.writeNode:
6408 pathoswith 3601
        mov     ebx, [ebp+NTFS.cur_index_buf]
3602
        mov     edx, [ebp+NTFS.nodeLastRead]
6080 pathoswith 3603
        call    writeRecord     ; directory
3604
        pop     ebx
6273 pathoswith 3605
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3606
        cmp     byte [ecx+nonResidentFlag], 0
3607
        jz      .done
3608
        mov     ecx, [ebx+12]
3609
        test    ecx, ecx
3610
        jz      .done
5994 pathoswith 3611
        mov     eax, [ebx+4]
3612
        mov     edx, [ebx+8]
3613
        mov     esi, [ebx+16]
3614
        shrd    eax, edx, 9
3615
        test    dword[ebx+4], 1FFh
3616
        jz      .aligned
6273 pathoswith 3617
        mov     [ebp+NTFS.cur_offs], eax
3618
        mov     [ebp+NTFS.cur_size], 1
3619
        lea     edi, [ebp+NTFS.bitmap_buf]
3620
        mov     [ebp+NTFS.cur_buf], edi
5994 pathoswith 3621
        call    ntfs_read_attr.continue
6019 pathoswith 3622
        jc      ntfsDevice
5994 pathoswith 3623
        mov     eax, [ebx+4]
3624
        and     eax, 1FFh
3625
        add     edi, eax
6273 pathoswith 3626
        sub     eax, [ebp+NTFS.cur_read]
5994 pathoswith 3627
        neg     eax
3628
        push    ecx
3629
        cmp     ecx, eax
3630
        jb      @f
3631
        mov     ecx, eax
3632
@@:
3633
        sub     [esp], ecx
3634
        rep movsb
3635
        push    ebx
6273 pathoswith 3636
        mov     eax, [ebp+NTFS.LastRead]
3637
        lea     ebx, [ebp+NTFS.bitmap_buf]
5994 pathoswith 3638
        mov     ecx, 1
3639
        xor     edx, edx
3640
        call    fs_write64_app
3641
        pop     ebx
3642
        pop     ecx
3643
        test    ecx, ecx
6151 pathoswith 3644
        jz      .done
5994 pathoswith 3645
        mov     eax, [ebx+4]
3646
        mov     edx, [ebx+8]
3647
        shrd    eax, edx, 9
3648
        inc     eax
3649
.aligned:
3650
        push    ecx
3651
        shr     ecx, 9
6273 pathoswith 3652
        mov     [ebp+NTFS.cur_offs], eax
3653
        mov     [ebp+NTFS.cur_size], ecx
3654
        mov     [ebp+NTFS.cur_buf], esi
5994 pathoswith 3655
        add     eax, ecx
3656
        push    eax
6273 pathoswith 3657
        mov     [ebp+NTFS.bWriteAttr], 1
5994 pathoswith 3658
        call    ntfs_read_attr.continue
6273 pathoswith 3659
        mov     [ebp+NTFS.bWriteAttr], 0
3660
        pop     [ebp+NTFS.cur_offs]
5994 pathoswith 3661
        pop     ecx
6019 pathoswith 3662
        jc      ntfsDevice
5994 pathoswith 3663
        and     ecx, 1FFh
6151 pathoswith 3664
        jz      .done
6273 pathoswith 3665
        add     esi, [ebp+NTFS.cur_read]
3666
        mov     [ebp+NTFS.cur_size], 1
3667
        lea     edi, [ebp+NTFS.bitmap_buf]
3668
        mov     [ebp+NTFS.cur_buf], edi
5994 pathoswith 3669
        call    ntfs_read_attr.continue
6019 pathoswith 3670
        jc      ntfsDevice
5994 pathoswith 3671
        rep movsb
3672
        push    ebx
6273 pathoswith 3673
        mov     eax, [ebp+NTFS.LastRead]
3674
        lea     ebx, [ebp+NTFS.bitmap_buf]
5994 pathoswith 3675
        mov     ecx, 1
3676
        xor     edx, edx
3677
        call    fs_write64_app
3678
        pop     ebx
6151 pathoswith 3679
.done:
5994 pathoswith 3680
        mov     ebx, [ebx+12]
6019 pathoswith 3681
        jmp     ntfsDone
3682
 
3683
;----------------------------------------------------------------
3684
ntfs_Delete:
3685
        cmp     byte [esi], 0
3686
        jnz     @f
6418 pathoswith 3687
        xor     ebx, ebx
6019 pathoswith 3688
        movi    eax, ERROR_ACCESS_DENIED
5994 pathoswith 3689
        ret
6401 pathoswith 3690
 
6019 pathoswith 3691
@@:
3692
        call    ntfs_lock
3693
        stdcall ntfs_find_lfn, [esp+4]
3694
        jc      ntfsNotFound
6273 pathoswith 3695
        cmp     [ebp+NTFS.cur_iRecord], 16
6019 pathoswith 3696
        jc      ntfsDenied
6420 pathoswith 3697
        test    byte [eax+fileFlags], 1
3698
        jnz     ntfsDenied
6273 pathoswith 3699
        cmp     [ebp+NTFS.fragmentCount], 1
6019 pathoswith 3700
        jnz     ntfsUnsupported     ; record fragmented
6418 pathoswith 3701
        mov     ebx, [eax+directoryRecordReference]
3702
        mov     [ebp+NTFS.newRecord], ebx
3703
        mov     bx, [eax+fileReferenceReuse]
3704
        mov     [ebp+NTFS.indexPointer], esi
3705
        mov     eax, [ebp+NTFS.cur_iRecord]
3706
        shr     eax, 3
3707
        cmp     eax, [ebp+NTFS.mftBitmapSize]
6019 pathoswith 3708
        jnc     ntfsUnsupported
6418 pathoswith 3709
; examine file record
3710
        mov     [ebp+NTFS.cur_attr], 0x80   ; file?
3711
        mov     [ebp+NTFS.cur_offs], 0
3712
        mov     [ebp+NTFS.cur_size], 0
3713
        call    ntfs_read_attr
3714
        jnc     @f
3715
        xor     eax, eax
3716
        push    ebx eax eax eax eax
3717
        mov     [esp+12], esp
3718
        push    eax
3719
        mov     ebx, esp
3720
        mov     [ebp+NTFS.cur_attr], 0x90   ; folder?
3721
        call    ntfs_ReadFolder.doit
3722
        mov     edx, [esp+12]
3723
        add     esp, 20
3724
        pop     ebx
3725
        test    eax, eax
3726
        jnz     .ret
3727
        cmp     edx, 2
3728
        jnz     ntfsDenied      ; folder is not empty
6401 pathoswith 3729
        mov     [ebp+NTFS.cur_attr], 0xA0
6418 pathoswith 3730
        mov     [ebp+NTFS.cur_offs], 0
3731
        mov     [ebp+NTFS.cur_size], 0
6401 pathoswith 3732
        call    ntfs_read_attr.newAttribute
6418 pathoswith 3733
        jc      .deleteFileRecord
6401 pathoswith 3734
@@:
6418 pathoswith 3735
        mov     esi, [ebp+NTFS.frs_buffer]
3736
        cmp     word [esi+baseRecordReuse], 0
3737
        jnz     ntfsUnsupported     ; auxiliary record
3738
        cmp     word [esi+reuseCounter], bx
3739
        jnz     .backToIndex        ; broken index
6420 pathoswith 3740
        test    byte [esi+recordFlags], 1
6418 pathoswith 3741
        jz      .writeBitmapMFT     ; record deleted
3742
        cmp     byte [esi+hardLinkCounter], 3
3743
        jnc     ntfsUnsupported
3744
        mov     esi, [ebp+NTFS.attr_offs]
3745
        cmp     byte [esi+nonResidentFlag], 0
3746
        jz      .deleteFileRecord
3747
        movzx   eax, byte [esi+dataRunsOffset]
6401 pathoswith 3748
        add     esi, eax
6418 pathoswith 3749
        xor     edi, edi
3750
        sub     esp, 16
3751
@@:
3752
        call    ntfs_decode_mcb_entry
3753
        jnc     @f
3754
        cmp     dword[esp+8], 0
6401 pathoswith 3755
        jz      @b
6418 pathoswith 3756
        add     edi, [esp+8]
3757
        mov     ebx, [esp]
3758
        call    ntfsSpaceFree
3759
        jnc     @b
3760
@@:
3761
        add     esp, 16
3762
.deleteFileRecord:
3763
        mov     ebx, [ebp+NTFS.frs_buffer]
3764
        mov     byte [ebx+recordFlags], 0
3765
        mov     edx, [ebp+NTFS.mftLastRead]
3766
        call    writeRecord
3767
.writeBitmapMFT:
3768
        mov     eax, [ebp+NTFS.cur_iRecord]
3769
        mov     ecx, eax
3770
        shr     eax, 3
3771
        and     ecx, 7
3772
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
3773
        btr     [edi+eax], ecx
3774
        shr     eax, 9
3775
        mov     ebx, eax
3776
        shl     ebx, 9
3777
        add     eax, [ebp+NTFS.mftBitmapLocation]
3778
        add     ebx, edi
3779
        mov     ecx, 1
3780
        xor     edx, edx
3781
        call    fs_write64_sys
3782
.backToIndex:
3783
        mov     eax, [ebp+NTFS.newRecord]
3784
        mov     [ebp+NTFS.cur_iRecord], eax
3785
        mov     esi, [ebp+NTFS.indexPointer]
3786
        stdcall ntfs_find_lfn.doit2, 0
3787
        jc      ntfsFail
3788
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3789
        mov     byte [ebx], 0
3790
        mov     ebx, [ebp+NTFS.LastRead]
3791
        mov     [ebp+NTFS.nodeLastRead], ebx
3792
        xor     ebx, ebx
3793
        test    byte [eax+indexFlags], 1
3794
        jz      .deleteIndex    ; no subnode
3795
        mov     edi, eax
3796
        call    .findSubindex
3797
        jc      ntfsFail
6401 pathoswith 3798
        movzx   edx, word [edi+indexAllocatedSize]
6418 pathoswith 3799
        test    esi, esi
3800
        jz      @f
6401 pathoswith 3801
        sub     edx, eax
3802
        sub     edx, 8
6418 pathoswith 3803
@@:
3804
        mov     eax, edi
6401 pathoswith 3805
        mov     ebx, esi
3806
        jmp     @f
3807
 
3808
.deleteIndex:
3809
        movzx   edx, word [eax+indexAllocatedSize]
6107 pathoswith 3810
        mov     ecx, [eax+fileRecordReference]
3811
        cmp     [eax+edx+fileRecordReference], ecx
3812
        jnz     @f
3813
        add     dx, [eax+edx+indexAllocatedSize]
3814
@@:
6019 pathoswith 3815
        mov     edi, [ebp+NTFS.cur_index_buf]
3816
        cmp     dword [edi], 'INDX'
3817
        jz      .indexRecord
6418 pathoswith 3818
        sub     eax, edi
6401 pathoswith 3819
        mov     edi, [ebp+NTFS.indexRoot]
6019 pathoswith 3820
        sub     [edi+sizeWithHeader], edx
3821
        sub     [edi+sizeWithoutHeader], edx
6418 pathoswith 3822
        movzx   ecx, byte [edi+attributeOffset]
6019 pathoswith 3823
        add     edi, ecx
6418 pathoswith 3824
        add     eax, edi
6273 pathoswith 3825
        sub     [edi+rootNode+nodeRealSize], edx
3826
        sub     [edi+rootNode+nodeAllocatedSize], edx
6418 pathoswith 3827
        mov     edi, [ebp+NTFS.frs_buffer]
3828
        sub     [edi+recordRealSize], edx
3829
        mov     ecx, [edi+recordRealSize]
3830
        cmp     [edi+recordAllocatedSize], ecx
6019 pathoswith 3831
        jmp     @f
2288 clevermous 3832
 
6019 pathoswith 3833
.indexRecord:
6401 pathoswith 3834
        add     edi, recordNode
3835
        sub     [edi+nodeRealSize], edx
3836
        mov     ecx, [edi+nodeRealSize]
3837
        cmp     [edi+nodeAllocatedSize], ecx
6418 pathoswith 3838
@@:
6401 pathoswith 3839
        jc      ntfsUnsupported
6418 pathoswith 3840
        add     ecx, edi
6019 pathoswith 3841
        sub     ecx, eax
3842
        mov     esi, eax
3843
        add     esi, edx
3844
        mov     edi, eax
6401 pathoswith 3845
        test    edx, edx
3846
        jns     @f
3847
        neg     edx
3848
        add     edx, ecx
3849
        sub     edx, 4
3850
        add     esi, edx
3851
        add     edi, edx
3852
        std
3853
@@:
3854
        jz      @f
3855
        shr     ecx, 2
6019 pathoswith 3856
        rep movsd
6401 pathoswith 3857
        cld
3858
@@:
3859
        test    ebx, ebx
6418 pathoswith 3860
        jz      .done
6401 pathoswith 3861
; copy index from the subnode to replace deleted pointing index
3862
        movzx   ecx, word [ebx+indexAllocatedSize]
3863
        mov     edx, ecx
6418 pathoswith 3864
        test    byte [ebx+indexFlags], 1
3865
        jz      @f
3866
        sub     ecx, 8
3867
        movzx   edi, word [ebx+edx+indexAllocatedSize]
3868
        add     edi, edx
3869
        mov     esi, [ebx+ecx]
3870
        mov     [ebx+edi-8], esi
3871
        mov     [ebx+indexAllocatedSize], cx
3872
@@:
6401 pathoswith 3873
        shr     ecx, 2
3874
        mov     esi, ebx
3875
        mov     edi, eax
3876
        rep movsd
3877
        add     word [eax+indexAllocatedSize], 8
3878
        mov     byte [eax+indexFlags], 1
6418 pathoswith 3879
        mov     edi, [ebp+NTFS.secondIndexBuffer]
6401 pathoswith 3880
        mov     eax, ebx
3881
        xor     ebx, ebx
3882
        jmp     .indexRecord
3883
 
6418 pathoswith 3884
.done:
6408 pathoswith 3885
        mov     ebx, [ebp+NTFS.frs_buffer]
6418 pathoswith 3886
        mov     edx, [ebp+NTFS.rootLastRead]
6019 pathoswith 3887
        call    writeRecord
6408 pathoswith 3888
        mov     ebx, [ebp+NTFS.cur_index_buf]
6418 pathoswith 3889
        cmp     dword [ebx], 'INDX'
3890
        jnz     @f
6408 pathoswith 3891
        mov     edx, [ebp+NTFS.nodeLastRead]
6401 pathoswith 3892
        call    writeRecord
6418 pathoswith 3893
@@:
6408 pathoswith 3894
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3895
        cmp     byte [ebx], 0
6401 pathoswith 3896
        jz      ntfsDone
6418 pathoswith 3897
        mov     edx, [ebp+NTFS.LastRead]
6019 pathoswith 3898
        call    writeRecord
6080 pathoswith 3899
        jmp     ntfsDone
6019 pathoswith 3900
 
6418 pathoswith 3901
.findSubindex:
3902
; in: eax -> index
3903
;   out:
3904
; CF=1 -> error
3905
; esi=0 -> subnode deleted
3906
; esi -> replacement index
3907
; eax = index effective size
3908
        movzx   edx, word [eax+indexAllocatedSize]
3909
        mov     eax, [eax+edx-8]
3910
        mov     edx, [ebp+NTFS.cur_size]
3911
        push    edx
3912
        cmp     edx, [ebp+NTFS.cur_subnode_size]
3913
        jz      @f
3914
        mul     [ebp+NTFS.sectors_per_cluster]
3915
@@:
3916
        mov     [ebp+NTFS.cur_attr], 0xA0
3917
        mov     [ebp+NTFS.cur_offs], eax
3918
        push    eax
3919
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3920
        mov     esi, ebx
3921
        mov     [ebp+NTFS.cur_buf], ebx
3922
        call    ntfs_read_attr.newAttribute
3923
        pop     [ebp+NTFS.cur_offs]
3924
        pop     eax
3925
        jc      .ret
3926
        cmp     dword [esi], 'INDX'
3927
        stc
3928
        jnz     .ret
3929
        mov     [ebp+NTFS.cur_size], eax
3930
        shl     eax, 9
3931
        call    ntfs_restore_usa
3932
        jc      .ret
3933
        add     esi, recordNode
3934
        add     esi, [esi+indexOffset]
3935
        test    byte [esi+indexFlags], 2
3936
        jnz     .emptyNode
3937
        cmp     [ebp+NTFS.fragmentCount], 1
3938
        stc
3939
        jnz     .ret    ; record fragmented
3940
        xor     eax, eax
3941
@@:
3942
        add     esi, eax
3943
        mov     ax, [esi+indexAllocatedSize]
3944
        test    byte [esi+eax+indexFlags], 2
3945
        jz      @b
3946
        test    byte [esi+indexFlags], 1
3947
        jz      .ret
3948
        add     eax, esi
3949
        push    esi
3950
        push    [ebp+NTFS.cur_offs]
3951
        call    .findSubindex
3952
        pop     [ebp+NTFS.cur_offs]
3953
        pop     edx
3954
        jc      .ret
3955
        test    esi, esi
3956
        jnz     .ret
3957
        mov     esi, edx
3958
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3959
        mov     [ebp+NTFS.cur_buf], ebx
3960
        push    [ebp+NTFS.cur_size]
3961
        call    ntfs_read_attr.continue
3962
        pop     eax
3963
        jc      .ret
3964
        shl     eax, 9
3965
        call    ntfs_restore_usa
3966
        jc      .ret
3967
        movzx   eax, word [esi+indexAllocatedSize]
3968
        sub     eax, 8
3969
.ret:
3970
        ret
3971
 
3972
.emptyNode:
3973
        test    byte [esi+indexFlags], 1
3974
        jz      @f
3975
        mov     eax, esi
3976
        push    [ebp+NTFS.cur_offs]
3977
        call    .findSubindex
3978
        pop     [ebp+NTFS.cur_offs]
3979
        jc      .ret
3980
        test    esi, esi
3981
        jnz     .ret
3982
@@:         ; delete node
3983
        mov     esi, [ebp+NTFS.attr_offs]
3984
        add     esi, [esi+sizeWithHeader]
3985
        cmp     byte [esi], 0xB0
3986
        stc
3987
        jnz     .ret
3988
        movzx   eax, byte [esi+attributeOffset]
3989
        add     esi, eax
3990
        mov     eax, [ebp+NTFS.cur_offs]
3991
        xor     edx, edx
3992
        div     [ebp+NTFS.cur_size]
3993
        mov     edx, eax
3994
        shr     eax, 3
3995
        and     edx, 7
3996
        btr     [esi+eax], edx
3997
        mov     esi, [ebp+NTFS.secondIndexBuffer]
3998
        mov     byte [esi], 0
3999
        xor     esi, esi
4000
        ret
4001
 
5954 pathoswith 4002
;----------------------------------------------------------------
3742 clevermous 4003
ntfs_SetFileEnd:
6107 pathoswith 4004
        cmp     byte [esi], 0
4005
        jnz     @f
4006
        xor     ebx, ebx
4007
        movi    eax, ERROR_ACCESS_DENIED
4008
        ret
4009
@@:
4010
        call    ntfs_lock
4011
        stdcall ntfs_find_lfn, [esp+4]
4012
        jc      ntfsNotFound
6273 pathoswith 4013
        cmp     [ebp+NTFS.cur_iRecord], 16
6107 pathoswith 4014
        jc      ntfsDenied
6420 pathoswith 4015
        test    dword [eax+fileFlags], 10000001h
4016
        jnz     ntfsDenied
6273 pathoswith 4017
        cmp     [ebp+NTFS.fragmentCount], 1
6107 pathoswith 4018
        jnz     ntfsUnsupported     ; record fragmented
6151 pathoswith 4019
; edit directory node
6107 pathoswith 4020
        mov     edi, [ebp+NTFS.cur_index_buf]
4021
        cmp     dword [edi], 'INDX'
4022
        jz      @f
4023
        mov     esi, [ebp+NTFS.frs_buffer]
4024
        mov     ecx, [esi+recordRealSize]
4025
        shr     ecx, 2
4026
        rep movsd
6273 pathoswith 4027
        mov     esi, [ebp+NTFS.attr_offs]
6107 pathoswith 4028
        mov     cl, [esi+attributeOffset]
4029
        sub     esi, [ebp+NTFS.frs_buffer]
4030
        add     eax, ecx
4031
        add     eax, esi
4032
@@:
6420 pathoswith 4033
        mov     edi, eax
4034
        mov     eax, [ebx+4]
6107 pathoswith 4035
        mov     edx, [ebx+8]
6420 pathoswith 4036
        mov     [edi+fileRealSize], eax
4037
        mov     [edi+fileRealSize+4], edx
4038
        push    edx eax ebx
4039
        call    ntfsGetTime
4040
        mov     [edi+fileModified], eax
4041
        mov     [edi+fileModified+4], edx
4042
        mov     [edi+recordModified], eax
4043
        mov     [edi+recordModified+4], edx
4044
        mov     [edi+fileAccessed], eax
4045
        mov     [edi+fileAccessed+4], edx
4046
        pop     ebx ecx edx
6273 pathoswith 4047
        mov     eax, [ebp+NTFS.LastRead]
6107 pathoswith 4048
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 4049
        mov     [ebp+NTFS.cur_attr], 0x80
4050
        mov     [ebp+NTFS.cur_offs], 0
4051
        mov     [ebp+NTFS.cur_size], 0
6107 pathoswith 4052
        call    ntfs_read_attr
4053
        jc      ntfsFail
6420 pathoswith 4054
        mov     esi, edi
4055
        mov     edi, [ebp+NTFS.frs_buffer]
4056
        cmp     word [edi+baseRecordReuse], 0
4057
        jnz     ntfsUnsupported     ; auxiliary record
4058
        mov     al, [edi+attributeOffset]
4059
        add     edi, eax
4060
        mov     al, [edi+attributeOffset]
4061
        add     edi, eax
6107 pathoswith 4062
        mov     eax, ecx
6420 pathoswith 4063
        mov     ecx, 6
4064
        add     esi, fileModified
4065
        add     edi, 8
4066
        rep movsd
6273 pathoswith 4067
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 4068
        cmp     word [ecx+attributeFlags], 0
4069
        jnz     ntfsUnsupported
4070
        cmp     byte [ecx+nonResidentFlag], 0
4071
        jz      .resizeAttribute
6107 pathoswith 4072
        cmp     [ecx+attributeRealSize+4], edx
4073
        jnz     .resizeAttribute
4074
        cmp     [ecx+attributeRealSize], eax
4075
        jnc     .resizeAttribute
4076
        mov     eax, [ecx+attributeRealSize]
4077
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 4078
        mov     [ebp+NTFS.cur_size], ecx
6107 pathoswith 4079
        shl     ecx, 9
4080
        div     ecx
4081
        test    edx, edx
4082
        jz      .aligned
4083
        push    edx
4084
        push    ecx
4085
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 4086
        mov     [ebp+NTFS.cur_offs], eax
6107 pathoswith 4087
        stdcall kernel_alloc, ecx
4088
        pop     ecx
4089
        pop     edi
6405 pathoswith 4090
        mov     esi, eax
6107 pathoswith 4091
        sub     ecx, edi
4092
        add     edi, eax
6273 pathoswith 4093
        mov     [ebp+NTFS.cur_buf], eax
6107 pathoswith 4094
        call    ntfs_read_attr.continue
4095
        jc      @f
4096
        xor     eax, eax
4097
        rep stosb
4098
        push    ebx
6273 pathoswith 4099
        mov     eax, [ebp+NTFS.LastRead]
6405 pathoswith 4100
        mov     ebx, esi
6107 pathoswith 4101
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
4102
        xor     edx, edx
4103
        call    fs_write64_app
4104
        pop     ebx
4105
@@:
6405 pathoswith 4106
        stdcall kernel_free, esi
6107 pathoswith 4107
.aligned:
4108
        mov     eax, [ebx+4]
4109
        mov     edx, [ebx+8]
4110
.resizeAttribute:
4111
        call    resizeAttribute
4112
        jc      ntfsError
6408 pathoswith 4113
        mov     ebx, [ebp+NTFS.frs_buffer]
4114
        mov     edx, [ebp+NTFS.mftLastRead]
6107 pathoswith 4115
        call    writeRecord     ; file
6408 pathoswith 4116
        mov     ebx, [ebp+NTFS.cur_index_buf]
4117
        mov     edx, [ebp+NTFS.nodeLastRead]
6107 pathoswith 4118
        call    writeRecord     ; directory
4119
        call    ntfsSpaceClean
4120
        jmp     ntfsDone
4121
 
6462 pathoswith 4122
ntfsGetTime:
4123
        call    fsGetTime
4124
        jmp     @f
2288 clevermous 4125
 
6420 pathoswith 4126
ntfsCalculateTime:
4127
; in: esi -> data block
6462 pathoswith 4128
; out: edx:eax = seconds since 01.01.1601 x10000000
4129
        call    fsCalculateTime
6420 pathoswith 4130
@@:
6462 pathoswith 4131
        mov     edx, 10000000
6420 pathoswith 4132
        mul     edx
6462 pathoswith 4133
        add     eax, 3365781504
4134
        adc     edx, 29389701
6420 pathoswith 4135
        ret
4136
 
3742 clevermous 4137
;----------------------------------------------------------------
6420 pathoswith 4138
ntfs_SetFileInfo:
2288 clevermous 4139
        cmp     byte [esi], 0
4140
        jnz     @f
5994 pathoswith 4141
        movi    eax, ERROR_UNSUPPORTED_FS
2288 clevermous 4142
        ret
4143
@@:
3742 clevermous 4144
        call    ntfs_lock
4145
        stdcall ntfs_find_lfn, [esp+4]
6420 pathoswith 4146
        jnc     @f
3742 clevermous 4147
        test    eax, eax
6019 pathoswith 4148
        jz      ntfsFail
4149
        jmp     ntfsNotFound
2288 clevermous 4150
 
6420 pathoswith 4151
@@:
4152
        cmp     [ebp+NTFS.fragmentCount], 1
4153
        jnz     ntfsUnsupported     ; record fragmented
4154
        mov     esi, [ebp+NTFS.cur_index_buf]
4155
        cmp     dword [esi], 'INDX'
4156
        jz      @f
4157
        sub     eax, esi
4158
        mov     esi, [ebp+NTFS.indexRoot]
4159
        movzx   edx, byte [esi+attributeOffset]
4160
        add     eax, esi
4161
        add     eax, edx
4162
@@:
4163
        mov     esi, [ebx+16]
4164
        mov     edi, eax
4165
        mov     eax, [esi]
4166
        and     eax, 27h
4167
        and     byte [edi+fileFlags], -28h
4168
        or      [edi+fileFlags], al
4169
        add     esi, 8
4170
        call    ntfsCalculateTime
4171
        mov     [edi+fileCreated], eax
4172
        mov     [edi+fileCreated+4], edx
4173
        add     esi, 8
4174
        call    ntfsCalculateTime
4175
        mov     [edi+fileAccessed], eax
4176
        mov     [edi+fileAccessed+4], edx
4177
        add     esi, 8
4178
        call    ntfsCalculateTime
4179
        mov     [edi+fileModified], eax
4180
        mov     [edi+fileModified+4], edx
4181
        mov     ebx, [ebp+NTFS.cur_index_buf]
4182
        cmp     dword [ebx], 'INDX'
4183
        jz      @f
4184
        mov     ebx, [ebp+NTFS.frs_buffer]
4185
@@:
4186
        mov     edx, [ebp+NTFS.LastRead]
4187
        call    writeRecord
4188
        jmp     ntfsDone
4189
 
6019 pathoswith 4190
ntfsUnsupported:
4191
        push    ERROR_UNSUPPORTED_FS
6080 pathoswith 4192
        jmp     ntfsOut
6019 pathoswith 4193
ntfsDevice:
4194
        push    ERROR_DEVICE
4195
        jmp     ntfsOut
4196
ntfsNotFound:
4197
        push    ERROR_FILE_NOT_FOUND
4198
        jmp     ntfsOut
4199
ntfsDenied:
4200
        push    ERROR_ACCESS_DENIED
4201
        jmp     ntfsOut
4202
ntfsFail:
4203
        push    ERROR_FS_FAIL
4204
        jmp     ntfsOut
6080 pathoswith 4205
ntfsDiskFull:
4206
        push    ERROR_DISK_FULL
4207
        jmp     ntfsOut
6414 pathoswith 4208
ntfsErrorPop5:
4209
        pop     ebx
4210
        pop     ebx
6340 pathoswith 4211
ntfsErrorPop3:
4212
        pop     ebx
6107 pathoswith 4213
ntfsErrorPop2:
4214
        pop     ebx
4215
ntfsErrorPop:
4216
        pop     ebx
6080 pathoswith 4217
ntfsError:
4218
        push    eax
4219
ntfsOut:
4220
        call    ntfs_unlock
4221
        xor     ebx, ebx
4222
        pop     eax
4223
        ret