Subversion Repositories Kolibri OS

Rev

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

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