Subversion Repositories Kolibri OS

Rev

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