Subversion Repositories Kolibri OS

Rev

Rev 521 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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