Subversion Repositories Kolibri OS

Rev

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