Subversion Repositories Kolibri OS

Rev

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

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