Subversion Repositories Kolibri OS

Rev

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