Subversion Repositories Kolibri OS

Rev

Rev 6262 | Rev 6471 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
  4. ;;  Distributed under terms of the GNU General Public License.  ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 6468 $
  9.  
  10. ; FAT external functions
  11. ;   in:
  12. ; ebx -> parameter structure of sysfunc 70
  13. ; ebp -> FAT structure
  14. ; esi -> path string
  15. ;   out:
  16. ; eax, ebx = return values for sysfunc 70
  17. iglobal
  18. align 4
  19. fat_user_functions:
  20.         dd      fat_free
  21.         dd      (fat_user_functions_end - fat_user_functions - 4) / 4
  22.         dd      fat_Read
  23.         dd      fat_ReadFolder
  24.         dd      fat_CreateFile
  25.         dd      fat_Write
  26.         dd      fat_SetFileEnd
  27.         dd      fat_GetFileInfo
  28.         dd      fat_SetFileInfo
  29.         dd      0
  30.         dd      fat_Delete
  31.         dd      fat_CreateFolder
  32. fat_user_functions_end:
  33. endg
  34.  
  35. cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
  36.  
  37. PUSHAD_EAX equ [esp+28]
  38. PUSHAD_ECX equ [esp+24]
  39. PUSHAD_EDX equ [esp+20]
  40. PUSHAD_EBX equ [esp+16]
  41. PUSHAD_EBP equ [esp+8]
  42. PUSHAD_ESI equ [esp+4]
  43. PUSHAD_EDI equ [esp+0]
  44.  
  45. ; Internal data for every FAT partition.
  46. struct FAT PARTITION
  47. fs_type             db  ?
  48. fat_change          db  ?   ; 1=fat has changed
  49.                     rb  2
  50. Lock                MUTEX   ; currently operations with one partition
  51. ; can not be executed in parallel since the legacy code is not ready
  52. SECTORS_PER_FAT     dd  ?
  53. NUMBER_OF_FATS      dd  ?
  54. SECTORS_PER_CLUSTER dd  ?
  55. BYTES_PER_SECTOR    dd  ?   ; Note: if BPS <> 512 need lots of changes
  56. ROOT_CLUSTER        dd  ?   ; first rootdir cluster
  57. FAT_START           dd  ?   ; start of fat table
  58. ROOT_START          dd  ?   ; start of rootdir (only fat16)
  59. ROOT_SECTORS        dd  ?   ; count of rootdir sectors (only fat16)
  60. DATA_START          dd  ?   ; start of data area (=first cluster 2)
  61. LAST_CLUSTER        dd  ?   ; last availabe cluster
  62. ADR_FSINFO          dd  ?   ; used only by fat32
  63. fatRESERVED         dd  ?
  64. fatBAD              dd  ?
  65. fatEND              dd  ?
  66. fatMASK             dd  ?
  67. fatStartScan        dd  ?
  68. cluster_tmp         dd  ?   ; used by analyze_directory and analyze_directory_to_write
  69. longname_sec1       dd  ?   ; used by analyze_directory to save 2 previous
  70. longname_sec2       dd  ?   ; directory sectors for delete long filename
  71. fat_in_cache        dd  ?
  72. ; For FAT16/FAT32, this points to 512-byte buffer for the current sector of FAT.
  73. ; For FAT12, the entire FAT structure is read
  74. ; and unpacked from 12bit per cluster to word per cluster.
  75. ; Note: work with unpacked copy of FAT12 means
  76. ; additional memory and additional code for packing/unpacking.
  77. ; I'm not sure that the economy justifies the cost, but anyway,
  78. ; there is how work was done before my edits, and I'm just keeping the principle.
  79. fat_cache_ptr       dd  ?
  80. fat12_unpacked_ptr  dd  ?
  81. buffer              rb  512
  82. fsinfo_buffer       rb  512
  83. ends
  84.  
  85. uglobal
  86. align 4
  87. partition_count     dd  ?   ; partitions found by set_FAT32_variables
  88. hd_error            dd  ?
  89. hd_setup            dd  ?
  90. hd_wait_timeout     dd  ?
  91. cache_search_start  dd  ?   ; used by find_empty_slot
  92. Sector512:      ; label for dev_hdcd.inc
  93. buffer:
  94. rb 512
  95. endg
  96.  
  97. ; these labels are located before the main function to make
  98. ; most of jumps to these be short
  99. fat_create_partition.free_return0:
  100.         mov     eax, ebp
  101.         call    free
  102.         pop     ebp
  103. fat_create_partition.return0:
  104.         xor     eax, eax
  105.         ret
  106. fat_create_partition:
  107. ; sector size must be 512
  108.         cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
  109.         jnz     .return0
  110. ; bootsector must have been successfully read
  111.         cmp     dword [esp+4], 0
  112.         jnz     .return0
  113. ; bootsector signature must be correct
  114.         cmp     word [ebx+0x1fe], 0xaa55
  115.         jnz     .return0
  116. ; sectors per cluster must be nonzero
  117.         cmp     byte [ebx+0xd], 0
  118.         jz      .return0
  119. ; bytes per sector must be 0x200
  120.         cmp     word [ebx+0xb], 0x200
  121.         jnz     .return0
  122. ; number of fats must be nonzero
  123.         cmp     byte [ebx+0x10], 0
  124.         jz      .return0
  125. ; The only reason to be invalid partition now is FAT12. Since the test for
  126. ; FAT size requires knowledge of some calculated values, which are also used
  127. ; in the normal operation, let's hope for the best and allocate data now; if
  128. ; it will prove wrong, just deallocate it.
  129.         movi    eax, sizeof.FAT
  130.         call    malloc
  131.         test    eax, eax
  132.         jz      .return0
  133.         mov     ecx, dword [ebp+PARTITION.FirstSector]
  134.         mov     dword [eax+FAT.FirstSector], ecx
  135.         mov     ecx, dword [ebp+PARTITION.FirstSector+4]
  136.         mov     dword [eax+FAT.FirstSector+4], ecx
  137.         mov     ecx, dword [ebp+PARTITION.Length]
  138.         mov     dword [eax+FAT.Length], ecx
  139.         mov     ecx, dword [ebp+PARTITION.Length+4]
  140.         mov     dword [eax+FAT.Length+4], ecx
  141.         mov     ecx, [ebp+PARTITION.Disk]
  142.         mov     [eax+FAT.Disk], ecx
  143.         mov     [eax+FAT.FSUserFunctions], fat_user_functions
  144.         or      [eax+FAT.fat_in_cache], -1
  145.         mov     [eax+FAT.fat_change], 0
  146.         push    ebp
  147.         mov     ebp, eax
  148.  
  149.         lea     ecx, [ebp+FAT.Lock]
  150.         call    mutex_init
  151.  
  152.         movzx   eax, word [ebx+0xe]     ; sectors reserved
  153.         mov     [ebp+FAT.FAT_START], eax
  154.  
  155.         movzx   eax, byte [ebx+0xd]     ; sectors per cluster
  156.         mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
  157.  
  158.         movzx   ecx, word [ebx+0xb]     ; bytes per sector
  159.         mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
  160.  
  161.         movzx   eax, word [ebx+0x11]    ; count of rootdir entries (=0 fat32)
  162.         shl     eax, 5                  ; mul 32
  163.         dec     ecx
  164.         add     eax, ecx                ; round up if not equal count
  165.         inc     ecx                     ; bytes per sector
  166.         xor     edx, edx
  167.         div     ecx
  168.         mov     [ebp+FAT.ROOT_SECTORS], eax     ; count of rootdir sectors
  169.  
  170.         movzx   eax, word [ebx+0x16]    ; sectors per fat <65536
  171.         test    eax, eax
  172.         jnz     @f
  173.         mov     eax, [ebx+0x24]         ; sectors per fat
  174. @@:
  175.         mov     [ebp+FAT.SECTORS_PER_FAT], eax
  176.  
  177.         movzx   eax, byte [ebx+0x10]    ; number of fats
  178.         mov     [ebp+FAT.NUMBER_OF_FATS], eax
  179.         mul     [ebp+FAT.SECTORS_PER_FAT]
  180.         test    edx, edx
  181.         jnz     .free_return0
  182.         add     eax, [ebp+FAT.FAT_START]
  183.         jc      .free_return0
  184.         mov     [ebp+FAT.ROOT_START], eax       ; rootdir = fat_start + fat_size * fat_count
  185.         add     eax, [ebp+FAT.ROOT_SECTORS]     ; rootdir sectors should be 0 on fat32
  186.         jc      .free_return0
  187.         mov     [ebp+FAT.DATA_START], eax       ; data area = rootdir + rootdir_size
  188.  
  189.         movzx   eax, word [ebx+0x13]    ; total sector count <65536
  190.         test    eax, eax
  191.         jnz     @f
  192.         mov     eax, [ebx+0x20]         ; total sector count
  193. @@:
  194. ; total sector count must not exceed partition size
  195.         cmp     dword [ebp+FAT.Length+4], 0
  196.         jnz     @f
  197.         cmp     eax, dword [ebp+FAT.Length]
  198.         ja      .free_return0
  199. @@:
  200.         mov     dword [ebp+FAT.Length], eax
  201.         and     dword [ebp+FAT.Length+4], 0
  202.         sub     eax, [ebp+FAT.DATA_START]       ; eax = count of data sectors
  203.         jc      .free_return0
  204.         xor     edx, edx
  205.         div     [ebp+FAT.SECTORS_PER_CLUSTER]
  206.         inc     eax
  207.         mov     [ebp+FAT.LAST_CLUSTER], eax
  208.         dec     eax                     ; cluster count
  209.         jz      .free_return0
  210.         mov     [ebp+FAT.fatStartScan], 2
  211.  
  212.         ; limits by Microsoft Hardware White Paper v1.03
  213.         cmp     eax, 4085               ; 0xff5
  214.         jb      .fat12
  215.         cmp     eax, 65525              ; 0xfff5
  216.         jb      .fat16
  217. .fat32:
  218.         mov     eax, [ebx+0x2c]         ; rootdir cluster
  219.         mov     [ebp+FAT.ROOT_CLUSTER], eax
  220.         movzx   eax, word [ebx+0x30]
  221.         mov     [ebp+FAT.ADR_FSINFO], eax
  222.         push    ebx
  223.         add     ebx, 512
  224.         call    fs_read32_sys
  225.         test    eax, eax
  226.         jnz     @f
  227.         mov     eax, [ebx+0x1ec]
  228.         cmp     eax, -1
  229.         jz      @f
  230.         mov     [ebp+FAT.fatStartScan], eax
  231. @@:
  232.         pop     ebx
  233.         mov     [ebp+FAT.fatRESERVED], 0x0FFFFFF6
  234.         mov     [ebp+FAT.fatBAD], 0x0FFFFFF7
  235.         mov     [ebp+FAT.fatEND], 0x0FFFFFF8
  236.         mov     [ebp+FAT.fatMASK], 0x0FFFFFFF
  237.         mov     al, 32
  238. .fat_not_12_finalize:
  239.         mov     [ebp+FAT.fs_type], al
  240. ; For FAT16 and FAT32, allocate 512 bytes for FAT cache.
  241.         mov     eax, 512
  242.         call    malloc
  243.         test    eax, eax
  244.         jz      .free_return0
  245.         mov     [ebp+FAT.fat_cache_ptr], eax
  246.         mov     eax, ebp
  247.         pop     ebp
  248.         ret
  249. .fat16:
  250.         and     [ebp+FAT.ROOT_CLUSTER], 0
  251.         mov     [ebp+FAT.fatRESERVED], 0x0000FFF6
  252.         mov     [ebp+FAT.fatBAD], 0x0000FFF7
  253.         mov     [ebp+FAT.fatEND], 0x0000FFF8
  254.         mov     [ebp+FAT.fatMASK], 0x0000FFFF
  255.         mov     al, 16
  256.         jmp     .fat_not_12_finalize
  257. .fat12:
  258.         and     [ebp+FAT.ROOT_CLUSTER], 0
  259.         mov     [ebp+FAT.fatRESERVED], 0xFF6
  260.         mov     [ebp+FAT.fatBAD], 0xFF7
  261.         mov     [ebp+FAT.fatEND], 0xFFF
  262.         mov     [ebp+FAT.fatMASK], 0xFFF
  263.         mov     al, 12
  264.         mov     [ebp+FAT.fs_type], al
  265. ; For FAT12, allocate&read data for entire table:
  266. ; calculate A = ALIGN_UP(NUM_CLUSTERS, 8),
  267. ; calculatefatchain/restorefatchain will process A items,
  268. ; allocate ALIGN_UP(A*3/2, 512) bytes for FAT table plus A*2 bytes for unpacked data.
  269.         mov     eax, [ebp+FAT.LAST_CLUSTER]
  270.         and     eax, not 7
  271.         add     eax, 8
  272.         mov     edx, eax
  273.         lea     eax, [eax*3]
  274.         add     eax, 512*2-1
  275.         shr     eax, 10
  276.         shl     eax, 9
  277.         lea     eax, [eax+edx*2]
  278.         call    malloc
  279.         test    eax, eax
  280.         jz      .free_return0
  281. ; Read ALIGN_UP(NUM_CLUSTERS*3/2, 512) bytes.
  282. ; Note that this can be less than allocated, this is ok,
  283. ; overallocation simplifies calculatefatchain/restorefatchain.
  284.         push    ebx
  285.         mov     [ebp+FAT.fat_cache_ptr], eax
  286.         mov     edx, [ebp+FAT.LAST_CLUSTER]
  287.         lea     edx, [(edx+1)*3 + 512*2-1]
  288.         shr     edx, 10
  289.         xchg    eax, ebx
  290.         xor     eax, eax
  291. .read_fat:
  292.         push    eax
  293.         add     eax, [ebp+FAT.FAT_START]
  294.         call    fs_read32_sys
  295.         test    eax, eax
  296.         pop     eax
  297.         jz      @f
  298.         dbgstr 'Failed to read FAT table'
  299.         mov     eax, [ebp+FAT.fat_cache_ptr]
  300.         call    free
  301.         pop     ebx
  302.         jmp     .free_return0
  303. @@:
  304.         add     ebx, 512
  305.         inc     eax
  306.         cmp     eax, edx
  307.         jb      .read_fat
  308.         mov     [ebp+FAT.fat12_unpacked_ptr], ebx
  309.         call    calculatefatchain
  310.         pop     ebx
  311.         mov     eax, ebp
  312.         pop     ebp
  313.         ret
  314.  
  315. fat_free:
  316.         push    eax
  317.         mov     eax, [eax+FAT.fat_cache_ptr]
  318.         call    free
  319.         pop     eax
  320.         jmp     free
  321.  
  322. calculatefatchain:
  323.  
  324.         pushad
  325.  
  326.         mov     esi, [ebp+FAT.fat_cache_ptr]
  327.         mov     edi, [ebp+FAT.fat12_unpacked_ptr]
  328.  
  329.         mov     edx, [ebp+FAT.LAST_CLUSTER]
  330.         and     edx, not 7
  331.         lea     edx, [edi+(edx+8)*2]
  332.         push    edx
  333.  
  334.  fcnew:
  335.         mov     eax, dword [esi]
  336.         mov     ebx, dword [esi+4]
  337.         mov     ecx, dword [esi+8]
  338.         mov     edx, ecx
  339.         shr     edx, 4;8 ok
  340.         shr     dx, 4;7 ok
  341.         xor     ch, ch
  342.         shld    ecx, ebx, 20;6 ok
  343.         shr     cx, 4;5 ok
  344.         shld    ebx, eax, 12
  345.         and     ebx, 0x0fffffff;4 ok
  346.         shr     bx, 4;3 ok
  347.         shl     eax, 4
  348.         and     eax, 0x0fffffff;2 ok
  349.         shr     ax, 4;1 ok
  350.         mov     dword [edi], eax
  351.         mov     dword [edi+4], ebx
  352.         mov     dword [edi+8], ecx
  353.         mov     dword [edi+12], edx
  354.         add     edi, 16
  355.         add     esi, 12
  356.  
  357.         cmp     edi, [esp]
  358.         jnz     fcnew
  359.         pop     eax
  360.  
  361.         popad
  362.         ret
  363.  
  364.  
  365. restorefatchain:   ; restore fat chain
  366.  
  367.         pushad
  368.  
  369.         mov     esi, [ebp+FAT.fat12_unpacked_ptr]
  370.         mov     edi, [ebp+FAT.fat_cache_ptr]
  371.  
  372.         mov     edx, [ebp+FAT.LAST_CLUSTER]
  373.         and     edx, not 7
  374.         lea     edx, [esi+(edx+8)*2]
  375.  
  376.   fcnew2:
  377.         mov     eax, dword [esi]
  378.         mov     ebx, dword [esi+4]
  379.         shl     ax, 4
  380.         shl     eax, 4
  381.         shl     bx, 4
  382.         shr     ebx, 4
  383.         shrd    eax, ebx, 8
  384.         shr     ebx, 8
  385.         mov     dword [edi], eax
  386.         mov     word [edi+4], bx
  387.         add     edi, 6
  388.         add     esi, 8
  389.  
  390.         cmp     esi, edx
  391.         jb      fcnew2
  392.  
  393.         mov     esi, [ebp+FAT.NUMBER_OF_FATS]
  394.         mov     edx, [ebp+FAT.LAST_CLUSTER]
  395.         lea     edx, [(edx+1)*3 + 512*2-1]
  396.         shr     edx, 10
  397.         push    [ebp+FAT.FAT_START]
  398.  
  399. .write_fats:
  400.         xor     eax, eax
  401.         mov     ebx, [ebp+FAT.fat_cache_ptr]
  402. .loop1:
  403.         push    eax
  404.         add     eax, [esp+4]
  405.         call    fs_write32_sys
  406.         test    eax, eax
  407.         pop     eax
  408.         jnz     .fail
  409.         add     ebx, 512
  410.         inc     eax
  411.         cmp     eax, edx
  412.         jb      .loop1
  413.         pop     eax
  414.         add     eax, [ebp+FAT.SECTORS_PER_FAT]
  415.         push    eax
  416.         dec     esi
  417.         jnz     .write_fats
  418.         pop     eax
  419.  
  420.         popad
  421.         ret
  422. .fail:
  423.         dbgstr 'Failed to save FAT'
  424.         popad
  425.         ret
  426.  
  427. iglobal
  428. label fat_legal_chars byte
  429. ; 0 = not allowed
  430. ; 1 = allowed only in long names
  431. ; 3 = allowed
  432.         times 32 db 0
  433. ;                 ! " # $ % & ' ( ) * + , - . /
  434.         db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
  435. ;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
  436.         db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
  437. ;               @ A B C D E F G H I J K L M N O
  438.         db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
  439. ;               P Q R S T U V W X Y Z [ \ ] ^ _
  440.         db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
  441. ;               ` a b c d e f g h i j k l m n o
  442.         db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
  443. ;               p q r s t u v w x y z { | } ~
  444.         db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
  445. endg
  446.  
  447. fat_name_is_legal:
  448. ; in: esi->(long) name
  449. ; out: CF set <=> legal
  450. ; destroys eax
  451.         push    esi
  452.         xor     eax, eax
  453. @@:
  454.         lodsb
  455.         test    al, al
  456.         jz      .done
  457.         cmp     al, 80h
  458.         jae     .big
  459.         test    [fat_legal_chars+eax], 1
  460.         jnz     @b
  461. .err:
  462.         pop     esi
  463.         clc
  464.         ret
  465. .big:
  466. ; 0x80-0xAF, 0xE0-0xEF
  467.         cmp     al, 0xB0
  468.         jb      @b
  469.         cmp     al, 0xE0
  470.         jb      .err
  471.         cmp     al, 0xF0
  472.         jb      @b
  473.         jmp     .err
  474. .done:
  475.         sub     esi, [esp]
  476.         cmp     esi, 257
  477.         pop     esi
  478.         ret
  479.  
  480. fat_next_short_name:
  481. ; in: edi->8+3 name
  482. ; out: name corrected
  483. ;      CF=1 <=> error
  484.         pushad
  485.         mov     ecx, 8
  486.         mov     al, '~'
  487.         std
  488.         push    edi
  489.         add     edi, 7
  490.         repnz scasb
  491.         pop     edi
  492.         cld
  493.         jz      .tilde
  494. ; tilde is not found, insert "~1" at end
  495.         add     edi, 6
  496.         cmp     word [edi], '  '
  497.         jnz     .insert_tilde
  498. @@:
  499.         dec     edi
  500.         cmp     byte [edi], ' '
  501.         jz      @b
  502.         inc     edi
  503. .insert_tilde:
  504.         mov     word [edi], '~1'
  505.         popad
  506.         clc
  507.         ret
  508. .tilde:
  509.         push    edi
  510.         add     edi, 7
  511.         xor     ecx, ecx
  512. @@:
  513. ; after tilde may be only digits and trailing spaces
  514.         cmp     byte [edi], '~'
  515.         jz      .break
  516.         cmp     byte [edi], ' '
  517.         jz      .space
  518.         cmp     byte [edi], '9'
  519.         jnz     .found
  520.         dec     edi
  521.         jmp     @b
  522. .space:
  523.         dec     edi
  524.         inc     ecx
  525.         jmp     @b
  526. .found:
  527.         inc     byte [edi]
  528.         add     dword [esp], 8
  529.         jmp     .zerorest
  530. .break:
  531.         jecxz   .noplace
  532.         inc     edi
  533.         mov     al, '1'
  534. @@:
  535.         xchg    al, [edi]
  536.         inc     edi
  537.         cmp     al, ' '
  538.         mov     al, '0'
  539.         jnz     @b
  540. .succ:
  541.         pop     edi
  542.         popad
  543.         clc
  544.         ret
  545. .noplace:
  546.         dec     edi
  547.         cmp     edi, [esp]
  548.         jz      .err
  549.         add     dword [esp], 8
  550.         mov     word [edi], '~1'
  551.         inc     edi
  552.         inc     edi
  553. @@:
  554.         mov     byte [edi], '0'
  555. .zerorest:
  556.         inc     edi
  557.         cmp     edi, [esp]
  558.         jb      @b
  559.         pop     edi
  560.         popad
  561.         ;clc    ; automatically
  562.         ret
  563. .err:
  564.         pop     edi
  565.         popad
  566.         stc
  567.         ret
  568.  
  569. fat_gen_short_name:
  570. ; in: esi->long name
  571. ;     edi->buffer (8+3=11 chars)
  572. ; out: buffer filled
  573.         pushad
  574.         mov     eax, '    '
  575.         push    edi
  576.         stosd
  577.         stosd
  578.         stosd
  579.         pop     edi
  580.         xor     eax, eax
  581.         movi    ebx, 8
  582.         lea     ecx, [edi+8]
  583. .loop:
  584.         lodsb
  585.         test    al, al
  586.         jz      .done
  587.         call    char_toupper
  588.         cmp     al, ' '
  589.         jz      .space
  590.         cmp     al, 80h
  591.         ja      .big
  592.         test    [fat_legal_chars+eax], 2
  593.         jnz     .symbol
  594. .inv_symbol:
  595.         mov     al, '_'
  596.         or      bh, 1
  597. .symbol:
  598.         cmp     al, '.'
  599.         jz      .dot
  600. .normal_symbol:
  601.         dec     bl
  602.         jns     .store
  603.         mov     bl, 0
  604. .space:
  605.         or      bh, 1
  606.         jmp     .loop
  607. .store:
  608.         stosb
  609.         jmp     .loop
  610. .big:
  611.         cmp     al, 0xB0
  612.         jb      .normal_symbol
  613.         cmp     al, 0xE0
  614.         jb      .inv_symbol
  615.         cmp     al, 0xF0
  616.         jb      .normal_symbol
  617.         jmp     .inv_symbol
  618. .dot:
  619.         test    bh, 2
  620.         jz      .firstdot
  621.         pop     ebx
  622.         add     ebx, edi
  623.         sub     ebx, ecx
  624.         push    ebx
  625.         cmp     ebx, ecx
  626.         jb      @f
  627.         pop     ebx
  628.         push    ecx
  629. @@:
  630.         cmp     edi, ecx
  631.         jbe     .skip
  632. @@:
  633.         dec     edi
  634.         mov     al, [edi]
  635.         dec     ebx
  636.         mov     [ebx], al
  637.         mov     byte [edi], ' '
  638.         cmp     edi, ecx
  639.         ja      @b
  640. .skip:
  641.         mov     bh, 3
  642.         jmp     @f
  643. .firstdot:
  644.         cmp     bl, 8
  645.         jz      .space
  646.         push    edi
  647.         or      bh, 2
  648. @@:
  649.         mov     edi, ecx
  650.         mov     bl, 3
  651.         jmp     .loop
  652. .done:
  653.         test    bh, 2
  654.         jz      @f
  655.         pop     edi
  656. @@:
  657.         lea     edi, [ecx-8]
  658.         test    bh, 1
  659.         jz      @f
  660.         call    fat_next_short_name
  661. @@:
  662.         popad
  663.         ret
  664.  
  665. fat12_free_space:
  666. ;---------------------------------------------
  667. ;
  668. ; returns free space in edi
  669. ; rewr.by Mihasik
  670. ;---------------------------------------------
  671.  
  672.         push    eax ebx ecx
  673.  
  674.         mov     edi, [ebp+FAT.fat12_unpacked_ptr];start of FAT
  675.         xor     ax, ax;Free cluster=0x0000 in FAT
  676.         xor     ebx, ebx;counter
  677.         mov     ecx, [ebp+FAT.LAST_CLUSTER]
  678.         inc     ecx
  679.         cld
  680.     rdfs1:
  681.         repne scasw
  682.         jnz     rdfs2 ;if last cluster not 0
  683.         inc     ebx
  684.         test    ecx, ecx
  685.         jnz     rdfs1
  686.     rdfs2:
  687.         shl     ebx, 9;free clusters*512
  688.         mov     edi, ebx
  689.  
  690.         pop     ecx ebx eax
  691.         ret
  692.  
  693.  
  694.  
  695. set_FAT:
  696. ;--------------------------------
  697. ; input  : EAX = cluster
  698. ;          EDX = value to save
  699. ;          EBP = pointer to FAT structure
  700. ; output : EDX = old value
  701. ;--------------------------------
  702. ; out: CF set <=> error
  703.         push    eax ebx esi
  704.  
  705.         cmp     eax, 2
  706.         jb      sfc_error
  707.         cmp     eax, [ebp+FAT.LAST_CLUSTER]
  708.         ja      sfc_error
  709.         cmp     [ebp+FAT.fs_type], 12
  710.         je      set_FAT12
  711.         cmp     [ebp+FAT.fs_type], 16
  712.         je      sfc_1
  713.         add     eax, eax
  714.   sfc_1:
  715.         add     eax, eax
  716.         mov     esi, 511
  717.         and     esi, eax        ; esi = position in fat sector
  718.         shr     eax, 9          ; eax = fat sector
  719.         add     eax, [ebp+FAT.FAT_START]
  720.         mov     ebx, [ebp+FAT.fat_cache_ptr]
  721.  
  722.         cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
  723.         je      sfc_in_cache    ; yes
  724.  
  725.         cmp     [ebp+FAT.fat_change], 0; is fat changed?
  726.         je      sfc_no_change   ; no
  727.         call    write_fat_sector; yes. write it into disk
  728.         jc      sfc_error
  729.  
  730.   sfc_no_change:
  731.         mov     [ebp+FAT.fat_in_cache], eax; save fat sector
  732.         call    fs_read32_sys
  733.         test    eax, eax
  734.         jne     sfc_error
  735.  
  736.  
  737.   sfc_in_cache:
  738.         cmp     [ebp+FAT.fs_type], 16
  739.         jne     sfc_test32
  740.  
  741.   sfc_set16:
  742.         xchg    [ebx+esi], dx   ; save new value and get old value
  743.         jmp     sfc_write
  744.  
  745.   sfc_test32:
  746.         mov     eax, [ebp+FAT.fatMASK]
  747.  
  748.   sfc_set32:
  749.         and     edx, eax
  750.         xor     eax, -1         ; mask for high bits
  751.         and     eax, [ebx+esi]  ; get high 4 bits
  752.         or      eax, edx
  753.         mov     edx, [ebx+esi]  ; get old value
  754.         mov     [ebx+esi], eax  ; save new value
  755.  
  756.   sfc_write:
  757.         mov     [ebp+FAT.fat_change], 1; fat has changed
  758.  
  759.   sfc_nonzero:
  760.         and     edx, [ebp+FAT.fatMASK]
  761.  
  762.   sfc_return:
  763.         pop     esi ebx eax
  764.         ret
  765.   sfc_error:
  766.         stc
  767.         jmp     sfc_return
  768.  
  769.   set_FAT12:
  770.         test    edx, 0xF000
  771.         jnz     sfc_error
  772.         mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
  773.         xchg    [ebx+eax*2], dx
  774.         mov     [ebp+FAT.fat_change], 1
  775.         pop     esi ebx eax
  776.         clc
  777.         ret
  778.  
  779. get_FAT:
  780. ;--------------------------------
  781. ; input  : EAX = cluster
  782. ;          EBP = pointer to FAT structure
  783. ; output : EAX = next cluster
  784. ;--------------------------------
  785. ; out: CF set <=> error
  786.         push    ebx esi
  787.  
  788.         cmp     [ebp+FAT.fs_type], 12
  789.         je      get_FAT12
  790.  
  791.         cmp     [ebp+FAT.fs_type], 16
  792.         je      gfc_1
  793.         add     eax, eax
  794.   gfc_1:
  795.         add     eax, eax
  796.         mov     esi, 511
  797.         and     esi, eax        ; esi = position in fat sector
  798.         shr     eax, 9          ; eax = fat sector
  799.         add     eax, [ebp+FAT.FAT_START]
  800.         mov     ebx, [ebp+FAT.fat_cache_ptr]
  801.  
  802.         cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
  803.         je      gfc_in_cache
  804.  
  805.         cmp     [ebp+FAT.fat_change], 0; is fat changed?
  806.         je      gfc_no_change   ; no
  807.         call    write_fat_sector; yes. write it into disk
  808.         jc      hd_error_01
  809.  
  810.   gfc_no_change:
  811.         mov     [ebp+FAT.fat_in_cache], eax
  812.         call    fs_read32_sys
  813.         test    eax, eax
  814.         jne     hd_error_01
  815.  
  816.   gfc_in_cache:
  817.         mov     eax, [ebx+esi]
  818.         and     eax, [ebp+FAT.fatMASK]
  819.   gfc_return:
  820.         pop     esi ebx
  821.         ret
  822.  hd_error_01:
  823.         stc
  824.         jmp     gfc_return
  825.  
  826. get_FAT12:
  827.         mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
  828.         movzx   eax, word [ebx+eax*2]
  829.         pop     esi ebx
  830.         clc
  831.         ret
  832.  
  833.  
  834. get_free_FAT:
  835. ;-----------------------------------------------------------
  836. ; output : if CARRY=0 EAX = # first cluster found free
  837. ;          if CARRY=1 disk full
  838. ; Note   : for more speed need to use fat_cache directly
  839. ;-----------------------------------------------------------
  840.         push    ecx
  841.         mov     ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
  842.         mov     eax, [ebp+FAT.fatStartScan]
  843.         cmp     [ebp+FAT.fs_type], 12
  844.         jz      get_free_FAT12
  845.         dec     ecx
  846.         cmp     eax, 2
  847.         jb      gff_reset
  848.  
  849.   gff_test:
  850.         cmp     eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
  851.         jbe     gff_in_range
  852.   gff_reset:
  853.         mov     eax, 2
  854.  
  855.   gff_in_range:
  856.         push    eax
  857.         call    get_FAT         ; get cluster state
  858.         jc      gff_not_found_1
  859.  
  860.         test    eax, eax        ; is it free?
  861.         pop     eax
  862.         je      gff_found       ; yes
  863.         inc     eax             ; next cluster
  864.         dec     ecx             ; is all checked?
  865.         jnz     gff_test        ; no
  866.  
  867.   gff_not_found:
  868.         pop     ecx             ; yes. disk is full
  869.         stc
  870.         ret
  871.  
  872.   gff_not_found_1:
  873.         pop     eax
  874.         jmp     gff_not_found
  875.  
  876.   gff_found:
  877.         lea     ecx, [eax+1]
  878.         mov     [ebp+FAT.fatStartScan], ecx
  879.         pop     ecx
  880.         clc
  881.         ret
  882.  
  883. get_free_FAT12:
  884.         push    edx edi
  885.         mov     edi, [ebp+FAT.fat12_unpacked_ptr]
  886.         cmp     eax, 2
  887.         jb      .reset
  888.         cmp     eax, ecx
  889.         jbe     @f
  890. .reset:
  891.         mov     eax, 2
  892. @@:
  893.         mov     edx, eax
  894.         lea     edi, [edi+eax*2]
  895.         sub     ecx, eax
  896.         inc     ecx
  897.         xor     eax, eax
  898.         repnz scasw
  899.         jz      .found
  900.         cmp     edx, 2
  901.         jz      .notfound
  902.         mov     edi, [ebp+FAT.fat12_unpacked_ptr]
  903.         lea     ecx, [edx-2]
  904.         repnz scasw
  905.         jnz     .notfound
  906. .found:
  907.         sub     edi, [ebp+FAT.fat12_unpacked_ptr]
  908.         shr     edi, 1
  909.         mov     [ebp+FAT.fatStartScan], edi
  910.         lea     eax, [edi-1]
  911.         pop     edi edx ecx
  912.         ret
  913. .notfound:
  914.         pop     edi edx ecx
  915.         stc
  916.         ret
  917.  
  918.  
  919. write_fat_sector:
  920. ;-----------------------------------------------------------
  921. ; write changed fat to disk
  922. ;-----------------------------------------------------------
  923.         push    eax ebx ecx
  924.  
  925.         mov     [ebp+FAT.fat_change], 0
  926.         mov     eax, [ebp+FAT.fat_in_cache]
  927.         cmp     eax, -1
  928.         jz      write_fat_not_used
  929.         mov     ebx, [ebp+FAT.fat_cache_ptr]
  930.         mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
  931.  
  932.   write_next_fat:
  933.         push    eax
  934.         call    fs_write32_sys
  935.         test    eax, eax
  936.         pop     eax
  937.         jnz     write_fat_not_used
  938.  
  939.         add     eax, [ebp+FAT.SECTORS_PER_FAT]
  940.         dec     ecx
  941.         jnz     write_next_fat
  942.  
  943.   write_fat_not_used:
  944.         pop     ecx ebx eax
  945.         ret
  946.  
  947.  
  948.  
  949.  
  950.  
  951. bcd2bin:
  952. ;----------------------------------
  953. ; input  : AL=BCD number (eg. 0x11)
  954. ; output : AH=0
  955. ;          AL=decimal number (eg. 11)
  956. ;----------------------------------
  957.         xor     ah, ah
  958.         shl     ax, 4
  959.         shr     al, 4
  960.         aad
  961.         ret
  962.  
  963.  
  964. get_date_for_file:
  965. ;-----------------------------------------------------
  966. ; Get date from CMOS and pack day,month,year in AX
  967. ; DATE   bits  0..4   : day of month 0..31
  968. ;              5..8   : month of year 1..12
  969. ;              9..15  : count of years from 1980
  970. ;-----------------------------------------------------
  971.         mov     al, 0x7 ;day
  972.         out     0x70, al
  973.         in      al, 0x71
  974.         call    bcd2bin
  975.         ror     eax, 5
  976.  
  977.         mov     al, 0x8 ;month
  978.         out     0x70, al
  979.         in      al, 0x71
  980.         call    bcd2bin
  981.         ror     eax, 4
  982.  
  983.         mov     al, 0x9 ;year
  984.         out     0x70, al
  985.         in      al, 0x71
  986.         call    bcd2bin
  987.         add     ax, 20  ;because CMOS return only the two last
  988.                         ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
  989.         rol     eax, 9  ;need the difference with 1980 (eg. 2001-1980)
  990.         ret
  991.  
  992.  
  993. get_time_for_file:
  994. ;-----------------------------------------------------
  995. ; Get time from CMOS and pack hour,minute,second in AX
  996. ; TIME   bits  0..4   : second (the low bit is lost)
  997. ;              5..10  : minute 0..59
  998. ;              11..15 : hour 0..23
  999. ;-----------------------------------------------------
  1000.         mov     al, 0x0 ;second
  1001.         out     0x70, al
  1002.         in      al, 0x71
  1003.         call    bcd2bin
  1004.         ror     eax, 6
  1005.  
  1006.         mov     al, 0x2 ;minute
  1007.         out     0x70, al
  1008.         in      al, 0x71
  1009.         call    bcd2bin
  1010.         ror     eax, 6
  1011.  
  1012.         mov     al, 0x4 ;hour
  1013.         out     0x70, al
  1014.         in      al, 0x71
  1015.         call    bcd2bin
  1016.         rol     eax, 11
  1017.         ret
  1018.  
  1019.  
  1020. set_current_time_for_entry:
  1021. ;-----------------------------------------------------
  1022. ; Set current time/date for file entry
  1023. ; input  : ebx = file entry pointer
  1024. ;-----------------------------------------------------
  1025.         push    eax
  1026.         call    get_time_for_file; update files date/time
  1027.         mov     [ebx+22], ax
  1028.         call    get_date_for_file
  1029.         mov     [ebx+24], ax
  1030.         pop     eax
  1031.         ret
  1032.  
  1033.  
  1034.  
  1035. add_disk_free_space:
  1036. ;-----------------------------------------------------
  1037. ; input  : ecx = cluster count
  1038. ; Note   : negative = remove clusters from free space
  1039. ;          positive = add clusters to free space
  1040. ;-----------------------------------------------------
  1041.         test    ecx, ecx        ; no change
  1042.         je      add_dfs_no
  1043.         cmp     [ebp+FAT.fs_type], 32  ; free disk space only used by fat32
  1044.         jne     add_dfs_no
  1045.  
  1046.         push    eax ebx
  1047.         mov     eax, [ebp+FAT.ADR_FSINFO]
  1048.         lea     ebx, [ebp+FAT.fsinfo_buffer]
  1049.         call    fs_read32_sys
  1050.         test    eax, eax
  1051.         jnz     add_not_fs
  1052.  
  1053.         cmp     dword [ebx+0x1fc], 0xaa550000; check sector id
  1054.         jne     add_not_fs
  1055.  
  1056.         add     [ebx+0x1e8], ecx
  1057.         push    [ebp+FAT.fatStartScan]
  1058.         pop     dword [ebx+0x1ec]
  1059.         mov     eax, [ebp+FAT.ADR_FSINFO]
  1060.         call    fs_write32_sys
  1061. ;    jc    add_not_fs
  1062.  
  1063.   add_not_fs:
  1064.         pop     ebx eax
  1065.  
  1066.   add_dfs_no:
  1067.         ret
  1068.  
  1069.  
  1070.  
  1071. clear_cluster_chain:
  1072. ;-----------------------------------------------------
  1073. ; input  : eax = first cluster
  1074. ;-----------------------------------------------------
  1075.         push    eax ecx edx
  1076.         xor     ecx, ecx        ; cluster count
  1077.  
  1078.   clean_new_chain:
  1079.         cmp     eax, [ebp+FAT.LAST_CLUSTER]; end of file
  1080.         ja      delete_OK
  1081.         cmp     eax, 2          ; unfinished fat chain or zero length file
  1082.         jb      delete_OK
  1083.         cmp     eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
  1084.         jz      delete_OK
  1085.  
  1086.         xor     edx, edx
  1087.         call    set_FAT         ; clear fat entry
  1088.         jc      access_denied_01
  1089.  
  1090.         inc     ecx             ; update cluster count
  1091.         mov     eax, edx        ; old cluster
  1092.         jmp     clean_new_chain
  1093.  
  1094.   delete_OK:
  1095.         call    add_disk_free_space; add clusters to free disk space
  1096.         clc
  1097.   access_denied_01:
  1098.         pop     edx ecx eax
  1099.         ret
  1100.  
  1101.  
  1102. if 0
  1103. get_hd_info:
  1104. ;-----------------------------------------------------------
  1105. ; output : eax = 0 - ok
  1106. ;                3 - unknown FS
  1107. ;               10 - access denied
  1108. ;          edx = cluster size in bytes
  1109. ;          ebx = total clusters on disk
  1110. ;          ecx = free clusters on disk
  1111. ;-----------------------------------------------------------
  1112.         cmp     [ebp+FAT.fs_type], 16
  1113.         jz      info_fat_ok
  1114.         cmp     [ebp+FAT.fs_type], 32
  1115.         jz      info_fat_ok
  1116.         xor     edx, edx
  1117.         xor     ebx, ebx
  1118.         xor     ecx, ecx
  1119.         mov     eax, ERROR_UNKNOWN_FS
  1120.         ret
  1121.  
  1122.   info_fat_ok:
  1123. ;    call  reserve_hd1
  1124.  
  1125.         xor     ecx, ecx        ; count of free clusters
  1126.         mov     eax, 2
  1127.         mov     ebx, [ebp+FAT.LAST_CLUSTER]
  1128.  
  1129.   info_cluster:
  1130.         push    eax
  1131.         call    get_FAT         ; get cluster info
  1132.         jc      info_access_denied
  1133.  
  1134.         test    eax, eax        ; is it free?
  1135.         jnz     info_used       ; no
  1136.         inc     ecx
  1137.  
  1138.   info_used:
  1139.         pop     eax
  1140.         inc     eax
  1141.         cmp     eax, ebx        ; is above last cluster?
  1142.         jbe     info_cluster    ; no. test next cluster
  1143.  
  1144.         dec     ebx             ; cluster count
  1145.         imul    edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
  1146.         xor     eax, eax
  1147.         ret
  1148.  
  1149.   info_access_denied:
  1150.         add     esp, 4
  1151.         xor     edx, edx
  1152.         xor     ebx, ebx
  1153.         xor     ecx, ecx
  1154.         mov     eax, ERROR_ACCESS_DENIED
  1155.         ret
  1156. end if
  1157.  
  1158. update_disk:
  1159.         cmp     [ebp+FAT.fat_change], 0 ; is fat changed?
  1160.         je      upd_no_change
  1161.         cmp     [ebp+FAT.fs_type], 12
  1162.         jz      .fat12
  1163. ;-----------------------------------------------------------
  1164. ; write changed fat and cache to disk
  1165. ;-----------------------------------------------------------
  1166.  
  1167.         call    write_fat_sector
  1168.         jc      update_disk_acces_denied
  1169.         jmp     upd_no_change
  1170. .fat12:
  1171.         call    restorefatchain
  1172.         mov     [ebp+FAT.fat_change], 0
  1173.  
  1174.   upd_no_change:
  1175.  
  1176.         push    esi
  1177.         mov     esi, [ebp+PARTITION.Disk]
  1178.         call    disk_sync
  1179.         pop     esi
  1180.   update_disk_acces_denied:
  1181.         ret
  1182.  
  1183. fat_lock:
  1184.         lea     ecx, [ebp+FAT.Lock]
  1185.         jmp     mutex_lock
  1186. fat_unlock:
  1187.         lea     ecx, [ebp+FAT.Lock]
  1188.         jmp     mutex_unlock
  1189.  
  1190.  
  1191. fat_get_name:
  1192. ; in: edi->FAT entry
  1193. ; out: CF=1 - no valid entry
  1194. ; else CF=0 and ebp->ASCIIZ-name
  1195. ; (maximum length of filename is 255 (wide) symbols without trailing 0,
  1196. ;  but implementation requires buffer 261 words)
  1197. ; destroys eax
  1198.         cmp     byte [edi], 0
  1199.         jz      .no
  1200.         cmp     byte [edi], 0xE5
  1201.         jnz     @f
  1202. .no:
  1203.         stc
  1204.         ret
  1205. @@:
  1206.         cmp     byte [edi+11], 0xF
  1207.         jz      .longname
  1208.         test    byte [edi+11], 8
  1209.         jnz     .no
  1210.         push    ecx
  1211.         push    edi ebp
  1212.         test    byte [ebp-4], 1
  1213.         jnz     .unicode_short
  1214.  
  1215.         mov     eax, [edi]
  1216.         mov     ecx, [edi+4]
  1217.         mov     [ebp], eax
  1218.         mov     [ebp+4], ecx
  1219.  
  1220.         mov     ecx, 8
  1221. @@:
  1222.         cmp     byte [ebp+ecx-1], ' '
  1223.         loope   @b
  1224.  
  1225.         mov     eax, [edi+8]
  1226.         cmp     al, ' '
  1227.         je      .done
  1228.         shl     eax, 8
  1229.         mov     al, '.'
  1230.  
  1231.         lea     ebp, [ebp+ecx+1]
  1232.         mov     [ebp], eax
  1233.         mov     ecx, 3
  1234. @@:
  1235.         rol     eax, 8
  1236.         cmp     al, ' '
  1237.         jne     .done
  1238.         loop    @b
  1239.         dec     ebp
  1240. .done:
  1241.         and     byte [ebp+ecx+1], 0   ; CF=0
  1242.         pop     ebp edi ecx
  1243.         ret
  1244. .unicode_short:
  1245.         mov     ecx, 8
  1246.         push    ecx
  1247. @@:
  1248.         mov     al, [edi]
  1249.         inc     edi
  1250.         call    ansi2uni_char
  1251.         mov     [ebp], ax
  1252.         inc     ebp
  1253.         inc     ebp
  1254.         loop    @b
  1255.         pop     ecx
  1256. @@:
  1257.         cmp     word [ebp-2], ' '
  1258.         jnz     @f
  1259.         dec     ebp
  1260.         dec     ebp
  1261.         loop    @b
  1262. @@:
  1263.         mov     word [ebp], '.'
  1264.         inc     ebp
  1265.         inc     ebp
  1266.         mov     ecx, 3
  1267.         push    ecx
  1268. @@:
  1269.         mov     al, [edi]
  1270.         inc     edi
  1271.         call    ansi2uni_char
  1272.         mov     [ebp], ax
  1273.         inc     ebp
  1274.         inc     ebp
  1275.         loop    @b
  1276.         pop     ecx
  1277. @@:
  1278.         cmp     word [ebp-2], ' '
  1279.         jnz     @f
  1280.         dec     ebp
  1281.         dec     ebp
  1282.         loop    @b
  1283.         dec     ebp
  1284.         dec     ebp
  1285. @@:
  1286.         and     word [ebp], 0   ; CF=0
  1287.         pop     ebp edi ecx
  1288.         ret
  1289. .longname:
  1290. ; LFN
  1291.         mov     al, byte [edi]
  1292.         and     eax, 0x3F
  1293.         dec     eax
  1294.         cmp     al, 20
  1295.         jae     .no     ; ignore invalid entries
  1296.         mov     word [ebp+260*2], 0     ; force null-terminating for orphans
  1297.         imul    eax, 13*2
  1298.         add     ebp, eax
  1299.         test    byte [edi], 0x40
  1300.         jz      @f
  1301.         mov     word [ebp+13*2], 0
  1302. @@:
  1303.         push    eax
  1304. ; now copy name from edi to ebp ...
  1305.         mov     eax, [edi+1]
  1306.         mov     [ebp], eax      ; symbols 1,2
  1307.         mov     eax, [edi+5]
  1308.         mov     [ebp+4], eax    ; 3,4
  1309.         mov     eax, [edi+9]
  1310.         mov     [ebp+8], ax     ; 5
  1311.         mov     eax, [edi+14]
  1312.         mov     [ebp+10], eax   ; 6,7
  1313.         mov     eax, [edi+18]
  1314.         mov     [ebp+14], eax   ; 8,9
  1315.         mov     eax, [edi+22]
  1316.         mov     [ebp+18], eax   ; 10,11
  1317.         mov     eax, [edi+28]
  1318.         mov     [ebp+22], eax   ; 12,13
  1319. ; ... done
  1320.         pop     eax
  1321.         sub     ebp, eax
  1322.         test    eax, eax
  1323.         jz      @f
  1324. ; if this is not first entry, more processing required
  1325.         stc
  1326.         ret
  1327. @@:
  1328. ; if this is first entry:
  1329.         test    byte [ebp-4], 1
  1330.         jnz     .ret
  1331. ; buffer at ebp contains UNICODE name, convert it to ANSI
  1332.         push    esi edi
  1333.         mov     esi, ebp
  1334.         mov     edi, ebp
  1335.         call    uni2ansi_str
  1336.         pop     edi esi
  1337. .ret:
  1338.         clc
  1339.         ret
  1340.  
  1341. fat_compare_name:
  1342. ; compares ASCIIZ-names, case-insensitive (cp866 encoding)
  1343. ; in: esi->name, ebp->name
  1344. ; out: if names match: ZF=1 and esi->next component of name
  1345. ;      else: ZF=0, esi is not changed
  1346. ; destroys eax
  1347.         push    ebp esi
  1348. .loop:
  1349.         mov     al, [ebp]
  1350.         inc     ebp
  1351.         call    char_toupper
  1352.         push    eax
  1353.         lodsb
  1354.         call    char_toupper
  1355.         cmp     al, [esp]
  1356.         jnz     .done
  1357.         pop     eax
  1358.         test    al, al
  1359.         jnz     .loop
  1360.         dec     esi
  1361.         pop     eax
  1362.         pop     ebp
  1363.         xor     eax, eax        ; set ZF flag
  1364.         ret
  1365. .done:
  1366.         cmp     al, '/'
  1367.         jnz     @f
  1368.         cmp     byte [esp], 0
  1369.         jnz     @f
  1370.         mov     [esp+4], esi
  1371. @@:
  1372.         pop     eax
  1373.         pop     esi ebp
  1374.         ret
  1375.  
  1376. fat_find_lfn:
  1377. ; in: esi->name
  1378. ;     [esp+4] = next
  1379. ;     [esp+8] = first
  1380. ;     [esp+C]... - possibly parameters for first and next
  1381. ; out: CF=1 - file not found, eax=error code
  1382. ;      else CF=0, esi->next name component, edi->direntry
  1383.         pusha
  1384.         lea     eax, [esp+0Ch+20h]
  1385.         call    dword [eax-4]
  1386.         jc      .reterr
  1387.         sub     esp, 262*2      ; reserve place for LFN
  1388.         push    0               ; for fat_get_name: read ASCII name
  1389. .l1:
  1390.         lea     ebp, [esp+4]
  1391.         call    fat_get_name
  1392.         jc      .l2
  1393.         call    fat_compare_name
  1394.         jz      .found
  1395. .l2:
  1396.         mov     ebp, [esp+8+262*2+4]
  1397.         lea     eax, [esp+0Ch+20h+262*2+4]
  1398.         call    dword [eax-8]
  1399.         jnc     .l1
  1400.         add     esp, 262*2+4
  1401. .reterr:
  1402.         mov     [esp+28], eax
  1403.         stc
  1404.         popa
  1405.         ret
  1406. .found:
  1407.         add     esp, 262*2+4
  1408.         mov     ebp, [esp+8]
  1409. ; if this is LFN entry, advance to true entry
  1410.         cmp     byte [edi+11], 0xF
  1411.         jnz     @f
  1412.         lea     eax, [esp+0Ch+20h]
  1413.         call    dword [eax-8]
  1414.         jc      .reterr
  1415. @@:
  1416.         add     esp, 8          ; CF=0
  1417.         push    esi
  1418.         push    edi
  1419.         popa
  1420.         ret
  1421.  
  1422. fat_time_to_bdfe:
  1423. ; in: eax=FAT time
  1424. ; out: eax=BDFE time
  1425.         push    ecx edx
  1426.         mov     ecx, eax
  1427.         mov     edx, eax
  1428.         shr     eax, 11
  1429.         shl     eax, 16 ; hours
  1430.         and     edx, 0x1F
  1431.         add     edx, edx
  1432.         mov     al, dl  ; seconds
  1433.         shr     ecx, 5
  1434.         and     ecx, 0x3F
  1435.         mov     ah, cl  ; minutes
  1436.         pop     edx ecx
  1437.         ret
  1438.  
  1439. fat_date_to_bdfe:
  1440.         push    ecx edx
  1441.         mov     ecx, eax
  1442.         mov     edx, eax
  1443.         shr     eax, 9
  1444.         add     ax, 1980
  1445.         shl     eax, 16 ; year
  1446.         and     edx, 0x1F
  1447.         mov     al, dl  ; day
  1448.         shr     ecx, 5
  1449.         and     ecx, 0xF
  1450.         mov     ah, cl  ; month
  1451.         pop     edx ecx
  1452.         ret
  1453.  
  1454. bdfe_to_fat_time:
  1455.         push    edx
  1456.         mov     edx, eax
  1457.         shr     eax, 16
  1458.         and     dh, 0x3F
  1459.         shl     eax, 6
  1460.         or      al, dh
  1461.         shr     dl, 1
  1462.         and     dl, 0x1F
  1463.         shl     eax, 5
  1464.         or      al, dl
  1465.         pop     edx
  1466.         ret
  1467.  
  1468. bdfe_to_fat_date:
  1469.         push    edx
  1470.         mov     edx, eax
  1471.         shr     eax, 16
  1472.         sub     ax, 1980
  1473.         and     dh, 0xF
  1474.         shl     eax, 4
  1475.         or      al, dh
  1476.         and     dl, 0x1F
  1477.         shl     eax, 5
  1478.         or      al, dl
  1479.         pop     edx
  1480.         ret
  1481.  
  1482. fat_entry_to_bdfe:
  1483. ; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
  1484. ; destroys eax
  1485.         mov     eax, [ebp-4]
  1486.         mov     [esi+4], eax    ; ASCII/UNICODE name
  1487. fat_entry_to_bdfe2:
  1488.         movzx   eax, byte [edi+11]
  1489.         mov     [esi], eax      ; attributes
  1490.         movzx   eax, word [edi+14]
  1491.         call    fat_time_to_bdfe
  1492.         mov     [esi+8], eax    ; creation time
  1493.         movzx   eax, word [edi+16]
  1494.         call    fat_date_to_bdfe
  1495.         mov     [esi+12], eax   ; creation date
  1496.         and     dword [esi+16], 0       ; last access time is not supported on FAT
  1497.         movzx   eax, word [edi+18]
  1498.         call    fat_date_to_bdfe
  1499.         mov     [esi+20], eax   ; last access date
  1500.         movzx   eax, word [edi+22]
  1501.         call    fat_time_to_bdfe
  1502.         mov     [esi+24], eax   ; last write time
  1503.         movzx   eax, word [edi+24]
  1504.         call    fat_date_to_bdfe
  1505.         mov     [esi+28], eax   ; last write date
  1506.         mov     eax, [edi+28]
  1507.         mov     [esi+32], eax   ; file size (low dword)
  1508.         xor     eax, eax
  1509.         mov     [esi+36], eax   ; file size (high dword)
  1510.         test    ebp, ebp
  1511.         jz      .ret
  1512.         push    ecx edi
  1513.         lea     edi, [esi+40]
  1514.         mov     esi, ebp
  1515.         test    byte [esi-4], 1
  1516.         jz      .ansi
  1517.         mov     ecx, 260/2
  1518.         rep movsd
  1519.         mov     [edi-2], ax
  1520. @@:
  1521.         mov     esi, edi
  1522.         pop     edi ecx
  1523. .ret:
  1524.         ret
  1525. .ansi:
  1526.         mov     ecx, 264/4
  1527.         rep movsd
  1528.         mov     [edi-1], al
  1529.         jmp     @b
  1530.  
  1531. bdfe_to_fat_entry:
  1532. ; convert BDFE at edx to FAT entry at edi
  1533. ; destroys eax
  1534. ; attributes byte
  1535.         test    byte [edi+11], 8        ; volume label?
  1536.         jnz     @f
  1537.         mov     al, [edx]
  1538.         and     al, 0x27
  1539.         and     byte [edi+11], 0x10
  1540.         or      byte [edi+11], al
  1541. @@:
  1542.         mov     eax, [edx+8]
  1543.         call    bdfe_to_fat_time
  1544.         mov     [edi+14], ax            ; creation time
  1545.         mov     eax, [edx+12]
  1546.         call    bdfe_to_fat_date
  1547.         mov     [edi+16], ax            ; creation date
  1548.         mov     eax, [edx+20]
  1549.         call    bdfe_to_fat_date
  1550.         mov     [edi+18], ax            ; last access date
  1551.         mov     eax, [edx+24]
  1552.         call    bdfe_to_fat_time
  1553.         mov     [edi+22], ax            ; last write time
  1554.         mov     eax, [edx+28]
  1555.         call    bdfe_to_fat_date
  1556.         mov     [edi+24], ax            ; last write date
  1557.         ret
  1558.  
  1559. hd_find_lfn:
  1560. ; in: esi -> path string
  1561. ; out: CF=1 - file not found, eax=error code
  1562. ;      else CF=0 and edi->direntry, eax=sector
  1563.         push    esi edi
  1564.         push    0
  1565.         push    0
  1566.         push    fat1x_root_first
  1567.         push    fat1x_root_next
  1568.         mov     eax, [ebp+FAT.ROOT_CLUSTER]
  1569.         cmp     [ebp+FAT.fs_type], 32
  1570.         jz      .fat32
  1571. .loop:
  1572.         and     [ebp+FAT.longname_sec1], 0
  1573.         and     [ebp+FAT.longname_sec2], 0
  1574.         call    fat_find_lfn
  1575.         jc      .notfound
  1576.         cmp     byte [esi], 0
  1577.         jz      .found
  1578.         test    byte [edi+11], 10h
  1579.         jz      .notfound
  1580.         and     dword [esp+12], 0
  1581.         mov     eax, [edi+20-2]
  1582.         mov     ax, [edi+26]    ; cluster
  1583. .fat32:
  1584.         mov     [esp+8], eax
  1585.         mov     dword [esp+4], fat_notroot_first
  1586.         mov     dword [esp], fat_notroot_next
  1587.         jmp     .loop
  1588.  
  1589. .notfound:
  1590.         add     esp, 16
  1591.         pop     edi esi
  1592.         stc
  1593.         ret
  1594.  
  1595. .found:
  1596.         lea     eax, [esp+8]
  1597.         cmp     dword [eax], 0
  1598.         jz      .root
  1599.         call    fat_get_sector
  1600.         jmp     .cmn
  1601.  
  1602. .root:
  1603.         mov     eax, [eax+4]
  1604.         add     eax, [ebp+FAT.ROOT_START]
  1605. .cmn:
  1606.         add     esp, 20         ; CF=0
  1607.         pop     esi
  1608.         ret
  1609.  
  1610. ;----------------------------------------------------------------
  1611. fat_Read:
  1612.         call    fat_lock
  1613.         push    edi
  1614.         cmp     byte [esi], 0
  1615.         jnz     @f
  1616. .noaccess:
  1617.         pop     edi
  1618.         call    fat_unlock
  1619.         or      ebx, -1
  1620.         mov     eax, ERROR_ACCESS_DENIED
  1621.         ret
  1622. @@:
  1623.         call    hd_find_lfn
  1624.         jnc     .found
  1625.         pop     edi
  1626.         push    eax
  1627.         call    fat_unlock
  1628.         pop     eax
  1629.         or      ebx, -1
  1630.         ret
  1631. .found:
  1632.         test    byte [edi+11], 0x10     ; do not allow read directories
  1633.         jnz     .noaccess
  1634.         cmp     dword [ebx+8], 0
  1635.         jz      @f
  1636.         xor     ebx, ebx
  1637.         call    fat_unlock
  1638.         mov     eax, ERROR_END_OF_FILE
  1639.         pop     edi
  1640.         ret
  1641. @@:
  1642.         mov     edx, [ebx+4]    ; file offset
  1643.         mov     ecx, [ebx+12]   ; size
  1644.         mov     ebx, [ebx+16]   ; buffer
  1645.         push    ebx
  1646.         push    0
  1647.         test    ecx, ecx
  1648.         jz      .done
  1649.         mov     eax, [edi+28]
  1650.         sub     eax, edx
  1651.         jb      .fileEnd
  1652.         cmp     eax, ecx
  1653.         jae     @f
  1654.         mov     ecx, eax
  1655.         mov     byte [esp], 6
  1656. @@:
  1657.         mov     eax, [edi+20-2]
  1658.         mov     ax, [edi+26]
  1659. ; now eax=cluster, ebx=buffer for data, ecx=count, edx=position
  1660.         mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
  1661.         shl     edi, 9
  1662. @@:
  1663.         cmp     eax, 2
  1664.         jb      .fileEnd
  1665.         cmp     eax, [ebp+FAT.fatRESERVED]
  1666.         jae     .fileEnd
  1667.         sub     edx, edi
  1668.         jc      @f
  1669.         call    get_FAT
  1670.         jc      .noaccess2
  1671.         jmp     @b
  1672. @@:
  1673.         mov     esi, eax
  1674.         dec     eax
  1675.         dec     eax
  1676.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1677.         add     eax, [ebp+FAT.DATA_START]
  1678.         add     edx, edi
  1679.         jz      .alignedCluster
  1680.         mov     edi, edx
  1681.         shr     edi, 9
  1682.         add     eax, edi
  1683.         and     edx, 511
  1684.         cmp     ecx, 512
  1685.         jc      .sectorPiece
  1686.         test    edx, edx
  1687.         jz      .alignedSector
  1688. .sectorPiece:
  1689.         push    eax ebx
  1690.         lea     ebx, [ebp+FAT.buffer]
  1691.         call    fs_read32_app
  1692.         test    eax, eax
  1693.         mov     eax, ebx
  1694.         pop     ebx
  1695.         jne     .noaccess3
  1696.         add     eax, edx
  1697.         push    ecx
  1698.         add     ecx, edx
  1699.         cmp     ecx, 512
  1700.         jbe     @f
  1701.         mov     ecx, 512
  1702. @@:
  1703.         sub     ecx, edx
  1704.         call    memmove
  1705.         sub     [esp], ecx
  1706.         add     ebx, ecx
  1707.         pop     ecx eax
  1708.         xor     edx, edx
  1709.         inc     edi
  1710.         inc     eax
  1711.         test    ecx, ecx
  1712.         jz      .done
  1713. .alignedSector:
  1714.         shl     edi, 9
  1715.         add     ecx, edi
  1716.         mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
  1717.         shl     edi, 9
  1718. .alignedCluster:
  1719.         cmp     ecx, 512
  1720.         jc      .sectorPiece
  1721.         mov     edx, eax
  1722.         mov     eax, esi
  1723. @@:
  1724.         sub     ecx, edi
  1725.         jbe     .readEnd
  1726.         call    get_FAT
  1727.         jc      .noaccess4
  1728.         cmp     eax, 2
  1729.         jb      .fileEnd2
  1730.         cmp     eax, [ebp+FAT.fatRESERVED]
  1731.         jae     .fileEnd2
  1732.         inc     esi
  1733.         cmp     eax, esi
  1734.         jz      @b
  1735. .fragmentEnd:
  1736.         xchg    eax, esi
  1737.         dec     eax
  1738.         dec     eax
  1739.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1740.         add     eax, [ebp+FAT.DATA_START]
  1741.         push    ecx
  1742.         mov     ecx, eax
  1743.         mov     eax, esi
  1744.         dec     eax
  1745.         dec     eax
  1746.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1747.         add     eax, [ebp+FAT.DATA_START]
  1748.         push    eax
  1749. .readFragment:
  1750.         sub     ecx, edx
  1751.         mov     eax, edx
  1752.         xor     edx, edx
  1753.         call    fs_read64_app
  1754.         shl     ecx, 9
  1755.         add     ebx, ecx
  1756.         test    eax, eax
  1757.         pop     eax
  1758.         jnz     .noaccess3
  1759.         pop     ecx
  1760.         xor     edx, edx
  1761.         jecxz   .done
  1762.         jmp     .alignedCluster
  1763. .readEnd:
  1764.         add     ecx, edi
  1765.         mov     edi, ecx
  1766.         and     ecx, 511
  1767.         shr     edi, 9
  1768.         dec     eax
  1769.         dec     eax
  1770.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1771.         add     eax, [ebp+FAT.DATA_START]
  1772.         add     eax, edi
  1773.         push    ecx
  1774.         push    eax
  1775.         mov     ecx, eax
  1776.         jmp     .readFragment
  1777. .noaccess3:
  1778.         pop     eax
  1779. .noaccess2:
  1780.         mov     byte [esp], ERROR_DEVICE
  1781. .done:
  1782.         call    fat_unlock
  1783.         pop     eax edx edi
  1784.         sub     ebx, edx
  1785.         ret
  1786. .fileEnd:
  1787.         mov     byte [esp], ERROR_END_OF_FILE
  1788.         jmp     .done
  1789. .noaccess4:
  1790.         mov     byte [esp], ERROR_DEVICE
  1791.         jmp     @f
  1792. .fileEnd2:
  1793.         mov     byte [esp], ERROR_END_OF_FILE
  1794. @@:
  1795.         inc     esi
  1796.         xor     ecx, ecx
  1797.         jmp     .fragmentEnd
  1798.  
  1799. ;----------------------------------------------------------------
  1800. fat_ReadFolder:
  1801.         call    fat_lock
  1802.         mov     eax, [ebp+FAT.ROOT_CLUSTER]
  1803.         push    edi
  1804.         cmp     byte [esi], 0
  1805.         jz      .doit
  1806.         call    hd_find_lfn
  1807.         jnc     .found
  1808.         pop     edi
  1809.         push    eax
  1810.         call    fat_unlock
  1811.         pop     eax
  1812.         or      ebx, -1
  1813.         ret
  1814. .found:
  1815.         test    byte [edi+11], 0x10     ; do not allow read files
  1816.         jnz     .found_dir
  1817.         pop     edi
  1818.         call    fat_unlock
  1819.         or      ebx, -1
  1820.         mov     eax, ERROR_ACCESS_DENIED
  1821.         ret
  1822. .found_dir:
  1823.         mov     eax, [edi+20-2]
  1824.         mov     ax, [edi+26]    ; eax=cluster
  1825. .doit:
  1826.         push    esi
  1827.         sub     esp, 262*2      ; reserve space for LFN
  1828.         push    dword [ebx+8]   ; for fat_get_name: read ANSI/UNICODE name
  1829.         mov     edx, [ebx+16]   ; pointer to buffer
  1830. ; init header
  1831.         push    eax
  1832.         mov     edi, edx
  1833.         mov     ecx, 32/4
  1834.         xor     eax, eax
  1835.         rep stosd
  1836.         pop     eax
  1837.         mov     byte [edx], 1   ; version
  1838.         mov     esi, edi        ; esi points to BDFE
  1839.         mov     ecx, [ebx+12]   ; number of blocks to read
  1840.         mov     ebx, [ebx+4]    ; index of the first block
  1841. .new_cluster:
  1842.         mov     [ebp+FAT.cluster_tmp], eax
  1843.         test    eax, eax
  1844.         jnz     @f
  1845.         cmp     [ebp+FAT.fs_type], 32
  1846.         jz      .notfound
  1847.         mov     eax, [ebp+FAT.ROOT_START]
  1848.         push    [ebp+FAT.ROOT_SECTORS]
  1849.         push    ebx
  1850.         jmp     .new_sector
  1851. @@:
  1852.         dec     eax
  1853.         dec     eax
  1854.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1855.         push    [ebp+FAT.SECTORS_PER_CLUSTER]
  1856.         add     eax, [ebp+FAT.DATA_START]
  1857.         push    ebx
  1858. .new_sector:
  1859.         lea     ebx, [ebp+FAT.buffer]
  1860.         mov     edi, ebx
  1861.         push    eax
  1862.         call    fs_read32_sys
  1863.         test    eax, eax
  1864.         pop     eax
  1865.         jnz     .notfound2
  1866.         add     ebx, 512
  1867.         push    eax
  1868. .l1:
  1869.         push    ebp
  1870.         lea     ebp, [esp+20]
  1871.         call    fat_get_name
  1872.         pop     ebp
  1873.         jc      .l2
  1874.         cmp     byte [edi+11], 0xF
  1875.         jnz     .do_bdfe
  1876.         add     edi, 0x20
  1877.         cmp     edi, ebx
  1878.         jb      .do_bdfe
  1879.         pop     eax
  1880.         inc     eax
  1881.         dec     dword [esp+4]
  1882.         jnz     @f
  1883.         mov     eax, [ebp+FAT.cluster_tmp]
  1884.         test    eax, eax
  1885.         jz      .done
  1886.         call    get_FAT
  1887.         jc      .notfound2
  1888.         cmp     eax, 2
  1889.         jb      .done
  1890.         cmp     eax, [ebp+FAT.fatRESERVED]
  1891.         jae     .done
  1892.         push    eax
  1893.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1894.         mov     [esp+8], eax
  1895.         pop     eax
  1896.         mov     [ebp+FAT.cluster_tmp], eax
  1897.         dec     eax
  1898.         dec     eax
  1899.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1900.         add     eax, [ebp+FAT.DATA_START]
  1901. @@:
  1902.         lea     ebx, [ebp+FAT.buffer]
  1903.         mov     edi, ebx
  1904.         push    eax
  1905.         call    fs_read32_sys
  1906.         test    eax, eax
  1907.         pop     eax
  1908.         jnz     .notfound2
  1909.         add     ebx, 512
  1910.         push    eax
  1911. .do_bdfe:
  1912.         inc     dword [edx+8]   ; new file found
  1913.         dec     dword [esp+4]
  1914.         jns     .l2
  1915.         dec     ecx
  1916.         js      .l2
  1917.         inc     dword [edx+4]   ; new file block copied
  1918.         push    ebp
  1919.         lea     ebp, [esp+20]
  1920.         call    fat_entry_to_bdfe
  1921.         pop     ebp
  1922. .l2:
  1923.         add     edi, 0x20
  1924.         cmp     edi, ebx
  1925.         jb      .l1
  1926.         pop     eax
  1927.         inc     eax
  1928.         dec     dword [esp+4]
  1929.         jnz     .new_sector
  1930.         mov     eax, [ebp+FAT.cluster_tmp]
  1931.         test    eax, eax
  1932.         jz      .done
  1933.         call    get_FAT
  1934.         jc      .notfound2
  1935.         cmp     eax, 2
  1936.         jb      .done
  1937.         cmp     eax, [ebp+FAT.fatRESERVED]
  1938.         jae     .done
  1939.         push    eax
  1940.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1941.         mov     [esp+8], eax
  1942.         pop     eax
  1943.         pop     ebx
  1944.         add     esp, 4
  1945.         jmp     .new_cluster
  1946. .notfound2:
  1947.         add     esp, 8
  1948. .notfound:
  1949.         add     esp, 262*2+4
  1950.         pop     esi edi
  1951.         mov     ebx, [edx+4]
  1952.         call    fat_unlock
  1953.         mov     eax, ERROR_DEVICE
  1954.         ret
  1955. .done:
  1956.         add     esp, 262*2+4+8
  1957.         mov     ebx, [edx+4]
  1958.         xor     eax, eax
  1959.         dec     ecx
  1960.         js      @f
  1961.         mov     al, ERROR_END_OF_FILE
  1962. @@:
  1963.         push    eax
  1964.         call    fat_unlock
  1965.         pop     eax
  1966.         pop     esi edi
  1967.         ret
  1968.  
  1969. fat1x_root_next:
  1970.         push    ecx
  1971.         lea     ecx, [ebp+FAT.buffer+0x200-0x20]
  1972.         cmp     edi, ecx
  1973.         jae     fat1x_root_next_sector
  1974.         pop     ecx
  1975.         add     edi, 0x20
  1976.         ret     ; CF=0
  1977. fat1x_root_next_sector:
  1978. ; read next sector
  1979.         push    [ebp+FAT.longname_sec2]
  1980.         pop     [ebp+FAT.longname_sec1]
  1981.         mov     ecx, [eax+4]
  1982.         push    ecx
  1983.         add     ecx, [ebp+FAT.ROOT_START]
  1984.         mov     [ebp+FAT.longname_sec2], ecx
  1985.         pop     ecx
  1986.         inc     ecx
  1987.         mov     [eax+4], ecx
  1988.         cmp     ecx, [ebp+FAT.ROOT_SECTORS]
  1989.         pop     ecx
  1990.         jb      fat1x_root_first
  1991.         mov     eax, ERROR_FILE_NOT_FOUND
  1992.         stc
  1993.         ret
  1994. fat1x_root_first:
  1995.         mov     eax, [eax+4]
  1996.         add     eax, [ebp+FAT.ROOT_START]
  1997.         push    ebx
  1998.         lea     edi, [ebp+FAT.buffer]
  1999.         mov     ebx, edi
  2000.         call    fs_read32_sys
  2001.         pop     ebx
  2002.         test    eax, eax
  2003.         jnz     .readerr
  2004.         ret     ; CF=0
  2005. .readerr:
  2006.         mov     eax, ERROR_DEVICE
  2007.         stc
  2008.         ret
  2009. .notfound:
  2010.         mov     eax, ERROR_FILE_NOT_FOUND
  2011.         stc
  2012.         ret
  2013. fat1x_root_begin_write:
  2014.         push    edi eax
  2015.         call    fat1x_root_first
  2016.         pop     eax edi
  2017.         ret
  2018. fat1x_root_end_write:
  2019.         pusha
  2020.         mov     eax, [eax+4]
  2021.         add     eax, [ebp+FAT.ROOT_START]
  2022.         lea     ebx, [ebp+FAT.buffer]
  2023.         call    fs_write32_sys
  2024.         popa
  2025.         ret
  2026. fat1x_root_next_write:
  2027.         push    ecx
  2028.         lea     ecx, [ebp+FAT.buffer+0x200]
  2029.         cmp     edi, ecx
  2030.         jae     @f
  2031.         pop     ecx
  2032.         ret
  2033. @@:
  2034.         call    fat1x_root_end_write
  2035.         jmp     fat1x_root_next_sector
  2036. fat1x_root_extend_dir:
  2037.         stc
  2038.         ret
  2039.  
  2040. fat_notroot_next:
  2041.         push    ecx
  2042.         lea     ecx, [ebp+FAT.buffer+0x200-0x20]
  2043.         cmp     edi, ecx
  2044.         jae     fat_notroot_next_sector
  2045.         pop     ecx
  2046.         add     edi, 0x20
  2047.         ret     ; CF=0
  2048. fat_notroot_next_sector:
  2049.         push    [ebp+FAT.longname_sec2]
  2050.         pop     [ebp+FAT.longname_sec1]
  2051.         push    eax
  2052.         call    fat_get_sector
  2053.         mov     [ebp+FAT.longname_sec2], eax
  2054.         pop     eax
  2055.         mov     ecx, [eax+4]
  2056.         inc     ecx
  2057.         cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2058.         jae     fat_notroot_next_cluster
  2059.         mov     [eax+4], ecx
  2060.         jmp     @f
  2061. fat_notroot_next_cluster:
  2062.         push    eax
  2063.         mov     eax, [eax]
  2064.         call    get_FAT
  2065.         mov     ecx, eax
  2066.         pop     eax
  2067.         jc      fat_notroot_first.deverr
  2068.         cmp     ecx, 2
  2069.         jb      fat_notroot_next_err
  2070.         cmp     ecx, [ebp+FAT.fatRESERVED]
  2071.         jae     fat_notroot_next_err
  2072.         mov     [eax], ecx
  2073.         and     dword [eax+4], 0
  2074. @@:
  2075.         pop     ecx
  2076. fat_notroot_first:
  2077.         call    fat_get_sector
  2078.         push    ebx
  2079.         lea     edi, [ebp+FAT.buffer]
  2080.         mov     ebx, edi
  2081.         call    fs_read32_sys
  2082.         pop     ebx
  2083.         test    eax, eax
  2084.         jz      .ret ; CF=0
  2085.         push    ecx
  2086. .deverr:
  2087.         pop     ecx
  2088.         mov     eax, ERROR_DEVICE
  2089.         stc
  2090. .ret:
  2091.         ret
  2092. fat_notroot_next_err:
  2093.         pop     ecx
  2094.         mov     eax, ERROR_FILE_NOT_FOUND
  2095.         stc
  2096.         ret
  2097. fat_notroot_begin_write:
  2098.         push    eax edi
  2099.         call    fat_notroot_first
  2100.         pop     edi eax
  2101.         ret
  2102. fat_notroot_end_write:
  2103.         call    fat_get_sector
  2104.         push    ebx
  2105.         lea     ebx, [ebp+FAT.buffer]
  2106.         call    fs_write32_sys
  2107.         pop     ebx
  2108.         ret
  2109. fat_notroot_next_write:
  2110.         push    ecx
  2111.         lea     ecx, [ebp+FAT.buffer+0x200]
  2112.         cmp     edi, ecx
  2113.         jae     @f
  2114.         pop     ecx
  2115.         ret
  2116. @@:
  2117.         push    eax
  2118.         call    fat_notroot_end_write
  2119.         pop     eax
  2120.         jmp     fat_notroot_next_sector
  2121. fat_notroot_extend_dir:
  2122.         push    eax
  2123.         call    get_free_FAT
  2124.         jnc     .found
  2125.         pop     eax
  2126.         ret     ; CF=1
  2127. .found:
  2128.         push    edx
  2129.         mov     edx, [ebp+FAT.fatEND]
  2130.         call    set_FAT
  2131.         jc      .writeerr
  2132.         mov     edx, eax
  2133.         mov     eax, [esp+4]
  2134.         mov     eax, [eax]
  2135.         push    edx
  2136.         call    set_FAT
  2137.         pop     edx
  2138.         jnc     @f
  2139. .writeerr:
  2140.         pop     edx
  2141.         pop     eax
  2142.         stc
  2143.         ret
  2144. @@:
  2145.         push    ecx
  2146.         or      ecx, -1
  2147.         call    add_disk_free_space
  2148. ; zero new cluster
  2149.         mov     ecx, 512/4
  2150.         lea     edi, [ebp+FAT.buffer]
  2151.         push    edi
  2152.         xor     eax, eax
  2153.         rep stosd
  2154.         pop     edi
  2155.         pop     ecx
  2156.         mov     eax, [esp+4]
  2157.         mov     [eax], edx
  2158.         and     dword [eax+4], 0
  2159.         pop     edx
  2160.         mov     eax, [eax]
  2161.         dec     eax
  2162.         dec     eax
  2163.         push    ebx ecx
  2164.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2165.         imul    eax, ecx
  2166.         add     eax, [ebp+FAT.DATA_START]
  2167.         mov     ebx, edi
  2168. @@:
  2169.         push    eax
  2170.         call    fs_write32_sys
  2171.         pop     eax
  2172.         inc     eax
  2173.         loop    @b
  2174.         pop     ecx ebx eax
  2175.         clc
  2176.         ret
  2177.  
  2178. fat_get_sector:
  2179.         push    ecx
  2180.         mov     ecx, [eax]
  2181.         dec     ecx
  2182.         dec     ecx
  2183.         imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2184.         add     ecx, [ebp+FAT.DATA_START]
  2185.         add     ecx, [eax+4]
  2186.         mov     eax, ecx
  2187.         pop     ecx
  2188.         ret
  2189.  
  2190. fshrad:
  2191.         call    fat_unlock
  2192.         mov     eax, ERROR_ACCESS_DENIED
  2193.         xor     ebx, ebx
  2194.         ret
  2195.  
  2196. ;----------------------------------------------------------------
  2197. fat_CreateFolder:
  2198.         push    1
  2199.         jmp     @f
  2200.  
  2201. fat_CreateFile:
  2202.         push    0
  2203. @@:
  2204.         call    fat_lock
  2205.         pop     eax
  2206.         cmp     byte [esi], 0
  2207.         jz      fshrad
  2208.         mov     ecx, [ebx+12]
  2209.         mov     edx, [ebx+16]
  2210.         pushad
  2211.         xor     edi, edi
  2212.         push    esi
  2213. @@:
  2214.         lodsb
  2215.         test    al, al
  2216.         jz      @f
  2217.         cmp     al, '/'
  2218.         jnz     @b
  2219.         lea     edi, [esi-1]
  2220.         jmp     @b
  2221.  
  2222. @@:
  2223.         pop     esi
  2224.         test    edi, edi
  2225.         jnz     .noroot
  2226.         mov     edx, [ebp+FAT.ROOT_CLUSTER]
  2227.         cmp     [ebp+FAT.fs_type], 32
  2228.         jz      .pushnotroot
  2229.         xor     edx, edx
  2230.         push    edx
  2231.         push    fat1x_root_extend_dir
  2232.         push    fat1x_root_end_write
  2233.         push    fat1x_root_next_write
  2234.         push    fat1x_root_begin_write
  2235.         push    edx
  2236.         push    edx
  2237.         push    fat1x_root_first
  2238.         push    fat1x_root_next
  2239.         jmp     .common1
  2240.  
  2241. .noroot:
  2242.         mov     eax, ERROR_ACCESS_DENIED
  2243.         cmp     byte [edi+1], 0
  2244.         jz      .ret1
  2245. ; check existence
  2246.         mov     byte [edi], 0
  2247.         push    edi
  2248.         call    hd_find_lfn
  2249.         pop     esi
  2250.         mov     byte [esi], '/'
  2251.         jnc     @f
  2252. .notfound0:
  2253.         mov     eax, ERROR_FILE_NOT_FOUND
  2254. .ret1:
  2255.         mov     [esp+28], eax
  2256.         call    fat_unlock
  2257.         popad
  2258.         xor     ebx, ebx
  2259.         ret
  2260.  
  2261. @@:
  2262.         inc     esi
  2263.         test    byte [edi+11], 0x10     ; must be directory
  2264.         mov     eax, ERROR_ACCESS_DENIED
  2265.         jz      .ret1
  2266.         mov     edx, [edi+20-2]
  2267.         mov     dx, [edi+26]            ; ebp=cluster
  2268.         mov     eax, ERROR_FS_FAIL
  2269.         cmp     edx, 2
  2270.         jb      .ret1
  2271. .pushnotroot:
  2272.         push    edx
  2273.         push    fat_notroot_extend_dir
  2274.         push    fat_notroot_end_write
  2275.         push    fat_notroot_next_write
  2276.         push    fat_notroot_begin_write
  2277.         push    0
  2278.         push    edx
  2279.         push    fat_notroot_first
  2280.         push    fat_notroot_next
  2281. .common1:
  2282.         call    fat_find_lfn
  2283.         jc      .notfound
  2284.         test    byte [edi+11], 10h
  2285.         jz      .exists_file
  2286. ; found directory
  2287.         add     esp, 36
  2288.         call    fat_unlock
  2289.         popad
  2290.         test    al, al
  2291.         mov     eax, ERROR_ACCESS_DENIED
  2292.         jz      @f
  2293.         mov     al, 0
  2294. @@:
  2295.         xor     ebx, ebx
  2296.         ret
  2297.  
  2298. .exists_file:
  2299.         cmp     byte [esp+36+28], 0
  2300.         jz      @f
  2301.         add     esp, 36
  2302.         call    fat_unlock
  2303.         popad
  2304.         mov     eax, ERROR_ACCESS_DENIED
  2305.         xor     ebx, ebx
  2306.         ret
  2307.  
  2308. @@: ; delete FAT chain
  2309.         push    edi
  2310.         xor     eax, eax
  2311.         mov     dword [edi+28], eax     ; zero size
  2312.         xor     ecx, ecx
  2313.         mov     eax, [edi+20-2]
  2314.         mov     ax, [edi+26]
  2315.         mov     word [edi+20], cx
  2316.         mov     word [edi+26], cx
  2317.         test    eax, eax
  2318.         jz      .done1
  2319. @@:
  2320.         cmp     eax, [ebp+FAT.fatRESERVED]
  2321.         jae     .done1
  2322.         push    edx
  2323.         xor     edx, edx
  2324.         call    set_FAT
  2325.         mov     eax, edx
  2326.         pop     edx
  2327.         jc      .done1
  2328.         inc     ecx
  2329.         jmp     @b
  2330.  
  2331. .short_name_found:
  2332.         pop     ecx edi esi
  2333.         call    fat_next_short_name
  2334.         jnc     .test_short_name_loop
  2335. .disk_full:
  2336.         add     esp, 12+36
  2337.         call    fat_unlock
  2338.         popa
  2339.         mov     eax, ERROR_DISK_FULL
  2340.         xor     ebx, ebx
  2341.         ret
  2342.  
  2343. .notfound:  ; generate short name
  2344.         call    fat_name_is_legal
  2345.         jc      @f
  2346.         add     esp, 36
  2347.         call    fat_unlock
  2348.         popad
  2349.         mov     eax, ERROR_FILE_NOT_FOUND
  2350.         xor     ebx, ebx
  2351.         ret
  2352.  
  2353. @@:
  2354.         sub     esp, 12
  2355.         mov     edi, esp
  2356.         call    fat_gen_short_name
  2357. .test_short_name_loop:
  2358.         push    esi edi ecx
  2359.         mov     esi, edi
  2360.         lea     eax, [esp+12+12+8]
  2361.         mov     edx, [eax+24]
  2362.         mov     [eax], edx
  2363.         and     dword [eax+4], 0
  2364.         call    dword [eax-4]
  2365.         jc      .found
  2366. .test_short_name_entry:
  2367.         cmp     byte [edi+11], 0xF
  2368.         jz      .test_short_name_cont
  2369.         mov     ecx, 11
  2370.         push    esi edi
  2371.         repz cmpsb
  2372.         pop     edi esi
  2373.         jz      .short_name_found
  2374. .test_short_name_cont:
  2375.         lea     eax, [esp+12+12+8]
  2376.         call    dword [eax-8]
  2377.         jnc     .test_short_name_entry
  2378. .found:
  2379.         pop     ecx edi esi
  2380. ; now find space in directory
  2381. ; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
  2382.         mov     al, '~'
  2383.         push    ecx edi
  2384.         mov     ecx, 8
  2385.         repnz scasb
  2386.         movi    eax, 1     ; 1 entry
  2387.         jnz     .notilde
  2388. ; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
  2389.         xor     eax, eax
  2390. @@:
  2391.         cmp     byte [esi], 0
  2392.         jz      @f
  2393.         inc     esi
  2394.         inc     eax
  2395.         jmp     @b
  2396.  
  2397. @@:
  2398.         sub     esi, eax
  2399.         add     eax, 12+13
  2400.         mov     ecx, 13
  2401.         push    edx
  2402.         cdq
  2403.         div     ecx
  2404.         pop     edx
  2405. .notilde:
  2406.         push    -1
  2407.         push    -1
  2408.         push    -1
  2409. ; find <eax> successive entries in directory
  2410.         xor     ecx, ecx
  2411.         push    eax
  2412.         lea     eax, [esp+16+8+12+8]
  2413.         mov     edx, [eax+24]
  2414.         mov     [eax], edx
  2415.         and     dword [eax+4], 0
  2416.         call    dword [eax-4]
  2417.         pop     eax
  2418.         jnc     .scan_dir
  2419. .fsfrfe3:
  2420.         add     esp, 12+8+12+36
  2421.         call    fat_unlock
  2422.         popad
  2423.         mov     eax, ERROR_DEVICE
  2424.         xor     ebx, ebx
  2425.         ret
  2426.  
  2427. .scan_dir:
  2428.         cmp     byte [edi], 0
  2429.         jz      .free
  2430.         cmp     byte [edi], 0xE5
  2431.         jz      .free
  2432.         xor     ecx, ecx
  2433. .scan_cont:
  2434.         push    eax
  2435.         lea     eax, [esp+16+8+12+8]
  2436.         call    dword [eax-8]
  2437.         mov     edx, eax
  2438.         pop     eax
  2439.         jnc     .scan_dir
  2440.         cmp     edx, ERROR_DEVICE
  2441.         jz      .fsfrfe3
  2442.         push    eax
  2443.         lea     eax, [esp+16+8+12+8]
  2444.         call    dword [eax+20]          ; extend directory
  2445.         pop     eax
  2446.         jnc     .scan_dir
  2447.         add     esp, 12+8+12+36
  2448.         call    fat_unlock
  2449.         popad
  2450.         mov     eax, ERROR_DISK_FULL
  2451.         xor     ebx, ebx
  2452.         ret
  2453.  
  2454. .free:
  2455.         test    ecx, ecx
  2456.         jnz     @f
  2457.         mov     [esp], edi
  2458.         mov     ecx, [esp+12+8+12+8]
  2459.         mov     [esp+4], ecx
  2460.         mov     ecx, [esp+12+8+12+12]
  2461.         mov     [esp+8], ecx
  2462.         xor     ecx, ecx
  2463. @@:
  2464.         inc     ecx
  2465.         cmp     ecx, eax
  2466.         jb      .scan_cont
  2467. ; found!
  2468.         push    esi ecx
  2469. ; If creating a directory, allocate one data cluster now and fail immediately
  2470. ; if this is impossible. This prevents from creating an invalid directory entry
  2471. ; on a full disk.
  2472. ; yup, the argument is quite non-intuitive... but what should I do if
  2473. ; the entire function uses such arguments? BTW, it refers to al from pushad,
  2474. ; which in turn is filled with 0 in fat_CreateFile and 1 in fat_CreateFolder.
  2475.         cmp     byte [esp+8+12+8+12+36+28], 0
  2476.         jz      .no.preallocate.folder.data
  2477.         call    get_free_FAT
  2478.         jnc     @f
  2479.         add     esp, 8+12+8
  2480.         jmp     .disk_full
  2481.  
  2482. @@:
  2483.         mov     [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
  2484. .no.preallocate.folder.data:    ; calculate name checksum
  2485.         mov     esi, [esp+8+12]
  2486.         mov     ecx, 11
  2487.         xor     eax, eax
  2488. @@:
  2489.         ror     al, 1
  2490.         add     al, [esi]
  2491.         inc     esi
  2492.         loop    @b
  2493.         pop     ecx esi
  2494.         pop     edi
  2495.         pop     dword [esp+8+12+12]
  2496.         pop     dword [esp+8+12+12]
  2497. ; edi points to first entry in free chunk
  2498.         dec     ecx
  2499.         jz      .nolfn
  2500.         push    esi
  2501.         push    eax
  2502.         lea     eax, [esp+8+8+12+8]
  2503.         call    dword [eax+8]         ; begin write
  2504.         mov     al, 40h
  2505. .writelfn:
  2506.         or      al, cl
  2507.         mov     esi, [esp+4]
  2508.         push    ecx
  2509.         dec     ecx
  2510.         imul    ecx, 13
  2511.         add     esi, ecx
  2512.         stosb
  2513.         mov     cl, 5
  2514.         call    fat_read_symbols
  2515.         mov     ax, 0xF
  2516.         stosw
  2517.         mov     al, [esp+4]
  2518.         stosb
  2519.         mov     cl, 6
  2520.         call    fat_read_symbols
  2521.         xor     eax, eax
  2522.         stosw
  2523.         mov     cl, 2
  2524.         call    fat_read_symbols
  2525.         pop     ecx
  2526.         lea     eax, [esp+8+8+12+8]
  2527.         call    dword [eax+12]         ; next write
  2528.         xor     eax, eax
  2529.         loop    .writelfn
  2530.         pop     eax
  2531.         pop     esi
  2532. .nolfn:
  2533.         xchg    esi, [esp]
  2534.         mov     ecx, 11
  2535.         rep movsb
  2536.         mov     word [edi], 20h         ; attributes
  2537.         sub     edi, 11
  2538.         pop     esi ecx
  2539.         add     esp, 12
  2540.         mov     byte [edi+13], 0        ; tenths of a second at file creation time
  2541.         call    get_time_for_file
  2542.         mov     [edi+14], ax            ; creation time
  2543.         mov     [edi+22], ax            ; last write time
  2544.         call    get_date_for_file
  2545.         mov     [edi+16], ax            ; creation date
  2546.         mov     [edi+24], ax            ; last write date
  2547.         mov     [edi+18], ax            ; last access date
  2548.         xor     ecx, ecx
  2549.         mov     word [edi+20], cx       ; high word of cluster
  2550.         mov     word [edi+26], cx       ; low word of cluster - to be filled
  2551.         mov     dword [edi+28], ecx     ; file size - to be filled
  2552.         cmp     byte [esp+36+28], cl
  2553.         jz      .doit
  2554. ; create directory
  2555.         mov     byte [edi+11], 10h      ; attributes: folder
  2556.         mov     esi, edi
  2557.         lea     eax, [esp+8]
  2558.         call    dword [eax+16]  ; flush directory
  2559.         mov     eax, [esp+36+20] ; extract saved cluster
  2560.         mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
  2561.         push    ecx
  2562.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2563.         shl     ecx, 9
  2564.         push    ecx
  2565.         push    edi
  2566.         jmp     .doit2
  2567.  
  2568. .done1:
  2569.         pop     edi
  2570.         call    get_time_for_file
  2571.         mov     [edi+22], ax
  2572.         call    get_date_for_file
  2573.         mov     [edi+24], ax
  2574.         mov     [edi+18], ax
  2575.         or      byte [edi+11], 20h      ; set 'archive' attribute
  2576. .doit:
  2577.         mov     esi, [esp+36+20]
  2578.         lea     eax, [esp+8]
  2579.         call    dword [eax+16]  ; flush directory
  2580.         push    ecx
  2581.         mov     ecx, [esp+4+36+24]
  2582.         push    ecx
  2583.         push    edi
  2584.         test    ecx, ecx
  2585.         jz      .done
  2586.         call    get_free_FAT
  2587.         jc      .diskfull
  2588. .doit2:
  2589.         push    eax
  2590.         mov     [edi+26], ax
  2591.         shr     eax, 16
  2592.         mov     [edi+20], ax
  2593.         lea     eax, [esp+16+8]
  2594.         call    dword [eax+16]  ; flush directory
  2595.         pop     eax
  2596.         push    edx
  2597.         mov     edx, [ebp+FAT.fatEND]
  2598.         call    set_FAT
  2599.         pop     edx
  2600. .write_cluster:
  2601.         push    eax
  2602.         dec     eax
  2603.         dec     eax
  2604.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2605.         add     eax, [ebp+FAT.DATA_START]
  2606.         push    [ebp+FAT.SECTORS_PER_CLUSTER]
  2607. .write_sector:
  2608.         cmp     byte [esp+20+36+28], 0
  2609.         jnz     .writedir
  2610.         mov     ecx, 512
  2611.         cmp     dword [esp+12], ecx
  2612.         jb      .writeshort
  2613. ; we can write directly from given buffer
  2614.         mov     ebx, esi
  2615.         add     esi, ecx
  2616.         jmp     .writecommon
  2617.  
  2618. .writeshort:
  2619.         mov     ecx, [esp+12]
  2620.         push    ecx
  2621.         lea     edi, [ebp+FAT.buffer]
  2622.         mov     ebx, edi
  2623.         rep movsb
  2624. .writedircont:
  2625.         lea     ecx, [ebp+FAT.buffer+0x200]
  2626.         sub     ecx, edi
  2627.         push    eax
  2628.         xor     eax, eax
  2629.         rep stosb
  2630.         pop     eax
  2631.         pop     ecx
  2632. .writecommon:
  2633.         push    eax
  2634.         call    fs_write32_app
  2635.         test    eax, eax
  2636.         pop     eax
  2637.         jnz     .writeerr
  2638.         inc     eax
  2639.         sub     dword [esp+12], ecx
  2640.         jz      .writedone
  2641.         dec     dword [esp]
  2642.         jnz     .write_sector
  2643.         pop     eax
  2644. ; allocate new cluster
  2645.         pop     eax
  2646.         mov     ecx, eax
  2647.         call    get_free_FAT
  2648.         jc      .diskfull
  2649.         push    edx
  2650.         mov     edx, [ebp+FAT.fatEND]
  2651.         call    set_FAT
  2652.         xchg    eax, ecx
  2653.         mov     edx, ecx
  2654.         call    set_FAT
  2655.         pop     edx
  2656.         xchg    eax, ecx
  2657.         jmp     .write_cluster
  2658.  
  2659. .diskfull:
  2660.         mov     eax, ERROR_DISK_FULL
  2661.         jmp     .ret
  2662.  
  2663. .writeerr:
  2664.         pop     eax eax
  2665.         sub     esi, ecx
  2666.         mov     eax, ERROR_DEVICE
  2667.         jmp     .ret
  2668.  
  2669. .writedone:
  2670.         pop     eax eax
  2671. .done:
  2672.         xor     eax, eax
  2673. .ret:
  2674.         pop     edi ecx
  2675.         sub     esi, [esp+4+36+20]
  2676.         mov     [esp+4+36+28], eax
  2677.         mov     [esp+4+36+16], esi
  2678.         lea     eax, [esp+12]
  2679.         call    dword [eax+8]
  2680.         mov     [edi+28], esi
  2681.         call    dword [eax+16]
  2682.         mov     [esp+36+16], ebx
  2683.         lea     eax, [esi+511]
  2684.         shr     eax, 9
  2685.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2686.         lea     eax, [eax+ecx-1]
  2687.         xor     edx, edx
  2688.         div     ecx
  2689.         pop     ecx
  2690.         sub     ecx, eax
  2691.         call    add_disk_free_space
  2692.         add     esp, 36
  2693.         call    update_disk
  2694.         call    fat_unlock
  2695.         popad
  2696.         ret
  2697.  
  2698. .writedir:
  2699.         push    512
  2700.         lea     edi, [ebp+FAT.buffer]
  2701.         mov     ebx, edi
  2702.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2703.         shl     ecx, 9
  2704.         cmp     ecx, [esp+16]
  2705.         jnz     .writedircont
  2706.         dec     dword [esp+20]
  2707.         push    esi
  2708.         mov     ecx, 32/4
  2709.         rep movsd
  2710.         pop     esi
  2711.         mov     dword [edi-32], '.   '
  2712.         mov     dword [edi-32+4], '    '
  2713.         mov     dword [edi-32+8], '    '
  2714.         mov     byte [edi-32+11], 10h
  2715.         push    esi
  2716.         mov     ecx, 32/4
  2717.         rep movsd
  2718.         pop     esi
  2719.         mov     dword [edi-32], '..  '
  2720.         mov     dword [edi-32+4], '    '
  2721.         mov     dword [edi-32+8], '    '
  2722.         mov     byte [edi-32+11], 10h
  2723.         mov     ecx, [esp+20+36]
  2724.         cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
  2725.         jnz     @f
  2726.         xor     ecx, ecx
  2727. @@:
  2728.         mov     word [edi-32+26], cx
  2729.         shr     ecx, 16
  2730.         mov     [edi-32+20], cx
  2731.         jmp     .writedircont
  2732.  
  2733. fat_read_symbol:
  2734.         or      ax, -1
  2735.         test    esi, esi
  2736.         jz      .retFFFF
  2737.         lodsb
  2738.         test    al, al
  2739.         jnz     ansi2uni_char
  2740.         xor     eax, eax
  2741.         xor     esi, esi
  2742. .retFFFF:
  2743.         ret
  2744.  
  2745. fat_read_symbols:
  2746.         call    fat_read_symbol
  2747.         stosw
  2748.         loop    fat_read_symbols
  2749.         ret
  2750.  
  2751. ;----------------------------------------------------------------
  2752. fat_Write:
  2753.         cmp     byte [esi], 0
  2754.         jz      .access_denied
  2755.         call    fat_lock
  2756.         push    edi
  2757.         call    hd_find_lfn
  2758.         jnc     .found
  2759.         pop     edi
  2760.         push    eax
  2761.         call    fat_unlock
  2762. .ret0:
  2763.         pop     eax
  2764.         xor     ebx, ebx
  2765.         ret
  2766.  
  2767. .access_denied:
  2768.         push    ERROR_ACCESS_DENIED
  2769.         jmp     .ret0
  2770.  
  2771. .found:     ; FAT does not support files larger than 4GB
  2772.         cmp     dword [ebx+8], 0
  2773.         jz      @f
  2774. .eof:
  2775.         pop     edi
  2776.         push    ERROR_END_OF_FILE
  2777.         call    fat_unlock
  2778.         jmp     .ret0
  2779. @@:
  2780.         mov     ecx, [ebx+12]
  2781.         mov     edx, [ebx+16]
  2782.         mov     ebx, [ebx+4]
  2783. ; now edi points to direntry, ebx=start byte to write,
  2784. ; ecx=number of bytes to write, edx=data pointer
  2785. ; extend file if needed
  2786.         add     ecx, ebx
  2787.         jc      .eof    ; FAT does not support files larger than 4GB
  2788.         push    edx
  2789.         push    eax     ; save directory sector
  2790.         push    0       ; return value=0
  2791.         call    get_time_for_file
  2792.         mov     [edi+22], ax            ; last write time
  2793.         call    get_date_for_file
  2794.         mov     [edi+24], ax            ; last write date
  2795.         mov     [edi+18], ax            ; last access date
  2796.         push    dword [edi+28]          ; save current file size
  2797.         cmp     ecx, [edi+28]
  2798.         jbe     .length_ok
  2799.         cmp     ecx, ebx
  2800.         jz      .length_ok
  2801.         call    hd_extend_file
  2802.         jnc     .length_ok
  2803.         mov     [esp+4], eax
  2804. ; hd_extend_file can return three error codes: FAT table error, device error or disk full.
  2805. ; First two cases are fatal errors, in third case we may write some data
  2806.         cmp     al, ERROR_DISK_FULL
  2807.         jz      .disk_full
  2808.         call    fat_unlock
  2809.         pop     eax
  2810.         pop     eax
  2811.         pop     ecx
  2812.         pop     edx
  2813.         pop     edi
  2814.         xor     ebx, ebx
  2815.         ret
  2816. .disk_full:
  2817. ; correct number of bytes to write
  2818.         mov     ecx, [edi+28]
  2819.         cmp     ecx, ebx
  2820.         ja      .length_ok
  2821.         push    0
  2822. .ret:
  2823.         pop     eax
  2824.         sub     edx, [esp+12]
  2825.         mov     ebx, edx        ; ebx=number of written bytes
  2826.         call    update_disk
  2827.         test    eax, eax
  2828.         jz      @f
  2829.         mov     byte [esp+4], ERROR_DEVICE
  2830. @@:
  2831.         call    fat_unlock
  2832.         pop     eax
  2833.         pop     eax
  2834.         pop     ecx
  2835.         pop     edx
  2836.         pop     edi
  2837.         ret
  2838. .length_ok:
  2839.         mov     esi, [edi+28]
  2840.         mov     eax, [edi+20-2]
  2841.         mov     ax, [edi+26]
  2842.         mov     edi, eax        ; edi=current cluster
  2843.         push    0               ; current sector in cluster
  2844. ; save directory
  2845.         mov     eax, [esp+12]
  2846.         push    ebx
  2847.         lea     ebx, [ebp+FAT.buffer]
  2848.         call    fs_write32_sys
  2849.         pop     ebx
  2850.         test    eax, eax
  2851.         jz      @f
  2852. .device_err:
  2853.         mov     byte [esp+8], ERROR_DEVICE
  2854.         jmp     .ret
  2855. .fat_err:
  2856.         mov     byte [esp+8], ERROR_FS_FAIL
  2857.         jmp     .ret
  2858. @@:
  2859.  
  2860. ; now ebx=start pos, ecx=end pos, both lie inside file
  2861.         sub     ecx, ebx
  2862.         jz      .ret
  2863. .write_loop:
  2864. ; skip unmodified sectors
  2865.         cmp     dword [esp+4], 0x200
  2866.         jb      .modify
  2867.         sub     ebx, 0x200
  2868.         jae     .skip
  2869.         add     ebx, 0x200
  2870. .modify:
  2871. ; get length of data in current sector
  2872.         push    ecx
  2873.         sub     ebx, 0x200
  2874.         jb      .hasdata
  2875.         neg     ebx
  2876.         xor     ecx, ecx
  2877.         jmp     @f
  2878. .hasdata:
  2879.         neg     ebx
  2880.         cmp     ecx, ebx
  2881.         jbe     @f
  2882.         mov     ecx, ebx
  2883. @@:
  2884. ; get current sector number
  2885.         mov     eax, edi
  2886.         dec     eax
  2887.         dec     eax
  2888.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2889.         add     eax, [ebp+FAT.DATA_START]
  2890.         add     eax, [esp+4]
  2891. ; load sector if needed
  2892.         cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
  2893.         jz      .noread
  2894.         cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
  2895.         jz      .noread
  2896.         cmp     ecx, esi        ; (same for the last sector)
  2897.         jz      .noread
  2898.         push    eax ebx
  2899.         lea     ebx, [ebp+FAT.buffer]
  2900.         call    fs_read32_app
  2901.         test    eax, eax
  2902.         pop     ebx eax
  2903.         jz      @f
  2904. .device_err2:
  2905.         pop     ecx
  2906.         jmp     .device_err
  2907. @@:
  2908. .noread:
  2909. ; zero uninitialized data if file was extended (because hd_extend_file does not this)
  2910.         push    eax ecx edi
  2911.         xor     eax, eax
  2912.         mov     ecx, 0x200
  2913.         sub     ecx, [esp+8+12]
  2914.         jbe     @f
  2915.         lea     edi, [ebp+FAT.buffer]
  2916.         add     edi, [esp+8+12]
  2917.         rep stosb
  2918. @@:
  2919. ; zero uninitialized data in the last sector
  2920.         mov     ecx, 0x200
  2921.         sub     ecx, esi
  2922.         jbe     @f
  2923.         lea     edi, [ebp+FAT.buffer+esi]
  2924.         rep stosb
  2925. @@:
  2926.         pop     edi ecx
  2927. ; copy new data
  2928.         mov     eax, edx
  2929.         neg     ebx
  2930.         jecxz   @f
  2931.         lea     ebx, [ebp+FAT.buffer+0x200+ebx]
  2932.         call    memmove
  2933.         xor     ebx, ebx
  2934. @@:
  2935.         pop     eax
  2936. ; save sector
  2937.         push    ebx
  2938.         lea     ebx, [ebp+FAT.buffer]
  2939.         call    fs_write32_app
  2940.         pop     ebx
  2941.         test    eax, eax
  2942.         jnz     .device_err2
  2943.         add     edx, ecx
  2944.         sub     [esp], ecx
  2945.         pop     ecx
  2946.         jz      .ret
  2947. .skip:
  2948. ; next sector
  2949.         pop     eax
  2950.         inc     eax
  2951.         push    eax
  2952.         cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2953.         jb      @f
  2954.         and     dword [esp], 0
  2955.         mov     eax, edi
  2956.         call    get_FAT
  2957.         mov     edi, eax
  2958.         jc      .device_err
  2959.         cmp     edi, 2
  2960.         jb      .fat_err
  2961.         cmp     edi, [ebp+FAT.fatRESERVED]
  2962.         jae     .fat_err
  2963. @@:
  2964.         sub     esi, 0x200
  2965.         jae     @f
  2966.         xor     esi, esi
  2967. @@:
  2968.         sub     dword [esp+4], 0x200
  2969.         jae     @f
  2970.         and     dword [esp+4], 0
  2971. @@:
  2972.         jmp     .write_loop
  2973.  
  2974. hd_extend_file.zero_size:
  2975.         xor     eax, eax
  2976.         jmp     hd_extend_file.start_extend
  2977.  
  2978. ; extends file on hd to given size (new data area is undefined)
  2979. ; in: edi->direntry, ecx=new size
  2980. ; out: CF=0 => OK, eax=0
  2981. ;      CF=1 => error, eax=code (ERROR_FS_FAIL or ERROR_DISK_FULL or ERROR_DEVICE)
  2982. hd_extend_file:
  2983.         push    esi
  2984.         mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
  2985.         imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
  2986.         push    ecx
  2987. ; find the last cluster of file
  2988.         mov     eax, [edi+20-2]
  2989.         mov     ax, [edi+26]
  2990.         mov     ecx, [edi+28]
  2991.         jecxz   .zero_size
  2992. .last_loop:
  2993.         sub     ecx, esi
  2994.         jbe     .last_found
  2995.         call    get_FAT
  2996.         jnc     @f
  2997. .device_err:
  2998.         pop     ecx
  2999. .device_err2:
  3000.         pop     esi
  3001.         push    ERROR_DEVICE
  3002. .ret_err:
  3003.         pop     eax
  3004.         stc
  3005.         ret
  3006. @@:
  3007.         cmp     eax, 2
  3008.         jb      .fat_err
  3009.         cmp     eax, [ebp+FAT.fatRESERVED]
  3010.         jb      .last_loop
  3011. .fat_err:
  3012.         pop     ecx esi
  3013.         push    ERROR_FS_FAIL
  3014.         jmp     .ret_err
  3015. .last_found:
  3016.         push    eax
  3017.         call    get_FAT
  3018.         jnc     @f
  3019.         pop     eax
  3020.         jmp     .device_err
  3021. @@:
  3022.         cmp     eax, [ebp+FAT.fatRESERVED]
  3023.         pop     eax
  3024.         jb      .fat_err
  3025. ; set length to full number of clusters
  3026.         sub     [edi+28], ecx
  3027. .start_extend:
  3028.         pop     ecx
  3029. ; now do extend
  3030.         push    edx
  3031.         mov     edx, 2          ; start scan from cluster 2
  3032. .extend_loop:
  3033.         cmp     [edi+28], ecx
  3034.         jae     .extend_done
  3035. ; add new cluster
  3036.         push    eax
  3037.         call    get_free_FAT
  3038.         jc      .disk_full
  3039.         mov     edx, [ebp+FAT.fatEND]
  3040.         call    set_FAT
  3041.         mov     edx, eax
  3042.         pop     eax
  3043.         test    eax, eax
  3044.         jz      .first_cluster
  3045.         push    edx
  3046.         call    set_FAT
  3047.         pop     edx
  3048.         jmp     @f
  3049. .first_cluster:
  3050.         ror     edx, 16
  3051.         mov     [edi+20], dx
  3052.         ror     edx, 16
  3053.         mov     [edi+26], dx
  3054. @@:
  3055.         push    ecx
  3056.         mov     ecx, -1
  3057.         call    add_disk_free_space
  3058.         pop     ecx
  3059.         mov     eax, edx
  3060.         add     [edi+28], esi
  3061.         jmp     .extend_loop
  3062. .extend_done:
  3063.         mov     [edi+28], ecx
  3064.         pop     edx esi
  3065.         xor     eax, eax        ; CF=0
  3066.         ret
  3067. .device_err3:
  3068.         pop     edx
  3069.         jmp     .device_err2
  3070. .disk_full:
  3071.         pop     eax edx esi
  3072.         movi    eax, ERROR_DISK_FULL
  3073.         stc
  3074.         ret
  3075.  
  3076. fat_update_datetime:
  3077.         call    get_time_for_file
  3078.         mov     [edi+22], ax            ; last write time
  3079.         call    get_date_for_file
  3080.         mov     [edi+24], ax            ; last write date
  3081.         mov     [edi+18], ax            ; last access date
  3082.         ret
  3083.  
  3084. ;----------------------------------------------------------------
  3085. fat_SetFileEnd:
  3086.         call    fat_lock
  3087.         push    edi
  3088.         cmp     byte [esi], 0
  3089.         jnz     @f
  3090. .access_denied:
  3091.         push    ERROR_ACCESS_DENIED
  3092. .ret:
  3093.         call    fat_unlock
  3094.         pop     eax
  3095.         pop     edi
  3096.         ret
  3097. @@:
  3098.         call    hd_find_lfn
  3099.         jnc     @f
  3100. .reteax:
  3101.         push    eax
  3102.         jmp     .ret
  3103. @@:
  3104. ; must not be directory
  3105.         test    byte [edi+11], 10h
  3106.         jnz     .access_denied
  3107. ; file size must not exceed 4 Gb
  3108.         cmp     dword [ebx+8], 0
  3109.         jz      @f
  3110.         push    ERROR_END_OF_FILE
  3111.         jmp     .ret
  3112. @@:
  3113.         push    eax     ; save directory sector
  3114. ; set file modification date/time to current
  3115.         call    fat_update_datetime
  3116.         mov     eax, [ebx+4]
  3117.         cmp     eax, [edi+28]
  3118.         jb      .truncate
  3119.         ja      .expand
  3120.         pop     eax
  3121.         lea     ebx, [ebp+FAT.buffer]
  3122.         call    fs_write32_sys
  3123.         test    eax, eax
  3124.         jz      @f
  3125.         push    ERROR_DEVICE
  3126.         jmp     .ret
  3127. @@:
  3128.         push    0
  3129.         jmp     .ret
  3130. .expand:
  3131.         push    ebx ebp ecx
  3132.         push    dword [edi+28]  ; save old size
  3133.         mov     ecx, eax
  3134.         call    hd_extend_file
  3135.         push    eax             ; return code
  3136.         jnc     .expand_ok
  3137.         cmp     al, ERROR_DISK_FULL
  3138.         jz      .disk_full
  3139. .pop_ret:
  3140.         call    update_disk
  3141.         pop     eax ecx ecx ebp ebx ecx
  3142.         jmp     .reteax
  3143. .expand_ok:
  3144. .disk_full:
  3145. ; save directory
  3146.         mov     eax, [edi+28]
  3147.         xchg    eax, [esp+20]
  3148.         lea     ebx, [ebp+FAT.buffer]
  3149.         call    fs_write32_sys
  3150.         test    eax, eax
  3151.         mov     eax, [edi+20-2]
  3152.         mov     ax, [edi+26]
  3153.         mov     edi, eax
  3154.         jz      @f
  3155. .pop_ret11:
  3156.         mov     byte [esp], ERROR_DEVICE
  3157.         jmp     .pop_ret
  3158. @@:
  3159.         test    edi, edi
  3160.         jz      .pop_ret
  3161. ; now zero new data
  3162.         push    0
  3163. ; edi=current cluster, [esp]=sector in cluster
  3164. ; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
  3165. .zero_loop:
  3166.         cmp     edi, 2
  3167.         jb      .error_fat
  3168.         cmp     edi, [ebp+FAT.fatRESERVED]
  3169.         jae     .error_fat
  3170.         sub     dword [esp+8], 0x200
  3171.         jae     .next_cluster
  3172.         lea     eax, [edi-2]
  3173.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  3174.         add     eax, [ebp+FAT.DATA_START]
  3175.         add     eax, [esp]
  3176.         cmp     dword [esp+8], -0x200
  3177.         jz      .noread
  3178.         push    eax
  3179.         lea     ebx, [ebp+FAT.buffer]
  3180.         call    fs_read32_app
  3181.         test    eax, eax
  3182.         pop     eax
  3183.         jnz     .err_next
  3184. .noread:
  3185.         mov     ecx, [esp+8]
  3186.         neg     ecx
  3187.         push    edi
  3188.         lea     edi, [ebp+FAT.buffer+0x200]
  3189.         add     edi, [esp+12]
  3190.         push    eax
  3191.         xor     eax, eax
  3192.         mov     [esp+16], eax
  3193.         rep stosb
  3194.         pop     eax
  3195.         pop     edi
  3196.         call    fs_write32_app
  3197.         test    eax, eax
  3198.         jz      .next_cluster
  3199. .err_next:
  3200.         mov     byte [esp+4], ERROR_DEVICE
  3201. .next_cluster:
  3202.         pop     eax
  3203.         sub     dword [esp+20], 0x200
  3204.         jbe     .pop_ret
  3205.         inc     eax
  3206.         push    eax
  3207.         cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  3208.         jb      .zero_loop
  3209.         and     dword [esp], 0
  3210.         mov     eax, edi
  3211.         call    get_FAT
  3212.         mov     edi, eax
  3213.         jnc     .zero_loop
  3214.         pop     eax
  3215.         jmp     .pop_ret11
  3216. .truncate:
  3217.         mov     [edi+28], eax
  3218.         push    ecx
  3219.         mov     ecx, [edi+20-2]
  3220.         mov     cx, [edi+26]
  3221.         push    eax
  3222.         test    eax, eax
  3223.         jz      .zero_size
  3224. ; find new last cluster
  3225. @@:
  3226.         cmp     ecx, 2
  3227.         jb      .error_fat2
  3228.         cmp     ecx, [ebp+FAT.fatRESERVED]
  3229.         jae     .error_fat2
  3230.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  3231.         shl     eax, 9
  3232.         sub     [esp], eax
  3233.         jbe     @f
  3234.         mov     eax, ecx
  3235.         call    get_FAT
  3236.         mov     ecx, eax
  3237.         jnc     @b
  3238. .device_err3:
  3239.         pop     eax ecx eax edi
  3240.         call    update_disk
  3241.         call    fat_unlock
  3242.         movi    eax, ERROR_DEVICE
  3243.         ret
  3244. @@:
  3245. ; we will zero data at the end of last sector - remember it
  3246.         push    ecx
  3247. ; terminate FAT chain
  3248.         push    edx
  3249.         mov     eax, ecx
  3250.         mov     edx, [ebp+FAT.fatEND]
  3251.         call    set_FAT
  3252.         mov     eax, edx
  3253.         pop     edx
  3254.         jnc     @f
  3255. .device_err4:
  3256.         pop     ecx
  3257.         jmp     .device_err3
  3258. .zero_size:
  3259.         and     word [edi+20], 0
  3260.         and     word [edi+26], 0
  3261.         push    0
  3262.         mov     eax, ecx
  3263. @@:
  3264. ; delete FAT chain
  3265.         call    clear_cluster_chain
  3266.         jc      .device_err4
  3267. ; save directory
  3268.         mov     eax, [esp+12]
  3269.         push    ebx
  3270.         lea     ebx, [ebp+FAT.buffer]
  3271.         call    fs_write32_sys
  3272.         pop     ebx
  3273.         test    eax, eax
  3274.         jnz     .device_err4
  3275. ; zero last sector, ignore errors
  3276.         pop     ecx
  3277.         pop     eax
  3278.         dec     ecx
  3279.         imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  3280.         add     ecx, [ebp+FAT.DATA_START]
  3281.         push    eax
  3282.         sar     eax, 9
  3283.         add     ecx, eax
  3284.         pop     eax
  3285.         and     eax, 0x1FF
  3286.         jz      .truncate_done
  3287.         push    ebx eax
  3288.         mov     eax, ecx
  3289.         lea     ebx, [ebp+FAT.buffer]
  3290.         call    fs_read32_app
  3291.         pop     eax
  3292.         lea     edi, [ebp+FAT.buffer+eax]
  3293.         push    ecx
  3294.         mov     ecx, 0x200
  3295.         sub     ecx, eax
  3296.         xor     eax, eax
  3297.         rep stosb
  3298.         pop     eax
  3299.         call    fs_write32_app
  3300.         pop     ebx
  3301. .truncate_done:
  3302.         pop     ecx eax edi
  3303.         call    update_disk
  3304.         call    fat_unlock
  3305.         xor     eax, eax
  3306.         ret
  3307. .error_fat:
  3308.         pop     eax
  3309.         mov     byte [esp], ERROR_FS_FAIL
  3310.         jmp     .pop_ret
  3311. .error_fat2:
  3312.         pop     eax ecx eax edi
  3313.         call    update_disk
  3314.         call    fat_unlock
  3315.         movi    eax, ERROR_FS_FAIL
  3316.         ret
  3317.  
  3318. ;----------------------------------------------------------------
  3319. fat_GetFileInfo:
  3320.         cmp     byte [esi], 0
  3321.         jnz     @f
  3322.         mov     eax, 2
  3323.         ret
  3324. @@:
  3325.         push    edi
  3326.         call    fat_lock
  3327.         call    hd_find_lfn
  3328.         jc      .error
  3329.         push    ebp
  3330.         xor     ebp, ebp
  3331.         mov     esi, [ebx+16]
  3332.         mov     dword [esi+4], ebp
  3333.         call    fat_entry_to_bdfe2
  3334.         pop     ebp
  3335.         call    fat_unlock
  3336.         xor     eax, eax
  3337.         pop     edi
  3338.         ret
  3339. .error:
  3340.         push    eax
  3341.         call    fat_unlock
  3342.         pop     eax
  3343.         pop     edi
  3344.         ret
  3345.  
  3346. ;----------------------------------------------------------------
  3347. fat_SetFileInfo:
  3348.         cmp     byte [esi], 0
  3349.         jnz     @f
  3350.         mov     eax, 2
  3351.         ret
  3352. @@:
  3353.         push    edi
  3354.         call    fat_lock
  3355.         call    hd_find_lfn
  3356.         jc      .error
  3357.         push    eax
  3358.         mov     edx, [ebx+16]
  3359.         call    bdfe_to_fat_entry
  3360.         pop     eax
  3361.         lea     ebx, [ebp+FAT.buffer]
  3362.         call    fs_write32_sys
  3363.         call    update_disk
  3364.         call    fat_unlock
  3365.         pop     edi
  3366.         xor     eax, eax
  3367.         ret
  3368. .error:
  3369.         push    eax
  3370.         call    fat_unlock
  3371.         pop     eax
  3372.         pop     edi
  3373.         ret
  3374.  
  3375. ;----------------------------------------------------------------
  3376. fat_Delete:
  3377.         call    fat_lock
  3378.         cmp     byte [esi], 0
  3379.         jnz     @f
  3380. ; cannot delete root!
  3381. .access_denied:
  3382.         push    ERROR_ACCESS_DENIED
  3383. .pop_ret:
  3384.         call    fat_unlock
  3385.         pop     eax
  3386.         xor     ebx, ebx
  3387.         ret
  3388. @@:
  3389.         and     [ebp+FAT.longname_sec1], 0
  3390.         and     [ebp+FAT.longname_sec2], 0
  3391.         push    edi
  3392.         call    hd_find_lfn
  3393.         jnc     .found
  3394.         pop     edi
  3395.         push    ERROR_FILE_NOT_FOUND
  3396.         jmp     .pop_ret
  3397. .found:
  3398.         cmp     dword [edi], '.   '
  3399.         jz      .access_denied2
  3400.         cmp     dword [edi], '..  '
  3401.         jz      .access_denied2
  3402.         test    byte [edi+11], 10h
  3403.         jz      .dodel
  3404. ; we can delete only empty folders!
  3405.         pushad
  3406.         mov     esi, [edi+20-2]
  3407.         mov     si, [edi+26]
  3408.         xor     ecx, ecx
  3409.         lea     eax, [esi-2]
  3410.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  3411.         add     eax, [ebp+FAT.DATA_START]
  3412.         lea     ebx, [ebp+FAT.buffer]
  3413.         call    fs_read32_sys
  3414.         test    eax, eax
  3415.         jnz     .err1
  3416.         lea     eax, [ebx+0x200]
  3417.         add     ebx, 2*0x20
  3418. .checkempty:
  3419.         cmp     byte [ebx], 0
  3420.         jz      .empty
  3421.         cmp     byte [ebx], 0xE5
  3422.         jnz     .notempty
  3423.         add     ebx, 0x20
  3424.         cmp     ebx, eax
  3425.         jb      .checkempty
  3426.         inc     ecx
  3427.         cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  3428.         jb      @f
  3429.         mov     eax, esi
  3430.         call    get_FAT
  3431.         jc      .err1
  3432.         cmp     eax, 2
  3433.         jb      .error_fat
  3434.         cmp     eax, [ebp+FAT.fatRESERVED]
  3435.         jae     .empty
  3436.         mov     esi, eax
  3437.         xor     ecx, ecx
  3438. @@:
  3439.         lea     eax, [esi-2]
  3440.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  3441.         add     eax, [ebp+FAT.DATA_START]
  3442.         add     eax, ecx
  3443.         lea     ebx, [ebp+FAT.buffer]
  3444.         call    fs_read32_sys
  3445.         test    eax, eax
  3446.         lea     eax, [ebx+0x200]
  3447.         jz      .checkempty
  3448. .err1:
  3449.         popad
  3450. .err2:
  3451.         pop     edi
  3452.         call    fat_unlock
  3453.         movi    eax, ERROR_DEVICE
  3454.         ret
  3455. .error_fat:
  3456.         popad
  3457.         pop     edi
  3458.         call    fat_unlock
  3459.         movi    eax, ERROR_FS_FAIL
  3460.         ret
  3461. .notempty:
  3462.         popad
  3463. .access_denied2:
  3464.         pop     edi
  3465.         call    fat_unlock
  3466.         movi    eax, ERROR_ACCESS_DENIED
  3467.         ret
  3468. .empty:
  3469.         popad
  3470.         push    eax ebx
  3471.         lea     ebx, [ebp+FAT.buffer]
  3472.         call    fs_read32_sys
  3473.         test    eax, eax
  3474.         pop     ebx eax
  3475.         jnz     .err2
  3476. .dodel:
  3477.         push    eax
  3478.         mov     eax, [edi+20-2]
  3479.         mov     ax, [edi+26]
  3480.         xchg    eax, [esp]
  3481. ; delete folder entry
  3482.         mov     byte [edi], 0xE5
  3483. ; delete LFN (if present)
  3484. .lfndel:
  3485.         lea     edx, [ebp+FAT.buffer]
  3486.         cmp     edi, edx
  3487.         ja      @f
  3488.         cmp     [ebp+FAT.longname_sec2], 0
  3489.         jz      .lfndone
  3490.         push    [ebp+FAT.longname_sec2]
  3491.         push    [ebp+FAT.longname_sec1]
  3492.         pop     [ebp+FAT.longname_sec2]
  3493.         and     [ebp+FAT.longname_sec1], 0
  3494.         push    ebx
  3495.         mov     ebx, edx
  3496.         call    fs_write32_sys
  3497.         mov     eax, [esp+4]
  3498.         call    fs_read32_sys
  3499.         pop     ebx
  3500.         pop     eax
  3501.         lea     edi, [ebp+FAT.buffer+0x200]
  3502. @@:
  3503.         sub     edi, 0x20
  3504.         cmp     byte [edi], 0xE5
  3505.         jz      .lfndone
  3506.         cmp     byte [edi+11], 0xF
  3507.         jnz     .lfndone
  3508.         mov     byte [edi], 0xE5
  3509.         jmp     .lfndel
  3510. .lfndone:
  3511.         push    ebx
  3512.         lea     ebx, [ebp+FAT.buffer]
  3513.         call    fs_write32_sys
  3514.         pop     ebx
  3515. ; delete FAT chain
  3516.         pop     eax
  3517.         call    clear_cluster_chain
  3518.         call    update_disk
  3519.         call    fat_unlock
  3520.         pop     edi
  3521.         xor     eax, eax
  3522.         ret
  3523.