Subversion Repositories Kolibri OS

Rev

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

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