Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
6080 pathoswith 3
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 6107 $
9
 
5954 pathoswith 10
; NTFS driver
11
 
12
; Basic concepts:
13
; File is a FileRecord in the $MFT.
14
; $MFT is a file, that consists of FileRecords and starts with FileRecord of itself.
15
; FileRecord (FILE) consists of a header and attributes.
16
; Attribute consists of a header and a body.
17
; Attribute's body can be inside (resident) or outside of FileRecord.
18
; File's data is a body of $Data (80h) attribute.
19
; FileRecords is a data of the $MFT file.
20
; Directory is a file, that consists of index nodes.
21
; Resident index node is always located in a body of $IndexRoot (90h) attribute.
22
; Body of $IndexAllocation (A0h) attribute is always non resident
23
;  and consists of IndexRecords.
24
; IndexRecord (INDX) consists of a header and an index node.
25
; Index node consists of a header and indexes.
26
; Index consists of a header and a copy of indexed attribute's body.
27
; Directories index $Filename (30h) attribute of all existing files.
28
; $IndexRoot and $IndexAllocation attributes of a directory has a name — $I30.
29
 
30
; Offsets:
31
    ; record header
32
updateSequenceOffset = 4
33
updateSequenceSize = 6
34
reuseCounter = 16
35
hardLinkCounter = 12h
36
attributeOffset = 14h
37
recordFlags = 16h
38
recordRealSize = 18h
39
recordAllocatedSize = 1ch
5994 pathoswith 40
baseRecordReference = 20h       ; for auxiliary records
41
baseRecordReuse = 26h
5954 pathoswith 42
newAttributeID = 28h
43
    ; attribute header
44
attributeType = 0
45
sizeWithHeader = 4
46
nonResidentFlag = 8
47
nameLength = 9
48
nameOffset = 10
6019 pathoswith 49
attributeFlags = 12
5954 pathoswith 50
attributeID = 14
6080 pathoswith 51
    ; resident attribute header
52
sizeWithoutHeader = 10h
53
; attributeOffset = 14h
6019 pathoswith 54
indexedFlag = 16h
5954 pathoswith 55
    ; non resident attribute header
6080 pathoswith 56
firstVCN = 10h
5954 pathoswith 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
 
3742 clevermous 83
struct NTFS PARTITION
5954 pathoswith 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
2288 clevermous 105
 
5954 pathoswith 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  ?
5994 pathoswith 121
ntfsWriteAttr           db  ?   ; Warning: Don't forget to turn off!!!
5954 pathoswith 122
ntfsFragmentCount       db  ?
3742 clevermous 123
 
5954 pathoswith 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  ?
3742 clevermous 131
 
5954 pathoswith 132
ntfs_attrlist_buf       rb  0x400
133
ntfs_attrlist_mft_buf   rb  0x400
134
ntfs_bitmap_buf         rb  0x400
3742 clevermous 135
ends
136
 
5954 pathoswith 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
3742 clevermous 144
iglobal
145
align 4
146
ntfs_user_functions:
147
        dd      ntfs_free
148
        dd      (ntfs_user_functions_end - ntfs_user_functions - 4) / 4
5954 pathoswith 149
        dd      ntfs_ReadFile
3742 clevermous 150
        dd      ntfs_ReadFolder
5954 pathoswith 151
        dd      ntfs_CreateFile
5994 pathoswith 152
        dd      ntfs_WriteFile
3742 clevermous 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
 
2288 clevermous 162
ntfs_test_bootsec:
5954 pathoswith 163
; in: ebx -> buffer, edx = size of partition
164
; out: CF=1 -> invalid
2288 clevermous 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
5954 pathoswith 217
; 7. Clusters per FRS must be either power of 2 or between -31 and -9
2288 clevermous 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
5954 pathoswith 227
@@:         ; 8. Same for clusters per IndexAllocationBuffer
2288 clevermous 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
5954 pathoswith 237
@@:         ; OK, this is correct NTFS bootsector
2288 clevermous 238
        clc
239
        ret
5954 pathoswith 240
.no:        ; No, this bootsector isn't NTFS
2288 clevermous 241
        stc
242
        ret
243
 
5954 pathoswith 244
ntfs_create_partition:
5089 clevermous 245
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
246
        jnz     .nope
3742 clevermous 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
5954 pathoswith 262
        jnz     .nope
3742 clevermous 263
.boot_read_ok:
264
        call    ntfs_test_bootsec
265
        jnc     .ntfs_setup
266
.nope:
267
        xor     eax, eax
268
        jmp     .exit
5954 pathoswith 269
; By given bootsector, initialize some NTFS variables
3742 clevermous 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
5994 pathoswith 282
        mov     [eax+NTFS.ntfsWriteAttr], 0
5954 pathoswith 283
 
3742 clevermous 284
        push    ebx ebp esi
285
        mov     ebp, eax
286
        lea     ecx, [ebp+NTFS.Lock]
287
        call    mutex_init
2288 clevermous 288
        movzx   eax, byte [ebx+13]
3742 clevermous 289
        mov     [ebp+NTFS.sectors_per_cluster], eax
2288 clevermous 290
        mov     eax, [ebx+0x28]
3742 clevermous 291
        mov     dword [ebp+NTFS.Length], eax
292
        and     dword [ebp+NTFS.Length+4], 0
2288 clevermous 293
        mov     eax, [ebx+0x30]
3742 clevermous 294
        mov     [ebp+NTFS.mft_cluster], eax
2288 clevermous 295
        mov     eax, [ebx+0x38]
3742 clevermous 296
        mov     [ebp+NTFS.mftmirr_cluster], eax
2288 clevermous 297
        movsx   eax, byte [ebx+0x40]
298
        test    eax, eax
5954 pathoswith 299
        js      @f
3742 clevermous 300
        mul     [ebp+NTFS.sectors_per_cluster]
2288 clevermous 301
        shl     eax, 9
5954 pathoswith 302
        jmp     .1
303
@@:
2288 clevermous 304
        neg     eax
305
        mov     ecx, eax
306
        mov     eax, 1
307
        shl     eax, cl
5954 pathoswith 308
.1:
3742 clevermous 309
        mov     [ebp+NTFS.frs_size], eax
5954 pathoswith 310
        stdcall kernel_alloc, eax
2288 clevermous 311
        test    eax, eax
3742 clevermous 312
        jz      .fail_free
313
        mov     [ebp+NTFS.frs_buffer], eax
2288 clevermous 314
; read $MFT disposition
3742 clevermous 315
        mov     eax, [ebp+NTFS.mft_cluster]
316
        mul     [ebp+NTFS.sectors_per_cluster]
2288 clevermous 317
        call    ntfs_read_frs_sector
3742 clevermous 318
        test    eax, eax
2288 clevermous 319
        jnz     .usemirr
320
        cmp     dword [ebx], 'FILE'
321
        jnz     .usemirr
322
        call    ntfs_restore_usa_frs
323
        jnc     .mftok
324
.usemirr:
3742 clevermous 325
        mov     eax, [ebp+NTFS.mftmirr_cluster]
326
        mul     [ebp+NTFS.sectors_per_cluster]
2288 clevermous 327
        call    ntfs_read_frs_sector
3742 clevermous 328
        test    eax, eax
5954 pathoswith 329
        jnz     .fail_free_frs
2288 clevermous 330
        cmp     dword [ebx], 'FILE'
5954 pathoswith 331
        jnz     .fail_free_frs
2288 clevermous 332
        call    ntfs_restore_usa_frs
5954 pathoswith 333
        jc      .fail_free_frs
2288 clevermous 334
.mftok:
335
; read $MFT table retrieval information
336
; start with one page, increase if not enough (when MFT too fragmented)
337
        push    ebx
5954 pathoswith 338
        stdcall kernel_alloc, 0x1000
2288 clevermous 339
        pop     ebx
340
        test    eax, eax
341
        jz      .fail_free_frs
3742 clevermous 342
        mov     [ebp+NTFS.mft_retrieval], eax
343
        and     [ebp+NTFS.mft_retrieval_size], 0
344
        mov     [ebp+NTFS.mft_retrieval_alloc], 0x1000/8
2288 clevermous 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]
3742 clevermous 363
        mov     [ebp+NTFS.mft_retrieval_end], edx
2288 clevermous 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
3742 clevermous 376
        inc     [ebp+NTFS.mft_retrieval_size]
2288 clevermous 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
3742 clevermous 382
        mov     [ebp+NTFS.cur_index_size], 0x1000/0x200
5954 pathoswith 383
        stdcall kernel_alloc, 0x1000
2288 clevermous 384
        test    eax, eax
385
        jz      .fail_free_mft
3742 clevermous 386
        mov     [ebp+NTFS.cur_index_buf], eax
5954 pathoswith 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
6107 pathoswith 445
        mov     ecx, [ebp+NTFS.ntfs_attr_offs]
446
        cmp     byte [ecx+nonResidentFlag], 1
447
        jnz     .failFreeBitmapMFT
5954 pathoswith 448
        mov     [ebp+NTFS.mftBitmapSize], eax
449
        mov     eax, [ebp+NTFS.ntfsLastRead]
450
        mov     [ebp+NTFS.mftBitmapLocation], eax
2288 clevermous 451
 
3742 clevermous 452
        mov     eax, ebp
5954 pathoswith 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
3742 clevermous 476
        jmp     .pop_exit
2288 clevermous 477
 
478
.get_mft_retrieval_ptr:
479
        pushad
3742 clevermous 480
        mov     eax, [ebp+NTFS.mft_retrieval_size]
481
        cmp     eax, [ebp+NTFS.mft_retrieval_alloc]
2288 clevermous 482
        jnz     .ok
483
        add     eax, 0x1000/8
3742 clevermous 484
        mov     [ebp+NTFS.mft_retrieval_alloc], eax
2288 clevermous 485
        shl     eax, 3
5954 pathoswith 486
        stdcall kernel_alloc, eax
2288 clevermous 487
        test    eax, eax
488
        jnz     @f
489
        popad
490
        add     esp, 14h
491
        jmp     .fail_free_mft
492
@@:
3742 clevermous 493
        mov     esi, [ebp+NTFS.mft_retrieval]
2288 clevermous 494
        mov     edi, eax
3742 clevermous 495
        mov     ecx, [ebp+NTFS.mft_retrieval_size]
2288 clevermous 496
        add     ecx, ecx
497
        rep movsd
3742 clevermous 498
        push    [ebp+NTFS.mft_retrieval]
499
        mov     [ebp+NTFS.mft_retrieval], eax
2288 clevermous 500
        call    kernel_free
3742 clevermous 501
        mov     eax, [ebp+NTFS.mft_retrieval_size]
2288 clevermous 502
.ok:
503
        shl     eax, 3
3742 clevermous 504
        add     eax, [ebp+NTFS.mft_retrieval]
2288 clevermous 505
        mov     [esp+28], eax
506
        popad
507
        ret
508
 
5954 pathoswith 509
ntfs_free:
3742 clevermous 510
        push    ebx
5954 pathoswith 511
        mov     ebx, eax
3742 clevermous 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]
5954 pathoswith 515
        stdcall kernel_free, [ebx+NTFS.mftBitmapBuffer]
516
        stdcall kernel_free, [ebx+NTFS.BitmapBuffer]
517
        mov     eax, ebx
3742 clevermous 518
        pop     ebx
5954 pathoswith 519
        jmp     free
3742 clevermous 520
 
5954 pathoswith 521
ntfs_lock:
3742 clevermous 522
        lea     ecx, [ebp+NTFS.Lock]
523
        jmp     mutex_lock
524
 
5954 pathoswith 525
ntfs_unlock:
3742 clevermous 526
        lea     ecx, [ebp+NTFS.Lock]
527
        jmp     mutex_unlock
528
 
2288 clevermous 529
ntfs_read_frs_sector:
3742 clevermous 530
        push    ecx
531
        mov     ebx, [ebp+NTFS.frs_buffer]
532
        push    ebx
533
        mov     ecx, [ebp+NTFS.frs_size]
2288 clevermous 534
        shr     ecx, 9
3742 clevermous 535
        push    ecx
536
        mov     ecx, eax
2288 clevermous 537
@@:
3742 clevermous 538
        mov     eax, ecx
539
        call    fs_read32_sys
540
        test    eax, eax
2288 clevermous 541
        jnz     .fail
542
        add     ebx, 0x200
3742 clevermous 543
        inc     ecx
544
        dec     dword [esp]
545
        jnz     @b
546
        pop     eax
2288 clevermous 547
.fail:
548
        pop     ebx
3742 clevermous 549
        pop     ecx
2288 clevermous 550
        ret
551
 
552
ntfs_read_attr:
5994 pathoswith 553
; [ebp+NTFS.ntfsWriteAttr]=1 -> write attribute
5954 pathoswith 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
3742 clevermous 563
        xor     eax, eax
2288 clevermous 564
        pushad
3742 clevermous 565
        and     [ebp+NTFS.ntfs_cur_read], 0
566
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
2288 clevermous 567
        jnz     .nomft
3742 clevermous 568
        cmp     [ebp+NTFS.ntfs_cur_attr], 0x80
2288 clevermous 569
        jnz     .nomft
3742 clevermous 570
        mov     eax, [ebp+NTFS.mft_retrieval_end]
2288 clevermous 571
        inc     eax
3742 clevermous 572
        mul     [ebp+NTFS.sectors_per_cluster]
573
        cmp     eax, [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 574
        jbe     .nomft
575
; precalculated part of $Mft $DATA
3742 clevermous 576
        mov     esi, [ebp+NTFS.mft_retrieval]
577
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 578
        xor     edx, edx
3742 clevermous 579
        div     [ebp+NTFS.sectors_per_cluster]
2288 clevermous 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
3742 clevermous 588
        mov     eax, [ebp+NTFS.mft_retrieval_end]
2288 clevermous 589
        shl     eax, 3
3742 clevermous 590
        add     eax, [ebp+NTFS.mft_retrieval]
2288 clevermous 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
3742 clevermous 601
        mov     eax, [ebp+NTFS.sectors_per_cluster]
2288 clevermous 602
        mul     ecx
603
; eax = sector on partition
604
        pop     edx
605
        add     eax, edx
3742 clevermous 606
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
2288 clevermous 607
        pop     ecx
608
        neg     ecx
3742 clevermous 609
        imul    ecx, [ebp+NTFS.sectors_per_cluster]
2288 clevermous 610
        sub     ecx, edx
5954 pathoswith 611
        mov     [ebp+NTFS.ntfsLastRead], eax
3742 clevermous 612
        cmp     ecx, [ebp+NTFS.ntfs_cur_size]
2288 clevermous 613
        jb      @f
3742 clevermous 614
        mov     ecx, [ebp+NTFS.ntfs_cur_size]
2288 clevermous 615
@@:
616
; ecx = number of sequential sectors to read
3742 clevermous 617
        push    eax
618
        call    fs_read32_sys
619
        pop     edx
620
        test    eax, eax
2288 clevermous 621
        jnz     .errread
3742 clevermous 622
        add     [ebp+NTFS.ntfs_cur_read], 0x200
623
        dec     [ebp+NTFS.ntfs_cur_size]
624
        inc     [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 625
        add     ebx, 0x200
3742 clevermous 626
        mov     [ebp+NTFS.ntfs_cur_buf], ebx
627
        lea     eax, [edx+1]
2288 clevermous 628
        loop    @b
629
        pop     ecx
630
        xor     eax, eax
631
        xor     edx, edx
3742 clevermous 632
        cmp     [ebp+NTFS.ntfs_cur_size], eax
2288 clevermous 633
        jz      @f
634
        add     esi, 8
635
        push    eax
3742 clevermous 636
        mov     eax, [ebp+NTFS.mft_retrieval_end]
2288 clevermous 637
        shl     eax, 3
3742 clevermous 638
        add     eax, [ebp+NTFS.mft_retrieval]
2288 clevermous 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:
3742 clevermous 649
        mov     [esp+28], eax
2288 clevermous 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.
3742 clevermous 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
2288 clevermous 662
        call    ntfs_read_file_record
3742 clevermous 663
        jc      .errret
2288 clevermous 664
; 2. Find required attribute.
3742 clevermous 665
        mov     eax, [ebp+NTFS.frs_buffer]
6107 pathoswith 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.
2288 clevermous 669
        cmp     dword [eax+24h], 0
670
        jz      @f
671
        mov     eax, [eax+20h]
672
.beginfindattr:
3742 clevermous 673
        mov     [ebp+NTFS.ntfs_attr_iRecord], eax
2288 clevermous 674
        call    ntfs_read_file_record
3742 clevermous 675
        jc      .errret
6107 pathoswith 676
        jmp     @f
677
.newAttribute:
678
        pushad
2288 clevermous 679
@@:
680
; b) Scan for required attribute and for $ATTR_LIST
3742 clevermous 681
        mov     eax, [ebp+NTFS.frs_buffer]
2288 clevermous 682
        movzx   ecx, word [eax+14h]
683
        add     eax, ecx
3742 clevermous 684
        mov     ecx, [ebp+NTFS.ntfs_cur_attr]
685
        and     [ebp+NTFS.ntfs_attr_offs], 0
2288 clevermous 686
.scanattr:
687
        cmp     dword [eax], -1
688
        jz      .scandone
689
        cmp     dword [eax], ecx
690
        jz      .okattr
3742 clevermous 691
        cmp     [ebp+NTFS.ntfs_attr_iBaseRecord], -1
2288 clevermous 692
        jnz     .scancont
693
        cmp     dword [eax], 0x20       ; $ATTR_LIST
694
        jnz     .scancont
3742 clevermous 695
        mov     [ebp+NTFS.ntfs_attr_list], eax
2288 clevermous 696
        jmp     .scancont
697
.okattr:
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
@@:
3742 clevermous 704
        mov     [ebp+NTFS.ntfs_attr_offs], eax
2288 clevermous 705
.scancont:
706
        add     eax, [eax+4]
707
        jmp     .scanattr
708
.continue:
709
        pushad
3742 clevermous 710
        and     [ebp+NTFS.ntfs_cur_read], 0
2288 clevermous 711
.scandone:
712
; c) Check for required offset and length
3742 clevermous 713
        mov     ecx, [ebp+NTFS.ntfs_attr_offs]
2288 clevermous 714
        jecxz   .noattr
3742 clevermous 715
        push    [ebp+NTFS.ntfs_cur_size]
716
        push    [ebp+NTFS.ntfs_cur_read]
2288 clevermous 717
        call    .doreadattr
718
        pop     edx
3742 clevermous 719
        pop     ecx
2288 clevermous 720
        jc      @f
3742 clevermous 721
        cmp     [ebp+NTFS.ntfs_bCanContinue], 0
2288 clevermous 722
        jz      @f
3742 clevermous 723
        sub     edx, [ebp+NTFS.ntfs_cur_read]
2288 clevermous 724
        neg     edx
725
        shr     edx, 9
3742 clevermous 726
        sub     ecx, edx
727
        mov     [ebp+NTFS.ntfs_cur_size], ecx
2288 clevermous 728
        jnz     .not_in_cur
729
@@:
730
        popad
731
        ret
732
.noattr:
733
.not_in_cur:
3742 clevermous 734
        cmp     [ebp+NTFS.ntfs_cur_attr], 0x20
2288 clevermous 735
        jz      @f
3742 clevermous 736
        mov     ecx, [ebp+NTFS.ntfs_attr_list]
2288 clevermous 737
        test    ecx, ecx
738
        jnz     .lookattr
739
.ret_is_attr:
3742 clevermous 740
        and     dword [esp+28], 0
741
        cmp     [ebp+NTFS.ntfs_attr_offs], 1     ; CF set <=> ntfs_attr_offs == 0
2288 clevermous 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
3742 clevermous 748
        mov     eax, [ebp+NTFS.ntfs_attr_iBaseRecord]
2288 clevermous 749
        cmp     eax, -1
750
        jz      @f
751
        call    ntfs_read_file_record
3742 clevermous 752
        jc      .errret
753
        or      [ebp+NTFS.ntfs_attr_iBaseRecord], -1
2288 clevermous 754
@@:
3742 clevermous 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
2288 clevermous 768
        jnz     @f
3742 clevermous 769
        lea     eax, [ebp+NTFS.ntfs_attrlist_mft_buf]
2288 clevermous 770
@@:
3742 clevermous 771
        mov     [ebp+NTFS.ntfs_cur_buf], eax
2288 clevermous 772
        push    eax
773
        call    .doreadattr
774
        pop     esi
775
        mov     edx, 1
3742 clevermous 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]
2288 clevermous 783
        jc      .errret
784
        or      edi, -1
3742 clevermous 785
        lea     ecx, [ecx+esi-1Ah]
2288 clevermous 786
.scanliststart:
3742 clevermous 787
        push    ecx
788
        mov     eax, [ebp+NTFS.ntfs_cur_attr]
2288 clevermous 789
.scanlist:
3742 clevermous 790
        cmp     esi, [esp]
2288 clevermous 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
@@:
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
@@:
805
        push    eax
806
        mov     eax, [esi+8]
807
        test    eax, eax
808
        jnz     .testf
3742 clevermous 809
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
810
        and     eax, dword [ebp+NTFS.ntfs_attr_size+4]
2288 clevermous 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
3742 clevermous 816
        jnc     @f
2288 clevermous 817
.errret_pop:
3742 clevermous 818
        pop     ecx ecx
2288 clevermous 819
        jmp     .errret
3742 clevermous 820
.errret2_pop:
821
        xor     eax, eax
822
        jmp     .errret_pop
2288 clevermous 823
@@:
3742 clevermous 824
        mov     eax, [ebp+NTFS.frs_buffer]
2288 clevermous 825
        movzx   ecx, word [eax+14h]
826
        add     eax, ecx
3742 clevermous 827
        mov     ecx, [ebp+NTFS.ntfs_cur_attr]
2288 clevermous 828
@@:
829
        cmp     dword [eax], -1
3742 clevermous 830
        jz      .errret2_pop
2288 clevermous 831
        cmp     dword [eax], ecx
832
        jz      @f
833
.l1:
834
        add     eax, [eax+4]
835
        jmp     @b
836
@@:
837
        cmp     eax, 0x80
838
        jnz     @f
839
        cmp     byte [eax+9], 0
840
        jnz     .l1
841
@@:
842
        cmp     byte [eax+8], 0
843
        jnz     .sdnores
844
        mov     eax, [eax+10h]
3742 clevermous 845
        mov     dword [ebp+NTFS.ntfs_attr_size], eax
846
        and     dword [ebp+NTFS.ntfs_attr_size+4], 0
2288 clevermous 847
        jmp     .testfz
848
.sdnores:
849
        mov     ecx, [eax+30h]
3742 clevermous 850
        mov     dword [ebp+NTFS.ntfs_attr_size], ecx
2288 clevermous 851
        mov     ecx, [eax+34h]
3742 clevermous 852
        mov     dword [ebp+NTFS.ntfs_attr_size+4], ecx
2288 clevermous 853
.testfz:
854
        xor     eax, eax
855
.testf:
3742 clevermous 856
        imul    eax, [ebp+NTFS.sectors_per_cluster]
857
        cmp     eax, [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 858
        pop     eax
859
        ja      @f
860
        mov     edi, [esi+10h]  ; keep previous iRecord
861
        jmp     .scanlistcont
862
@@:
3742 clevermous 863
        pop     ecx
2288 clevermous 864
.scanlistfound:
865
        cmp     edi, -1
866
        jnz     @f
867
        popad
868
        ret
869
@@:
3742 clevermous 870
        mov     eax, [ebp+NTFS.ntfs_cur_iRecord]
871
        mov     [ebp+NTFS.ntfs_attr_iBaseRecord], eax
2288 clevermous 872
        mov     eax, edi
873
        jmp     .beginfindattr
874
.scanlistdone:
3742 clevermous 875
        pop     ecx
876
        sub     ecx, ebp
877
        sub     ecx, NTFS.ntfs_attrlist_buf-1Ah
878
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
2288 clevermous 879
        jnz     @f
3742 clevermous 880
        sub     ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf
2288 clevermous 881
@@:
3742 clevermous 882
        cmp     ecx, 0x400
2288 clevermous 883
        jnz     .scanlistfound
884
        inc     edx
885
        push    esi edi
3742 clevermous 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
2288 clevermous 889
        jnz     @f
3742 clevermous 890
        lea     esi, [ebp+NTFS.ntfs_attrlist_mft_buf+0x200]
891
        lea     edi, [ebp+NTFS.ntfs_attrlist_mft_buf]
2288 clevermous 892
@@:
893
        mov     ecx, 0x200/4
894
        rep movsd
895
        mov     eax, edi
896
        pop     edi esi
897
        sub     esi, 0x200
3742 clevermous 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
2288 clevermous 912
        call    .doreadattr
3742 clevermous 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]
2288 clevermous 921
        jc      .errret
3742 clevermous 922
        lea     ecx, [ecx+ebp+NTFS.ntfs_attrlist_buf+0x200-0x1A]
923
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
2288 clevermous 924
        jnz     .scanliststart
3742 clevermous 925
        add     ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf
2288 clevermous 926
        jmp     .scanliststart
927
 
928
.doreadattr:
3742 clevermous 929
        mov     [ebp+NTFS.ntfs_bCanContinue], 0
2288 clevermous 930
        cmp     byte [ecx+8], 0
931
        jnz     .nonresident
932
        mov     eax, [ecx+10h]  ; length
933
        mov     esi, eax
3742 clevermous 934
        mov     edx, [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 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
3742 clevermous 943
        mov     eax, [ebp+NTFS.ntfs_cur_size]
2288 clevermous 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
3742 clevermous 954
        mov     [ebp+NTFS.ntfs_cur_read], eax
2288 clevermous 955
        mov     ecx, eax
956
        mov     eax, edx
3742 clevermous 957
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
2288 clevermous 958
        call    memmove
3742 clevermous 959
        and     [ebp+NTFS.ntfs_cur_size], 0      ; CF=0
2288 clevermous 960
        ret
961
.nonresident:
962
; Not all auxiliary records contain correct FileSize info
3742 clevermous 963
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
964
        mov     edx, dword [ebp+NTFS.ntfs_attr_size+4]
2288 clevermous 965
        push    eax
966
        and     eax, edx
967
        cmp     eax, -1
968
        pop     eax
969
        jnz     @f
970
        mov     eax, [ecx+30h]  ; FileSize
971
        mov     edx, [ecx+34h]
3742 clevermous 972
        mov     dword [ebp+NTFS.ntfs_attr_size], eax
973
        mov     dword [ebp+NTFS.ntfs_attr_size+4], edx
2288 clevermous 974
@@:
975
        add     eax, 0x1FF
976
        adc     edx, 0
977
        shrd    eax, edx, 9
3742 clevermous 978
        sub     eax, [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 979
        ja      @f
980
; return with nothing read
3742 clevermous 981
        and     [ebp+NTFS.ntfs_cur_size], 0
2288 clevermous 982
.okret:
983
        clc
984
        ret
985
@@:
986
; reduce read length
3742 clevermous 987
        and     [ebp+NTFS.ntfs_cur_tail], 0
988
        cmp     [ebp+NTFS.ntfs_cur_size], eax
2288 clevermous 989
        jb      @f
3742 clevermous 990
        mov     [ebp+NTFS.ntfs_cur_size], eax
991
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
2288 clevermous 992
        and     eax, 0x1FF
3742 clevermous 993
        mov     [ebp+NTFS.ntfs_cur_tail], eax
2288 clevermous 994
@@:
3742 clevermous 995
        cmp     [ebp+NTFS.ntfs_cur_size], 0
2288 clevermous 996
        jz      .okret
3742 clevermous 997
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 998
        xor     edx, edx
3742 clevermous 999
        div     [ebp+NTFS.sectors_per_cluster]
2288 clevermous 1000
        sub     eax, [ecx+10h]  ; first_vbo
1001
        jb      .okret
1002
; eax = cluster, edx = starting sector
5994 pathoswith 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
@@:
2288 clevermous 1015
        sub     esp, 10h
1016
        movzx   esi, word [ecx+20h]     ; mcb_info_ofs
1017
        add     esi, ecx
3742 clevermous 1018
        xor     edi, edi
5954 pathoswith 1019
        mov     [ebp+NTFS.ntfsFragmentCount], 0
2288 clevermous 1020
.readloop:
1021
        call    ntfs_decode_mcb_entry
1022
        jnc     .break
3742 clevermous 1023
        add     edi, [esp+8]
2288 clevermous 1024
        sub     eax, [esp]
1025
        jae     .readloop
1026
        push    ecx
1027
        push    eax
1028
        add     eax, [esp+8]
3742 clevermous 1029
        add     eax, edi
1030
        imul    eax, [ebp+NTFS.sectors_per_cluster]
2288 clevermous 1031
        add     eax, edx
1032
        pop     ecx
1033
        neg     ecx
3742 clevermous 1034
        imul    ecx, [ebp+NTFS.sectors_per_cluster]
2288 clevermous 1035
        sub     ecx, edx
3742 clevermous 1036
        cmp     ecx, [ebp+NTFS.ntfs_cur_size]
2288 clevermous 1037
        jb      @f
3742 clevermous 1038
        mov     ecx, [ebp+NTFS.ntfs_cur_size]
2288 clevermous 1039
@@:
3742 clevermous 1040
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
5954 pathoswith 1041
        mov     [ebp+NTFS.ntfsLastRead], eax
1042
        push    ecx
1043
        xor     edx, edx
5994 pathoswith 1044
        call    dword[esp+18h]
5954 pathoswith 1045
        pop     ecx
3742 clevermous 1046
        test    eax, eax
2288 clevermous 1047
        jnz     .errread2
5954 pathoswith 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]
2288 clevermous 1054
        pop     ecx
1055
        xor     eax, eax
1056
        xor     edx, edx
3742 clevermous 1057
        cmp     [ebp+NTFS.ntfs_cur_size], 0
2288 clevermous 1058
        jnz     .readloop
5994 pathoswith 1059
        add     esp, 14h
3742 clevermous 1060
        mov     eax, [ebp+NTFS.ntfs_cur_tail]
2288 clevermous 1061
        test    eax, eax
1062
        jz      @f
1063
        sub     eax, 0x200
3742 clevermous 1064
        add     [ebp+NTFS.ntfs_cur_read], eax
2288 clevermous 1065
@@:
1066
        clc
1067
        ret
1068
.errread2:
1069
        pop     ecx
5994 pathoswith 1070
        add     esp, 14h
2288 clevermous 1071
        stc
1072
        ret
1073
.break:
5994 pathoswith 1074
        add     esp, 14h        ; CF=0
3742 clevermous 1075
        mov     [ebp+NTFS.ntfs_bCanContinue], 1
2288 clevermous 1076
        ret
1077
 
1078
ntfs_read_file_record:
5954 pathoswith 1079
; in: eax = iRecord
6080 pathoswith 1080
; out: [ebp+NTFS.frs_buffer] -> file record
5954 pathoswith 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]
2288 clevermous 1083
        push    ecx edx
3742 clevermous 1084
        mov     ecx, [ebp+NTFS.frs_size]
2288 clevermous 1085
        mul     ecx
1086
        shrd    eax, edx, 9
1087
        shr     edx, 9
3742 clevermous 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
2288 clevermous 1104
        shr     ecx, 9
3742 clevermous 1105
        mov     [ebp+NTFS.ntfs_cur_size], ecx
1106
        mov     eax, [ebp+NTFS.frs_buffer]
1107
        mov     [ebp+NTFS.ntfs_cur_buf], eax
2288 clevermous 1108
        call    ntfs_read_attr
3742 clevermous 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]
2288 clevermous 1124
        jnz     .errret
3742 clevermous 1125
        mov     eax, [ebp+NTFS.frs_buffer]
2288 clevermous 1126
        cmp     dword [eax], 'FILE'
1127
        jnz     .errret
1128
        push    ebx
1129
        mov     ebx, eax
1130
        call    ntfs_restore_usa_frs
1131
        pop     ebx
3742 clevermous 1132
        jc      .errret
2288 clevermous 1133
.ret:
3742 clevermous 1134
        pop     edx ecx
2288 clevermous 1135
        ret
3742 clevermous 1136
.errret:
2288 clevermous 1137
        pop     edx ecx
1138
        xor     eax, eax
3742 clevermous 1139
        stc
2288 clevermous 1140
        ret
1141
 
1142
ntfs_restore_usa_frs:
3742 clevermous 1143
        mov     eax, [ebp+NTFS.frs_size]
2288 clevermous 1144
ntfs_restore_usa:
6080 pathoswith 1145
;   in:
1146
; ebx -> record
1147
; eax = size in bytes
2288 clevermous 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:
6019 pathoswith 1175
;   in:
6080 pathoswith 1176
; esi -> MCB entry
6019 pathoswith 1177
; esp -> buffer (16 bytes)
1178
;   out:
6080 pathoswith 1179
; esi -> next MCB entry
6019 pathoswith 1180
; esp -> data run size
1181
; esp+8 -> cluster (delta)
6080 pathoswith 1182
; CF=0 -> MCB end
2288 clevermous 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
1194
        rep movsb
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
1202
        rep stosb
1203
        pop     ecx
1204
        shr     ecx, 4
1205
        cmp     ecx, 8
1206
        ja      .end
1207
        push    ecx
1208
        rep movsb
1209
        pop     ecx
1210
        sub     ecx, 8
1211
        neg     ecx
1212
        cmp     byte [esi-1], 80h
1213
        cmc
1214
        sbb     eax, eax
1215
        rep stosb
1216
        stc
1217
.end:
1218
        pop     edi ecx eax
1219
        ret
1220
 
1221
unichar_toupper:
1222
        push    eax
1223
        call    uni2ansi_char
1224
        cmp     al, '_'
1225
        jz      .unk
1226
        add     esp, 4
1504 diamond 1227
        call    char_toupper
1228
        jmp     ansi2uni_char
1229
.unk:
1230
        pop     eax
1231
        ret
2288 clevermous 1232
 
1233
ntfs_find_lfn:
5954 pathoswith 1234
; in: [esi]+[esp+4] = name
1235
;   out:
1236
; [ebp+NTFS.ntfs_cur_iRecord] = number of MFT fileRecord
5994 pathoswith 1237
; eax -> index in the parent index node
1238
; CF=1 -> file not found, eax=0 -> error
3742 clevermous 1239
        mov     [ebp+NTFS.ntfs_cur_iRecord], 5   ; start parse from root cluster
2288 clevermous 1240
.doit2:
3742 clevermous 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
2288 clevermous 1247
        call    ntfs_read_attr
5994 pathoswith 1248
        mov     eax, 0
2288 clevermous 1249
        jnc     @f
1250
.ret:
3742 clevermous 1251
        ret     4
2288 clevermous 1252
@@:
3742 clevermous 1253
        cmp     [ebp+NTFS.ntfs_cur_read], 0x20
2288 clevermous 1254
        jc      .ret
1255
        pushad
3742 clevermous 1256
        mov     esi, [ebp+NTFS.cur_index_buf]
2288 clevermous 1257
        mov     eax, [esi+14h]
1258
        add     eax, 10h
3742 clevermous 1259
        cmp     [ebp+NTFS.ntfs_cur_read], eax
2288 clevermous 1260
        jae     .readok1
1261
        add     eax, 1FFh
1262
        shr     eax, 9
3742 clevermous 1263
        cmp     eax, [ebp+NTFS.cur_index_size]
2288 clevermous 1264
        ja      @f
1265
.stc_ret:
1266
        popad
1267
        stc
3742 clevermous 1268
        ret     4
2288 clevermous 1269
@@:
1270
; reallocate
1271
        push    eax
5954 pathoswith 1272
        stdcall kernel_free, [ebp+NTFS.cur_index_buf]
2288 clevermous 1273
        pop     eax
3742 clevermous 1274
        mov     [ebp+NTFS.cur_index_size], eax
5954 pathoswith 1275
        stdcall kernel_alloc, eax
2288 clevermous 1276
        test    eax, eax
1277
        jnz     @f
3742 clevermous 1278
        and     [ebp+NTFS.cur_index_size], 0
1279
        and     [ebp+NTFS.cur_index_buf], 0
2288 clevermous 1280
        jmp     .stc_ret
1281
@@:
3742 clevermous 1282
        mov     [ebp+NTFS.cur_index_buf], eax
2288 clevermous 1283
        popad
1284
        jmp     .doit2
1285
.readok1:
3742 clevermous 1286
        mov     edx, [esi+8]    ; subnode_size
1287
        shr     edx, 9
1288
        cmp     edx, [ebp+NTFS.cur_index_size]
2288 clevermous 1289
        jbe     .ok2
3742 clevermous 1290
        push    esi edx
5954 pathoswith 1291
        stdcall kernel_alloc, edx
3742 clevermous 1292
        pop     edx esi
2288 clevermous 1293
        test    eax, eax
1294
        jz      .stc_ret
1295
        mov     edi, eax
3742 clevermous 1296
        mov     ecx, [ebp+NTFS.cur_index_size]
2288 clevermous 1297
        shl     ecx, 9-2
1298
        rep movsd
1299
        mov     esi, eax
3742 clevermous 1300
        mov     [ebp+NTFS.cur_index_size], edx
1301
        push    esi edx
5954 pathoswith 1302
        stdcall kernel_free, [ebp+NTFS.cur_index_buf]
3742 clevermous 1303
        pop     edx esi
1304
        mov     [ebp+NTFS.cur_index_buf], esi
2288 clevermous 1305
.ok2:
1306
        add     esi, 10h
1307
        mov     edi, [esp+4]
3742 clevermous 1308
; edi -> name, esi -> current index data, edx = subnode size
2288 clevermous 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
1320
        call    unichar_toupper
1321
        push    eax
1322
        mov     al, [edi]
1323
        inc     edi
1324
        cmp     al, '/'
1325
        jz      .slash
1326
        call    char_toupper
1327
        call    ansi2uni_char
1328
        cmp     ax, [esp]
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
1339
.slash:
1340
        pop     eax
1341
        pop     edi
1342
        pop     esi
1343
.subnode:
1344
        test    byte [esi+0Ch], 1
1345
        jz      .notfound
1346
        movzx   eax, word [esi+8]
1347
        mov     eax, [esi+eax-8]
3742 clevermous 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]
2288 clevermous 1353
        mov     esi, eax
3742 clevermous 1354
        mov     [ebp+NTFS.ntfs_cur_buf], eax
1355
        push    edx
2288 clevermous 1356
        call    ntfs_read_attr
3742 clevermous 1357
        pop     edx
1358
        mov     eax, edx
2288 clevermous 1359
        shl     eax, 9
3742 clevermous 1360
        cmp     [ebp+NTFS.ntfs_cur_read], eax
5954 pathoswith 1361
        jnz     .err
2288 clevermous 1362
        cmp     dword [esi], 'INDX'
5954 pathoswith 1363
        jnz     .err
1364
        mov     [ebp+NTFS.ntfs_cur_buf], esi
2288 clevermous 1365
        mov     ebx, esi
1366
        call    ntfs_restore_usa
5954 pathoswith 1367
        jc      .err
2288 clevermous 1368
        add     esi, 0x18
1369
        jmp     .scanloop
1370
.notfound:
5954 pathoswith 1371
        mov     [esp+1Ch], esi
1372
.err:
2288 clevermous 1373
        popad
1374
        stc
3742 clevermous 1375
        ret     4
2288 clevermous 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]
3742 clevermous 1389
        mov     [ebp+NTFS.ntfs_cur_iRecord], eax
2288 clevermous 1390
        mov     [esp+1Ch], esi
1391
        mov     [esp+4], edi
1392
        popad
1393
        inc     esi
1394
        cmp     byte [esi-1], 0
1395
        jnz     .doit2
3742 clevermous 1396
        cmp     dword [esp+4], 0
2288 clevermous 1397
        jz      @f
3742 clevermous 1398
        mov     esi, [esp+4]
1399
        mov     dword [esp+4], 0
2288 clevermous 1400
        jmp     .doit2
1401
@@:
3742 clevermous 1402
        ret     4
2288 clevermous 1403
 
1404
;----------------------------------------------------------------
5954 pathoswith 1405
ntfs_ReadFile:
2288 clevermous 1406
        cmp     byte [esi], 0
1407
        jnz     @f
1408
        or      ebx, -1
3598 clevermous 1409
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 1410
        ret
1411
@@:
3742 clevermous 1412
        call    ntfs_lock
1413
        stdcall ntfs_find_lfn, [esp+4]
2288 clevermous 1414
        jnc     .found
3742 clevermous 1415
        call    ntfs_unlock
2288 clevermous 1416
        or      ebx, -1
3598 clevermous 1417
        movi    eax, ERROR_FILE_NOT_FOUND
2288 clevermous 1418
        ret
1419
.found:
3742 clevermous 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
2288 clevermous 1423
        call    ntfs_read_attr
1424
        jnc     @f
3742 clevermous 1425
        call    ntfs_unlock
2288 clevermous 1426
        or      ebx, -1
3598 clevermous 1427
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 1428
        ret
1429
@@:
1430
        pushad
1431
        and     dword [esp+10h], 0
1432
        xor     eax, eax
3742 clevermous 1433
        cmp     dword [ebx+8], 0x200
2288 clevermous 1434
        jb      @f
1435
.eof0:
1436
        popad
1437
        xor     ebx, ebx
1438
.eof:
5954 pathoswith 1439
        push    ERROR_END_OF_FILE
3742 clevermous 1440
        call    ntfs_unlock
1441
        pop     eax
2288 clevermous 1442
        ret
1443
@@:
3742 clevermous 1444
        mov     ecx, [ebx+12]
1445
        mov     edx, [ebx+16]
1446
        mov     eax, [ebx+4]
2288 clevermous 1447
        test    eax, 0x1FF
1448
        jz      .alignedstart
1449
        push    edx
3742 clevermous 1450
        mov     edx, [ebx+8]
2288 clevermous 1451
        shrd    eax, edx, 9
1400 turbanoff 1452
        pop     edx
3742 clevermous 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
2288 clevermous 1457
        call    ntfs_read_attr.continue
3742 clevermous 1458
        mov     eax, [ebx+4]
2288 clevermous 1459
        and     eax, 0x1FF
3742 clevermous 1460
        lea     esi, [ebp+NTFS.ntfs_bitmap_buf+eax]
1461
        sub     eax, [ebp+NTFS.ntfs_cur_read]
2288 clevermous 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
1471
        rep movsb
1472
        mov     edx, edi
1473
        pop     ecx
1474
        sub     ecx, [esp+10h]
1475
        jnz     @f
1476
.retok:
1477
        popad
3742 clevermous 1478
        call    ntfs_unlock
2288 clevermous 1479
        xor     eax, eax
1400 turbanoff 1480
        ret
2288 clevermous 1481
@@:
3742 clevermous 1482
        cmp     [ebp+NTFS.ntfs_cur_read], 0x200
2288 clevermous 1483
        jz      .alignedstart
1484
.eof_ebx:
1485
        popad
1486
        jmp     .eof
1487
.alignedstart:
3742 clevermous 1488
        mov     eax, [ebx+4]
2288 clevermous 1489
        push    edx
3742 clevermous 1490
        mov     edx, [ebx+8]
2288 clevermous 1491
        add     eax, 511
1492
        adc     edx, 0
1493
        shrd    eax, edx, 9
1494
        pop     edx
3742 clevermous 1495
        mov     [ebp+NTFS.ntfs_cur_offs], eax
1496
        mov     [ebp+NTFS.ntfs_cur_buf], edx
2288 clevermous 1497
        mov     eax, ecx
1498
        shr     eax, 9
3742 clevermous 1499
        mov     [ebp+NTFS.ntfs_cur_size], eax
1500
        add     eax, [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 1501
        push    eax
1502
        call    ntfs_read_attr.continue
3742 clevermous 1503
        pop     [ebp+NTFS.ntfs_cur_offs]
1504
        mov     eax, [ebp+NTFS.ntfs_cur_read]
2288 clevermous 1505
        add     [esp+10h], eax
1506
        mov     eax, ecx
1507
        and     eax, not 0x1FF
3742 clevermous 1508
        cmp     [ebp+NTFS.ntfs_cur_read], eax
2288 clevermous 1509
        jnz     .eof_ebx
1510
        and     ecx, 0x1FF
1511
        jz      .retok
3742 clevermous 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
2288 clevermous 1516
        call    ntfs_read_attr.continue
3742 clevermous 1517
        cmp     [ebp+NTFS.ntfs_cur_read], ecx
2288 clevermous 1518
        jb      @f
3742 clevermous 1519
        mov     [ebp+NTFS.ntfs_cur_read], ecx
2288 clevermous 1520
@@:
3742 clevermous 1521
        xchg    ecx, [ebp+NTFS.ntfs_cur_read]
2288 clevermous 1522
        push    ecx
1523
        mov     edi, edx
3742 clevermous 1524
        lea     esi, [ebp+NTFS.ntfs_bitmap_buf]
2288 clevermous 1525
        add     [esp+10h+4], ecx
1526
        rep movsb
1527
        pop     ecx
1528
        xor     eax, eax
3742 clevermous 1529
        cmp     ecx, [ebp+NTFS.ntfs_cur_read]
2288 clevermous 1530
        jz      @f
1531
        mov     al, ERROR_END_OF_FILE
1532
@@:
1533
        mov     [esp+1Ch], eax
3742 clevermous 1534
        call    ntfs_unlock
2288 clevermous 1535
        popad
1536
        ret
1400 turbanoff 1537
 
2288 clevermous 1538
;----------------------------------------------------------------
3742 clevermous 1539
ntfs_ReadFolder:
1540
        call    ntfs_lock
2288 clevermous 1541
        mov     eax, 5          ; root cluster
1542
        cmp     byte [esi], 0
1543
        jz      .doit
3742 clevermous 1544
        stdcall ntfs_find_lfn, [esp+4]
2288 clevermous 1545
        jnc     .doit2
1546
.notfound:
1547
        or      ebx, -1
1548
        push    ERROR_FILE_NOT_FOUND
1549
.pop_ret:
3742 clevermous 1550
        call    ntfs_unlock
2288 clevermous 1551
        pop     eax
1552
        ret
1553
.doit:
3742 clevermous 1554
        mov     [ebp+NTFS.ntfs_cur_iRecord], eax
2288 clevermous 1555
.doit2:
3742 clevermous 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
2288 clevermous 1561
        call    ntfs_read_attr
1562
        jc      .notfound
3742 clevermous 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
2288 clevermous 1569
        call    ntfs_read_attr
1570
        jnc     .ok
3742 clevermous 1571
        test    eax, eax
2288 clevermous 1572
        jz      .notfound
1573
        or      ebx, -1
5994 pathoswith 1574
        push    ERROR_DEVICE
2288 clevermous 1575
        jmp     .pop_ret
1576
.ok:
3742 clevermous 1577
        cmp     [ebp+NTFS.ntfs_cur_read], 0x20
2288 clevermous 1578
        jae     @f
1579
        or      ebx, -1
1580
.fserr:
1581
        push    ERROR_FAT_TABLE
1582
        jmp     .pop_ret
1583
@@:
1584
        pushad
3742 clevermous 1585
        mov     esi, [ebp+NTFS.cur_index_buf]
2288 clevermous 1586
        mov     eax, [esi+14h]
1587
        add     eax, 10h
3742 clevermous 1588
        cmp     [ebp+NTFS.ntfs_cur_read], eax
2288 clevermous 1589
        jae     .readok1
1590
        add     eax, 1FFh
1591
        shr     eax, 9
3742 clevermous 1592
        cmp     eax, [ebp+NTFS.cur_index_size]
2288 clevermous 1593
        ja      @f
1594
        popad
1595
        jmp     .fserr
1596
@@:
1597
; reallocate
1598
        push    eax
5954 pathoswith 1599
        stdcall kernel_free, [ebp+NTFS.cur_index_buf]
2288 clevermous 1600
        pop     eax
3742 clevermous 1601
        mov     [ebp+NTFS.cur_index_size], eax
5954 pathoswith 1602
        stdcall kernel_alloc, eax
2288 clevermous 1603
        test    eax, eax
1604
        jnz     @f
3742 clevermous 1605
        and     [ebp+NTFS.cur_index_size], 0
1606
        and     [ebp+NTFS.cur_index_buf], 0
2288 clevermous 1607
.nomem:
3742 clevermous 1608
        call    ntfs_unlock
2288 clevermous 1609
        popad
1610
        or      ebx, -1
5994 pathoswith 1611
        movi    eax, ERROR_OUT_OF_MEMORY
2288 clevermous 1612
        ret
1613
@@:
3742 clevermous 1614
        mov     [ebp+NTFS.cur_index_buf], eax
2288 clevermous 1615
        popad
1616
        jmp     .doit2
1617
.readok1:
3742 clevermous 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]
2288 clevermous 1622
        jbe     .ok2
3742 clevermous 1623
        push    esi edx
5954 pathoswith 1624
        stdcall kernel_alloc, edx
3742 clevermous 1625
        pop     edx esi
2288 clevermous 1626
        test    eax, eax
1627
        jz      .nomem
1628
        mov     edi, eax
3742 clevermous 1629
        mov     ecx, [ebp+NTFS.cur_index_size]
2288 clevermous 1630
        shl     ecx, 9-2
1631
        rep movsd
1632
        mov     esi, eax
3742 clevermous 1633
        mov     [ebp+NTFS.cur_index_size], edx
5954 pathoswith 1634
        stdcall kernel_free, [ebp+NTFS.cur_index_buf]
3742 clevermous 1635
        mov     [ebp+NTFS.cur_index_buf], esi
2288 clevermous 1636
.ok2:
1637
        add     esi, 10h
3742 clevermous 1638
        mov     edx, [ebx+16]
1639
        push    dword [ebx+8]   ; read ANSI/UNICODE name
2288 clevermous 1640
; init header
1641
        mov     edi, edx
1642
        mov     ecx, 32/4
1643
        xor     eax, eax
1644
        rep stosd
1645
        mov     byte [edx], 1   ; version
3742 clevermous 1646
        mov     ecx, [ebx+12]
1647
        mov     ebx, [ebx+4]
2288 clevermous 1648
        push    edx
1649
        mov     edx, esp
3742 clevermous 1650
; edi -> BDFE, esi -> current index data, ebx = first wanted block,
2288 clevermous 1651
; ecx = number of blocks to read
1652
; edx -> parameters block: dd , dd 
3742 clevermous 1653
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 5
2288 clevermous 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:
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
3742 clevermous 1675
        lea     edi, [ebp+NTFS.ntfs_bitmap_buf]
1676
        mov     [ebp+NTFS.ntfs_cur_buf], edi
2288 clevermous 1677
        mov     ecx, 0x400/4
1678
        xor     eax, eax
1679
        rep stosd
3742 clevermous 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
2288 clevermous 1683
        call    ntfs_read_attr
1684
        pop     edi ecx
1685
        push    0       ; save offset in $BITMAP attribute
3742 clevermous 1686
        and     [ebp+NTFS.ntfs_cur_offs], 0
2288 clevermous 1687
.dumploop:
3742 clevermous 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]
2288 clevermous 1692
        mov     esi, eax
3742 clevermous 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
2288 clevermous 1698
        call    ntfs_read_attr
3742 clevermous 1699
        pop     [ebp+NTFS.ntfs_cur_offs]
1700
        mov     eax, [ebp+NTFS.cur_subnode_size]
2288 clevermous 1701
        shl     eax, 9
3742 clevermous 1702
        cmp     [ebp+NTFS.ntfs_cur_read], eax
2288 clevermous 1703
        jnz     .done
1704
        push    eax
3742 clevermous 1705
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 1706
        and     eax, 0x400*8-1
3742 clevermous 1707
        bt      dword [ebp+NTFS.ntfs_bitmap_buf], eax
2288 clevermous 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:
3742 clevermous 1727
        inc     [ebp+NTFS.ntfs_cur_offs]
1728
        test    [ebp+NTFS.ntfs_cur_offs], 0x400*8-1
2288 clevermous 1729
        jnz     .dumploop
3742 clevermous 1730
        mov     [ebp+NTFS.ntfs_cur_attr], 0xB0
2288 clevermous 1731
        push    ecx edi
3742 clevermous 1732
        lea     edi, [ebp+NTFS.ntfs_bitmap_buf]
1733
        mov     [ebp+NTFS.ntfs_cur_buf], edi
2288 clevermous 1734
        mov     ecx, 0x400/4
1735
        xor     eax, eax
1736
        rep stosd
1737
        pop     edi ecx
1738
        pop     eax
3742 clevermous 1739
        push    [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 1740
        inc     eax
3742 clevermous 1741
        mov     [ebp+NTFS.ntfs_cur_offs], eax
1742
        mov     [ebp+NTFS.ntfs_cur_size], 2
2288 clevermous 1743
        push    eax
1744
        call    ntfs_read_attr
1745
        pop     eax
3742 clevermous 1746
        pop     [ebp+NTFS.ntfs_cur_offs]
2288 clevermous 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
3742 clevermous 1761
        call    ntfs_unlock
2288 clevermous 1762
        popad
1763
        ret
1764
 
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
3742 clevermous 1781
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf]
1782
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+4]
2288 clevermous 1783
        call    ntfs_datetime_to_bdfe
3742 clevermous 1784
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf+0x18]
1785
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+0x1C]
2288 clevermous 1786
        call    ntfs_datetime_to_bdfe
3742 clevermous 1787
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf+8]
1788
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+0xC]
2288 clevermous 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
1799
        rep stosw
1800
        pop     ecx
1801
        xor     eax, eax
1802
        stosw
1803
        pop     edi
1804
        add     edi, 520
1805
        ret
1806
@@:
1807
        rep stosb
1808
        pop     ecx
1809
        xor     eax, eax
1810
        stosb
1811
        pop     edi
1812
        add     edi, 264
1813
.ret:
1814
        ret
1815
 
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
1832
        call    ntfs_direntry_to_bdfe
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
1839
        rep movsd
1840
        adc     ecx, ecx
1841
        rep movsw
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
 
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
 
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
5954 pathoswith 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
2288 clevermous 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]
1911
        pop     edx
1912
    .sec:
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
;----------------------------------------------------------------
3742 clevermous 1997
ntfs_CreateFolder:
5954 pathoswith 1998
        mov     [ebp+NTFS.ntfsFolder], 1
1999
        jmp     @f
5994 pathoswith 2000
 
5954 pathoswith 2001
ntfs_CreateFile:
2002
        mov     [ebp+NTFS.ntfsFolder], 0
2003
@@:
2004
        cmp     byte [esi], 0
2005
        jnz     @f
2288 clevermous 2006
        xor     ebx, ebx
6019 pathoswith 2007
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 2008
        ret
5954 pathoswith 2009
@@: ; 1. Search file
2010
        call    ntfs_lock
2011
        stdcall ntfs_find_lfn, [esp+4]
6080 pathoswith 2012
        jc      .notFound
2013
; found, rewrite
6019 pathoswith 2014
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 16
2015
        jc      ntfsDenied
2016
        cmp     [ebp+NTFS.ntfsFolder], 1
6080 pathoswith 2017
        jz      .folder
2018
        xor     ecx, ecx
2019
        mov     edx, [ebx+12]
2020
        mov     [ebp+NTFS.nodeLastRead], ecx
2021
        cmp     [eax+fileRealSize+4], ecx
2022
        jnz     @f
2023
        cmp     [eax+fileRealSize], edx
2024
        jz      .readAttribute
2025
@@:         ; set file size in the directory
2026
        cmp     [ebp+NTFS.ntfsFragmentCount], 1
2027
        jnz     ntfsUnsupported     ; record fragmented
2028
        mov     edi, [ebp+NTFS.cur_index_buf]
2029
        cmp     dword [edi], 'INDX'
2030
        jz      @f
2031
        mov     esi, [ebp+NTFS.frs_buffer]
2032
        mov     ecx, [esi+recordRealSize]
2033
        shr     ecx, 2
2034
        rep movsd
2035
        mov     esi, [ebp+NTFS.ntfs_attr_offs]
2036
        mov     cl, [esi+attributeOffset]
2037
        sub     esi, [ebp+NTFS.frs_buffer]
2038
        add     eax, ecx
2039
        add     eax, esi
2040
        xor     ecx, ecx
2041
@@:
2042
        mov     [eax+fileRealSize], edx
2043
        mov     [eax+fileRealSize+4], ecx
2044
        mov     eax, [ebp+NTFS.ntfsLastRead]
2045
        mov     [ebp+NTFS.nodeLastRead], eax
2046
.readAttribute:
5994 pathoswith 2047
        mov     [ebp+NTFS.ntfs_cur_attr], 0x80
2048
        mov     [ebp+NTFS.ntfs_cur_offs], 0
2049
        mov     [ebp+NTFS.ntfs_cur_size], 0
2050
        call    ntfs_read_attr
6080 pathoswith 2051
        jc      ntfsFail
2052
        mov     ecx, [ebp+NTFS.frs_buffer]
2053
        mov     eax, edx
2054
        xor     edx, edx
2055
        cmp     word [ecx+baseRecordReuse], 0
6019 pathoswith 2056
        jnz     ntfsUnsupported     ; auxiliary record
5994 pathoswith 2057
        mov     ecx, [ebp+NTFS.ntfs_attr_offs]
2058
        cmp     byte [ecx+nonResidentFlag], 1
6019 pathoswith 2059
        jnz     ntfsUnsupported     ; resident $DATA
6080 pathoswith 2060
        test    eax, eax
2061
        jz      ntfsUnsupported
2062
        cmp     [ecx+attributeRealSize+4], edx
2063
        jnz     @f
5994 pathoswith 2064
        cmp     [ecx+attributeRealSize], eax
6080 pathoswith 2065
        jz      ntfs_WriteFile.writeNode
2066
@@:
2067
        jmp     ntfs_WriteFile.resizeAttribute
5994 pathoswith 2068
 
6080 pathoswith 2069
.folder:
2070
        bt      dword [eax+fileFlags], 28
2071
        jnc     ntfsDenied
2072
        push    0
2073
        jmp     ntfsOut
2074
 
2075
.notFound:  ; create
2076
        test    eax, eax
2077
        jz      ntfsFail
2078
        cmp     [ebp+NTFS.ntfsFragmentCount], 1
2079
        jnz     ntfsUnsupported     ; record fragmented
6019 pathoswith 2080
; 2. Prepare directory record
5954 pathoswith 2081
        mov     ecx, esi
2082
@@:         ; count characters
2083
        inc     ecx
2084
        cmp     byte [ecx], '/'
6080 pathoswith 2085
        jz      ntfsNotFound    ; path folder not found
5954 pathoswith 2086
        cmp     byte [ecx], 0
2087
        jnz     @b
2088
        sub     ecx, esi
2089
        push    ecx
6080 pathoswith 2090
        lea     ecx, [ecx*2+52h+7]  ; precalculate index length
2091
        and     ecx, not 7          ; align 8
5954 pathoswith 2092
        mov     edi, [ebp+NTFS.cur_index_buf]
2093
        push    esi
2094
        push    ecx
6019 pathoswith 2095
        cmp     dword [edi], 'INDX'
5954 pathoswith 2096
        jz      .indexRecord
6019 pathoswith 2097
        mov     esi, [ebp+NTFS.frs_buffer]  ; indexRoot
5954 pathoswith 2098
        mov     edx, [esi+recordRealSize]
2099
        add     edx, ecx
2100
        cmp     [esi+recordAllocatedSize], edx
2101
        jnc     @f
2102
        add     esp, 12
6019 pathoswith 2103
        jmp     ntfsUnsupported     ; indexAllocation required
5954 pathoswith 2104
@@:         ; index fits in the indexRoot
2105
        mov     [esi+recordRealSize], edx
2106
        mov     ecx, edx
2107
        shr     ecx, 2
2108
        rep movsd
2109
        mov     edi, [ebp+NTFS.ntfs_attr_offs]
2110
        sub     edi, [ebp+NTFS.frs_buffer]
2111
        add     edi, [ebp+NTFS.cur_index_buf]
2112
        mov     esi, [esp]
2113
        add     [edi+sizeWithHeader], esi
2114
        add     [edi+sizeWithoutHeader], esi
6019 pathoswith 2115
        mov     cl, [edi+attributeOffset]
5954 pathoswith 2116
        add     edi, ecx
2117
        add     [edi+16+nodeRealSize], esi
2118
        add     [edi+16+nodeAllocatedSize], esi
2119
        sub     eax, [ebp+NTFS.cur_index_buf]
2120
        add     eax, edi
2121
        mov     edi, [ebp+NTFS.cur_index_buf]
2122
        add     edi, edx
2123
        sub     edi, 4
2124
        jmp     .common
2288 clevermous 2125
 
5954 pathoswith 2126
.indexRecord:
6019 pathoswith 2127
        mov     edx, [edi+28]
5954 pathoswith 2128
        add     edx, ecx
6019 pathoswith 2129
        cmp     [edi+32], edx
5954 pathoswith 2130
        jnc     @f
2131
        add     esp, 12
6019 pathoswith 2132
        jmp     ntfsUnsupported     ; new node required
5954 pathoswith 2133
@@:         ; index fits in the node
6019 pathoswith 2134
        mov     [edi+28], edx
2135
        lea     edi, [edi+edx+24-4]
5954 pathoswith 2136
.common:
2137
        mov     esi, edi
2138
        sub     esi, [esp]
2139
        mov     ecx, esi
2140
        sub     ecx, eax    ; eax = pointer in the node
2141
        shr     ecx, 2
2142
        inc     ecx
2143
        std
2144
        rep movsd           ; move forward, make space
2145
        mov     ecx, [esp]
2146
        shr     ecx, 2
2147
        xor     eax, eax
2148
        rep stosd
2149
        cld
2150
        add     edi, 4
2151
        pop     eax
2152
        pop     esi
2153
        mov     [edi+indexAllocatedSize], ax     ; fill index with data
2154
        mov     eax, [esp]
6080 pathoswith 2155
        shl     eax, 1
2156
        add     eax, 42h
5954 pathoswith 2157
        mov     [edi+indexRawSize], ax
2158
        mov     eax, [ebp+NTFS.ntfs_attr_iRecord]
2159
        mov     [edi+directoryRecordReference], eax
2160
        mov     eax, [ebp+NTFS.frs_buffer]
2161
        mov     eax, [eax+reuseCounter]
2162
        mov     [edi+directoryReferenceReuse], ax
2163
        mov     eax, [ebx+12]
2164
        mov     [ebp+NTFS.fileRealSize], eax
2165
        mov     [edi+fileRealSize], eax
2166
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2167
        shl     ecx, 9
2168
        add     eax, ecx
2169
        dec     eax
2170
        xor     edx, edx
2171
        div     ecx
2172
        mov     [ebp+NTFS.fileDataSize], eax
2173
        mul     ecx
2174
        mov     [edi+fileAllocatedSize], eax
2175
        pop     ecx
2176
        mov     [ebp+NTFS.indexOffset], edi
2177
        mov     [edi+fileNameLength], cl
2178
        add     edi, 52h
2179
@@:         ; record filename
2180
        lodsb
2181
        call    ansi2uni_char
2182
        stosw
2183
        dec     ecx
2184
        jnz     @b
2185
        mov     eax, [ebp+NTFS.ntfsLastRead]
2186
        mov     [ebp+NTFS.nodeLastRead], eax
2187
        cmp     [ebp+NTFS.ntfsFolder], 0
2188
        jz      @f
2189
        mov     edi, [ebp+NTFS.indexOffset]
6080 pathoswith 2190
        bts     dword [edi+fileFlags], 28
5954 pathoswith 2191
        jmp     .mftBitmap
2192
 
2193
@@: ; 3. File data
2194
        cmp     [ebp+NTFS.fileRealSize], 0
2195
        jz      .mftBitmap
6080 pathoswith 2196
        mov     edi, [ebp+NTFS.BitmapStart]
2197
        call    ntfsSpaceAlloc
2198
        jc      ntfsDiskFull
5954 pathoswith 2199
        mov     [ebp+NTFS.fileDataStart], eax
2200
        mul     [ebp+NTFS.sectors_per_cluster]
2201
        mov     ecx, [ebp+NTFS.fileRealSize]
2202
        add     ecx, 511
2203
        shr     ecx, 9
2204
        mov     ebx, [ebx+16]
2205
        call    fs_write64_app
2206
        test    eax, eax
6019 pathoswith 2207
        jnz     ntfsDevice
5954 pathoswith 2208
    ; 4. MFT record
2209
.mftBitmap: ; search for free record
2210
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2211
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2212
        mov     al, -1
2213
        add     edi, 3
2214
        sub     ecx, 3
2215
        repz scasb
2216
        dec     edi
2217
        movzx   eax, byte [edi]
2218
        not     al
2219
        bsf     ecx, eax
6107 pathoswith 2220
        jz      .extendBitmapMFT    ; no free records
6019 pathoswith 2221
        bts     [edi], ecx
2222
; get record location
5954 pathoswith 2223
        sub     edi, [ebp+NTFS.mftBitmapBuffer]
2224
        shl     edi, 3
2225
        add     edi, ecx
2226
        mov     [ebp+NTFS.newMftRecord], edi
2227
        mov     eax, [ebp+NTFS.frs_size]
2228
        shr     eax, 9
2229
        mul     edi
2230
        mov     [ebp+NTFS.ntfs_cur_iRecord], 0
2231
        mov     [ebp+NTFS.ntfs_cur_attr], 0x80
2232
        mov     [ebp+NTFS.ntfs_cur_offs], eax
2233
        mov     [ebp+NTFS.ntfs_cur_size], 1
2234
        mov     eax, [ebp+NTFS.frs_buffer]
2235
        mov     [ebp+NTFS.ntfs_cur_buf], eax
2236
        call    ntfs_read_attr
2237
        cmp     [ebp+NTFS.ntfs_cur_read], 0
6107 pathoswith 2238
        jz      .extendMFT
2239
        jmp     .mftRecord
2240
 
2241
.extendBitmapMFT:
2242
        mov     eax, [ebp+NTFS.sectors_per_cluster]
2243
        shl     eax, 9
2244
        cmp     [ebp+NTFS.mftBitmapSize], eax
2245
        jnc     ntfsUnsupported
2246
        mov     [ebp+NTFS.ntfs_cur_iRecord], 0
2247
        mov     [ebp+NTFS.ntfs_cur_attr], 0xB0
2248
        mov     [ebp+NTFS.ntfs_cur_offs], 0
2249
        mov     [ebp+NTFS.ntfs_cur_size], 0
2250
        call    ntfs_read_attr
2251
        jc      ntfsFail
5954 pathoswith 2252
        mov     eax, [ebp+NTFS.mft_cluster]
2253
        mul     [ebp+NTFS.sectors_per_cluster]
2254
        cmp     eax, [ebp+NTFS.ntfsLastRead]
6019 pathoswith 2255
        jnz     ntfsUnsupported     ; auxiliary record
6107 pathoswith 2256
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
2257
        mov     ecx, [ebp+NTFS.mftBitmapSize]
2258
        add     edi, ecx
2259
        mov     eax, ecx
2260
        mov     edx, [ebp+NTFS.ntfs_attr_offs]
2261
        add     ecx, 8
2262
        mov     [edx+attributeRealSize], ecx
2263
        mov     [edx+initialDataSize], ecx
2264
        shl     eax, 3
2265
        mov     [ebp+NTFS.newMftRecord], eax
2266
        mov     dword [edi], 1
2267
        mov     dword [edi+4], 0
2268
        mov     [ebp+NTFS.ntfs_cur_attr], 0x80
2269
        call    ntfs_read_attr.newAttribute
2270
        jc      ntfsFail
2271
        mov     [ebp+NTFS.mftBitmapSize], ecx
2272
.extendMFT:
2273
        mov     eax, [ebp+NTFS.mft_cluster]
5954 pathoswith 2274
        mul     [ebp+NTFS.sectors_per_cluster]
6107 pathoswith 2275
        cmp     eax, [ebp+NTFS.ntfsLastRead]
2276
        jnz     ntfsUnsupported     ; auxiliary record
2277
        mov     ecx, [ebp+NTFS.ntfs_attr_offs]
2278
        mov     eax, [ecx+attributeRealSize]
2279
        mov     edx, [ecx+attributeRealSize+4]
2280
        xor     ax, ax
2281
        add     eax, 10000h
2282
        adc     edx, 0
2283
        push    [ebp+NTFS.fileDataStart]
2284
        push    [ebp+NTFS.fileDataSize]
2285
        call    resizeAttribute
2286
        jc      ntfsErrorPop2
5954 pathoswith 2287
        mov     eax, [ebp+NTFS.frs_buffer]
2288
        mov     [ebp+NTFS.ntfs_cur_buf], eax
2289
        call    writeRecord     ; $MFT
2290
        mov     eax, [ebp+NTFS.mftmirr_cluster]
2291
        mul     [ebp+NTFS.sectors_per_cluster]
2292
        mov     ebx, [ebp+NTFS.frs_buffer]
2293
        movzx   ecx, word [ebx+updateSequenceSize]
2294
        dec     ecx
2295
        call    fs_write64_sys  ; $MFTMirr
6107 pathoswith 2296
        call    ntfsSpaceClean
2297
        pop     [ebp+NTFS.fileDataSize]
2298
        pop     [ebp+NTFS.fileDataStart]
5954 pathoswith 2299
.mftRecord:
2300
        mov     esi, [ebp+NTFS.indexOffset]
2301
        mov     edi, [ebp+NTFS.frs_buffer]
2302
        xor     eax, eax
2303
        movzx   ecx, word [esi+indexAllocatedSize]
2304
        add     ecx, 8+30h+48h+50h+8
2305
        push    ecx
2306
        shr     ecx, 2
2307
        rep stosd
2308
        mov     edi, [ebp+NTFS.frs_buffer]
6019 pathoswith 2309
; record header
5954 pathoswith 2310
        mov     dword[edi], 'FILE'
2311
        mov     byte [edi+updateSequenceOffset], 2ah
2312
        mov     byte [edi+updateSequenceSize], 3
2313
        mov     byte [edi+hardLinkCounter], 1
2314
        mov     byte [edi+attributeOffset], 30h
6080 pathoswith 2315
        popd    [edi+recordRealSize]
5954 pathoswith 2316
        mov     word [edi+recordAllocatedSize], 1024
2317
        mov     byte [edi+newAttributeID], 3
2318
        rdtsc
2319
        mov     [edi+2ah], ax
2320
        add     edi, 30h
6019 pathoswith 2321
; $StandardInformation
5954 pathoswith 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
6019 pathoswith 2327
; $FileName
5954 pathoswith 2328
        mov     byte [edi+attributeType], 30h
2329
        mov     byte [edi+attributeID], 1
2330
        mov     cx, [esi+indexRawSize]
2331
        mov     [edi+sizeWithoutHeader], ecx
2332
        mov     cx, [esi+indexAllocatedSize]
2333
        add     ecx, 8
2334
        mov     [edi+sizeWithHeader], ecx
2335
        mov     byte [edi+attributeOffset], 18h
6019 pathoswith 2336
        mov     byte [edi+indexedFlag], 1
5954 pathoswith 2337
        add     edi, 18h
2338
        add     esi, 16
2339
        sub     ecx, 18h
2340
        shr     ecx, 2
2341
        rep movsd
6080 pathoswith 2342
        mov     byte [edi+sizeWithHeader], 50h
2343
        mov     byte [edi+attributeID], 2
2344
        mov     dword[edi+50h], -1      ; $End
5954 pathoswith 2345
        cmp     [ebp+NTFS.ntfsFolder], 0
2346
        jnz     @f
6019 pathoswith 2347
; $Data
5954 pathoswith 2348
        mov     byte [edi+attributeType], 80h
2349
        cmp     [ebp+NTFS.fileRealSize], 0
2350
        jz      .zeroSize
2351
        mov     esi, [ebp+NTFS.indexOffset]
6080 pathoswith 2352
        mov     eax, [ebp+NTFS.fileDataSize]
2353
        dec     eax
2354
        mov     [edi+lastVCN], eax
5954 pathoswith 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
6080 pathoswith 2362
        mov     esi, edi
2363
        add     edi, 40h
2364
        call    createMcbEntry
5954 pathoswith 2365
        mov     al, 1
2366
        jmp     .writeMftRecord
2367
 
2368
.zeroSize:
2369
        mov     byte [edi+attributeOffset], 18h
2370
        mov     al, 1
2371
        jmp     .writeMftRecord
2372
 
2373
@@: ; $IndexRoot
2374
        mov     byte [edi+attributeType], 90h
2375
        mov     byte [edi+nameLength], 4
2376
        mov     byte [edi+nameOffset], 18h
2377
        mov     byte [edi+sizeWithoutHeader], 30h
2378
        mov     byte [edi+attributeOffset], 20h
2379
        mov     dword[edi+18h], 490024h     ; unicode $I30
2380
        mov     dword[edi+18h+4], 300033h
6019 pathoswith 2381
        mov     byte [edi+20h+attributeType], 30h
2382
        mov     byte [edi+20h+collationRule], 1
5954 pathoswith 2383
        mov     eax, [ebp+NTFS.sectors_per_cluster]
2384
        shl     eax, 9
6019 pathoswith 2385
        mov     [edi+20h+indexRecordSize], eax
2386
        mov     byte [edi+20h+indexRecordSizeClus], 1
2387
        mov     byte [edi+30h+indexOffset], 16
2388
        mov     byte [edi+30h+nodeRealSize], 32
2389
        mov     byte [edi+30h+nodeAllocatedSize], 32
2390
        mov     byte [edi+40h+indexAllocatedSize], 16
2391
        mov     byte [edi+40h+indexFlags], 2
5954 pathoswith 2392
        mov     al, 3
2393
.writeMftRecord:
2394
        mov     edi, [ebp+NTFS.frs_buffer]
6080 pathoswith 2395
        mov     [ebp+NTFS.ntfs_cur_buf], edi
5954 pathoswith 2396
        mov     [edi+recordFlags], al
2397
        call    writeRecord
2398
        test    eax, eax
6019 pathoswith 2399
        jnz     ntfsDevice
2400
; write MFT bitmap
5954 pathoswith 2401
        mov     eax, [ebp+NTFS.newMftRecord]
2402
        shr     eax, 3+9
2403
        mov     ebx, eax
2404
        shl     ebx, 9
2405
        add     eax, [ebp+NTFS.mftBitmapLocation]
2406
        add     ebx, [ebp+NTFS.mftBitmapBuffer]
2407
        mov     ecx, 1
2408
        xor     edx, edx
2409
        call    fs_write64_sys
2410
        test    eax, eax
6019 pathoswith 2411
        jnz     ntfsDevice
2412
; 5. Write partition bitmap
5954 pathoswith 2413
        cmp     [ebp+NTFS.ntfsFolder], 0
2414
        jnz     @f
2415
        cmp     [ebp+NTFS.fileRealSize], 0
2416
        jz      @f
6080 pathoswith 2417
        mov     eax, [ebp+NTFS.fileDataStart]
2418
        mov     ecx, [ebp+NTFS.fileDataSize]
2419
        add     ecx, eax
5954 pathoswith 2420
        add     ecx, 4095
2421
        shr     ecx, 3+9
2422
        shr     eax, 3+9
2423
        sub     ecx, eax
2424
        mov     ebx, eax
2425
        shl     ebx, 9
2426
        add     eax, [ebp+NTFS.BitmapLocation]
2427
        add     ebx, [ebp+NTFS.BitmapBuffer]
2428
        xor     edx, edx
2429
        call    fs_write64_app
2430
        test    eax, eax
6019 pathoswith 2431
        jnz     ntfsDevice
5954 pathoswith 2432
@@:
2433
        mov     edi, [ebp+NTFS.indexOffset]
2434
        mov     eax, [ebp+NTFS.newMftRecord]
2435
        mov     [edi+fileRecordReference], eax
6019 pathoswith 2436
; 6. Write directory node
5954 pathoswith 2437
        mov     eax, [ebp+NTFS.nodeLastRead]
2438
        mov     [ebp+NTFS.ntfsLastRead], eax
2439
        mov     eax, [ebp+NTFS.cur_index_buf]
2440
        mov     [ebp+NTFS.ntfs_cur_buf], eax
2441
        call    writeRecord
6019 pathoswith 2442
        mov     ebx, [ebp+NTFS.fileRealSize]
2443
ntfsDone:
5954 pathoswith 2444
        mov     esi, [ebp+PARTITION.Disk]
2445
        call    disk_sync
2446
        call    ntfs_unlock
6019 pathoswith 2447
        xor     eax, eax
5954 pathoswith 2448
        ret
2449
 
2450
writeRecord:
6080 pathoswith 2451
; make updateSequence and write to disk
5954 pathoswith 2452
;   in:
6080 pathoswith 2453
; [ebp+NTFS.ntfs_cur_buf] -> record
5954 pathoswith 2454
; [ebp+NTFS.ntfsLastRead] = partition sector
2455
        mov     esi, [ebp+NTFS.ntfs_cur_buf]
2456
        mov     edi, esi
2457
        movzx   ecx, word [esi+updateSequenceOffset]
2458
        add     edi, ecx
2459
        mov     ax, [edi]
6080 pathoswith 2460
        inc     ax
2461
        stosw
5954 pathoswith 2462
        mov     cx, [esi+updateSequenceSize]
2463
        dec     ecx
2464
        push    ecx
2465
@@:
2466
        add     esi, 510
2467
        movsw
2468
        mov     [esi-2], ax
2469
        dec     ecx
2470
        jnz     @b
2471
        mov     eax, [ebp+NTFS.ntfsLastRead]
2472
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
2473
        pop     ecx
2474
        xor     edx, edx
2475
        jmp     fs_write64_sys
2476
 
6080 pathoswith 2477
createMcbEntry:
2478
;   in:
2479
; [ebp+NTFS.fileDataStart] = position value
2480
; [ebp+NTFS.fileDataSize] = size value
2481
; edi -> destination
2482
; esi -> attribute header
2483
        mov     eax, [ebp+NTFS.fileDataStart]
2484
        xor     edx, edx
2485
        shl     eax, 1
2486
        jnc     @f
2487
        not     eax
2488
@@:
2489
        inc     edx
2490
        shr     eax, 8
2491
        jnz     @b
2492
        mov     eax, [ebp+NTFS.fileDataSize]
2493
        shl     eax, 1
2494
        xor     ecx, ecx
2495
@@:
2496
        inc     ecx
2497
        shr     eax, 8
2498
        jnz     @b
2499
        lea     eax, [edi+edx+1]
2500
        add     eax, ecx
2501
        sub     eax, esi
2502
        sub     ax, [esi+sizeWithHeader]
2503
        jc      @f
2504
        add     word [esi+sizeWithHeader], 8    ; extend attribute
2505
        mov     esi, [ebp+NTFS.frs_buffer]
2506
        mov     eax, [esi+recordRealSize]
2507
        add     eax, 8
2508
        cmp     [esi+recordAllocatedSize], eax
2509
        jc      .end    ; no space in the record
2510
        mov     [esi+recordRealSize], eax
2511
        push    ecx edi
2512
        add     esi, eax
2513
        mov     ecx, esi
2514
        sub     ecx, edi
2515
        sub     ecx, 8
2516
        shr     ecx, 2
2517
        mov     edi, esi
2518
        sub     edi, 4
2519
        sub     esi, 12
2520
        std
2521
        rep movsd
2522
        cld
2523
        pop     edi ecx
2524
@@:
2525
        mov     eax, edx
2526
        shl     eax, 4
2527
        add     eax, ecx
2528
        stosb
2529
        lea     esi, [ebp+NTFS.fileDataSize]
2530
        rep movsb
2531
        lea     esi, [ebp+NTFS.fileDataStart]
2532
        mov     ecx, edx
2533
        rep movsb
2534
.end:
2535
        ret
2536
 
2537
resizeAttribute:
2538
;   in:
2539
; [ebp+NTFS.frs_buffer] -> file record
2540
; [ebp+NTFS.ntfs_attr_offs] -> attribute
2541
; edx:eax = new size
2542
;   out:
6107 pathoswith 2543
; [ebp+NTFS.fileDataSize] = clusters added (positive)
2544
; [ebp+NTFS.fileDataStart] = added block
6080 pathoswith 2545
; CF=1 -> eax = error code
2546
        mov     esi, [ebp+NTFS.ntfs_attr_offs]
2547
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
2548
        shl     ecx, 9
2549
        mov     dword [ebp+NTFS.ntfs_attr_size], eax
2550
        mov     dword [ebp+NTFS.ntfs_attr_size+4], edx
2551
        mov     [esi+attributeRealSize], eax
2552
        mov     [esi+attributeRealSize+4], edx
2553
        mov     [esi+initialDataSize], eax
2554
        mov     [esi+initialDataSize+4], edx
2555
        sub     eax, 1
2556
        sbb     edx, 0
2557
        div     ecx
2558
        mov     edi, eax
2559
        inc     eax
2560
        mul     ecx
2561
        mov     [esi+attributeAllocatedSize], eax
2562
        mov     [esi+attributeAllocatedSize+4], edx
2563
        mov     ecx, [esi+lastVCN]
2564
        mov     [esi+lastVCN], edi
2565
        movzx   eax, byte [esi+dataRunsOffset]
2566
        sub     edi, ecx
6107 pathoswith 2567
        mov     [ebp+NTFS.fileDataSize], edi
6080 pathoswith 2568
        jz      .done
2569
        jc      .shrinkAttribute
2570
; extend attribute
2571
        xor     edi, edi
2572
        add     esi, eax
2573
        push    edi edi edi edi
2574
@@:
2575
        mov     edx, eax
2576
        mov     eax, esi
2577
        add     edi, [esp+8]
2578
        call    ntfs_decode_mcb_entry
2579
        jc      @b
2580
        mov     [esp+4], edx
2581
        mov     [esp+12], edi
2582
        add     edi, [esp]
2583
        push    edi
2584
        shr     edi, 5
2585
        shl     edi, 2
2586
        push    eax
6107 pathoswith 2587
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
2588
        jz      @f
6080 pathoswith 2589
        cmp     edi, [ebp+NTFS.BitmapStart]
2590
        jc      .err1
6107 pathoswith 2591
@@:
6080 pathoswith 2592
        call    ntfsSpaceAlloc
2593
        jc      .err1
2594
        pop     edi
2595
        pop     edx
2596
        cmp     edx, eax
2597
        jnz     .newEntry
2598
        pop     edx
2599
        pop     edi
2600
        pop     [ebp+NTFS.fileDataStart]
2601
        mov     [esp], eax
2602
        push    [ebp+NTFS.fileDataSize]
2603
        add     [ebp+NTFS.fileDataSize], edx
2604
        jmp     @f
2605
 
2606
.newEntry:
2607
        add     esp, 12
2608
        pop     edx
2609
        push    eax
2610
        push    [ebp+NTFS.fileDataSize]
2611
        sub     eax, edx
2612
        mov     [ebp+NTFS.fileDataStart], eax
2613
@@:
2614
        mov     esi, [ebp+NTFS.ntfs_attr_offs]
2615
        call    createMcbEntry
2616
        pop     ecx
2617
        pop     eax
2618
        jc      .err2
2619
        mov     byte [edi], 0
6107 pathoswith 2620
        mov     [ebp+NTFS.fileDataSize], ecx
2621
        mov     [ebp+NTFS.fileDataStart], eax
6080 pathoswith 2622
        add     ecx, eax
2623
        add     ecx, 4095
2624
        shr     ecx, 3+9
2625
        shr     eax, 3+9
2626
        sub     ecx, eax
2627
        mov     ebx, eax
2628
        shl     ebx, 9
2629
        add     eax, [ebp+NTFS.BitmapLocation]
2630
        add     ebx, [ebp+NTFS.BitmapBuffer]
2631
        xor     edx, edx
2632
        call    fs_write64_app
2633
        test    eax, eax
2634
        jz      .done
2635
        movi    eax, ERROR_DEVICE
2636
        stc
2637
.done:
2638
        ret
2639
 
2640
.err1:
2641
        movi    eax, ERROR_DISK_FULL
2642
        add     esp, 24
2643
        stc
2644
        ret
2645
 
2646
.err2:
2647
        movi    eax, ERROR_UNSUPPORTED_FS
2648
        ret
2649
 
2650
.shrinkAttribute:
2651
        add     ecx, edi
2652
        inc     ecx
2653
        add     esi, eax
2654
        xor     edi, edi
2655
        sub     esp, 20
2656
@@:
2657
        mov     [esp+16], esi
2658
        call    ntfs_decode_mcb_entry
2659
        jnc     .err3
2660
        add     edi, [esp+8]
2661
        sub     ecx, [esp]
2662
        jnc     @b
2663
        mov     ebx, ecx
2664
        add     ecx, [esp]
2665
        mov     eax, [esp+8]
2666
        mov     [ebp+NTFS.fileDataSize], ecx
2667
        mov     [ebp+NTFS.fileDataStart], eax
2668
        push    edi
2669
        add     edi, ecx
2670
        neg     ebx
2671
        call    ntfsSpaceFree
2672
        pop     edi
2673
        jc      .end
2674
@@:
2675
        call    ntfs_decode_mcb_entry
2676
        jnc     .end
2677
        cmp     dword[esp+8], 0
2678
        jz      @b
2679
        add     edi, [esp+8]
2680
        mov     ebx, [esp]
2681
        call    ntfsSpaceFree
2682
        jnc     @b
2683
.end:
2684
        add     esp, 16
2685
        pop     edi
2686
        cmp     [ebp+NTFS.fileDataSize], 0
2687
        jz      @f
2688
        mov     esi, [ebp+NTFS.ntfs_attr_offs]
2689
        call    createMcbEntry
6107 pathoswith 2690
        mov     [ebp+NTFS.fileDataSize], 0
6080 pathoswith 2691
@@:
2692
        mov     byte [edi], 0
2693
        ret
2694
 
2695
.err3:
2696
        movi    eax, ERROR_FS_FAIL
2697
        add     esp, 20
2698
        stc
2699
        ret
2700
 
6107 pathoswith 2701
ntfsSpaceClean:
2702
; clean up to 16 Mb of disk space
2703
;   in:
2704
; [ebp+NTFS.fileDataStart] = block to clean
2705
; [ebp+NTFS.fileDataSize] = block size
2706
        mov     eax, [ebp+NTFS.fileDataSize]
2707
        test    eax, eax
2708
        jz      @f
2709
        mul     [ebp+NTFS.sectors_per_cluster]
2710
        cmp     eax, 8001h
2711
        jnc     @f
2712
        push    eax
2713
        shl     eax, 9
2714
        stdcall kernel_alloc, eax
2715
        pop     ecx
2716
        test    eax, eax
2717
        jz      @f
2718
        push    ecx
2719
        shl     ecx, 7
2720
        mov     edi, eax
2721
        mov     ebx, eax
2722
        xor     eax, eax
2723
        rep stosd
2724
        mov     eax, [ebp+NTFS.fileDataStart]
2725
        mul     [ebp+NTFS.sectors_per_cluster]
2726
        mov     [ebp+NTFS.ntfsLastRead], eax
2727
        pop     ecx
2728
        call    fs_write64_app
2729
        stdcall kernel_free, ebx
2730
@@:
2731
        ret
2732
 
6080 pathoswith 2733
ntfsSpaceAlloc:
2734
; find and mark block of free space in bitmap buffer
2735
;   in:
2736
; edi = offset in bitmap to start search from
2737
; [ebp+NTFS.fileDataSize] = block size in clusters
2738
;   out:
2739
; eax = allocated block starting cluster
2740
; CF=1 -> disk full
2741
        mov     ecx, [ebp+NTFS.BitmapBuffer]
2742
        add     edi, ecx
2743
        add     ecx, [ebp+NTFS.BitmapSize]
2744
        sub     ecx, edi
2745
        jnc     @f
2746
        call    bitmapBuffering
2747
        shl     ecx, 2
2748
@@:
2749
        shr     ecx, 2
2750
        mov     eax, [ebp+NTFS.fileDataSize]
2751
        shr     eax, 5
2752
        jz      .small
2753
        push    eax         ; bitmap dwords
2754
.start:
2755
        mov     ecx, [ebp+NTFS.BitmapBuffer]
2756
        add     ecx, [ebp+NTFS.BitmapSize]
2757
        sub     ecx, edi
2758
        shr     ecx, 2
2759
@@:
2760
        xor     eax, eax
2761
        repnz scasd         ; search for empty dword
2762
        jz      @f
2763
        call    bitmapBuffering
2764
        jmp     @b
2765
@@:
2766
        cmp     ecx, [esp]
2767
        jnc     @f
2768
        call    bitmapBuffering
2769
        jmp     @b
2770
@@:
2771
        sub     edi, 4
2772
        mov     ecx, [esp]
2773
        mov     esi, edi
2774
        xor     eax, eax
2775
        repz scasd          ; check following dwords
2776
        jnz     .start
2777
        sub     esi, 4
2778
        mov     eax, [esi]
2779
        xor     edx, edx
2780
        bsr     edx, eax
2781
        inc     edx
2782
        push    edx         ; starting bit
2783
        push    esi         ; starting dword
2784
        add     esi, 4
2785
        neg     edx
2786
        add     edx, 32
2787
        mov     eax, [ebp+NTFS.fileDataSize]
2788
        sub     eax, edx
2789
        mov     edx, eax
2790
        shr     eax, 5
2791
        shl     eax, 2
2792
        add     esi, eax
2793
        mov     eax, [esi]
2794
        bsf     ecx, eax    ; check last dword
2795
        jz      .done
2796
        and     edx, 31
2797
        cmp     ecx, edx
2798
        jnc     .done
2799
        add     esp, 8
2800
        jmp     .start
2801
 
2802
.small:     ; less than 32 clusters
2803
        mov     eax, -1
2804
        repz scasd          ; search for zero bits
2805
        push    ecx
2806
        test    ecx, ecx
2807
        jnz     @f
2808
        call    bitmapBuffering
2809
        pop     eax
2810
        jmp     .small
2811
@@:
2812
        sub     edi, 4
2813
        mov     eax, [edi]
2814
        not     eax
2815
@@:
2816
        bsf     ecx, eax    ; first 0
2817
        jz      .again
2818
        not     eax
2819
        shr     eax, cl
2820
        shl     eax, cl
2821
        bsf     edx, eax    ; next 1
2822
        jz      @f
2823
        sub     edx, ecx
2824
        cmp     edx, [ebp+NTFS.fileDataSize]
2825
        jnc     .got        ; fits inside
2826
        bsf     ecx, eax
2827
        not     eax
2828
        shr     eax, cl
2829
        shl     eax, cl
2830
        jmp     @b
2831
@@:         ; next dword
2832
        mov     eax, [edi+4]
2833
        bsf     edx, eax
2834
        jz      .got        ; empty
2835
        add     edx, 32
2836
        sub     edx, ecx
2837
        cmp     edx, [ebp+NTFS.fileDataSize]
2838
        jnc     .got        ; share between dwords
2839
.again:
2840
        add     edi, 4
2841
        pop     ecx
2842
        jmp     .small
2843
 
2844
.got:
2845
        push    ecx         ; starting bit
2846
        push    edi         ; starting dword
2847
.done:      ; mark space
2848
        mov     ecx, [esp+4]
2849
        cmp     ecx, 32
2850
        jc      @f
2851
        xor     ecx, ecx
2852
        add     dword [esp], 4
2853
        mov     [esp+4], ecx
2854
@@:
2855
        mov     edi, [esp]
2856
        xor     eax, eax
2857
        dec     eax
2858
        shr     eax, cl
2859
        shl     eax, cl
2860
        neg     ecx
2861
        add     ecx, 32
2862
        sub     ecx, [ebp+NTFS.fileDataSize]
2863
        jc      @f
2864
        shl     eax, cl     ; fits inside dword
2865
        shr     eax, cl
2866
        or      [edi], eax
2867
        jmp     .end
2868
 
2869
@@:
2870
        or      [edi], eax
2871
        neg     ecx
2872
        push    ecx
2873
        shr     ecx, 5
2874
        add     edi, 4
2875
        xor     eax, eax
2876
        dec     eax
2877
        rep stosd
2878
        pop     ecx
2879
        and     ecx, 31
2880
        shr     eax, cl
2881
        shl     eax, cl
2882
        not     eax
2883
        or      [edi], eax
2884
.end:
2885
        pop     eax
2886
        sub     eax, [ebp+NTFS.BitmapBuffer]
2887
        shl     eax, 3
2888
        pop     edx
2889
        add     eax, edx
2890
        pop     edx
2891
        ret
2892
 
2893
ntfsSpaceFree:
2894
; free disk space
2895
;   in:
2896
; edi = starting cluster
2897
; ebx = size in clusters
2898
        mov     eax, edi
2899
        add     eax, ebx
2900
        shr     eax, 3
2901
        inc     eax
2902
        cmp     eax, [ebp+NTFS.BitmapSize]
2903
        jc      @f
2904
        add     eax, [ebp+NTFS.BitmapBuffer]
2905
        push    edi
2906
        mov     edi, eax
2907
        call    bitmapBuffering
2908
        pop     edi
2909
@@:
2910
        push    edi
2911
        mov     ecx, edi
2912
        shr     edi, 5
2913
        shl     edi, 2
2914
        add     edi, [ebp+NTFS.BitmapBuffer]
2915
        and     ecx, 31
2916
        xor     eax, eax
2917
        dec     eax
2918
        shr     eax, cl
2919
        shl     eax, cl
2920
        neg     ecx
2921
        add     ecx, 32
2922
        sub     ecx, ebx
2923
        jc      @f
2924
        shl     eax, cl     ; fits inside dword
2925
        shr     eax, cl
2926
        not     eax
2927
        and     [edi], eax
2928
        jmp     .writeBitmap
2929
 
2930
@@:
2931
        not     eax
2932
        and     [edi], eax
2933
        neg     ecx
2934
        push    ecx
2935
        shr     ecx, 5
2936
        add     edi, 4
2937
        xor     eax, eax
2938
        rep stosd
2939
        pop     ecx
2940
        and     ecx, 31
2941
        dec     eax
2942
        shr     eax, cl
2943
        shl     eax, cl
2944
        and     [edi], eax
2945
.writeBitmap:
2946
        pop     eax
2947
        mov     edi, eax
2948
        lea     ecx, [eax+ebx+4095]
2949
        shr     eax, 3+9
2950
        shr     ecx, 3+9
2951
        sub     ecx, eax
2952
        mov     ebx, eax
2953
        shl     ebx, 9
2954
        add     eax, [ebp+NTFS.BitmapLocation]
2955
        add     ebx, [ebp+NTFS.BitmapBuffer]
2956
        xor     edx, edx
2957
        jmp     fs_write64_app
2958
 
5954 pathoswith 2959
bitmapBuffering:
2960
; Extend BitmapBuffer and read next 32kb of bitmap
2961
; Warning: $Bitmap fragmentation is not foreseen
6080 pathoswith 2962
; in: edi -> position in bitmap buffer
2963
; out: ecx = number of buffered dwords left
5954 pathoswith 2964
        push    ebx
2965
        mov     eax, [ebp+NTFS.BitmapTotalSize]
2966
        cmp     eax, [ebp+NTFS.BitmapSize]
2967
        jz      .end
2968
        stdcall alloc_pages, 8
2969
        test    eax, eax
2970
        jz      .end
2971
        add     eax, 3
2972
        mov     ebx, [ebp+NTFS.BitmapBuffer]
2973
        add     ebx, [ebp+NTFS.BitmapSize]
2974
        push    ebx
2975
        mov     ecx, 8
2976
        call    commit_pages
2977
        mov     eax, [ebp+NTFS.BitmapSize]
2978
        shr     eax, 9
2979
        add     eax, [ebp+NTFS.BitmapLocation]
2980
        pop     ebx
2981
        mov     ecx, 64
2982
        xor     edx, edx
2983
        call    fs_read64_app
2984
        test    eax, eax
2985
        jnz     .err
2986
        add     [ebp+NTFS.BitmapSize], 8000h
2987
        mov     eax, [ebp+NTFS.BitmapTotalSize]
2988
        cmp     eax, [ebp+NTFS.BitmapSize]
2989
        jnc     @f
2990
        mov     [ebp+NTFS.BitmapSize], eax
2991
@@:
6080 pathoswith 2992
        pop     ebx
2993
        mov     ecx, [ebp+NTFS.BitmapBuffer]
2994
        add     ecx, [ebp+NTFS.BitmapSize]
6019 pathoswith 2995
        sub     ecx, edi
6080 pathoswith 2996
        jc      bitmapBuffering
5954 pathoswith 2997
        shr     ecx, 2
2998
        ret
2999
 
3000
.err:
3001
        mov     eax, [ebp+NTFS.BitmapBuffer]
3002
        add     eax, [ebp+NTFS.BitmapSize]
3003
        mov     ecx, 8
3004
        call    release_pages
3005
.end:
6080 pathoswith 3006
        pop     ebx
3007
        pop     eax     ; ret
3008
        pop     eax
3009
        stc
3010
        ret
5954 pathoswith 3011
 
2288 clevermous 3012
;----------------------------------------------------------------
5994 pathoswith 3013
ntfs_WriteFile:
3014
        cmp     byte [esi], 0
3015
        jnz     @f
2288 clevermous 3016
        xor     ebx, ebx
5994 pathoswith 3017
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 3018
        ret
5994 pathoswith 3019
@@:
3020
        call    ntfs_lock
3021
        stdcall ntfs_find_lfn, [esp+4]
6019 pathoswith 3022
        jc      ntfsNotFound
3023
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 16
3024
        jc      ntfsDenied
6080 pathoswith 3025
        bt      dword [eax+fileFlags], 28
3026
        jc      ntfsDenied
3027
        mov     ecx, eax
3028
        mov     eax, [ebx+4]
3029
        mov     edx, [ebx+8]
3030
        add     eax, [ebx+12]
3031
        adc     edx, 0
3032
        mov     [ebp+NTFS.nodeLastRead], 0
3033
        cmp     edx, [ecx+fileRealSize+4]
3034
        jc      .readAttribute
3035
        jnz     @f
3036
        cmp     [ecx+fileRealSize], eax
3037
        jnc     .readAttribute
3038
@@:         ; set file size in the directory
3039
        cmp     [ebp+NTFS.ntfsFragmentCount], 1
3040
        jnz     ntfsUnsupported     ; record fragmented
3041
        mov     edi, [ebp+NTFS.cur_index_buf]
3042
        cmp     dword [edi], 'INDX'
3043
        jz      @f
3044
        mov     esi, [ebp+NTFS.frs_buffer]
3045
        push    ecx
3046
        mov     ecx, [esi+recordRealSize]
3047
        shr     ecx, 2
3048
        rep movsd
3049
        mov     esi, [ebp+NTFS.ntfs_attr_offs]
3050
        mov     cl, [esi+attributeOffset]
3051
        sub     esi, [ebp+NTFS.frs_buffer]
3052
        add     esi, ecx
3053
        pop     ecx
3054
        add     ecx, esi
3055
@@:
3056
        mov     [ecx+fileRealSize], eax
3057
        mov     [ecx+fileRealSize+4], edx
3058
        mov     ecx, [ebp+NTFS.ntfsLastRead]
3059
        mov     [ebp+NTFS.nodeLastRead], ecx
3060
.readAttribute:
5994 pathoswith 3061
        mov     [ebp+NTFS.ntfs_cur_attr], 0x80
3062
        mov     [ebp+NTFS.ntfs_cur_offs], 0
3063
        mov     [ebp+NTFS.ntfs_cur_size], 0
6080 pathoswith 3064
        push    eax
5994 pathoswith 3065
        call    ntfs_read_attr
6080 pathoswith 3066
        pop     eax
3067
        jc      ntfsFail
3068
        mov     ecx, [ebp+NTFS.frs_buffer]
3069
        cmp     word [ecx+baseRecordReuse], 0
6019 pathoswith 3070
        jnz     ntfsUnsupported     ; auxiliary record
5994 pathoswith 3071
        mov     ecx, [ebp+NTFS.ntfs_attr_offs]
3072
        cmp     byte [ecx+nonResidentFlag], 1
6019 pathoswith 3073
        jnz     ntfsUnsupported     ; resident $DATA
5994 pathoswith 3074
        cmp     edx, [ecx+attributeRealSize+4]
6080 pathoswith 3075
        jc      .writeNode
3076
        jnz     .resizeAttribute
5994 pathoswith 3077
        cmp     [ecx+attributeRealSize], eax
6080 pathoswith 3078
        jnc     .writeNode
3079
.resizeAttribute:
3080
        push    ebx
3081
        call    resizeAttribute
6107 pathoswith 3082
        jc      ntfsErrorPop
6080 pathoswith 3083
        mov     eax, [ebp+NTFS.frs_buffer]
3084
        mov     [ebp+NTFS.ntfs_cur_buf], eax
3085
        call    writeRecord     ; file
3086
        mov     ebx, [ebp+NTFS.frs_buffer]
3087
        call    ntfs_restore_usa_frs
3088
        pop     ebx
3089
.writeNode:
3090
        mov     eax, [ebp+NTFS.nodeLastRead]
3091
        test    eax, eax
3092
        jz      .writeData
3093
        mov     [ebp+NTFS.ntfsLastRead], eax
3094
        mov     eax, [ebp+NTFS.cur_index_buf]
3095
        mov     [ebp+NTFS.ntfs_cur_buf], eax
3096
        push    ebx
3097
        call    writeRecord     ; directory
3098
        pop     ebx
3099
.writeData:
5994 pathoswith 3100
        mov     eax, [ebx+4]
3101
        mov     edx, [ebx+8]
3102
        mov     ecx, [ebx+12]
3103
        mov     esi, [ebx+16]
3104
        shrd    eax, edx, 9
3105
        test    dword[ebx+4], 1FFh
3106
        jz      .aligned
3107
        mov     [ebp+NTFS.ntfs_cur_offs], eax
3108
        mov     [ebp+NTFS.ntfs_cur_size], 1
3109
        lea     edi, [ebp+NTFS.ntfs_bitmap_buf]
3110
        mov     [ebp+NTFS.ntfs_cur_buf], edi
3111
        call    ntfs_read_attr.continue
6019 pathoswith 3112
        jc      ntfsDevice
5994 pathoswith 3113
        mov     eax, [ebx+4]
3114
        and     eax, 1FFh
3115
        add     edi, eax
3116
        sub     eax, [ebp+NTFS.ntfs_cur_read]
3117
        neg     eax
3118
        push    ecx
3119
        cmp     ecx, eax
3120
        jb      @f
3121
        mov     ecx, eax
3122
@@:
3123
        sub     [esp], ecx
3124
        rep movsb
3125
        push    ebx
3126
        mov     eax, [ebp+NTFS.ntfsLastRead]
3127
        lea     ebx, [ebp+NTFS.ntfs_bitmap_buf]
3128
        mov     ecx, 1
3129
        xor     edx, edx
3130
        call    fs_write64_app
3131
        pop     ebx
3132
        pop     ecx
3133
        test    ecx, ecx
3134
        jz      @f
3135
        mov     eax, [ebx+4]
3136
        mov     edx, [ebx+8]
3137
        shrd    eax, edx, 9
3138
        inc     eax
3139
.aligned:
3140
        push    ecx
3141
        shr     ecx, 9
3142
        mov     [ebp+NTFS.ntfs_cur_offs], eax
3143
        mov     [ebp+NTFS.ntfs_cur_size], ecx
3144
        mov     [ebp+NTFS.ntfs_cur_buf], esi
3145
        add     eax, ecx
3146
        push    eax
3147
        mov     [ebp+NTFS.ntfsWriteAttr], 1
3148
        call    ntfs_read_attr.continue
3149
        mov     [ebp+NTFS.ntfsWriteAttr], 0
3150
        pop     [ebp+NTFS.ntfs_cur_offs]
3151
        pop     ecx
6019 pathoswith 3152
        jc      ntfsDevice
5994 pathoswith 3153
        and     ecx, 1FFh
3154
        jz      @f
3155
        add     esi, [ebp+NTFS.ntfs_cur_read]
3156
        mov     [ebp+NTFS.ntfs_cur_size], 1
3157
        lea     edi, [ebp+NTFS.ntfs_bitmap_buf]
3158
        mov     [ebp+NTFS.ntfs_cur_buf], edi
3159
        call    ntfs_read_attr.continue
6019 pathoswith 3160
        jc      ntfsDevice
5994 pathoswith 3161
        rep movsb
3162
        push    ebx
3163
        mov     eax, [ebp+NTFS.ntfsLastRead]
3164
        lea     ebx, [ebp+NTFS.ntfs_bitmap_buf]
3165
        mov     ecx, 1
3166
        xor     edx, edx
3167
        call    fs_write64_app
3168
        pop     ebx
3169
@@:
3170
        mov     ebx, [ebx+12]
6019 pathoswith 3171
        jmp     ntfsDone
3172
 
3173
;----------------------------------------------------------------
3174
ntfs_Delete:
3175
        cmp     byte [esi], 0
3176
        jnz     @f
3177
        xor     ebx, ebx
3178
        movi    eax, ERROR_ACCESS_DENIED
5994 pathoswith 3179
        ret
6019 pathoswith 3180
@@:
3181
        call    ntfs_lock
3182
        stdcall ntfs_find_lfn, [esp+4]
3183
        jc      ntfsNotFound
3184
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 16
3185
        jc      ntfsDenied
3186
        cmp     [ebp+NTFS.ntfsFragmentCount], 1
3187
        jnz     ntfsUnsupported     ; record fragmented
3188
        test    byte [eax+indexFlags], 1
3189
        jnz     ntfsUnsupported     ; index has a subnode
3190
        mov     edx, [ebp+NTFS.ntfs_cur_iRecord]
3191
        shr     edx, 3
3192
        cmp     edx, [ebp+NTFS.mftBitmapSize]
3193
        jnc     ntfsUnsupported
3194
; delete index from the node
3195
        movzx   edx, word [eax+indexAllocatedSize]
6107 pathoswith 3196
        mov     ecx, [eax+fileRecordReference]
3197
        cmp     [eax+edx+fileRecordReference], ecx
3198
        jnz     @f
3199
        add     dx, [eax+edx+indexAllocatedSize]
3200
@@:
6019 pathoswith 3201
        mov     edi, [ebp+NTFS.cur_index_buf]
3202
        cmp     dword [edi], 'INDX'
3203
        jz      .indexRecord
3204
        mov     esi, [ebp+NTFS.frs_buffer]  ; indexRoot
3205
        mov     ecx, [esi+recordRealSize]
3206
        shr     ecx, 2
3207
        rep movsd
3208
        mov     esi, [ebp+NTFS.cur_index_buf]
3209
        mov     edi, [ebp+NTFS.ntfs_attr_offs]
3210
        sub     edi, [ebp+NTFS.frs_buffer]
3211
        add     edi, esi
3212
        sub     [edi+sizeWithHeader], edx
3213
        sub     [edi+sizeWithoutHeader], edx
3214
        mov     cl, [edi+attributeOffset]
3215
        add     edi, ecx
3216
        sub     [edi+16+nodeRealSize], edx
3217
        sub     [edi+16+nodeAllocatedSize], edx
3218
        sub     eax, esi
3219
        add     eax, edi
3220
        sub     [esi+recordRealSize], edx
3221
        mov     ecx, [esi+recordRealSize]
3222
        jmp     @f
2288 clevermous 3223
 
6019 pathoswith 3224
.indexRecord:
3225
        sub     [edi+28], edx
3226
        mov     ecx, [edi+28]
3227
        add     ecx, 24
3228
@@:
3229
        add     ecx, [ebp+NTFS.cur_index_buf]
3230
        sub     ecx, eax
3231
        shr     ecx, 2
3232
        mov     esi, eax
3233
        add     esi, edx
3234
        mov     edi, eax
3235
        rep movsd
3236
        mov     eax, [ebp+NTFS.ntfsLastRead]
3237
        mov     [ebp+NTFS.nodeLastRead], eax
3238
; examine file record
3239
        mov     [ebp+NTFS.ntfs_cur_attr], 0x80
3240
        mov     [ebp+NTFS.ntfs_cur_offs], 0
3241
        mov     [ebp+NTFS.ntfs_cur_size], 0
3242
        call    ntfs_read_attr
3243
        jc      .folder
3244
        mov     esi, [ebp+NTFS.frs_buffer]
3245
        cmp     word [esi+baseRecordReuse], 0
3246
        jnz     ntfsUnsupported     ; auxiliary record
3247
        mov     esi, [ebp+NTFS.ntfs_attr_offs]
3248
        cmp     byte [esi+nonResidentFlag], 0
3249
        jz      .writeBitmapMFT
3250
        movzx   eax, byte [esi+dataRunsOffset]
3251
        add     esi, eax
3252
        xor     edi, edi
3253
        sub     esp, 16
6080 pathoswith 3254
@@:         ; "delete" file data
6019 pathoswith 3255
        call    ntfs_decode_mcb_entry
6080 pathoswith 3256
        jnc     @f
6019 pathoswith 3257
        cmp     dword[esp+8], 0
6080 pathoswith 3258
        jz      @b
6019 pathoswith 3259
        add     edi, [esp+8]
3260
        mov     ebx, [esp]
6080 pathoswith 3261
        call    ntfsSpaceFree
3262
        jnc     @b
6019 pathoswith 3263
@@:
3264
        add     esp, 16
3265
        jmp     .writeBitmapMFT
3266
 
3267
.folder:    ; empty?
3268
        lea     esi, [ebp+NTFS.ntfs_bitmap_buf]
3269
        mov     [ebp+NTFS.ntfs_cur_buf], esi
3270
        mov     [ebp+NTFS.ntfs_cur_attr], 0x90
3271
        mov     [ebp+NTFS.ntfs_cur_offs], 0
3272
        mov     [ebp+NTFS.ntfs_cur_size], 1
3273
        call    ntfs_read_attr
3274
        cmp     [ebp+NTFS.ntfs_cur_read], 48
3275
        jnz     ntfsDenied
3276
        test    byte [esi+32+indexFlags], 1
3277
        jnz     ntfsDenied
3278
.writeBitmapMFT:    ; "delete" file record
3279
        mov     eax, [ebp+NTFS.ntfs_cur_iRecord]
3280
        mov     ecx, eax
3281
        shr     eax, 3
3282
        and     ecx, 7
3283
        mov     edi, [ebp+NTFS.mftBitmapBuffer]
3284
        btr     [edi+eax], ecx
3285
        shr     eax, 9
3286
        mov     ebx, eax
3287
        shl     ebx, 9
3288
        add     eax, [ebp+NTFS.mftBitmapLocation]
3289
        add     ebx, edi
3290
        mov     ecx, 1
3291
        xor     edx, edx
3292
        call    fs_write64_sys
3293
        mov     esi, [ebp+NTFS.frs_buffer]
6107 pathoswith 3294
        mov     [ebp+NTFS.ntfs_cur_buf], esi
6019 pathoswith 3295
        mov     byte [esi+recordFlags], 0
3296
        call    writeRecord
3297
; write directory node
3298
        mov     eax, [ebp+NTFS.nodeLastRead]
3299
        mov     [ebp+NTFS.ntfsLastRead], eax
3300
        mov     eax, [ebp+NTFS.cur_index_buf]
3301
        mov     [ebp+NTFS.ntfs_cur_buf], eax
3302
        call    writeRecord
6080 pathoswith 3303
        jmp     ntfsDone
6019 pathoswith 3304
 
5954 pathoswith 3305
;----------------------------------------------------------------
3742 clevermous 3306
ntfs_SetFileEnd:
6107 pathoswith 3307
        cmp     byte [esi], 0
3308
        jnz     @f
3309
        xor     ebx, ebx
3310
        movi    eax, ERROR_ACCESS_DENIED
3311
        ret
3312
@@:
3313
        call    ntfs_lock
3314
        stdcall ntfs_find_lfn, [esp+4]
3315
        jc      ntfsNotFound
3316
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 16
3317
        jc      ntfsDenied
3318
        bt      dword [eax+fileFlags], 28
3319
        jc      ntfsDenied
3320
        cmp     [ebp+NTFS.ntfsFragmentCount], 1
3321
        jnz     ntfsUnsupported     ; record fragmented
3322
; set file size in the directory
3323
        mov     edi, [ebp+NTFS.cur_index_buf]
3324
        cmp     dword [edi], 'INDX'
3325
        jz      @f
3326
        mov     esi, [ebp+NTFS.frs_buffer]
3327
        mov     ecx, [esi+recordRealSize]
3328
        shr     ecx, 2
3329
        rep movsd
3330
        mov     esi, [ebp+NTFS.ntfs_attr_offs]
3331
        mov     cl, [esi+attributeOffset]
3332
        sub     esi, [ebp+NTFS.frs_buffer]
3333
        add     eax, ecx
3334
        add     eax, esi
3335
@@:
3336
        mov     ecx, [ebx+4]
3337
        mov     edx, [ebx+8]
3338
        mov     [eax+fileRealSize], ecx
3339
        mov     [eax+fileRealSize+4], edx
3340
        mov     eax, [ebp+NTFS.ntfsLastRead]
3341
        mov     [ebp+NTFS.nodeLastRead], eax
3342
        mov     [ebp+NTFS.ntfs_cur_attr], 0x80
3343
        mov     [ebp+NTFS.ntfs_cur_offs], 0
3344
        mov     [ebp+NTFS.ntfs_cur_size], 0
3345
        call    ntfs_read_attr
3346
        jc      ntfsFail
3347
        mov     eax, ecx
3348
        mov     ecx, [ebp+NTFS.frs_buffer]
3349
        cmp     word [ecx+baseRecordReuse], 0
3350
        jnz     ntfsUnsupported     ; auxiliary record
3351
        mov     ecx, [ebp+NTFS.ntfs_attr_offs]
3352
        cmp     byte [ecx+nonResidentFlag], 1
3353
        jnz     ntfsUnsupported     ; resident $DATA
3354
        cmp     [ecx+attributeRealSize+4], edx
3355
        jnz     .resizeAttribute
3356
        cmp     [ecx+attributeRealSize], eax
3357
        jnc     .resizeAttribute
3358
        mov     eax, [ecx+attributeRealSize]
3359
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3360
        mov     [ebp+NTFS.ntfs_cur_size], ecx
3361
        shl     ecx, 9
3362
        div     ecx
3363
        test    edx, edx
3364
        jz      .aligned
3365
        push    edx
3366
        push    ecx
3367
        mul     [ebp+NTFS.sectors_per_cluster]
3368
        mov     [ebp+NTFS.ntfs_cur_offs], eax
3369
        stdcall kernel_alloc, ecx
3370
        pop     ecx
3371
        pop     edi
3372
        sub     ecx, edi
3373
        add     edi, eax
3374
        mov     [ebp+NTFS.ntfs_cur_buf], eax
3375
        push    [ebp+NTFS.ntfsLastRead]
3376
        call    ntfs_read_attr.continue
3377
        jc      @f
3378
        xor     eax, eax
3379
        rep stosb
3380
        push    ebx
3381
        mov     eax, [ebp+NTFS.ntfsLastRead]
3382
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
3383
        mov     ecx, [ebp+NTFS.sectors_per_cluster]
3384
        xor     edx, edx
3385
        call    fs_write64_app
3386
        pop     ebx
3387
@@:
3388
        pop     [ebp+NTFS.ntfsLastRead]
3389
        stdcall kernel_free, [ebp+NTFS.ntfs_cur_buf]
3390
.aligned:
3391
        mov     eax, [ebx+4]
3392
        mov     edx, [ebx+8]
3393
.resizeAttribute:
3394
        call    resizeAttribute
3395
        jc      ntfsError
3396
        mov     eax, [ebp+NTFS.frs_buffer]
3397
        mov     [ebp+NTFS.ntfs_cur_buf], eax
3398
        call    writeRecord     ; file
3399
        mov     eax, [ebp+NTFS.nodeLastRead]
3400
        mov     [ebp+NTFS.ntfsLastRead], eax
3401
        mov     eax, [ebp+NTFS.cur_index_buf]
3402
        mov     [ebp+NTFS.ntfs_cur_buf], eax
3403
        call    writeRecord     ; directory
3404
        call    ntfsSpaceClean
3405
        jmp     ntfsDone
3406
 
3407
;----------------------------------------------------------------
3742 clevermous 3408
ntfs_SetFileInfo:
6019 pathoswith 3409
        movi    eax, ERROR_UNSUPPORTED_FS
2288 clevermous 3410
        ret
3411
 
3742 clevermous 3412
;----------------------------------------------------------------
3413
ntfs_GetFileInfo:
2288 clevermous 3414
        cmp     byte [esi], 0
3415
        jnz     @f
5994 pathoswith 3416
        movi    eax, ERROR_UNSUPPORTED_FS
2288 clevermous 3417
        ret
3418
@@:
3742 clevermous 3419
        call    ntfs_lock
3420
        stdcall ntfs_find_lfn, [esp+4]
5994 pathoswith 3421
        jnc     .found
3742 clevermous 3422
        test    eax, eax
6019 pathoswith 3423
        jz      ntfsFail
3424
        jmp     ntfsNotFound
5994 pathoswith 3425
.found:
2288 clevermous 3426
        push    esi edi
3427
        mov     esi, eax
3742 clevermous 3428
        mov     edi, [ebx+16]
2288 clevermous 3429
        xor     eax, eax
3430
        call    ntfs_direntry_to_bdfe
3431
        pop     edi esi
3742 clevermous 3432
        call    ntfs_unlock
2288 clevermous 3433
        xor     eax, eax
3434
        ret
3435
 
6019 pathoswith 3436
ntfsUnsupported:
3437
        push    ERROR_UNSUPPORTED_FS
6080 pathoswith 3438
        jmp     ntfsOut
6019 pathoswith 3439
ntfsDevice:
3440
        push    ERROR_DEVICE
3441
        jmp     ntfsOut
3442
ntfsNotFound:
3443
        push    ERROR_FILE_NOT_FOUND
3444
        jmp     ntfsOut
3445
ntfsDenied:
3446
        push    ERROR_ACCESS_DENIED
3447
        jmp     ntfsOut
3448
ntfsFail:
3449
        push    ERROR_FS_FAIL
3450
        jmp     ntfsOut
6080 pathoswith 3451
ntfsDiskFull:
3452
        push    ERROR_DISK_FULL
3453
        jmp     ntfsOut
6107 pathoswith 3454
ntfsErrorPop2:
3455
        pop     ebx
3456
ntfsErrorPop:
3457
        pop     ebx
6080 pathoswith 3458
ntfsError:
3459
        push    eax
3460
ntfsOut:
3461
        call    ntfs_unlock
3462
        xor     ebx, ebx
3463
        pop     eax
3464
        ret