Subversion Repositories Kolibri OS

Rev

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