Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3908 Serge 3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
593 mikedld 8
$Revision: 3908 $
9
 
3908 Serge 10
struct NTFS PARTITION
11
Lock                    MUTEX ?    ; currently operations with one partition
12
                                   ; can not be executed in parallel since the
13
                                   ; legacy code is not ready; this mutex guards
14
                                   ; all operations
15
sectors_per_cluster     dd      ?
16
mft_cluster             dd      ?
17
mftmirr_cluster         dd      ?
18
frs_size                dd      ?       ; FRS size in bytes
19
iab_size                dd      ?       ; IndexAllocationBuffer size in bytes
20
frs_buffer              dd      ?
21
iab_buffer              dd      ?
22
mft_retrieval           dd      ?
23
mft_retrieval_size      dd      ?
24
mft_retrieval_alloc     dd      ?
25
mft_retrieval_end       dd      ?
26
cur_index_size          dd      ?
27
cur_index_buf           dd      ?
593 mikedld 28
 
3908 Serge 29
ntfs_cur_attr   dd      ?
30
ntfs_cur_iRecord dd     ?
31
ntfs_cur_offs   dd      ?       ; in sectors
32
ntfs_cur_size   dd      ?       ; in sectors
33
ntfs_cur_buf    dd      ?
34
ntfs_cur_read   dd      ?       ; [output]
35
ntfs_bCanContinue db    ?
36
                rb      3
37
 
38
cur_subnode_size        dd      ?
39
ntfs_attr_iRecord       dd      ?
40
ntfs_attr_iBaseRecord   dd      ?
41
ntfs_attr_offs          dd      ?
42
ntfs_attr_list          dd      ?
43
ntfs_attr_size          dq      ?
44
ntfs_cur_tail           dd      ?
45
 
46
ntfs_attrlist_buf       rb      0x400
47
ntfs_attrlist_mft_buf   rb      0x400
48
ntfs_bitmap_buf         rb      0x400
49
ends
50
 
51
iglobal
52
align 4
53
ntfs_user_functions:
54
        dd      ntfs_free
55
        dd      (ntfs_user_functions_end - ntfs_user_functions - 4) / 4
56
        dd      ntfs_Read
57
        dd      ntfs_ReadFolder
58
        dd      ntfs_Rewrite
59
        dd      ntfs_Write
60
        dd      ntfs_SetFileEnd
61
        dd      ntfs_GetFileInfo
62
        dd      ntfs_SetFileInfo
63
        dd      0
64
        dd      ntfs_Delete
65
        dd      ntfs_CreateFolder
66
ntfs_user_functions_end:
67
endg
68
 
1378 turbanoff 69
ntfs_test_bootsec:
256 diamond 70
; in: ebx->buffer, edx=size of partition
71
; out: CF set <=> invalid
72
; 1. Name=='NTFS    '
73
        cmp     dword [ebx+3], 'NTFS'
74
        jnz     .no
75
        cmp     dword [ebx+7], '    '
76
        jnz     .no
77
; 2. Number of bytes per sector is the same as for physical device
78
; (that is, 0x200 for hard disk)
79
        cmp     word [ebx+11], 0x200
80
        jnz     .no
81
; 3. Number of sectors per cluster must be power of 2
82
        movzx   eax, byte [ebx+13]
83
        dec     eax
84
        js      .no
85
        test    al, [ebx+13]
86
        jnz     .no
87
; 4. FAT parameters must be zero
88
        cmp     word [ebx+14], 0
89
        jnz     .no
90
        cmp     dword [ebx+16], 0
91
        jnz     .no
92
        cmp     byte [ebx+20], 0
93
        jnz     .no
94
        cmp     word [ebx+22], 0
95
        jnz     .no
96
        cmp     dword [ebx+32], 0
97
        jnz     .no
98
; 5. Number of sectors <= partition size
99
        cmp     dword [ebx+0x2C], 0
100
        ja      .no
101
        cmp     [ebx+0x28], edx
102
        ja      .no
103
; 6. $MFT and $MFTMirr clusters must be within partition
104
        cmp     dword [ebx+0x34], 0
105
        ja      .no
106
        push    edx
107
        movzx   eax, byte [ebx+13]
108
        mul     dword [ebx+0x30]
109
        test    edx, edx
110
        pop     edx
111
        jnz     .no
112
        cmp     eax, edx
113
        ja      .no
114
        cmp     dword [ebx+0x3C], 0
115
        ja      .no
116
        push    edx
117
        movzx   eax, byte [ebx+13]
118
        mul     dword [ebx+0x38]
119
        test    edx, edx
120
        pop     edx
121
        jnz     .no
122
        cmp     eax, edx
123
        ja      .no
124
; 7. Clusters per FRS must be either negative and in [-31,-9] or positive and power of 2
125
        movsx   eax, byte [ebx+0x40]
126
        cmp     al, -31
127
        jl      .no
128
        cmp     al, -9
129
        jle     @f
130
        dec     eax
131
        js      .no
132
        test    [ebx+0x40], al
133
        jnz     .no
134
@@:
135
; 8. Same for clusters per IndexAllocationBuffer
136
        movsx   eax, byte [ebx+0x44]
137
        cmp     al, -31
138
        jl      .no
139
        cmp     al, -9
140
        jle     @f
141
        dec     eax
142
        js      .no
143
        test    [ebx+0x44], al
144
        jnz     .no
145
@@:
146
; OK, this is correct NTFS bootsector
147
        clc
148
        ret
149
.no:
150
; No, this bootsector isn't NTFS
151
        stc
152
        ret
153
 
3908 Serge 154
proc ntfs_create_partition
155
        mov     edx, dword [ebp+PARTITION.Length]
156
        cmp     dword [esp+4], 0
157
        jz      .boot_read_ok
158
        add     ebx, 512
159
        lea     eax, [edx-1]
160
        call    fs_read32_sys
161
        test    eax, eax
162
        jnz     @f
163
        call    ntfs_test_bootsec
164
        jnc     .ntfs_setup
165
@@:
166
        mov     eax, edx
167
        shr     eax, 1
168
        call    fs_read32_sys
169
        test    eax, eax
170
        jnz     .nope                   ; no chance...
171
.boot_read_ok:
172
        call    ntfs_test_bootsec
173
        jnc     .ntfs_setup
174
.nope:
175
        xor     eax, eax
176
        jmp     .exit
177
 
178
.ntfs_setup:
256 diamond 179
; By given bootsector, initialize some NTFS variables
3908 Serge 180
        movi    eax, sizeof.NTFS
181
        call    malloc
182
        test    eax, eax
183
        jz      .exit
184
        mov     ecx, dword [ebp+PARTITION.FirstSector]
185
        mov     dword [eax+NTFS.FirstSector], ecx
186
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
187
        mov     dword [eax+NTFS.FirstSector+4], ecx
188
        mov     ecx, dword [ebp+PARTITION.Length]
189
        mov     dword [eax+NTFS.Length], ecx
190
        mov     ecx, dword [ebp+PARTITION.Length+4]
191
        mov     dword [eax+NTFS.Length+4], ecx
192
        mov     ecx, [ebp+PARTITION.Disk]
193
        mov     [eax+NTFS.Disk], ecx
194
        mov     [eax+NTFS.FSUserFunctions], ntfs_user_functions
195
        push    ebx ebp esi
196
        mov     ebp, eax
197
 
198
        lea     ecx, [ebp+NTFS.Lock]
199
        call    mutex_init
200
 
256 diamond 201
        movzx   eax, byte [ebx+13]
3908 Serge 202
        mov     [ebp+NTFS.sectors_per_cluster], eax
256 diamond 203
        mov     eax, [ebx+0x28]
3908 Serge 204
        mov     dword [ebp+NTFS.Length], eax
205
        and     dword [ebp+NTFS.Length+4], 0
256 diamond 206
        mov     eax, [ebx+0x30]
3908 Serge 207
        mov     [ebp+NTFS.mft_cluster], eax
256 diamond 208
        mov     eax, [ebx+0x38]
3908 Serge 209
        mov     [ebp+NTFS.mftmirr_cluster], eax
256 diamond 210
        movsx   eax, byte [ebx+0x40]
211
        test    eax, eax
212
        js      .1
3908 Serge 213
        mul     [ebp+NTFS.sectors_per_cluster]
256 diamond 214
        shl     eax, 9
215
        jmp     .2
216
.1:
217
        neg     eax
218
        mov     ecx, eax
219
        mov     eax, 1
220
        shl     eax, cl
221
.2:
3908 Serge 222
        mov     [ebp+NTFS.frs_size], eax
256 diamond 223
        movsx   eax, byte [ebx+0x44]
224
        test    eax, eax
225
        js      .3
3908 Serge 226
        mul     [ebp+NTFS.sectors_per_cluster]
256 diamond 227
        shl     eax, 9
228
        jmp     .4
229
.3:
230
        neg     eax
231
        mov     ecx, eax
232
        mov     eax, 1
233
        shl     eax, cl
234
.4:
3908 Serge 235
        mov     [ebp+NTFS.iab_size], eax
256 diamond 236
; allocate space for buffers
3908 Serge 237
        add     eax, [ebp+NTFS.frs_size]
256 diamond 238
        push    eax
239
        call    kernel_alloc
240
        test    eax, eax
3908 Serge 241
        jz      .fail_free
242
        mov     [ebp+NTFS.frs_buffer], eax
243
        add     eax, [ebp+NTFS.frs_size]
244
        mov     [ebp+NTFS.iab_buffer], eax
256 diamond 245
; read $MFT disposition
3908 Serge 246
        mov     eax, [ebp+NTFS.mft_cluster]
247
        mul     [ebp+NTFS.sectors_per_cluster]
256 diamond 248
        call    ntfs_read_frs_sector
3908 Serge 249
        test    eax, eax
256 diamond 250
        jnz     .usemirr
251
        cmp     dword [ebx], 'FILE'
252
        jnz     .usemirr
253
        call    ntfs_restore_usa_frs
254
        jnc     .mftok
255
.usemirr:
3908 Serge 256
        mov     eax, [ebp+NTFS.mftmirr_cluster]
257
        mul     [ebp+NTFS.sectors_per_cluster]
256 diamond 258
        call    ntfs_read_frs_sector
3908 Serge 259
        test    eax, eax
256 diamond 260
        jnz     @f
261
        cmp     dword [ebx], 'FILE'
262
        jnz     @f
263
        call    ntfs_restore_usa_frs
264
        jnc     .mftok
265
@@:
266
; $MFT and $MFTMirr invalid!
267
.fail_free_frs:
3908 Serge 268
        push    [ebp+NTFS.frs_buffer]
256 diamond 269
        call    kernel_free
3908 Serge 270
.fail_free:
271
        mov     eax, ebp
272
        call    free
273
        xor     eax, eax
274
.pop_exit:
275
        pop     esi ebp ebx
276
.exit:
277
        cmp     dword [esp+4], 0
278
        jz      @f
279
        sub     ebx, 512
280
@@:
281
        ret
256 diamond 282
.fail_free_mft:
3908 Serge 283
        push    [ebp+NTFS.mft_retrieval]
256 diamond 284
        call    kernel_free
285
        jmp     .fail_free_frs
286
.mftok:
287
; read $MFT table retrieval information
288
; start with one page, increase if not enough (when MFT too fragmented)
289
        push    ebx
290
        push    0x1000
291
        call    kernel_alloc
292
        pop     ebx
293
        test    eax, eax
294
        jz      .fail_free_frs
3908 Serge 295
        mov     [ebp+NTFS.mft_retrieval], eax
296
        and     [ebp+NTFS.mft_retrieval_size], 0
297
        mov     [ebp+NTFS.mft_retrieval_alloc], 0x1000/8
256 diamond 298
; $MFT base record must contain unnamed non-resident $DATA attribute
299
        movzx   eax, word [ebx+14h]
300
        add     eax, ebx
301
.scandata:
302
        cmp     dword [eax], -1
303
        jz      .fail_free_mft
304
        cmp     dword [eax], 0x80
305
        jnz     @f
306
        cmp     byte [eax+9], 0
307
        jz      .founddata
308
@@:
309
        add     eax, [eax+4]
310
        jmp     .scandata
311
.founddata:
312
        cmp     byte [eax+8], 0
313
        jz      .fail_free_mft
314
; load first portion of $DATA attribute retrieval information
315
        mov     edx, [eax+0x18]
3908 Serge 316
        mov     [ebp+NTFS.mft_retrieval_end], edx
256 diamond 317
        mov     esi, eax
318
        movzx   eax, word [eax+0x20]
319
        add     esi, eax
320
        sub     esp, 10h
321
.scanmcb:
322
        call    ntfs_decode_mcb_entry
323
        jnc     .scanmcbend
324
        call    .get_mft_retrieval_ptr
325
        mov     edx, [esp]      ; block length
326
        mov     [eax], edx
327
        mov     edx, [esp+8]    ; block addr (relative)
328
        mov     [eax+4], edx
3908 Serge 329
        inc     [ebp+NTFS.mft_retrieval_size]
256 diamond 330
        jmp     .scanmcb
331
.scanmcbend:
332
        add     esp, 10h
333
; there may be other portions of $DATA attribute in auxiliary records;
334
; if they will be needed, they will be loaded later
335
 
3908 Serge 336
        mov     [ebp+NTFS.cur_index_size], 0x1000/0x200
256 diamond 337
        push    0x1000
338
        call    kernel_alloc
339
        test    eax, eax
340
        jz      .fail_free_mft
3908 Serge 341
        mov     [ebp+NTFS.cur_index_buf], eax
256 diamond 342
 
3908 Serge 343
        mov     eax, ebp
344
        jmp     .pop_exit
345
endp
256 diamond 346
 
347
.get_mft_retrieval_ptr:
348
        pushad
3908 Serge 349
        mov     eax, [ebp+NTFS.mft_retrieval_size]
350
        cmp     eax, [ebp+NTFS.mft_retrieval_alloc]
256 diamond 351
        jnz     .ok
352
        add     eax, 0x1000/8
3908 Serge 353
        mov     [ebp+NTFS.mft_retrieval_alloc], eax
256 diamond 354
        shl     eax, 3
355
        push    eax
356
        call    kernel_alloc
357
        test    eax, eax
358
        jnz     @f
359
        popad
360
        add     esp, 14h
361
        jmp     .fail_free_mft
362
@@:
3908 Serge 363
        mov     esi, [ebp+NTFS.mft_retrieval]
256 diamond 364
        mov     edi, eax
3908 Serge 365
        mov     ecx, [ebp+NTFS.mft_retrieval_size]
256 diamond 366
        add     ecx, ecx
3908 Serge 367
        rep movsd
368
        push    [ebp+NTFS.mft_retrieval]
369
        mov     [ebp+NTFS.mft_retrieval], eax
256 diamond 370
        call    kernel_free
3908 Serge 371
        mov     eax, [ebp+NTFS.mft_retrieval_size]
256 diamond 372
.ok:
373
        shl     eax, 3
3908 Serge 374
        add     eax, [ebp+NTFS.mft_retrieval]
256 diamond 375
        mov     [esp+28], eax
376
        popad
377
        ret
378
 
3908 Serge 379
proc ntfs_free
380
        push    ebx
381
        xchg    ebx, eax
382
        stdcall kernel_free, [ebx+NTFS.frs_buffer]
383
        stdcall kernel_free, [ebx+NTFS.mft_retrieval]
384
        stdcall kernel_free, [ebx+NTFS.cur_index_buf]
385
        xchg    ebx, eax
386
        call    free
387
        pop     ebx
388
        ret
389
endp
390
 
391
proc ntfs_lock
392
        lea     ecx, [ebp+NTFS.Lock]
393
        jmp     mutex_lock
394
endp
395
 
396
proc ntfs_unlock
397
        lea     ecx, [ebp+NTFS.Lock]
398
        jmp     mutex_unlock
399
endp
400
 
256 diamond 401
ntfs_read_frs_sector:
3908 Serge 402
        push    ecx
403
        mov     ebx, [ebp+NTFS.frs_buffer]
404
        push    ebx
405
        mov     ecx, [ebp+NTFS.frs_size]
256 diamond 406
        shr     ecx, 9
3908 Serge 407
        push    ecx
408
        mov     ecx, eax
256 diamond 409
@@:
3908 Serge 410
        mov     eax, ecx
411
        call    fs_read32_sys
412
        test    eax, eax
256 diamond 413
        jnz     .fail
414
        add     ebx, 0x200
3908 Serge 415
        inc     ecx
416
        dec     dword [esp]
417
        jnz     @b
418
        pop     eax
256 diamond 419
.fail:
420
        pop     ebx
3908 Serge 421
        pop     ecx
256 diamond 422
        ret
423
 
424
ntfs_read_attr:
3908 Serge 425
; in: variables in ebp+NTFS.*
426
; out: [ebp+NTFS.ntfs_cur_read]
427
; out: CF=1 => notfound, in this case eax=0 => disk ok, otherwise eax=disk error code
428
        xor     eax, eax
256 diamond 429
        pushad
3908 Serge 430
        and     [ebp+NTFS.ntfs_cur_read], 0
431
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
256 diamond 432
        jnz     .nomft
3908 Serge 433
        cmp     [ebp+NTFS.ntfs_cur_attr], 0x80
256 diamond 434
        jnz     .nomft
3908 Serge 435
        mov     eax, [ebp+NTFS.mft_retrieval_end]
256 diamond 436
        inc     eax
3908 Serge 437
        mul     [ebp+NTFS.sectors_per_cluster]
438
        cmp     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 439
        jbe     .nomft
440
; precalculated part of $Mft $DATA
3908 Serge 441
        mov     esi, [ebp+NTFS.mft_retrieval]
442
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 443
        xor     edx, edx
3908 Serge 444
        div     [ebp+NTFS.sectors_per_cluster]
256 diamond 445
; eax = VCN, edx = offset in sectors from beginning of cluster
446
        xor     ecx, ecx        ; ecx will contain LCN
447
.mftscan:
448
        add     ecx, [esi+4]
449
        sub     eax, [esi]
450
        jb      @f
451
        add     esi, 8
452
        push    eax
3908 Serge 453
        mov     eax, [ebp+NTFS.mft_retrieval_end]
256 diamond 454
        shl     eax, 3
3908 Serge 455
        add     eax, [ebp+NTFS.mft_retrieval]
256 diamond 456
        cmp     eax, esi
457
        pop     eax
458
        jnz     .mftscan
459
        jmp     .nomft
460
@@:
461
        push    ecx
462
        add     ecx, eax
463
        add     ecx, [esi]
464
        push    eax
465
        push    edx
3908 Serge 466
        mov     eax, [ebp+NTFS.sectors_per_cluster]
256 diamond 467
        mul     ecx
468
; eax = sector on partition
469
        pop     edx
470
        add     eax, edx
3908 Serge 471
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
256 diamond 472
        pop     ecx
473
        neg     ecx
3908 Serge 474
        imul    ecx, [ebp+NTFS.sectors_per_cluster]
256 diamond 475
        sub     ecx, edx
3908 Serge 476
        cmp     ecx, [ebp+NTFS.ntfs_cur_size]
256 diamond 477
        jb      @f
3908 Serge 478
        mov     ecx, [ebp+NTFS.ntfs_cur_size]
256 diamond 479
@@:
480
; ecx = number of sequential sectors to read
3908 Serge 481
        push    eax
482
        call    fs_read32_sys
483
        pop     edx
484
        test    eax, eax
256 diamond 485
        jnz     .errread
3908 Serge 486
        add     [ebp+NTFS.ntfs_cur_read], 0x200
487
        dec     [ebp+NTFS.ntfs_cur_size]
488
        inc     [ebp+NTFS.ntfs_cur_offs]
256 diamond 489
        add     ebx, 0x200
3908 Serge 490
        mov     [ebp+NTFS.ntfs_cur_buf], ebx
491
        lea     eax, [edx+1]
256 diamond 492
        loop    @b
493
        pop     ecx
494
        xor     eax, eax
495
        xor     edx, edx
3908 Serge 496
        cmp     [ebp+NTFS.ntfs_cur_size], eax
256 diamond 497
        jz      @f
498
        add     esi, 8
499
        push    eax
3908 Serge 500
        mov     eax, [ebp+NTFS.mft_retrieval_end]
256 diamond 501
        shl     eax, 3
3908 Serge 502
        add     eax, [ebp+NTFS.mft_retrieval]
256 diamond 503
        cmp     eax, esi
504
        pop     eax
505
        jz      .nomft
506
        jmp     .mftscan
507
@@:
508
        popad
509
        ret
510
.errread:
511
        pop     ecx
512
.errret:
3908 Serge 513
        mov     [esp+28], eax
256 diamond 514
        stc
515
        popad
516
        ret
517
.nomft:
518
; 1. Read file record.
519
; N.B. This will do recursive call of read_attr for $MFT::$Data.
3908 Serge 520
        mov     eax, [ebp+NTFS.ntfs_cur_iRecord]
521
        mov     [ebp+NTFS.ntfs_attr_iRecord], eax
522
        and     [ebp+NTFS.ntfs_attr_list], 0
523
        or      dword [ebp+NTFS.ntfs_attr_size], -1
524
        or      dword [ebp+NTFS.ntfs_attr_size+4], -1
525
        or      [ebp+NTFS.ntfs_attr_iBaseRecord], -1
256 diamond 526
        call    ntfs_read_file_record
3908 Serge 527
        jc      .errret
256 diamond 528
; 2. Find required attribute.
3908 Serge 529
        mov     eax, [ebp+NTFS.frs_buffer]
256 diamond 530
; a) For auxiliary records, read base record
531
; N.B. If base record is present,
532
;      base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero
533
        cmp     dword [eax+24h], 0
534
        jz      @f
535
        mov     eax, [eax+20h]
536
;        test    eax, eax
537
;        jz      @f
538
.beginfindattr:
3908 Serge 539
        mov     [ebp+NTFS.ntfs_attr_iRecord], eax
256 diamond 540
        call    ntfs_read_file_record
3908 Serge 541
        jc      .errret
256 diamond 542
@@:
543
; b) Scan for required attribute and for $ATTR_LIST
3908 Serge 544
        mov     eax, [ebp+NTFS.frs_buffer]
256 diamond 545
        movzx   ecx, word [eax+14h]
546
        add     eax, ecx
3908 Serge 547
        mov     ecx, [ebp+NTFS.ntfs_cur_attr]
548
        and     [ebp+NTFS.ntfs_attr_offs], 0
256 diamond 549
.scanattr:
550
        cmp     dword [eax], -1
551
        jz      .scandone
552
        cmp     dword [eax], ecx
553
        jz      .okattr
3908 Serge 554
        cmp     [ebp+NTFS.ntfs_attr_iBaseRecord], -1
256 diamond 555
        jnz     .scancont
556
        cmp     dword [eax], 0x20       ; $ATTR_LIST
557
        jnz     .scancont
3908 Serge 558
        mov     [ebp+NTFS.ntfs_attr_list], eax
256 diamond 559
        jmp     .scancont
560
.okattr:
273 diamond 561
; ignore named $DATA attributes (aka NTFS streams)
562
        cmp     ecx, 0x80
563
        jnz     @f
564
        cmp     byte [eax+9], 0
565
        jnz     .scancont
566
@@:
3908 Serge 567
        mov     [ebp+NTFS.ntfs_attr_offs], eax
256 diamond 568
.scancont:
569
        add     eax, [eax+4]
570
        jmp     .scanattr
262 diamond 571
.continue:
572
        pushad
3908 Serge 573
        and     [ebp+NTFS.ntfs_cur_read], 0
256 diamond 574
.scandone:
575
; c) Check for required offset and length
3908 Serge 576
        mov     ecx, [ebp+NTFS.ntfs_attr_offs]
256 diamond 577
        jecxz   .noattr
3908 Serge 578
        push    [ebp+NTFS.ntfs_cur_size]
579
        push    [ebp+NTFS.ntfs_cur_read]
256 diamond 580
        call    .doreadattr
265 diamond 581
        pop     edx
3908 Serge 582
        pop     ecx
256 diamond 583
        jc      @f
3908 Serge 584
        cmp     [ebp+NTFS.ntfs_bCanContinue], 0
265 diamond 585
        jz      @f
3908 Serge 586
        sub     edx, [ebp+NTFS.ntfs_cur_read]
265 diamond 587
        neg     edx
588
        shr     edx, 9
3908 Serge 589
        sub     ecx, edx
590
        mov     [ebp+NTFS.ntfs_cur_size], ecx
256 diamond 591
        jnz     .not_in_cur
592
@@:
593
        popad
594
        ret
595
.noattr:
596
.not_in_cur:
3908 Serge 597
        cmp     [ebp+NTFS.ntfs_cur_attr], 0x20
256 diamond 598
        jz      @f
3908 Serge 599
        mov     ecx, [ebp+NTFS.ntfs_attr_list]
256 diamond 600
        test    ecx, ecx
601
        jnz     .lookattr
602
.ret_is_attr:
3908 Serge 603
        and     dword [esp+28], 0
604
        cmp     [ebp+NTFS.ntfs_attr_offs], 1     ; CF set <=> ntfs_attr_offs == 0
256 diamond 605
        popad
606
        ret
607
.lookattr:
608
; required attribute or required offset was not found in base record;
609
; it may be present in auxiliary records;
610
; scan $ATTR_LIST
3908 Serge 611
        mov     eax, [ebp+NTFS.ntfs_attr_iBaseRecord]
256 diamond 612
        cmp     eax, -1
613
        jz      @f
614
        call    ntfs_read_file_record
3908 Serge 615
        jc      .errret
616
        or      [ebp+NTFS.ntfs_attr_iBaseRecord], -1
256 diamond 617
@@:
3908 Serge 618
        push    [ebp+NTFS.ntfs_cur_offs]
619
        push    [ebp+NTFS.ntfs_cur_size]
620
        push    [ebp+NTFS.ntfs_cur_read]
621
        push    [ebp+NTFS.ntfs_cur_buf]
622
        push    dword [ebp+NTFS.ntfs_attr_size]
623
        push    dword [ebp+NTFS.ntfs_attr_size+4]
624
        or      dword [ebp+NTFS.ntfs_attr_size], -1
625
        or      dword [ebp+NTFS.ntfs_attr_size+4], -1
626
        and     [ebp+NTFS.ntfs_cur_offs], 0
627
        mov     [ebp+NTFS.ntfs_cur_size], 2
628
        and     [ebp+NTFS.ntfs_cur_read], 0
629
        lea     eax, [ebp+NTFS.ntfs_attrlist_buf]
630
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
273 diamond 631
        jnz     @f
3908 Serge 632
        lea     eax, [ebp+NTFS.ntfs_attrlist_mft_buf]
273 diamond 633
@@:
3908 Serge 634
        mov     [ebp+NTFS.ntfs_cur_buf], eax
273 diamond 635
        push    eax
256 diamond 636
        call    .doreadattr
273 diamond 637
        pop     esi
638
        mov     edx, 1
3908 Serge 639
        pop     dword [ebp+NTFS.ntfs_attr_size+4]
640
        pop     dword [ebp+NTFS.ntfs_attr_size]
641
        mov     ecx, [ebp+NTFS.ntfs_cur_read]
642
        pop     [ebp+NTFS.ntfs_cur_buf]
643
        pop     [ebp+NTFS.ntfs_cur_read]
644
        pop     [ebp+NTFS.ntfs_cur_size]
645
        pop     [ebp+NTFS.ntfs_cur_offs]
256 diamond 646
        jc      .errret
647
        or      edi, -1
3908 Serge 648
        lea     ecx, [ecx+esi-1Ah]
256 diamond 649
.scanliststart:
3908 Serge 650
        push    ecx
651
        mov     eax, [ebp+NTFS.ntfs_cur_attr]
256 diamond 652
.scanlist:
3908 Serge 653
        cmp     esi, [esp]
256 diamond 654
        jae     .scanlistdone
655
        cmp     eax, [esi]
656
        jz      @f
657
.scanlistcont:
658
        movzx   ecx, word [esi+4]
659
        add     esi, ecx
660
        jmp     .scanlist
661
@@:
273 diamond 662
; ignore named $DATA attributes (aka NTFS streams)
663
        cmp     eax, 0x80
664
        jnz     @f
665
        cmp     byte [esi+6], 0
666
        jnz     .scanlistcont
667
@@:
256 diamond 668
        push    eax
669
        mov     eax, [esi+8]
257 diamond 670
        test    eax, eax
671
        jnz     .testf
3908 Serge 672
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
673
        and     eax, dword [ebp+NTFS.ntfs_attr_size+4]
257 diamond 674
        cmp     eax, -1
675
        jnz     .testfz
676
; if attribute is in auxiliary records, its size is defined only in first
677
        mov     eax, [esi+10h]
678
        call    ntfs_read_file_record
3908 Serge 679
        jnc     @f
257 diamond 680
.errret_pop:
3908 Serge 681
        pop     ecx ecx
257 diamond 682
        jmp     .errret
3908 Serge 683
.errret2_pop:
684
        xor     eax, eax
685
        jmp     .errret_pop
257 diamond 686
@@:
3908 Serge 687
        mov     eax, [ebp+NTFS.frs_buffer]
257 diamond 688
        movzx   ecx, word [eax+14h]
689
        add     eax, ecx
3908 Serge 690
        mov     ecx, [ebp+NTFS.ntfs_cur_attr]
257 diamond 691
@@:
692
        cmp     dword [eax], -1
3908 Serge 693
        jz      .errret2_pop
257 diamond 694
        cmp     dword [eax], ecx
695
        jz      @f
273 diamond 696
.l1:
257 diamond 697
        add     eax, [eax+4]
698
        jmp     @b
699
@@:
273 diamond 700
        cmp     eax, 0x80
701
        jnz     @f
702
        cmp     byte [eax+9], 0
703
        jnz     .l1
704
@@:
257 diamond 705
        cmp     byte [eax+8], 0
706
        jnz     .sdnores
707
        mov     eax, [eax+10h]
3908 Serge 708
        mov     dword [ebp+NTFS.ntfs_attr_size], eax
709
        and     dword [ebp+NTFS.ntfs_attr_size+4], 0
257 diamond 710
        jmp     .testfz
711
.sdnores:
712
        mov     ecx, [eax+30h]
3908 Serge 713
        mov     dword [ebp+NTFS.ntfs_attr_size], ecx
257 diamond 714
        mov     ecx, [eax+34h]
3908 Serge 715
        mov     dword [ebp+NTFS.ntfs_attr_size+4], ecx
257 diamond 716
.testfz:
717
        xor     eax, eax
718
.testf:
3908 Serge 719
        imul    eax, [ebp+NTFS.sectors_per_cluster]
720
        cmp     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 721
        pop     eax
722
        ja      @f
723
        mov     edi, [esi+10h]  ; keep previous iRecord
724
        jmp     .scanlistcont
725
@@:
3908 Serge 726
        pop     ecx
257 diamond 727
.scanlistfound:
256 diamond 728
        cmp     edi, -1
729
        jnz     @f
730
        popad
731
        ret
732
@@:
3908 Serge 733
        mov     eax, [ebp+NTFS.ntfs_cur_iRecord]
734
        mov     [ebp+NTFS.ntfs_attr_iBaseRecord], eax
256 diamond 735
        mov     eax, edi
736
        jmp     .beginfindattr
737
.scanlistdone:
3908 Serge 738
        pop     ecx
739
        sub     ecx, ebp
740
        sub     ecx, NTFS.ntfs_attrlist_buf-1Ah
741
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
256 diamond 742
        jnz     @f
3908 Serge 743
        sub     ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf
273 diamond 744
@@:
3908 Serge 745
        cmp     ecx, 0x400
257 diamond 746
        jnz     .scanlistfound
256 diamond 747
        inc     edx
748
        push    esi edi
3908 Serge 749
        lea     esi, [ebp+NTFS.ntfs_attrlist_buf+0x200]
750
        lea     edi, [ebp+NTFS.ntfs_attrlist_buf]
751
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
273 diamond 752
        jnz     @f
3908 Serge 753
        lea     esi, [ebp+NTFS.ntfs_attrlist_mft_buf+0x200]
754
        lea     edi, [ebp+NTFS.ntfs_attrlist_mft_buf]
273 diamond 755
@@:
256 diamond 756
        mov     ecx, 0x200/4
3908 Serge 757
        rep movsd
273 diamond 758
        mov     eax, edi
256 diamond 759
        pop     edi esi
760
        sub     esi, 0x200
3908 Serge 761
        push    [ebp+NTFS.ntfs_cur_offs]
762
        push    [ebp+NTFS.ntfs_cur_size]
763
        push    [ebp+NTFS.ntfs_cur_read]
764
        push    [ebp+NTFS.ntfs_cur_buf]
765
        push    dword [ebp+NTFS.ntfs_attr_size]
766
        push    dword [ebp+NTFS.ntfs_attr_size+4]
767
        or      dword [ebp+NTFS.ntfs_attr_size], -1
768
        or      dword [ebp+NTFS.ntfs_attr_size+4], -1
769
        mov     [ebp+NTFS.ntfs_cur_offs], edx
770
        mov     [ebp+NTFS.ntfs_cur_size], 1
771
        and     [ebp+NTFS.ntfs_cur_read], 0
772
        mov     [ebp+NTFS.ntfs_cur_buf], eax
773
        mov     ecx, [ebp+NTFS.ntfs_attr_list]
774
        push    esi edx edi
256 diamond 775
        call    .doreadattr
3908 Serge 776
        pop     edi edx esi
777
        mov     ecx, [ebp+NTFS.ntfs_cur_read]
778
        pop     dword [ebp+NTFS.ntfs_attr_size+4]
779
        pop     dword [ebp+NTFS.ntfs_attr_size]
780
        pop     [ebp+NTFS.ntfs_cur_buf]
781
        pop     [ebp+NTFS.ntfs_cur_read]
782
        pop     [ebp+NTFS.ntfs_cur_size]
783
        pop     [ebp+NTFS.ntfs_cur_offs]
256 diamond 784
        jc      .errret
3908 Serge 785
        lea     ecx, [ecx+ebp+NTFS.ntfs_attrlist_buf+0x200-0x1A]
786
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
273 diamond 787
        jnz     .scanliststart
3908 Serge 788
        add     ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf
256 diamond 789
        jmp     .scanliststart
790
 
791
.doreadattr:
3908 Serge 792
        mov     [ebp+NTFS.ntfs_bCanContinue], 0
256 diamond 793
        cmp     byte [ecx+8], 0
794
        jnz     .nonresident
795
        mov     eax, [ecx+10h]  ; length
796
        mov     esi, eax
3908 Serge 797
        mov     edx, [ebp+NTFS.ntfs_cur_offs]
256 diamond 798
        shr     eax, 9
799
        cmp     eax, edx
800
        jb      .okret
801
        shl     edx, 9
802
        sub     esi, edx
803
        movzx   eax, word [ecx+14h]
804
        add     edx, eax
805
        add     edx, ecx        ; edx -> data
3908 Serge 806
        mov     eax, [ebp+NTFS.ntfs_cur_size]
256 diamond 807
        cmp     eax, (0xFFFFFFFF shr 9)+1
808
        jbe     @f
809
        mov     eax, (0xFFFFFFFF shr 9)+1
810
@@:
811
        shl     eax, 9
812
        cmp     eax, esi
813
        jbe     @f
814
        mov     eax, esi
815
@@:
816
; eax = length, edx -> data
3908 Serge 817
        mov     [ebp+NTFS.ntfs_cur_read], eax
256 diamond 818
        mov     ecx, eax
819
        mov     eax, edx
3908 Serge 820
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
256 diamond 821
        call    memmove
3908 Serge 822
        and     [ebp+NTFS.ntfs_cur_size], 0      ; CF=0
256 diamond 823
        ret
824
.nonresident:
257 diamond 825
; Not all auxiliary records contain correct FileSize info
3908 Serge 826
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
827
        mov     edx, dword [ebp+NTFS.ntfs_attr_size+4]
257 diamond 828
        push    eax
829
        and     eax, edx
830
        cmp     eax, -1
831
        pop     eax
832
        jnz     @f
256 diamond 833
        mov     eax, [ecx+30h]  ; FileSize
834
        mov     edx, [ecx+34h]
3908 Serge 835
        mov     dword [ebp+NTFS.ntfs_attr_size], eax
836
        mov     dword [ebp+NTFS.ntfs_attr_size+4], edx
257 diamond 837
@@:
256 diamond 838
        add     eax, 0x1FF
839
        adc     edx, 0
840
        shrd    eax, edx, 9
3908 Serge 841
        sub     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 842
        ja      @f
843
; return with nothing read
3908 Serge 844
        and     [ebp+NTFS.ntfs_cur_size], 0
256 diamond 845
.okret:
846
        clc
847
        ret
848
@@:
849
; reduce read length
3908 Serge 850
        and     [ebp+NTFS.ntfs_cur_tail], 0
851
        cmp     [ebp+NTFS.ntfs_cur_size], eax
256 diamond 852
        jb      @f
3908 Serge 853
        mov     [ebp+NTFS.ntfs_cur_size], eax
854
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
262 diamond 855
        and     eax, 0x1FF
3908 Serge 856
        mov     [ebp+NTFS.ntfs_cur_tail], eax
256 diamond 857
@@:
3908 Serge 858
        cmp     [ebp+NTFS.ntfs_cur_size], 0
256 diamond 859
        jz      .okret
3908 Serge 860
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 861
        xor     edx, edx
3908 Serge 862
        div     [ebp+NTFS.sectors_per_cluster]
256 diamond 863
        sub     eax, [ecx+10h]  ; first_vbo
864
        jb      .okret
865
; eax = cluster, edx = starting sector
866
        sub     esp, 10h
867
        movzx   esi, word [ecx+20h]     ; mcb_info_ofs
868
        add     esi, ecx
3908 Serge 869
        xor     edi, edi
256 diamond 870
.readloop:
871
        call    ntfs_decode_mcb_entry
872
        jnc     .break
3908 Serge 873
        add     edi, [esp+8]
256 diamond 874
        sub     eax, [esp]
875
        jae     .readloop
876
        push    ecx
877
        push    eax
878
        add     eax, [esp+8]
3908 Serge 879
        add     eax, edi
880
        imul    eax, [ebp+NTFS.sectors_per_cluster]
256 diamond 881
        add     eax, edx
882
        pop     ecx
883
        neg     ecx
3908 Serge 884
        imul    ecx, [ebp+NTFS.sectors_per_cluster]
256 diamond 885
        sub     ecx, edx
3908 Serge 886
        cmp     ecx, [ebp+NTFS.ntfs_cur_size]
256 diamond 887
        jb      @f
3908 Serge 888
        mov     ecx, [ebp+NTFS.ntfs_cur_size]
256 diamond 889
@@:
3908 Serge 890
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
256 diamond 891
@@:
3908 Serge 892
        push    eax
893
        cmp     [ebp+NTFS.ntfs_cur_attr], 0x80
894
        jnz     .sys
895
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
896
        jz      .sys
897
        call    fs_read32_app
898
        jmp     .appsys
899
.sys:
900
        call    fs_read32_sys
901
.appsys:
902
        pop     edx
903
        test    eax, eax
256 diamond 904
        jnz     .errread2
905
        add     ebx, 0x200
3908 Serge 906
        mov     [ebp+NTFS.ntfs_cur_buf], ebx
907
        lea     eax, [edx+1]
908
        add     [ebp+NTFS.ntfs_cur_read], 0x200
909
        dec     [ebp+NTFS.ntfs_cur_size]
910
        inc     [ebp+NTFS.ntfs_cur_offs]
256 diamond 911
        loop    @b
912
        pop     ecx
265 diamond 913
        xor     eax, eax
914
        xor     edx, edx
3908 Serge 915
        cmp     [ebp+NTFS.ntfs_cur_size], 0
256 diamond 916
        jnz     .readloop
917
        add     esp, 10h
3908 Serge 918
        mov     eax, [ebp+NTFS.ntfs_cur_tail]
262 diamond 919
        test    eax, eax
820 diamond 920
        jz      @f
262 diamond 921
        sub     eax, 0x200
3908 Serge 922
        add     [ebp+NTFS.ntfs_cur_read], eax
820 diamond 923
@@:
924
        clc
925
        ret
256 diamond 926
.errread2:
927
        pop     ecx
928
        add     esp, 10h
820 diamond 929
        stc
930
        ret
256 diamond 931
.break:
932
        add     esp, 10h        ; CF=0
3908 Serge 933
        mov     [ebp+NTFS.ntfs_bCanContinue], 1
256 diamond 934
        ret
935
 
936
ntfs_read_file_record:
937
; in: eax=iRecord
3908 Serge 938
; out: [ebp+NTFS.frs_buffer] contains information
939
;      CF=1 - failed, in this case eax=0 => something with FS, eax nonzero => disk error
940
; Read attr $DATA of $Mft, starting from eax*[ebp+NTFS.frs_size]
256 diamond 941
        push    ecx edx
3908 Serge 942
        mov     ecx, [ebp+NTFS.frs_size]
256 diamond 943
        mul     ecx
944
        shrd    eax, edx, 9
945
        shr     edx, 9
3908 Serge 946
        jnz     .errret
947
        push    [ebp+NTFS.ntfs_attr_iRecord]
948
        push    [ebp+NTFS.ntfs_attr_iBaseRecord]
949
        push    [ebp+NTFS.ntfs_attr_offs]
950
        push    [ebp+NTFS.ntfs_attr_list]
951
        push    dword [ebp+NTFS.ntfs_attr_size+4]
952
        push    dword [ebp+NTFS.ntfs_attr_size]
953
        push    [ebp+NTFS.ntfs_cur_iRecord]
954
        push    [ebp+NTFS.ntfs_cur_attr]
955
        push    [ebp+NTFS.ntfs_cur_offs]
956
        push    [ebp+NTFS.ntfs_cur_size]
957
        push    [ebp+NTFS.ntfs_cur_buf]
958
        push    [ebp+NTFS.ntfs_cur_read]
959
        mov     [ebp+NTFS.ntfs_cur_attr], 0x80   ; $DATA
960
        and     [ebp+NTFS.ntfs_cur_iRecord], 0   ; $Mft
961
        mov     [ebp+NTFS.ntfs_cur_offs], eax
256 diamond 962
        shr     ecx, 9
3908 Serge 963
        mov     [ebp+NTFS.ntfs_cur_size], ecx
964
        mov     eax, [ebp+NTFS.frs_buffer]
965
        mov     [ebp+NTFS.ntfs_cur_buf], eax
256 diamond 966
        call    ntfs_read_attr
3908 Serge 967
        mov     edx, [ebp+NTFS.ntfs_cur_read]
968
        pop     [ebp+NTFS.ntfs_cur_read]
969
        pop     [ebp+NTFS.ntfs_cur_buf]
970
        pop     [ebp+NTFS.ntfs_cur_size]
971
        pop     [ebp+NTFS.ntfs_cur_offs]
972
        pop     [ebp+NTFS.ntfs_cur_attr]
973
        pop     [ebp+NTFS.ntfs_cur_iRecord]
974
        pop     dword [ebp+NTFS.ntfs_attr_size]
975
        pop     dword [ebp+NTFS.ntfs_attr_size+4]
976
        pop     [ebp+NTFS.ntfs_attr_list]
977
        pop     [ebp+NTFS.ntfs_attr_offs]
978
        pop     [ebp+NTFS.ntfs_attr_iBaseRecord]
979
        pop     [ebp+NTFS.ntfs_attr_iRecord]
980
        jc      .ret
981
        cmp     edx, [ebp+NTFS.frs_size]
256 diamond 982
        jnz     .errret
3908 Serge 983
        mov     eax, [ebp+NTFS.frs_buffer]
256 diamond 984
        cmp     dword [eax], 'FILE'
985
        jnz     .errret
986
        push    ebx
987
        mov     ebx, eax
988
        call    ntfs_restore_usa_frs
989
        pop     ebx
3908 Serge 990
        jc      .errret
256 diamond 991
.ret:
3908 Serge 992
        pop     edx ecx
256 diamond 993
        ret
3908 Serge 994
.errret:
256 diamond 995
        pop     edx ecx
996
        xor     eax, eax
3908 Serge 997
        stc
256 diamond 998
        ret
999
 
1000
ntfs_restore_usa_frs:
3908 Serge 1001
        mov     eax, [ebp+NTFS.frs_size]
256 diamond 1002
ntfs_restore_usa:
1003
        pushad
1004
        shr     eax, 9
1005
        mov     ecx, eax
1006
        inc     eax
1007
        cmp     [ebx+6], ax
1008
        jnz     .err
1009
        movzx   eax, word [ebx+4]
1010
        lea     esi, [eax+ebx]
1011
        lodsw
1012
        mov     edx, eax
1013
        lea     edi, [ebx+0x1FE]
1014
@@:
1015
        cmp     [edi], dx
1016
        jnz     .err
1017
        lodsw
1018
        stosw
1019
        add     edi, 0x1FE
1020
        loop    @b
1021
        popad
1022
        clc
1023
        ret
1024
.err:
1025
        popad
1026
        stc
1027
        ret
1028
 
1029
ntfs_decode_mcb_entry:
1030
        push    eax ecx edi
1031
        lea     edi, [esp+16]
1032
        xor     eax, eax
1033
        lodsb
1034
        test    al, al
1035
        jz      .end
1036
        mov     ecx, eax
1037
        and     ecx, 0xF
1038
        cmp     ecx, 8
1039
        ja      .end
1040
        push    ecx
3908 Serge 1041
        rep movsb
256 diamond 1042
        pop     ecx
1043
        sub     ecx, 8
1044
        neg     ecx
1045
        cmp     byte [esi-1], 80h
1046
        jae     .end
1047
        push    eax
1048
        xor     eax, eax
3908 Serge 1049
        rep stosb
256 diamond 1050
        pop     ecx
1051
        shr     ecx, 4
1052
        cmp     ecx, 8
1053
        ja      .end
1054
        push    ecx
3908 Serge 1055
        rep movsb
256 diamond 1056
        pop     ecx
1057
        sub     ecx, 8
1058
        neg     ecx
1059
        cmp     byte [esi-1], 80h
257 diamond 1060
        cmc
256 diamond 1061
        sbb     eax, eax
3908 Serge 1062
        rep stosb
256 diamond 1063
        stc
1064
.end:
1065
        pop     edi ecx eax
1066
        ret
1067
 
1504 diamond 1068
unichar_toupper:
1069
        push    eax
1070
        call    uni2ansi_char
1071
        cmp     al, '_'
1072
        jz      .unk
1073
        add     esp, 4
2465 Serge 1074
        call    char_toupper
1075
        jmp     ansi2uni_char
1076
.unk:
1077
        pop     eax
1078
        ret
1504 diamond 1079
 
257 diamond 1080
ntfs_find_lfn:
3908 Serge 1081
; in: esi+[esp+4] -> name
257 diamond 1082
; out: CF=1 - file not found
3908 Serge 1083
;      else CF=0, [ebp+NTFS.ntfs_cur_iRecord] valid, eax->record in parent directory
1084
        mov     [ebp+NTFS.ntfs_cur_iRecord], 5   ; start parse from root cluster
257 diamond 1085
.doit2:
3908 Serge 1086
        mov     [ebp+NTFS.ntfs_cur_attr], 0x90   ; $INDEX_ROOT
1087
        and     [ebp+NTFS.ntfs_cur_offs], 0
1088
        mov     eax, [ebp+NTFS.cur_index_size]
1089
        mov     [ebp+NTFS.ntfs_cur_size], eax
1090
        mov     eax, [ebp+NTFS.cur_index_buf]
1091
        mov     [ebp+NTFS.ntfs_cur_buf], eax
257 diamond 1092
        call    ntfs_read_attr
1093
        jnc     @f
1094
.ret:
3908 Serge 1095
        ret     4
257 diamond 1096
@@:
3908 Serge 1097
        xor     eax, eax
1098
        cmp     [ebp+NTFS.ntfs_cur_read], 0x20
257 diamond 1099
        jc      .ret
1100
        pushad
3908 Serge 1101
        mov     esi, [ebp+NTFS.cur_index_buf]
257 diamond 1102
        mov     eax, [esi+14h]
1103
        add     eax, 10h
3908 Serge 1104
        cmp     [ebp+NTFS.ntfs_cur_read], eax
257 diamond 1105
        jae     .readok1
1106
        add     eax, 1FFh
1107
        shr     eax, 9
3908 Serge 1108
        cmp     eax, [ebp+NTFS.cur_index_size]
257 diamond 1109
        ja      @f
1110
.stc_ret:
1111
        popad
1112
        stc
3908 Serge 1113
        ret     4
257 diamond 1114
@@:
1115
; reallocate
1116
        push    eax
3908 Serge 1117
        push    [ebp+NTFS.cur_index_buf]
257 diamond 1118
        call    kernel_free
1119
        pop     eax
3908 Serge 1120
        mov     [ebp+NTFS.cur_index_size], eax
257 diamond 1121
        push    eax
1122
        call    kernel_alloc
1123
        test    eax, eax
1124
        jnz     @f
3908 Serge 1125
        and     [ebp+NTFS.cur_index_size], 0
1126
        and     [ebp+NTFS.cur_index_buf], 0
257 diamond 1127
        jmp     .stc_ret
1128
@@:
3908 Serge 1129
        mov     [ebp+NTFS.cur_index_buf], eax
257 diamond 1130
        popad
1131
        jmp     .doit2
1132
.readok1:
3908 Serge 1133
        mov     edx, [esi+8]    ; subnode_size
1134
        shr     edx, 9
1135
        cmp     edx, [ebp+NTFS.cur_index_size]
257 diamond 1136
        jbe     .ok2
3908 Serge 1137
        push    esi edx
1138
        push    edx
257 diamond 1139
        call    kernel_alloc
3908 Serge 1140
        pop     edx esi
257 diamond 1141
        test    eax, eax
1142
        jz      .stc_ret
1143
        mov     edi, eax
3908 Serge 1144
        mov     ecx, [ebp+NTFS.cur_index_size]
257 diamond 1145
        shl     ecx, 9-2
3908 Serge 1146
        rep movsd
257 diamond 1147
        mov     esi, eax
3908 Serge 1148
        mov     [ebp+NTFS.cur_index_size], edx
1149
        push    esi edx
1150
        push    [ebp+NTFS.cur_index_buf]
257 diamond 1151
        call    kernel_free
3908 Serge 1152
        pop     edx esi
1153
        mov     [ebp+NTFS.cur_index_buf], esi
257 diamond 1154
.ok2:
1155
        add     esi, 10h
1156
        mov     edi, [esp+4]
3908 Serge 1157
; edi -> name, esi -> current index data, edx = subnode size
257 diamond 1158
.scanloop:
1159
        add     esi, [esi]
1160
.scanloopint:
1161
        test    byte [esi+0Ch], 2
1162
        jnz     .subnode
1163
        push    esi
1164
        add     esi, 0x52
1165
        movzx   ecx, byte [esi-2]
1166
        push    edi
1167
@@:
1168
        lodsw
1504 diamond 1169
        call    unichar_toupper
257 diamond 1170
        push    eax
1171
        mov     al, [edi]
1172
        inc     edi
820 diamond 1173
        cmp     al, '/'
1174
        jz      .slash
257 diamond 1175
        call    char_toupper
1504 diamond 1176
        call    ansi2uni_char
1177
        cmp     ax, [esp]
257 diamond 1178
        pop     eax
1179
        loopz   @b
1180
        jz      .found
1181
        pop     edi
1182
        pop     esi
1183
        jb      .subnode
1184
.scanloopcont:
1185
        movzx   eax, word [esi+8]
1186
        add     esi, eax
1187
        jmp     .scanloopint
820 diamond 1188
.slash:
1189
        pop     eax
1190
        pop     edi
1191
        pop     esi
257 diamond 1192
.subnode:
1193
        test    byte [esi+0Ch], 1
1194
        jz      .notfound
1195
        movzx   eax, word [esi+8]
1196
        mov     eax, [esi+eax-8]
3908 Serge 1197
        imul    eax, [ebp+NTFS.sectors_per_cluster]
1198
        mov     [ebp+NTFS.ntfs_cur_offs], eax
1199
        mov     [ebp+NTFS.ntfs_cur_attr], 0xA0   ; $INDEX_ALLOCATION
1200
        mov     [ebp+NTFS.ntfs_cur_size], edx
1201
        mov     eax, [ebp+NTFS.cur_index_buf]
257 diamond 1202
        mov     esi, eax
3908 Serge 1203
        mov     [ebp+NTFS.ntfs_cur_buf], eax
1204
        push    edx
257 diamond 1205
        call    ntfs_read_attr
3908 Serge 1206
        pop     edx
1207
        mov     eax, edx
257 diamond 1208
        shl     eax, 9
3908 Serge 1209
        cmp     [ebp+NTFS.ntfs_cur_read], eax
257 diamond 1210
        jnz     .notfound
1211
        cmp     dword [esi], 'INDX'
1212
        jnz     .notfound
1213
        mov     ebx, esi
1214
        call    ntfs_restore_usa
1215
        jc      .notfound
1216
        add     esi, 0x18
1217
        jmp     .scanloop
1218
.notfound:
1219
        popad
1220
        stc
3908 Serge 1221
        ret     4
257 diamond 1222
.found:
1223
        cmp     byte [edi], 0
1224
        jz      .done
1225
        cmp     byte [edi], '/'
1226
        jz      .next
1227
        pop     edi
1228
        pop     esi
1229
        jmp     .scanloopcont
1230
.done:
1231
.next:
1232
        pop     esi
1233
        pop     esi
1234
        mov     eax, [esi]
3908 Serge 1235
        mov     [ebp+NTFS.ntfs_cur_iRecord], eax
262 diamond 1236
        mov     [esp+1Ch], esi
257 diamond 1237
        mov     [esp+4], edi
1238
        popad
1239
        inc     esi
1240
        cmp     byte [esi-1], 0
1241
        jnz     .doit2
3908 Serge 1242
        cmp     dword [esp+4], 0
521 diamond 1243
        jz      @f
3908 Serge 1244
        mov     esi, [esp+4]
1245
        mov     dword [esp+4], 0
521 diamond 1246
        jmp     .doit2
1247
@@:
3908 Serge 1248
        ret     4
257 diamond 1249
 
256 diamond 1250
;----------------------------------------------------------------
3908 Serge 1251
; ntfs_Read - NTFS implementation of reading a file
1252
; in:  ebp = pointer to NTFS structure
1253
; in:  esi+[esp+4] = name
1254
; in:  ebx = pointer to parameters from sysfunc 70
1255
; out: eax, ebx = return values for sysfunc 70
1256
;----------------------------------------------------------------
1257
ntfs_Read:
262 diamond 1258
        cmp     byte [esi], 0
1259
        jnz     @f
256 diamond 1260
        or      ebx, -1
3626 Serge 1261
        movi    eax, ERROR_ACCESS_DENIED
256 diamond 1262
        ret
262 diamond 1263
@@:
3908 Serge 1264
        call    ntfs_lock
1265
        stdcall ntfs_find_lfn, [esp+4]
262 diamond 1266
        jnc     .found
3908 Serge 1267
        call    ntfs_unlock
262 diamond 1268
        or      ebx, -1
3626 Serge 1269
        movi    eax, ERROR_FILE_NOT_FOUND
262 diamond 1270
        ret
1271
.found:
3908 Serge 1272
        mov     [ebp+NTFS.ntfs_cur_attr], 0x80   ; $DATA
1273
        and     [ebp+NTFS.ntfs_cur_offs], 0
1274
        and     [ebp+NTFS.ntfs_cur_size], 0
262 diamond 1275
        call    ntfs_read_attr
1276
        jnc     @f
3908 Serge 1277
        call    ntfs_unlock
262 diamond 1278
        or      ebx, -1
3626 Serge 1279
        movi    eax, ERROR_ACCESS_DENIED
262 diamond 1280
        ret
1281
@@:
1282
        pushad
1283
        and     dword [esp+10h], 0
1284
        xor     eax, eax
3908 Serge 1285
        cmp     dword [ebx+8], 0x200
262 diamond 1286
        jb      @f
1287
.eof0:
1288
        popad
1289
        xor     ebx, ebx
1290
.eof:
3626 Serge 1291
        movi    eax, ERROR_END_OF_FILE
3908 Serge 1292
        push    eax
1293
        call    ntfs_unlock
1294
        pop     eax
262 diamond 1295
        ret
1296
@@:
3908 Serge 1297
        mov     ecx, [ebx+12]
1298
        mov     edx, [ebx+16]
1299
        mov     eax, [ebx+4]
262 diamond 1300
        test    eax, 0x1FF
1301
        jz      .alignedstart
1302
        push    edx
3908 Serge 1303
        mov     edx, [ebx+8]
262 diamond 1304
        shrd    eax, edx, 9
1305
        pop     edx
3908 Serge 1306
        mov     [ebp+NTFS.ntfs_cur_offs], eax
1307
        mov     [ebp+NTFS.ntfs_cur_size], 1
1308
        lea     eax, [ebp+NTFS.ntfs_bitmap_buf]
1309
        mov     [ebp+NTFS.ntfs_cur_buf], eax
262 diamond 1310
        call    ntfs_read_attr.continue
3908 Serge 1311
        mov     eax, [ebx+4]
262 diamond 1312
        and     eax, 0x1FF
3908 Serge 1313
        lea     esi, [ebp+NTFS.ntfs_bitmap_buf+eax]
1314
        sub     eax, [ebp+NTFS.ntfs_cur_read]
262 diamond 1315
        jae     .eof0
1316
        neg     eax
1317
        push    ecx
1318
        cmp     ecx, eax
1319
        jb      @f
1320
        mov     ecx, eax
1321
@@:
1322
        mov     [esp+10h+4], ecx
1323
        mov     edi, edx
3908 Serge 1324
        rep movsb
262 diamond 1325
        mov     edx, edi
1326
        pop     ecx
1327
        sub     ecx, [esp+10h]
1328
        jnz     @f
1329
.retok:
1330
        popad
3908 Serge 1331
        call    ntfs_unlock
262 diamond 1332
        xor     eax, eax
1333
        ret
1334
@@:
3908 Serge 1335
        cmp     [ebp+NTFS.ntfs_cur_read], 0x200
262 diamond 1336
        jz      .alignedstart
1337
.eof_ebx:
1338
        popad
1339
        jmp     .eof
1340
.alignedstart:
3908 Serge 1341
        mov     eax, [ebx+4]
262 diamond 1342
        push    edx
3908 Serge 1343
        mov     edx, [ebx+8]
262 diamond 1344
        add     eax, 511
1345
        adc     edx, 0
1346
        shrd    eax, edx, 9
1347
        pop     edx
1348
.zero1:
3908 Serge 1349
        mov     [ebp+NTFS.ntfs_cur_offs], eax
1350
        mov     [ebp+NTFS.ntfs_cur_buf], edx
262 diamond 1351
        mov     eax, ecx
1352
        shr     eax, 9
3908 Serge 1353
        mov     [ebp+NTFS.ntfs_cur_size], eax
1354
        add     eax, [ebp+NTFS.ntfs_cur_offs]
262 diamond 1355
        push    eax
1356
        call    ntfs_read_attr.continue
3908 Serge 1357
        pop     [ebp+NTFS.ntfs_cur_offs]
1358
        mov     eax, [ebp+NTFS.ntfs_cur_read]
262 diamond 1359
        add     [esp+10h], eax
1360
        mov     eax, ecx
1361
        and     eax, not 0x1FF
3908 Serge 1362
        cmp     [ebp+NTFS.ntfs_cur_read], eax
262 diamond 1363
        jnz     .eof_ebx
1364
        and     ecx, 0x1FF
1365
        jz      .retok
3908 Serge 1366
        add     edx, [ebp+NTFS.ntfs_cur_read]
1367
        mov     [ebp+NTFS.ntfs_cur_size], 1
1368
        lea     eax, [ebp+NTFS.ntfs_bitmap_buf]
1369
        mov     [ebp+NTFS.ntfs_cur_buf], eax
262 diamond 1370
        call    ntfs_read_attr.continue
3908 Serge 1371
        cmp     [ebp+NTFS.ntfs_cur_read], ecx
262 diamond 1372
        jb      @f
3908 Serge 1373
        mov     [ebp+NTFS.ntfs_cur_read], ecx
262 diamond 1374
@@:
3908 Serge 1375
        xchg    ecx, [ebp+NTFS.ntfs_cur_read]
262 diamond 1376
        push    ecx
1377
        mov     edi, edx
3908 Serge 1378
        lea     esi, [ebp+NTFS.ntfs_bitmap_buf]
262 diamond 1379
        add     [esp+10h+4], ecx
3908 Serge 1380
        rep movsb
262 diamond 1381
        pop     ecx
1382
        xor     eax, eax
3908 Serge 1383
        cmp     ecx, [ebp+NTFS.ntfs_cur_read]
262 diamond 1384
        jz      @f
1385
        mov     al, ERROR_END_OF_FILE
1386
@@:
1387
        mov     [esp+1Ch], eax
3908 Serge 1388
        call    ntfs_unlock
262 diamond 1389
        popad
1390
        ret
256 diamond 1391
 
1392
;----------------------------------------------------------------
3908 Serge 1393
; ntfs_ReadFolder - NTFS implementation of reading a folder
1394
; in:  ebp = pointer to NTFS structure
1395
; in:  esi+[esp+4] = name
1396
; in:  ebx = pointer to parameters from sysfunc 70
1397
; out: eax, ebx = return values for sysfunc 70
1398
;----------------------------------------------------------------
1399
ntfs_ReadFolder:
1400
        call    ntfs_lock
256 diamond 1401
        mov     eax, 5          ; root cluster
1402
        cmp     byte [esi], 0
1403
        jz      .doit
3908 Serge 1404
        stdcall ntfs_find_lfn, [esp+4]
257 diamond 1405
        jnc     .doit2
256 diamond 1406
.notfound:
1407
        or      ebx, -1
1408
        push    ERROR_FILE_NOT_FOUND
1409
.pop_ret:
3908 Serge 1410
        call    ntfs_unlock
256 diamond 1411
        pop     eax
1412
        ret
1413
.doit:
3908 Serge 1414
        mov     [ebp+NTFS.ntfs_cur_iRecord], eax
256 diamond 1415
.doit2:
3908 Serge 1416
        mov     [ebp+NTFS.ntfs_cur_attr], 0x10   ; $STANDARD_INFORMATION
1417
        and     [ebp+NTFS.ntfs_cur_offs], 0
1418
        mov     [ebp+NTFS.ntfs_cur_size], 1
1419
        lea     eax, [ebp+NTFS.ntfs_bitmap_buf]
1420
        mov     [ebp+NTFS.ntfs_cur_buf], eax
257 diamond 1421
        call    ntfs_read_attr
1422
        jc      .notfound
3908 Serge 1423
        mov     [ebp+NTFS.ntfs_cur_attr], 0x90   ; $INDEX_ROOT
1424
        and     [ebp+NTFS.ntfs_cur_offs], 0
1425
        mov     eax, [ebp+NTFS.cur_index_size]
1426
        mov     [ebp+NTFS.ntfs_cur_size], eax
1427
        mov     eax, [ebp+NTFS.cur_index_buf]
1428
        mov     [ebp+NTFS.ntfs_cur_buf], eax
256 diamond 1429
        call    ntfs_read_attr
1430
        jnc     .ok
3908 Serge 1431
        test    eax, eax
256 diamond 1432
        jz      .notfound
1433
        or      ebx, -1
1434
        push    11
1435
        jmp     .pop_ret
1436
.ok:
3908 Serge 1437
        cmp     [ebp+NTFS.ntfs_cur_read], 0x20
256 diamond 1438
        jae     @f
1439
        or      ebx, -1
1440
.fserr:
1441
        push    ERROR_FAT_TABLE
1442
        jmp     .pop_ret
1443
@@:
1444
        pushad
3908 Serge 1445
        mov     esi, [ebp+NTFS.cur_index_buf]
256 diamond 1446
        mov     eax, [esi+14h]
1447
        add     eax, 10h
3908 Serge 1448
        cmp     [ebp+NTFS.ntfs_cur_read], eax
256 diamond 1449
        jae     .readok1
1450
        add     eax, 1FFh
1451
        shr     eax, 9
3908 Serge 1452
        cmp     eax, [ebp+NTFS.cur_index_size]
256 diamond 1453
        ja      @f
1454
        popad
1455
        jmp     .fserr
1456
@@:
1457
; reallocate
1458
        push    eax
3908 Serge 1459
        push    [ebp+NTFS.cur_index_buf]
256 diamond 1460
        call    kernel_free
1461
        pop     eax
3908 Serge 1462
        mov     [ebp+NTFS.cur_index_size], eax
256 diamond 1463
        push    eax
1464
        call    kernel_alloc
1465
        test    eax, eax
1466
        jnz     @f
3908 Serge 1467
        and     [ebp+NTFS.cur_index_size], 0
1468
        and     [ebp+NTFS.cur_index_buf], 0
256 diamond 1469
.nomem:
3908 Serge 1470
        call    ntfs_unlock
256 diamond 1471
        popad
1472
        or      ebx, -1
3626 Serge 1473
        movi    eax, 12
256 diamond 1474
        ret
1475
@@:
3908 Serge 1476
        mov     [ebp+NTFS.cur_index_buf], eax
256 diamond 1477
        popad
1478
        jmp     .doit2
1479
.readok1:
3908 Serge 1480
        mov     edx, [esi+8]    ; subnode_size
1481
        shr     edx, 9
1482
        mov     [ebp+NTFS.cur_subnode_size], edx
1483
        cmp     edx, [ebp+NTFS.cur_index_size]
256 diamond 1484
        jbe     .ok2
3908 Serge 1485
        push    esi edx
1486
        push    edx
256 diamond 1487
        call    kernel_alloc
3908 Serge 1488
        pop     edx esi
256 diamond 1489
        test    eax, eax
1490
        jz      .nomem
1491
        mov     edi, eax
3908 Serge 1492
        mov     ecx, [ebp+NTFS.cur_index_size]
256 diamond 1493
        shl     ecx, 9-2
3908 Serge 1494
        rep movsd
256 diamond 1495
        mov     esi, eax
3908 Serge 1496
        mov     [ebp+NTFS.cur_index_size], edx
1497
        push    [ebp+NTFS.cur_index_buf]
256 diamond 1498
        call    kernel_free
3908 Serge 1499
        mov     [ebp+NTFS.cur_index_buf], esi
256 diamond 1500
.ok2:
1501
        add     esi, 10h
3908 Serge 1502
        mov     edx, [ebx+16]
1503
        push    dword [ebx+8]   ; read ANSI/UNICODE name
256 diamond 1504
; init header
1505
        mov     edi, edx
1506
        mov     ecx, 32/4
1507
        xor     eax, eax
3908 Serge 1508
        rep stosd
256 diamond 1509
        mov     byte [edx], 1   ; version
3908 Serge 1510
        mov     ecx, [ebx+12]
1511
        mov     ebx, [ebx+4]
256 diamond 1512
        push    edx
1513
        mov     edx, esp
3908 Serge 1514
; edi -> BDFE, esi -> current index data, ebx = first wanted block,
256 diamond 1515
; ecx = number of blocks to read
1516
; edx -> parameters block: dd , dd 
3908 Serge 1517
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 5
257 diamond 1518
        jz      .skip_specials
1519
; dot and dotdot entries
1520
        push    esi
1521
        xor     esi, esi
1522
        call    .add_special_entry
1523
        inc     esi
1524
        call    .add_special_entry
1525
        pop     esi
1526
.skip_specials:
256 diamond 1527
; at first, dump index root
1528
        add     esi, [esi]
1529
.dump_root:
1530
        test    byte [esi+0Ch], 2
1531
        jnz     .dump_root_done
1532
        call    .add_entry
1533
        movzx   eax, word [esi+8]
1534
        add     esi, eax
1535
        jmp     .dump_root
1536
.dump_root_done:
1537
; now dump all subnodes
1538
        push    ecx edi
3908 Serge 1539
        lea     edi, [ebp+NTFS.ntfs_bitmap_buf]
1540
        mov     [ebp+NTFS.ntfs_cur_buf], edi
256 diamond 1541
        mov     ecx, 0x400/4
1542
        xor     eax, eax
3908 Serge 1543
        rep stosd
1544
        mov     [ebp+NTFS.ntfs_cur_attr], 0xB0   ; $BITMAP
1545
        and     [ebp+NTFS.ntfs_cur_offs], 0
1546
        mov     [ebp+NTFS.ntfs_cur_size], 2
256 diamond 1547
        call    ntfs_read_attr
1548
        pop     edi ecx
1549
        push    0       ; save offset in $BITMAP attribute
3908 Serge 1550
        and     [ebp+NTFS.ntfs_cur_offs], 0
256 diamond 1551
.dumploop:
3908 Serge 1552
        mov     [ebp+NTFS.ntfs_cur_attr], 0xA0
1553
        mov     eax, [ebp+NTFS.cur_subnode_size]
1554
        mov     [ebp+NTFS.ntfs_cur_size], eax
1555
        mov     eax, [ebp+NTFS.cur_index_buf]
256 diamond 1556
        mov     esi, eax
3908 Serge 1557
        mov     [ebp+NTFS.ntfs_cur_buf], eax
1558
        push    [ebp+NTFS.ntfs_cur_offs]
1559
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
1560
        imul    eax, [ebp+NTFS.cur_subnode_size]
1561
        mov     [ebp+NTFS.ntfs_cur_offs], eax
256 diamond 1562
        call    ntfs_read_attr
3908 Serge 1563
        pop     [ebp+NTFS.ntfs_cur_offs]
1564
        mov     eax, [ebp+NTFS.cur_subnode_size]
256 diamond 1565
        shl     eax, 9
3908 Serge 1566
        cmp     [ebp+NTFS.ntfs_cur_read], eax
256 diamond 1567
        jnz     .done
1568
        push    eax
3908 Serge 1569
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 1570
        and     eax, 0x400*8-1
3908 Serge 1571
        bt      dword [ebp+NTFS.ntfs_bitmap_buf], eax
256 diamond 1572
        pop     eax
1573
        jnc     .dump_subnode_done
1574
        cmp     dword [esi], 'INDX'
1575
        jnz     .dump_subnode_done
1576
        push    ebx
1577
        mov     ebx, esi
1578
        call    ntfs_restore_usa
1579
        pop     ebx
1580
        jc      .dump_subnode_done
1581
        add     esi, 0x18
1582
        add     esi, [esi]
1583
.dump_subnode:
1584
        test    byte [esi+0Ch], 2
1585
        jnz     .dump_subnode_done
1586
        call    .add_entry
1587
        movzx   eax, word [esi+8]
1588
        add     esi, eax
1589
        jmp     .dump_subnode
1590
.dump_subnode_done:
3908 Serge 1591
        inc     [ebp+NTFS.ntfs_cur_offs]
1592
        test    [ebp+NTFS.ntfs_cur_offs], 0x400*8-1
256 diamond 1593
        jnz     .dumploop
3908 Serge 1594
        mov     [ebp+NTFS.ntfs_cur_attr], 0xB0
256 diamond 1595
        push    ecx edi
3908 Serge 1596
        lea     edi, [ebp+NTFS.ntfs_bitmap_buf]
1597
        mov     [ebp+NTFS.ntfs_cur_buf], edi
256 diamond 1598
        mov     ecx, 0x400/4
1599
        xor     eax, eax
3908 Serge 1600
        rep stosd
256 diamond 1601
        pop     edi ecx
1602
        pop     eax
3908 Serge 1603
        push    [ebp+NTFS.ntfs_cur_offs]
256 diamond 1604
        inc     eax
3908 Serge 1605
        mov     [ebp+NTFS.ntfs_cur_offs], eax
1606
        mov     [ebp+NTFS.ntfs_cur_size], 2
256 diamond 1607
        push    eax
1608
        call    ntfs_read_attr
1609
        pop     eax
3908 Serge 1610
        pop     [ebp+NTFS.ntfs_cur_offs]
256 diamond 1611
        push    eax
1612
        jmp     .dumploop
1613
.done:
1614
        pop     eax
1615
        pop     edx
1616
        mov     ebx, [edx+4]
1617
        pop     edx
1618
        xor     eax, eax
1619
        dec     ecx
1620
        js      @f
1621
        mov     al, ERROR_END_OF_FILE
1622
@@:
1623
        mov     [esp+1Ch], eax
1624
        mov     [esp+10h], ebx
3908 Serge 1625
        call    ntfs_unlock
256 diamond 1626
        popad
1627
        ret
1628
 
257 diamond 1629
.add_special_entry:
1630
        mov     eax, [edx]
1631
        inc     dword [eax+8]   ; new file found
1632
        dec     ebx
1633
        jns     .ret
1634
        dec     ecx
1635
        js      .ret
1636
        inc     dword [eax+4]   ; new file block copied
1637
        mov     eax, [edx+4]
1638
        mov     [edi+4], eax
1639
;        mov     eax, dword [ntfs_bitmap_buf+0x20]
1640
;        or      al, 0x10
1641
        mov     eax, 0x10
1642
        stosd
1643
        scasd
1644
        push    edx
3908 Serge 1645
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf]
1646
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+4]
257 diamond 1647
        call    ntfs_datetime_to_bdfe
3908 Serge 1648
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf+0x18]
1649
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+0x1C]
257 diamond 1650
        call    ntfs_datetime_to_bdfe
3908 Serge 1651
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf+8]
1652
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+0xC]
257 diamond 1653
        call    ntfs_datetime_to_bdfe
1654
        pop     edx
1655
        xor     eax, eax
1656
        stosd
1657
        stosd
1658
        mov     al, '.'
1659
        push    edi ecx
1660
        lea     ecx, [esi+1]
1661
        test    byte [edi-0x24], 1
1662
        jz      @f
3908 Serge 1663
        rep stosw
257 diamond 1664
        pop     ecx
1665
        xor     eax, eax
1666
        stosw
1667
        pop     edi
1668
        add     edi, 520
1669
        ret
1670
@@:
3908 Serge 1671
        rep stosb
257 diamond 1672
        pop     ecx
1673
        xor     eax, eax
1674
        stosb
1675
        pop     edi
1676
        add     edi, 264
1677
.ret:
1678
        ret
1679
 
256 diamond 1680
.add_entry:
1681
; do not return DOS 8.3 names
1682
        cmp     byte [esi+0x51], 2
1683
        jz      .ret
1684
; do not return system files
1685
; ... note that there will be no bad effects if system files also were reported ...
1686
        cmp     dword [esi], 0x10
1687
        jb      .ret
1688
        mov     eax, [edx]
1689
        inc     dword [eax+8]   ; new file found
1690
        dec     ebx
1691
        jns     .ret
1692
        dec     ecx
1693
        js      .ret
1694
        inc     dword [eax+4]   ; new file block copied
1695
        mov     eax, [edx+4]    ; flags
262 diamond 1696
        call    ntfs_direntry_to_bdfe
256 diamond 1697
        push    ecx esi edi
1698
        movzx   ecx, byte [esi+0x50]
1699
        add     esi, 0x52
1700
        test    byte [edi-0x24], 1
1701
        jz      .ansi
1702
        shr     ecx, 1
3908 Serge 1703
        rep movsd
256 diamond 1704
        adc     ecx, ecx
3908 Serge 1705
        rep movsw
256 diamond 1706
        and     word [edi], 0
1707
        pop     edi
1708
        add     edi, 520
1709
        pop     esi ecx
1710
        ret
1711
.ansi:
1712
        jecxz   .skip
1713
@@:
1714
        lodsw
1715
        call    uni2ansi_char
1716
        stosb
1717
        loop    @b
1718
.skip:
1719
        xor     al, al
1720
        stosb
1721
        pop     edi
1722
        add     edi, 264
1723
        pop     esi ecx
1724
        ret
1725
 
262 diamond 1726
ntfs_direntry_to_bdfe:
1727
        mov     [edi+4], eax    ; ANSI/UNICODE name
1728
        mov     eax, [esi+48h]
1729
        test    eax, 0x10000000
1730
        jz      @f
1731
        and     eax, not 0x10000000
1732
        or      al, 0x10
1733
@@:
1734
        stosd
1735
        scasd
1736
        push    edx
1737
        mov     eax, [esi+0x18]
1738
        mov     edx, [esi+0x1C]
1739
        call    ntfs_datetime_to_bdfe
1740
        mov     eax, [esi+0x30]
1741
        mov     edx, [esi+0x34]
1742
        call    ntfs_datetime_to_bdfe
1743
        mov     eax, [esi+0x20]
1744
        mov     edx, [esi+0x24]
1745
        call    ntfs_datetime_to_bdfe
1746
        pop     edx
1747
        mov     eax, [esi+0x40]
1748
        stosd
1749
        mov     eax, [esi+0x44]
1750
        stosd
1751
        ret
1752
 
256 diamond 1753
iglobal
1754
_24             dd      24
1755
_60             dd      60
1756
_10000000       dd      10000000
1757
days400year     dd      365*400+100-4+1
1758
days100year     dd      365*100+25-1
1759
days4year       dd      365*4+1
1760
days1year       dd      365
1761
months  dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1762
months2 dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1763
_400            dd      400
1764
_100            dd      100
1765
endg
1766
 
1767
ntfs_datetime_to_bdfe:
1768
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
1769
        push    eax
1770
        mov     eax, edx
1771
        xor     edx, edx
1772
        div     [_10000000]
1773
        xchg    eax, [esp]
1774
        div     [_10000000]
2465 Serge 1775
        pop     edx
1400 turbanoff 1776
    .sec:
256 diamond 1777
; edx:eax = number of seconds since January 1, 1601
1778
        push    eax
1779
        mov     eax, edx
1780
        xor     edx, edx
1781
        div     [_60]
1782
        xchg    eax, [esp]
1783
        div     [_60]
1784
        mov     [edi], dl
1785
        pop     edx
1786
; edx:eax = number of minutes
1787
        div     [_60]
1788
        mov     [edi+1], dl
1789
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
1790
        xor     edx, edx
1791
        div     [_24]
1792
        mov     [edi+2], dl
1793
        mov     [edi+3], byte 0
1794
; eax = number of days since January 1, 1601
1795
        xor     edx, edx
1796
        div     [days400year]
1797
        imul    eax, 400
1798
        add     eax, 1601
1799
        mov     [edi+6], ax
1800
        mov     eax, edx
1801
        xor     edx, edx
1802
        div     [days100year]
1803
        cmp     al, 4
1804
        jnz     @f
1805
        dec     eax
1806
        add     edx, [days100year]
1807
@@:
1808
        imul    eax, 100
1809
        add     [edi+6], ax
1810
        mov     eax, edx
1811
        xor     edx, edx
1812
        div     [days4year]
1813
        shl     eax, 2
1814
        add     [edi+6], ax
1815
        mov     eax, edx
1816
        xor     edx, edx
1817
        div     [days1year]
1818
        cmp     al, 4
1819
        jnz     @f
1820
        dec     eax
1821
        add     edx, [days1year]
1822
@@:
1823
        add     [edi+6], ax
1824
        push    esi edx
1825
        mov     esi, months
1826
        movzx   eax, word [edi+6]
1827
        test    al, 3
1828
        jnz     .noleap
1829
        xor     edx, edx
1830
        push    eax
1831
        div     [_400]
1832
        pop     eax
1833
        test    edx, edx
1834
        jz      .leap
1835
        xor     edx, edx
1836
        div     [_100]
1837
        test    edx, edx
1838
        jz      .noleap
1839
.leap:
1840
        mov     esi, months2
1841
.noleap:
1842
        pop     edx
1843
        xor     eax, eax
1844
        inc     eax
1845
@@:
1846
        sub     edx, [esi]
1847
        jb      @f
1848
        add     esi, 4
1849
        inc     eax
1850
        jmp     @b
1851
@@:
1852
        add     edx, [esi]
1853
        pop     esi
1854
        inc     edx
1855
        mov     [edi+4], dl
1856
        mov     [edi+5], al
1857
        add     edi, 8
1858
        ret
1859
 
1860
;----------------------------------------------------------------
3908 Serge 1861
; ntfs_Rewrite - NTFS implementation of creating a new file
1862
; in:  ebp = pointer to NTFS structure
1863
; in:  esi+[esp+4] = name
1864
; in:  ebx = pointer to parameters from sysfunc 70
1865
; out: eax, ebx = return values for sysfunc 70
1866
;----------------------------------------------------------------
1867
ntfs_Rewrite:
1868
ntfs_CreateFolder:
256 diamond 1869
        xor     ebx, ebx
1870
        mov     eax, ERROR_UNSUPPORTED_FS
1871
        ret
1872
 
1873
;----------------------------------------------------------------
3908 Serge 1874
; ntfs_Write - NTFS implementation of writing to file
1875
; in:  ebp = pointer to NTFS structure
1876
; in:  esi+[esp+4] = name
1877
; in:  ebx = pointer to parameters from sysfunc 70
1878
; out: eax, ebx = return values for sysfunc 70
1879
;----------------------------------------------------------------
1880
ntfs_Write:
256 diamond 1881
        xor     ebx, ebx
1882
        mov     eax, ERROR_UNSUPPORTED_FS
1883
        ret
1884
 
3908 Serge 1885
ntfs_SetFileEnd:
1886
ntfs_SetFileInfo:
1887
ntfs_Delete:
256 diamond 1888
        mov     eax, ERROR_UNSUPPORTED_FS
1889
        ret
1890
 
3908 Serge 1891
;----------------------------------------------------------------
1892
; ntfs_GetFileInfo - NTFS implementation of getting file info
1893
; in:  ebp = pointer to NTFS structure
1894
; in:  esi+[esp+4] = name
1895
; in:  ebx = pointer to parameters from sysfunc 70
1896
; out: eax, ebx = return values for sysfunc 70
1897
;----------------------------------------------------------------
1898
ntfs_GetFileInfo:
262 diamond 1899
        cmp     byte [esi], 0
1900
        jnz     @f
3626 Serge 1901
        movi    eax, 2
256 diamond 1902
        ret
262 diamond 1903
@@:
3908 Serge 1904
        call    ntfs_lock
1905
        stdcall ntfs_find_lfn, [esp+4]
262 diamond 1906
        jnc     .doit
3908 Serge 1907
        test    eax, eax
3626 Serge 1908
        movi    eax, ERROR_FILE_NOT_FOUND
262 diamond 1909
        jz      @f
1910
        mov     al, 11
1911
@@:
3908 Serge 1912
        push    eax
1913
        call    ntfs_unlock
1914
        pop     eax
262 diamond 1915
        ret
1916
.doit:
1917
        push    esi edi
1918
        mov     esi, eax
3908 Serge 1919
        mov     edi, [ebx+16]
262 diamond 1920
        xor     eax, eax
1921
        call    ntfs_direntry_to_bdfe
1922
        pop     edi esi
3908 Serge 1923
        call    ntfs_unlock
262 diamond 1924
        xor     eax, eax
2465 Serge 1925
        ret
1926