Subversion Repositories Kolibri OS

Rev

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