Subversion Repositories Kolibri OS

Rev

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