Subversion Repositories Kolibri OS

Rev

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