Subversion Repositories Kolibri OS

Rev

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