Subversion Repositories Kolibri OS

Rev

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