Subversion Repositories Kolibri OS

Rev

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

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