Subversion Repositories Kolibri OS

Rev

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

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