Subversion Repositories Kolibri OS

Rev

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