Subversion Repositories Kolibri OS

Rev

Rev 257 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
256 diamond 1
ntfs_test_bootsec:
2
; in: ebx->buffer, edx=size of partition
3
; out: CF set <=> invalid
4
; 1. Name=='NTFS    '
5
        cmp     dword [ebx+3], 'NTFS'
6
        jnz     .no
7
        cmp     dword [ebx+7], '    '
8
        jnz     .no
9
; 2. Number of bytes per sector is the same as for physical device
10
; (that is, 0x200 for hard disk)
11
        cmp     word [ebx+11], 0x200
12
        jnz     .no
13
; 3. Number of sectors per cluster must be power of 2
14
        movzx   eax, byte [ebx+13]
15
        dec     eax
16
        js      .no
17
        test    al, [ebx+13]
18
        jnz     .no
19
; 4. FAT parameters must be zero
20
        cmp     word [ebx+14], 0
21
        jnz     .no
22
        cmp     dword [ebx+16], 0
23
        jnz     .no
24
        cmp     byte [ebx+20], 0
25
        jnz     .no
26
        cmp     word [ebx+22], 0
27
        jnz     .no
28
        cmp     dword [ebx+32], 0
29
        jnz     .no
30
; 5. Number of sectors <= partition size
31
        cmp     dword [ebx+0x2C], 0
32
        ja      .no
33
        cmp     [ebx+0x28], edx
34
        ja      .no
35
; 6. $MFT and $MFTMirr clusters must be within partition
36
        cmp     dword [ebx+0x34], 0
37
        ja      .no
38
        push    edx
39
        movzx   eax, byte [ebx+13]
40
        mul     dword [ebx+0x30]
41
        test    edx, edx
42
        pop     edx
43
        jnz     .no
44
        cmp     eax, edx
45
        ja      .no
46
        cmp     dword [ebx+0x3C], 0
47
        ja      .no
48
        push    edx
49
        movzx   eax, byte [ebx+13]
50
        mul     dword [ebx+0x38]
51
        test    edx, edx
52
        pop     edx
53
        jnz     .no
54
        cmp     eax, edx
55
        ja      .no
56
; 7. Clusters per FRS must be either negative and in [-31,-9] or positive and power of 2
57
        movsx   eax, byte [ebx+0x40]
58
        cmp     al, -31
59
        jl      .no
60
        cmp     al, -9
61
        jle     @f
62
        dec     eax
63
        js      .no
64
        test    [ebx+0x40], al
65
        jnz     .no
66
@@:
67
; 8. Same for clusters per IndexAllocationBuffer
68
        movsx   eax, byte [ebx+0x44]
69
        cmp     al, -31
70
        jl      .no
71
        cmp     al, -9
72
        jle     @f
73
        dec     eax
74
        js      .no
75
        test    [ebx+0x44], al
76
        jnz     .no
77
@@:
78
; OK, this is correct NTFS bootsector
79
        clc
80
        ret
81
.no:
82
; No, this bootsector isn't NTFS
83
        stc
84
        ret
85
 
86
ntfs_setup:             ; CODE XREF: part_set.inc
87
; By given bootsector, initialize some NTFS variables
88
        call    ntfs_test_bootsec
89
        jc      problem_fat_dec_count
90
        movzx   eax, byte [ebx+13]
91
        mov     [ntfs_data.sectors_per_cluster], eax
92
        mov     eax, [ebx+0x28]
93
        add     eax, [PARTITION_START]
94
        dec     eax
95
        mov     [PARTITION_END], eax
96
        mov     [fs_type], 1
97
        mov     eax, [ebx+0x30]
98
        mov     [ntfs_data.mft_cluster], eax
99
        mov     eax, [ebx+0x38]
100
        mov     [ntfs_data.mftmirr_cluster], eax
101
        movsx   eax, byte [ebx+0x40]
102
        test    eax, eax
103
        js      .1
104
        mul     [ntfs_data.sectors_per_cluster]
105
        shl     eax, 9
106
        jmp     .2
107
.1:
108
        neg     eax
109
        mov     ecx, eax
110
        mov     eax, 1
111
        shl     eax, cl
112
.2:
113
        mov     [ntfs_data.frs_size], eax
114
        movsx   eax, byte [ebx+0x44]
115
        test    eax, eax
116
        js      .3
117
        mul     [ntfs_data.sectors_per_cluster]
118
        shl     eax, 9
119
        jmp     .4
120
.3:
121
        neg     eax
122
        mov     ecx, eax
123
        mov     eax, 1
124
        shl     eax, cl
125
.4:
126
        mov     [ntfs_data.iab_size], eax
127
; allocate space for buffers
128
        add     eax, [ntfs_data.frs_size]
129
        push    eax
130
        call    kernel_alloc
131
        test    eax, eax
132
        jz      problem_fat_dec_count
133
        mov     [ntfs_data.frs_buffer], eax
134
        add     eax, [ntfs_data.frs_size]
135
        mov     [ntfs_data.iab_buffer], eax
136
; read $MFT disposition
137
        mov     eax, [ntfs_data.mft_cluster]
138
        mul     [ntfs_data.sectors_per_cluster]
139
        call    ntfs_read_frs_sector
140
        cmp     [hd_error], 0
141
        jnz     .usemirr
142
        cmp     dword [ebx], 'FILE'
143
        jnz     .usemirr
144
        call    ntfs_restore_usa_frs
145
        jnc     .mftok
146
.usemirr:
147
        and     [hd_error], 0
148
        mov     eax, [ntfs_data.mftmirr_cluster]
149
        mul     [ntfs_data.sectors_per_cluster]
150
        call    ntfs_read_frs_sector
151
        cmp     [hd_error], 0
152
        jnz     @f
153
        cmp     dword [ebx], 'FILE'
154
        jnz     @f
155
        call    ntfs_restore_usa_frs
156
        jnc     .mftok
157
@@:
158
; $MFT and $MFTMirr invalid!
159
.fail_free_frs:
160
        push    [ntfs_data.frs_buffer]
161
        call    kernel_free
162
        jmp     problem_fat_dec_count
163
.fail_free_mft:
164
        push    [ntfs_data.mft_retrieval]
165
        call    kernel_free
166
        jmp     .fail_free_frs
167
.mftok:
168
; read $MFT table retrieval information
169
; start with one page, increase if not enough (when MFT too fragmented)
170
        push    ebx
171
        push    0x1000
172
        call    kernel_alloc
173
        pop     ebx
174
        test    eax, eax
175
        jz      .fail_free_frs
176
        mov     [ntfs_data.mft_retrieval], eax
177
        and     [ntfs_data.mft_retrieval_size], 0
178
        mov     [ntfs_data.mft_retrieval_alloc], 0x1000/8
179
; $MFT base record must contain unnamed non-resident $DATA attribute
180
        movzx   eax, word [ebx+14h]
181
        add     eax, ebx
182
.scandata:
183
        cmp     dword [eax], -1
184
        jz      .fail_free_mft
185
        cmp     dword [eax], 0x80
186
        jnz     @f
187
        cmp     byte [eax+9], 0
188
        jz      .founddata
189
@@:
190
        add     eax, [eax+4]
191
        jmp     .scandata
192
.founddata:
193
        cmp     byte [eax+8], 0
194
        jz      .fail_free_mft
195
; load first portion of $DATA attribute retrieval information
196
        mov     edx, [eax+0x18]
197
        mov     [ntfs_data.mft_retrieval_end], edx
198
        mov     esi, eax
199
        movzx   eax, word [eax+0x20]
200
        add     esi, eax
201
        sub     esp, 10h
202
.scanmcb:
203
        call    ntfs_decode_mcb_entry
204
        jnc     .scanmcbend
205
        call    .get_mft_retrieval_ptr
206
        mov     edx, [esp]      ; block length
207
        mov     [eax], edx
208
        mov     edx, [esp+8]    ; block addr (relative)
209
        mov     [eax+4], edx
210
        inc     [ntfs_data.mft_retrieval_size]
211
        jmp     .scanmcb
212
.scanmcbend:
213
        add     esp, 10h
214
; there may be other portions of $DATA attribute in auxiliary records;
215
; if they will be needed, they will be loaded later
216
 
217
        mov     [ntfs_data.cur_index_size], 0x1000/0x200
218
        push    0x1000
219
        call    kernel_alloc
220
        test    eax, eax
221
        jz      .fail_free_mft
222
        mov     [ntfs_data.cur_index_buf], eax
223
 
224
        popad
225
        and     [hd1_status], 0
226
        ret
227
 
228
.get_mft_retrieval_ptr:
229
        pushad
230
        mov     eax, [ntfs_data.mft_retrieval_size]
231
        cmp     eax, [ntfs_data.mft_retrieval_alloc]
232
        jnz     .ok
233
        add     eax, 0x1000/8
234
        mov     [ntfs_data.mft_retrieval_alloc], eax
235
        shl     eax, 3
236
        push    eax
237
        call    kernel_alloc
238
        test    eax, eax
239
        jnz     @f
240
        popad
241
        add     esp, 14h
242
        jmp     .fail_free_mft
243
@@:
244
        mov     esi, [ntfs_data.mft_retrieval]
245
        mov     edi, eax
246
        mov     ecx, [ntfs_data.mft_retrieval_size]
247
        add     ecx, ecx
248
        rep     movsd
249
        push    [ntfs_data.mft_retrieval]
250
        mov     [ntfs_data.mft_retrieval], eax
251
        call    kernel_free
252
        mov     eax, [ntfs_data.mft_retrieval_size]
253
.ok:
254
        shl     eax, 3
255
        add     eax, [ntfs_data.mft_retrieval]
256
        mov     [esp+28], eax
257
        popad
258
        ret
259
 
260
ntfs_read_frs_sector:
261
        push    eax ecx
262
        add     eax, [PARTITION_START]
263
        mov     ecx, [ntfs_data.frs_size]
264
        shr     ecx, 9
265
        mov     ebx, [ntfs_data.frs_buffer]
266
        push    ebx
267
@@:
268
        call    hd_read
269
        cmp     [hd_error], 0
270
        jnz     .fail
271
        add     ebx, 0x200
272
        inc     eax
273
        loop    @b
274
.fail:
275
        pop     ebx
276
        pop     ecx eax
277
        ret
278
 
279
uglobal
280
align 4
281
ntfs_cur_attr   dd      ?
282
ntfs_cur_iRecord dd     ?
283
ntfs_cur_offs   dd      ?       ; in sectors
284
ntfs_cur_size   dd      ?       ; in sectors
285
ntfs_cur_buf    dd      ?
286
ntfs_cur_read   dd      ?       ; [output]
287
 
288
ntfs_attrlist_buf       rb      0x400
289
ntfs_bitmap_buf         rb      0x400
290
 
291
ntfs_attr_iRecord       dd      ?
292
ntfs_attr_iBaseRecord   dd      ?
293
ntfs_attr_offs          dd      ?
294
ntfs_attr_list          dd      ?
295
endg
296
 
297
ntfs_read_attr:
298
; in: global variables
299
; out: [ntfs_cur_read]
300
        pushad
301
        and     [ntfs_cur_read], 0
302
        cmp     [ntfs_cur_iRecord], 0
303
        jnz     .nomft
304
        cmp     [ntfs_cur_attr], 0x80
305
        jnz     .nomft
306
        mov     eax, [ntfs_data.mft_retrieval_end]
307
        inc     eax
308
        mul     [ntfs_data.sectors_per_cluster]
309
        cmp     eax, [ntfs_cur_offs]
310
        jbe     .nomft
311
; precalculated part of $Mft $DATA
312
        mov     esi, [ntfs_data.mft_retrieval]
313
        mov     eax, [ntfs_cur_offs]
314
        xor     edx, edx
315
        div     [ntfs_data.sectors_per_cluster]
316
; eax = VCN, edx = offset in sectors from beginning of cluster
317
        xor     ecx, ecx        ; ecx will contain LCN
318
.mftscan:
319
        add     ecx, [esi+4]
320
        sub     eax, [esi]
321
        jb      @f
322
        add     esi, 8
323
        push    eax
324
        mov     eax, [ntfs_data.mft_retrieval_end]
325
        shl     eax, 3
326
        add     eax, [ntfs_data.mft_retrieval]
327
        cmp     eax, esi
328
        pop     eax
329
        jnz     .mftscan
330
        jmp     .nomft
331
@@:
332
        push    ecx
333
        add     ecx, eax
334
        add     ecx, [esi]
335
        push    eax
336
        push    edx
337
        mov     eax, [ntfs_data.sectors_per_cluster]
338
        mul     ecx
339
; eax = sector on partition
340
        add     eax, [PARTITION_START]
341
        pop     edx
342
        add     eax, edx
343
        mov     ebx, [ntfs_cur_buf]
344
        pop     ecx
345
        neg     ecx
346
        imul    ecx, [ntfs_data.sectors_per_cluster]
347
        sub     ecx, edx
348
        cmp     ecx, [ntfs_cur_size]
349
        jb      @f
350
        mov     ecx, [ntfs_cur_size]
351
@@:
352
; ecx = number of sequential sectors to read
353
        call    hd_read
354
        cmp     [hd_error], 0
355
        jnz     .errread
356
        add     [ntfs_cur_read], 0x200
357
        dec     [ntfs_cur_size]
358
        inc     [ntfs_cur_offs]
359
        add     ebx, 0x200
360
        mov     [ntfs_cur_buf], ebx
361
        inc     eax
362
        loop    @b
363
        pop     ecx
364
        xor     eax, eax
365
        xor     edx, edx
366
        cmp     [ntfs_cur_size], eax
367
        jz      @f
368
        add     esi, 8
369
        push    eax
370
        mov     eax, [ntfs_data.mft_retrieval_end]
371
        shl     eax, 3
372
        add     eax, [ntfs_data.mft_retrieval]
373
        cmp     eax, esi
374
        pop     eax
375
        jz      .nomft
376
        jmp     .mftscan
377
@@:
378
        popad
379
        ret
380
.errread:
381
        pop     ecx
382
.errret:
383
        stc
384
        popad
385
        ret
386
.nomft:
387
; 1. Read file record.
388
; N.B. This will do recursive call of read_attr for $MFT::$Data.
389
        mov     eax, [ntfs_cur_iRecord]
390
        mov     [ntfs_attr_iRecord], eax
391
        and     [ntfs_attr_list], 0
392
        or      [ntfs_attr_iBaseRecord], -1
393
        call    ntfs_read_file_record
394
        test    eax, eax
395
        jz      .errret
396
; 2. Find required attribute.
397
        mov     eax, [ntfs_data.frs_buffer]
398
; a) For auxiliary records, read base record
399
; N.B. If base record is present,
400
;      base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero
401
        cmp     dword [eax+24h], 0
402
        jz      @f
403
        mov     eax, [eax+20h]
404
;        test    eax, eax
405
;        jz      @f
406
.beginfindattr:
407
        mov     [ntfs_attr_iRecord], eax
408
        call    ntfs_read_file_record
409
        test    eax, eax
410
        jz      .errret
411
@@:
412
; b) Scan for required attribute and for $ATTR_LIST
413
        mov     eax, [ntfs_data.frs_buffer]
414
        movzx   ecx, word [eax+14h]
415
        add     eax, ecx
416
        mov     ecx, [ntfs_cur_attr]
417
        and     [ntfs_attr_offs], 0
418
.scanattr:
419
        cmp     dword [eax], -1
420
        jz      .scandone
421
        cmp     dword [eax], ecx
422
        jz      .okattr
423
        cmp     [ntfs_attr_iBaseRecord], -1
424
        jnz     .scancont
425
        cmp     dword [eax], 0x20       ; $ATTR_LIST
426
        jnz     .scancont
427
        mov     [ntfs_attr_list], eax
428
        jmp     .scancont
429
.okattr:
430
        mov     [ntfs_attr_offs], eax
431
.scancont:
432
        add     eax, [eax+4]
433
        jmp     .scanattr
434
.scandone:
435
; c) Check for required offset and length
436
        mov     ecx, [ntfs_attr_offs]
437
        jecxz   .noattr
438
        call    .doreadattr
439
        jc      @f
440
        cmp     [ntfs_cur_size], 0
441
        jnz     .not_in_cur
442
@@:
443
        popad
444
        ret
445
.noattr:
446
.not_in_cur:
447
        cmp     [ntfs_cur_attr], 0x20
448
        jz      @f
449
        mov     ecx, [ntfs_attr_list]
450
        test    ecx, ecx
451
        jnz     .lookattr
452
.ret_is_attr:
453
        cmp     [ntfs_attr_offs], 1     ; CF set <=> ntfs_attr_offs == 0
454
        popad
455
        ret
456
.lookattr:
457
; required attribute or required offset was not found in base record;
458
; it may be present in auxiliary records;
459
; scan $ATTR_LIST
460
        mov     eax, [ntfs_attr_iBaseRecord]
461
        cmp     eax, -1
462
        jz      @f
463
        call    ntfs_read_file_record
464
        test    eax, eax
465
        jz      .errret
466
        or      [ntfs_attr_iBaseRecord], -1
467
@@:
468
        push    [ntfs_cur_offs]
469
        push    [ntfs_cur_size]
470
        push    [ntfs_cur_read]
471
        push    [ntfs_cur_buf]
472
        xor     edx, edx
473
        mov     [ntfs_cur_offs], edx
474
        mov     [ntfs_cur_size], 2
475
        and     [ntfs_cur_read], 0
476
        mov     [ntfs_cur_buf], ntfs_attrlist_buf
477
        push    edx
478
        call    .doreadattr
479
        pop     edx
480
        mov     ebp, [ntfs_cur_read]
481
        pop     [ntfs_cur_buf]
482
        pop     [ntfs_cur_read]
483
        pop     [ntfs_cur_size]
484
        pop     [ntfs_cur_offs]
485
        jc      .errret
486
        mov     esi, ntfs_attrlist_buf
487
        or      edi, -1
488
.scanliststart:
489
        lea     ebp, [ebp+esi-1Ah]
490
        mov     eax, [ntfs_cur_attr]
491
.scanlist:
492
        cmp     esi, ebp
493
        jae     .scanlistdone
494
        cmp     eax, [esi]
495
        jz      @f
496
.scanlistcont:
497
        movzx   ecx, word [esi+4]
498
        add     esi, ecx
499
        jmp     .scanlist
500
@@:
501
        push    eax
502
        mov     eax, [esi+8]
503
        imul    eax, [ntfs_data.sectors_per_cluster]
504
        cmp     eax, [ntfs_cur_offs]
505
        pop     eax
506
        ja      @f
507
        mov     edi, [esi+10h]  ; keep previous iRecord
508
        jmp     .scanlistcont
509
@@:
510
        cmp     edi, -1
511
        jnz     @f
512
        popad
513
        ret
514
@@:
515
        mov     eax, [ntfs_cur_iRecord]
516
        mov     [ntfs_attr_iBaseRecord], eax
517
        mov     eax, edi
518
        jmp     .beginfindattr
519
.scanlistdone:
520
        sub     ebp, ntfs_attrlist_buf-1Ah
521
        test    ebp, 1FFh
522
        jnz     .ret_is_attr
523
        test    edx, edx
524
        jnz     @f
525
        inc     edx
526
        cmp     ebp, 0x400
527
        jnz     .ret_is_attr
528
@@:
529
        inc     edx
530
        push    esi edi
531
        mov     esi, ntfs_attrlist_buf+0x200
532
        mov     edi, ntfs_attrlist_buf
533
        mov     ecx, 0x200/4
534
        rep     movsd
535
        pop     edi esi
536
        sub     esi, 0x200
537
        push    [ntfs_cur_offs]
538
        push    [ntfs_cur_size]
539
        push    [ntfs_cur_read]
540
        push    [ntfs_cur_buf]
541
        mov     [ntfs_cur_offs], edx
542
        mov     [ntfs_cur_size], 1
543
        and     [ntfs_cur_read], 0
544
        mov     [ntfs_cur_buf], ntfs_attrlist_buf+0x200
545
        push    esi edx
546
        call    .doreadattr
547
        pop     edx esi
548
        mov     ebp, [ntfs_cur_read]
549
        pop     [ntfs_cur_buf]
550
        pop     [ntfs_cur_read]
551
        pop     [ntfs_cur_size]
552
        pop     [ntfs_cur_offs]
553
        jc      .errret
554
        jmp     .scanliststart
555
 
556
.doreadattr:
557
        cmp     byte [ecx+8], 0
558
        jnz     .nonresident
559
        mov     eax, [ecx+10h]  ; length
560
        mov     esi, eax
561
        mov     edx, [ntfs_cur_offs]
562
        shr     eax, 9
563
        cmp     eax, edx
564
        jb      .okret
565
        shl     edx, 9
566
        sub     esi, edx
567
        movzx   eax, word [ecx+14h]
568
        add     edx, eax
569
        add     edx, ecx        ; edx -> data
570
        mov     eax, [ntfs_cur_size]
571
        cmp     eax, (0xFFFFFFFF shr 9)+1
572
        jbe     @f
573
        mov     eax, (0xFFFFFFFF shr 9)+1
574
@@:
575
        shl     eax, 9
576
        cmp     eax, esi
577
        jbe     @f
578
        mov     eax, esi
579
@@:
580
; eax = length, edx -> data
581
        mov     [ntfs_cur_read], eax
582
        mov     ecx, eax
583
        mov     eax, edx
584
        mov     ebx, [ntfs_cur_buf]
585
        call    memmove
586
        clc
587
        ret
588
.nonresident:
589
        mov     eax, [ecx+30h]  ; FileSize
590
        mov     edx, [ecx+34h]
591
        add     eax, 0x1FF
592
        adc     edx, 0
593
        shrd    eax, edx, 9
594
        sub     eax, [ntfs_cur_offs]
595
        ja      @f
596
; return with nothing read
597
.okret:
598
        clc
599
        ret
600
@@:
601
; reduce read length
602
        cmp     [ntfs_cur_size], eax
603
        jb      @f
604
        mov     [ntfs_cur_size], eax
605
@@:
606
        cmp     [ntfs_cur_size], 0
607
        jz      .okret
608
        mov     eax, [ntfs_cur_offs]
609
        xor     edx, edx
610
        div     [ntfs_data.sectors_per_cluster]
611
        sub     eax, [ecx+10h]  ; first_vbo
612
        jb      .okret
613
; eax = cluster, edx = starting sector
614
        sub     esp, 10h
615
        movzx   esi, word [ecx+20h]     ; mcb_info_ofs
616
        add     esi, ecx
617
        xor     ebp, ebp
618
.readloop:
619
        call    ntfs_decode_mcb_entry
620
        jnc     .break
621
        add     ebp, [esp+8]
622
        sub     eax, [esp]
623
        jae     .readloop
624
        push    ecx
625
        push    eax
626
        add     eax, [esp+8]
627
        add     eax, ebp
628
        imul    eax, [ntfs_data.sectors_per_cluster]
629
        add     eax, edx
630
        add     eax, [PARTITION_START]
631
        pop     ecx
632
        neg     ecx
633
        imul    ecx, [ntfs_data.sectors_per_cluster]
634
        sub     ecx, edx
635
        cmp     ecx, [ntfs_cur_size]
636
        jb      @f
637
        mov     ecx, [ntfs_cur_size]
638
@@:
639
        mov     ebx, [ntfs_cur_buf]
640
@@:
641
        call    hd_read
642
        cmp     [hd_error], 0
643
        jnz     .errread2
644
        add     ebx, 0x200
645
        mov     [ntfs_cur_buf], ebx
646
        inc     eax
647
        add     [ntfs_cur_read], 0x200
648
        dec     [ntfs_cur_size]
649
        inc     [ntfs_cur_offs]
650
        loop    @b
651
        pop     ecx
652
        cmp     [ntfs_cur_size], 0
653
        jnz     .readloop
654
        add     esp, 10h
655
        jmp     .okret
656
.errread2:
657
        pop     ecx
658
        add     esp, 10h
659
        jmp     .errret
660
.break:
661
        add     esp, 10h        ; CF=0
662
        ret
663
 
664
ntfs_read_file_record:
665
; in: eax=iRecord
666
; out: [ntfs_data.frs_buffer] contains information
667
;      eax=0 - failed, eax=1 - success
668
; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size]
669
        push    ecx edx
670
        mov     ecx, [ntfs_data.frs_size]
671
        mul     ecx
672
        shrd    eax, edx, 9
673
        shr     edx, 9
674
        jnz     .err
675
        push    [ntfs_cur_iRecord]
676
        push    [ntfs_cur_attr]
677
        push    [ntfs_cur_offs]
678
        push    [ntfs_cur_size]
679
        push    [ntfs_cur_buf]
680
        push    [ntfs_cur_read]
681
        mov     [ntfs_cur_attr], 0x80   ; $DATA
682
        and     [ntfs_cur_iRecord], 0   ; $Mft
683
        mov     [ntfs_cur_offs], eax
684
        shr     ecx, 9
685
        mov     [ntfs_cur_size], ecx
686
        mov     eax, [ntfs_data.frs_buffer]
687
        mov     [ntfs_cur_buf], eax
688
        call    ntfs_read_attr
689
        mov     eax, [ntfs_cur_read]
690
        pop     [ntfs_cur_read]
691
        pop     [ntfs_cur_buf]
692
        pop     [ntfs_cur_size]
693
        pop     [ntfs_cur_offs]
694
        pop     [ntfs_cur_attr]
695
        pop     [ntfs_cur_iRecord]
696
        pop     edx ecx
697
        jc      .errret
698
        cmp     eax, [ntfs_data.frs_size]
699
        jnz     .errret
700
        mov     eax, [ntfs_data.frs_buffer]
701
        cmp     dword [eax], 'FILE'
702
        jnz     .errret
703
        push    ebx
704
        mov     ebx, eax
705
        call    ntfs_restore_usa_frs
706
        pop     ebx
707
        setnc   al
708
        movzx   eax, al
709
.ret:
710
        ret
711
.err:
712
        pop     edx ecx
713
.errret:
714
        xor     eax, eax
715
        ret
716
 
717
ntfs_restore_usa_frs:
718
        mov     eax, [ntfs_data.frs_size]
719
ntfs_restore_usa:
720
        pushad
721
        shr     eax, 9
722
        mov     ecx, eax
723
        inc     eax
724
        cmp     [ebx+6], ax
725
        jnz     .err
726
        movzx   eax, word [ebx+4]
727
        lea     esi, [eax+ebx]
728
        lodsw
729
        mov     edx, eax
730
        lea     edi, [ebx+0x1FE]
731
@@:
732
        cmp     [edi], dx
733
        jnz     .err
734
        lodsw
735
        stosw
736
        add     edi, 0x1FE
737
        loop    @b
738
        popad
739
        clc
740
        ret
741
.err:
742
        popad
743
        stc
744
        ret
745
 
746
ntfs_decode_mcb_entry:
747
        push    eax ecx edi
748
        lea     edi, [esp+16]
749
        xor     eax, eax
750
        lodsb
751
        test    al, al
752
        jz      .end
753
        mov     ecx, eax
754
        and     ecx, 0xF
755
        cmp     ecx, 8
756
        ja      .end
757
        push    ecx
758
        rep     movsb
759
        pop     ecx
760
        sub     ecx, 8
761
        neg     ecx
762
        cmp     byte [esi-1], 80h
763
        jae     .end
764
        push    eax
765
        xor     eax, eax
766
        rep     stosb
767
        pop     ecx
768
        shr     ecx, 4
769
        cmp     ecx, 8
770
        ja      .end
771
        push    ecx
772
        rep     movsb
773
        pop     ecx
774
        sub     ecx, 8
775
        neg     ecx
776
        cmp     byte [esi-1], 80h
777
        sbb     eax, eax
778
        inc     eax
779
        rep     stosb
780
        stc
781
.end:
782
        pop     edi ecx eax
783
        ret
784
 
785
;----------------------------------------------------------------
786
;
787
;  ntfs_HdRead - read NTFS hard disk
788
;
789
;  esi  points to filename
790
;  ebx  pointer to 64-bit number = first wanted byte, 0+
791
;       may be ebx=0 - start from first byte
792
;  ecx  number of bytes to read, 0+
793
;  edx  mem location to return data
794
;
795
;  ret ebx = bytes read or 0xffffffff file not found
796
;      eax = 0 ok read or other = errormsg
797
;
798
;--------------------------------------------------------------
799
ntfs_HdRead:
800
        or      ebx, -1
801
        mov     eax, ERROR_UNSUPPORTED_FS
802
        ret
803
 
804
;----------------------------------------------------------------
805
;
806
;  ntfs_HdReadFolder - read NTFS hard disk folder
807
;
808
;  esi  points to filename
809
;  ebx  pointer to structure 32-bit number = first wanted block, 0+
810
;                          & flags (bitfields)
811
; flags: bit 0: 0=ANSI names, 1=UNICODE names
812
;  ecx  number of blocks to read, 0+
813
;  edx  mem location to return data
814
;
815
;  ret ebx = blocks read or 0xffffffff folder not found
816
;      eax = 0 ok read or other = errormsg
817
;
818
;--------------------------------------------------------------
819
ntfs_HdReadFolder:
820
        mov     eax, 5          ; root cluster
821
        cmp     byte [esi], 0
822
        jz      .doit
823
;        call    ntfs_find_lfn
824
;        jnc     .doit
825
.notfound:
826
        or      ebx, -1
827
        push    ERROR_FILE_NOT_FOUND
828
.pop_ret:
829
        pop     eax
830
        ret
831
.doit:
832
        mov     [ntfs_cur_iRecord], eax
833
.doit2:
834
        mov     [ntfs_cur_attr], 0x90   ; $INDEX_ROOT
835
        and     [ntfs_cur_offs], 0
836
        mov     eax, [ntfs_data.cur_index_size]
837
        mov     [ntfs_cur_size], eax
838
        mov     eax, [ntfs_data.cur_index_buf]
839
        mov     [ntfs_cur_buf], eax
840
        call    ntfs_read_attr
841
        jnc     .ok
842
        cmp     [hd_error], 0
843
        jz      .notfound
844
        or      ebx, -1
845
        push    11
846
        jmp     .pop_ret
847
.ok:
848
        cmp     [ntfs_cur_read], 0x20
849
        jae     @f
850
        or      ebx, -1
851
.fserr:
852
        push    ERROR_FAT_TABLE
853
        jmp     .pop_ret
854
@@:
855
        pushad
856
        mov     esi, [ntfs_data.cur_index_buf]
857
        mov     eax, [esi+14h]
858
        add     eax, 10h
859
        cmp     [ntfs_cur_read], eax
860
        jae     .readok1
861
        add     eax, 1FFh
862
        shr     eax, 9
863
        cmp     eax, [ntfs_data.cur_index_size]
864
        ja      @f
865
        popad
866
        jmp     .fserr
867
@@:
868
; reallocate
869
        push    eax
870
        push    [ntfs_data.cur_index_buf]
871
        call    kernel_free
872
        pop     eax
873
        mov     [ntfs_data.cur_index_size], eax
874
        push    eax
875
        call    kernel_alloc
876
        test    eax, eax
877
        jnz     @f
878
        and     [ntfs_data.cur_index_size], 0
879
        and     [ntfs_data.cur_index_buf], 0
880
.nomem:
881
        popad
882
        or      ebx, -1
883
        push    12
884
        pop     eax
885
        ret
886
@@:
887
        mov     [ntfs_data.cur_index_buf], eax
888
        popad
889
        jmp     .doit2
890
.readok1:
891
        mov     ebp, [esi+8]    ; subnode_size
892
        shr     ebp, 9
893
        cmp     ebp, [ntfs_data.cur_index_size]
894
        jbe     .ok2
895
        push    esi ebp
896
        push    ebp
897
        call    kernel_alloc
898
        pop     ebp esi
899
        test    eax, eax
900
        jz      .nomem
901
        mov     edi, eax
902
        mov     ecx, [ntfs_data.cur_index_size]
903
        shl     ecx, 9-2
904
        rep     movsd
905
        mov     esi, eax
906
        mov     [ntfs_data.cur_index_size], ebp
907
        push    esi ebp
908
        push    [ntfs_data.cur_index_buf]
909
        call    kernel_free
910
        pop     ebp esi
911
        mov     [ntfs_data.cur_index_buf], esi
912
.ok2:
913
        add     esi, 10h
914
        mov     ebx, [esp+10h]
915
        mov     edx, [esp+14h]
916
        push    dword [ebx+4]   ; read ANSI/UNICODE name
917
        mov     ebx, [ebx]
918
; init header
919
        mov     edi, edx
920
        mov     ecx, 32/4
921
        xor     eax, eax
922
        rep     stosd
923
        mov     byte [edx], 1   ; version
924
        mov     ecx, [esp+4+18h]
925
        push    edx
926
        mov     edx, esp
927
; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block,
928
; ecx = number of blocks to read
929
; edx -> parameters block: dd , dd 
930
; at first, dump index root
931
        add     esi, [esi]
932
.dump_root:
933
        test    byte [esi+0Ch], 2
934
        jnz     .dump_root_done
935
        call    .add_entry
936
        movzx   eax, word [esi+8]
937
        add     esi, eax
938
        jmp     .dump_root
939
.dump_root_done:
940
; now dump all subnodes
941
        push    ecx edi
942
        mov     edi, ntfs_bitmap_buf
943
        mov     [ntfs_cur_buf], edi
944
        mov     ecx, 0x400/4
945
        xor     eax, eax
946
        rep     stosd
947
        mov     [ntfs_cur_attr], 0xB0   ; $BITMAP
948
        and     [ntfs_cur_offs], 0
949
        mov     [ntfs_cur_size], 2
950
        call    ntfs_read_attr
951
        pop     edi ecx
952
        push    0       ; save offset in $BITMAP attribute
953
        and     [ntfs_cur_offs], 0
954
.dumploop:
955
        mov     [ntfs_cur_attr], 0xA0
956
        mov     [ntfs_cur_size], ebp
957
        mov     eax, [ntfs_data.cur_index_buf]
958
        mov     esi, eax
959
        mov     [ntfs_cur_buf], eax
960
        push    [ntfs_cur_offs]
961
        call    ntfs_read_attr
962
        pop     [ntfs_cur_offs]
963
        mov     eax, ebp
964
        shl     eax, 9
965
        cmp     [ntfs_cur_read], eax
966
        jnz     .done
967
        push    eax
968
        mov     eax, [ntfs_cur_offs]
969
        and     eax, 0x400*8-1
970
        bt      dword [ntfs_bitmap_buf], eax
971
        pop     eax
972
        jnc     .dump_subnode_done
973
        cmp     dword [esi], 'INDX'
974
        jnz     .dump_subnode_done
975
        push    ebx
976
        mov     ebx, esi
977
        call    ntfs_restore_usa
978
        pop     ebx
979
        jc      .dump_subnode_done
980
        add     esi, 0x18
981
        add     esi, [esi]
982
.dump_subnode:
983
        test    byte [esi+0Ch], 2
984
        jnz     .dump_subnode_done
985
        call    .add_entry
986
        movzx   eax, word [esi+8]
987
        add     esi, eax
988
        jmp     .dump_subnode
989
.dump_subnode_done:
990
        inc     [ntfs_cur_offs]
991
        test    [ntfs_cur_offs], 0x400*8-1
992
        jnz     .dumploop
993
        mov     [ntfs_cur_attr], 0xB0
994
        push    ecx edi
995
        mov     edi, ntfs_bitmap_buf
996
        mov     [ntfs_cur_buf], edi
997
        mov     ecx, 0x400/4
998
        xor     eax, eax
999
        rep     stosd
1000
        pop     edi ecx
1001
        pop     eax
1002
        push    [ntfs_cur_offs]
1003
        inc     eax
1004
        mov     [ntfs_cur_offs], eax
1005
        mov     [ntfs_cur_size], 2
1006
        push    eax
1007
        call    ntfs_read_attr
1008
        pop     eax
1009
        pop     [ntfs_cur_offs]
1010
        push    eax
1011
        jmp     .dumploop
1012
.done:
1013
        pop     eax
1014
        pop     edx
1015
        mov     ebx, [edx+4]
1016
        pop     edx
1017
        xor     eax, eax
1018
        dec     ecx
1019
        js      @f
1020
        mov     al, ERROR_END_OF_FILE
1021
@@:
1022
        mov     [esp+1Ch], eax
1023
        mov     [esp+10h], ebx
1024
        popad
1025
        ret
1026
 
1027
.add_entry:
1028
; do not return DOS 8.3 names
1029
        cmp     byte [esi+0x51], 2
1030
        jz      .ret
1031
; do not return system files
1032
; ... note that there will be no bad effects if system files also were reported ...
1033
        cmp     dword [esi], 0x10
1034
        jb      .ret
1035
        mov     eax, [edx]
1036
        inc     dword [eax+8]   ; new file found
1037
        dec     ebx
1038
        jns     .ret
1039
        dec     ecx
1040
        js      .ret
1041
        inc     dword [eax+4]   ; new file block copied
1042
        mov     eax, [edx+4]    ; flags
1043
        call    ntfs_direntry_to_bdfe
1044
.ret:
1045
        ret
1046
 
1047
ntfs_direntry_to_bdfe:
1048
        mov     [edi+4], eax    ; ANSI/UNICODE name
1049
        mov     eax, [esi+48h]
1050
        test    eax, 0x10000000
1051
        jz      @f
1052
        and     eax, not 0x10000000
1053
        or      al, 0x10
1054
@@:
1055
        stosd
1056
        scasd
1057
        push    edx
1058
        mov     eax, [esi+0x18]
1059
        mov     edx, [esi+0x1C]
1060
        call    ntfs_datetime_to_bdfe
1061
        mov     eax, [esi+0x30]
1062
        mov     edx, [esi+0x34]
1063
        call    ntfs_datetime_to_bdfe
1064
        mov     eax, [esi+0x20]
1065
        mov     edx, [esi+0x24]
1066
        call    ntfs_datetime_to_bdfe
1067
        pop     edx
1068
        mov     eax, [esi+0x40]
1069
        stosd
1070
        mov     eax, [esi+0x44]
1071
        stosd
1072
        push    ecx esi edi
1073
        movzx   ecx, byte [esi+0x50]
1074
        add     esi, 0x52
1075
        test    byte [edi-0x24], 1
1076
        jz      .ansi
1077
        shr     ecx, 1
1078
        rep     movsd
1079
        adc     ecx, ecx
1080
        rep     movsw
1081
        and     word [edi], 0
1082
        pop     edi
1083
        add     edi, 520
1084
        pop     esi ecx
1085
        ret
1086
.ansi:
1087
        jecxz   .skip
1088
@@:
1089
        lodsw
1090
        call    uni2ansi_char
1091
        stosb
1092
        loop    @b
1093
.skip:
1094
        xor     al, al
1095
        stosb
1096
        pop     edi
1097
        add     edi, 264
1098
        pop     esi ecx
1099
        ret
1100
 
1101
iglobal
1102
_24             dd      24
1103
_60             dd      60
1104
_10000000       dd      10000000
1105
days400year     dd      365*400+100-4+1
1106
days100year     dd      365*100+25-1
1107
days4year       dd      365*4+1
1108
days1year       dd      365
1109
months  dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1110
months2 dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1111
_400            dd      400
1112
_100            dd      100
1113
endg
1114
 
1115
ntfs_datetime_to_bdfe:
1116
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
1117
        push    eax
1118
        mov     eax, edx
1119
        xor     edx, edx
1120
        div     [_10000000]
1121
        xchg    eax, [esp]
1122
        div     [_10000000]
1123
        pop     edx
1124
; edx:eax = number of seconds since January 1, 1601
1125
        push    eax
1126
        mov     eax, edx
1127
        xor     edx, edx
1128
        div     [_60]
1129
        xchg    eax, [esp]
1130
        div     [_60]
1131
        mov     [edi], dl
1132
        pop     edx
1133
; edx:eax = number of minutes
1134
        div     [_60]
1135
        mov     [edi+1], dl
1136
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
1137
        xor     edx, edx
1138
        div     [_24]
1139
        mov     [edi+2], dl
1140
        mov     [edi+3], byte 0
1141
; eax = number of days since January 1, 1601
1142
        xor     edx, edx
1143
        div     [days400year]
1144
        imul    eax, 400
1145
        add     eax, 1601
1146
        mov     [edi+6], ax
1147
        mov     eax, edx
1148
        xor     edx, edx
1149
        div     [days100year]
1150
        cmp     al, 4
1151
        jnz     @f
1152
        dec     eax
1153
        add     edx, [days100year]
1154
@@:
1155
        imul    eax, 100
1156
        add     [edi+6], ax
1157
        mov     eax, edx
1158
        xor     edx, edx
1159
        div     [days4year]
1160
        shl     eax, 2
1161
        add     [edi+6], ax
1162
        mov     eax, edx
1163
        xor     edx, edx
1164
        div     [days1year]
1165
        cmp     al, 4
1166
        jnz     @f
1167
        dec     eax
1168
        add     edx, [days1year]
1169
@@:
1170
        add     [edi+6], ax
1171
        push    esi edx
1172
        mov     esi, months
1173
        movzx   eax, word [edi+6]
1174
        test    al, 3
1175
        jnz     .noleap
1176
        xor     edx, edx
1177
        push    eax
1178
        div     [_400]
1179
        pop     eax
1180
        test    edx, edx
1181
        jz      .leap
1182
        xor     edx, edx
1183
        div     [_100]
1184
        test    edx, edx
1185
        jz      .noleap
1186
.leap:
1187
        mov     esi, months2
1188
.noleap:
1189
        pop     edx
1190
        xor     eax, eax
1191
        inc     eax
1192
@@:
1193
        sub     edx, [esi]
1194
        jb      @f
1195
        add     esi, 4
1196
        inc     eax
1197
        jmp     @b
1198
@@:
1199
        add     edx, [esi]
1200
        pop     esi
1201
        inc     edx
1202
        mov     [edi+4], dl
1203
        mov     [edi+5], al
1204
        add     edi, 8
1205
        ret
1206
 
1207
;----------------------------------------------------------------
1208
;
1209
;  ntfs_HdRewrite - write to NTFS hard disk
1210
;
1211
;  esi  points to filename
1212
;  ebx  ignored (reserved)
1213
;  ecx  number of bytes to write, 0+
1214
;  edx  mem location to data
1215
;
1216
;  ret ebx = number of written bytes
1217
;      eax = 0 ok read or other = errormsg
1218
;
1219
;--------------------------------------------------------------
1220
ntfs_HdRewrite:
1221
        xor     ebx, ebx
1222
        mov     eax, ERROR_UNSUPPORTED_FS
1223
        ret
1224
 
1225
;----------------------------------------------------------------
1226
;
1227
;  ntfs_HdWrite - write to NTFS hard disk
1228
;
1229
;  esi  points to filename
1230
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1231
;       may be ebx=0 - start from first byte
1232
;  ecx  number of bytes to write, 0+
1233
;  edx  mem location to data
1234
;
1235
;  ret ebx = bytes written (maybe 0)
1236
;      eax = 0 ok write or other = errormsg
1237
;
1238
;--------------------------------------------------------------
1239
ntfs_HdWrite:
1240
        xor     ebx, ebx
1241
        mov     eax, ERROR_UNSUPPORTED_FS
1242
        ret
1243
 
1244
;----------------------------------------------------------------
1245
;
1246
;  ntfs_HdSetFileEnd - set end of file on NTFS hard disk
1247
;
1248
;  esi  points to filename
1249
;  ebx  points to 64-bit number = new file size
1250
;  ecx  ignored (reserved)
1251
;  edx  ignored (reserved)
1252
;
1253
;  ret eax = 0 ok or other = errormsg
1254
;
1255
;--------------------------------------------------------------
1256
ntfs_HdSetFileEnd:
1257
ntfs_HdSetFileInfo:
1258
;----------------------------------------------------------------
1259
;
1260
;  ntfs_HdDelete - delete file or empty folder from NTFS hard disk
1261
;
1262
;  esi  points to filename
1263
;
1264
;  ret  eax = 0 ok or other = errormsg
1265
;
1266
;--------------------------------------------------------------
1267
ntfs_HdDelete:
1268
        mov     eax, ERROR_UNSUPPORTED_FS
1269
        ret
1270
 
1271
ntfs_HdGetFileInfo:
1272
        mov     eax, ERROR_UNSUPPORTED_FS
1273
        ret
1274