Subversion Repositories Kolibri OS

Rev

Rev 256 | Rev 262 | Go to most recent revision | Blame | Compare with Previous | 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.         and     [hd1_status], 0
  226.         ret
  227.  
  228. .get_mft_retrieval_ptr:
  229.         pushad
  230.         mov     eax, [ntfs_data.mft_retrieval_size]
  231.         cmp     eax, [ntfs_data.mft_retrieval_alloc]
  232.         jnz     .ok
  233.         add     eax, 0x1000/8
  234.         mov     [ntfs_data.mft_retrieval_alloc], eax
  235.         shl     eax, 3
  236.         push    eax
  237.         call    kernel_alloc
  238.         test    eax, eax
  239.         jnz     @f
  240.         popad
  241.         add     esp, 14h
  242.         jmp     .fail_free_mft
  243. @@:
  244.         mov     esi, [ntfs_data.mft_retrieval]
  245.         mov     edi, eax
  246.         mov     ecx, [ntfs_data.mft_retrieval_size]
  247.         add     ecx, ecx
  248.         rep     movsd
  249.         push    [ntfs_data.mft_retrieval]
  250.         mov     [ntfs_data.mft_retrieval], eax
  251.         call    kernel_free
  252.         mov     eax, [ntfs_data.mft_retrieval_size]
  253. .ok:
  254.         shl     eax, 3
  255.         add     eax, [ntfs_data.mft_retrieval]
  256.         mov     [esp+28], eax
  257.         popad
  258.         ret
  259.  
  260. ntfs_read_frs_sector:
  261.         push    eax ecx
  262.         add     eax, [PARTITION_START]
  263.         mov     ecx, [ntfs_data.frs_size]
  264.         shr     ecx, 9
  265.         mov     ebx, [ntfs_data.frs_buffer]
  266.         push    ebx
  267. @@:
  268.         call    hd_read
  269.         cmp     [hd_error], 0
  270.         jnz     .fail
  271.         add     ebx, 0x200
  272.         inc     eax
  273.         loop    @b
  274. .fail:
  275.         pop     ebx
  276.         pop     ecx eax
  277.         ret
  278.  
  279. uglobal
  280. align 4
  281. ntfs_cur_attr   dd      ?
  282. ntfs_cur_iRecord dd     ?
  283. ntfs_cur_offs   dd      ?       ; in sectors
  284. ntfs_cur_size   dd      ?       ; in sectors
  285. ntfs_cur_buf    dd      ?
  286. ntfs_cur_read   dd      ?       ; [output]
  287.  
  288. ntfs_attrlist_buf       rb      0x400
  289. ntfs_bitmap_buf         rb      0x400
  290.  
  291. ntfs_attr_iRecord       dd      ?
  292. ntfs_attr_iBaseRecord   dd      ?
  293. ntfs_attr_offs          dd      ?
  294. ntfs_attr_list          dd      ?
  295. ntfs_attr_size          dq      ?
  296. endg
  297.  
  298. ntfs_read_attr:
  299. ; in: global variables
  300. ; out: [ntfs_cur_read]
  301.         pushad
  302.         and     [ntfs_cur_read], 0
  303.         cmp     [ntfs_cur_iRecord], 0
  304.         jnz     .nomft
  305.         cmp     [ntfs_cur_attr], 0x80
  306.         jnz     .nomft
  307.         mov     eax, [ntfs_data.mft_retrieval_end]
  308.         inc     eax
  309.         mul     [ntfs_data.sectors_per_cluster]
  310.         cmp     eax, [ntfs_cur_offs]
  311.         jbe     .nomft
  312. ; precalculated part of $Mft $DATA
  313.         mov     esi, [ntfs_data.mft_retrieval]
  314.         mov     eax, [ntfs_cur_offs]
  315.         xor     edx, edx
  316.         div     [ntfs_data.sectors_per_cluster]
  317. ; eax = VCN, edx = offset in sectors from beginning of cluster
  318.         xor     ecx, ecx        ; ecx will contain LCN
  319. .mftscan:
  320.         add     ecx, [esi+4]
  321.         sub     eax, [esi]
  322.         jb      @f
  323.         add     esi, 8
  324.         push    eax
  325.         mov     eax, [ntfs_data.mft_retrieval_end]
  326.         shl     eax, 3
  327.         add     eax, [ntfs_data.mft_retrieval]
  328.         cmp     eax, esi
  329.         pop     eax
  330.         jnz     .mftscan
  331.         jmp     .nomft
  332. @@:
  333.         push    ecx
  334.         add     ecx, eax
  335.         add     ecx, [esi]
  336.         push    eax
  337.         push    edx
  338.         mov     eax, [ntfs_data.sectors_per_cluster]
  339.         mul     ecx
  340. ; eax = sector on partition
  341.         add     eax, [PARTITION_START]
  342.         pop     edx
  343.         add     eax, edx
  344.         mov     ebx, [ntfs_cur_buf]
  345.         pop     ecx
  346.         neg     ecx
  347.         imul    ecx, [ntfs_data.sectors_per_cluster]
  348.         sub     ecx, edx
  349.         cmp     ecx, [ntfs_cur_size]
  350.         jb      @f
  351.         mov     ecx, [ntfs_cur_size]
  352. @@:
  353. ; ecx = number of sequential sectors to read
  354.         call    hd_read
  355.         cmp     [hd_error], 0
  356.         jnz     .errread
  357.         add     [ntfs_cur_read], 0x200
  358.         dec     [ntfs_cur_size]
  359.         inc     [ntfs_cur_offs]
  360.         add     ebx, 0x200
  361.         mov     [ntfs_cur_buf], ebx
  362.         inc     eax
  363.         loop    @b
  364.         pop     ecx
  365.         xor     eax, eax
  366.         xor     edx, edx
  367.         cmp     [ntfs_cur_size], eax
  368.         jz      @f
  369.         add     esi, 8
  370.         push    eax
  371.         mov     eax, [ntfs_data.mft_retrieval_end]
  372.         shl     eax, 3
  373.         add     eax, [ntfs_data.mft_retrieval]
  374.         cmp     eax, esi
  375.         pop     eax
  376.         jz      .nomft
  377.         jmp     .mftscan
  378. @@:
  379.         popad
  380.         ret
  381. .errread:
  382.         pop     ecx
  383. .errret:
  384.         stc
  385.         popad
  386.         ret
  387. .nomft:
  388. ; 1. Read file record.
  389. ; N.B. This will do recursive call of read_attr for $MFT::$Data.
  390.         mov     eax, [ntfs_cur_iRecord]
  391.         mov     [ntfs_attr_iRecord], eax
  392.         and     [ntfs_attr_list], 0
  393.         or      dword [ntfs_attr_size], -1
  394.         or      dword [ntfs_attr_size+4], -1
  395.         or      [ntfs_attr_iBaseRecord], -1
  396.         call    ntfs_read_file_record
  397.         test    eax, eax
  398.         jz      .errret
  399. ; 2. Find required attribute.
  400.         mov     eax, [ntfs_data.frs_buffer]
  401. ; a) For auxiliary records, read base record
  402. ; N.B. If base record is present,
  403. ;      base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero
  404.         cmp     dword [eax+24h], 0
  405.         jz      @f
  406.         mov     eax, [eax+20h]
  407. ;        test    eax, eax
  408. ;        jz      @f
  409. .beginfindattr:
  410.         mov     [ntfs_attr_iRecord], eax
  411.         call    ntfs_read_file_record
  412.         test    eax, eax
  413.         jz      .errret
  414. @@:
  415. ; b) Scan for required attribute and for $ATTR_LIST
  416.         mov     eax, [ntfs_data.frs_buffer]
  417.         movzx   ecx, word [eax+14h]
  418.         add     eax, ecx
  419.         mov     ecx, [ntfs_cur_attr]
  420.         and     [ntfs_attr_offs], 0
  421. .scanattr:
  422.         cmp     dword [eax], -1
  423.         jz      .scandone
  424.         cmp     dword [eax], ecx
  425.         jz      .okattr
  426.         cmp     [ntfs_attr_iBaseRecord], -1
  427.         jnz     .scancont
  428.         cmp     dword [eax], 0x20       ; $ATTR_LIST
  429.         jnz     .scancont
  430.         mov     [ntfs_attr_list], eax
  431.         jmp     .scancont
  432. .okattr:
  433.         mov     [ntfs_attr_offs], eax
  434. .scancont:
  435.         add     eax, [eax+4]
  436.         jmp     .scanattr
  437. .scandone:
  438. ; c) Check for required offset and length
  439.         mov     ecx, [ntfs_attr_offs]
  440.         jecxz   .noattr
  441.         call    .doreadattr
  442.         jc      @f
  443.         cmp     [ntfs_cur_size], 0
  444.         jnz     .not_in_cur
  445. @@:
  446.         popad
  447.         ret
  448. .noattr:
  449. .not_in_cur:
  450.         cmp     [ntfs_cur_attr], 0x20
  451.         jz      @f
  452.         mov     ecx, [ntfs_attr_list]
  453.         test    ecx, ecx
  454.         jnz     .lookattr
  455. .ret_is_attr:
  456.         cmp     [ntfs_attr_offs], 1     ; CF set <=> ntfs_attr_offs == 0
  457.         popad
  458.         ret
  459. .lookattr:
  460. ; required attribute or required offset was not found in base record;
  461. ; it may be present in auxiliary records;
  462. ; scan $ATTR_LIST
  463.         mov     eax, [ntfs_attr_iBaseRecord]
  464.         cmp     eax, -1
  465.         jz      @f
  466.         call    ntfs_read_file_record
  467.         test    eax, eax
  468.         jz      .errret
  469.         or      [ntfs_attr_iBaseRecord], -1
  470. @@:
  471.         push    [ntfs_cur_offs]
  472.         push    [ntfs_cur_size]
  473.         push    [ntfs_cur_read]
  474.         push    [ntfs_cur_buf]
  475.         push    dword [ntfs_attr_size]
  476.         push    dword [ntfs_attr_size+4]
  477.         or      dword [ntfs_attr_size], -1
  478.         or      dword [ntfs_attr_size+4], -1
  479.         xor     edx, edx
  480.         mov     [ntfs_cur_offs], edx
  481.         mov     [ntfs_cur_size], 2
  482.         and     [ntfs_cur_read], 0
  483.         mov     [ntfs_cur_buf], ntfs_attrlist_buf
  484.         push    edx
  485.         call    .doreadattr
  486.         pop     edx
  487.         pop     dword [ntfs_attr_size+4]
  488.         pop     dword [ntfs_attr_size]
  489.         mov     ebp, [ntfs_cur_read]
  490.         pop     [ntfs_cur_buf]
  491.         pop     [ntfs_cur_read]
  492.         pop     [ntfs_cur_size]
  493.         pop     [ntfs_cur_offs]
  494.         jc      .errret
  495.         mov     esi, ntfs_attrlist_buf
  496.         or      edi, -1
  497. .scanliststart:
  498.         lea     ebp, [ebp+esi-1Ah]
  499.         mov     eax, [ntfs_cur_attr]
  500. .scanlist:
  501.         cmp     esi, ebp
  502.         jae     .scanlistdone
  503.         cmp     eax, [esi]
  504.         jz      @f
  505. .scanlistcont:
  506.         movzx   ecx, word [esi+4]
  507.         add     esi, ecx
  508.         jmp     .scanlist
  509. @@:
  510.         push    eax
  511.         mov     eax, [esi+8]
  512.         test    eax, eax
  513.         jnz     .testf
  514.         mov     eax, dword [ntfs_attr_size]
  515.         and     eax, dword [ntfs_attr_size+4]
  516.         cmp     eax, -1
  517.         jnz     .testfz
  518. ; if attribute is in auxiliary records, its size is defined only in first
  519.         mov     eax, [esi+10h]
  520.         call    ntfs_read_file_record
  521.         test    eax, eax
  522.         jnz     @f
  523. .errret_pop:
  524.         pop     eax
  525.         jmp     .errret
  526. @@:
  527.         mov     eax, [ntfs_data.frs_buffer]
  528.         movzx   ecx, word [eax+14h]
  529.         add     eax, ecx
  530.         mov     ecx, [ntfs_cur_attr]
  531. @@:
  532.         cmp     dword [eax], -1
  533.         jz      .errret_pop
  534.         cmp     dword [eax], ecx
  535.         jz      @f
  536.         add     eax, [eax+4]
  537.         jmp     @b
  538. @@:
  539.         cmp     byte [eax+8], 0
  540.         jnz     .sdnores
  541.         mov     eax, [eax+10h]
  542.         mov     dword [ntfs_attr_size], eax
  543.         and     dword [ntfs_attr_size+4], 0
  544.         jmp     .testfz
  545. .sdnores:
  546.         mov     ecx, [eax+30h]
  547.         mov     dword [ntfs_attr_size], ecx
  548.         mov     ecx, [eax+34h]
  549.         mov     dword [ntfs_attr_size+4], ecx
  550. .testfz:
  551.         xor     eax, eax
  552. .testf:
  553.         imul    eax, [ntfs_data.sectors_per_cluster]
  554.         cmp     eax, [ntfs_cur_offs]
  555.         pop     eax
  556.         ja      @f
  557.         mov     edi, [esi+10h]  ; keep previous iRecord
  558.         jmp     .scanlistcont
  559. @@:
  560. .scanlistfound:
  561.         cmp     edi, -1
  562.         jnz     @f
  563.         popad
  564.         ret
  565. @@:
  566.         mov     eax, [ntfs_cur_iRecord]
  567.         mov     [ntfs_attr_iBaseRecord], eax
  568.         mov     eax, edi
  569.         jmp     .beginfindattr
  570. .sde:
  571.         popad
  572.         stc
  573.         ret
  574. .scanlistdone:
  575.         sub     ebp, ntfs_attrlist_buf-1Ah
  576.         test    ebp, 1FFh
  577.         jnz     .scanlistfound
  578.         test    edx, edx
  579.         jnz     @f
  580.         inc     edx
  581.         cmp     ebp, 0x400
  582.         jnz     .scanlistfound
  583. @@:
  584.         inc     edx
  585.         push    esi edi
  586.         mov     esi, ntfs_attrlist_buf+0x200
  587.         mov     edi, ntfs_attrlist_buf
  588.         mov     ecx, 0x200/4
  589.         rep     movsd
  590.         pop     edi esi
  591.         sub     esi, 0x200
  592.         push    [ntfs_cur_offs]
  593.         push    [ntfs_cur_size]
  594.         push    [ntfs_cur_read]
  595.         push    [ntfs_cur_buf]
  596.         mov     [ntfs_cur_offs], edx
  597.         mov     [ntfs_cur_size], 1
  598.         and     [ntfs_cur_read], 0
  599.         mov     [ntfs_cur_buf], ntfs_attrlist_buf+0x200
  600.         push    esi edx
  601.         call    .doreadattr
  602.         pop     edx esi
  603.         mov     ebp, [ntfs_cur_read]
  604.         pop     [ntfs_cur_buf]
  605.         pop     [ntfs_cur_read]
  606.         pop     [ntfs_cur_size]
  607.         pop     [ntfs_cur_offs]
  608.         jc      .errret
  609.         jmp     .scanliststart
  610.  
  611. .doreadattr:
  612.         cmp     byte [ecx+8], 0
  613.         jnz     .nonresident
  614.         mov     eax, [ecx+10h]  ; length
  615.         mov     esi, eax
  616.         mov     edx, [ntfs_cur_offs]
  617.         shr     eax, 9
  618.         cmp     eax, edx
  619.         jb      .okret
  620.         shl     edx, 9
  621.         sub     esi, edx
  622.         movzx   eax, word [ecx+14h]
  623.         add     edx, eax
  624.         add     edx, ecx        ; edx -> data
  625.         mov     eax, [ntfs_cur_size]
  626.         cmp     eax, (0xFFFFFFFF shr 9)+1
  627.         jbe     @f
  628.         mov     eax, (0xFFFFFFFF shr 9)+1
  629. @@:
  630.         shl     eax, 9
  631.         cmp     eax, esi
  632.         jbe     @f
  633.         mov     eax, esi
  634. @@:
  635. ; eax = length, edx -> data
  636.         mov     [ntfs_cur_read], eax
  637.         mov     ecx, eax
  638.         mov     eax, edx
  639.         mov     ebx, [ntfs_cur_buf]
  640.         call    memmove
  641.         and     [ntfs_cur_size], 0      ; CF=0
  642.         ret
  643. .nonresident:
  644. ; Not all auxiliary records contain correct FileSize info
  645.         mov     eax, dword [ntfs_attr_size]
  646.         mov     edx, dword [ntfs_attr_size+4]
  647.         push    eax
  648.         and     eax, edx
  649.         cmp     eax, -1
  650.         pop     eax
  651.         jnz     @f
  652.         mov     eax, [ecx+30h]  ; FileSize
  653.         mov     edx, [ecx+34h]
  654.         mov     dword [ntfs_attr_size], eax
  655.         mov     dword [ntfs_attr_size+4], edx
  656. @@:
  657.         add     eax, 0x1FF
  658.         adc     edx, 0
  659.         shrd    eax, edx, 9
  660.         sub     eax, [ntfs_cur_offs]
  661.         ja      @f
  662. ; return with nothing read
  663.         and     [ntfs_cur_size], 0
  664. .okret:
  665.         clc
  666.         ret
  667. @@:
  668. ; reduce read length
  669.         cmp     [ntfs_cur_size], eax
  670.         jb      @f
  671.         mov     [ntfs_cur_size], eax
  672. @@:
  673.         cmp     [ntfs_cur_size], 0
  674.         jz      .okret
  675.         mov     eax, [ntfs_cur_offs]
  676.         xor     edx, edx
  677.         div     [ntfs_data.sectors_per_cluster]
  678.         sub     eax, [ecx+10h]  ; first_vbo
  679.         jb      .okret
  680. ; eax = cluster, edx = starting sector
  681.         sub     esp, 10h
  682.         movzx   esi, word [ecx+20h]     ; mcb_info_ofs
  683.         add     esi, ecx
  684.         xor     ebp, ebp
  685. .readloop:
  686.         call    ntfs_decode_mcb_entry
  687.         jnc     .break
  688.         add     ebp, [esp+8]
  689.         sub     eax, [esp]
  690.         jae     .readloop
  691.         push    ecx
  692.         push    eax
  693.         add     eax, [esp+8]
  694.         add     eax, ebp
  695.         imul    eax, [ntfs_data.sectors_per_cluster]
  696.         add     eax, edx
  697.         add     eax, [PARTITION_START]
  698.         pop     ecx
  699.         neg     ecx
  700.         imul    ecx, [ntfs_data.sectors_per_cluster]
  701.         sub     ecx, edx
  702.         cmp     ecx, [ntfs_cur_size]
  703.         jb      @f
  704.         mov     ecx, [ntfs_cur_size]
  705. @@:
  706.         mov     ebx, [ntfs_cur_buf]
  707. @@:
  708.         call    hd_read
  709.         cmp     [hd_error], 0
  710.         jnz     .errread2
  711.         add     ebx, 0x200
  712.         mov     [ntfs_cur_buf], ebx
  713.         inc     eax
  714.         add     [ntfs_cur_read], 0x200
  715.         dec     [ntfs_cur_size]
  716.         inc     [ntfs_cur_offs]
  717.         loop    @b
  718.         pop     ecx
  719.         cmp     [ntfs_cur_size], 0
  720.         jnz     .readloop
  721.         add     esp, 10h
  722.         jmp     .okret
  723. .errread2:
  724.         pop     ecx
  725.         add     esp, 10h
  726.         jmp     .errret
  727. .break:
  728.         add     esp, 10h        ; CF=0
  729.         ret
  730.  
  731. ntfs_read_file_record:
  732. ; in: eax=iRecord
  733. ; out: [ntfs_data.frs_buffer] contains information
  734. ;      eax=0 - failed, eax=1 - success
  735. ; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size]
  736.         push    ecx edx
  737.         mov     ecx, [ntfs_data.frs_size]
  738.         mul     ecx
  739.         shrd    eax, edx, 9
  740.         shr     edx, 9
  741.         jnz     .err
  742.         push    [ntfs_attr_iRecord]
  743.         push    [ntfs_attr_iBaseRecord]
  744.         push    [ntfs_attr_offs]
  745.         push    [ntfs_attr_list]
  746.         push    dword [ntfs_attr_size+4]
  747.         push    dword [ntfs_attr_size]
  748.         push    [ntfs_cur_iRecord]
  749.         push    [ntfs_cur_attr]
  750.         push    [ntfs_cur_offs]
  751.         push    [ntfs_cur_size]
  752.         push    [ntfs_cur_buf]
  753.         push    [ntfs_cur_read]
  754.         mov     [ntfs_cur_attr], 0x80   ; $DATA
  755.         and     [ntfs_cur_iRecord], 0   ; $Mft
  756.         mov     [ntfs_cur_offs], eax
  757.         shr     ecx, 9
  758.         mov     [ntfs_cur_size], ecx
  759.         mov     eax, [ntfs_data.frs_buffer]
  760.         mov     [ntfs_cur_buf], eax
  761.         call    ntfs_read_attr
  762.         mov     eax, [ntfs_cur_read]
  763.         pop     [ntfs_cur_read]
  764.         pop     [ntfs_cur_buf]
  765.         pop     [ntfs_cur_size]
  766.         pop     [ntfs_cur_offs]
  767.         pop     [ntfs_cur_attr]
  768.         pop     [ntfs_cur_iRecord]
  769.         pop     dword [ntfs_attr_size]
  770.         pop     dword [ntfs_attr_size+4]
  771.         pop     [ntfs_attr_list]
  772.         pop     [ntfs_attr_offs]
  773.         pop     [ntfs_attr_iBaseRecord]
  774.         pop     [ntfs_attr_iRecord]
  775.         pop     edx ecx
  776.         jc      .errret
  777.         cmp     eax, [ntfs_data.frs_size]
  778.         jnz     .errret
  779.         mov     eax, [ntfs_data.frs_buffer]
  780.         cmp     dword [eax], 'FILE'
  781.         jnz     .errret
  782.         push    ebx
  783.         mov     ebx, eax
  784.         call    ntfs_restore_usa_frs
  785.         pop     ebx
  786.         setnc   al
  787.         movzx   eax, al
  788. .ret:
  789.         ret
  790. .err:
  791.         pop     edx ecx
  792. .errret:
  793.         xor     eax, eax
  794.         ret
  795.  
  796. ntfs_restore_usa_frs:
  797.         mov     eax, [ntfs_data.frs_size]
  798. ntfs_restore_usa:
  799.         pushad
  800.         shr     eax, 9
  801.         mov     ecx, eax
  802.         inc     eax
  803.         cmp     [ebx+6], ax
  804.         jnz     .err
  805.         movzx   eax, word [ebx+4]
  806.         lea     esi, [eax+ebx]
  807.         lodsw
  808.         mov     edx, eax
  809.         lea     edi, [ebx+0x1FE]
  810. @@:
  811.         cmp     [edi], dx
  812.         jnz     .err
  813.         lodsw
  814.         stosw
  815.         add     edi, 0x1FE
  816.         loop    @b
  817.         popad
  818.         clc
  819.         ret
  820. .err:
  821.         popad
  822.         stc
  823.         ret
  824.  
  825. ntfs_decode_mcb_entry:
  826.         push    eax ecx edi
  827.         lea     edi, [esp+16]
  828.         xor     eax, eax
  829.         lodsb
  830.         test    al, al
  831.         jz      .end
  832.         mov     ecx, eax
  833.         and     ecx, 0xF
  834.         cmp     ecx, 8
  835.         ja      .end
  836.         push    ecx
  837.         rep     movsb
  838.         pop     ecx
  839.         sub     ecx, 8
  840.         neg     ecx
  841.         cmp     byte [esi-1], 80h
  842.         jae     .end
  843.         push    eax
  844.         xor     eax, eax
  845.         rep     stosb
  846.         pop     ecx
  847.         shr     ecx, 4
  848.         cmp     ecx, 8
  849.         ja      .end
  850.         push    ecx
  851.         rep     movsb
  852.         pop     ecx
  853.         sub     ecx, 8
  854.         neg     ecx
  855.         cmp     byte [esi-1], 80h
  856.         cmc
  857.         sbb     eax, eax
  858.         rep     stosb
  859.         stc
  860. .end:
  861.         pop     edi ecx eax
  862.         ret
  863.  
  864. ntfs_find_lfn:
  865. ; in: esi->name
  866. ; out: CF=1 - file not found
  867. ;      else CF=0 and eax=ntfs_cur_iRecord valid
  868.         mov     [ntfs_cur_iRecord], 5   ; start parse from root cluster
  869. .doit2:
  870.         mov     [ntfs_cur_attr], 0x90   ; $INDEX_ROOT
  871.         and     [ntfs_cur_offs], 0
  872.         mov     eax, [ntfs_data.cur_index_size]
  873.         mov     [ntfs_cur_size], eax
  874.         mov     eax, [ntfs_data.cur_index_buf]
  875.         mov     [ntfs_cur_buf], eax
  876.         call    ntfs_read_attr
  877.         jnc     @f
  878. .ret:
  879.         ret
  880. @@:
  881.         cmp     [ntfs_cur_read], 0x20
  882.         jc      .ret
  883.         pushad
  884.         mov     esi, [ntfs_data.cur_index_buf]
  885.         mov     eax, [esi+14h]
  886.         add     eax, 10h
  887.         cmp     [ntfs_cur_read], eax
  888.         jae     .readok1
  889.         add     eax, 1FFh
  890.         shr     eax, 9
  891.         cmp     eax, [ntfs_data.cur_index_size]
  892.         ja      @f
  893. .stc_ret:
  894.         popad
  895.         stc
  896.         ret
  897. @@:
  898. ; reallocate
  899.         push    eax
  900.         push    [ntfs_data.cur_index_buf]
  901.         call    kernel_free
  902.         pop     eax
  903.         mov     [ntfs_data.cur_index_size], eax
  904.         push    eax
  905.         call    kernel_alloc
  906.         test    eax, eax
  907.         jnz     @f
  908.         and     [ntfs_data.cur_index_size], 0
  909.         and     [ntfs_data.cur_index_buf], 0
  910.         jmp     .stc_ret
  911. @@:
  912.         mov     [ntfs_data.cur_index_buf], eax
  913.         popad
  914.         jmp     .doit2
  915. .readok1:
  916.         mov     ebp, [esi+8]    ; subnode_size
  917.         shr     ebp, 9
  918.         cmp     ebp, [ntfs_data.cur_index_size]
  919.         jbe     .ok2
  920.         push    esi ebp
  921.         push    ebp
  922.         call    kernel_alloc
  923.         pop     ebp esi
  924.         test    eax, eax
  925.         jz      .stc_ret
  926.         mov     edi, eax
  927.         mov     ecx, [ntfs_data.cur_index_size]
  928.         shl     ecx, 9-2
  929.         rep     movsd
  930.         mov     esi, eax
  931.         mov     [ntfs_data.cur_index_size], ebp
  932.         push    esi ebp
  933.         push    [ntfs_data.cur_index_buf]
  934.         call    kernel_free
  935.         pop     ebp esi
  936.         mov     [ntfs_data.cur_index_buf], esi
  937. .ok2:
  938.         add     esi, 10h
  939.         mov     edi, [esp+4]
  940. ; edi -> name, esi -> current index data, ebp = subnode size
  941. .scanloop:
  942.         add     esi, [esi]
  943. .scanloopint:
  944.         test    byte [esi+0Ch], 2
  945.         jnz     .subnode
  946.         push    esi
  947.         add     esi, 0x52
  948.         movzx   ecx, byte [esi-2]
  949.         push    edi
  950. @@:
  951.         lodsw
  952.         call    uni2ansi_char
  953.         call    char_toupper
  954.         push    eax
  955.         mov     al, [edi]
  956.         inc     edi
  957.         call    char_toupper
  958.         cmp     al, [esp]
  959.         pop     eax
  960.         loopz   @b
  961.         jz      .found
  962.         pop     edi
  963.         pop     esi
  964.         jb      .subnode
  965. .scanloopcont:
  966.         movzx   eax, word [esi+8]
  967.         add     esi, eax
  968.         jmp     .scanloopint
  969. .subnode:
  970.         test    byte [esi+0Ch], 1
  971.         jz      .notfound
  972.         movzx   eax, word [esi+8]
  973.         mov     eax, [esi+eax-8]
  974.         mul     [ntfs_data.sectors_per_cluster]
  975.         mov     [ntfs_cur_offs], eax
  976.         mov     [ntfs_cur_attr], 0xA0   ; $INDEX_ALLOCATION
  977.         mov     [ntfs_cur_size], ebp
  978.         mov     eax, [ntfs_data.cur_index_buf]
  979.         mov     esi, eax
  980.         mov     [ntfs_cur_buf], eax
  981.         call    ntfs_read_attr
  982.         mov     eax, ebp
  983.         shl     eax, 9
  984.         cmp     [ntfs_cur_read], eax
  985.         jnz     .notfound
  986.         cmp     dword [esi], 'INDX'
  987.         jnz     .notfound
  988.         mov     ebx, esi
  989.         call    ntfs_restore_usa
  990.         jc      .notfound
  991.         add     esi, 0x18
  992.         jmp     .scanloop
  993. .notfound:
  994.         popad
  995.         stc
  996.         ret
  997. .found:
  998.         cmp     byte [edi], 0
  999.         jz      .done
  1000.         cmp     byte [edi], '/'
  1001.         jz      .next
  1002.         pop     edi
  1003.         pop     esi
  1004.         jmp     .scanloopcont
  1005. .done:
  1006. .next:
  1007.         pop     esi
  1008.         pop     esi
  1009.         mov     eax, [esi]
  1010.         mov     [ntfs_cur_iRecord], eax
  1011.         mov     [esp+1Ch], eax
  1012.         mov     [esp+4], edi
  1013.         popad
  1014.         inc     esi
  1015.         cmp     byte [esi-1], 0
  1016.         jnz     .doit2
  1017.         ret
  1018.  
  1019. ;----------------------------------------------------------------
  1020. ;
  1021. ;  ntfs_HdRead - read NTFS hard disk
  1022. ;
  1023. ;  esi  points to filename
  1024. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1025. ;       may be ebx=0 - start from first byte
  1026. ;  ecx  number of bytes to read, 0+
  1027. ;  edx  mem location to return data
  1028. ;
  1029. ;  ret ebx = bytes read or 0xffffffff file not found
  1030. ;      eax = 0 ok read or other = errormsg
  1031. ;
  1032. ;--------------------------------------------------------------
  1033. ntfs_HdRead:
  1034.         or      ebx, -1
  1035.         mov     eax, ERROR_UNSUPPORTED_FS
  1036.         ret
  1037.  
  1038. ;----------------------------------------------------------------
  1039. ;
  1040. ;  ntfs_HdReadFolder - read NTFS hard disk folder
  1041. ;
  1042. ;  esi  points to filename
  1043. ;  ebx  pointer to structure 32-bit number = first wanted block, 0+
  1044. ;                          & flags (bitfields)
  1045. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  1046. ;  ecx  number of blocks to read, 0+
  1047. ;  edx  mem location to return data
  1048. ;
  1049. ;  ret ebx = blocks read or 0xffffffff folder not found
  1050. ;      eax = 0 ok read or other = errormsg
  1051. ;
  1052. ;--------------------------------------------------------------
  1053. ntfs_HdReadFolder:
  1054.         mov     eax, 5          ; root cluster
  1055.         cmp     byte [esi], 0
  1056.         jz      .doit
  1057.         call    ntfs_find_lfn
  1058.         jnc     .doit2
  1059. .notfound:
  1060.         or      ebx, -1
  1061.         push    ERROR_FILE_NOT_FOUND
  1062. .pop_ret:
  1063.         pop     eax
  1064.         ret
  1065. .doit:
  1066.         mov     [ntfs_cur_iRecord], eax
  1067. .doit2:
  1068.         mov     [ntfs_cur_attr], 0x10   ; $STANDARD_INFORMATION
  1069.         and     [ntfs_cur_offs], 0
  1070.         mov     [ntfs_cur_size], 1
  1071.         mov     [ntfs_cur_buf], ntfs_bitmap_buf
  1072.         call    ntfs_read_attr
  1073.         jc      .notfound
  1074.         mov     [ntfs_cur_attr], 0x90   ; $INDEX_ROOT
  1075.         and     [ntfs_cur_offs], 0
  1076.         mov     eax, [ntfs_data.cur_index_size]
  1077.         mov     [ntfs_cur_size], eax
  1078.         mov     eax, [ntfs_data.cur_index_buf]
  1079.         mov     [ntfs_cur_buf], eax
  1080.         call    ntfs_read_attr
  1081.         jnc     .ok
  1082.         cmp     [hd_error], 0
  1083.         jz      .notfound
  1084.         or      ebx, -1
  1085.         push    11
  1086.         jmp     .pop_ret
  1087. .ok:
  1088.         cmp     [ntfs_cur_read], 0x20
  1089.         jae     @f
  1090.         or      ebx, -1
  1091. .fserr:
  1092.         push    ERROR_FAT_TABLE
  1093.         jmp     .pop_ret
  1094. @@:
  1095.         pushad
  1096.         mov     esi, [ntfs_data.cur_index_buf]
  1097.         mov     eax, [esi+14h]
  1098.         add     eax, 10h
  1099.         cmp     [ntfs_cur_read], eax
  1100.         jae     .readok1
  1101.         add     eax, 1FFh
  1102.         shr     eax, 9
  1103.         cmp     eax, [ntfs_data.cur_index_size]
  1104.         ja      @f
  1105.         popad
  1106.         jmp     .fserr
  1107. @@:
  1108. ; reallocate
  1109.         push    eax
  1110.         push    [ntfs_data.cur_index_buf]
  1111.         call    kernel_free
  1112.         pop     eax
  1113.         mov     [ntfs_data.cur_index_size], eax
  1114.         push    eax
  1115.         call    kernel_alloc
  1116.         test    eax, eax
  1117.         jnz     @f
  1118.         and     [ntfs_data.cur_index_size], 0
  1119.         and     [ntfs_data.cur_index_buf], 0
  1120. .nomem:
  1121.         popad
  1122.         or      ebx, -1
  1123.         push    12
  1124.         pop     eax
  1125.         ret
  1126. @@:
  1127.         mov     [ntfs_data.cur_index_buf], eax
  1128.         popad
  1129.         jmp     .doit2
  1130. .readok1:
  1131.         mov     ebp, [esi+8]    ; subnode_size
  1132.         shr     ebp, 9
  1133.         cmp     ebp, [ntfs_data.cur_index_size]
  1134.         jbe     .ok2
  1135.         push    esi ebp
  1136.         push    ebp
  1137.         call    kernel_alloc
  1138.         pop     ebp esi
  1139.         test    eax, eax
  1140.         jz      .nomem
  1141.         mov     edi, eax
  1142.         mov     ecx, [ntfs_data.cur_index_size]
  1143.         shl     ecx, 9-2
  1144.         rep     movsd
  1145.         mov     esi, eax
  1146.         mov     [ntfs_data.cur_index_size], ebp
  1147.         push    esi ebp
  1148.         push    [ntfs_data.cur_index_buf]
  1149.         call    kernel_free
  1150.         pop     ebp esi
  1151.         mov     [ntfs_data.cur_index_buf], esi
  1152. .ok2:
  1153.         add     esi, 10h
  1154.         mov     ebx, [esp+10h]
  1155.         mov     edx, [esp+14h]
  1156.         push    dword [ebx+4]   ; read ANSI/UNICODE name
  1157.         mov     ebx, [ebx]
  1158. ; init header
  1159.         mov     edi, edx
  1160.         mov     ecx, 32/4
  1161.         xor     eax, eax
  1162.         rep     stosd
  1163.         mov     byte [edx], 1   ; version
  1164.         mov     ecx, [esp+4+18h]
  1165.         push    edx
  1166.         mov     edx, esp
  1167. ; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block,
  1168. ; ecx = number of blocks to read
  1169. ; edx -> parameters block: dd <output>, dd <flags>
  1170.         cmp     [ntfs_cur_iRecord], 5
  1171.         jz      .skip_specials
  1172. ; dot and dotdot entries
  1173.         push    esi
  1174.         xor     esi, esi
  1175.         call    .add_special_entry
  1176.         inc     esi
  1177.         call    .add_special_entry
  1178.         pop     esi
  1179. .skip_specials:
  1180. ; at first, dump index root
  1181.         add     esi, [esi]
  1182. .dump_root:
  1183.         test    byte [esi+0Ch], 2
  1184.         jnz     .dump_root_done
  1185.         call    .add_entry
  1186.         movzx   eax, word [esi+8]
  1187.         add     esi, eax
  1188.         jmp     .dump_root
  1189. .dump_root_done:
  1190. ; now dump all subnodes
  1191.         push    ecx edi
  1192.         mov     edi, ntfs_bitmap_buf
  1193.         mov     [ntfs_cur_buf], edi
  1194.         mov     ecx, 0x400/4
  1195.         xor     eax, eax
  1196.         rep     stosd
  1197.         mov     [ntfs_cur_attr], 0xB0   ; $BITMAP
  1198.         and     [ntfs_cur_offs], 0
  1199.         mov     [ntfs_cur_size], 2
  1200.         call    ntfs_read_attr
  1201.         pop     edi ecx
  1202.         push    0       ; save offset in $BITMAP attribute
  1203.         and     [ntfs_cur_offs], 0
  1204. .dumploop:
  1205.         mov     [ntfs_cur_attr], 0xA0
  1206.         mov     [ntfs_cur_size], ebp
  1207.         mov     eax, [ntfs_data.cur_index_buf]
  1208.         mov     esi, eax
  1209.         mov     [ntfs_cur_buf], eax
  1210.         push    [ntfs_cur_offs]
  1211.         mov     eax, [ntfs_cur_offs]
  1212.         imul    eax, ebp
  1213.         mov     [ntfs_cur_offs], eax
  1214.         call    ntfs_read_attr
  1215.         pop     [ntfs_cur_offs]
  1216.         mov     eax, ebp
  1217.         shl     eax, 9
  1218.         cmp     [ntfs_cur_read], eax
  1219.         jnz     .done
  1220.         push    eax
  1221.         mov     eax, [ntfs_cur_offs]
  1222.         and     eax, 0x400*8-1
  1223.         bt      dword [ntfs_bitmap_buf], eax
  1224.         pop     eax
  1225.         jnc     .dump_subnode_done
  1226.         cmp     dword [esi], 'INDX'
  1227.         jnz     .dump_subnode_done
  1228.         push    ebx
  1229.         mov     ebx, esi
  1230.         call    ntfs_restore_usa
  1231.         pop     ebx
  1232.         jc      .dump_subnode_done
  1233.         add     esi, 0x18
  1234.         add     esi, [esi]
  1235. .dump_subnode:
  1236.         test    byte [esi+0Ch], 2
  1237.         jnz     .dump_subnode_done
  1238.         call    .add_entry
  1239.         movzx   eax, word [esi+8]
  1240.         add     esi, eax
  1241.         jmp     .dump_subnode
  1242. .dump_subnode_done:
  1243.         inc     [ntfs_cur_offs]
  1244.         test    [ntfs_cur_offs], 0x400*8-1
  1245.         jnz     .dumploop
  1246.         mov     [ntfs_cur_attr], 0xB0
  1247.         push    ecx edi
  1248.         mov     edi, ntfs_bitmap_buf
  1249.         mov     [ntfs_cur_buf], edi
  1250.         mov     ecx, 0x400/4
  1251.         xor     eax, eax
  1252.         rep     stosd
  1253.         pop     edi ecx
  1254.         pop     eax
  1255.         push    [ntfs_cur_offs]
  1256.         inc     eax
  1257.         mov     [ntfs_cur_offs], eax
  1258.         mov     [ntfs_cur_size], 2
  1259.         push    eax
  1260.         call    ntfs_read_attr
  1261.         pop     eax
  1262.         pop     [ntfs_cur_offs]
  1263.         push    eax
  1264.         jmp     .dumploop
  1265. .done:
  1266.         pop     eax
  1267.         pop     edx
  1268.         mov     ebx, [edx+4]
  1269.         pop     edx
  1270.         xor     eax, eax
  1271.         dec     ecx
  1272.         js      @f
  1273.         mov     al, ERROR_END_OF_FILE
  1274. @@:
  1275.         mov     [esp+1Ch], eax
  1276.         mov     [esp+10h], ebx
  1277.         popad
  1278.         ret
  1279.  
  1280. .add_special_entry:
  1281.         mov     eax, [edx]
  1282.         inc     dword [eax+8]   ; new file found
  1283.         dec     ebx
  1284.         jns     .ret
  1285.         dec     ecx
  1286.         js      .ret
  1287.         inc     dword [eax+4]   ; new file block copied
  1288.         mov     eax, [edx+4]
  1289.         mov     [edi+4], eax
  1290. ;        mov     eax, dword [ntfs_bitmap_buf+0x20]
  1291. ;        or      al, 0x10
  1292.         mov     eax, 0x10
  1293.         stosd
  1294.         scasd
  1295.         push    edx
  1296.         mov     eax, dword [ntfs_bitmap_buf]
  1297.         mov     edx, dword [ntfs_bitmap_buf+4]
  1298.         call    ntfs_datetime_to_bdfe
  1299.         mov     eax, dword [ntfs_bitmap_buf+0x18]
  1300.         mov     edx, dword [ntfs_bitmap_buf+0x1C]
  1301.         call    ntfs_datetime_to_bdfe
  1302.         mov     eax, dword [ntfs_bitmap_buf+8]
  1303.         mov     edx, dword [ntfs_bitmap_buf+0xC]
  1304.         call    ntfs_datetime_to_bdfe
  1305.         pop     edx
  1306.         xor     eax, eax
  1307.         stosd
  1308.         stosd
  1309.         mov     al, '.'
  1310.         push    edi ecx
  1311.         lea     ecx, [esi+1]
  1312.         test    byte [edi-0x24], 1
  1313.         jz      @f
  1314.         rep     stosw
  1315.         pop     ecx
  1316.         xor     eax, eax
  1317.         stosw
  1318.         pop     edi
  1319.         add     edi, 520
  1320.         ret
  1321. @@:
  1322.         rep     stosb
  1323.         pop     ecx
  1324.         xor     eax, eax
  1325.         stosb
  1326.         pop     edi
  1327.         add     edi, 264
  1328. .ret:
  1329.         ret
  1330.  
  1331. .add_entry:
  1332. ; do not return DOS 8.3 names
  1333.         cmp     byte [esi+0x51], 2
  1334.         jz      .ret
  1335. ; do not return system files
  1336. ; ... note that there will be no bad effects if system files also were reported ...
  1337.         cmp     dword [esi], 0x10
  1338.         jb      .ret
  1339.         mov     eax, [edx]
  1340.         inc     dword [eax+8]   ; new file found
  1341.         dec     ebx
  1342.         jns     .ret
  1343.         dec     ecx
  1344.         js      .ret
  1345.         inc     dword [eax+4]   ; new file block copied
  1346.         mov     eax, [edx+4]    ; flags
  1347.  
  1348. ntfs_direntry_to_bdfe:
  1349.         mov     [edi+4], eax    ; ANSI/UNICODE name
  1350.         mov     eax, [esi+48h]
  1351.         test    eax, 0x10000000
  1352.         jz      @f
  1353.         and     eax, not 0x10000000
  1354.         or      al, 0x10
  1355. @@:
  1356.         stosd
  1357.         scasd
  1358.         push    edx
  1359.         mov     eax, [esi+0x18]
  1360.         mov     edx, [esi+0x1C]
  1361.         call    ntfs_datetime_to_bdfe
  1362.         mov     eax, [esi+0x30]
  1363.         mov     edx, [esi+0x34]
  1364.         call    ntfs_datetime_to_bdfe
  1365.         mov     eax, [esi+0x20]
  1366.         mov     edx, [esi+0x24]
  1367.         call    ntfs_datetime_to_bdfe
  1368.         pop     edx
  1369.         mov     eax, [esi+0x40]
  1370.         stosd
  1371.         mov     eax, [esi+0x44]
  1372.         stosd
  1373.         push    ecx esi edi
  1374.         movzx   ecx, byte [esi+0x50]
  1375.         add     esi, 0x52
  1376.         test    byte [edi-0x24], 1
  1377.         jz      .ansi
  1378.         shr     ecx, 1
  1379.         rep     movsd
  1380.         adc     ecx, ecx
  1381.         rep     movsw
  1382.         and     word [edi], 0
  1383.         pop     edi
  1384.         add     edi, 520
  1385.         pop     esi ecx
  1386.         ret
  1387. .ansi:
  1388.         jecxz   .skip
  1389. @@:
  1390.         lodsw
  1391.         call    uni2ansi_char
  1392.         stosb
  1393.         loop    @b
  1394. .skip:
  1395.         xor     al, al
  1396.         stosb
  1397.         pop     edi
  1398.         add     edi, 264
  1399.         pop     esi ecx
  1400.         ret
  1401.  
  1402. iglobal
  1403. _24             dd      24
  1404. _60             dd      60
  1405. _10000000       dd      10000000
  1406. days400year     dd      365*400+100-4+1
  1407. days100year     dd      365*100+25-1
  1408. days4year       dd      365*4+1
  1409. days1year       dd      365
  1410. months  dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1411. months2 dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1412. _400            dd      400
  1413. _100            dd      100
  1414. endg
  1415.  
  1416. ntfs_datetime_to_bdfe:
  1417. ; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
  1418.         push    eax
  1419.         mov     eax, edx
  1420.         xor     edx, edx
  1421.         div     [_10000000]
  1422.         xchg    eax, [esp]
  1423.         div     [_10000000]
  1424.         pop     edx
  1425. ; edx:eax = number of seconds since January 1, 1601
  1426.         push    eax
  1427.         mov     eax, edx
  1428.         xor     edx, edx
  1429.         div     [_60]
  1430.         xchg    eax, [esp]
  1431.         div     [_60]
  1432.         mov     [edi], dl
  1433.         pop     edx
  1434. ; edx:eax = number of minutes
  1435.         div     [_60]
  1436.         mov     [edi+1], dl
  1437. ; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
  1438.         xor     edx, edx
  1439.         div     [_24]
  1440.         mov     [edi+2], dl
  1441.         mov     [edi+3], byte 0
  1442. ; eax = number of days since January 1, 1601
  1443.         xor     edx, edx
  1444.         div     [days400year]
  1445.         imul    eax, 400
  1446.         add     eax, 1601
  1447.         mov     [edi+6], ax
  1448.         mov     eax, edx
  1449.         xor     edx, edx
  1450.         div     [days100year]
  1451.         cmp     al, 4
  1452.         jnz     @f
  1453.         dec     eax
  1454.         add     edx, [days100year]
  1455. @@:
  1456.         imul    eax, 100
  1457.         add     [edi+6], ax
  1458.         mov     eax, edx
  1459.         xor     edx, edx
  1460.         div     [days4year]
  1461.         shl     eax, 2
  1462.         add     [edi+6], ax
  1463.         mov     eax, edx
  1464.         xor     edx, edx
  1465.         div     [days1year]
  1466.         cmp     al, 4
  1467.         jnz     @f
  1468.         dec     eax
  1469.         add     edx, [days1year]
  1470. @@:
  1471.         add     [edi+6], ax
  1472.         push    esi edx
  1473.         mov     esi, months
  1474.         movzx   eax, word [edi+6]
  1475.         test    al, 3
  1476.         jnz     .noleap
  1477.         xor     edx, edx
  1478.         push    eax
  1479.         div     [_400]
  1480.         pop     eax
  1481.         test    edx, edx
  1482.         jz      .leap
  1483.         xor     edx, edx
  1484.         div     [_100]
  1485.         test    edx, edx
  1486.         jz      .noleap
  1487. .leap:
  1488.         mov     esi, months2
  1489. .noleap:
  1490.         pop     edx
  1491.         xor     eax, eax
  1492.         inc     eax
  1493. @@:
  1494.         sub     edx, [esi]
  1495.         jb      @f
  1496.         add     esi, 4
  1497.         inc     eax
  1498.         jmp     @b
  1499. @@:
  1500.         add     edx, [esi]
  1501.         pop     esi
  1502.         inc     edx
  1503.         mov     [edi+4], dl
  1504.         mov     [edi+5], al
  1505.         add     edi, 8
  1506.         ret
  1507.  
  1508. ;----------------------------------------------------------------
  1509. ;
  1510. ;  ntfs_HdRewrite - write to NTFS hard disk
  1511. ;
  1512. ;  esi  points to filename
  1513. ;  ebx  ignored (reserved)
  1514. ;  ecx  number of bytes to write, 0+
  1515. ;  edx  mem location to data
  1516. ;
  1517. ;  ret ebx = number of written bytes
  1518. ;      eax = 0 ok read or other = errormsg
  1519. ;
  1520. ;--------------------------------------------------------------
  1521. ntfs_HdRewrite:
  1522.         xor     ebx, ebx
  1523.         mov     eax, ERROR_UNSUPPORTED_FS
  1524.         ret
  1525.  
  1526. ;----------------------------------------------------------------
  1527. ;
  1528. ;  ntfs_HdWrite - write to NTFS hard disk
  1529. ;
  1530. ;  esi  points to filename
  1531. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1532. ;       may be ebx=0 - start from first byte
  1533. ;  ecx  number of bytes to write, 0+
  1534. ;  edx  mem location to data
  1535. ;
  1536. ;  ret ebx = bytes written (maybe 0)
  1537. ;      eax = 0 ok write or other = errormsg
  1538. ;
  1539. ;--------------------------------------------------------------
  1540. ntfs_HdWrite:
  1541.         xor     ebx, ebx
  1542.         mov     eax, ERROR_UNSUPPORTED_FS
  1543.         ret
  1544.  
  1545. ;----------------------------------------------------------------
  1546. ;
  1547. ;  ntfs_HdSetFileEnd - set end of file on NTFS hard disk
  1548. ;
  1549. ;  esi  points to filename
  1550. ;  ebx  points to 64-bit number = new file size
  1551. ;  ecx  ignored (reserved)
  1552. ;  edx  ignored (reserved)
  1553. ;
  1554. ;  ret eax = 0 ok or other = errormsg
  1555. ;
  1556. ;--------------------------------------------------------------
  1557. ntfs_HdSetFileEnd:
  1558. ntfs_HdSetFileInfo:
  1559. ;----------------------------------------------------------------
  1560. ;
  1561. ;  ntfs_HdDelete - delete file or empty folder from NTFS hard disk
  1562. ;
  1563. ;  esi  points to filename
  1564. ;
  1565. ;  ret  eax = 0 ok or other = errormsg
  1566. ;
  1567. ;--------------------------------------------------------------
  1568. ntfs_HdDelete:
  1569.         mov     eax, ERROR_UNSUPPORTED_FS
  1570.         ret
  1571.  
  1572. ntfs_HdGetFileInfo:
  1573.         mov     eax, ERROR_UNSUPPORTED_FS
  1574.         ret
  1575.  
  1576.