Subversion Repositories Kolibri OS

Rev

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