Subversion Repositories Kolibri OS

Rev

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

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