Subversion Repositories Kolibri OS

Rev

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