Subversion Repositories Kolibri OS

Rev

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

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