Subversion Repositories Kolibri OS

Rev

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