Subversion Repositories Kolibri OS

Rev

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

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