Subversion Repositories Kolibri OS

Rev

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