Subversion Repositories Kolibri OS

Rev

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

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