Subversion Repositories Kolibri OS

Rev

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