Subversion Repositories Kolibri OS

Rev

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

  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.  
  8. $Revision: 5201 $
  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
  155.         cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
  156.         jnz     .nope
  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 <output>, dd <flags>
  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.  
  1929.