Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
425 victor 1
$Revision: 521 $
431 serge 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
 
467 mikedld 9
ntfs_test_bootsec:
256 diamond 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:
521 diamond 941
; in: esi+ebp -> name
257 diamond 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
521 diamond 1093
        test    ebp, ebp
1094
        jz      @f
1095
        mov     esi, ebp
1096
        xor     ebp, ebp
1097
        jmp     .doit2
1098
@@:
257 diamond 1099
        ret
1100
 
256 diamond 1101
;----------------------------------------------------------------
1102
;
1103
;  ntfs_HdRead - read NTFS hard disk
1104
;
1105
;  esi  points to filename
1106
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1107
;       may be ebx=0 - start from first byte
1108
;  ecx  number of bytes to read, 0+
1109
;  edx  mem location to return data
1110
;
1111
;  ret ebx = bytes read or 0xffffffff file not found
1112
;      eax = 0 ok read or other = errormsg
1113
;
1114
;--------------------------------------------------------------
1115
ntfs_HdRead:
262 diamond 1116
        cmp     byte [esi], 0
1117
        jnz     @f
256 diamond 1118
        or      ebx, -1
262 diamond 1119
        push    ERROR_ACCESS_DENIED
1120
        pop     eax
256 diamond 1121
        ret
262 diamond 1122
@@:
1123
        call    ntfs_find_lfn
1124
        jnc     .found
1125
        or      ebx, -1
1126
        push    ERROR_FILE_NOT_FOUND
1127
        pop     eax
1128
        ret
1129
.found:
1130
        mov     [ntfs_cur_attr], 0x80   ; $DATA
1131
        and     [ntfs_cur_offs], 0
1132
        and     [ntfs_cur_size], 0
1133
        call    ntfs_read_attr
1134
        jnc     @f
1135
        or      ebx, -1
1136
        push    ERROR_ACCESS_DENIED
1137
        pop     eax
1138
        ret
1139
@@:
1140
        pushad
1141
        and     dword [esp+10h], 0
1142
        xor     eax, eax
1143
        test    ebx, ebx
1144
        jz      .zero1
1145
        cmp     dword [ebx+4], 0x200
1146
        jb      @f
1147
.eof0:
1148
        popad
1149
        xor     ebx, ebx
1150
.eof:
1151
        push    ERROR_END_OF_FILE
1152
        pop     eax
1153
        ret
1154
@@:
1155
        mov     eax, [ebx]
1156
        test    eax, 0x1FF
1157
        jz      .alignedstart
1158
        push    edx
1159
        mov     edx, [ebx+4]
1160
        shrd    eax, edx, 9
1161
        pop     edx
1162
        mov     [ntfs_cur_offs], eax
1163
        mov     [ntfs_cur_size], 1
1164
        mov     [ntfs_cur_buf], ntfs_bitmap_buf
1165
        call    ntfs_read_attr.continue
1166
        mov     eax, [ebx]
1167
        and     eax, 0x1FF
1168
        lea     esi, [ntfs_bitmap_buf+eax]
1169
        sub     eax, [ntfs_cur_read]
1170
        jae     .eof0
1171
        neg     eax
1172
        push    ecx
1173
        cmp     ecx, eax
1174
        jb      @f
1175
        mov     ecx, eax
1176
@@:
1177
        mov     [esp+10h+4], ecx
1178
        mov     edi, edx
1179
        rep     movsb
1180
        mov     edx, edi
1181
        pop     ecx
1182
        sub     ecx, [esp+10h]
1183
        jnz     @f
1184
.retok:
1185
        popad
1186
        xor     eax, eax
1187
        ret
1188
@@:
1189
        cmp     [ntfs_cur_read], 0x200
1190
        jz      .alignedstart
1191
.eof_ebx:
1192
        popad
1193
        jmp     .eof
1194
.alignedstart:
1195
        mov     eax, [ebx]
1196
        push    edx
1197
        mov     edx, [ebx+4]
1198
        add     eax, 511
1199
        adc     edx, 0
1200
        shrd    eax, edx, 9
1201
        pop     edx
1202
.zero1:
1203
        mov     [ntfs_cur_offs], eax
1204
        mov     [ntfs_cur_buf], edx
1205
        mov     eax, ecx
1206
        shr     eax, 9
1207
        mov     [ntfs_cur_size], eax
1208
        add     eax, [ntfs_cur_offs]
1209
        push    eax
1210
        call    ntfs_read_attr.continue
1211
        pop     [ntfs_cur_offs]
1212
        mov     eax, [ntfs_cur_read]
1213
        add     [esp+10h], eax
1214
        mov     eax, ecx
1215
        and     eax, not 0x1FF
1216
        cmp     [ntfs_cur_read], eax
1217
        jnz     .eof_ebx
1218
        and     ecx, 0x1FF
1219
        jz      .retok
1220
        add     edx, [ntfs_cur_read]
1221
        mov     [ntfs_cur_size], 1
1222
        mov     [ntfs_cur_buf], ntfs_bitmap_buf
1223
        call    ntfs_read_attr.continue
1224
        cmp     [ntfs_cur_read], ecx
1225
        jb      @f
1226
        mov     [ntfs_cur_read], ecx
1227
@@:
1228
        xchg    ecx, [ntfs_cur_read]
1229
        push    ecx
1230
        mov     edi, edx
1231
        mov     esi, ntfs_bitmap_buf
1232
        add     [esp+10h+4], ecx
1233
        rep     movsb
1234
        pop     ecx
1235
        xor     eax, eax
1236
        cmp     ecx, [ntfs_cur_read]
1237
        jz      @f
1238
        mov     al, ERROR_END_OF_FILE
1239
@@:
1240
        mov     [esp+1Ch], eax
1241
        popad
1242
        ret
256 diamond 1243
 
1244
;----------------------------------------------------------------
1245
;
1246
;  ntfs_HdReadFolder - read NTFS hard disk folder
1247
;
1248
;  esi  points to filename
1249
;  ebx  pointer to structure 32-bit number = first wanted block, 0+
1250
;                          & flags (bitfields)
1251
; flags: bit 0: 0=ANSI names, 1=UNICODE names
1252
;  ecx  number of blocks to read, 0+
1253
;  edx  mem location to return data
1254
;
1255
;  ret ebx = blocks read or 0xffffffff folder not found
1256
;      eax = 0 ok read or other = errormsg
1257
;
1258
;--------------------------------------------------------------
1259
ntfs_HdReadFolder:
1260
        mov     eax, 5          ; root cluster
1261
        cmp     byte [esi], 0
1262
        jz      .doit
257 diamond 1263
        call    ntfs_find_lfn
1264
        jnc     .doit2
256 diamond 1265
.notfound:
1266
        or      ebx, -1
1267
        push    ERROR_FILE_NOT_FOUND
1268
.pop_ret:
1269
        pop     eax
1270
        ret
1271
.doit:
1272
        mov     [ntfs_cur_iRecord], eax
1273
.doit2:
257 diamond 1274
        mov     [ntfs_cur_attr], 0x10   ; $STANDARD_INFORMATION
1275
        and     [ntfs_cur_offs], 0
1276
        mov     [ntfs_cur_size], 1
1277
        mov     [ntfs_cur_buf], ntfs_bitmap_buf
1278
        call    ntfs_read_attr
1279
        jc      .notfound
256 diamond 1280
        mov     [ntfs_cur_attr], 0x90   ; $INDEX_ROOT
1281
        and     [ntfs_cur_offs], 0
1282
        mov     eax, [ntfs_data.cur_index_size]
1283
        mov     [ntfs_cur_size], eax
1284
        mov     eax, [ntfs_data.cur_index_buf]
1285
        mov     [ntfs_cur_buf], eax
1286
        call    ntfs_read_attr
1287
        jnc     .ok
1288
        cmp     [hd_error], 0
1289
        jz      .notfound
1290
        or      ebx, -1
1291
        push    11
1292
        jmp     .pop_ret
1293
.ok:
1294
        cmp     [ntfs_cur_read], 0x20
1295
        jae     @f
1296
        or      ebx, -1
1297
.fserr:
1298
        push    ERROR_FAT_TABLE
1299
        jmp     .pop_ret
1300
@@:
1301
        pushad
1302
        mov     esi, [ntfs_data.cur_index_buf]
1303
        mov     eax, [esi+14h]
1304
        add     eax, 10h
1305
        cmp     [ntfs_cur_read], eax
1306
        jae     .readok1
1307
        add     eax, 1FFh
1308
        shr     eax, 9
1309
        cmp     eax, [ntfs_data.cur_index_size]
1310
        ja      @f
1311
        popad
1312
        jmp     .fserr
1313
@@:
1314
; reallocate
1315
        push    eax
1316
        push    [ntfs_data.cur_index_buf]
1317
        call    kernel_free
1318
        pop     eax
1319
        mov     [ntfs_data.cur_index_size], eax
1320
        push    eax
1321
        call    kernel_alloc
1322
        test    eax, eax
1323
        jnz     @f
1324
        and     [ntfs_data.cur_index_size], 0
1325
        and     [ntfs_data.cur_index_buf], 0
1326
.nomem:
1327
        popad
1328
        or      ebx, -1
1329
        push    12
1330
        pop     eax
1331
        ret
1332
@@:
1333
        mov     [ntfs_data.cur_index_buf], eax
1334
        popad
1335
        jmp     .doit2
1336
.readok1:
1337
        mov     ebp, [esi+8]    ; subnode_size
1338
        shr     ebp, 9
1339
        cmp     ebp, [ntfs_data.cur_index_size]
1340
        jbe     .ok2
1341
        push    esi ebp
1342
        push    ebp
1343
        call    kernel_alloc
1344
        pop     ebp esi
1345
        test    eax, eax
1346
        jz      .nomem
1347
        mov     edi, eax
1348
        mov     ecx, [ntfs_data.cur_index_size]
1349
        shl     ecx, 9-2
1350
        rep     movsd
1351
        mov     esi, eax
1352
        mov     [ntfs_data.cur_index_size], ebp
1353
        push    esi ebp
1354
        push    [ntfs_data.cur_index_buf]
1355
        call    kernel_free
1356
        pop     ebp esi
1357
        mov     [ntfs_data.cur_index_buf], esi
1358
.ok2:
1359
        add     esi, 10h
1360
        mov     ebx, [esp+10h]
1361
        mov     edx, [esp+14h]
1362
        push    dword [ebx+4]   ; read ANSI/UNICODE name
1363
        mov     ebx, [ebx]
1364
; init header
1365
        mov     edi, edx
1366
        mov     ecx, 32/4
1367
        xor     eax, eax
1368
        rep     stosd
1369
        mov     byte [edx], 1   ; version
1370
        mov     ecx, [esp+4+18h]
1371
        push    edx
1372
        mov     edx, esp
1373
; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block,
1374
; ecx = number of blocks to read
1375
; edx -> parameters block: dd , dd 
257 diamond 1376
        cmp     [ntfs_cur_iRecord], 5
1377
        jz      .skip_specials
1378
; dot and dotdot entries
1379
        push    esi
1380
        xor     esi, esi
1381
        call    .add_special_entry
1382
        inc     esi
1383
        call    .add_special_entry
1384
        pop     esi
1385
.skip_specials:
256 diamond 1386
; at first, dump index root
1387
        add     esi, [esi]
1388
.dump_root:
1389
        test    byte [esi+0Ch], 2
1390
        jnz     .dump_root_done
1391
        call    .add_entry
1392
        movzx   eax, word [esi+8]
1393
        add     esi, eax
1394
        jmp     .dump_root
1395
.dump_root_done:
1396
; now dump all subnodes
1397
        push    ecx edi
1398
        mov     edi, ntfs_bitmap_buf
1399
        mov     [ntfs_cur_buf], edi
1400
        mov     ecx, 0x400/4
1401
        xor     eax, eax
1402
        rep     stosd
1403
        mov     [ntfs_cur_attr], 0xB0   ; $BITMAP
1404
        and     [ntfs_cur_offs], 0
1405
        mov     [ntfs_cur_size], 2
1406
        call    ntfs_read_attr
1407
        pop     edi ecx
1408
        push    0       ; save offset in $BITMAP attribute
1409
        and     [ntfs_cur_offs], 0
1410
.dumploop:
1411
        mov     [ntfs_cur_attr], 0xA0
1412
        mov     [ntfs_cur_size], ebp
1413
        mov     eax, [ntfs_data.cur_index_buf]
1414
        mov     esi, eax
1415
        mov     [ntfs_cur_buf], eax
1416
        push    [ntfs_cur_offs]
257 diamond 1417
        mov     eax, [ntfs_cur_offs]
1418
        imul    eax, ebp
1419
        mov     [ntfs_cur_offs], eax
256 diamond 1420
        call    ntfs_read_attr
1421
        pop     [ntfs_cur_offs]
1422
        mov     eax, ebp
1423
        shl     eax, 9
1424
        cmp     [ntfs_cur_read], eax
1425
        jnz     .done
1426
        push    eax
1427
        mov     eax, [ntfs_cur_offs]
1428
        and     eax, 0x400*8-1
1429
        bt      dword [ntfs_bitmap_buf], eax
1430
        pop     eax
1431
        jnc     .dump_subnode_done
1432
        cmp     dword [esi], 'INDX'
1433
        jnz     .dump_subnode_done
1434
        push    ebx
1435
        mov     ebx, esi
1436
        call    ntfs_restore_usa
1437
        pop     ebx
1438
        jc      .dump_subnode_done
1439
        add     esi, 0x18
1440
        add     esi, [esi]
1441
.dump_subnode:
1442
        test    byte [esi+0Ch], 2
1443
        jnz     .dump_subnode_done
1444
        call    .add_entry
1445
        movzx   eax, word [esi+8]
1446
        add     esi, eax
1447
        jmp     .dump_subnode
1448
.dump_subnode_done:
1449
        inc     [ntfs_cur_offs]
1450
        test    [ntfs_cur_offs], 0x400*8-1
1451
        jnz     .dumploop
1452
        mov     [ntfs_cur_attr], 0xB0
1453
        push    ecx edi
1454
        mov     edi, ntfs_bitmap_buf
1455
        mov     [ntfs_cur_buf], edi
1456
        mov     ecx, 0x400/4
1457
        xor     eax, eax
1458
        rep     stosd
1459
        pop     edi ecx
1460
        pop     eax
1461
        push    [ntfs_cur_offs]
1462
        inc     eax
1463
        mov     [ntfs_cur_offs], eax
1464
        mov     [ntfs_cur_size], 2
1465
        push    eax
1466
        call    ntfs_read_attr
1467
        pop     eax
1468
        pop     [ntfs_cur_offs]
1469
        push    eax
1470
        jmp     .dumploop
1471
.done:
1472
        pop     eax
1473
        pop     edx
1474
        mov     ebx, [edx+4]
1475
        pop     edx
1476
        xor     eax, eax
1477
        dec     ecx
1478
        js      @f
1479
        mov     al, ERROR_END_OF_FILE
1480
@@:
1481
        mov     [esp+1Ch], eax
1482
        mov     [esp+10h], ebx
1483
        popad
1484
        ret
1485
 
257 diamond 1486
.add_special_entry:
1487
        mov     eax, [edx]
1488
        inc     dword [eax+8]   ; new file found
1489
        dec     ebx
1490
        jns     .ret
1491
        dec     ecx
1492
        js      .ret
1493
        inc     dword [eax+4]   ; new file block copied
1494
        mov     eax, [edx+4]
1495
        mov     [edi+4], eax
1496
;        mov     eax, dword [ntfs_bitmap_buf+0x20]
1497
;        or      al, 0x10
1498
        mov     eax, 0x10
1499
        stosd
1500
        scasd
1501
        push    edx
1502
        mov     eax, dword [ntfs_bitmap_buf]
1503
        mov     edx, dword [ntfs_bitmap_buf+4]
1504
        call    ntfs_datetime_to_bdfe
1505
        mov     eax, dword [ntfs_bitmap_buf+0x18]
1506
        mov     edx, dword [ntfs_bitmap_buf+0x1C]
1507
        call    ntfs_datetime_to_bdfe
1508
        mov     eax, dword [ntfs_bitmap_buf+8]
1509
        mov     edx, dword [ntfs_bitmap_buf+0xC]
1510
        call    ntfs_datetime_to_bdfe
1511
        pop     edx
1512
        xor     eax, eax
1513
        stosd
1514
        stosd
1515
        mov     al, '.'
1516
        push    edi ecx
1517
        lea     ecx, [esi+1]
1518
        test    byte [edi-0x24], 1
1519
        jz      @f
1520
        rep     stosw
1521
        pop     ecx
1522
        xor     eax, eax
1523
        stosw
1524
        pop     edi
1525
        add     edi, 520
1526
        ret
1527
@@:
1528
        rep     stosb
1529
        pop     ecx
1530
        xor     eax, eax
1531
        stosb
1532
        pop     edi
1533
        add     edi, 264
1534
.ret:
1535
        ret
1536
 
256 diamond 1537
.add_entry:
1538
; do not return DOS 8.3 names
1539
        cmp     byte [esi+0x51], 2
1540
        jz      .ret
1541
; do not return system files
1542
; ... note that there will be no bad effects if system files also were reported ...
1543
        cmp     dword [esi], 0x10
1544
        jb      .ret
1545
        mov     eax, [edx]
1546
        inc     dword [eax+8]   ; new file found
1547
        dec     ebx
1548
        jns     .ret
1549
        dec     ecx
1550
        js      .ret
1551
        inc     dword [eax+4]   ; new file block copied
1552
        mov     eax, [edx+4]    ; flags
262 diamond 1553
        call    ntfs_direntry_to_bdfe
256 diamond 1554
        push    ecx esi edi
1555
        movzx   ecx, byte [esi+0x50]
1556
        add     esi, 0x52
1557
        test    byte [edi-0x24], 1
1558
        jz      .ansi
1559
        shr     ecx, 1
1560
        rep     movsd
1561
        adc     ecx, ecx
1562
        rep     movsw
1563
        and     word [edi], 0
1564
        pop     edi
1565
        add     edi, 520
1566
        pop     esi ecx
1567
        ret
1568
.ansi:
1569
        jecxz   .skip
1570
@@:
1571
        lodsw
1572
        call    uni2ansi_char
1573
        stosb
1574
        loop    @b
1575
.skip:
1576
        xor     al, al
1577
        stosb
1578
        pop     edi
1579
        add     edi, 264
1580
        pop     esi ecx
1581
        ret
1582
 
262 diamond 1583
ntfs_direntry_to_bdfe:
1584
        mov     [edi+4], eax    ; ANSI/UNICODE name
1585
        mov     eax, [esi+48h]
1586
        test    eax, 0x10000000
1587
        jz      @f
1588
        and     eax, not 0x10000000
1589
        or      al, 0x10
1590
@@:
1591
        stosd
1592
        scasd
1593
        push    edx
1594
        mov     eax, [esi+0x18]
1595
        mov     edx, [esi+0x1C]
1596
        call    ntfs_datetime_to_bdfe
1597
        mov     eax, [esi+0x30]
1598
        mov     edx, [esi+0x34]
1599
        call    ntfs_datetime_to_bdfe
1600
        mov     eax, [esi+0x20]
1601
        mov     edx, [esi+0x24]
1602
        call    ntfs_datetime_to_bdfe
1603
        pop     edx
1604
        mov     eax, [esi+0x40]
1605
        stosd
1606
        mov     eax, [esi+0x44]
1607
        stosd
1608
        ret
1609
 
256 diamond 1610
iglobal
1611
_24             dd      24
1612
_60             dd      60
1613
_10000000       dd      10000000
1614
days400year     dd      365*400+100-4+1
1615
days100year     dd      365*100+25-1
1616
days4year       dd      365*4+1
1617
days1year       dd      365
1618
months  dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1619
months2 dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1620
_400            dd      400
1621
_100            dd      100
1622
endg
1623
 
1624
ntfs_datetime_to_bdfe:
1625
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
1626
        push    eax
1627
        mov     eax, edx
1628
        xor     edx, edx
1629
        div     [_10000000]
1630
        xchg    eax, [esp]
1631
        div     [_10000000]
1632
        pop     edx
1633
; edx:eax = number of seconds since January 1, 1601
1634
        push    eax
1635
        mov     eax, edx
1636
        xor     edx, edx
1637
        div     [_60]
1638
        xchg    eax, [esp]
1639
        div     [_60]
1640
        mov     [edi], dl
1641
        pop     edx
1642
; edx:eax = number of minutes
1643
        div     [_60]
1644
        mov     [edi+1], dl
1645
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
1646
        xor     edx, edx
1647
        div     [_24]
1648
        mov     [edi+2], dl
1649
        mov     [edi+3], byte 0
1650
; eax = number of days since January 1, 1601
1651
        xor     edx, edx
1652
        div     [days400year]
1653
        imul    eax, 400
1654
        add     eax, 1601
1655
        mov     [edi+6], ax
1656
        mov     eax, edx
1657
        xor     edx, edx
1658
        div     [days100year]
1659
        cmp     al, 4
1660
        jnz     @f
1661
        dec     eax
1662
        add     edx, [days100year]
1663
@@:
1664
        imul    eax, 100
1665
        add     [edi+6], ax
1666
        mov     eax, edx
1667
        xor     edx, edx
1668
        div     [days4year]
1669
        shl     eax, 2
1670
        add     [edi+6], ax
1671
        mov     eax, edx
1672
        xor     edx, edx
1673
        div     [days1year]
1674
        cmp     al, 4
1675
        jnz     @f
1676
        dec     eax
1677
        add     edx, [days1year]
1678
@@:
1679
        add     [edi+6], ax
1680
        push    esi edx
1681
        mov     esi, months
1682
        movzx   eax, word [edi+6]
1683
        test    al, 3
1684
        jnz     .noleap
1685
        xor     edx, edx
1686
        push    eax
1687
        div     [_400]
1688
        pop     eax
1689
        test    edx, edx
1690
        jz      .leap
1691
        xor     edx, edx
1692
        div     [_100]
1693
        test    edx, edx
1694
        jz      .noleap
1695
.leap:
1696
        mov     esi, months2
1697
.noleap:
1698
        pop     edx
1699
        xor     eax, eax
1700
        inc     eax
1701
@@:
1702
        sub     edx, [esi]
1703
        jb      @f
1704
        add     esi, 4
1705
        inc     eax
1706
        jmp     @b
1707
@@:
1708
        add     edx, [esi]
1709
        pop     esi
1710
        inc     edx
1711
        mov     [edi+4], dl
1712
        mov     [edi+5], al
1713
        add     edi, 8
1714
        ret
1715
 
1716
;----------------------------------------------------------------
1717
;
1718
;  ntfs_HdRewrite - write to NTFS hard disk
1719
;
1720
;  esi  points to filename
1721
;  ebx  ignored (reserved)
1722
;  ecx  number of bytes to write, 0+
1723
;  edx  mem location to data
1724
;
1725
;  ret ebx = number of written bytes
1726
;      eax = 0 ok read or other = errormsg
1727
;
1728
;--------------------------------------------------------------
1729
ntfs_HdRewrite:
1730
        xor     ebx, ebx
1731
        mov     eax, ERROR_UNSUPPORTED_FS
1732
        ret
1733
 
1734
;----------------------------------------------------------------
1735
;
1736
;  ntfs_HdWrite - write to NTFS hard disk
1737
;
1738
;  esi  points to filename
1739
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1740
;       may be ebx=0 - start from first byte
1741
;  ecx  number of bytes to write, 0+
1742
;  edx  mem location to data
1743
;
1744
;  ret ebx = bytes written (maybe 0)
1745
;      eax = 0 ok write or other = errormsg
1746
;
1747
;--------------------------------------------------------------
1748
ntfs_HdWrite:
1749
        xor     ebx, ebx
1750
        mov     eax, ERROR_UNSUPPORTED_FS
1751
        ret
1752
 
1753
;----------------------------------------------------------------
1754
;
1755
;  ntfs_HdSetFileEnd - set end of file on NTFS hard disk
1756
;
1757
;  esi  points to filename
1758
;  ebx  points to 64-bit number = new file size
1759
;  ecx  ignored (reserved)
1760
;  edx  ignored (reserved)
1761
;
1762
;  ret eax = 0 ok or other = errormsg
1763
;
1764
;--------------------------------------------------------------
1765
ntfs_HdSetFileEnd:
1766
ntfs_HdSetFileInfo:
1767
;----------------------------------------------------------------
1768
;
1769
;  ntfs_HdDelete - delete file or empty folder from NTFS hard disk
1770
;
1771
;  esi  points to filename
1772
;
1773
;  ret  eax = 0 ok or other = errormsg
1774
;
1775
;--------------------------------------------------------------
1776
ntfs_HdDelete:
1777
        mov     eax, ERROR_UNSUPPORTED_FS
1778
        ret
1779
 
1780
ntfs_HdGetFileInfo:
262 diamond 1781
        cmp     byte [esi], 0
1782
        jnz     @f
1783
        push    2
1784
        pop     eax
256 diamond 1785
        ret
262 diamond 1786
@@:
1787
        call    ntfs_find_lfn
1788
        jnc     .doit
1789
        push    ERROR_FILE_NOT_FOUND
1790
        pop     eax
1791
        cmp     [hd_error], 0
1792
        jz      @f
1793
        mov     al, 11
1794
@@:
1795
        ret
1796
.doit:
1797
        push    esi edi
1798
        mov     esi, eax
1799
        mov     edi, edx
1800
        xor     eax, eax
1801
        call    ntfs_direntry_to_bdfe
1802
        pop     edi esi
1803
        xor     eax, eax
1804
        ret