Subversion Repositories Kolibri OS

Rev

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

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