Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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