Subversion Repositories Kolibri OS

Rev

Rev 6240 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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