Subversion Repositories Kolibri OS

Rev

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