Subversion Repositories Kolibri OS

Rev

Rev 6408 | Rev 6411 | 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: 6409 $
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
6409 pathoswith 2231
        push    edi eax
6407 pathoswith 2232
        call    .ntfsNodeAlloc
6409 pathoswith 2233
        pop     ecx edi
6407 pathoswith 2234
        jc      ntfsErrorPop3
6340 pathoswith 2235
        push    edi
2236
        mov     edi, [ebp+NTFS.indexRoot]
6409 pathoswith 2237
        mov     eax, ecx
6340 pathoswith 2238
        add     [ebp+NTFS.attr_offs], eax
2239
        add     [edi+sizeWithHeader], eax
2240
        add     [edi+sizeWithoutHeader], eax
2241
        movzx   ecx, byte [edi+attributeOffset]
2242
        add     ecx, edi
2243
        add     [ecx+rootNode+nodeRealSize], eax
2244
        add     [ecx+rootNode+nodeAllocatedSize], eax
6405 pathoswith 2245
        add     ecx, [ebp+NTFS.indexPointer]
6340 pathoswith 2246
        sub     ecx, [ebp+NTFS.secondIndexBuffer]
6409 pathoswith 2247
        mov     esi, [ebp+NTFS.frs_buffer]
2248
        add     [esi+recordRealSize], eax
2249
        add     esi, [esi+recordRealSize]
6340 pathoswith 2250
        mov     edi, esi
2251
        sub     esi, eax
2252
        neg     ecx
2253
        add     ecx, esi
2254
        shr     ecx, 2
2255
        sub     esi, 4
2256
        sub     edi, 4
2257
        std
2258
        rep movsd   ; make space
2259
        mov     [edi], ecx
2260
        mov     edi, esi
2261
        add     edi, 4
2262
        mov     esi, [esp]
2263
        add     word [esi+indexAllocatedSize], 8
2264
        mov     byte [esi+indexFlags], 1
2265
        mov     ecx, eax
2266
        sub     ecx, 8
2267
        shr     ecx, 2
2268
        cld
2269
        rep movsd   ; insert index
2270
        mov     eax, [ebp+NTFS.newRecord]
2271
        stosd
2272
; split node
2273
        mov     edi, [ebp+NTFS.cur_index_buf]
2274
        mov     eax, edi
2275
        add     eax, recordNode
2276
        add     eax, [edi+recordNode+nodeRealSize]
2277
        sub     eax, esi
2278
        push    eax
2279
        mov     ecx, [edi+recordNode+indexOffset]
2280
        add     eax, ecx
2281
        add     ecx, recordNode
2282
        shr     ecx, 2
2283
        push    esi
2284
        mov     esi, edi
2285
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2286
        rep movsd
2287
        pop     esi
2288
        pop     ecx
2289
        shr     ecx, 2
2290
        rep movsd
2291
        mov     edi, [ebp+NTFS.secondIndexBuffer]
2292
        mov     [edi+recordNode+nodeRealSize], eax
2293
        pop     edi
2294
        mov     cl, 4
2295
        xor     eax, eax
2296
        mov     esi, edi
2297
        rep stosd
2298
        mov     byte [esi+indexAllocatedSize], 16
2299
        mov     byte [esi+indexFlags], 2
2300
        mov     esi, [ebp+NTFS.cur_index_buf]
2301
        mov     eax, [ebp+NTFS.newRecord]
2302
        mov     [esi+recordVCN], eax
2303
        add     esi, recordNode
2304
        sub     edi, esi
2305
        mov     [esi+nodeRealSize], edi
6408 pathoswith 2306
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
2307
        mov     edx, [ebp+NTFS.LastRead]
6340 pathoswith 2308
        call    writeRecord
6407 pathoswith 2309
        jmp     .refresh
6340 pathoswith 2310
 
6292 pathoswith 2311
.common:
6273 pathoswith 2312
        add     edi, edx
2313
        sub     edi, 4
5954 pathoswith 2314
        mov     esi, edi
2315
        sub     esi, [esp]
2316
        mov     ecx, esi
6292 pathoswith 2317
        sub     ecx, eax    ; eax = pointer in the record
5954 pathoswith 2318
        shr     ecx, 2
2319
        inc     ecx
2320
        std
2321
        rep movsd           ; move forward, make space
2322
        mov     ecx, [esp]
2323
        shr     ecx, 2
2324
        xor     eax, eax
2325
        rep stosd
2326
        cld
2327
        add     edi, 4
6151 pathoswith 2328
        pop     ecx
5954 pathoswith 2329
        pop     esi
6151 pathoswith 2330
        mov     [edi+indexAllocatedSize], cx    ; fill index with data
5954 pathoswith 2331
        mov     eax, [esp]
6080 pathoswith 2332
        shl     eax, 1
2333
        add     eax, 42h
5954 pathoswith 2334
        mov     [edi+indexRawSize], ax
6273 pathoswith 2335
        mov     eax, [ebp+NTFS.attr_iRecord]
5954 pathoswith 2336
        mov     [edi+directoryRecordReference], eax
2337
        mov     eax, [ebp+NTFS.frs_buffer]
2338
        mov     eax, [eax+reuseCounter]
2339
        mov     [edi+directoryReferenceReuse], ax
6292 pathoswith 2340
        mov     eax, [ebp+NTFS.frs_size]
2341
        shr     eax, 8
6151 pathoswith 2342
        add     ecx, 30h+48h+8+18h+8
2343
        add     ecx, eax
6292 pathoswith 2344
        mov     eax, [ebp+NTFS.fileRealSize]
2345
        add     ecx, eax
5954 pathoswith 2346
        mov     [edi+fileRealSize], eax
6151 pathoswith 2347
        cmp     [ebp+NTFS.frs_size], ecx
2348
        jc      @f
2349
        xor     eax, eax
2350
@@:
5954 pathoswith 2351
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2352
        shl     ecx, 9
2353
        add     eax, ecx
2354
        dec     eax
2355
        xor     edx, edx
2356
        div     ecx
2357
        mov     [ebp+NTFS.fileDataSize], eax
2358
        mul     ecx
2359
        mov     [edi+fileAllocatedSize], eax
2360
        pop     ecx
6405 pathoswith 2361
        mov     [ebp+NTFS.indexPointer], edi
5954 pathoswith 2362
        mov     [edi+fileNameLength], cl
6297 pathoswith 2363
        add     edi, fileName
5954 pathoswith 2364
@@:         ; record filename
2365
        lodsb
2366
        call    ansi2uni_char
2367
        stosw
2368
        dec     ecx
2369
        jnz     @b
6273 pathoswith 2370
        mov     eax, [ebp+NTFS.LastRead]
5954 pathoswith 2371
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 2372
        cmp     [ebp+NTFS.bFolder], 0
5954 pathoswith 2373
        jz      @f
6405 pathoswith 2374
        mov     edi, [ebp+NTFS.indexPointer]
6080 pathoswith 2375
        bts     dword [edi+fileFlags], 28
5954 pathoswith 2376
        jmp     .mftBitmap
2377
 
2378
@@: ; 3. File data
6151 pathoswith 2379
        cmp     [ebp+NTFS.fileDataSize], 0
5954 pathoswith 2380
        jz      .mftBitmap
6080 pathoswith 2381
        mov     edi, [ebp+NTFS.BitmapStart]
2382
        call    ntfsSpaceAlloc
2383
        jc      ntfsDiskFull
6292 pathoswith 2384
        mov     eax, [ebp+NTFS.fileDataStart]
5954 pathoswith 2385
        mul     [ebp+NTFS.sectors_per_cluster]
2386
        mov     ecx, [ebp+NTFS.fileRealSize]
2387
        add     ecx, 511
2388
        shr     ecx, 9
6292 pathoswith 2389
        mov     ebx, [ebp+NTFS.fileDataBuffer]
5954 pathoswith 2390
        call    fs_write64_app
2391
        test    eax, eax
6019 pathoswith 2392
        jnz     ntfsDevice
5954 pathoswith 2393
    ; 4. MFT record
2394
.mftBitmap: ; search for free record
2395
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2396
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2397
        mov     al, -1
2398
        add     edi, 3
2399
        sub     ecx, 3
2400
        repz scasb
2401
        dec     edi
2402
        movzx   eax, byte [edi]
2403
        not     al
2404
        bsf     ecx, eax
6107 pathoswith 2405
        jz      .extendBitmapMFT    ; no free records
6019 pathoswith 2406
        bts     [edi], ecx
2407
; get record location
5954 pathoswith 2408
        sub     edi, [ebp+NTFS.mftBitmapBuffer]
2409
        shl     edi, 3
2410
        add     edi, ecx
6340 pathoswith 2411
        mov     [ebp+NTFS.newRecord], edi
5954 pathoswith 2412
        mov     eax, [ebp+NTFS.frs_size]
2413
        shr     eax, 9
2414
        mul     edi
6273 pathoswith 2415
        mov     [ebp+NTFS.cur_iRecord], 0
2416
        mov     [ebp+NTFS.cur_attr], 0x80
2417
        mov     [ebp+NTFS.cur_offs], eax
6405 pathoswith 2418
        push    eax
2419
        mov     [ebp+NTFS.cur_size], 0
5954 pathoswith 2420
        mov     eax, [ebp+NTFS.frs_buffer]
6273 pathoswith 2421
        mov     [ebp+NTFS.cur_buf], eax
5954 pathoswith 2422
        call    ntfs_read_attr
6405 pathoswith 2423
        pop     eax
2424
        jc      ntfsFail
2425
        cmp     eax, [ebp+NTFS.mftSize]
2426
        jnc     .extendMFT
6107 pathoswith 2427
        jmp     .mftRecord
2428
 
2429
.extendBitmapMFT:
2430
        mov     eax, [ebp+NTFS.sectors_per_cluster]
6405 pathoswith 2431
        mov     [ebp+NTFS.cur_offs], eax
6107 pathoswith 2432
        shl     eax, 9
2433
        cmp     [ebp+NTFS.mftBitmapSize], eax
2434
        jnc     ntfsUnsupported
6273 pathoswith 2435
        mov     [ebp+NTFS.cur_iRecord], 0
2436
        mov     [ebp+NTFS.cur_attr], 0xB0
2437
        mov     [ebp+NTFS.cur_size], 0
6107 pathoswith 2438
        call    ntfs_read_attr
2439
        jc      ntfsFail
5954 pathoswith 2440
        mov     eax, [ebp+NTFS.mft_cluster]
2441
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 2442
        cmp     eax, [ebp+NTFS.LastRead]
6019 pathoswith 2443
        jnz     ntfsUnsupported     ; auxiliary record
6107 pathoswith 2444
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2445
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2446
        add     edi, ecx
2447
        mov     eax, ecx
6273 pathoswith 2448
        mov     edx, [ebp+NTFS.attr_offs]
6107 pathoswith 2449
        add     ecx, 8
2450
        mov     [edx+attributeRealSize], ecx
2451
        mov     [edx+initialDataSize], ecx
2452
        shl     eax, 3
6340 pathoswith 2453
        mov     [ebp+NTFS.newRecord], eax
6107 pathoswith 2454
        mov     dword [edi], 1
2455
        mov     dword [edi+4], 0
6273 pathoswith 2456
        mov     [ebp+NTFS.cur_attr], 0x80
6405 pathoswith 2457
        mov     [ebp+NTFS.cur_offs], 0
6107 pathoswith 2458
        call    ntfs_read_attr.newAttribute
2459
        jc      ntfsFail
2460
        mov     [ebp+NTFS.mftBitmapSize], ecx
2461
.extendMFT:
2462
        mov     eax, [ebp+NTFS.mft_cluster]
5954 pathoswith 2463
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 2464
        cmp     eax, [ebp+NTFS.LastRead]
6107 pathoswith 2465
        jnz     ntfsUnsupported     ; auxiliary record
6273 pathoswith 2466
        mov     ecx, [ebp+NTFS.attr_offs]
6107 pathoswith 2467
        mov     eax, [ecx+attributeRealSize]
2468
        mov     edx, [ecx+attributeRealSize+4]
2469
        xor     ax, ax
2470
        add     eax, 10000h
2471
        adc     edx, 0
2472
        push    [ebp+NTFS.fileDataStart]
2473
        push    [ebp+NTFS.fileDataSize]
2474
        call    resizeAttribute
2475
        jc      ntfsErrorPop2
6408 pathoswith 2476
        mov     ebx, [ebp+NTFS.frs_buffer]
2477
        mov     edx, [ebp+NTFS.LastRead]
5954 pathoswith 2478
        call    writeRecord     ; $MFT
2479
        mov     eax, [ebp+NTFS.mftmirr_cluster]
2480
        mul     [ebp+NTFS.sectors_per_cluster]
6408 pathoswith 2481
        mov     ecx, [ebp+NTFS.frs_size]
2482
        shr     ecx, 9
5954 pathoswith 2483
        call    fs_write64_sys  ; $MFTMirr
6405 pathoswith 2484
; update $MFT retrieval information
2485
        mov     edi, [ebp+NTFS.mft_retrieval_end]
2486
        mov     eax, [edi-4]
2487
        add     eax, [edi-8]
2488
        mov     edx, [ebp+NTFS.fileDataSize]
2489
        cmp     eax, [ebp+NTFS.fileDataStart]
2490
        jnz     .newFragment
2491
        add     [edi-8], edx
2492
        jmp     @f
2493
.newFragment:
2494
        lea     eax, [ebp+NTFS.attrlist_buf]
2495
        cmp     eax, edi
2496
        jz      @f
2497
        mov     [edi], edx
2498
        mov     eax, [ebp+NTFS.fileDataStart]
2499
        mov     [edi+4], eax
2500
        add     [ebp+NTFS.mft_retrieval_end], 8
2501
@@:
2502
        mov     eax, [ebp+NTFS.fileDataSize]
2503
        mul     [ebp+NTFS.sectors_per_cluster]
2504
        add     [ebp+NTFS.mftSize], eax
6107 pathoswith 2505
        call    ntfsSpaceClean
2506
        pop     [ebp+NTFS.fileDataSize]
2507
        pop     [ebp+NTFS.fileDataStart]
5954 pathoswith 2508
.mftRecord:
6151 pathoswith 2509
        mov     ecx, [ebp+NTFS.frs_size]
2510
        shr     ecx, 2
5954 pathoswith 2511
        mov     edi, [ebp+NTFS.frs_buffer]
2512
        xor     eax, eax
2513
        rep stosd
2514
        mov     edi, [ebp+NTFS.frs_buffer]
6019 pathoswith 2515
; record header
6292 pathoswith 2516
        rdtsc
2517
        mov     [edi+2ah], ax
6151 pathoswith 2518
        mov     eax, [ebp+NTFS.frs_size]
2519
        mov     [edi+recordAllocatedSize], eax
2520
        shr     eax, 9
2521
        inc     eax
2522
        mov     [edi+updateSequenceSize], al
6292 pathoswith 2523
        shl     eax, 1
2524
        add     eax, 2ah+7
2525
        and     eax, not 7
5954 pathoswith 2526
        mov     dword[edi], 'FILE'
2527
        mov     byte [edi+updateSequenceOffset], 2ah
2528
        mov     byte [edi+hardLinkCounter], 1
2529
        mov     byte [edi+newAttributeID], 3
6292 pathoswith 2530
        mov     [edi+attributeOffset], al
2531
        add     edi, eax
6019 pathoswith 2532
; $StandardInformation
5954 pathoswith 2533
        mov     byte [edi+attributeType], 10h
2534
        mov     byte [edi+sizeWithHeader], 48h
2535
        mov     byte [edi+sizeWithoutHeader], 30h
2536
        mov     byte [edi+attributeOffset], 18h
2537
        add     edi, 48h
6019 pathoswith 2538
; $FileName
6405 pathoswith 2539
        mov     esi, [ebp+NTFS.indexPointer]
5954 pathoswith 2540
        mov     byte [edi+attributeType], 30h
2541
        mov     byte [edi+attributeID], 1
6151 pathoswith 2542
        mov     byte [edi+attributeOffset], 18h
2543
        mov     byte [edi+indexedFlag], 1
5954 pathoswith 2544
        mov     cx, [esi+indexRawSize]
2545
        mov     [edi+sizeWithoutHeader], ecx
2546
        mov     cx, [esi+indexAllocatedSize]
2547
        add     ecx, 8
2548
        mov     [edi+sizeWithHeader], ecx
2549
        add     edi, 18h
2550
        add     esi, 16
2551
        sub     ecx, 18h
2552
        shr     ecx, 2
2553
        rep movsd
6080 pathoswith 2554
        mov     byte [edi+sizeWithHeader], 50h
2555
        mov     byte [edi+attributeID], 2
6273 pathoswith 2556
        cmp     [ebp+NTFS.bFolder], 1
6151 pathoswith 2557
        jz      .indexRoot
6019 pathoswith 2558
; $Data
5954 pathoswith 2559
        mov     byte [edi+attributeType], 80h
6151 pathoswith 2560
        mov     eax, [ebp+NTFS.fileDataSize]
2561
        test    eax, eax
2562
        jz      .resident
6405 pathoswith 2563
        mov     esi, [ebp+NTFS.indexPointer]
6080 pathoswith 2564
        dec     eax
2565
        mov     [edi+lastVCN], eax
5954 pathoswith 2566
        mov     byte [edi+nonResidentFlag], 1
2567
        mov     byte [edi+dataRunsOffset], 40h
2568
        mov     eax, [esi+fileAllocatedSize]
2569
        mov     [edi+attributeAllocatedSize], eax
2570
        mov     eax, [esi+fileRealSize]
2571
        mov     [edi+attributeRealSize], eax
2572
        mov     [edi+initialDataSize], eax
6151 pathoswith 2573
        push    edi
6080 pathoswith 2574
        mov     esi, edi
2575
        add     edi, 40h
2576
        call    createMcbEntry
6151 pathoswith 2577
        inc     edi
2578
        jmp     @f
5954 pathoswith 2579
 
6151 pathoswith 2580
.resident:
2581
        mov     ecx, [ebp+NTFS.fileRealSize]
2582
        mov     [edi+sizeWithoutHeader], ecx
5954 pathoswith 2583
        mov     byte [edi+attributeOffset], 18h
6151 pathoswith 2584
        push    edi
6292 pathoswith 2585
        mov     esi, [ebp+NTFS.fileDataBuffer]
6151 pathoswith 2586
        add     edi, 18h
2587
        rep movsb
2588
@@:
2589
        mov     eax, edi
2590
        pop     edi
2591
        sub     eax, edi
2592
        add     eax, 7
2593
        and     eax, not 7
2594
        mov     [edi+sizeWithHeader], eax
2595
        add     edi, eax
5954 pathoswith 2596
        mov     al, 1
6292 pathoswith 2597
        jmp     .end
5954 pathoswith 2598
 
6151 pathoswith 2599
.indexRoot:
5954 pathoswith 2600
        mov     byte [edi+attributeType], 90h
2601
        mov     byte [edi+nameLength], 4
2602
        mov     byte [edi+nameOffset], 18h
2603
        mov     byte [edi+sizeWithoutHeader], 30h
2604
        mov     byte [edi+attributeOffset], 20h
2605
        mov     dword[edi+18h], 490024h     ; unicode $I30
2606
        mov     dword[edi+18h+4], 300033h
6273 pathoswith 2607
        mov     byte [edi+20h+indexedAttributesType], 30h
6019 pathoswith 2608
        mov     byte [edi+20h+collationRule], 1
5954 pathoswith 2609
        mov     eax, [ebp+NTFS.sectors_per_cluster]
6292 pathoswith 2610
        mov     dl, 1
2611
        shl     eax, 8
2612
@@:
2613
        shl     eax, 1
2614
        shl     edx, 1
2615
        cmp     eax, [ebp+NTFS.frs_size]
2616
        jc      @b
2617
        shr     edx, 1
6019 pathoswith 2618
        mov     [edi+20h+indexRecordSize], eax
6292 pathoswith 2619
        mov     [edi+20h+indexRecordSizeClus], dl
6019 pathoswith 2620
        mov     byte [edi+30h+indexOffset], 16
2621
        mov     byte [edi+30h+nodeRealSize], 32
2622
        mov     byte [edi+30h+nodeAllocatedSize], 32
2623
        mov     byte [edi+40h+indexAllocatedSize], 16
2624
        mov     byte [edi+40h+indexFlags], 2
6151 pathoswith 2625
        add     edi, 50h
5954 pathoswith 2626
        mov     al, 3
6292 pathoswith 2627
.end:
6408 pathoswith 2628
        mov     ebx, [ebp+NTFS.frs_buffer]
6151 pathoswith 2629
        mov     dword [edi], -1
2630
        mov     dword [edi+4], 0
2631
        add     edi, 8
6408 pathoswith 2632
        sub     edi, ebx
2633
        mov     [ebx+recordFlags], al
2634
        mov     [ebx+recordRealSize], edi
2635
        mov     edx, [ebp+NTFS.LastRead]
5954 pathoswith 2636
        call    writeRecord
6019 pathoswith 2637
; write MFT bitmap
6340 pathoswith 2638
        mov     eax, [ebp+NTFS.newRecord]
5954 pathoswith 2639
        shr     eax, 3+9
2640
        mov     ebx, eax
2641
        shl     ebx, 9
2642
        add     eax, [ebp+NTFS.mftBitmapLocation]
2643
        add     ebx, [ebp+NTFS.mftBitmapBuffer]
2644
        mov     ecx, 1
2645
        xor     edx, edx
2646
        call    fs_write64_sys
6405 pathoswith 2647
        mov     edi, [ebp+NTFS.indexPointer]
6340 pathoswith 2648
        mov     eax, [ebp+NTFS.newRecord]
5954 pathoswith 2649
        mov     [edi+fileRecordReference], eax
6292 pathoswith 2650
; 5. Write directory node
6408 pathoswith 2651
        mov     ebx, [ebp+NTFS.cur_index_buf]
2652
        mov     edx, [ebp+NTFS.nodeLastRead]
5954 pathoswith 2653
        call    writeRecord
6019 pathoswith 2654
        mov     ebx, [ebp+NTFS.fileRealSize]
2655
ntfsDone:
5954 pathoswith 2656
        mov     esi, [ebp+PARTITION.Disk]
2657
        call    disk_sync
2658
        call    ntfs_unlock
6019 pathoswith 2659
        xor     eax, eax
5954 pathoswith 2660
        ret
2661
 
2662
writeRecord:
6080 pathoswith 2663
; make updateSequence and write to disk
5954 pathoswith 2664
;   in:
6408 pathoswith 2665
; ebx -> record
2666
; edx = partition sector
2667
        mov     esi, ebx
2668
        mov     edi, ebx
5954 pathoswith 2669
        movzx   ecx, word [esi+updateSequenceOffset]
2670
        add     edi, ecx
2671
        mov     ax, [edi]
6080 pathoswith 2672
        inc     ax
2673
        stosw
5954 pathoswith 2674
        mov     cx, [esi+updateSequenceSize]
2675
        dec     ecx
2676
        push    ecx
2677
@@:
2678
        add     esi, 510
2679
        movsw
2680
        mov     [esi-2], ax
2681
        dec     ecx
2682
        jnz     @b
6408 pathoswith 2683
        mov     eax, edx
2684
        xor     edx, edx
5954 pathoswith 2685
        pop     ecx
2686
        jmp     fs_write64_sys
2687
 
6080 pathoswith 2688
createMcbEntry:
2689
;   in:
2690
; [ebp+NTFS.fileDataStart] = position value
2691
; [ebp+NTFS.fileDataSize] = size value
2692
; edi -> destination
2693
; esi -> attribute header
2694
        mov     eax, [ebp+NTFS.fileDataStart]
2695
        xor     edx, edx
2696
        shl     eax, 1
2697
        jnc     @f
2698
        not     eax
2699
@@:
2700
        inc     edx
2701
        shr     eax, 8
2702
        jnz     @b
2703
        mov     eax, [ebp+NTFS.fileDataSize]
2704
        shl     eax, 1
2705
        xor     ecx, ecx
2706
@@:
2707
        inc     ecx
2708
        shr     eax, 8
2709
        jnz     @b
2710
        lea     eax, [edi+edx+1]
2711
        add     eax, ecx
2712
        sub     eax, esi
6151 pathoswith 2713
        sub     eax, [esi+sizeWithHeader]
6080 pathoswith 2714
        jc      @f
2715
        add     word [esi+sizeWithHeader], 8    ; extend attribute
2716
        mov     esi, [ebp+NTFS.frs_buffer]
2717
        mov     eax, [esi+recordRealSize]
2718
        add     eax, 8
2719
        cmp     [esi+recordAllocatedSize], eax
2720
        jc      .end    ; no space in the record
2721
        mov     [esi+recordRealSize], eax
2722
        push    ecx edi
2723
        add     esi, eax
2724
        mov     ecx, esi
2725
        sub     ecx, edi
2726
        sub     ecx, 8
2727
        shr     ecx, 2
2728
        mov     edi, esi
2729
        sub     edi, 4
2730
        sub     esi, 12
2731
        std
2732
        rep movsd
2733
        cld
2734
        pop     edi ecx
2735
@@:
2736
        mov     eax, edx
2737
        shl     eax, 4
2738
        add     eax, ecx
2739
        stosb
2740
        lea     esi, [ebp+NTFS.fileDataSize]
2741
        rep movsb
2742
        lea     esi, [ebp+NTFS.fileDataStart]
2743
        mov     ecx, edx
2744
        rep movsb
6151 pathoswith 2745
        mov     [edi], cl
6080 pathoswith 2746
.end:
2747
        ret
2748
 
2749
resizeAttribute:
2750
;   in:
2751
; [ebp+NTFS.frs_buffer] -> file record
6273 pathoswith 2752
; [ebp+NTFS.attr_offs] -> attribute
6080 pathoswith 2753
; edx:eax = new size
2754
;   out:
6107 pathoswith 2755
; [ebp+NTFS.fileDataSize] = clusters added (positive)
2756
; [ebp+NTFS.fileDataStart] = added block
6080 pathoswith 2757
; CF=1 -> eax = error code
6273 pathoswith 2758
        mov     esi, [ebp+NTFS.attr_offs]
2759
        mov     dword [ebp+NTFS.attr_size], eax
2760
        mov     dword [ebp+NTFS.attr_size+4], edx
6151 pathoswith 2761
        cmp     byte [esi+nonResidentFlag], 0
2762
        jz      .resident
6080 pathoswith 2763
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2764
        shl     ecx, 9
2765
        mov     [esi+attributeRealSize], eax
2766
        mov     [esi+attributeRealSize+4], edx
2767
        mov     [esi+initialDataSize], eax
2768
        mov     [esi+initialDataSize+4], edx
2769
        sub     eax, 1
2770
        sbb     edx, 0
6151 pathoswith 2771
        jc      .makeResident
6080 pathoswith 2772
        div     ecx
2773
        mov     edi, eax
2774
        inc     eax
2775
        mul     ecx
2776
        mov     [esi+attributeAllocatedSize], eax
2777
        mov     [esi+attributeAllocatedSize+4], edx
2778
        mov     ecx, [esi+lastVCN]
2779
        mov     [esi+lastVCN], edi
2780
        movzx   eax, byte [esi+dataRunsOffset]
2781
        sub     edi, ecx
6107 pathoswith 2782
        mov     [ebp+NTFS.fileDataSize], edi
6080 pathoswith 2783
        jz      .done
2784
        jc      .shrinkAttribute
2785
; extend attribute
2786
        xor     edi, edi
2787
        add     esi, eax
2788
        push    edi edi edi edi
2789
@@:
2790
        mov     edx, eax
2791
        mov     eax, esi
2792
        add     edi, [esp+8]
2793
        call    ntfs_decode_mcb_entry
2794
        jc      @b
2795
        mov     [esp+4], edx
2796
        mov     [esp+12], edi
2797
        add     edi, [esp]
2798
        push    edi
2799
        shr     edi, 5
2800
        shl     edi, 2
2801
        push    eax
6273 pathoswith 2802
        cmp     [ebp+NTFS.cur_iRecord], 0
6107 pathoswith 2803
        jz      @f
6080 pathoswith 2804
        cmp     edi, [ebp+NTFS.BitmapStart]
2805
        jc      .err1
6107 pathoswith 2806
@@:
6080 pathoswith 2807
        call    ntfsSpaceAlloc
2808
        jc      .err1
6292 pathoswith 2809
        mov     eax, [ebp+NTFS.fileDataStart]
6080 pathoswith 2810
        pop     edi
2811
        pop     edx
2812
        cmp     edx, eax
2813
        jnz     .newEntry
2814
        pop     edx
2815
        pop     edi
2816
        pop     [ebp+NTFS.fileDataStart]
2817
        mov     [esp], eax
2818
        push    [ebp+NTFS.fileDataSize]
2819
        add     [ebp+NTFS.fileDataSize], edx
2820
        jmp     @f
2821
 
2822
.newEntry:
2823
        add     esp, 12
2824
        pop     edx
2825
        push    eax
2826
        push    [ebp+NTFS.fileDataSize]
2827
        sub     eax, edx
2828
        mov     [ebp+NTFS.fileDataStart], eax
2829
@@:
6273 pathoswith 2830
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 2831
        call    createMcbEntry
6292 pathoswith 2832
        pop     [ebp+NTFS.fileDataSize]
2833
        pop     [ebp+NTFS.fileDataStart]
2834
        movi    eax, ERROR_UNSUPPORTED_FS
6151 pathoswith 2835
.done:
2836
        ret
2837
 
6080 pathoswith 2838
.err1:
2839
        add     esp, 24
2840
        stc
6292 pathoswith 2841
.err2:
6151 pathoswith 2842
        movi    eax, ERROR_DISK_FULL
6080 pathoswith 2843
        ret
2844
 
6292 pathoswith 2845
.err3:
2846
        movi    eax, ERROR_FS_FAIL
2847
        add     esp, 20
2848
        stc
6080 pathoswith 2849
        ret
2850
 
2851
.shrinkAttribute:
2852
        add     ecx, edi
2853
        inc     ecx
2854
        add     esi, eax
2855
        xor     edi, edi
2856
        sub     esp, 20
2857
@@:
2858
        mov     [esp+16], esi
2859
        call    ntfs_decode_mcb_entry
2860
        jnc     .err3
2861
        add     edi, [esp+8]
2862
        sub     ecx, [esp]
2863
        jnc     @b
2864
        mov     ebx, ecx
2865
        add     ecx, [esp]
2866
        mov     eax, [esp+8]
2867
        mov     [ebp+NTFS.fileDataSize], ecx
2868
        mov     [ebp+NTFS.fileDataStart], eax
2869
        push    edi
2870
        add     edi, ecx
2871
        neg     ebx
2872
        call    ntfsSpaceFree
2873
        pop     edi
2874
        jc      .end
2875
@@:
2876
        call    ntfs_decode_mcb_entry
2877
        jnc     .end
2878
        cmp     dword[esp+8], 0
2879
        jz      @b
2880
        add     edi, [esp+8]
2881
        mov     ebx, [esp]
2882
        call    ntfsSpaceFree
2883
        jnc     @b
2884
.end:
2885
        add     esp, 16
2886
        pop     edi
2887
        cmp     [ebp+NTFS.fileDataSize], 0
2888
        jz      @f
6273 pathoswith 2889
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 2890
        call    createMcbEntry
6107 pathoswith 2891
        mov     [ebp+NTFS.fileDataSize], 0
6080 pathoswith 2892
@@:
2893
        ret
2894
 
6151 pathoswith 2895
.resident:
2896
        test    edx, edx
2897
        jnz     .nonResident
2898
        cmp     eax, 8000h
2899
        jnc     .nonResident
2900
        add     ax, [esi+attributeOffset]
2901
        sub     eax, [esi+sizeWithHeader]
2902
        jc      @f
2903
        mov     edi, [ebp+NTFS.frs_buffer]
2904
        mov     ecx, eax
2905
        add     ecx, [edi+recordRealSize]
2906
        cmp     [edi+recordAllocatedSize], ecx
2907
        jc      .nonResident
2908
        add     eax, 7
2909
        and     eax, not 7
2910
        add     [edi+recordRealSize], eax
2911
        add     edi, [edi+recordRealSize]
2912
        add     [esi+sizeWithHeader], eax
2913
        add     esi, [esi+sizeWithHeader]
2914
        mov     ecx, edi
2915
        sub     ecx, esi
2916
        shr     ecx, 2
2917
        sub     edi, 4
2918
        mov     esi, edi
2919
        sub     esi, eax
2920
        std
2921
        rep movsd
2922
        mov     ecx, eax
2923
        shr     ecx, 2
2924
        xor     eax, eax
2925
        rep stosd
2926
        cld
6273 pathoswith 2927
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 2928
@@:
6273 pathoswith 2929
        mov     eax, dword [ebp+NTFS.attr_size]
6151 pathoswith 2930
        mov     [esi+sizeWithoutHeader], eax
2931
        mov     [ebp+NTFS.fileDataSize], 0
2932
        clc
2933
        ret
2934
 
2935
.nonResident:   ; convert resident to non-resident
6273 pathoswith 2936
        mov     eax, dword [ebp+NTFS.attr_size]
6151 pathoswith 2937
        sub     eax, 1
2938
        sbb     edx, 0
2939
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2940
        shl     ecx, 9
2941
        div     ecx
2942
        inc     eax
2943
        mov     [ebp+NTFS.fileDataSize], eax
2944
        mov     edi, [ebp+NTFS.BitmapStart]
2945
        push    ecx
2946
        call    ntfsSpaceAlloc
2947
        pop     ecx
6292 pathoswith 2948
        jc      .err2
6273 pathoswith 2949
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 2950
        xor     eax, eax
2951
        xor     edx, edx
2952
@@:
2953
        add     eax, ecx
2954
        inc     edx
2955
        cmp     eax, [esi+sizeWithoutHeader]
2956
        jc      @b
2957
        push    edx
2958
        push    eax
2959
        stdcall kernel_alloc, eax
2960
        mov     ecx, [esp]
2961
        shr     ecx, 2
2962
        mov     edi, eax
2963
        mov     ebx, eax
2964
        xor     eax, eax
2965
        rep stosd
2966
        mov     al, [esi+attributeOffset]
2967
        mov     ecx, [esi+sizeWithoutHeader]
2968
        add     esi, eax
2969
        mov     edi, ebx
2970
        rep movsb
2971
        mov     eax, [ebp+NTFS.fileDataStart]
2972
        mul     [ebp+NTFS.sectors_per_cluster]
2973
        pop     ecx
2974
        shr     ecx, 9
2975
        call    fs_write64_app
6292 pathoswith 2976
        stdcall kernel_free, ebx
6273 pathoswith 2977
        mov     esi, [ebp+NTFS.attr_offs]
6151 pathoswith 2978
        add     esi, [esi+sizeWithHeader]
2979
        mov     ecx, [ebp+NTFS.frs_buffer]
2980
        add     ecx, [ecx+recordRealSize]
2981
        sub     ecx, esi
2982
        shr     ecx, 2
6273 pathoswith 2983
        lea     edi, [ebp+NTFS.bitmap_buf]
6151 pathoswith 2984
        push    ecx
2985
        rep movsd
6273 pathoswith 2986
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 2987
        add     edi, 16
2988
        mov     cl, 6
2989
        xor     eax, eax
2990
        rep stosd
6273 pathoswith 2991
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 2992
        mov     eax, [ebp+NTFS.fileDataSize]
2993
        dec     eax
2994
        mov     [edi+lastVCN], eax
2995
        inc     eax
2996
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2997
        shl     ecx, 9
2998
        mul     ecx
2999
        mov     byte [edi+sizeWithHeader], 50h
3000
        mov     byte [edi+nonResidentFlag], 1
3001
        mov     byte [edi+dataRunsOffset], 40h
3002
        mov     [edi+attributeAllocatedSize], eax
3003
        mov     [edi+attributeAllocatedSize+4], edx
6273 pathoswith 3004
        mov     eax, dword [ebp+NTFS.attr_size]
3005
        mov     edx, dword [ebp+NTFS.attr_size+4]
6151 pathoswith 3006
        mov     [edi+attributeRealSize], eax
3007
        mov     [edi+attributeRealSize+4], edx
3008
        mov     [edi+initialDataSize], eax
3009
        mov     [edi+initialDataSize+4], edx
3010
        mov     esi, edi
3011
        add     edi, 40h
3012
        call    createMcbEntry
3013
        mov     eax, edi
6273 pathoswith 3014
        mov     edi, [ebp+NTFS.attr_offs]
6151 pathoswith 3015
        sub     eax, edi
3016
        add     eax, 8
3017
        and     eax, not 7
3018
        mov     [edi+sizeWithHeader], eax
3019
        pop     ecx
6273 pathoswith 3020
        lea     esi, [ebp+NTFS.bitmap_buf]
6151 pathoswith 3021
        add     edi, eax
3022
        rep movsd
3023
        mov     esi, [ebp+NTFS.frs_buffer]
3024
        sub     edi, esi
3025
        mov     [esi+recordRealSize], edi
3026
        pop     edx
3027
        sub     [ebp+NTFS.fileDataSize], edx
3028
        add     [ebp+NTFS.fileDataStart], edx
6292 pathoswith 3029
        ret
6151 pathoswith 3030
 
3031
.makeResident:  ; convert non-resident to empty resident
3032
        movzx   eax, byte [esi+dataRunsOffset]
3033
        mov     byte [esi+nonResidentFlag], 0
3034
        mov     dword [esi+sizeWithoutHeader], 0
3035
        mov     dword [esi+attributeOffset], 18h
3036
        add     esi, eax
3037
        xor     edi, edi
3038
        sub     esp, 16
3039
@@:
3040
        call    ntfs_decode_mcb_entry
3041
        jnc     @f
3042
        cmp     dword[esp+8], 0
3043
        jz      @b
3044
        add     edi, [esp+8]
3045
        mov     ebx, [esp]
3046
        call    ntfsSpaceFree
3047
        jnc     @b
3048
@@:
3049
        add     esp, 16
3050
        mov     [ebp+NTFS.fileDataSize], 0
3051
        ret
3052
 
6107 pathoswith 3053
ntfsSpaceClean:
3054
; clean up to 16 Mb of disk space
3055
;   in:
3056
; [ebp+NTFS.fileDataStart] = block to clean
3057
; [ebp+NTFS.fileDataSize] = block size
3058
        mov     eax, [ebp+NTFS.fileDataSize]
3059
        test    eax, eax
3060
        jz      @f
3061
        mul     [ebp+NTFS.sectors_per_cluster]
3062
        cmp     eax, 8001h
3063
        jnc     @f
3064
        push    eax
3065
        shl     eax, 9
3066
        stdcall kernel_alloc, eax
3067
        pop     ecx
3068
        test    eax, eax
3069
        jz      @f
3070
        push    ecx
3071
        shl     ecx, 7
3072
        mov     edi, eax
3073
        mov     ebx, eax
3074
        xor     eax, eax
3075
        rep stosd
3076
        mov     eax, [ebp+NTFS.fileDataStart]
3077
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 3078
        mov     [ebp+NTFS.LastRead], eax
6107 pathoswith 3079
        pop     ecx
3080
        call    fs_write64_app
3081
        stdcall kernel_free, ebx
3082
@@:
3083
        ret
3084
 
6080 pathoswith 3085
ntfsSpaceAlloc:
6292 pathoswith 3086
; allocate disk space
6080 pathoswith 3087
;   in:
3088
; edi = offset in bitmap to start search from
3089
; [ebp+NTFS.fileDataSize] = block size in clusters
3090
;   out:
6292 pathoswith 3091
; [ebp+NTFS.fileDataStart] = allocated block starting cluster
6080 pathoswith 3092
; CF=1 -> disk full
6292 pathoswith 3093
        push    eax
6080 pathoswith 3094
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3095
        add     edi, ecx
3096
        add     ecx, [ebp+NTFS.BitmapSize]
3097
        sub     ecx, edi
3098
        jnc     @f
3099
        call    bitmapBuffering
3100
        shl     ecx, 2
3101
@@:
3102
        shr     ecx, 2
3103
        mov     eax, [ebp+NTFS.fileDataSize]
3104
        shr     eax, 5
3105
        jz      .small
6292 pathoswith 3106
        mov     ebx, eax    ; bitmap dwords
6080 pathoswith 3107
.start:
3108
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3109
        add     ecx, [ebp+NTFS.BitmapSize]
3110
        sub     ecx, edi
3111
        shr     ecx, 2
3112
@@:
3113
        xor     eax, eax
3114
        repnz scasd         ; search for empty dword
3115
        jz      @f
3116
        call    bitmapBuffering
3117
        jmp     @b
3118
@@:
6292 pathoswith 3119
        cmp     ecx, ebx
6080 pathoswith 3120
        jnc     @f
3121
        call    bitmapBuffering
3122
        jmp     @b
3123
@@:
3124
        sub     edi, 4
6292 pathoswith 3125
        mov     ecx, ebx
6080 pathoswith 3126
        mov     esi, edi
3127
        xor     eax, eax
3128
        repz scasd          ; check following dwords
3129
        jnz     .start
3130
        sub     esi, 4
3131
        mov     eax, [esi]
3132
        xor     edx, edx
3133
        bsr     edx, eax
3134
        inc     edx
3135
        push    edx         ; starting bit
3136
        push    esi         ; starting dword
3137
        add     esi, 4
3138
        neg     edx
3139
        add     edx, 32
3140
        mov     eax, [ebp+NTFS.fileDataSize]
3141
        sub     eax, edx
3142
        mov     edx, eax
3143
        shr     eax, 5
3144
        shl     eax, 2
3145
        add     esi, eax
3146
        mov     eax, [esi]
3147
        bsf     ecx, eax    ; check last dword
3148
        jz      .done
3149
        and     edx, 31
3150
        cmp     ecx, edx
3151
        jnc     .done
3152
        add     esp, 8
3153
        jmp     .start
3154
 
3155
.small:     ; less than 32 clusters
3156
        mov     eax, -1
3157
        repz scasd          ; search for zero bits
3158
        test    ecx, ecx
3159
        jnz     @f
3160
        call    bitmapBuffering
3161
        jmp     .small
3162
@@:
3163
        sub     edi, 4
3164
        mov     eax, [edi]
3165
        not     eax
3166
@@:
6292 pathoswith 3167
        bsf     ebx, eax    ; first 0
6080 pathoswith 3168
        jz      .again
3169
        not     eax
3170
        shr     eax, cl
3171
        shl     eax, cl
3172
        bsf     edx, eax    ; next 1
3173
        jz      @f
6292 pathoswith 3174
        sub     edx, ebx
6080 pathoswith 3175
        cmp     edx, [ebp+NTFS.fileDataSize]
3176
        jnc     .got        ; fits inside
6292 pathoswith 3177
        bsf     ebx, eax
6080 pathoswith 3178
        not     eax
3179
        shr     eax, cl
3180
        shl     eax, cl
3181
        jmp     @b
3182
@@:         ; next dword
3183
        mov     eax, [edi+4]
3184
        bsf     edx, eax
3185
        jz      .got        ; empty
3186
        add     edx, 32
6292 pathoswith 3187
        sub     edx, ebx
6080 pathoswith 3188
        cmp     edx, [ebp+NTFS.fileDataSize]
3189
        jnc     .got        ; share between dwords
3190
.again:
3191
        add     edi, 4
3192
        jmp     .small
3193
 
3194
.got:
6292 pathoswith 3195
        push    ebx         ; starting bit
6080 pathoswith 3196
        push    edi         ; starting dword
3197
.done:      ; mark space
3198
        mov     ecx, [esp+4]
3199
        cmp     ecx, 32
3200
        jc      @f
3201
        xor     ecx, ecx
3202
        add     dword [esp], 4
3203
        mov     [esp+4], ecx
3204
@@:
3205
        mov     edi, [esp]
3206
        xor     eax, eax
3207
        dec     eax
3208
        shr     eax, cl
3209
        shl     eax, cl
3210
        neg     ecx
3211
        add     ecx, 32
3212
        sub     ecx, [ebp+NTFS.fileDataSize]
3213
        jc      @f
3214
        shl     eax, cl     ; fits inside dword
3215
        shr     eax, cl
3216
        or      [edi], eax
3217
        jmp     .end
3218
 
3219
@@:
3220
        or      [edi], eax
3221
        neg     ecx
3222
        push    ecx
3223
        shr     ecx, 5
3224
        add     edi, 4
3225
        xor     eax, eax
3226
        dec     eax
3227
        rep stosd
3228
        pop     ecx
3229
        and     ecx, 31
3230
        shr     eax, cl
3231
        shl     eax, cl
3232
        not     eax
3233
        or      [edi], eax
3234
.end:
3235
        pop     eax
6292 pathoswith 3236
        pop     ecx
6080 pathoswith 3237
        sub     eax, [ebp+NTFS.BitmapBuffer]
3238
        shl     eax, 3
6292 pathoswith 3239
        add     eax, ecx
3240
        pop     ecx
3241
        mov     ecx, [ebp+NTFS.fileDataSize]
3242
        mov     [ebp+NTFS.fileDataStart], eax
3243
        add     ecx, eax
3244
        add     ecx, 4095
3245
        shr     ecx, 3+9
3246
        shr     eax, 3+9
3247
        sub     ecx, eax
3248
        mov     ebx, eax
3249
        shl     ebx, 9
3250
        add     eax, [ebp+NTFS.BitmapLocation]
3251
        add     ebx, [ebp+NTFS.BitmapBuffer]
3252
        xor     edx, edx
3253
        jmp     fs_write64_app
6080 pathoswith 3254
 
3255
ntfsSpaceFree:
3256
; free disk space
3257
;   in:
3258
; edi = starting cluster
3259
; ebx = size in clusters
3260
        mov     eax, edi
3261
        add     eax, ebx
3262
        shr     eax, 3
3263
        inc     eax
3264
        cmp     eax, [ebp+NTFS.BitmapSize]
3265
        jc      @f
3266
        add     eax, [ebp+NTFS.BitmapBuffer]
3267
        push    edi
3268
        mov     edi, eax
3269
        call    bitmapBuffering
3270
        pop     edi
3271
@@:
3272
        push    edi
3273
        mov     ecx, edi
3274
        shr     edi, 5
3275
        shl     edi, 2
3276
        add     edi, [ebp+NTFS.BitmapBuffer]
3277
        and     ecx, 31
3278
        xor     eax, eax
3279
        dec     eax
3280
        shr     eax, cl
3281
        shl     eax, cl
3282
        neg     ecx
3283
        add     ecx, 32
3284
        sub     ecx, ebx
3285
        jc      @f
3286
        shl     eax, cl     ; fits inside dword
3287
        shr     eax, cl
3288
        not     eax
3289
        and     [edi], eax
3290
        jmp     .writeBitmap
3291
 
3292
@@:
3293
        not     eax
3294
        and     [edi], eax
3295
        neg     ecx
3296
        push    ecx
3297
        shr     ecx, 5
3298
        add     edi, 4
3299
        xor     eax, eax
3300
        rep stosd
3301
        pop     ecx
3302
        and     ecx, 31
3303
        dec     eax
3304
        shr     eax, cl
3305
        shl     eax, cl
3306
        and     [edi], eax
3307
.writeBitmap:
3308
        pop     eax
3309
        mov     edi, eax
3310
        lea     ecx, [eax+ebx+4095]
3311
        shr     eax, 3+9
3312
        shr     ecx, 3+9
3313
        sub     ecx, eax
3314
        mov     ebx, eax
3315
        shl     ebx, 9
3316
        add     eax, [ebp+NTFS.BitmapLocation]
3317
        add     ebx, [ebp+NTFS.BitmapBuffer]
3318
        xor     edx, edx
3319
        jmp     fs_write64_app
3320
 
5954 pathoswith 3321
bitmapBuffering:
3322
; Extend BitmapBuffer and read next 32kb of bitmap
3323
; Warning: $Bitmap fragmentation is not foreseen
6080 pathoswith 3324
; in: edi -> position in bitmap buffer
3325
; out: ecx = number of buffered dwords left
5954 pathoswith 3326
        push    ebx
3327
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3328
        cmp     eax, [ebp+NTFS.BitmapSize]
3329
        jz      .end
3330
        stdcall alloc_pages, 8
3331
        test    eax, eax
3332
        jz      .end
3333
        add     eax, 3
3334
        mov     ebx, [ebp+NTFS.BitmapBuffer]
3335
        add     ebx, [ebp+NTFS.BitmapSize]
3336
        push    ebx
3337
        mov     ecx, 8
3338
        call    commit_pages
3339
        mov     eax, [ebp+NTFS.BitmapSize]
3340
        shr     eax, 9
3341
        add     eax, [ebp+NTFS.BitmapLocation]
3342
        pop     ebx
3343
        mov     ecx, 64
3344
        xor     edx, edx
3345
        call    fs_read64_app
3346
        test    eax, eax
3347
        jnz     .err
3348
        add     [ebp+NTFS.BitmapSize], 8000h
3349
        mov     eax, [ebp+NTFS.BitmapTotalSize]
3350
        cmp     eax, [ebp+NTFS.BitmapSize]
3351
        jnc     @f
3352
        mov     [ebp+NTFS.BitmapSize], eax
3353
@@:
6080 pathoswith 3354
        pop     ebx
3355
        mov     ecx, [ebp+NTFS.BitmapBuffer]
3356
        add     ecx, [ebp+NTFS.BitmapSize]
6019 pathoswith 3357
        sub     ecx, edi
6080 pathoswith 3358
        jc      bitmapBuffering
5954 pathoswith 3359
        shr     ecx, 2
3360
        ret
3361
 
3362
.err:
3363
        mov     eax, [ebp+NTFS.BitmapBuffer]
3364
        add     eax, [ebp+NTFS.BitmapSize]
3365
        mov     ecx, 8
3366
        call    release_pages
3367
.end:
6292 pathoswith 3368
        add     esp, 12     ; ret
6080 pathoswith 3369
        stc
3370
        ret
5954 pathoswith 3371
 
2288 clevermous 3372
;----------------------------------------------------------------
5994 pathoswith 3373
ntfs_WriteFile:
3374
        cmp     byte [esi], 0
3375
        jnz     @f
2288 clevermous 3376
        xor     ebx, ebx
5994 pathoswith 3377
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 3378
        ret
5994 pathoswith 3379
@@:
3380
        call    ntfs_lock
3381
        stdcall ntfs_find_lfn, [esp+4]
6019 pathoswith 3382
        jc      ntfsNotFound
6273 pathoswith 3383
        cmp     [ebp+NTFS.cur_iRecord], 16
6019 pathoswith 3384
        jc      ntfsDenied
6080 pathoswith 3385
        bt      dword [eax+fileFlags], 28
3386
        jc      ntfsDenied
6273 pathoswith 3387
        cmp     [ebp+NTFS.fragmentCount], 1
6080 pathoswith 3388
        jnz     ntfsUnsupported     ; record fragmented
6151 pathoswith 3389
; edit directory node
6080 pathoswith 3390
        mov     edi, [ebp+NTFS.cur_index_buf]
3391
        cmp     dword [edi], 'INDX'
3392
        jz      @f
3393
        mov     esi, [ebp+NTFS.frs_buffer]
3394
        mov     ecx, [esi+recordRealSize]
3395
        shr     ecx, 2
3396
        rep movsd
6273 pathoswith 3397
        mov     esi, [ebp+NTFS.attr_offs]
6080 pathoswith 3398
        mov     cl, [esi+attributeOffset]
3399
        sub     esi, [ebp+NTFS.frs_buffer]
6151 pathoswith 3400
        add     eax, ecx
3401
        add     eax, esi
6080 pathoswith 3402
@@:
6151 pathoswith 3403
        mov     ecx, [ebx+4]
3404
        mov     edx, [ebx+8]
3405
        add     ecx, [ebx+12]
3406
        adc     edx, 0
3407
        mov     [eax+fileRealSize], ecx
3408
        mov     [eax+fileRealSize+4], edx
6273 pathoswith 3409
        mov     eax, [ebp+NTFS.LastRead]
6151 pathoswith 3410
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 3411
        mov     [ebp+NTFS.cur_attr], 0x80
3412
        mov     [ebp+NTFS.cur_offs], 0
3413
        mov     [ebp+NTFS.cur_size], 0
5994 pathoswith 3414
        call    ntfs_read_attr
6080 pathoswith 3415
        jc      ntfsFail
6151 pathoswith 3416
        mov     eax, ecx
6080 pathoswith 3417
        mov     ecx, [ebp+NTFS.frs_buffer]
3418
        cmp     word [ecx+baseRecordReuse], 0
6019 pathoswith 3419
        jnz     ntfsUnsupported     ; auxiliary record
6273 pathoswith 3420
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3421
        cmp     word [ecx+attributeFlags], 0
3422
        jnz     ntfsUnsupported
3423
        push    ebx
3424
        cmp     byte [ecx+nonResidentFlag], 0
3425
        jz      .resizeAttribute
5994 pathoswith 3426
        cmp     edx, [ecx+attributeRealSize+4]
6080 pathoswith 3427
        jc      .writeNode
3428
        jnz     .resizeAttribute
5994 pathoswith 3429
        cmp     [ecx+attributeRealSize], eax
6080 pathoswith 3430
        jnc     .writeNode
3431
.resizeAttribute:
3432
        call    resizeAttribute
6107 pathoswith 3433
        jc      ntfsErrorPop
6273 pathoswith 3434
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3435
        cmp     byte [ecx+nonResidentFlag], 1
3436
        jz      @f
3437
        mov     ebx, [esp]
3438
        movzx   edi, byte [ecx+attributeOffset]
3439
        add     edi, ecx
3440
        add     edi, [ebx+4]
3441
        mov     ecx, [ebx+12]
3442
        mov     esi, [ebx+16]
3443
        rep movsb
3444
@@:
6408 pathoswith 3445
        mov     ebx, [ebp+NTFS.frs_buffer]
3446
        mov     edx, [ebp+NTFS.mftLastRead]
6080 pathoswith 3447
        call    writeRecord     ; file
3448
        call    ntfs_restore_usa_frs
3449
.writeNode:
6408 pathoswith 3450
        mov     ebx, [ebp+NTFS.cur_index_buf]
3451
        mov     edx, [ebp+NTFS.nodeLastRead]
6080 pathoswith 3452
        call    writeRecord     ; directory
3453
        pop     ebx
6273 pathoswith 3454
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3455
        cmp     byte [ecx+nonResidentFlag], 0
3456
        jz      .done
3457
        mov     ecx, [ebx+12]
3458
        test    ecx, ecx
3459
        jz      .done
5994 pathoswith 3460
        mov     eax, [ebx+4]
3461
        mov     edx, [ebx+8]
3462
        mov     esi, [ebx+16]
3463
        shrd    eax, edx, 9
3464
        test    dword[ebx+4], 1FFh
3465
        jz      .aligned
6273 pathoswith 3466
        mov     [ebp+NTFS.cur_offs], eax
3467
        mov     [ebp+NTFS.cur_size], 1
3468
        lea     edi, [ebp+NTFS.bitmap_buf]
3469
        mov     [ebp+NTFS.cur_buf], edi
5994 pathoswith 3470
        call    ntfs_read_attr.continue
6019 pathoswith 3471
        jc      ntfsDevice
5994 pathoswith 3472
        mov     eax, [ebx+4]
3473
        and     eax, 1FFh
3474
        add     edi, eax
6273 pathoswith 3475
        sub     eax, [ebp+NTFS.cur_read]
5994 pathoswith 3476
        neg     eax
3477
        push    ecx
3478
        cmp     ecx, eax
3479
        jb      @f
3480
        mov     ecx, eax
3481
@@:
3482
        sub     [esp], ecx
3483
        rep movsb
3484
        push    ebx
6273 pathoswith 3485
        mov     eax, [ebp+NTFS.LastRead]
3486
        lea     ebx, [ebp+NTFS.bitmap_buf]
5994 pathoswith 3487
        mov     ecx, 1
3488
        xor     edx, edx
3489
        call    fs_write64_app
3490
        pop     ebx
3491
        pop     ecx
3492
        test    ecx, ecx
6151 pathoswith 3493
        jz      .done
5994 pathoswith 3494
        mov     eax, [ebx+4]
3495
        mov     edx, [ebx+8]
3496
        shrd    eax, edx, 9
3497
        inc     eax
3498
.aligned:
3499
        push    ecx
3500
        shr     ecx, 9
6273 pathoswith 3501
        mov     [ebp+NTFS.cur_offs], eax
3502
        mov     [ebp+NTFS.cur_size], ecx
3503
        mov     [ebp+NTFS.cur_buf], esi
5994 pathoswith 3504
        add     eax, ecx
3505
        push    eax
6273 pathoswith 3506
        mov     [ebp+NTFS.bWriteAttr], 1
5994 pathoswith 3507
        call    ntfs_read_attr.continue
6273 pathoswith 3508
        mov     [ebp+NTFS.bWriteAttr], 0
3509
        pop     [ebp+NTFS.cur_offs]
5994 pathoswith 3510
        pop     ecx
6019 pathoswith 3511
        jc      ntfsDevice
5994 pathoswith 3512
        and     ecx, 1FFh
6151 pathoswith 3513
        jz      .done
6273 pathoswith 3514
        add     esi, [ebp+NTFS.cur_read]
3515
        mov     [ebp+NTFS.cur_size], 1
3516
        lea     edi, [ebp+NTFS.bitmap_buf]
3517
        mov     [ebp+NTFS.cur_buf], edi
5994 pathoswith 3518
        call    ntfs_read_attr.continue
6019 pathoswith 3519
        jc      ntfsDevice
5994 pathoswith 3520
        rep movsb
3521
        push    ebx
6273 pathoswith 3522
        mov     eax, [ebp+NTFS.LastRead]
3523
        lea     ebx, [ebp+NTFS.bitmap_buf]
5994 pathoswith 3524
        mov     ecx, 1
3525
        xor     edx, edx
3526
        call    fs_write64_app
3527
        pop     ebx
6151 pathoswith 3528
.done:
5994 pathoswith 3529
        mov     ebx, [ebx+12]
6019 pathoswith 3530
        jmp     ntfsDone
3531
 
3532
;----------------------------------------------------------------
3533
ntfs_Delete:
6401 pathoswith 3534
        xor     ebx, ebx
6019 pathoswith 3535
        cmp     byte [esi], 0
3536
        jnz     @f
3537
        movi    eax, ERROR_ACCESS_DENIED
5994 pathoswith 3538
        ret
6401 pathoswith 3539
 
6019 pathoswith 3540
@@:
3541
        call    ntfs_lock
3542
        stdcall ntfs_find_lfn, [esp+4]
3543
        jc      ntfsNotFound
6273 pathoswith 3544
        cmp     [ebp+NTFS.cur_iRecord], 16
6019 pathoswith 3545
        jc      ntfsDenied
6273 pathoswith 3546
        cmp     [ebp+NTFS.fragmentCount], 1
6019 pathoswith 3547
        jnz     ntfsUnsupported     ; record fragmented
6273 pathoswith 3548
        mov     edx, [ebp+NTFS.cur_iRecord]
6019 pathoswith 3549
        shr     edx, 3
3550
        cmp     edx, [ebp+NTFS.mftBitmapSize]
3551
        jnc     ntfsUnsupported
6401 pathoswith 3552
        mov     edx, [ebp+NTFS.secondIndexBuffer]
3553
        mov     byte [edx], 0
3554
        mov     edx, [ebp+NTFS.LastRead]
3555
        mov     [ebp+NTFS.nodeLastRead], edx
3556
        test    byte [eax+indexFlags], 1
3557
        jz      .deleteIndex    ; no subnode
6019 pathoswith 3558
        movzx   edx, word [eax+indexAllocatedSize]
6401 pathoswith 3559
        mov     edi, eax
3560
        mov     eax, [eax+edx-8]
3561
        mov     edx, [ebp+NTFS.cur_size]
3562
        push    edx
3563
        cmp     edx, [ebp+NTFS.cur_subnode_size]
3564
        jz      @f
3565
        mul     [ebp+NTFS.sectors_per_cluster]
3566
@@:
3567
        mov     [ebp+NTFS.cur_attr], 0xA0
3568
        mov     [ebp+NTFS.cur_offs], eax
3569
        push    eax
3570
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3571
        mov     esi, ebx
3572
        mov     [ebp+NTFS.cur_buf], ebx
3573
        call    ntfs_read_attr.newAttribute
3574
        pop     [ebp+NTFS.cur_offs]
3575
        pop     eax
3576
        jc      ntfsFail
3577
        cmp     dword [esi], 'INDX'
3578
        jnz     ntfsFail
3579
        mov     [ebp+NTFS.cur_size], eax
3580
        shl     eax, 9
3581
        call    ntfs_restore_usa
3582
        jc      ntfsFail
3583
        add     esi, recordNode
3584
        cmp     byte [esi+nonLeafFlag], 0
3585
        jnz     ntfsUnsupported ; non leaf node
3586
        add     esi, [esi+indexOffset]
3587
        test    byte [esi+indexFlags], 2
3588
        jnz     .deleteSubnode  ; empty node
3589
        xor     eax, eax
3590
@@:
3591
        add     esi, eax
3592
        mov     ax, [esi+indexAllocatedSize]
3593
        test    byte [esi+eax+indexFlags], 2
3594
        jz      @b
3595
        movzx   edx, word [edi+indexAllocatedSize]
3596
        sub     edx, eax
3597
        sub     edx, 8
3598
        mov     ebx, esi
3599
        mov     eax, edi
3600
        jmp     @f
3601
 
3602
.deleteSubnode:
3603
        mov     esi, [ebp+NTFS.attr_offs]
3604
        add     esi, [esi+sizeWithHeader]
3605
        cmp     byte [esi], 0xB0
3606
        jnz     ntfsFail
3607
        movzx   eax, byte [esi+attributeOffset]
3608
        add     esi, eax
3609
        mov     eax, [ebp+NTFS.cur_offs]
3610
        xor     edx, edx
3611
        div     [ebp+NTFS.cur_size]
3612
        mov     edx, eax
3613
        shr     eax, 3
3614
        and     edx, 7
3615
        btr     [esi+eax], edx
3616
        mov     dx, [edi+indexAllocatedSize]
3617
        mov     eax, edi
3618
        mov     edi, [ebp+NTFS.secondIndexBuffer]
3619
        mov     byte [edi], 0
3620
        xor     ebx, ebx
3621
        mov     esi, [ebp+NTFS.cur_index_buf]
3622
        cmp     dword [esi], 'INDX'
3623
        jnz     @f
3624
        mov     esi, [ebp+NTFS.frs_buffer]
3625
        mov     ecx, [esi+recordRealSize]
3626
        shr     ecx, 2
3627
        rep movsd
3628
        jmp     @f
3629
 
3630
.deleteIndex:
3631
        movzx   edx, word [eax+indexAllocatedSize]
6107 pathoswith 3632
        mov     ecx, [eax+fileRecordReference]
3633
        cmp     [eax+edx+fileRecordReference], ecx
3634
        jnz     @f
3635
        add     dx, [eax+edx+indexAllocatedSize]
3636
@@:
6019 pathoswith 3637
        mov     edi, [ebp+NTFS.cur_index_buf]
3638
        cmp     dword [edi], 'INDX'
3639
        jz      .indexRecord
3640
        mov     esi, [ebp+NTFS.frs_buffer]  ; indexRoot
3641
        mov     ecx, [esi+recordRealSize]
3642
        shr     ecx, 2
3643
        rep movsd
3644
        mov     esi, [ebp+NTFS.cur_index_buf]
6401 pathoswith 3645
        mov     edi, [ebp+NTFS.indexRoot]
6019 pathoswith 3646
        sub     edi, [ebp+NTFS.frs_buffer]
3647
        add     edi, esi
3648
        sub     [edi+sizeWithHeader], edx
3649
        sub     [edi+sizeWithoutHeader], edx
3650
        mov     cl, [edi+attributeOffset]
3651
        add     edi, ecx
6273 pathoswith 3652
        sub     [edi+rootNode+nodeRealSize], edx
3653
        sub     [edi+rootNode+nodeAllocatedSize], edx
6019 pathoswith 3654
        sub     eax, esi
3655
        add     eax, edi
3656
        sub     [esi+recordRealSize], edx
3657
        mov     ecx, [esi+recordRealSize]
6401 pathoswith 3658
        cmp     [esi+recordAllocatedSize], ecx
3659
        jc      ntfsUnsupported
6019 pathoswith 3660
        jmp     @f
2288 clevermous 3661
 
6019 pathoswith 3662
.indexRecord:
6401 pathoswith 3663
        add     edi, recordNode
3664
        sub     [edi+nodeRealSize], edx
3665
        mov     ecx, [edi+nodeRealSize]
3666
        cmp     [edi+nodeAllocatedSize], ecx
3667
        jc      ntfsUnsupported
6273 pathoswith 3668
        add     ecx, recordNode
6019 pathoswith 3669
@@:
3670
        add     ecx, [ebp+NTFS.cur_index_buf]
3671
        sub     ecx, eax
3672
        mov     esi, eax
3673
        add     esi, edx
3674
        mov     edi, eax
6401 pathoswith 3675
        test    edx, edx
3676
        jns     @f
3677
        neg     edx
3678
        add     edx, ecx
3679
        sub     edx, 4
3680
        add     esi, edx
3681
        add     edi, edx
3682
        std
3683
@@:
3684
        jz      @f
3685
        shr     ecx, 2
6019 pathoswith 3686
        rep movsd
6401 pathoswith 3687
        cld
3688
@@:
3689
        test    ebx, ebx
3690
        jz      @f
3691
; copy index from the subnode to replace deleted pointing index
3692
        movzx   ecx, word [ebx+indexAllocatedSize]
3693
        mov     edx, ecx
3694
        shr     ecx, 2
3695
        mov     esi, ebx
3696
        mov     edi, eax
3697
        rep movsd
3698
        mov     edi, [ebp+NTFS.cur_index_buf]
3699
        xchg    [ebp+NTFS.secondIndexBuffer], edi
3700
        mov     [ebp+NTFS.cur_index_buf], edi
3701
        add     word [eax+indexAllocatedSize], 8
3702
        mov     byte [eax+indexFlags], 1
6273 pathoswith 3703
        mov     eax, [ebp+NTFS.LastRead]
6401 pathoswith 3704
        xchg    [ebp+NTFS.nodeLastRead], eax
3705
        mov     [ebp+NTFS.rootLastRead], eax
3706
        mov     eax, ebx
3707
        xor     ebx, ebx
3708
        jmp     .indexRecord
3709
 
6408 pathoswith 3710
.ret:
3711
        ret
3712
 
6401 pathoswith 3713
@@:         ; examine file record
6408 pathoswith 3714
        mov     [ebp+NTFS.cur_attr], 0x80   ; file?
6273 pathoswith 3715
        mov     [ebp+NTFS.cur_offs], 0
3716
        mov     [ebp+NTFS.cur_size], 0
6019 pathoswith 3717
        call    ntfs_read_attr
6408 pathoswith 3718
        jnc     @f
3719
        mov     eax, [ebp+NTFS.cur_index_size]
3720
        shl     eax, 9
3721
        stdcall kernel_alloc, eax
3722
        test    eax, eax
3723
        jz      ntfsFail
3724
        push    [ebp+NTFS.cur_index_buf]
3725
        push    [ebp+NTFS.secondIndexBuffer]
3726
        push    [ebp+NTFS.cur_index_size]
3727
        mov     [ebp+NTFS.cur_index_buf], eax
3728
        mov     [ebp+NTFS.secondIndexBuffer], eax
3729
        xor     eax, eax
3730
        push    eax eax eax eax
3731
        mov     [esp+12], esp
3732
        push    eax
3733
        mov     ebx, esp
3734
        mov     [ebp+NTFS.cur_attr], 0x90   ; folder?
3735
        call    ntfs_ReadFolder.doit
3736
        push    eax
3737
        stdcall kernel_free, [ebp+NTFS.cur_index_buf]
3738
        pop     eax
3739
        mov     edx, [esp+12]
3740
        add     esp, 20
3741
        pop     [ebp+NTFS.cur_index_size]
3742
        pop     [ebp+NTFS.secondIndexBuffer]
3743
        pop     [ebp+NTFS.cur_index_buf]
3744
        test    eax, eax
3745
        jnz     .ret
3746
        cmp     edx, 2
3747
        jnz     ntfsDenied      ; folder is not empty
3748
        mov     [ebp+NTFS.cur_attr], 0xA0
3749
        mov     [ebp+NTFS.cur_offs], 0
3750
        mov     [ebp+NTFS.cur_size], 0
3751
        call    ntfs_read_attr.newAttribute
3752
        jc      .writeBitmapMFT
3753
@@:
6019 pathoswith 3754
        mov     esi, [ebp+NTFS.frs_buffer]
3755
        cmp     word [esi+baseRecordReuse], 0
3756
        jnz     ntfsUnsupported     ; auxiliary record
6273 pathoswith 3757
        mov     esi, [ebp+NTFS.attr_offs]
6019 pathoswith 3758
        cmp     byte [esi+nonResidentFlag], 0
3759
        jz      .writeBitmapMFT
3760
        movzx   eax, byte [esi+dataRunsOffset]
3761
        add     esi, eax
3762
        xor     edi, edi
3763
        sub     esp, 16
6408 pathoswith 3764
@@:
6019 pathoswith 3765
        call    ntfs_decode_mcb_entry
6080 pathoswith 3766
        jnc     @f
6019 pathoswith 3767
        cmp     dword[esp+8], 0
6080 pathoswith 3768
        jz      @b
6019 pathoswith 3769
        add     edi, [esp+8]
3770
        mov     ebx, [esp]
6080 pathoswith 3771
        call    ntfsSpaceFree
3772
        jnc     @b
6019 pathoswith 3773
@@:
3774
        add     esp, 16
3775
.writeBitmapMFT:    ; "delete" file record
6273 pathoswith 3776
        mov     eax, [ebp+NTFS.cur_iRecord]
6019 pathoswith 3777
        mov     ecx, eax
3778
        shr     eax, 3
3779
        and     ecx, 7
3780
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
3781
        btr     [edi+eax], ecx
3782
        shr     eax, 9
3783
        mov     ebx, eax
3784
        shl     ebx, 9
3785
        add     eax, [ebp+NTFS.mftBitmapLocation]
3786
        add     ebx, edi
3787
        mov     ecx, 1
3788
        xor     edx, edx
3789
        call    fs_write64_sys
6408 pathoswith 3790
        mov     ebx, [ebp+NTFS.frs_buffer]
3791
        mov     byte [ebx+recordFlags], 0
3792
        mov     edx, [ebp+NTFS.mftLastRead]
6019 pathoswith 3793
        call    writeRecord
3794
; write directory node
6408 pathoswith 3795
        mov     ebx, [ebp+NTFS.cur_index_buf]
3796
        mov     edx, [ebp+NTFS.nodeLastRead]
6401 pathoswith 3797
        call    writeRecord
6408 pathoswith 3798
        mov     ebx, [ebp+NTFS.secondIndexBuffer]
3799
        cmp     byte [ebx], 0
6401 pathoswith 3800
        jz      ntfsDone
6408 pathoswith 3801
        mov     edx, [ebp+NTFS.rootLastRead]
6019 pathoswith 3802
        call    writeRecord
6080 pathoswith 3803
        jmp     ntfsDone
6019 pathoswith 3804
 
5954 pathoswith 3805
;----------------------------------------------------------------
3742 clevermous 3806
ntfs_SetFileEnd:
6107 pathoswith 3807
        cmp     byte [esi], 0
3808
        jnz     @f
3809
        xor     ebx, ebx
3810
        movi    eax, ERROR_ACCESS_DENIED
3811
        ret
3812
@@:
3813
        call    ntfs_lock
3814
        stdcall ntfs_find_lfn, [esp+4]
3815
        jc      ntfsNotFound
6273 pathoswith 3816
        cmp     [ebp+NTFS.cur_iRecord], 16
6107 pathoswith 3817
        jc      ntfsDenied
3818
        bt      dword [eax+fileFlags], 28
3819
        jc      ntfsDenied
6273 pathoswith 3820
        cmp     [ebp+NTFS.fragmentCount], 1
6107 pathoswith 3821
        jnz     ntfsUnsupported     ; record fragmented
6151 pathoswith 3822
; edit directory node
6107 pathoswith 3823
        mov     edi, [ebp+NTFS.cur_index_buf]
3824
        cmp     dword [edi], 'INDX'
3825
        jz      @f
3826
        mov     esi, [ebp+NTFS.frs_buffer]
3827
        mov     ecx, [esi+recordRealSize]
3828
        shr     ecx, 2
3829
        rep movsd
6273 pathoswith 3830
        mov     esi, [ebp+NTFS.attr_offs]
6107 pathoswith 3831
        mov     cl, [esi+attributeOffset]
3832
        sub     esi, [ebp+NTFS.frs_buffer]
3833
        add     eax, ecx
3834
        add     eax, esi
3835
@@:
3836
        mov     ecx, [ebx+4]
3837
        mov     edx, [ebx+8]
3838
        mov     [eax+fileRealSize], ecx
3839
        mov     [eax+fileRealSize+4], edx
6273 pathoswith 3840
        mov     eax, [ebp+NTFS.LastRead]
6107 pathoswith 3841
        mov     [ebp+NTFS.nodeLastRead], eax
6273 pathoswith 3842
        mov     [ebp+NTFS.cur_attr], 0x80
3843
        mov     [ebp+NTFS.cur_offs], 0
3844
        mov     [ebp+NTFS.cur_size], 0
6107 pathoswith 3845
        call    ntfs_read_attr
3846
        jc      ntfsFail
3847
        mov     eax, ecx
3848
        mov     ecx, [ebp+NTFS.frs_buffer]
3849
        cmp     word [ecx+baseRecordReuse], 0
3850
        jnz     ntfsUnsupported     ; auxiliary record
6273 pathoswith 3851
        mov     ecx, [ebp+NTFS.attr_offs]
6151 pathoswith 3852
        cmp     word [ecx+attributeFlags], 0
3853
        jnz     ntfsUnsupported
3854
        cmp     byte [ecx+nonResidentFlag], 0
3855
        jz      .resizeAttribute
6107 pathoswith 3856
        cmp     [ecx+attributeRealSize+4], edx
3857
        jnz     .resizeAttribute
3858
        cmp     [ecx+attributeRealSize], eax
3859
        jnc     .resizeAttribute
3860
        mov     eax, [ecx+attributeRealSize]
3861
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 3862
        mov     [ebp+NTFS.cur_size], ecx
6107 pathoswith 3863
        shl     ecx, 9
3864
        div     ecx
3865
        test    edx, edx
3866
        jz      .aligned
3867
        push    edx
3868
        push    ecx
3869
        mul     [ebp+NTFS.sectors_per_cluster]
6273 pathoswith 3870
        mov     [ebp+NTFS.cur_offs], eax
6107 pathoswith 3871
        stdcall kernel_alloc, ecx
3872
        pop     ecx
3873
        pop     edi
6405 pathoswith 3874
        mov     esi, eax
6107 pathoswith 3875
        sub     ecx, edi
3876
        add     edi, eax
6273 pathoswith 3877
        mov     [ebp+NTFS.cur_buf], eax
6107 pathoswith 3878
        call    ntfs_read_attr.continue
3879
        jc      @f
3880
        xor     eax, eax
3881
        rep stosb
3882
        push    ebx
6273 pathoswith 3883
        mov     eax, [ebp+NTFS.LastRead]
6405 pathoswith 3884
        mov     ebx, esi
6107 pathoswith 3885
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3886
        xor     edx, edx
3887
        call    fs_write64_app
3888
        pop     ebx
3889
@@:
6405 pathoswith 3890
        stdcall kernel_free, esi
6107 pathoswith 3891
.aligned:
3892
        mov     eax, [ebx+4]
3893
        mov     edx, [ebx+8]
3894
.resizeAttribute:
3895
        call    resizeAttribute
3896
        jc      ntfsError
6408 pathoswith 3897
        mov     ebx, [ebp+NTFS.frs_buffer]
3898
        mov     edx, [ebp+NTFS.mftLastRead]
6107 pathoswith 3899
        call    writeRecord     ; file
6408 pathoswith 3900
        mov     ebx, [ebp+NTFS.cur_index_buf]
3901
        mov     edx, [ebp+NTFS.nodeLastRead]
6107 pathoswith 3902
        call    writeRecord     ; directory
3903
        call    ntfsSpaceClean
3904
        jmp     ntfsDone
3905
 
3906
;----------------------------------------------------------------
3742 clevermous 3907
ntfs_SetFileInfo:
6019 pathoswith 3908
        movi    eax, ERROR_UNSUPPORTED_FS
2288 clevermous 3909
        ret
3910
 
3742 clevermous 3911
;----------------------------------------------------------------
3912
ntfs_GetFileInfo:
2288 clevermous 3913
        cmp     byte [esi], 0
3914
        jnz     @f
5994 pathoswith 3915
        movi    eax, ERROR_UNSUPPORTED_FS
2288 clevermous 3916
        ret
3917
@@:
3742 clevermous 3918
        call    ntfs_lock
3919
        stdcall ntfs_find_lfn, [esp+4]
5994 pathoswith 3920
        jnc     .found
3742 clevermous 3921
        test    eax, eax
6019 pathoswith 3922
        jz      ntfsFail
3923
        jmp     ntfsNotFound
5994 pathoswith 3924
.found:
2288 clevermous 3925
        push    esi edi
3926
        mov     esi, eax
3742 clevermous 3927
        mov     edi, [ebx+16]
2288 clevermous 3928
        xor     eax, eax
3929
        call    ntfs_direntry_to_bdfe
3930
        pop     edi esi
3742 clevermous 3931
        call    ntfs_unlock
2288 clevermous 3932
        xor     eax, eax
3933
        ret
3934
 
6019 pathoswith 3935
ntfsUnsupported:
3936
        push    ERROR_UNSUPPORTED_FS
6080 pathoswith 3937
        jmp     ntfsOut
6019 pathoswith 3938
ntfsDevice:
3939
        push    ERROR_DEVICE
3940
        jmp     ntfsOut
3941
ntfsNotFound:
3942
        push    ERROR_FILE_NOT_FOUND
3943
        jmp     ntfsOut
3944
ntfsDenied:
3945
        push    ERROR_ACCESS_DENIED
3946
        jmp     ntfsOut
3947
ntfsFail:
3948
        push    ERROR_FS_FAIL
3949
        jmp     ntfsOut
6080 pathoswith 3950
ntfsDiskFull:
3951
        push    ERROR_DISK_FULL
3952
        jmp     ntfsOut
6340 pathoswith 3953
ntfsErrorPop3:
3954
        pop     ebx
6107 pathoswith 3955
ntfsErrorPop2:
3956
        pop     ebx
3957
ntfsErrorPop:
3958
        pop     ebx
6080 pathoswith 3959
ntfsError:
3960
        push    eax
3961
ntfsOut:
3962
        call    ntfs_unlock
3963
        xor     ebx, ebx
3964
        pop     eax
3965
        ret