Subversion Repositories Kolibri OS

Rev

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

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