Subversion Repositories Kolibri OS

Rev

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