Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3908 Serge 3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
593 mikedld 8
$Revision: 5201 $
9
 
3908 Serge 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      ?
593 mikedld 28
 
3908 Serge 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
 
1378 turbanoff 69
ntfs_test_bootsec:
256 diamond 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
 
3908 Serge 154
proc ntfs_create_partition
5201 serge 155
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
156
        jnz     .nope
3908 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:
256 diamond 181
; By given bootsector, initialize some NTFS variables
3908 Serge 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
 
256 diamond 203
        movzx   eax, byte [ebx+13]
3908 Serge 204
        mov     [ebp+NTFS.sectors_per_cluster], eax
256 diamond 205
        mov     eax, [ebx+0x28]
3908 Serge 206
        mov     dword [ebp+NTFS.Length], eax
207
        and     dword [ebp+NTFS.Length+4], 0
256 diamond 208
        mov     eax, [ebx+0x30]
3908 Serge 209
        mov     [ebp+NTFS.mft_cluster], eax
256 diamond 210
        mov     eax, [ebx+0x38]
3908 Serge 211
        mov     [ebp+NTFS.mftmirr_cluster], eax
256 diamond 212
        movsx   eax, byte [ebx+0x40]
213
        test    eax, eax
214
        js      .1
3908 Serge 215
        mul     [ebp+NTFS.sectors_per_cluster]
256 diamond 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:
3908 Serge 224
        mov     [ebp+NTFS.frs_size], eax
256 diamond 225
        movsx   eax, byte [ebx+0x44]
226
        test    eax, eax
227
        js      .3
3908 Serge 228
        mul     [ebp+NTFS.sectors_per_cluster]
256 diamond 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:
3908 Serge 237
        mov     [ebp+NTFS.iab_size], eax
256 diamond 238
; allocate space for buffers
3908 Serge 239
        add     eax, [ebp+NTFS.frs_size]
256 diamond 240
        push    eax
241
        call    kernel_alloc
242
        test    eax, eax
3908 Serge 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
256 diamond 247
; read $MFT disposition
3908 Serge 248
        mov     eax, [ebp+NTFS.mft_cluster]
249
        mul     [ebp+NTFS.sectors_per_cluster]
256 diamond 250
        call    ntfs_read_frs_sector
3908 Serge 251
        test    eax, eax
256 diamond 252
        jnz     .usemirr
253
        cmp     dword [ebx], 'FILE'
254
        jnz     .usemirr
255
        call    ntfs_restore_usa_frs
256
        jnc     .mftok
257
.usemirr:
3908 Serge 258
        mov     eax, [ebp+NTFS.mftmirr_cluster]
259
        mul     [ebp+NTFS.sectors_per_cluster]
256 diamond 260
        call    ntfs_read_frs_sector
3908 Serge 261
        test    eax, eax
256 diamond 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:
3908 Serge 270
        push    [ebp+NTFS.frs_buffer]
256 diamond 271
        call    kernel_free
3908 Serge 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
256 diamond 284
.fail_free_mft:
3908 Serge 285
        push    [ebp+NTFS.mft_retrieval]
256 diamond 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
3908 Serge 297
        mov     [ebp+NTFS.mft_retrieval], eax
298
        and     [ebp+NTFS.mft_retrieval_size], 0
299
        mov     [ebp+NTFS.mft_retrieval_alloc], 0x1000/8
256 diamond 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]
3908 Serge 318
        mov     [ebp+NTFS.mft_retrieval_end], edx
256 diamond 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
3908 Serge 331
        inc     [ebp+NTFS.mft_retrieval_size]
256 diamond 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
 
3908 Serge 338
        mov     [ebp+NTFS.cur_index_size], 0x1000/0x200
256 diamond 339
        push    0x1000
340
        call    kernel_alloc
341
        test    eax, eax
342
        jz      .fail_free_mft
3908 Serge 343
        mov     [ebp+NTFS.cur_index_buf], eax
256 diamond 344
 
3908 Serge 345
        mov     eax, ebp
346
        jmp     .pop_exit
347
endp
256 diamond 348
 
349
.get_mft_retrieval_ptr:
350
        pushad
3908 Serge 351
        mov     eax, [ebp+NTFS.mft_retrieval_size]
352
        cmp     eax, [ebp+NTFS.mft_retrieval_alloc]
256 diamond 353
        jnz     .ok
354
        add     eax, 0x1000/8
3908 Serge 355
        mov     [ebp+NTFS.mft_retrieval_alloc], eax
256 diamond 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
@@:
3908 Serge 365
        mov     esi, [ebp+NTFS.mft_retrieval]
256 diamond 366
        mov     edi, eax
3908 Serge 367
        mov     ecx, [ebp+NTFS.mft_retrieval_size]
256 diamond 368
        add     ecx, ecx
3908 Serge 369
        rep movsd
370
        push    [ebp+NTFS.mft_retrieval]
371
        mov     [ebp+NTFS.mft_retrieval], eax
256 diamond 372
        call    kernel_free
3908 Serge 373
        mov     eax, [ebp+NTFS.mft_retrieval_size]
256 diamond 374
.ok:
375
        shl     eax, 3
3908 Serge 376
        add     eax, [ebp+NTFS.mft_retrieval]
256 diamond 377
        mov     [esp+28], eax
378
        popad
379
        ret
380
 
3908 Serge 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
 
256 diamond 403
ntfs_read_frs_sector:
3908 Serge 404
        push    ecx
405
        mov     ebx, [ebp+NTFS.frs_buffer]
406
        push    ebx
407
        mov     ecx, [ebp+NTFS.frs_size]
256 diamond 408
        shr     ecx, 9
3908 Serge 409
        push    ecx
410
        mov     ecx, eax
256 diamond 411
@@:
3908 Serge 412
        mov     eax, ecx
413
        call    fs_read32_sys
414
        test    eax, eax
256 diamond 415
        jnz     .fail
416
        add     ebx, 0x200
3908 Serge 417
        inc     ecx
418
        dec     dword [esp]
419
        jnz     @b
420
        pop     eax
256 diamond 421
.fail:
422
        pop     ebx
3908 Serge 423
        pop     ecx
256 diamond 424
        ret
425
 
426
ntfs_read_attr:
3908 Serge 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
256 diamond 431
        pushad
3908 Serge 432
        and     [ebp+NTFS.ntfs_cur_read], 0
433
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
256 diamond 434
        jnz     .nomft
3908 Serge 435
        cmp     [ebp+NTFS.ntfs_cur_attr], 0x80
256 diamond 436
        jnz     .nomft
3908 Serge 437
        mov     eax, [ebp+NTFS.mft_retrieval_end]
256 diamond 438
        inc     eax
3908 Serge 439
        mul     [ebp+NTFS.sectors_per_cluster]
440
        cmp     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 441
        jbe     .nomft
442
; precalculated part of $Mft $DATA
3908 Serge 443
        mov     esi, [ebp+NTFS.mft_retrieval]
444
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 445
        xor     edx, edx
3908 Serge 446
        div     [ebp+NTFS.sectors_per_cluster]
256 diamond 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
3908 Serge 455
        mov     eax, [ebp+NTFS.mft_retrieval_end]
256 diamond 456
        shl     eax, 3
3908 Serge 457
        add     eax, [ebp+NTFS.mft_retrieval]
256 diamond 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
3908 Serge 468
        mov     eax, [ebp+NTFS.sectors_per_cluster]
256 diamond 469
        mul     ecx
470
; eax = sector on partition
471
        pop     edx
472
        add     eax, edx
3908 Serge 473
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
256 diamond 474
        pop     ecx
475
        neg     ecx
3908 Serge 476
        imul    ecx, [ebp+NTFS.sectors_per_cluster]
256 diamond 477
        sub     ecx, edx
3908 Serge 478
        cmp     ecx, [ebp+NTFS.ntfs_cur_size]
256 diamond 479
        jb      @f
3908 Serge 480
        mov     ecx, [ebp+NTFS.ntfs_cur_size]
256 diamond 481
@@:
482
; ecx = number of sequential sectors to read
3908 Serge 483
        push    eax
484
        call    fs_read32_sys
485
        pop     edx
486
        test    eax, eax
256 diamond 487
        jnz     .errread
3908 Serge 488
        add     [ebp+NTFS.ntfs_cur_read], 0x200
489
        dec     [ebp+NTFS.ntfs_cur_size]
490
        inc     [ebp+NTFS.ntfs_cur_offs]
256 diamond 491
        add     ebx, 0x200
3908 Serge 492
        mov     [ebp+NTFS.ntfs_cur_buf], ebx
493
        lea     eax, [edx+1]
256 diamond 494
        loop    @b
495
        pop     ecx
496
        xor     eax, eax
497
        xor     edx, edx
3908 Serge 498
        cmp     [ebp+NTFS.ntfs_cur_size], eax
256 diamond 499
        jz      @f
500
        add     esi, 8
501
        push    eax
3908 Serge 502
        mov     eax, [ebp+NTFS.mft_retrieval_end]
256 diamond 503
        shl     eax, 3
3908 Serge 504
        add     eax, [ebp+NTFS.mft_retrieval]
256 diamond 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:
3908 Serge 515
        mov     [esp+28], eax
256 diamond 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.
3908 Serge 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
256 diamond 528
        call    ntfs_read_file_record
3908 Serge 529
        jc      .errret
256 diamond 530
; 2. Find required attribute.
3908 Serge 531
        mov     eax, [ebp+NTFS.frs_buffer]
256 diamond 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:
3908 Serge 541
        mov     [ebp+NTFS.ntfs_attr_iRecord], eax
256 diamond 542
        call    ntfs_read_file_record
3908 Serge 543
        jc      .errret
256 diamond 544
@@:
545
; b) Scan for required attribute and for $ATTR_LIST
3908 Serge 546
        mov     eax, [ebp+NTFS.frs_buffer]
256 diamond 547
        movzx   ecx, word [eax+14h]
548
        add     eax, ecx
3908 Serge 549
        mov     ecx, [ebp+NTFS.ntfs_cur_attr]
550
        and     [ebp+NTFS.ntfs_attr_offs], 0
256 diamond 551
.scanattr:
552
        cmp     dword [eax], -1
553
        jz      .scandone
554
        cmp     dword [eax], ecx
555
        jz      .okattr
3908 Serge 556
        cmp     [ebp+NTFS.ntfs_attr_iBaseRecord], -1
256 diamond 557
        jnz     .scancont
558
        cmp     dword [eax], 0x20       ; $ATTR_LIST
559
        jnz     .scancont
3908 Serge 560
        mov     [ebp+NTFS.ntfs_attr_list], eax
256 diamond 561
        jmp     .scancont
562
.okattr:
273 diamond 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
@@:
3908 Serge 569
        mov     [ebp+NTFS.ntfs_attr_offs], eax
256 diamond 570
.scancont:
571
        add     eax, [eax+4]
572
        jmp     .scanattr
262 diamond 573
.continue:
574
        pushad
3908 Serge 575
        and     [ebp+NTFS.ntfs_cur_read], 0
256 diamond 576
.scandone:
577
; c) Check for required offset and length
3908 Serge 578
        mov     ecx, [ebp+NTFS.ntfs_attr_offs]
256 diamond 579
        jecxz   .noattr
3908 Serge 580
        push    [ebp+NTFS.ntfs_cur_size]
581
        push    [ebp+NTFS.ntfs_cur_read]
256 diamond 582
        call    .doreadattr
265 diamond 583
        pop     edx
3908 Serge 584
        pop     ecx
256 diamond 585
        jc      @f
3908 Serge 586
        cmp     [ebp+NTFS.ntfs_bCanContinue], 0
265 diamond 587
        jz      @f
3908 Serge 588
        sub     edx, [ebp+NTFS.ntfs_cur_read]
265 diamond 589
        neg     edx
590
        shr     edx, 9
3908 Serge 591
        sub     ecx, edx
592
        mov     [ebp+NTFS.ntfs_cur_size], ecx
256 diamond 593
        jnz     .not_in_cur
594
@@:
595
        popad
596
        ret
597
.noattr:
598
.not_in_cur:
3908 Serge 599
        cmp     [ebp+NTFS.ntfs_cur_attr], 0x20
256 diamond 600
        jz      @f
3908 Serge 601
        mov     ecx, [ebp+NTFS.ntfs_attr_list]
256 diamond 602
        test    ecx, ecx
603
        jnz     .lookattr
604
.ret_is_attr:
3908 Serge 605
        and     dword [esp+28], 0
606
        cmp     [ebp+NTFS.ntfs_attr_offs], 1     ; CF set <=> ntfs_attr_offs == 0
256 diamond 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
3908 Serge 613
        mov     eax, [ebp+NTFS.ntfs_attr_iBaseRecord]
256 diamond 614
        cmp     eax, -1
615
        jz      @f
616
        call    ntfs_read_file_record
3908 Serge 617
        jc      .errret
618
        or      [ebp+NTFS.ntfs_attr_iBaseRecord], -1
256 diamond 619
@@:
3908 Serge 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
273 diamond 633
        jnz     @f
3908 Serge 634
        lea     eax, [ebp+NTFS.ntfs_attrlist_mft_buf]
273 diamond 635
@@:
3908 Serge 636
        mov     [ebp+NTFS.ntfs_cur_buf], eax
273 diamond 637
        push    eax
256 diamond 638
        call    .doreadattr
273 diamond 639
        pop     esi
640
        mov     edx, 1
3908 Serge 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]
256 diamond 648
        jc      .errret
649
        or      edi, -1
3908 Serge 650
        lea     ecx, [ecx+esi-1Ah]
256 diamond 651
.scanliststart:
3908 Serge 652
        push    ecx
653
        mov     eax, [ebp+NTFS.ntfs_cur_attr]
256 diamond 654
.scanlist:
3908 Serge 655
        cmp     esi, [esp]
256 diamond 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
@@:
273 diamond 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
@@:
256 diamond 670
        push    eax
671
        mov     eax, [esi+8]
257 diamond 672
        test    eax, eax
673
        jnz     .testf
3908 Serge 674
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
675
        and     eax, dword [ebp+NTFS.ntfs_attr_size+4]
257 diamond 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
3908 Serge 681
        jnc     @f
257 diamond 682
.errret_pop:
3908 Serge 683
        pop     ecx ecx
257 diamond 684
        jmp     .errret
3908 Serge 685
.errret2_pop:
686
        xor     eax, eax
687
        jmp     .errret_pop
257 diamond 688
@@:
3908 Serge 689
        mov     eax, [ebp+NTFS.frs_buffer]
257 diamond 690
        movzx   ecx, word [eax+14h]
691
        add     eax, ecx
3908 Serge 692
        mov     ecx, [ebp+NTFS.ntfs_cur_attr]
257 diamond 693
@@:
694
        cmp     dword [eax], -1
3908 Serge 695
        jz      .errret2_pop
257 diamond 696
        cmp     dword [eax], ecx
697
        jz      @f
273 diamond 698
.l1:
257 diamond 699
        add     eax, [eax+4]
700
        jmp     @b
701
@@:
273 diamond 702
        cmp     eax, 0x80
703
        jnz     @f
704
        cmp     byte [eax+9], 0
705
        jnz     .l1
706
@@:
257 diamond 707
        cmp     byte [eax+8], 0
708
        jnz     .sdnores
709
        mov     eax, [eax+10h]
3908 Serge 710
        mov     dword [ebp+NTFS.ntfs_attr_size], eax
711
        and     dword [ebp+NTFS.ntfs_attr_size+4], 0
257 diamond 712
        jmp     .testfz
713
.sdnores:
714
        mov     ecx, [eax+30h]
3908 Serge 715
        mov     dword [ebp+NTFS.ntfs_attr_size], ecx
257 diamond 716
        mov     ecx, [eax+34h]
3908 Serge 717
        mov     dword [ebp+NTFS.ntfs_attr_size+4], ecx
257 diamond 718
.testfz:
719
        xor     eax, eax
720
.testf:
3908 Serge 721
        imul    eax, [ebp+NTFS.sectors_per_cluster]
722
        cmp     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 723
        pop     eax
724
        ja      @f
725
        mov     edi, [esi+10h]  ; keep previous iRecord
726
        jmp     .scanlistcont
727
@@:
3908 Serge 728
        pop     ecx
257 diamond 729
.scanlistfound:
256 diamond 730
        cmp     edi, -1
731
        jnz     @f
732
        popad
733
        ret
734
@@:
3908 Serge 735
        mov     eax, [ebp+NTFS.ntfs_cur_iRecord]
736
        mov     [ebp+NTFS.ntfs_attr_iBaseRecord], eax
256 diamond 737
        mov     eax, edi
738
        jmp     .beginfindattr
739
.scanlistdone:
3908 Serge 740
        pop     ecx
741
        sub     ecx, ebp
742
        sub     ecx, NTFS.ntfs_attrlist_buf-1Ah
743
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
256 diamond 744
        jnz     @f
3908 Serge 745
        sub     ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf
273 diamond 746
@@:
3908 Serge 747
        cmp     ecx, 0x400
257 diamond 748
        jnz     .scanlistfound
256 diamond 749
        inc     edx
750
        push    esi edi
3908 Serge 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
273 diamond 754
        jnz     @f
3908 Serge 755
        lea     esi, [ebp+NTFS.ntfs_attrlist_mft_buf+0x200]
756
        lea     edi, [ebp+NTFS.ntfs_attrlist_mft_buf]
273 diamond 757
@@:
256 diamond 758
        mov     ecx, 0x200/4
3908 Serge 759
        rep movsd
273 diamond 760
        mov     eax, edi
256 diamond 761
        pop     edi esi
762
        sub     esi, 0x200
3908 Serge 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
256 diamond 777
        call    .doreadattr
3908 Serge 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]
256 diamond 786
        jc      .errret
3908 Serge 787
        lea     ecx, [ecx+ebp+NTFS.ntfs_attrlist_buf+0x200-0x1A]
788
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 0
273 diamond 789
        jnz     .scanliststart
3908 Serge 790
        add     ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf
256 diamond 791
        jmp     .scanliststart
792
 
793
.doreadattr:
3908 Serge 794
        mov     [ebp+NTFS.ntfs_bCanContinue], 0
256 diamond 795
        cmp     byte [ecx+8], 0
796
        jnz     .nonresident
797
        mov     eax, [ecx+10h]  ; length
798
        mov     esi, eax
3908 Serge 799
        mov     edx, [ebp+NTFS.ntfs_cur_offs]
256 diamond 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
3908 Serge 808
        mov     eax, [ebp+NTFS.ntfs_cur_size]
256 diamond 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
3908 Serge 819
        mov     [ebp+NTFS.ntfs_cur_read], eax
256 diamond 820
        mov     ecx, eax
821
        mov     eax, edx
3908 Serge 822
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
256 diamond 823
        call    memmove
3908 Serge 824
        and     [ebp+NTFS.ntfs_cur_size], 0      ; CF=0
256 diamond 825
        ret
826
.nonresident:
257 diamond 827
; Not all auxiliary records contain correct FileSize info
3908 Serge 828
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
829
        mov     edx, dword [ebp+NTFS.ntfs_attr_size+4]
257 diamond 830
        push    eax
831
        and     eax, edx
832
        cmp     eax, -1
833
        pop     eax
834
        jnz     @f
256 diamond 835
        mov     eax, [ecx+30h]  ; FileSize
836
        mov     edx, [ecx+34h]
3908 Serge 837
        mov     dword [ebp+NTFS.ntfs_attr_size], eax
838
        mov     dword [ebp+NTFS.ntfs_attr_size+4], edx
257 diamond 839
@@:
256 diamond 840
        add     eax, 0x1FF
841
        adc     edx, 0
842
        shrd    eax, edx, 9
3908 Serge 843
        sub     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 844
        ja      @f
845
; return with nothing read
3908 Serge 846
        and     [ebp+NTFS.ntfs_cur_size], 0
256 diamond 847
.okret:
848
        clc
849
        ret
850
@@:
851
; reduce read length
3908 Serge 852
        and     [ebp+NTFS.ntfs_cur_tail], 0
853
        cmp     [ebp+NTFS.ntfs_cur_size], eax
256 diamond 854
        jb      @f
3908 Serge 855
        mov     [ebp+NTFS.ntfs_cur_size], eax
856
        mov     eax, dword [ebp+NTFS.ntfs_attr_size]
262 diamond 857
        and     eax, 0x1FF
3908 Serge 858
        mov     [ebp+NTFS.ntfs_cur_tail], eax
256 diamond 859
@@:
3908 Serge 860
        cmp     [ebp+NTFS.ntfs_cur_size], 0
256 diamond 861
        jz      .okret
3908 Serge 862
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 863
        xor     edx, edx
3908 Serge 864
        div     [ebp+NTFS.sectors_per_cluster]
256 diamond 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
3908 Serge 871
        xor     edi, edi
256 diamond 872
.readloop:
873
        call    ntfs_decode_mcb_entry
874
        jnc     .break
3908 Serge 875
        add     edi, [esp+8]
256 diamond 876
        sub     eax, [esp]
877
        jae     .readloop
878
        push    ecx
879
        push    eax
880
        add     eax, [esp+8]
3908 Serge 881
        add     eax, edi
882
        imul    eax, [ebp+NTFS.sectors_per_cluster]
256 diamond 883
        add     eax, edx
884
        pop     ecx
885
        neg     ecx
3908 Serge 886
        imul    ecx, [ebp+NTFS.sectors_per_cluster]
256 diamond 887
        sub     ecx, edx
3908 Serge 888
        cmp     ecx, [ebp+NTFS.ntfs_cur_size]
256 diamond 889
        jb      @f
3908 Serge 890
        mov     ecx, [ebp+NTFS.ntfs_cur_size]
256 diamond 891
@@:
3908 Serge 892
        mov     ebx, [ebp+NTFS.ntfs_cur_buf]
256 diamond 893
@@:
3908 Serge 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
256 diamond 906
        jnz     .errread2
907
        add     ebx, 0x200
3908 Serge 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]
256 diamond 913
        loop    @b
914
        pop     ecx
265 diamond 915
        xor     eax, eax
916
        xor     edx, edx
3908 Serge 917
        cmp     [ebp+NTFS.ntfs_cur_size], 0
256 diamond 918
        jnz     .readloop
919
        add     esp, 10h
3908 Serge 920
        mov     eax, [ebp+NTFS.ntfs_cur_tail]
262 diamond 921
        test    eax, eax
820 diamond 922
        jz      @f
262 diamond 923
        sub     eax, 0x200
3908 Serge 924
        add     [ebp+NTFS.ntfs_cur_read], eax
820 diamond 925
@@:
926
        clc
927
        ret
256 diamond 928
.errread2:
929
        pop     ecx
930
        add     esp, 10h
820 diamond 931
        stc
932
        ret
256 diamond 933
.break:
934
        add     esp, 10h        ; CF=0
3908 Serge 935
        mov     [ebp+NTFS.ntfs_bCanContinue], 1
256 diamond 936
        ret
937
 
938
ntfs_read_file_record:
939
; in: eax=iRecord
3908 Serge 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]
256 diamond 943
        push    ecx edx
3908 Serge 944
        mov     ecx, [ebp+NTFS.frs_size]
256 diamond 945
        mul     ecx
946
        shrd    eax, edx, 9
947
        shr     edx, 9
3908 Serge 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
256 diamond 964
        shr     ecx, 9
3908 Serge 965
        mov     [ebp+NTFS.ntfs_cur_size], ecx
966
        mov     eax, [ebp+NTFS.frs_buffer]
967
        mov     [ebp+NTFS.ntfs_cur_buf], eax
256 diamond 968
        call    ntfs_read_attr
3908 Serge 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]
256 diamond 984
        jnz     .errret
3908 Serge 985
        mov     eax, [ebp+NTFS.frs_buffer]
256 diamond 986
        cmp     dword [eax], 'FILE'
987
        jnz     .errret
988
        push    ebx
989
        mov     ebx, eax
990
        call    ntfs_restore_usa_frs
991
        pop     ebx
3908 Serge 992
        jc      .errret
256 diamond 993
.ret:
3908 Serge 994
        pop     edx ecx
256 diamond 995
        ret
3908 Serge 996
.errret:
256 diamond 997
        pop     edx ecx
998
        xor     eax, eax
3908 Serge 999
        stc
256 diamond 1000
        ret
1001
 
1002
ntfs_restore_usa_frs:
3908 Serge 1003
        mov     eax, [ebp+NTFS.frs_size]
256 diamond 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
3908 Serge 1043
        rep movsb
256 diamond 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
3908 Serge 1051
        rep stosb
256 diamond 1052
        pop     ecx
1053
        shr     ecx, 4
1054
        cmp     ecx, 8
1055
        ja      .end
1056
        push    ecx
3908 Serge 1057
        rep movsb
256 diamond 1058
        pop     ecx
1059
        sub     ecx, 8
1060
        neg     ecx
1061
        cmp     byte [esi-1], 80h
257 diamond 1062
        cmc
256 diamond 1063
        sbb     eax, eax
3908 Serge 1064
        rep stosb
256 diamond 1065
        stc
1066
.end:
1067
        pop     edi ecx eax
1068
        ret
1069
 
1504 diamond 1070
unichar_toupper:
1071
        push    eax
1072
        call    uni2ansi_char
1073
        cmp     al, '_'
1074
        jz      .unk
1075
        add     esp, 4
2465 Serge 1076
        call    char_toupper
1077
        jmp     ansi2uni_char
1078
.unk:
1079
        pop     eax
1080
        ret
1504 diamond 1081
 
257 diamond 1082
ntfs_find_lfn:
3908 Serge 1083
; in: esi+[esp+4] -> name
257 diamond 1084
; out: CF=1 - file not found
3908 Serge 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
257 diamond 1087
.doit2:
3908 Serge 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
257 diamond 1094
        call    ntfs_read_attr
1095
        jnc     @f
1096
.ret:
3908 Serge 1097
        ret     4
257 diamond 1098
@@:
3908 Serge 1099
        xor     eax, eax
1100
        cmp     [ebp+NTFS.ntfs_cur_read], 0x20
257 diamond 1101
        jc      .ret
1102
        pushad
3908 Serge 1103
        mov     esi, [ebp+NTFS.cur_index_buf]
257 diamond 1104
        mov     eax, [esi+14h]
1105
        add     eax, 10h
3908 Serge 1106
        cmp     [ebp+NTFS.ntfs_cur_read], eax
257 diamond 1107
        jae     .readok1
1108
        add     eax, 1FFh
1109
        shr     eax, 9
3908 Serge 1110
        cmp     eax, [ebp+NTFS.cur_index_size]
257 diamond 1111
        ja      @f
1112
.stc_ret:
1113
        popad
1114
        stc
3908 Serge 1115
        ret     4
257 diamond 1116
@@:
1117
; reallocate
1118
        push    eax
3908 Serge 1119
        push    [ebp+NTFS.cur_index_buf]
257 diamond 1120
        call    kernel_free
1121
        pop     eax
3908 Serge 1122
        mov     [ebp+NTFS.cur_index_size], eax
257 diamond 1123
        push    eax
1124
        call    kernel_alloc
1125
        test    eax, eax
1126
        jnz     @f
3908 Serge 1127
        and     [ebp+NTFS.cur_index_size], 0
1128
        and     [ebp+NTFS.cur_index_buf], 0
257 diamond 1129
        jmp     .stc_ret
1130
@@:
3908 Serge 1131
        mov     [ebp+NTFS.cur_index_buf], eax
257 diamond 1132
        popad
1133
        jmp     .doit2
1134
.readok1:
3908 Serge 1135
        mov     edx, [esi+8]    ; subnode_size
1136
        shr     edx, 9
1137
        cmp     edx, [ebp+NTFS.cur_index_size]
257 diamond 1138
        jbe     .ok2
3908 Serge 1139
        push    esi edx
1140
        push    edx
257 diamond 1141
        call    kernel_alloc
3908 Serge 1142
        pop     edx esi
257 diamond 1143
        test    eax, eax
1144
        jz      .stc_ret
1145
        mov     edi, eax
3908 Serge 1146
        mov     ecx, [ebp+NTFS.cur_index_size]
257 diamond 1147
        shl     ecx, 9-2
3908 Serge 1148
        rep movsd
257 diamond 1149
        mov     esi, eax
3908 Serge 1150
        mov     [ebp+NTFS.cur_index_size], edx
1151
        push    esi edx
1152
        push    [ebp+NTFS.cur_index_buf]
257 diamond 1153
        call    kernel_free
3908 Serge 1154
        pop     edx esi
1155
        mov     [ebp+NTFS.cur_index_buf], esi
257 diamond 1156
.ok2:
1157
        add     esi, 10h
1158
        mov     edi, [esp+4]
3908 Serge 1159
; edi -> name, esi -> current index data, edx = subnode size
257 diamond 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
1504 diamond 1171
        call    unichar_toupper
257 diamond 1172
        push    eax
1173
        mov     al, [edi]
1174
        inc     edi
820 diamond 1175
        cmp     al, '/'
1176
        jz      .slash
257 diamond 1177
        call    char_toupper
1504 diamond 1178
        call    ansi2uni_char
1179
        cmp     ax, [esp]
257 diamond 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
820 diamond 1190
.slash:
1191
        pop     eax
1192
        pop     edi
1193
        pop     esi
257 diamond 1194
.subnode:
1195
        test    byte [esi+0Ch], 1
1196
        jz      .notfound
1197
        movzx   eax, word [esi+8]
1198
        mov     eax, [esi+eax-8]
3908 Serge 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]
257 diamond 1204
        mov     esi, eax
3908 Serge 1205
        mov     [ebp+NTFS.ntfs_cur_buf], eax
1206
        push    edx
257 diamond 1207
        call    ntfs_read_attr
3908 Serge 1208
        pop     edx
1209
        mov     eax, edx
257 diamond 1210
        shl     eax, 9
3908 Serge 1211
        cmp     [ebp+NTFS.ntfs_cur_read], eax
257 diamond 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
3908 Serge 1223
        ret     4
257 diamond 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]
3908 Serge 1237
        mov     [ebp+NTFS.ntfs_cur_iRecord], eax
262 diamond 1238
        mov     [esp+1Ch], esi
257 diamond 1239
        mov     [esp+4], edi
1240
        popad
1241
        inc     esi
1242
        cmp     byte [esi-1], 0
1243
        jnz     .doit2
3908 Serge 1244
        cmp     dword [esp+4], 0
521 diamond 1245
        jz      @f
3908 Serge 1246
        mov     esi, [esp+4]
1247
        mov     dword [esp+4], 0
521 diamond 1248
        jmp     .doit2
1249
@@:
3908 Serge 1250
        ret     4
257 diamond 1251
 
256 diamond 1252
;----------------------------------------------------------------
3908 Serge 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:
262 diamond 1260
        cmp     byte [esi], 0
1261
        jnz     @f
256 diamond 1262
        or      ebx, -1
3626 Serge 1263
        movi    eax, ERROR_ACCESS_DENIED
256 diamond 1264
        ret
262 diamond 1265
@@:
3908 Serge 1266
        call    ntfs_lock
1267
        stdcall ntfs_find_lfn, [esp+4]
262 diamond 1268
        jnc     .found
3908 Serge 1269
        call    ntfs_unlock
262 diamond 1270
        or      ebx, -1
3626 Serge 1271
        movi    eax, ERROR_FILE_NOT_FOUND
262 diamond 1272
        ret
1273
.found:
3908 Serge 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
262 diamond 1277
        call    ntfs_read_attr
1278
        jnc     @f
3908 Serge 1279
        call    ntfs_unlock
262 diamond 1280
        or      ebx, -1
3626 Serge 1281
        movi    eax, ERROR_ACCESS_DENIED
262 diamond 1282
        ret
1283
@@:
1284
        pushad
1285
        and     dword [esp+10h], 0
1286
        xor     eax, eax
3908 Serge 1287
        cmp     dword [ebx+8], 0x200
262 diamond 1288
        jb      @f
1289
.eof0:
1290
        popad
1291
        xor     ebx, ebx
1292
.eof:
3626 Serge 1293
        movi    eax, ERROR_END_OF_FILE
3908 Serge 1294
        push    eax
1295
        call    ntfs_unlock
1296
        pop     eax
262 diamond 1297
        ret
1298
@@:
3908 Serge 1299
        mov     ecx, [ebx+12]
1300
        mov     edx, [ebx+16]
1301
        mov     eax, [ebx+4]
262 diamond 1302
        test    eax, 0x1FF
1303
        jz      .alignedstart
1304
        push    edx
3908 Serge 1305
        mov     edx, [ebx+8]
262 diamond 1306
        shrd    eax, edx, 9
1307
        pop     edx
3908 Serge 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
262 diamond 1312
        call    ntfs_read_attr.continue
3908 Serge 1313
        mov     eax, [ebx+4]
262 diamond 1314
        and     eax, 0x1FF
3908 Serge 1315
        lea     esi, [ebp+NTFS.ntfs_bitmap_buf+eax]
1316
        sub     eax, [ebp+NTFS.ntfs_cur_read]
262 diamond 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
3908 Serge 1326
        rep movsb
262 diamond 1327
        mov     edx, edi
1328
        pop     ecx
1329
        sub     ecx, [esp+10h]
1330
        jnz     @f
1331
.retok:
1332
        popad
3908 Serge 1333
        call    ntfs_unlock
262 diamond 1334
        xor     eax, eax
1335
        ret
1336
@@:
3908 Serge 1337
        cmp     [ebp+NTFS.ntfs_cur_read], 0x200
262 diamond 1338
        jz      .alignedstart
1339
.eof_ebx:
1340
        popad
1341
        jmp     .eof
1342
.alignedstart:
3908 Serge 1343
        mov     eax, [ebx+4]
262 diamond 1344
        push    edx
3908 Serge 1345
        mov     edx, [ebx+8]
262 diamond 1346
        add     eax, 511
1347
        adc     edx, 0
1348
        shrd    eax, edx, 9
1349
        pop     edx
1350
.zero1:
3908 Serge 1351
        mov     [ebp+NTFS.ntfs_cur_offs], eax
1352
        mov     [ebp+NTFS.ntfs_cur_buf], edx
262 diamond 1353
        mov     eax, ecx
1354
        shr     eax, 9
3908 Serge 1355
        mov     [ebp+NTFS.ntfs_cur_size], eax
1356
        add     eax, [ebp+NTFS.ntfs_cur_offs]
262 diamond 1357
        push    eax
1358
        call    ntfs_read_attr.continue
3908 Serge 1359
        pop     [ebp+NTFS.ntfs_cur_offs]
1360
        mov     eax, [ebp+NTFS.ntfs_cur_read]
262 diamond 1361
        add     [esp+10h], eax
1362
        mov     eax, ecx
1363
        and     eax, not 0x1FF
3908 Serge 1364
        cmp     [ebp+NTFS.ntfs_cur_read], eax
262 diamond 1365
        jnz     .eof_ebx
1366
        and     ecx, 0x1FF
1367
        jz      .retok
3908 Serge 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
262 diamond 1372
        call    ntfs_read_attr.continue
3908 Serge 1373
        cmp     [ebp+NTFS.ntfs_cur_read], ecx
262 diamond 1374
        jb      @f
3908 Serge 1375
        mov     [ebp+NTFS.ntfs_cur_read], ecx
262 diamond 1376
@@:
3908 Serge 1377
        xchg    ecx, [ebp+NTFS.ntfs_cur_read]
262 diamond 1378
        push    ecx
1379
        mov     edi, edx
3908 Serge 1380
        lea     esi, [ebp+NTFS.ntfs_bitmap_buf]
262 diamond 1381
        add     [esp+10h+4], ecx
3908 Serge 1382
        rep movsb
262 diamond 1383
        pop     ecx
1384
        xor     eax, eax
3908 Serge 1385
        cmp     ecx, [ebp+NTFS.ntfs_cur_read]
262 diamond 1386
        jz      @f
1387
        mov     al, ERROR_END_OF_FILE
1388
@@:
1389
        mov     [esp+1Ch], eax
3908 Serge 1390
        call    ntfs_unlock
262 diamond 1391
        popad
1392
        ret
256 diamond 1393
 
1394
;----------------------------------------------------------------
3908 Serge 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
256 diamond 1403
        mov     eax, 5          ; root cluster
1404
        cmp     byte [esi], 0
1405
        jz      .doit
3908 Serge 1406
        stdcall ntfs_find_lfn, [esp+4]
257 diamond 1407
        jnc     .doit2
256 diamond 1408
.notfound:
1409
        or      ebx, -1
1410
        push    ERROR_FILE_NOT_FOUND
1411
.pop_ret:
3908 Serge 1412
        call    ntfs_unlock
256 diamond 1413
        pop     eax
1414
        ret
1415
.doit:
3908 Serge 1416
        mov     [ebp+NTFS.ntfs_cur_iRecord], eax
256 diamond 1417
.doit2:
3908 Serge 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
257 diamond 1423
        call    ntfs_read_attr
1424
        jc      .notfound
3908 Serge 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
256 diamond 1431
        call    ntfs_read_attr
1432
        jnc     .ok
3908 Serge 1433
        test    eax, eax
256 diamond 1434
        jz      .notfound
1435
        or      ebx, -1
1436
        push    11
1437
        jmp     .pop_ret
1438
.ok:
3908 Serge 1439
        cmp     [ebp+NTFS.ntfs_cur_read], 0x20
256 diamond 1440
        jae     @f
1441
        or      ebx, -1
1442
.fserr:
1443
        push    ERROR_FAT_TABLE
1444
        jmp     .pop_ret
1445
@@:
1446
        pushad
3908 Serge 1447
        mov     esi, [ebp+NTFS.cur_index_buf]
256 diamond 1448
        mov     eax, [esi+14h]
1449
        add     eax, 10h
3908 Serge 1450
        cmp     [ebp+NTFS.ntfs_cur_read], eax
256 diamond 1451
        jae     .readok1
1452
        add     eax, 1FFh
1453
        shr     eax, 9
3908 Serge 1454
        cmp     eax, [ebp+NTFS.cur_index_size]
256 diamond 1455
        ja      @f
1456
        popad
1457
        jmp     .fserr
1458
@@:
1459
; reallocate
1460
        push    eax
3908 Serge 1461
        push    [ebp+NTFS.cur_index_buf]
256 diamond 1462
        call    kernel_free
1463
        pop     eax
3908 Serge 1464
        mov     [ebp+NTFS.cur_index_size], eax
256 diamond 1465
        push    eax
1466
        call    kernel_alloc
1467
        test    eax, eax
1468
        jnz     @f
3908 Serge 1469
        and     [ebp+NTFS.cur_index_size], 0
1470
        and     [ebp+NTFS.cur_index_buf], 0
256 diamond 1471
.nomem:
3908 Serge 1472
        call    ntfs_unlock
256 diamond 1473
        popad
1474
        or      ebx, -1
3626 Serge 1475
        movi    eax, 12
256 diamond 1476
        ret
1477
@@:
3908 Serge 1478
        mov     [ebp+NTFS.cur_index_buf], eax
256 diamond 1479
        popad
1480
        jmp     .doit2
1481
.readok1:
3908 Serge 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]
256 diamond 1486
        jbe     .ok2
3908 Serge 1487
        push    esi edx
1488
        push    edx
256 diamond 1489
        call    kernel_alloc
3908 Serge 1490
        pop     edx esi
256 diamond 1491
        test    eax, eax
1492
        jz      .nomem
1493
        mov     edi, eax
3908 Serge 1494
        mov     ecx, [ebp+NTFS.cur_index_size]
256 diamond 1495
        shl     ecx, 9-2
3908 Serge 1496
        rep movsd
256 diamond 1497
        mov     esi, eax
3908 Serge 1498
        mov     [ebp+NTFS.cur_index_size], edx
1499
        push    [ebp+NTFS.cur_index_buf]
256 diamond 1500
        call    kernel_free
3908 Serge 1501
        mov     [ebp+NTFS.cur_index_buf], esi
256 diamond 1502
.ok2:
1503
        add     esi, 10h
3908 Serge 1504
        mov     edx, [ebx+16]
1505
        push    dword [ebx+8]   ; read ANSI/UNICODE name
256 diamond 1506
; init header
1507
        mov     edi, edx
1508
        mov     ecx, 32/4
1509
        xor     eax, eax
3908 Serge 1510
        rep stosd
256 diamond 1511
        mov     byte [edx], 1   ; version
3908 Serge 1512
        mov     ecx, [ebx+12]
1513
        mov     ebx, [ebx+4]
256 diamond 1514
        push    edx
1515
        mov     edx, esp
3908 Serge 1516
; edi -> BDFE, esi -> current index data, ebx = first wanted block,
256 diamond 1517
; ecx = number of blocks to read
1518
; edx -> parameters block: dd , dd 
3908 Serge 1519
        cmp     [ebp+NTFS.ntfs_cur_iRecord], 5
257 diamond 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:
256 diamond 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
3908 Serge 1541
        lea     edi, [ebp+NTFS.ntfs_bitmap_buf]
1542
        mov     [ebp+NTFS.ntfs_cur_buf], edi
256 diamond 1543
        mov     ecx, 0x400/4
1544
        xor     eax, eax
3908 Serge 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
256 diamond 1549
        call    ntfs_read_attr
1550
        pop     edi ecx
1551
        push    0       ; save offset in $BITMAP attribute
3908 Serge 1552
        and     [ebp+NTFS.ntfs_cur_offs], 0
256 diamond 1553
.dumploop:
3908 Serge 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]
256 diamond 1558
        mov     esi, eax
3908 Serge 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
256 diamond 1564
        call    ntfs_read_attr
3908 Serge 1565
        pop     [ebp+NTFS.ntfs_cur_offs]
1566
        mov     eax, [ebp+NTFS.cur_subnode_size]
256 diamond 1567
        shl     eax, 9
3908 Serge 1568
        cmp     [ebp+NTFS.ntfs_cur_read], eax
256 diamond 1569
        jnz     .done
1570
        push    eax
3908 Serge 1571
        mov     eax, [ebp+NTFS.ntfs_cur_offs]
256 diamond 1572
        and     eax, 0x400*8-1
3908 Serge 1573
        bt      dword [ebp+NTFS.ntfs_bitmap_buf], eax
256 diamond 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:
3908 Serge 1593
        inc     [ebp+NTFS.ntfs_cur_offs]
1594
        test    [ebp+NTFS.ntfs_cur_offs], 0x400*8-1
256 diamond 1595
        jnz     .dumploop
3908 Serge 1596
        mov     [ebp+NTFS.ntfs_cur_attr], 0xB0
256 diamond 1597
        push    ecx edi
3908 Serge 1598
        lea     edi, [ebp+NTFS.ntfs_bitmap_buf]
1599
        mov     [ebp+NTFS.ntfs_cur_buf], edi
256 diamond 1600
        mov     ecx, 0x400/4
1601
        xor     eax, eax
3908 Serge 1602
        rep stosd
256 diamond 1603
        pop     edi ecx
1604
        pop     eax
3908 Serge 1605
        push    [ebp+NTFS.ntfs_cur_offs]
256 diamond 1606
        inc     eax
3908 Serge 1607
        mov     [ebp+NTFS.ntfs_cur_offs], eax
1608
        mov     [ebp+NTFS.ntfs_cur_size], 2
256 diamond 1609
        push    eax
1610
        call    ntfs_read_attr
1611
        pop     eax
3908 Serge 1612
        pop     [ebp+NTFS.ntfs_cur_offs]
256 diamond 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
3908 Serge 1627
        call    ntfs_unlock
256 diamond 1628
        popad
1629
        ret
1630
 
257 diamond 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
3908 Serge 1647
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf]
1648
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+4]
257 diamond 1649
        call    ntfs_datetime_to_bdfe
3908 Serge 1650
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf+0x18]
1651
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+0x1C]
257 diamond 1652
        call    ntfs_datetime_to_bdfe
3908 Serge 1653
        mov     eax, dword [ebp+NTFS.ntfs_bitmap_buf+8]
1654
        mov     edx, dword [ebp+NTFS.ntfs_bitmap_buf+0xC]
257 diamond 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
3908 Serge 1665
        rep stosw
257 diamond 1666
        pop     ecx
1667
        xor     eax, eax
1668
        stosw
1669
        pop     edi
1670
        add     edi, 520
1671
        ret
1672
@@:
3908 Serge 1673
        rep stosb
257 diamond 1674
        pop     ecx
1675
        xor     eax, eax
1676
        stosb
1677
        pop     edi
1678
        add     edi, 264
1679
.ret:
1680
        ret
1681
 
256 diamond 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
262 diamond 1698
        call    ntfs_direntry_to_bdfe
256 diamond 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
3908 Serge 1705
        rep movsd
256 diamond 1706
        adc     ecx, ecx
3908 Serge 1707
        rep movsw
256 diamond 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
 
262 diamond 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
 
256 diamond 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]
2465 Serge 1777
        pop     edx
1400 turbanoff 1778
    .sec:
256 diamond 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
;----------------------------------------------------------------
3908 Serge 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:
256 diamond 1871
        xor     ebx, ebx
1872
        mov     eax, ERROR_UNSUPPORTED_FS
1873
        ret
1874
 
1875
;----------------------------------------------------------------
3908 Serge 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:
256 diamond 1883
        xor     ebx, ebx
1884
        mov     eax, ERROR_UNSUPPORTED_FS
1885
        ret
1886
 
3908 Serge 1887
ntfs_SetFileEnd:
1888
ntfs_SetFileInfo:
1889
ntfs_Delete:
256 diamond 1890
        mov     eax, ERROR_UNSUPPORTED_FS
1891
        ret
1892
 
3908 Serge 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:
262 diamond 1901
        cmp     byte [esi], 0
1902
        jnz     @f
3626 Serge 1903
        movi    eax, 2
256 diamond 1904
        ret
262 diamond 1905
@@:
3908 Serge 1906
        call    ntfs_lock
1907
        stdcall ntfs_find_lfn, [esp+4]
262 diamond 1908
        jnc     .doit
3908 Serge 1909
        test    eax, eax
3626 Serge 1910
        movi    eax, ERROR_FILE_NOT_FOUND
262 diamond 1911
        jz      @f
1912
        mov     al, 11
1913
@@:
3908 Serge 1914
        push    eax
1915
        call    ntfs_unlock
1916
        pop     eax
262 diamond 1917
        ret
1918
.doit:
1919
        push    esi edi
1920
        mov     esi, eax
3908 Serge 1921
        mov     edi, [ebx+16]
262 diamond 1922
        xor     eax, eax
1923
        call    ntfs_direntry_to_bdfe
1924
        pop     edi esi
3908 Serge 1925
        call    ntfs_unlock
262 diamond 1926
        xor     eax, eax
2465 Serge 1927
        ret
1928