Subversion Repositories Kolibri OS

Rev

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

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