Subversion Repositories Kolibri OS

Rev

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

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