Subversion Repositories Kolibri OS

Rev

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

  1. $Revision: 467 $
  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->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.         ret
  1094.  
  1095. ;----------------------------------------------------------------
  1096. ;
  1097. ;  ntfs_HdRead - read NTFS hard disk
  1098. ;
  1099. ;  esi  points to filename
  1100. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1101. ;       may be ebx=0 - start from first byte
  1102. ;  ecx  number of bytes to read, 0+
  1103. ;  edx  mem location to return data
  1104. ;
  1105. ;  ret ebx = bytes read or 0xffffffff file not found
  1106. ;      eax = 0 ok read or other = errormsg
  1107. ;
  1108. ;--------------------------------------------------------------
  1109. ntfs_HdRead:
  1110.         cmp     byte [esi], 0
  1111.         jnz     @f
  1112.         or      ebx, -1
  1113.         push    ERROR_ACCESS_DENIED
  1114.         pop     eax
  1115.         ret
  1116. @@:
  1117.         call    ntfs_find_lfn
  1118.         jnc     .found
  1119.         or      ebx, -1
  1120.         push    ERROR_FILE_NOT_FOUND
  1121.         pop     eax
  1122.         ret
  1123. .found:
  1124.         mov     [ntfs_cur_attr], 0x80   ; $DATA
  1125.         and     [ntfs_cur_offs], 0
  1126.         and     [ntfs_cur_size], 0
  1127.         call    ntfs_read_attr
  1128.         jnc     @f
  1129.         or      ebx, -1
  1130.         push    ERROR_ACCESS_DENIED
  1131.         pop     eax
  1132.         ret
  1133. @@:
  1134.         pushad
  1135.         and     dword [esp+10h], 0
  1136.         xor     eax, eax
  1137.         test    ebx, ebx
  1138.         jz      .zero1
  1139.         cmp     dword [ebx+4], 0x200
  1140.         jb      @f
  1141. .eof0:
  1142.         popad
  1143.         xor     ebx, ebx
  1144. .eof:
  1145.         push    ERROR_END_OF_FILE
  1146.         pop     eax
  1147.         ret
  1148. @@:
  1149.         mov     eax, [ebx]
  1150.         test    eax, 0x1FF
  1151.         jz      .alignedstart
  1152.         push    edx
  1153.         mov     edx, [ebx+4]
  1154.         shrd    eax, edx, 9
  1155.         pop     edx
  1156.         mov     [ntfs_cur_offs], eax
  1157.         mov     [ntfs_cur_size], 1
  1158.         mov     [ntfs_cur_buf], ntfs_bitmap_buf
  1159.         call    ntfs_read_attr.continue
  1160.         mov     eax, [ebx]
  1161.         and     eax, 0x1FF
  1162.         lea     esi, [ntfs_bitmap_buf+eax]
  1163.         sub     eax, [ntfs_cur_read]
  1164.         jae     .eof0
  1165.         neg     eax
  1166.         push    ecx
  1167.         cmp     ecx, eax
  1168.         jb      @f
  1169.         mov     ecx, eax
  1170. @@:
  1171.         mov     [esp+10h+4], ecx
  1172.         mov     edi, edx
  1173.         rep     movsb
  1174.         mov     edx, edi
  1175.         pop     ecx
  1176.         sub     ecx, [esp+10h]
  1177.         jnz     @f
  1178. .retok:
  1179.         popad
  1180.         xor     eax, eax
  1181.         ret
  1182. @@:
  1183.         cmp     [ntfs_cur_read], 0x200
  1184.         jz      .alignedstart
  1185. .eof_ebx:
  1186.         popad
  1187.         jmp     .eof
  1188. .alignedstart:
  1189.         mov     eax, [ebx]
  1190.         push    edx
  1191.         mov     edx, [ebx+4]
  1192.         add     eax, 511
  1193.         adc     edx, 0
  1194.         shrd    eax, edx, 9
  1195.         pop     edx
  1196. .zero1:
  1197.         mov     [ntfs_cur_offs], eax
  1198.         mov     [ntfs_cur_buf], edx
  1199.         mov     eax, ecx
  1200.         shr     eax, 9
  1201.         mov     [ntfs_cur_size], eax
  1202.         add     eax, [ntfs_cur_offs]
  1203.         push    eax
  1204.         call    ntfs_read_attr.continue
  1205.         pop     [ntfs_cur_offs]
  1206.         mov     eax, [ntfs_cur_read]
  1207.         add     [esp+10h], eax
  1208.         mov     eax, ecx
  1209.         and     eax, not 0x1FF
  1210.         cmp     [ntfs_cur_read], eax
  1211.         jnz     .eof_ebx
  1212.         and     ecx, 0x1FF
  1213.         jz      .retok
  1214.         add     edx, [ntfs_cur_read]
  1215.         mov     [ntfs_cur_size], 1
  1216.         mov     [ntfs_cur_buf], ntfs_bitmap_buf
  1217.         call    ntfs_read_attr.continue
  1218.         cmp     [ntfs_cur_read], ecx
  1219.         jb      @f
  1220.         mov     [ntfs_cur_read], ecx
  1221. @@:
  1222.         xchg    ecx, [ntfs_cur_read]
  1223.         push    ecx
  1224.         mov     edi, edx
  1225.         mov     esi, ntfs_bitmap_buf
  1226.         add     [esp+10h+4], ecx
  1227.         rep     movsb
  1228.         pop     ecx
  1229.         xor     eax, eax
  1230.         cmp     ecx, [ntfs_cur_read]
  1231.         jz      @f
  1232.         mov     al, ERROR_END_OF_FILE
  1233. @@:
  1234.         mov     [esp+1Ch], eax
  1235.         popad
  1236.         ret
  1237.  
  1238. ;----------------------------------------------------------------
  1239. ;
  1240. ;  ntfs_HdReadFolder - read NTFS hard disk folder
  1241. ;
  1242. ;  esi  points to filename
  1243. ;  ebx  pointer to structure 32-bit number = first wanted block, 0+
  1244. ;                          & flags (bitfields)
  1245. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  1246. ;  ecx  number of blocks to read, 0+
  1247. ;  edx  mem location to return data
  1248. ;
  1249. ;  ret ebx = blocks read or 0xffffffff folder not found
  1250. ;      eax = 0 ok read or other = errormsg
  1251. ;
  1252. ;--------------------------------------------------------------
  1253. ntfs_HdReadFolder:
  1254.         mov     eax, 5          ; root cluster
  1255.         cmp     byte [esi], 0
  1256.         jz      .doit
  1257.         call    ntfs_find_lfn
  1258.         jnc     .doit2
  1259. .notfound:
  1260.         or      ebx, -1
  1261.         push    ERROR_FILE_NOT_FOUND
  1262. .pop_ret:
  1263.         pop     eax
  1264.         ret
  1265. .doit:
  1266.         mov     [ntfs_cur_iRecord], eax
  1267. .doit2:
  1268.         mov     [ntfs_cur_attr], 0x10   ; $STANDARD_INFORMATION
  1269.         and     [ntfs_cur_offs], 0
  1270.         mov     [ntfs_cur_size], 1
  1271.         mov     [ntfs_cur_buf], ntfs_bitmap_buf
  1272.         call    ntfs_read_attr
  1273.         jc      .notfound
  1274.         mov     [ntfs_cur_attr], 0x90   ; $INDEX_ROOT
  1275.         and     [ntfs_cur_offs], 0
  1276.         mov     eax, [ntfs_data.cur_index_size]
  1277.         mov     [ntfs_cur_size], eax
  1278.         mov     eax, [ntfs_data.cur_index_buf]
  1279.         mov     [ntfs_cur_buf], eax
  1280.         call    ntfs_read_attr
  1281.         jnc     .ok
  1282.         cmp     [hd_error], 0
  1283.         jz      .notfound
  1284.         or      ebx, -1
  1285.         push    11
  1286.         jmp     .pop_ret
  1287. .ok:
  1288.         cmp     [ntfs_cur_read], 0x20
  1289.         jae     @f
  1290.         or      ebx, -1
  1291. .fserr:
  1292.         push    ERROR_FAT_TABLE
  1293.         jmp     .pop_ret
  1294. @@:
  1295.         pushad
  1296.         mov     esi, [ntfs_data.cur_index_buf]
  1297.         mov     eax, [esi+14h]
  1298.         add     eax, 10h
  1299.         cmp     [ntfs_cur_read], eax
  1300.         jae     .readok1
  1301.         add     eax, 1FFh
  1302.         shr     eax, 9
  1303.         cmp     eax, [ntfs_data.cur_index_size]
  1304.         ja      @f
  1305.         popad
  1306.         jmp     .fserr
  1307. @@:
  1308. ; reallocate
  1309.         push    eax
  1310.         push    [ntfs_data.cur_index_buf]
  1311.         call    kernel_free
  1312.         pop     eax
  1313.         mov     [ntfs_data.cur_index_size], eax
  1314.         push    eax
  1315.         call    kernel_alloc
  1316.         test    eax, eax
  1317.         jnz     @f
  1318.         and     [ntfs_data.cur_index_size], 0
  1319.         and     [ntfs_data.cur_index_buf], 0
  1320. .nomem:
  1321.         popad
  1322.         or      ebx, -1
  1323.         push    12
  1324.         pop     eax
  1325.         ret
  1326. @@:
  1327.         mov     [ntfs_data.cur_index_buf], eax
  1328.         popad
  1329.         jmp     .doit2
  1330. .readok1:
  1331.         mov     ebp, [esi+8]    ; subnode_size
  1332.         shr     ebp, 9
  1333.         cmp     ebp, [ntfs_data.cur_index_size]
  1334.         jbe     .ok2
  1335.         push    esi ebp
  1336.         push    ebp
  1337.         call    kernel_alloc
  1338.         pop     ebp esi
  1339.         test    eax, eax
  1340.         jz      .nomem
  1341.         mov     edi, eax
  1342.         mov     ecx, [ntfs_data.cur_index_size]
  1343.         shl     ecx, 9-2
  1344.         rep     movsd
  1345.         mov     esi, eax
  1346.         mov     [ntfs_data.cur_index_size], ebp
  1347.         push    esi ebp
  1348.         push    [ntfs_data.cur_index_buf]
  1349.         call    kernel_free
  1350.         pop     ebp esi
  1351.         mov     [ntfs_data.cur_index_buf], esi
  1352. .ok2:
  1353.         add     esi, 10h
  1354.         mov     ebx, [esp+10h]
  1355.         mov     edx, [esp+14h]
  1356.         push    dword [ebx+4]   ; read ANSI/UNICODE name
  1357.         mov     ebx, [ebx]
  1358. ; init header
  1359.         mov     edi, edx
  1360.         mov     ecx, 32/4
  1361.         xor     eax, eax
  1362.         rep     stosd
  1363.         mov     byte [edx], 1   ; version
  1364.         mov     ecx, [esp+4+18h]
  1365.         push    edx
  1366.         mov     edx, esp
  1367. ; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block,
  1368. ; ecx = number of blocks to read
  1369. ; edx -> parameters block: dd <output>, dd <flags>
  1370.         cmp     [ntfs_cur_iRecord], 5
  1371.         jz      .skip_specials
  1372. ; dot and dotdot entries
  1373.         push    esi
  1374.         xor     esi, esi
  1375.         call    .add_special_entry
  1376.         inc     esi
  1377.         call    .add_special_entry
  1378.         pop     esi
  1379. .skip_specials:
  1380. ; at first, dump index root
  1381.         add     esi, [esi]
  1382. .dump_root:
  1383.         test    byte [esi+0Ch], 2
  1384.         jnz     .dump_root_done
  1385.         call    .add_entry
  1386.         movzx   eax, word [esi+8]
  1387.         add     esi, eax
  1388.         jmp     .dump_root
  1389. .dump_root_done:
  1390. ; now dump all subnodes
  1391.         push    ecx edi
  1392.         mov     edi, ntfs_bitmap_buf
  1393.         mov     [ntfs_cur_buf], edi
  1394.         mov     ecx, 0x400/4
  1395.         xor     eax, eax
  1396.         rep     stosd
  1397.         mov     [ntfs_cur_attr], 0xB0   ; $BITMAP
  1398.         and     [ntfs_cur_offs], 0
  1399.         mov     [ntfs_cur_size], 2
  1400.         call    ntfs_read_attr
  1401.         pop     edi ecx
  1402.         push    0       ; save offset in $BITMAP attribute
  1403.         and     [ntfs_cur_offs], 0
  1404. .dumploop:
  1405.         mov     [ntfs_cur_attr], 0xA0
  1406.         mov     [ntfs_cur_size], ebp
  1407.         mov     eax, [ntfs_data.cur_index_buf]
  1408.         mov     esi, eax
  1409.         mov     [ntfs_cur_buf], eax
  1410.         push    [ntfs_cur_offs]
  1411.         mov     eax, [ntfs_cur_offs]
  1412.         imul    eax, ebp
  1413.         mov     [ntfs_cur_offs], eax
  1414.         call    ntfs_read_attr
  1415.         pop     [ntfs_cur_offs]
  1416.         mov     eax, ebp
  1417.         shl     eax, 9
  1418.         cmp     [ntfs_cur_read], eax
  1419.         jnz     .done
  1420.         push    eax
  1421.         mov     eax, [ntfs_cur_offs]
  1422.         and     eax, 0x400*8-1
  1423.         bt      dword [ntfs_bitmap_buf], eax
  1424.         pop     eax
  1425.         jnc     .dump_subnode_done
  1426.         cmp     dword [esi], 'INDX'
  1427.         jnz     .dump_subnode_done
  1428.         push    ebx
  1429.         mov     ebx, esi
  1430.         call    ntfs_restore_usa
  1431.         pop     ebx
  1432.         jc      .dump_subnode_done
  1433.         add     esi, 0x18
  1434.         add     esi, [esi]
  1435. .dump_subnode:
  1436.         test    byte [esi+0Ch], 2
  1437.         jnz     .dump_subnode_done
  1438.         call    .add_entry
  1439.         movzx   eax, word [esi+8]
  1440.         add     esi, eax
  1441.         jmp     .dump_subnode
  1442. .dump_subnode_done:
  1443.         inc     [ntfs_cur_offs]
  1444.         test    [ntfs_cur_offs], 0x400*8-1
  1445.         jnz     .dumploop
  1446.         mov     [ntfs_cur_attr], 0xB0
  1447.         push    ecx edi
  1448.         mov     edi, ntfs_bitmap_buf
  1449.         mov     [ntfs_cur_buf], edi
  1450.         mov     ecx, 0x400/4
  1451.         xor     eax, eax
  1452.         rep     stosd
  1453.         pop     edi ecx
  1454.         pop     eax
  1455.         push    [ntfs_cur_offs]
  1456.         inc     eax
  1457.         mov     [ntfs_cur_offs], eax
  1458.         mov     [ntfs_cur_size], 2
  1459.         push    eax
  1460.         call    ntfs_read_attr
  1461.         pop     eax
  1462.         pop     [ntfs_cur_offs]
  1463.         push    eax
  1464.         jmp     .dumploop
  1465. .done:
  1466.         pop     eax
  1467.         pop     edx
  1468.         mov     ebx, [edx+4]
  1469.         pop     edx
  1470.         xor     eax, eax
  1471.         dec     ecx
  1472.         js      @f
  1473.         mov     al, ERROR_END_OF_FILE
  1474. @@:
  1475.         mov     [esp+1Ch], eax
  1476.         mov     [esp+10h], ebx
  1477.         popad
  1478.         ret
  1479.  
  1480. .add_special_entry:
  1481.         mov     eax, [edx]
  1482.         inc     dword [eax+8]   ; new file found
  1483.         dec     ebx
  1484.         jns     .ret
  1485.         dec     ecx
  1486.         js      .ret
  1487.         inc     dword [eax+4]   ; new file block copied
  1488.         mov     eax, [edx+4]
  1489.         mov     [edi+4], eax
  1490. ;        mov     eax, dword [ntfs_bitmap_buf+0x20]
  1491. ;        or      al, 0x10
  1492.         mov     eax, 0x10
  1493.         stosd
  1494.         scasd
  1495.         push    edx
  1496.         mov     eax, dword [ntfs_bitmap_buf]
  1497.         mov     edx, dword [ntfs_bitmap_buf+4]
  1498.         call    ntfs_datetime_to_bdfe
  1499.         mov     eax, dword [ntfs_bitmap_buf+0x18]
  1500.         mov     edx, dword [ntfs_bitmap_buf+0x1C]
  1501.         call    ntfs_datetime_to_bdfe
  1502.         mov     eax, dword [ntfs_bitmap_buf+8]
  1503.         mov     edx, dword [ntfs_bitmap_buf+0xC]
  1504.         call    ntfs_datetime_to_bdfe
  1505.         pop     edx
  1506.         xor     eax, eax
  1507.         stosd
  1508.         stosd
  1509.         mov     al, '.'
  1510.         push    edi ecx
  1511.         lea     ecx, [esi+1]
  1512.         test    byte [edi-0x24], 1
  1513.         jz      @f
  1514.         rep     stosw
  1515.         pop     ecx
  1516.         xor     eax, eax
  1517.         stosw
  1518.         pop     edi
  1519.         add     edi, 520
  1520.         ret
  1521. @@:
  1522.         rep     stosb
  1523.         pop     ecx
  1524.         xor     eax, eax
  1525.         stosb
  1526.         pop     edi
  1527.         add     edi, 264
  1528. .ret:
  1529.         ret
  1530.  
  1531. .add_entry:
  1532. ; do not return DOS 8.3 names
  1533.         cmp     byte [esi+0x51], 2
  1534.         jz      .ret
  1535. ; do not return system files
  1536. ; ... note that there will be no bad effects if system files also were reported ...
  1537.         cmp     dword [esi], 0x10
  1538.         jb      .ret
  1539.         mov     eax, [edx]
  1540.         inc     dword [eax+8]   ; new file found
  1541.         dec     ebx
  1542.         jns     .ret
  1543.         dec     ecx
  1544.         js      .ret
  1545.         inc     dword [eax+4]   ; new file block copied
  1546.         mov     eax, [edx+4]    ; flags
  1547.         call    ntfs_direntry_to_bdfe
  1548.         push    ecx esi edi
  1549.         movzx   ecx, byte [esi+0x50]
  1550.         add     esi, 0x52
  1551.         test    byte [edi-0x24], 1
  1552.         jz      .ansi
  1553.         shr     ecx, 1
  1554.         rep     movsd
  1555.         adc     ecx, ecx
  1556.         rep     movsw
  1557.         and     word [edi], 0
  1558.         pop     edi
  1559.         add     edi, 520
  1560.         pop     esi ecx
  1561.         ret
  1562. .ansi:
  1563.         jecxz   .skip
  1564. @@:
  1565.         lodsw
  1566.         call    uni2ansi_char
  1567.         stosb
  1568.         loop    @b
  1569. .skip:
  1570.         xor     al, al
  1571.         stosb
  1572.         pop     edi
  1573.         add     edi, 264
  1574.         pop     esi ecx
  1575.         ret
  1576.  
  1577. ntfs_direntry_to_bdfe:
  1578.         mov     [edi+4], eax    ; ANSI/UNICODE name
  1579.         mov     eax, [esi+48h]
  1580.         test    eax, 0x10000000
  1581.         jz      @f
  1582.         and     eax, not 0x10000000
  1583.         or      al, 0x10
  1584. @@:
  1585.         stosd
  1586.         scasd
  1587.         push    edx
  1588.         mov     eax, [esi+0x18]
  1589.         mov     edx, [esi+0x1C]
  1590.         call    ntfs_datetime_to_bdfe
  1591.         mov     eax, [esi+0x30]
  1592.         mov     edx, [esi+0x34]
  1593.         call    ntfs_datetime_to_bdfe
  1594.         mov     eax, [esi+0x20]
  1595.         mov     edx, [esi+0x24]
  1596.         call    ntfs_datetime_to_bdfe
  1597.         pop     edx
  1598.         mov     eax, [esi+0x40]
  1599.         stosd
  1600.         mov     eax, [esi+0x44]
  1601.         stosd
  1602.         ret
  1603.  
  1604. iglobal
  1605. _24             dd      24
  1606. _60             dd      60
  1607. _10000000       dd      10000000
  1608. days400year     dd      365*400+100-4+1
  1609. days100year     dd      365*100+25-1
  1610. days4year       dd      365*4+1
  1611. days1year       dd      365
  1612. months  dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1613. months2 dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1614. _400            dd      400
  1615. _100            dd      100
  1616. endg
  1617.  
  1618. ntfs_datetime_to_bdfe:
  1619. ; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
  1620.         push    eax
  1621.         mov     eax, edx
  1622.         xor     edx, edx
  1623.         div     [_10000000]
  1624.         xchg    eax, [esp]
  1625.         div     [_10000000]
  1626.         pop     edx
  1627. ; edx:eax = number of seconds since January 1, 1601
  1628.         push    eax
  1629.         mov     eax, edx
  1630.         xor     edx, edx
  1631.         div     [_60]
  1632.         xchg    eax, [esp]
  1633.         div     [_60]
  1634.         mov     [edi], dl
  1635.         pop     edx
  1636. ; edx:eax = number of minutes
  1637.         div     [_60]
  1638.         mov     [edi+1], dl
  1639. ; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
  1640.         xor     edx, edx
  1641.         div     [_24]
  1642.         mov     [edi+2], dl
  1643.         mov     [edi+3], byte 0
  1644. ; eax = number of days since January 1, 1601
  1645.         xor     edx, edx
  1646.         div     [days400year]
  1647.         imul    eax, 400
  1648.         add     eax, 1601
  1649.         mov     [edi+6], ax
  1650.         mov     eax, edx
  1651.         xor     edx, edx
  1652.         div     [days100year]
  1653.         cmp     al, 4
  1654.         jnz     @f
  1655.         dec     eax
  1656.         add     edx, [days100year]
  1657. @@:
  1658.         imul    eax, 100
  1659.         add     [edi+6], ax
  1660.         mov     eax, edx
  1661.         xor     edx, edx
  1662.         div     [days4year]
  1663.         shl     eax, 2
  1664.         add     [edi+6], ax
  1665.         mov     eax, edx
  1666.         xor     edx, edx
  1667.         div     [days1year]
  1668.         cmp     al, 4
  1669.         jnz     @f
  1670.         dec     eax
  1671.         add     edx, [days1year]
  1672. @@:
  1673.         add     [edi+6], ax
  1674.         push    esi edx
  1675.         mov     esi, months
  1676.         movzx   eax, word [edi+6]
  1677.         test    al, 3
  1678.         jnz     .noleap
  1679.         xor     edx, edx
  1680.         push    eax
  1681.         div     [_400]
  1682.         pop     eax
  1683.         test    edx, edx
  1684.         jz      .leap
  1685.         xor     edx, edx
  1686.         div     [_100]
  1687.         test    edx, edx
  1688.         jz      .noleap
  1689. .leap:
  1690.         mov     esi, months2
  1691. .noleap:
  1692.         pop     edx
  1693.         xor     eax, eax
  1694.         inc     eax
  1695. @@:
  1696.         sub     edx, [esi]
  1697.         jb      @f
  1698.         add     esi, 4
  1699.         inc     eax
  1700.         jmp     @b
  1701. @@:
  1702.         add     edx, [esi]
  1703.         pop     esi
  1704.         inc     edx
  1705.         mov     [edi+4], dl
  1706.         mov     [edi+5], al
  1707.         add     edi, 8
  1708.         ret
  1709.  
  1710. ;----------------------------------------------------------------
  1711. ;
  1712. ;  ntfs_HdRewrite - write to NTFS hard disk
  1713. ;
  1714. ;  esi  points to filename
  1715. ;  ebx  ignored (reserved)
  1716. ;  ecx  number of bytes to write, 0+
  1717. ;  edx  mem location to data
  1718. ;
  1719. ;  ret ebx = number of written bytes
  1720. ;      eax = 0 ok read or other = errormsg
  1721. ;
  1722. ;--------------------------------------------------------------
  1723. ntfs_HdRewrite:
  1724.         xor     ebx, ebx
  1725.         mov     eax, ERROR_UNSUPPORTED_FS
  1726.         ret
  1727.  
  1728. ;----------------------------------------------------------------
  1729. ;
  1730. ;  ntfs_HdWrite - write to NTFS hard disk
  1731. ;
  1732. ;  esi  points to filename
  1733. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1734. ;       may be ebx=0 - start from first byte
  1735. ;  ecx  number of bytes to write, 0+
  1736. ;  edx  mem location to data
  1737. ;
  1738. ;  ret ebx = bytes written (maybe 0)
  1739. ;      eax = 0 ok write or other = errormsg
  1740. ;
  1741. ;--------------------------------------------------------------
  1742. ntfs_HdWrite:
  1743.         xor     ebx, ebx
  1744.         mov     eax, ERROR_UNSUPPORTED_FS
  1745.         ret
  1746.  
  1747. ;----------------------------------------------------------------
  1748. ;
  1749. ;  ntfs_HdSetFileEnd - set end of file on NTFS hard disk
  1750. ;
  1751. ;  esi  points to filename
  1752. ;  ebx  points to 64-bit number = new file size
  1753. ;  ecx  ignored (reserved)
  1754. ;  edx  ignored (reserved)
  1755. ;
  1756. ;  ret eax = 0 ok or other = errormsg
  1757. ;
  1758. ;--------------------------------------------------------------
  1759. ntfs_HdSetFileEnd:
  1760. ntfs_HdSetFileInfo:
  1761. ;----------------------------------------------------------------
  1762. ;
  1763. ;  ntfs_HdDelete - delete file or empty folder from NTFS hard disk
  1764. ;
  1765. ;  esi  points to filename
  1766. ;
  1767. ;  ret  eax = 0 ok or other = errormsg
  1768. ;
  1769. ;--------------------------------------------------------------
  1770. ntfs_HdDelete:
  1771.         mov     eax, ERROR_UNSUPPORTED_FS
  1772.         ret
  1773.  
  1774. ntfs_HdGetFileInfo:
  1775.         cmp     byte [esi], 0
  1776.         jnz     @f
  1777.         push    2
  1778.         pop     eax
  1779.         ret
  1780. @@:
  1781.         call    ntfs_find_lfn
  1782.         jnc     .doit
  1783.         push    ERROR_FILE_NOT_FOUND
  1784.         pop     eax
  1785.         cmp     [hd_error], 0
  1786.         jz      @f
  1787.         mov     al, 11
  1788. @@:
  1789.         ret
  1790. .doit:
  1791.         push    esi edi
  1792.         mov     esi, eax
  1793.         mov     edi, edx
  1794.         xor     eax, eax
  1795.         call    ntfs_direntry_to_bdfe
  1796.         pop     edi esi
  1797.         xor     eax, eax
  1798.         ret
  1799.