Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 983 $
  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      @f
  797.         sub     eax, 0x200
  798.         add     [ntfs_cur_read], eax
  799. @@:
  800.         clc
  801.         ret
  802. .errread2:
  803.         pop     ecx
  804.         add     esp, 10h
  805.         stc
  806.         ret
  807. .break:
  808.         add     esp, 10h        ; CF=0
  809.         mov     [ntfs_bCanContinue], 1
  810.         ret
  811.  
  812. ntfs_read_file_record:
  813. ; in: eax=iRecord
  814. ; out: [ntfs_data.frs_buffer] contains information
  815. ;      eax=0 - failed, eax=1 - success
  816. ; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size]
  817.         push    ecx edx
  818.         mov     ecx, [ntfs_data.frs_size]
  819.         mul     ecx
  820.         shrd    eax, edx, 9
  821.         shr     edx, 9
  822.         jnz     .err
  823.         push    [ntfs_attr_iRecord]
  824.         push    [ntfs_attr_iBaseRecord]
  825.         push    [ntfs_attr_offs]
  826.         push    [ntfs_attr_list]
  827.         push    dword [ntfs_attr_size+4]
  828.         push    dword [ntfs_attr_size]
  829.         push    [ntfs_cur_iRecord]
  830.         push    [ntfs_cur_attr]
  831.         push    [ntfs_cur_offs]
  832.         push    [ntfs_cur_size]
  833.         push    [ntfs_cur_buf]
  834.         push    [ntfs_cur_read]
  835.         mov     [ntfs_cur_attr], 0x80   ; $DATA
  836.         and     [ntfs_cur_iRecord], 0   ; $Mft
  837.         mov     [ntfs_cur_offs], eax
  838.         shr     ecx, 9
  839.         mov     [ntfs_cur_size], ecx
  840.         mov     eax, [ntfs_data.frs_buffer]
  841.         mov     [ntfs_cur_buf], eax
  842.         call    ntfs_read_attr
  843.         mov     eax, [ntfs_cur_read]
  844.         pop     [ntfs_cur_read]
  845.         pop     [ntfs_cur_buf]
  846.         pop     [ntfs_cur_size]
  847.         pop     [ntfs_cur_offs]
  848.         pop     [ntfs_cur_attr]
  849.         pop     [ntfs_cur_iRecord]
  850.         pop     dword [ntfs_attr_size]
  851.         pop     dword [ntfs_attr_size+4]
  852.         pop     [ntfs_attr_list]
  853.         pop     [ntfs_attr_offs]
  854.         pop     [ntfs_attr_iBaseRecord]
  855.         pop     [ntfs_attr_iRecord]
  856.         pop     edx ecx
  857.         jc      .errret
  858.         cmp     eax, [ntfs_data.frs_size]
  859.         jnz     .errret
  860.         mov     eax, [ntfs_data.frs_buffer]
  861.         cmp     dword [eax], 'FILE'
  862.         jnz     .errret
  863.         push    ebx
  864.         mov     ebx, eax
  865.         call    ntfs_restore_usa_frs
  866.         pop     ebx
  867.         setnc   al
  868.         movzx   eax, al
  869. .ret:
  870.         ret
  871. .err:
  872.         pop     edx ecx
  873. .errret:
  874.         xor     eax, eax
  875.         ret
  876.  
  877. ntfs_restore_usa_frs:
  878.         mov     eax, [ntfs_data.frs_size]
  879. ntfs_restore_usa:
  880.         pushad
  881.         shr     eax, 9
  882.         mov     ecx, eax
  883.         inc     eax
  884.         cmp     [ebx+6], ax
  885.         jnz     .err
  886.         movzx   eax, word [ebx+4]
  887.         lea     esi, [eax+ebx]
  888.         lodsw
  889.         mov     edx, eax
  890.         lea     edi, [ebx+0x1FE]
  891. @@:
  892.         cmp     [edi], dx
  893.         jnz     .err
  894.         lodsw
  895.         stosw
  896.         add     edi, 0x1FE
  897.         loop    @b
  898.         popad
  899.         clc
  900.         ret
  901. .err:
  902.         popad
  903.         stc
  904.         ret
  905.  
  906. ntfs_decode_mcb_entry:
  907.         push    eax ecx edi
  908.         lea     edi, [esp+16]
  909.         xor     eax, eax
  910.         lodsb
  911.         test    al, al
  912.         jz      .end
  913.         mov     ecx, eax
  914.         and     ecx, 0xF
  915.         cmp     ecx, 8
  916.         ja      .end
  917.         push    ecx
  918.         rep     movsb
  919.         pop     ecx
  920.         sub     ecx, 8
  921.         neg     ecx
  922.         cmp     byte [esi-1], 80h
  923.         jae     .end
  924.         push    eax
  925.         xor     eax, eax
  926.         rep     stosb
  927.         pop     ecx
  928.         shr     ecx, 4
  929.         cmp     ecx, 8
  930.         ja      .end
  931.         push    ecx
  932.         rep     movsb
  933.         pop     ecx
  934.         sub     ecx, 8
  935.         neg     ecx
  936.         cmp     byte [esi-1], 80h
  937.         cmc
  938.         sbb     eax, eax
  939.         rep     stosb
  940.         stc
  941. .end:
  942.         pop     edi ecx eax
  943.         ret
  944.  
  945. ntfs_find_lfn:
  946. ; in: esi+ebp -> name
  947. ; out: CF=1 - file not found
  948. ;      else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory
  949.         mov     [ntfs_cur_iRecord], 5   ; start parse from root cluster
  950. .doit2:
  951.         mov     [ntfs_cur_attr], 0x90   ; $INDEX_ROOT
  952.         and     [ntfs_cur_offs], 0
  953.         mov     eax, [ntfs_data.cur_index_size]
  954.         mov     [ntfs_cur_size], eax
  955.         mov     eax, [ntfs_data.cur_index_buf]
  956.         mov     [ntfs_cur_buf], eax
  957.         call    ntfs_read_attr
  958.         jnc     @f
  959. .ret:
  960.         ret
  961. @@:
  962.         cmp     [ntfs_cur_read], 0x20
  963.         jc      .ret
  964.         pushad
  965.         mov     esi, [ntfs_data.cur_index_buf]
  966.         mov     eax, [esi+14h]
  967.         add     eax, 10h
  968.         cmp     [ntfs_cur_read], eax
  969.         jae     .readok1
  970.         add     eax, 1FFh
  971.         shr     eax, 9
  972.         cmp     eax, [ntfs_data.cur_index_size]
  973.         ja      @f
  974. .stc_ret:
  975.         popad
  976.         stc
  977.         ret
  978. @@:
  979. ; reallocate
  980.         push    eax
  981.         push    [ntfs_data.cur_index_buf]
  982.         call    kernel_free
  983.         pop     eax
  984.         mov     [ntfs_data.cur_index_size], eax
  985.         push    eax
  986.         call    kernel_alloc
  987.         test    eax, eax
  988.         jnz     @f
  989.         and     [ntfs_data.cur_index_size], 0
  990.         and     [ntfs_data.cur_index_buf], 0
  991.         jmp     .stc_ret
  992. @@:
  993.         mov     [ntfs_data.cur_index_buf], eax
  994.         popad
  995.         jmp     .doit2
  996. .readok1:
  997.         mov     ebp, [esi+8]    ; subnode_size
  998.         shr     ebp, 9
  999.         cmp     ebp, [ntfs_data.cur_index_size]
  1000.         jbe     .ok2
  1001.         push    esi ebp
  1002.         push    ebp
  1003.         call    kernel_alloc
  1004.         pop     ebp esi
  1005.         test    eax, eax
  1006.         jz      .stc_ret
  1007.         mov     edi, eax
  1008.         mov     ecx, [ntfs_data.cur_index_size]
  1009.         shl     ecx, 9-2
  1010.         rep     movsd
  1011.         mov     esi, eax
  1012.         mov     [ntfs_data.cur_index_size], ebp
  1013.         push    esi ebp
  1014.         push    [ntfs_data.cur_index_buf]
  1015.         call    kernel_free
  1016.         pop     ebp esi
  1017.         mov     [ntfs_data.cur_index_buf], esi
  1018. .ok2:
  1019.         add     esi, 10h
  1020.         mov     edi, [esp+4]
  1021. ; edi -> name, esi -> current index data, ebp = subnode size
  1022. .scanloop:
  1023.         add     esi, [esi]
  1024. .scanloopint:
  1025.         test    byte [esi+0Ch], 2
  1026.         jnz     .subnode
  1027.         push    esi
  1028.         add     esi, 0x52
  1029.         movzx   ecx, byte [esi-2]
  1030.         push    edi
  1031. @@:
  1032.         lodsw
  1033.         call    uni2ansi_char
  1034.         call    char_toupper
  1035.         push    eax
  1036.         mov     al, [edi]
  1037.         inc     edi
  1038.         cmp     al, '/'
  1039.         jz      .slash
  1040.         call    char_toupper
  1041.         cmp     al, [esp]
  1042.         pop     eax
  1043.         loopz   @b
  1044.         jz      .found
  1045.         pop     edi
  1046.         pop     esi
  1047.         jb      .subnode
  1048. .scanloopcont:
  1049.         movzx   eax, word [esi+8]
  1050.         add     esi, eax
  1051.         jmp     .scanloopint
  1052. .slash:
  1053.         pop     eax
  1054.         pop     edi
  1055.         pop     esi
  1056. .subnode:
  1057.         test    byte [esi+0Ch], 1
  1058.         jz      .notfound
  1059.         movzx   eax, word [esi+8]
  1060.         mov     eax, [esi+eax-8]
  1061.         mul     [ntfs_data.sectors_per_cluster]
  1062.         mov     [ntfs_cur_offs], eax
  1063.         mov     [ntfs_cur_attr], 0xA0   ; $INDEX_ALLOCATION
  1064.         mov     [ntfs_cur_size], ebp
  1065.         mov     eax, [ntfs_data.cur_index_buf]
  1066.         mov     esi, eax
  1067.         mov     [ntfs_cur_buf], eax
  1068.         call    ntfs_read_attr
  1069.         mov     eax, ebp
  1070.         shl     eax, 9
  1071.         cmp     [ntfs_cur_read], eax
  1072.         jnz     .notfound
  1073.         cmp     dword [esi], 'INDX'
  1074.         jnz     .notfound
  1075.         mov     ebx, esi
  1076.         call    ntfs_restore_usa
  1077.         jc      .notfound
  1078.         add     esi, 0x18
  1079.         jmp     .scanloop
  1080. .notfound:
  1081.         popad
  1082.         stc
  1083.         ret
  1084. .found:
  1085.         cmp     byte [edi], 0
  1086.         jz      .done
  1087.         cmp     byte [edi], '/'
  1088.         jz      .next
  1089.         pop     edi
  1090.         pop     esi
  1091.         jmp     .scanloopcont
  1092. .done:
  1093. .next:
  1094.         pop     esi
  1095.         pop     esi
  1096.         mov     eax, [esi]
  1097.         mov     [ntfs_cur_iRecord], eax
  1098.         mov     [esp+1Ch], esi
  1099.         mov     [esp+4], edi
  1100.         popad
  1101.         inc     esi
  1102.         cmp     byte [esi-1], 0
  1103.         jnz     .doit2
  1104.         test    ebp, ebp
  1105.         jz      @f
  1106.         mov     esi, ebp
  1107.         xor     ebp, ebp
  1108.         jmp     .doit2
  1109. @@:
  1110.         ret
  1111.  
  1112. ;----------------------------------------------------------------
  1113. ;
  1114. ;  ntfs_HdRead - read NTFS hard disk
  1115. ;
  1116. ;  esi  points to filename
  1117. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1118. ;       may be ebx=0 - start from first byte
  1119. ;  ecx  number of bytes to read, 0+
  1120. ;  edx  mem location to return data
  1121. ;
  1122. ;  ret ebx = bytes read or 0xffffffff file not found
  1123. ;      eax = 0 ok read or other = errormsg
  1124. ;
  1125. ;--------------------------------------------------------------
  1126. ntfs_HdRead:
  1127.         cmp     byte [esi], 0
  1128.         jnz     @f
  1129.         or      ebx, -1
  1130.         push    ERROR_ACCESS_DENIED
  1131.         pop     eax
  1132.         ret
  1133. @@:
  1134.         call    ntfs_find_lfn
  1135.         jnc     .found
  1136.         or      ebx, -1
  1137.         push    ERROR_FILE_NOT_FOUND
  1138.         pop     eax
  1139.         ret
  1140. .found:
  1141.         mov     [ntfs_cur_attr], 0x80   ; $DATA
  1142.         and     [ntfs_cur_offs], 0
  1143.         and     [ntfs_cur_size], 0
  1144.         call    ntfs_read_attr
  1145.         jnc     @f
  1146.         or      ebx, -1
  1147.         push    ERROR_ACCESS_DENIED
  1148.         pop     eax
  1149.         ret
  1150. @@:
  1151.         pushad
  1152.         and     dword [esp+10h], 0
  1153.         xor     eax, eax
  1154.         test    ebx, ebx
  1155.         jz      .zero1
  1156.         cmp     dword [ebx+4], 0x200
  1157.         jb      @f
  1158. .eof0:
  1159.         popad
  1160.         xor     ebx, ebx
  1161. .eof:
  1162.         push    ERROR_END_OF_FILE
  1163.         pop     eax
  1164.         ret
  1165. @@:
  1166.         mov     eax, [ebx]
  1167.         test    eax, 0x1FF
  1168.         jz      .alignedstart
  1169.         push    edx
  1170.         mov     edx, [ebx+4]
  1171.         shrd    eax, edx, 9
  1172.         pop     edx
  1173.         mov     [ntfs_cur_offs], eax
  1174.         mov     [ntfs_cur_size], 1
  1175.         mov     [ntfs_cur_buf], ntfs_bitmap_buf
  1176.         call    ntfs_read_attr.continue
  1177.         mov     eax, [ebx]
  1178.         and     eax, 0x1FF
  1179.         lea     esi, [ntfs_bitmap_buf+eax]
  1180.         sub     eax, [ntfs_cur_read]
  1181.         jae     .eof0
  1182.         neg     eax
  1183.         push    ecx
  1184.         cmp     ecx, eax
  1185.         jb      @f
  1186.         mov     ecx, eax
  1187. @@:
  1188.         mov     [esp+10h+4], ecx
  1189.         mov     edi, edx
  1190.         rep     movsb
  1191.         mov     edx, edi
  1192.         pop     ecx
  1193.         sub     ecx, [esp+10h]
  1194.         jnz     @f
  1195. .retok:
  1196.         popad
  1197.         xor     eax, eax
  1198.         ret
  1199. @@:
  1200.         cmp     [ntfs_cur_read], 0x200
  1201.         jz      .alignedstart
  1202. .eof_ebx:
  1203.         popad
  1204.         jmp     .eof
  1205. .alignedstart:
  1206.         mov     eax, [ebx]
  1207.         push    edx
  1208.         mov     edx, [ebx+4]
  1209.         add     eax, 511
  1210.         adc     edx, 0
  1211.         shrd    eax, edx, 9
  1212.         pop     edx
  1213. .zero1:
  1214.         mov     [ntfs_cur_offs], eax
  1215.         mov     [ntfs_cur_buf], edx
  1216.         mov     eax, ecx
  1217.         shr     eax, 9
  1218.         mov     [ntfs_cur_size], eax
  1219.         add     eax, [ntfs_cur_offs]
  1220.         push    eax
  1221.         call    ntfs_read_attr.continue
  1222.         pop     [ntfs_cur_offs]
  1223.         mov     eax, [ntfs_cur_read]
  1224.         add     [esp+10h], eax
  1225.         mov     eax, ecx
  1226.         and     eax, not 0x1FF
  1227.         cmp     [ntfs_cur_read], eax
  1228.         jnz     .eof_ebx
  1229.         and     ecx, 0x1FF
  1230.         jz      .retok
  1231.         add     edx, [ntfs_cur_read]
  1232.         mov     [ntfs_cur_size], 1
  1233.         mov     [ntfs_cur_buf], ntfs_bitmap_buf
  1234.         call    ntfs_read_attr.continue
  1235.         cmp     [ntfs_cur_read], ecx
  1236.         jb      @f
  1237.         mov     [ntfs_cur_read], ecx
  1238. @@:
  1239.         xchg    ecx, [ntfs_cur_read]
  1240.         push    ecx
  1241.         mov     edi, edx
  1242.         mov     esi, ntfs_bitmap_buf
  1243.         add     [esp+10h+4], ecx
  1244.         rep     movsb
  1245.         pop     ecx
  1246.         xor     eax, eax
  1247.         cmp     ecx, [ntfs_cur_read]
  1248.         jz      @f
  1249.         mov     al, ERROR_END_OF_FILE
  1250. @@:
  1251.         mov     [esp+1Ch], eax
  1252.         popad
  1253.         ret
  1254.  
  1255. ;----------------------------------------------------------------
  1256. ;
  1257. ;  ntfs_HdReadFolder - read NTFS hard disk folder
  1258. ;
  1259. ;  esi  points to filename
  1260. ;  ebx  pointer to structure 32-bit number = first wanted block, 0+
  1261. ;                          & flags (bitfields)
  1262. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  1263. ;  ecx  number of blocks to read, 0+
  1264. ;  edx  mem location to return data
  1265. ;
  1266. ;  ret ebx = blocks read or 0xffffffff folder not found
  1267. ;      eax = 0 ok read or other = errormsg
  1268. ;
  1269. ;--------------------------------------------------------------
  1270. ntfs_HdReadFolder:
  1271.         mov     eax, 5          ; root cluster
  1272.         cmp     byte [esi], 0
  1273.         jz      .doit
  1274.         call    ntfs_find_lfn
  1275.         jnc     .doit2
  1276. .notfound:
  1277.         or      ebx, -1
  1278.         push    ERROR_FILE_NOT_FOUND
  1279. .pop_ret:
  1280.         pop     eax
  1281.         ret
  1282. .doit:
  1283.         mov     [ntfs_cur_iRecord], eax
  1284. .doit2:
  1285.         mov     [ntfs_cur_attr], 0x10   ; $STANDARD_INFORMATION
  1286.         and     [ntfs_cur_offs], 0
  1287.         mov     [ntfs_cur_size], 1
  1288.         mov     [ntfs_cur_buf], ntfs_bitmap_buf
  1289.         call    ntfs_read_attr
  1290.         jc      .notfound
  1291.         mov     [ntfs_cur_attr], 0x90   ; $INDEX_ROOT
  1292.         and     [ntfs_cur_offs], 0
  1293.         mov     eax, [ntfs_data.cur_index_size]
  1294.         mov     [ntfs_cur_size], eax
  1295.         mov     eax, [ntfs_data.cur_index_buf]
  1296.         mov     [ntfs_cur_buf], eax
  1297.         call    ntfs_read_attr
  1298.         jnc     .ok
  1299.         cmp     [hd_error], 0
  1300.         jz      .notfound
  1301.         or      ebx, -1
  1302.         push    11
  1303.         jmp     .pop_ret
  1304. .ok:
  1305.         cmp     [ntfs_cur_read], 0x20
  1306.         jae     @f
  1307.         or      ebx, -1
  1308. .fserr:
  1309.         push    ERROR_FAT_TABLE
  1310.         jmp     .pop_ret
  1311. @@:
  1312.         pushad
  1313.         mov     esi, [ntfs_data.cur_index_buf]
  1314.         mov     eax, [esi+14h]
  1315.         add     eax, 10h
  1316.         cmp     [ntfs_cur_read], eax
  1317.         jae     .readok1
  1318.         add     eax, 1FFh
  1319.         shr     eax, 9
  1320.         cmp     eax, [ntfs_data.cur_index_size]
  1321.         ja      @f
  1322.         popad
  1323.         jmp     .fserr
  1324. @@:
  1325. ; reallocate
  1326.         push    eax
  1327.         push    [ntfs_data.cur_index_buf]
  1328.         call    kernel_free
  1329.         pop     eax
  1330.         mov     [ntfs_data.cur_index_size], eax
  1331.         push    eax
  1332.         call    kernel_alloc
  1333.         test    eax, eax
  1334.         jnz     @f
  1335.         and     [ntfs_data.cur_index_size], 0
  1336.         and     [ntfs_data.cur_index_buf], 0
  1337. .nomem:
  1338.         popad
  1339.         or      ebx, -1
  1340.         push    12
  1341.         pop     eax
  1342.         ret
  1343. @@:
  1344.         mov     [ntfs_data.cur_index_buf], eax
  1345.         popad
  1346.         jmp     .doit2
  1347. .readok1:
  1348.         mov     ebp, [esi+8]    ; subnode_size
  1349.         shr     ebp, 9
  1350.         cmp     ebp, [ntfs_data.cur_index_size]
  1351.         jbe     .ok2
  1352.         push    esi ebp
  1353.         push    ebp
  1354.         call    kernel_alloc
  1355.         pop     ebp esi
  1356.         test    eax, eax
  1357.         jz      .nomem
  1358.         mov     edi, eax
  1359.         mov     ecx, [ntfs_data.cur_index_size]
  1360.         shl     ecx, 9-2
  1361.         rep     movsd
  1362.         mov     esi, eax
  1363.         mov     [ntfs_data.cur_index_size], ebp
  1364.         push    esi ebp
  1365.         push    [ntfs_data.cur_index_buf]
  1366.         call    kernel_free
  1367.         pop     ebp esi
  1368.         mov     [ntfs_data.cur_index_buf], esi
  1369. .ok2:
  1370.         add     esi, 10h
  1371.         mov     ebx, [esp+10h]
  1372.         mov     edx, [esp+14h]
  1373.         push    dword [ebx+4]   ; read ANSI/UNICODE name
  1374.         mov     ebx, [ebx]
  1375. ; init header
  1376.         mov     edi, edx
  1377.         mov     ecx, 32/4
  1378.         xor     eax, eax
  1379.         rep     stosd
  1380.         mov     byte [edx], 1   ; version
  1381.         mov     ecx, [esp+4+18h]
  1382.         push    edx
  1383.         mov     edx, esp
  1384. ; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block,
  1385. ; ecx = number of blocks to read
  1386. ; edx -> parameters block: dd <output>, dd <flags>
  1387.         cmp     [ntfs_cur_iRecord], 5
  1388.         jz      .skip_specials
  1389. ; dot and dotdot entries
  1390.         push    esi
  1391.         xor     esi, esi
  1392.         call    .add_special_entry
  1393.         inc     esi
  1394.         call    .add_special_entry
  1395.         pop     esi
  1396. .skip_specials:
  1397. ; at first, dump index root
  1398.         add     esi, [esi]
  1399. .dump_root:
  1400.         test    byte [esi+0Ch], 2
  1401.         jnz     .dump_root_done
  1402.         call    .add_entry
  1403.         movzx   eax, word [esi+8]
  1404.         add     esi, eax
  1405.         jmp     .dump_root
  1406. .dump_root_done:
  1407. ; now dump all subnodes
  1408.         push    ecx edi
  1409.         mov     edi, ntfs_bitmap_buf
  1410.         mov     [ntfs_cur_buf], edi
  1411.         mov     ecx, 0x400/4
  1412.         xor     eax, eax
  1413.         rep     stosd
  1414.         mov     [ntfs_cur_attr], 0xB0   ; $BITMAP
  1415.         and     [ntfs_cur_offs], 0
  1416.         mov     [ntfs_cur_size], 2
  1417.         call    ntfs_read_attr
  1418.         pop     edi ecx
  1419.         push    0       ; save offset in $BITMAP attribute
  1420.         and     [ntfs_cur_offs], 0
  1421. .dumploop:
  1422.         mov     [ntfs_cur_attr], 0xA0
  1423.         mov     [ntfs_cur_size], ebp
  1424.         mov     eax, [ntfs_data.cur_index_buf]
  1425.         mov     esi, eax
  1426.         mov     [ntfs_cur_buf], eax
  1427.         push    [ntfs_cur_offs]
  1428.         mov     eax, [ntfs_cur_offs]
  1429.         imul    eax, ebp
  1430.         mov     [ntfs_cur_offs], eax
  1431.         call    ntfs_read_attr
  1432.         pop     [ntfs_cur_offs]
  1433.         mov     eax, ebp
  1434.         shl     eax, 9
  1435.         cmp     [ntfs_cur_read], eax
  1436.         jnz     .done
  1437.         push    eax
  1438.         mov     eax, [ntfs_cur_offs]
  1439.         and     eax, 0x400*8-1
  1440.         bt      dword [ntfs_bitmap_buf], eax
  1441.         pop     eax
  1442.         jnc     .dump_subnode_done
  1443.         cmp     dword [esi], 'INDX'
  1444.         jnz     .dump_subnode_done
  1445.         push    ebx
  1446.         mov     ebx, esi
  1447.         call    ntfs_restore_usa
  1448.         pop     ebx
  1449.         jc      .dump_subnode_done
  1450.         add     esi, 0x18
  1451.         add     esi, [esi]
  1452. .dump_subnode:
  1453.         test    byte [esi+0Ch], 2
  1454.         jnz     .dump_subnode_done
  1455.         call    .add_entry
  1456.         movzx   eax, word [esi+8]
  1457.         add     esi, eax
  1458.         jmp     .dump_subnode
  1459. .dump_subnode_done:
  1460.         inc     [ntfs_cur_offs]
  1461.         test    [ntfs_cur_offs], 0x400*8-1
  1462.         jnz     .dumploop
  1463.         mov     [ntfs_cur_attr], 0xB0
  1464.         push    ecx edi
  1465.         mov     edi, ntfs_bitmap_buf
  1466.         mov     [ntfs_cur_buf], edi
  1467.         mov     ecx, 0x400/4
  1468.         xor     eax, eax
  1469.         rep     stosd
  1470.         pop     edi ecx
  1471.         pop     eax
  1472.         push    [ntfs_cur_offs]
  1473.         inc     eax
  1474.         mov     [ntfs_cur_offs], eax
  1475.         mov     [ntfs_cur_size], 2
  1476.         push    eax
  1477.         call    ntfs_read_attr
  1478.         pop     eax
  1479.         pop     [ntfs_cur_offs]
  1480.         push    eax
  1481.         jmp     .dumploop
  1482. .done:
  1483.         pop     eax
  1484.         pop     edx
  1485.         mov     ebx, [edx+4]
  1486.         pop     edx
  1487.         xor     eax, eax
  1488.         dec     ecx
  1489.         js      @f
  1490.         mov     al, ERROR_END_OF_FILE
  1491. @@:
  1492.         mov     [esp+1Ch], eax
  1493.         mov     [esp+10h], ebx
  1494.         popad
  1495.         ret
  1496.  
  1497. .add_special_entry:
  1498.         mov     eax, [edx]
  1499.         inc     dword [eax+8]   ; new file found
  1500.         dec     ebx
  1501.         jns     .ret
  1502.         dec     ecx
  1503.         js      .ret
  1504.         inc     dword [eax+4]   ; new file block copied
  1505.         mov     eax, [edx+4]
  1506.         mov     [edi+4], eax
  1507. ;        mov     eax, dword [ntfs_bitmap_buf+0x20]
  1508. ;        or      al, 0x10
  1509.         mov     eax, 0x10
  1510.         stosd
  1511.         scasd
  1512.         push    edx
  1513.         mov     eax, dword [ntfs_bitmap_buf]
  1514.         mov     edx, dword [ntfs_bitmap_buf+4]
  1515.         call    ntfs_datetime_to_bdfe
  1516.         mov     eax, dword [ntfs_bitmap_buf+0x18]
  1517.         mov     edx, dword [ntfs_bitmap_buf+0x1C]
  1518.         call    ntfs_datetime_to_bdfe
  1519.         mov     eax, dword [ntfs_bitmap_buf+8]
  1520.         mov     edx, dword [ntfs_bitmap_buf+0xC]
  1521.         call    ntfs_datetime_to_bdfe
  1522.         pop     edx
  1523.         xor     eax, eax
  1524.         stosd
  1525.         stosd
  1526.         mov     al, '.'
  1527.         push    edi ecx
  1528.         lea     ecx, [esi+1]
  1529.         test    byte [edi-0x24], 1
  1530.         jz      @f
  1531.         rep     stosw
  1532.         pop     ecx
  1533.         xor     eax, eax
  1534.         stosw
  1535.         pop     edi
  1536.         add     edi, 520
  1537.         ret
  1538. @@:
  1539.         rep     stosb
  1540.         pop     ecx
  1541.         xor     eax, eax
  1542.         stosb
  1543.         pop     edi
  1544.         add     edi, 264
  1545. .ret:
  1546.         ret
  1547.  
  1548. .add_entry:
  1549. ; do not return DOS 8.3 names
  1550.         cmp     byte [esi+0x51], 2
  1551.         jz      .ret
  1552. ; do not return system files
  1553. ; ... note that there will be no bad effects if system files also were reported ...
  1554.         cmp     dword [esi], 0x10
  1555.         jb      .ret
  1556.         mov     eax, [edx]
  1557.         inc     dword [eax+8]   ; new file found
  1558.         dec     ebx
  1559.         jns     .ret
  1560.         dec     ecx
  1561.         js      .ret
  1562.         inc     dword [eax+4]   ; new file block copied
  1563.         mov     eax, [edx+4]    ; flags
  1564.         call    ntfs_direntry_to_bdfe
  1565.         push    ecx esi edi
  1566.         movzx   ecx, byte [esi+0x50]
  1567.         add     esi, 0x52
  1568.         test    byte [edi-0x24], 1
  1569.         jz      .ansi
  1570.         shr     ecx, 1
  1571.         rep     movsd
  1572.         adc     ecx, ecx
  1573.         rep     movsw
  1574.         and     word [edi], 0
  1575.         pop     edi
  1576.         add     edi, 520
  1577.         pop     esi ecx
  1578.         ret
  1579. .ansi:
  1580.         jecxz   .skip
  1581. @@:
  1582.         lodsw
  1583.         call    uni2ansi_char
  1584.         stosb
  1585.         loop    @b
  1586. .skip:
  1587.         xor     al, al
  1588.         stosb
  1589.         pop     edi
  1590.         add     edi, 264
  1591.         pop     esi ecx
  1592.         ret
  1593.  
  1594. ntfs_direntry_to_bdfe:
  1595.         mov     [edi+4], eax    ; ANSI/UNICODE name
  1596.         mov     eax, [esi+48h]
  1597.         test    eax, 0x10000000
  1598.         jz      @f
  1599.         and     eax, not 0x10000000
  1600.         or      al, 0x10
  1601. @@:
  1602.         stosd
  1603.         scasd
  1604.         push    edx
  1605.         mov     eax, [esi+0x18]
  1606.         mov     edx, [esi+0x1C]
  1607.         call    ntfs_datetime_to_bdfe
  1608.         mov     eax, [esi+0x30]
  1609.         mov     edx, [esi+0x34]
  1610.         call    ntfs_datetime_to_bdfe
  1611.         mov     eax, [esi+0x20]
  1612.         mov     edx, [esi+0x24]
  1613.         call    ntfs_datetime_to_bdfe
  1614.         pop     edx
  1615.         mov     eax, [esi+0x40]
  1616.         stosd
  1617.         mov     eax, [esi+0x44]
  1618.         stosd
  1619.         ret
  1620.  
  1621. iglobal
  1622. _24             dd      24
  1623. _60             dd      60
  1624. _10000000       dd      10000000
  1625. days400year     dd      365*400+100-4+1
  1626. days100year     dd      365*100+25-1
  1627. days4year       dd      365*4+1
  1628. days1year       dd      365
  1629. months  dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1630. months2 dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1631. _400            dd      400
  1632. _100            dd      100
  1633. endg
  1634.  
  1635. ntfs_datetime_to_bdfe:
  1636. ; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
  1637.         push    eax
  1638.         mov     eax, edx
  1639.         xor     edx, edx
  1640.         div     [_10000000]
  1641.         xchg    eax, [esp]
  1642.         div     [_10000000]
  1643.         pop     edx
  1644. ; edx:eax = number of seconds since January 1, 1601
  1645.         push    eax
  1646.         mov     eax, edx
  1647.         xor     edx, edx
  1648.         div     [_60]
  1649.         xchg    eax, [esp]
  1650.         div     [_60]
  1651.         mov     [edi], dl
  1652.         pop     edx
  1653. ; edx:eax = number of minutes
  1654.         div     [_60]
  1655.         mov     [edi+1], dl
  1656. ; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
  1657.         xor     edx, edx
  1658.         div     [_24]
  1659.         mov     [edi+2], dl
  1660.         mov     [edi+3], byte 0
  1661. ; eax = number of days since January 1, 1601
  1662.         xor     edx, edx
  1663.         div     [days400year]
  1664.         imul    eax, 400
  1665.         add     eax, 1601
  1666.         mov     [edi+6], ax
  1667.         mov     eax, edx
  1668.         xor     edx, edx
  1669.         div     [days100year]
  1670.         cmp     al, 4
  1671.         jnz     @f
  1672.         dec     eax
  1673.         add     edx, [days100year]
  1674. @@:
  1675.         imul    eax, 100
  1676.         add     [edi+6], ax
  1677.         mov     eax, edx
  1678.         xor     edx, edx
  1679.         div     [days4year]
  1680.         shl     eax, 2
  1681.         add     [edi+6], ax
  1682.         mov     eax, edx
  1683.         xor     edx, edx
  1684.         div     [days1year]
  1685.         cmp     al, 4
  1686.         jnz     @f
  1687.         dec     eax
  1688.         add     edx, [days1year]
  1689. @@:
  1690.         add     [edi+6], ax
  1691.         push    esi edx
  1692.         mov     esi, months
  1693.         movzx   eax, word [edi+6]
  1694.         test    al, 3
  1695.         jnz     .noleap
  1696.         xor     edx, edx
  1697.         push    eax
  1698.         div     [_400]
  1699.         pop     eax
  1700.         test    edx, edx
  1701.         jz      .leap
  1702.         xor     edx, edx
  1703.         div     [_100]
  1704.         test    edx, edx
  1705.         jz      .noleap
  1706. .leap:
  1707.         mov     esi, months2
  1708. .noleap:
  1709.         pop     edx
  1710.         xor     eax, eax
  1711.         inc     eax
  1712. @@:
  1713.         sub     edx, [esi]
  1714.         jb      @f
  1715.         add     esi, 4
  1716.         inc     eax
  1717.         jmp     @b
  1718. @@:
  1719.         add     edx, [esi]
  1720.         pop     esi
  1721.         inc     edx
  1722.         mov     [edi+4], dl
  1723.         mov     [edi+5], al
  1724.         add     edi, 8
  1725.         ret
  1726.  
  1727. ;----------------------------------------------------------------
  1728. ;
  1729. ;  ntfs_HdRewrite - write to NTFS hard disk
  1730. ;
  1731. ;  esi  points to filename
  1732. ;  ebx  ignored (reserved)
  1733. ;  ecx  number of bytes to write, 0+
  1734. ;  edx  mem location to data
  1735. ;
  1736. ;  ret ebx = number of written bytes
  1737. ;      eax = 0 ok read or other = errormsg
  1738. ;
  1739. ;--------------------------------------------------------------
  1740. ntfs_HdRewrite:
  1741.         xor     ebx, ebx
  1742.         mov     eax, ERROR_UNSUPPORTED_FS
  1743.         ret
  1744.  
  1745. ;----------------------------------------------------------------
  1746. ;
  1747. ;  ntfs_HdWrite - write to NTFS hard disk
  1748. ;
  1749. ;  esi  points to filename
  1750. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1751. ;       may be ebx=0 - start from first byte
  1752. ;  ecx  number of bytes to write, 0+
  1753. ;  edx  mem location to data
  1754. ;
  1755. ;  ret ebx = bytes written (maybe 0)
  1756. ;      eax = 0 ok write or other = errormsg
  1757. ;
  1758. ;--------------------------------------------------------------
  1759. ntfs_HdWrite:
  1760.         xor     ebx, ebx
  1761.         mov     eax, ERROR_UNSUPPORTED_FS
  1762.         ret
  1763.  
  1764. ;----------------------------------------------------------------
  1765. ;
  1766. ;  ntfs_HdSetFileEnd - set end of file on NTFS hard disk
  1767. ;
  1768. ;  esi  points to filename
  1769. ;  ebx  points to 64-bit number = new file size
  1770. ;  ecx  ignored (reserved)
  1771. ;  edx  ignored (reserved)
  1772. ;
  1773. ;  ret eax = 0 ok or other = errormsg
  1774. ;
  1775. ;--------------------------------------------------------------
  1776. ntfs_HdSetFileEnd:
  1777. ntfs_HdSetFileInfo:
  1778. ;----------------------------------------------------------------
  1779. ;
  1780. ;  ntfs_HdDelete - delete file or empty folder from NTFS hard disk
  1781. ;
  1782. ;  esi  points to filename
  1783. ;
  1784. ;  ret  eax = 0 ok or other = errormsg
  1785. ;
  1786. ;--------------------------------------------------------------
  1787. ntfs_HdDelete:
  1788.         mov     eax, ERROR_UNSUPPORTED_FS
  1789.         ret
  1790.  
  1791. ntfs_HdGetFileInfo:
  1792.         cmp     byte [esi], 0
  1793.         jnz     @f
  1794.         push    2
  1795.         pop     eax
  1796.         ret
  1797. @@:
  1798.         call    ntfs_find_lfn
  1799.         jnc     .doit
  1800.         push    ERROR_FILE_NOT_FOUND
  1801.         pop     eax
  1802.         cmp     [hd_error], 0
  1803.         jz      @f
  1804.         mov     al, 11
  1805. @@:
  1806.         ret
  1807. .doit:
  1808.         push    esi edi
  1809.         mov     esi, eax
  1810.         mov     edi, edx
  1811.         xor     eax, eax
  1812.         call    ntfs_direntry_to_bdfe
  1813.         pop     edi esi
  1814.         xor     eax, eax
  1815.         ret
  1816.