Subversion Repositories Kolibri OS

Rev

Rev 257 | 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. endg
  296.  
  297. ntfs_read_attr:
  298. ; in: global variables
  299. ; out: [ntfs_cur_read]
  300.         pushad
  301.         and     [ntfs_cur_read], 0
  302.         cmp     [ntfs_cur_iRecord], 0
  303.         jnz     .nomft
  304.         cmp     [ntfs_cur_attr], 0x80
  305.         jnz     .nomft
  306.         mov     eax, [ntfs_data.mft_retrieval_end]
  307.         inc     eax
  308.         mul     [ntfs_data.sectors_per_cluster]
  309.         cmp     eax, [ntfs_cur_offs]
  310.         jbe     .nomft
  311. ; precalculated part of $Mft $DATA
  312.         mov     esi, [ntfs_data.mft_retrieval]
  313.         mov     eax, [ntfs_cur_offs]
  314.         xor     edx, edx
  315.         div     [ntfs_data.sectors_per_cluster]
  316. ; eax = VCN, edx = offset in sectors from beginning of cluster
  317.         xor     ecx, ecx        ; ecx will contain LCN
  318. .mftscan:
  319.         add     ecx, [esi+4]
  320.         sub     eax, [esi]
  321.         jb      @f
  322.         add     esi, 8
  323.         push    eax
  324.         mov     eax, [ntfs_data.mft_retrieval_end]
  325.         shl     eax, 3
  326.         add     eax, [ntfs_data.mft_retrieval]
  327.         cmp     eax, esi
  328.         pop     eax
  329.         jnz     .mftscan
  330.         jmp     .nomft
  331. @@:
  332.         push    ecx
  333.         add     ecx, eax
  334.         add     ecx, [esi]
  335.         push    eax
  336.         push    edx
  337.         mov     eax, [ntfs_data.sectors_per_cluster]
  338.         mul     ecx
  339. ; eax = sector on partition
  340.         add     eax, [PARTITION_START]
  341.         pop     edx
  342.         add     eax, edx
  343.         mov     ebx, [ntfs_cur_buf]
  344.         pop     ecx
  345.         neg     ecx
  346.         imul    ecx, [ntfs_data.sectors_per_cluster]
  347.         sub     ecx, edx
  348.         cmp     ecx, [ntfs_cur_size]
  349.         jb      @f
  350.         mov     ecx, [ntfs_cur_size]
  351. @@:
  352. ; ecx = number of sequential sectors to read
  353.         call    hd_read
  354.         cmp     [hd_error], 0
  355.         jnz     .errread
  356.         add     [ntfs_cur_read], 0x200
  357.         dec     [ntfs_cur_size]
  358.         inc     [ntfs_cur_offs]
  359.         add     ebx, 0x200
  360.         mov     [ntfs_cur_buf], ebx
  361.         inc     eax
  362.         loop    @b
  363.         pop     ecx
  364.         xor     eax, eax
  365.         xor     edx, edx
  366.         cmp     [ntfs_cur_size], eax
  367.         jz      @f
  368.         add     esi, 8
  369.         push    eax
  370.         mov     eax, [ntfs_data.mft_retrieval_end]
  371.         shl     eax, 3
  372.         add     eax, [ntfs_data.mft_retrieval]
  373.         cmp     eax, esi
  374.         pop     eax
  375.         jz      .nomft
  376.         jmp     .mftscan
  377. @@:
  378.         popad
  379.         ret
  380. .errread:
  381.         pop     ecx
  382. .errret:
  383.         stc
  384.         popad
  385.         ret
  386. .nomft:
  387. ; 1. Read file record.
  388. ; N.B. This will do recursive call of read_attr for $MFT::$Data.
  389.         mov     eax, [ntfs_cur_iRecord]
  390.         mov     [ntfs_attr_iRecord], eax
  391.         and     [ntfs_attr_list], 0
  392.         or      [ntfs_attr_iBaseRecord], -1
  393.         call    ntfs_read_file_record
  394.         test    eax, eax
  395.         jz      .errret
  396. ; 2. Find required attribute.
  397.         mov     eax, [ntfs_data.frs_buffer]
  398. ; a) For auxiliary records, read base record
  399. ; N.B. If base record is present,
  400. ;      base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero
  401.         cmp     dword [eax+24h], 0
  402.         jz      @f
  403.         mov     eax, [eax+20h]
  404. ;        test    eax, eax
  405. ;        jz      @f
  406. .beginfindattr:
  407.         mov     [ntfs_attr_iRecord], eax
  408.         call    ntfs_read_file_record
  409.         test    eax, eax
  410.         jz      .errret
  411. @@:
  412. ; b) Scan for required attribute and for $ATTR_LIST
  413.         mov     eax, [ntfs_data.frs_buffer]
  414.         movzx   ecx, word [eax+14h]
  415.         add     eax, ecx
  416.         mov     ecx, [ntfs_cur_attr]
  417.         and     [ntfs_attr_offs], 0
  418. .scanattr:
  419.         cmp     dword [eax], -1
  420.         jz      .scandone
  421.         cmp     dword [eax], ecx
  422.         jz      .okattr
  423.         cmp     [ntfs_attr_iBaseRecord], -1
  424.         jnz     .scancont
  425.         cmp     dword [eax], 0x20       ; $ATTR_LIST
  426.         jnz     .scancont
  427.         mov     [ntfs_attr_list], eax
  428.         jmp     .scancont
  429. .okattr:
  430.         mov     [ntfs_attr_offs], eax
  431. .scancont:
  432.         add     eax, [eax+4]
  433.         jmp     .scanattr
  434. .scandone:
  435. ; c) Check for required offset and length
  436.         mov     ecx, [ntfs_attr_offs]
  437.         jecxz   .noattr
  438.         call    .doreadattr
  439.         jc      @f
  440.         cmp     [ntfs_cur_size], 0
  441.         jnz     .not_in_cur
  442. @@:
  443.         popad
  444.         ret
  445. .noattr:
  446. .not_in_cur:
  447.         cmp     [ntfs_cur_attr], 0x20
  448.         jz      @f
  449.         mov     ecx, [ntfs_attr_list]
  450.         test    ecx, ecx
  451.         jnz     .lookattr
  452. .ret_is_attr:
  453.         cmp     [ntfs_attr_offs], 1     ; CF set <=> ntfs_attr_offs == 0
  454.         popad
  455.         ret
  456. .lookattr:
  457. ; required attribute or required offset was not found in base record;
  458. ; it may be present in auxiliary records;
  459. ; scan $ATTR_LIST
  460.         mov     eax, [ntfs_attr_iBaseRecord]
  461.         cmp     eax, -1
  462.         jz      @f
  463.         call    ntfs_read_file_record
  464.         test    eax, eax
  465.         jz      .errret
  466.         or      [ntfs_attr_iBaseRecord], -1
  467. @@:
  468.         push    [ntfs_cur_offs]
  469.         push    [ntfs_cur_size]
  470.         push    [ntfs_cur_read]
  471.         push    [ntfs_cur_buf]
  472.         xor     edx, edx
  473.         mov     [ntfs_cur_offs], edx
  474.         mov     [ntfs_cur_size], 2
  475.         and     [ntfs_cur_read], 0
  476.         mov     [ntfs_cur_buf], ntfs_attrlist_buf
  477.         push    edx
  478.         call    .doreadattr
  479.         pop     edx
  480.         mov     ebp, [ntfs_cur_read]
  481.         pop     [ntfs_cur_buf]
  482.         pop     [ntfs_cur_read]
  483.         pop     [ntfs_cur_size]
  484.         pop     [ntfs_cur_offs]
  485.         jc      .errret
  486.         mov     esi, ntfs_attrlist_buf
  487.         or      edi, -1
  488. .scanliststart:
  489.         lea     ebp, [ebp+esi-1Ah]
  490.         mov     eax, [ntfs_cur_attr]
  491. .scanlist:
  492.         cmp     esi, ebp
  493.         jae     .scanlistdone
  494.         cmp     eax, [esi]
  495.         jz      @f
  496. .scanlistcont:
  497.         movzx   ecx, word [esi+4]
  498.         add     esi, ecx
  499.         jmp     .scanlist
  500. @@:
  501.         push    eax
  502.         mov     eax, [esi+8]
  503.         imul    eax, [ntfs_data.sectors_per_cluster]
  504.         cmp     eax, [ntfs_cur_offs]
  505.         pop     eax
  506.         ja      @f
  507.         mov     edi, [esi+10h]  ; keep previous iRecord
  508.         jmp     .scanlistcont
  509. @@:
  510.         cmp     edi, -1
  511.         jnz     @f
  512.         popad
  513.         ret
  514. @@:
  515.         mov     eax, [ntfs_cur_iRecord]
  516.         mov     [ntfs_attr_iBaseRecord], eax
  517.         mov     eax, edi
  518.         jmp     .beginfindattr
  519. .scanlistdone:
  520.         sub     ebp, ntfs_attrlist_buf-1Ah
  521.         test    ebp, 1FFh
  522.         jnz     .ret_is_attr
  523.         test    edx, edx
  524.         jnz     @f
  525.         inc     edx
  526.         cmp     ebp, 0x400
  527.         jnz     .ret_is_attr
  528. @@:
  529.         inc     edx
  530.         push    esi edi
  531.         mov     esi, ntfs_attrlist_buf+0x200
  532.         mov     edi, ntfs_attrlist_buf
  533.         mov     ecx, 0x200/4
  534.         rep     movsd
  535.         pop     edi esi
  536.         sub     esi, 0x200
  537.         push    [ntfs_cur_offs]
  538.         push    [ntfs_cur_size]
  539.         push    [ntfs_cur_read]
  540.         push    [ntfs_cur_buf]
  541.         mov     [ntfs_cur_offs], edx
  542.         mov     [ntfs_cur_size], 1
  543.         and     [ntfs_cur_read], 0
  544.         mov     [ntfs_cur_buf], ntfs_attrlist_buf+0x200
  545.         push    esi edx
  546.         call    .doreadattr
  547.         pop     edx esi
  548.         mov     ebp, [ntfs_cur_read]
  549.         pop     [ntfs_cur_buf]
  550.         pop     [ntfs_cur_read]
  551.         pop     [ntfs_cur_size]
  552.         pop     [ntfs_cur_offs]
  553.         jc      .errret
  554.         jmp     .scanliststart
  555.  
  556. .doreadattr:
  557.         cmp     byte [ecx+8], 0
  558.         jnz     .nonresident
  559.         mov     eax, [ecx+10h]  ; length
  560.         mov     esi, eax
  561.         mov     edx, [ntfs_cur_offs]
  562.         shr     eax, 9
  563.         cmp     eax, edx
  564.         jb      .okret
  565.         shl     edx, 9
  566.         sub     esi, edx
  567.         movzx   eax, word [ecx+14h]
  568.         add     edx, eax
  569.         add     edx, ecx        ; edx -> data
  570.         mov     eax, [ntfs_cur_size]
  571.         cmp     eax, (0xFFFFFFFF shr 9)+1
  572.         jbe     @f
  573.         mov     eax, (0xFFFFFFFF shr 9)+1
  574. @@:
  575.         shl     eax, 9
  576.         cmp     eax, esi
  577.         jbe     @f
  578.         mov     eax, esi
  579. @@:
  580. ; eax = length, edx -> data
  581.         mov     [ntfs_cur_read], eax
  582.         mov     ecx, eax
  583.         mov     eax, edx
  584.         mov     ebx, [ntfs_cur_buf]
  585.         call    memmove
  586.         clc
  587.         ret
  588. .nonresident:
  589.         mov     eax, [ecx+30h]  ; FileSize
  590.         mov     edx, [ecx+34h]
  591.         add     eax, 0x1FF
  592.         adc     edx, 0
  593.         shrd    eax, edx, 9
  594.         sub     eax, [ntfs_cur_offs]
  595.         ja      @f
  596. ; return with nothing read
  597. .okret:
  598.         clc
  599.         ret
  600. @@:
  601. ; reduce read length
  602.         cmp     [ntfs_cur_size], eax
  603.         jb      @f
  604.         mov     [ntfs_cur_size], eax
  605. @@:
  606.         cmp     [ntfs_cur_size], 0
  607.         jz      .okret
  608.         mov     eax, [ntfs_cur_offs]
  609.         xor     edx, edx
  610.         div     [ntfs_data.sectors_per_cluster]
  611.         sub     eax, [ecx+10h]  ; first_vbo
  612.         jb      .okret
  613. ; eax = cluster, edx = starting sector
  614.         sub     esp, 10h
  615.         movzx   esi, word [ecx+20h]     ; mcb_info_ofs
  616.         add     esi, ecx
  617.         xor     ebp, ebp
  618. .readloop:
  619.         call    ntfs_decode_mcb_entry
  620.         jnc     .break
  621.         add     ebp, [esp+8]
  622.         sub     eax, [esp]
  623.         jae     .readloop
  624.         push    ecx
  625.         push    eax
  626.         add     eax, [esp+8]
  627.         add     eax, ebp
  628.         imul    eax, [ntfs_data.sectors_per_cluster]
  629.         add     eax, edx
  630.         add     eax, [PARTITION_START]
  631.         pop     ecx
  632.         neg     ecx
  633.         imul    ecx, [ntfs_data.sectors_per_cluster]
  634.         sub     ecx, edx
  635.         cmp     ecx, [ntfs_cur_size]
  636.         jb      @f
  637.         mov     ecx, [ntfs_cur_size]
  638. @@:
  639.         mov     ebx, [ntfs_cur_buf]
  640. @@:
  641.         call    hd_read
  642.         cmp     [hd_error], 0
  643.         jnz     .errread2
  644.         add     ebx, 0x200
  645.         mov     [ntfs_cur_buf], ebx
  646.         inc     eax
  647.         add     [ntfs_cur_read], 0x200
  648.         dec     [ntfs_cur_size]
  649.         inc     [ntfs_cur_offs]
  650.         loop    @b
  651.         pop     ecx
  652.         cmp     [ntfs_cur_size], 0
  653.         jnz     .readloop
  654.         add     esp, 10h
  655.         jmp     .okret
  656. .errread2:
  657.         pop     ecx
  658.         add     esp, 10h
  659.         jmp     .errret
  660. .break:
  661.         add     esp, 10h        ; CF=0
  662.         ret
  663.  
  664. ntfs_read_file_record:
  665. ; in: eax=iRecord
  666. ; out: [ntfs_data.frs_buffer] contains information
  667. ;      eax=0 - failed, eax=1 - success
  668. ; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size]
  669.         push    ecx edx
  670.         mov     ecx, [ntfs_data.frs_size]
  671.         mul     ecx
  672.         shrd    eax, edx, 9
  673.         shr     edx, 9
  674.         jnz     .err
  675.         push    [ntfs_cur_iRecord]
  676.         push    [ntfs_cur_attr]
  677.         push    [ntfs_cur_offs]
  678.         push    [ntfs_cur_size]
  679.         push    [ntfs_cur_buf]
  680.         push    [ntfs_cur_read]
  681.         mov     [ntfs_cur_attr], 0x80   ; $DATA
  682.         and     [ntfs_cur_iRecord], 0   ; $Mft
  683.         mov     [ntfs_cur_offs], eax
  684.         shr     ecx, 9
  685.         mov     [ntfs_cur_size], ecx
  686.         mov     eax, [ntfs_data.frs_buffer]
  687.         mov     [ntfs_cur_buf], eax
  688.         call    ntfs_read_attr
  689.         mov     eax, [ntfs_cur_read]
  690.         pop     [ntfs_cur_read]
  691.         pop     [ntfs_cur_buf]
  692.         pop     [ntfs_cur_size]
  693.         pop     [ntfs_cur_offs]
  694.         pop     [ntfs_cur_attr]
  695.         pop     [ntfs_cur_iRecord]
  696.         pop     edx ecx
  697.         jc      .errret
  698.         cmp     eax, [ntfs_data.frs_size]
  699.         jnz     .errret
  700.         mov     eax, [ntfs_data.frs_buffer]
  701.         cmp     dword [eax], 'FILE'
  702.         jnz     .errret
  703.         push    ebx
  704.         mov     ebx, eax
  705.         call    ntfs_restore_usa_frs
  706.         pop     ebx
  707.         setnc   al
  708.         movzx   eax, al
  709. .ret:
  710.         ret
  711. .err:
  712.         pop     edx ecx
  713. .errret:
  714.         xor     eax, eax
  715.         ret
  716.  
  717. ntfs_restore_usa_frs:
  718.         mov     eax, [ntfs_data.frs_size]
  719. ntfs_restore_usa:
  720.         pushad
  721.         shr     eax, 9
  722.         mov     ecx, eax
  723.         inc     eax
  724.         cmp     [ebx+6], ax
  725.         jnz     .err
  726.         movzx   eax, word [ebx+4]
  727.         lea     esi, [eax+ebx]
  728.         lodsw
  729.         mov     edx, eax
  730.         lea     edi, [ebx+0x1FE]
  731. @@:
  732.         cmp     [edi], dx
  733.         jnz     .err
  734.         lodsw
  735.         stosw
  736.         add     edi, 0x1FE
  737.         loop    @b
  738.         popad
  739.         clc
  740.         ret
  741. .err:
  742.         popad
  743.         stc
  744.         ret
  745.  
  746. ntfs_decode_mcb_entry:
  747.         push    eax ecx edi
  748.         lea     edi, [esp+16]
  749.         xor     eax, eax
  750.         lodsb
  751.         test    al, al
  752.         jz      .end
  753.         mov     ecx, eax
  754.         and     ecx, 0xF
  755.         cmp     ecx, 8
  756.         ja      .end
  757.         push    ecx
  758.         rep     movsb
  759.         pop     ecx
  760.         sub     ecx, 8
  761.         neg     ecx
  762.         cmp     byte [esi-1], 80h
  763.         jae     .end
  764.         push    eax
  765.         xor     eax, eax
  766.         rep     stosb
  767.         pop     ecx
  768.         shr     ecx, 4
  769.         cmp     ecx, 8
  770.         ja      .end
  771.         push    ecx
  772.         rep     movsb
  773.         pop     ecx
  774.         sub     ecx, 8
  775.         neg     ecx
  776.         cmp     byte [esi-1], 80h
  777.         sbb     eax, eax
  778.         inc     eax
  779.         rep     stosb
  780.         stc
  781. .end:
  782.         pop     edi ecx eax
  783.         ret
  784.  
  785. ;----------------------------------------------------------------
  786. ;
  787. ;  ntfs_HdRead - read NTFS hard disk
  788. ;
  789. ;  esi  points to filename
  790. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  791. ;       may be ebx=0 - start from first byte
  792. ;  ecx  number of bytes to read, 0+
  793. ;  edx  mem location to return data
  794. ;
  795. ;  ret ebx = bytes read or 0xffffffff file not found
  796. ;      eax = 0 ok read or other = errormsg
  797. ;
  798. ;--------------------------------------------------------------
  799. ntfs_HdRead:
  800.         or      ebx, -1
  801.         mov     eax, ERROR_UNSUPPORTED_FS
  802.         ret
  803.  
  804. ;----------------------------------------------------------------
  805. ;
  806. ;  ntfs_HdReadFolder - read NTFS hard disk folder
  807. ;
  808. ;  esi  points to filename
  809. ;  ebx  pointer to structure 32-bit number = first wanted block, 0+
  810. ;                          & flags (bitfields)
  811. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  812. ;  ecx  number of blocks to read, 0+
  813. ;  edx  mem location to return data
  814. ;
  815. ;  ret ebx = blocks read or 0xffffffff folder not found
  816. ;      eax = 0 ok read or other = errormsg
  817. ;
  818. ;--------------------------------------------------------------
  819. ntfs_HdReadFolder:
  820.         mov     eax, 5          ; root cluster
  821.         cmp     byte [esi], 0
  822.         jz      .doit
  823. ;        call    ntfs_find_lfn
  824. ;        jnc     .doit
  825. .notfound:
  826.         or      ebx, -1
  827.         push    ERROR_FILE_NOT_FOUND
  828. .pop_ret:
  829.         pop     eax
  830.         ret
  831. .doit:
  832.         mov     [ntfs_cur_iRecord], eax
  833. .doit2:
  834.         mov     [ntfs_cur_attr], 0x90   ; $INDEX_ROOT
  835.         and     [ntfs_cur_offs], 0
  836.         mov     eax, [ntfs_data.cur_index_size]
  837.         mov     [ntfs_cur_size], eax
  838.         mov     eax, [ntfs_data.cur_index_buf]
  839.         mov     [ntfs_cur_buf], eax
  840.         call    ntfs_read_attr
  841.         jnc     .ok
  842.         cmp     [hd_error], 0
  843.         jz      .notfound
  844.         or      ebx, -1
  845.         push    11
  846.         jmp     .pop_ret
  847. .ok:
  848.         cmp     [ntfs_cur_read], 0x20
  849.         jae     @f
  850.         or      ebx, -1
  851. .fserr:
  852.         push    ERROR_FAT_TABLE
  853.         jmp     .pop_ret
  854. @@:
  855.         pushad
  856.         mov     esi, [ntfs_data.cur_index_buf]
  857.         mov     eax, [esi+14h]
  858.         add     eax, 10h
  859.         cmp     [ntfs_cur_read], eax
  860.         jae     .readok1
  861.         add     eax, 1FFh
  862.         shr     eax, 9
  863.         cmp     eax, [ntfs_data.cur_index_size]
  864.         ja      @f
  865.         popad
  866.         jmp     .fserr
  867. @@:
  868. ; reallocate
  869.         push    eax
  870.         push    [ntfs_data.cur_index_buf]
  871.         call    kernel_free
  872.         pop     eax
  873.         mov     [ntfs_data.cur_index_size], eax
  874.         push    eax
  875.         call    kernel_alloc
  876.         test    eax, eax
  877.         jnz     @f
  878.         and     [ntfs_data.cur_index_size], 0
  879.         and     [ntfs_data.cur_index_buf], 0
  880. .nomem:
  881.         popad
  882.         or      ebx, -1
  883.         push    12
  884.         pop     eax
  885.         ret
  886. @@:
  887.         mov     [ntfs_data.cur_index_buf], eax
  888.         popad
  889.         jmp     .doit2
  890. .readok1:
  891.         mov     ebp, [esi+8]    ; subnode_size
  892.         shr     ebp, 9
  893.         cmp     ebp, [ntfs_data.cur_index_size]
  894.         jbe     .ok2
  895.         push    esi ebp
  896.         push    ebp
  897.         call    kernel_alloc
  898.         pop     ebp esi
  899.         test    eax, eax
  900.         jz      .nomem
  901.         mov     edi, eax
  902.         mov     ecx, [ntfs_data.cur_index_size]
  903.         shl     ecx, 9-2
  904.         rep     movsd
  905.         mov     esi, eax
  906.         mov     [ntfs_data.cur_index_size], ebp
  907.         push    esi ebp
  908.         push    [ntfs_data.cur_index_buf]
  909.         call    kernel_free
  910.         pop     ebp esi
  911.         mov     [ntfs_data.cur_index_buf], esi
  912. .ok2:
  913.         add     esi, 10h
  914.         mov     ebx, [esp+10h]
  915.         mov     edx, [esp+14h]
  916.         push    dword [ebx+4]   ; read ANSI/UNICODE name
  917.         mov     ebx, [ebx]
  918. ; init header
  919.         mov     edi, edx
  920.         mov     ecx, 32/4
  921.         xor     eax, eax
  922.         rep     stosd
  923.         mov     byte [edx], 1   ; version
  924.         mov     ecx, [esp+4+18h]
  925.         push    edx
  926.         mov     edx, esp
  927. ; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block,
  928. ; ecx = number of blocks to read
  929. ; edx -> parameters block: dd <output>, dd <flags>
  930. ; at first, dump index root
  931.         add     esi, [esi]
  932. .dump_root:
  933.         test    byte [esi+0Ch], 2
  934.         jnz     .dump_root_done
  935.         call    .add_entry
  936.         movzx   eax, word [esi+8]
  937.         add     esi, eax
  938.         jmp     .dump_root
  939. .dump_root_done:
  940. ; now dump all subnodes
  941.         push    ecx edi
  942.         mov     edi, ntfs_bitmap_buf
  943.         mov     [ntfs_cur_buf], edi
  944.         mov     ecx, 0x400/4
  945.         xor     eax, eax
  946.         rep     stosd
  947.         mov     [ntfs_cur_attr], 0xB0   ; $BITMAP
  948.         and     [ntfs_cur_offs], 0
  949.         mov     [ntfs_cur_size], 2
  950.         call    ntfs_read_attr
  951.         pop     edi ecx
  952.         push    0       ; save offset in $BITMAP attribute
  953.         and     [ntfs_cur_offs], 0
  954. .dumploop:
  955.         mov     [ntfs_cur_attr], 0xA0
  956.         mov     [ntfs_cur_size], ebp
  957.         mov     eax, [ntfs_data.cur_index_buf]
  958.         mov     esi, eax
  959.         mov     [ntfs_cur_buf], eax
  960.         push    [ntfs_cur_offs]
  961.         call    ntfs_read_attr
  962.         pop     [ntfs_cur_offs]
  963.         mov     eax, ebp
  964.         shl     eax, 9
  965.         cmp     [ntfs_cur_read], eax
  966.         jnz     .done
  967.         push    eax
  968.         mov     eax, [ntfs_cur_offs]
  969.         and     eax, 0x400*8-1
  970.         bt      dword [ntfs_bitmap_buf], eax
  971.         pop     eax
  972.         jnc     .dump_subnode_done
  973.         cmp     dword [esi], 'INDX'
  974.         jnz     .dump_subnode_done
  975.         push    ebx
  976.         mov     ebx, esi
  977.         call    ntfs_restore_usa
  978.         pop     ebx
  979.         jc      .dump_subnode_done
  980.         add     esi, 0x18
  981.         add     esi, [esi]
  982. .dump_subnode:
  983.         test    byte [esi+0Ch], 2
  984.         jnz     .dump_subnode_done
  985.         call    .add_entry
  986.         movzx   eax, word [esi+8]
  987.         add     esi, eax
  988.         jmp     .dump_subnode
  989. .dump_subnode_done:
  990.         inc     [ntfs_cur_offs]
  991.         test    [ntfs_cur_offs], 0x400*8-1
  992.         jnz     .dumploop
  993.         mov     [ntfs_cur_attr], 0xB0
  994.         push    ecx edi
  995.         mov     edi, ntfs_bitmap_buf
  996.         mov     [ntfs_cur_buf], edi
  997.         mov     ecx, 0x400/4
  998.         xor     eax, eax
  999.         rep     stosd
  1000.         pop     edi ecx
  1001.         pop     eax
  1002.         push    [ntfs_cur_offs]
  1003.         inc     eax
  1004.         mov     [ntfs_cur_offs], eax
  1005.         mov     [ntfs_cur_size], 2
  1006.         push    eax
  1007.         call    ntfs_read_attr
  1008.         pop     eax
  1009.         pop     [ntfs_cur_offs]
  1010.         push    eax
  1011.         jmp     .dumploop
  1012. .done:
  1013.         pop     eax
  1014.         pop     edx
  1015.         mov     ebx, [edx+4]
  1016.         pop     edx
  1017.         xor     eax, eax
  1018.         dec     ecx
  1019.         js      @f
  1020.         mov     al, ERROR_END_OF_FILE
  1021. @@:
  1022.         mov     [esp+1Ch], eax
  1023.         mov     [esp+10h], ebx
  1024.         popad
  1025.         ret
  1026.  
  1027. .add_entry:
  1028. ; do not return DOS 8.3 names
  1029.         cmp     byte [esi+0x51], 2
  1030.         jz      .ret
  1031. ; do not return system files
  1032. ; ... note that there will be no bad effects if system files also were reported ...
  1033.         cmp     dword [esi], 0x10
  1034.         jb      .ret
  1035.         mov     eax, [edx]
  1036.         inc     dword [eax+8]   ; new file found
  1037.         dec     ebx
  1038.         jns     .ret
  1039.         dec     ecx
  1040.         js      .ret
  1041.         inc     dword [eax+4]   ; new file block copied
  1042.         mov     eax, [edx+4]    ; flags
  1043.         call    ntfs_direntry_to_bdfe
  1044. .ret:
  1045.         ret
  1046.  
  1047. ntfs_direntry_to_bdfe:
  1048.         mov     [edi+4], eax    ; ANSI/UNICODE name
  1049.         mov     eax, [esi+48h]
  1050.         test    eax, 0x10000000
  1051.         jz      @f
  1052.         and     eax, not 0x10000000
  1053.         or      al, 0x10
  1054. @@:
  1055.         stosd
  1056.         scasd
  1057.         push    edx
  1058.         mov     eax, [esi+0x18]
  1059.         mov     edx, [esi+0x1C]
  1060.         call    ntfs_datetime_to_bdfe
  1061.         mov     eax, [esi+0x30]
  1062.         mov     edx, [esi+0x34]
  1063.         call    ntfs_datetime_to_bdfe
  1064.         mov     eax, [esi+0x20]
  1065.         mov     edx, [esi+0x24]
  1066.         call    ntfs_datetime_to_bdfe
  1067.         pop     edx
  1068.         mov     eax, [esi+0x40]
  1069.         stosd
  1070.         mov     eax, [esi+0x44]
  1071.         stosd
  1072.         push    ecx esi edi
  1073.         movzx   ecx, byte [esi+0x50]
  1074.         add     esi, 0x52
  1075.         test    byte [edi-0x24], 1
  1076.         jz      .ansi
  1077.         shr     ecx, 1
  1078.         rep     movsd
  1079.         adc     ecx, ecx
  1080.         rep     movsw
  1081.         and     word [edi], 0
  1082.         pop     edi
  1083.         add     edi, 520
  1084.         pop     esi ecx
  1085.         ret
  1086. .ansi:
  1087.         jecxz   .skip
  1088. @@:
  1089.         lodsw
  1090.         call    uni2ansi_char
  1091.         stosb
  1092.         loop    @b
  1093. .skip:
  1094.         xor     al, al
  1095.         stosb
  1096.         pop     edi
  1097.         add     edi, 264
  1098.         pop     esi ecx
  1099.         ret
  1100.  
  1101. iglobal
  1102. _24             dd      24
  1103. _60             dd      60
  1104. _10000000       dd      10000000
  1105. days400year     dd      365*400+100-4+1
  1106. days100year     dd      365*100+25-1
  1107. days4year       dd      365*4+1
  1108. days1year       dd      365
  1109. months  dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1110. months2 dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1111. _400            dd      400
  1112. _100            dd      100
  1113. endg
  1114.  
  1115. ntfs_datetime_to_bdfe:
  1116. ; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
  1117.         push    eax
  1118.         mov     eax, edx
  1119.         xor     edx, edx
  1120.         div     [_10000000]
  1121.         xchg    eax, [esp]
  1122.         div     [_10000000]
  1123.         pop     edx
  1124. ; edx:eax = number of seconds since January 1, 1601
  1125.         push    eax
  1126.         mov     eax, edx
  1127.         xor     edx, edx
  1128.         div     [_60]
  1129.         xchg    eax, [esp]
  1130.         div     [_60]
  1131.         mov     [edi], dl
  1132.         pop     edx
  1133. ; edx:eax = number of minutes
  1134.         div     [_60]
  1135.         mov     [edi+1], dl
  1136. ; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
  1137.         xor     edx, edx
  1138.         div     [_24]
  1139.         mov     [edi+2], dl
  1140.         mov     [edi+3], byte 0
  1141. ; eax = number of days since January 1, 1601
  1142.         xor     edx, edx
  1143.         div     [days400year]
  1144.         imul    eax, 400
  1145.         add     eax, 1601
  1146.         mov     [edi+6], ax
  1147.         mov     eax, edx
  1148.         xor     edx, edx
  1149.         div     [days100year]
  1150.         cmp     al, 4
  1151.         jnz     @f
  1152.         dec     eax
  1153.         add     edx, [days100year]
  1154. @@:
  1155.         imul    eax, 100
  1156.         add     [edi+6], ax
  1157.         mov     eax, edx
  1158.         xor     edx, edx
  1159.         div     [days4year]
  1160.         shl     eax, 2
  1161.         add     [edi+6], ax
  1162.         mov     eax, edx
  1163.         xor     edx, edx
  1164.         div     [days1year]
  1165.         cmp     al, 4
  1166.         jnz     @f
  1167.         dec     eax
  1168.         add     edx, [days1year]
  1169. @@:
  1170.         add     [edi+6], ax
  1171.         push    esi edx
  1172.         mov     esi, months
  1173.         movzx   eax, word [edi+6]
  1174.         test    al, 3
  1175.         jnz     .noleap
  1176.         xor     edx, edx
  1177.         push    eax
  1178.         div     [_400]
  1179.         pop     eax
  1180.         test    edx, edx
  1181.         jz      .leap
  1182.         xor     edx, edx
  1183.         div     [_100]
  1184.         test    edx, edx
  1185.         jz      .noleap
  1186. .leap:
  1187.         mov     esi, months2
  1188. .noleap:
  1189.         pop     edx
  1190.         xor     eax, eax
  1191.         inc     eax
  1192. @@:
  1193.         sub     edx, [esi]
  1194.         jb      @f
  1195.         add     esi, 4
  1196.         inc     eax
  1197.         jmp     @b
  1198. @@:
  1199.         add     edx, [esi]
  1200.         pop     esi
  1201.         inc     edx
  1202.         mov     [edi+4], dl
  1203.         mov     [edi+5], al
  1204.         add     edi, 8
  1205.         ret
  1206.  
  1207. ;----------------------------------------------------------------
  1208. ;
  1209. ;  ntfs_HdRewrite - write to NTFS hard disk
  1210. ;
  1211. ;  esi  points to filename
  1212. ;  ebx  ignored (reserved)
  1213. ;  ecx  number of bytes to write, 0+
  1214. ;  edx  mem location to data
  1215. ;
  1216. ;  ret ebx = number of written bytes
  1217. ;      eax = 0 ok read or other = errormsg
  1218. ;
  1219. ;--------------------------------------------------------------
  1220. ntfs_HdRewrite:
  1221.         xor     ebx, ebx
  1222.         mov     eax, ERROR_UNSUPPORTED_FS
  1223.         ret
  1224.  
  1225. ;----------------------------------------------------------------
  1226. ;
  1227. ;  ntfs_HdWrite - write to NTFS hard disk
  1228. ;
  1229. ;  esi  points to filename
  1230. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1231. ;       may be ebx=0 - start from first byte
  1232. ;  ecx  number of bytes to write, 0+
  1233. ;  edx  mem location to data
  1234. ;
  1235. ;  ret ebx = bytes written (maybe 0)
  1236. ;      eax = 0 ok write or other = errormsg
  1237. ;
  1238. ;--------------------------------------------------------------
  1239. ntfs_HdWrite:
  1240.         xor     ebx, ebx
  1241.         mov     eax, ERROR_UNSUPPORTED_FS
  1242.         ret
  1243.  
  1244. ;----------------------------------------------------------------
  1245. ;
  1246. ;  ntfs_HdSetFileEnd - set end of file on NTFS hard disk
  1247. ;
  1248. ;  esi  points to filename
  1249. ;  ebx  points to 64-bit number = new file size
  1250. ;  ecx  ignored (reserved)
  1251. ;  edx  ignored (reserved)
  1252. ;
  1253. ;  ret eax = 0 ok or other = errormsg
  1254. ;
  1255. ;--------------------------------------------------------------
  1256. ntfs_HdSetFileEnd:
  1257. ntfs_HdSetFileInfo:
  1258. ;----------------------------------------------------------------
  1259. ;
  1260. ;  ntfs_HdDelete - delete file or empty folder from NTFS hard disk
  1261. ;
  1262. ;  esi  points to filename
  1263. ;
  1264. ;  ret  eax = 0 ok or other = errormsg
  1265. ;
  1266. ;--------------------------------------------------------------
  1267. ntfs_HdDelete:
  1268.         mov     eax, ERROR_UNSUPPORTED_FS
  1269.         ret
  1270.  
  1271. ntfs_HdGetFileInfo:
  1272.         mov     eax, ERROR_UNSUPPORTED_FS
  1273.         ret
  1274.  
  1275.