Subversion Repositories Kolibri OS

Rev

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