Subversion Repositories Kolibri OS

Rev

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