Subversion Repositories Kolibri OS

Rev

Rev 3725 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  FAT32.INC                                                      ;;
  7. ;;                                                                 ;;
  8. ;;  FAT16/32 functions for KolibriOS                               ;;
  9. ;;                                                                 ;;
  10. ;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
  11. ;;                                                                 ;;
  12. ;;  See file COPYING for details                                   ;;
  13. ;;  04.02.2007 LFN create folder - diamond                         ;;
  14. ;;  08.10.2006 LFN delete file/folder - diamond                    ;;
  15. ;;  20.08.2006 LFN set file size (truncate/extend) - diamond       ;;
  16. ;;  17.08.2006 LFN write/append to file - diamond                  ;;
  17. ;;  23.06.2006 LFN start application - diamond                     ;;
  18. ;;  15.06.2006 LFN get/set file/folder info - diamond              ;;
  19. ;;  27.05.2006 LFN create/rewrite file - diamond                   ;;
  20. ;;  04.05.2006 LFN read folder - diamond                           ;;
  21. ;;  29.04.2006 Elimination of hangup after the                     ;;
  22. ;;             expiration hd_wait_timeout -  Mario79               ;;
  23. ;;  23.04.2006 LFN read file - diamond                             ;;
  24. ;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
  25. ;;             to MBR, see file part_set.inc - Mario79             ;;
  26. ;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
  27. ;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
  28. ;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
  29. ;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
  30. ;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
  31. ;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
  32. ;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
  33. ;;  08.11.2004 rename - ATV                                        ;;
  34. ;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
  35. ;;  20.10.2004 Makedir/Removedir - ATV                             ;;
  36. ;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
  37. ;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
  38. ;;  24.5.2004  Write back buffer for File_write -VT                ;;
  39. ;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
  40. ;;  30.3.2004  Error parameters at function return - VT            ;;
  41. ;;  01.5.2002  Bugfix in device write - VT                         ;;
  42. ;;  20.5.2002  Hd status check - VT                                ;;
  43. ;;  29.6.2002  Improved fat32 verification - VT                    ;;
  44. ;;                                                                 ;;
  45. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  46.  
  47. $Revision: 3908 $
  48.  
  49.  
  50. cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
  51.  
  52. PUSHAD_EAX equ [esp+28]
  53. PUSHAD_ECX equ [esp+24]
  54. PUSHAD_EDX equ [esp+20]
  55. PUSHAD_EBX equ [esp+16]
  56. PUSHAD_EBP equ [esp+8]
  57. PUSHAD_ESI equ [esp+4]
  58. PUSHAD_EDI equ [esp+0]
  59.  
  60. ; Internal data for every FAT partition.
  61. struct FAT PARTITION
  62. fs_type              db ?
  63. fat16_root           db 0       ; flag for fat16 rootdir
  64. fat_change           db 0       ; 1=fat has changed
  65.                      db ?       ; alignment
  66. Lock                 MUTEX ?    ; currently operations with one partition
  67.                                 ; can not be executed in parallel since the
  68.                                 ; legacy code is not ready; this mutex guards
  69.                                 ; all operations
  70. SECTORS_PER_FAT      dd 0x1f3a
  71. NUMBER_OF_FATS       dd 0x2
  72. SECTORS_PER_CLUSTER  dd 0x8
  73. BYTES_PER_SECTOR     dd 0x200   ; Note: if BPS <> 512 need lots of changes
  74. ROOT_CLUSTER         dd 2       ; first rootdir cluster
  75. FAT_START            dd 0       ; start of fat table
  76. ROOT_START           dd 0       ; start of rootdir (only fat16)
  77. ROOT_SECTORS         dd 0       ; count of rootdir sectors (only fat16)
  78. DATA_START           dd 0       ; start of data area (=first cluster 2)
  79. LAST_CLUSTER         dd 0       ; last availabe cluster
  80. ADR_FSINFO           dd 0       ; used only by fat32
  81.  
  82. fatRESERVED          dd 0x0FFFFFF6
  83. fatBAD               dd 0x0FFFFFF7
  84. fatEND               dd 0x0FFFFFF8
  85. fatMASK              dd 0x0FFFFFFF
  86.  
  87. fatStartScan         dd 2
  88.  
  89. cluster_tmp          dd 0       ; used by analyze_directory
  90.                                 ; and analyze_directory_to_write
  91.  
  92. longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
  93. longname_sec2        dd 0       ; directory sectors for delete long filename
  94.  
  95. fat_in_cache         dd -1
  96.  
  97. fat_cache            rb 512
  98. buffer               rb 512
  99. fsinfo_buffer        rb 512
  100. ends
  101.  
  102. uglobal
  103. align 4
  104. partition_count      dd 0       ; partitions found by set_FAT32_variables
  105.  
  106. hd_error             dd 0       ; set by wait_for_sector_buffer
  107. hd_setup             dd 0
  108. hd_wait_timeout      dd 0
  109.  
  110. cache_search_start   dd 0       ; used by find_empty_slot
  111. endg
  112.  
  113. uglobal
  114. align 4
  115.  Sector512:                      ; label for dev_hdcd.inc
  116.   buffer:
  117.                 times 512 db 0
  118. endg
  119.  
  120. iglobal
  121. align 4
  122. fat_user_functions:
  123.         dd      free
  124.         dd      (fat_user_functions_end - fat_user_functions - 4) / 4
  125.         dd      fat_Read
  126.         dd      fat_ReadFolder
  127.         dd      fat_Rewrite
  128.         dd      fat_Write
  129.         dd      fat_SetFileEnd
  130.         dd      fat_GetFileInfo
  131.         dd      fat_SetFileInfo
  132.         dd      0
  133.         dd      fat_Delete
  134.         dd      fat_CreateFolder
  135. fat_user_functions_end:
  136. endg
  137.  
  138. ; these labels are located before the main function to make
  139. ; most of jumps to these be short
  140. fat_create_partition.free_return0:
  141.         mov     eax, ebp
  142.         call    free
  143.         pop     ebp
  144. fat_create_partition.return0:
  145.         xor     eax, eax
  146.         ret
  147. fat_create_partition:
  148. ; bootsector must have been successfully read
  149.         cmp     dword [esp+4], 0
  150.         jnz     .return0
  151. ; bootsector signature must be correct
  152.         cmp     word [ebx+0x1fe], 0xaa55
  153.         jnz     .return0
  154. ; sectors per cluster must be nonzero
  155.         cmp     byte [ebx+0xd], 0
  156.         jz      .return0
  157. ; bytes per sector must be 0x200
  158.         cmp     word [ebx+0xb], 0x200
  159.         jnz     .return0
  160. ; number of fats must be nonzero
  161.         cmp     byte [ebx+0x10], 0
  162.         jz      .return0
  163. ; The only reason to be invalid partition now is FAT12. Since the test for
  164. ; FAT size requires knowledge of some calculated values, which are also used
  165. ; in the normal operation, let's hope for the best and allocate data now; if
  166. ; it will prove wrong, just deallocate it.
  167.         movi    eax, sizeof.FAT
  168.         call    malloc
  169.         test    eax, eax
  170.         jz      .return0
  171.         mov     ecx, dword [ebp+PARTITION.FirstSector]
  172.         mov     dword [eax+FAT.FirstSector], ecx
  173.         mov     ecx, dword [ebp+PARTITION.FirstSector+4]
  174.         mov     dword [eax+FAT.FirstSector+4], ecx
  175.         mov     ecx, dword [ebp+PARTITION.Length]
  176.         mov     dword [eax+FAT.Length], ecx
  177.         mov     ecx, dword [ebp+PARTITION.Length+4]
  178.         mov     dword [eax+FAT.Length+4], ecx
  179.         mov     ecx, [ebp+PARTITION.Disk]
  180.         mov     [eax+FAT.Disk], ecx
  181.         mov     [eax+FAT.FSUserFunctions], fat_user_functions
  182.         or      [eax+FAT.fat_in_cache], -1
  183.         mov     [eax+FAT.fat_change], 0
  184.         push    ebp
  185.         mov     ebp, eax
  186.  
  187.         lea     ecx, [ebp+FAT.Lock]
  188.         call    mutex_init
  189.  
  190.         movzx   eax, word [ebx+0xe]     ; sectors reserved
  191.         mov     [ebp+FAT.FAT_START], eax
  192.  
  193.         movzx   eax, byte [ebx+0xd]     ; sectors per cluster
  194.         mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
  195.  
  196.         movzx   ecx, word [ebx+0xb]     ; bytes per sector
  197.         mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
  198.  
  199.         movzx   eax, word [ebx+0x11]    ; count of rootdir entries (=0 fat32)
  200.         shl     eax, 5                  ; mul 32
  201.         dec     ecx
  202.         add     eax, ecx                ; round up if not equal count
  203.         inc     ecx                     ; bytes per sector
  204.         xor     edx, edx
  205.         div     ecx
  206.         mov     [ebp+FAT.ROOT_SECTORS], eax     ; count of rootdir sectors
  207.  
  208.         movzx   eax, word [ebx+0x16]    ; sectors per fat <65536
  209.         test    eax, eax
  210.         jnz     @f
  211.         mov     eax, [ebx+0x24]         ; sectors per fat
  212. @@:
  213.         mov     [ebp+FAT.SECTORS_PER_FAT], eax
  214.  
  215.         movzx   eax, byte [ebx+0x10]    ; number of fats
  216.         mov     [ebp+FAT.NUMBER_OF_FATS], eax
  217.         imul    eax, [ebp+FAT.SECTORS_PER_FAT]
  218.         add     eax, [ebp+FAT.FAT_START]
  219.         mov     [ebp+FAT.ROOT_START], eax       ; rootdir = fat_start + fat_size * fat_count
  220.         add     eax, [ebp+FAT.ROOT_SECTORS]     ; rootdir sectors should be 0 on fat32
  221.         mov     [ebp+FAT.DATA_START], eax       ; data area = rootdir + rootdir_size
  222.  
  223.         movzx   eax, word [ebx+0x13]    ; total sector count <65536
  224.         test    eax, eax
  225.         jnz     @f
  226.         mov     eax, [ebx+0x20]         ; total sector count
  227. @@:
  228.         mov     dword [ebp+FAT.Length], eax
  229.         and     dword [ebp+FAT.Length+4], 0
  230.         sub     eax, [ebp+FAT.DATA_START]       ; eax = count of data sectors
  231.         xor     edx, edx
  232.         div     [ebp+FAT.SECTORS_PER_CLUSTER]
  233.         inc     eax
  234.         mov     [ebp+FAT.LAST_CLUSTER], eax
  235.         dec     eax                     ; cluster count
  236.         mov     [ebp+FAT.fatStartScan], 2
  237.  
  238.         ; limits by Microsoft Hardware White Paper v1.03
  239.         cmp     eax, 4085               ; 0xff5
  240.         jb      .free_return0           ; fat12 not supported
  241.         cmp     eax, 65525              ; 0xfff5
  242.         jb      .fat16
  243. .fat32:
  244.         mov     eax, [ebx+0x2c]         ; rootdir cluster
  245.         mov     [ebp+FAT.ROOT_CLUSTER], eax
  246.         movzx   eax, word [ebx+0x30]
  247.         mov     [ebp+FAT.ADR_FSINFO], eax
  248.         push    ebx
  249.         add     ebx, 512
  250.         call    fs_read32_sys
  251.         test    eax, eax
  252.         jnz     @f
  253.         mov     eax, [ebx+0x1ec]
  254.         cmp     eax, -1
  255.         jz      @f
  256.         mov     [ebp+FAT.fatStartScan], eax
  257. @@:
  258.         pop     ebx
  259.         mov     [ebp+FAT.fatRESERVED], 0x0FFFFFF6
  260.         mov     [ebp+FAT.fatBAD], 0x0FFFFFF7
  261.         mov     [ebp+FAT.fatEND], 0x0FFFFFF8
  262.         mov     [ebp+FAT.fatMASK], 0x0FFFFFFF
  263.         mov     al, 32
  264.         mov     [ebp+FAT.fs_type], al
  265.         mov     eax, ebp
  266.         pop     ebp
  267.         ret
  268. .fat16:
  269.         and     [ebp+FAT.ROOT_CLUSTER], 0
  270.         mov     [ebp+FAT.fatRESERVED], 0x0000FFF6
  271.         mov     [ebp+FAT.fatBAD], 0x0000FFF7
  272.         mov     [ebp+FAT.fatEND], 0x0000FFF8
  273.         mov     [ebp+FAT.fatMASK], 0x0000FFFF
  274.         mov     al, 16
  275.         mov     [ebp+FAT.fs_type], al
  276.         mov     eax, ebp
  277.         pop     ebp
  278.         ret
  279.  
  280. set_FAT:
  281. ;--------------------------------
  282. ; input  : EAX = cluster
  283. ;          EDX = value to save
  284. ;          EBP = pointer to FAT structure
  285. ; output : EDX = old value
  286. ;--------------------------------
  287. ; out: CF set <=> error
  288.         push    eax ebx esi
  289.  
  290.         cmp     eax, 2
  291.         jb      sfc_error
  292.         cmp     eax, [ebp+FAT.LAST_CLUSTER]
  293.         ja      sfc_error
  294.         cmp     [ebp+FAT.fs_type], 16
  295.         je      sfc_1
  296.         add     eax, eax
  297.   sfc_1:
  298.         add     eax, eax
  299.         mov     esi, 511
  300.         and     esi, eax        ; esi = position in fat sector
  301.         shr     eax, 9          ; eax = fat sector
  302.         add     eax, [ebp+FAT.FAT_START]
  303.         lea     ebx, [ebp+FAT.fat_cache]
  304.  
  305.         cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
  306.         je      sfc_in_cache    ; yes
  307.  
  308.         cmp     [ebp+FAT.fat_change], 0; is fat changed?
  309.         je      sfc_no_change   ; no
  310.         call    write_fat_sector; yes. write it into disk
  311.         jc      sfc_error
  312.  
  313.   sfc_no_change:
  314.         mov     [ebp+FAT.fat_in_cache], eax; save fat sector
  315.         call    fs_read32_sys
  316.         test    eax, eax
  317.         jne     sfc_error
  318.  
  319.  
  320.   sfc_in_cache:
  321.         cmp     [ebp+FAT.fs_type], 16
  322.         jne     sfc_test32
  323.  
  324.   sfc_set16:
  325.         xchg    [ebx+esi], dx   ; save new value and get old value
  326.         jmp     sfc_write
  327.  
  328.   sfc_test32:
  329.         mov     eax, [ebp+FAT.fatMASK]
  330.  
  331.   sfc_set32:
  332.         and     edx, eax
  333.         xor     eax, -1         ; mask for high bits
  334.         and     eax, [ebx+esi]  ; get high 4 bits
  335.         or      eax, edx
  336.         mov     edx, [ebx+esi]  ; get old value
  337.         mov     [ebx+esi], eax  ; save new value
  338.  
  339.   sfc_write:
  340.         mov     [ebp+FAT.fat_change], 1; fat has changed
  341.  
  342.   sfc_nonzero:
  343.         and     edx, [ebp+FAT.fatMASK]
  344.  
  345.   sfc_return:
  346.         pop     esi ebx eax
  347.         ret
  348.   sfc_error:
  349.         stc
  350.         jmp     sfc_return
  351.  
  352.  
  353. get_FAT:
  354. ;--------------------------------
  355. ; input  : EAX = cluster
  356. ;          EBP = pointer to FAT structure
  357. ; output : EAX = next cluster
  358. ;--------------------------------
  359. ; out: CF set <=> error
  360.         push    ebx esi
  361.  
  362.         cmp     [ebp+FAT.fs_type], 16
  363.         je      gfc_1
  364.         add     eax, eax
  365.   gfc_1:
  366.         add     eax, eax
  367.         mov     esi, 511
  368.         and     esi, eax        ; esi = position in fat sector
  369.         shr     eax, 9          ; eax = fat sector
  370.         add     eax, [ebp+FAT.FAT_START]
  371.         lea     ebx, [ebp+FAT.fat_cache]
  372.  
  373.         cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
  374.         je      gfc_in_cache
  375.  
  376.         cmp     [ebp+FAT.fat_change], 0; is fat changed?
  377.         je      gfc_no_change   ; no
  378.         call    write_fat_sector; yes. write it into disk
  379.         jc      hd_error_01
  380.  
  381.   gfc_no_change:
  382.         mov     [ebp+FAT.fat_in_cache], eax
  383.         call    fs_read32_sys
  384.         test    eax, eax
  385.         jne     hd_error_01
  386.  
  387.   gfc_in_cache:
  388.         mov     eax, [ebx+esi]
  389.         and     eax, [ebp+FAT.fatMASK]
  390.   gfc_return:
  391.         pop     esi ebx
  392.         ret
  393.  hd_error_01:
  394.         stc
  395.         jmp     gfc_return
  396.  
  397.  
  398. get_free_FAT:
  399. ;-----------------------------------------------------------
  400. ; output : if CARRY=0 EAX = # first cluster found free
  401. ;          if CARRY=1 disk full
  402. ; Note   : for more speed need to use fat_cache directly
  403. ;-----------------------------------------------------------
  404.         push    ecx
  405.         mov     ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
  406.         sub     ecx, 2
  407.         mov     eax, [ebp+FAT.fatStartScan]
  408.         cmp     eax, 2
  409.         jb      gff_reset
  410.  
  411.   gff_test:
  412.         cmp     eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
  413.         jbe     gff_in_range
  414.   gff_reset:
  415.         mov     eax, 2
  416.  
  417.   gff_in_range:
  418.         push    eax
  419.         call    get_FAT         ; get cluster state
  420.         jc      gff_not_found_1
  421.  
  422.         test    eax, eax        ; is it free?
  423.         pop     eax
  424.         je      gff_found       ; yes
  425.         inc     eax             ; next cluster
  426.         dec     ecx             ; is all checked?
  427.         jns     gff_test        ; no
  428.  
  429.   gff_not_found:
  430.         pop     ecx             ; yes. disk is full
  431.         stc
  432.         ret
  433.  
  434.   gff_not_found_1:
  435.         pop     eax
  436.         jmp     gff_not_found
  437.  
  438.   gff_found:
  439.         lea     ecx, [eax+1]
  440.         mov     [ebp+FAT.fatStartScan], ecx
  441.         pop     ecx
  442.         clc
  443.         ret
  444.  
  445.  
  446. write_fat_sector:
  447. ;-----------------------------------------------------------
  448. ; write changed fat to disk
  449. ;-----------------------------------------------------------
  450.         push    eax ebx ecx
  451.  
  452.         mov     [ebp+FAT.fat_change], 0
  453.         mov     eax, [ebp+FAT.fat_in_cache]
  454.         cmp     eax, -1
  455.         jz      write_fat_not_used
  456.         lea     ebx, [ebp+FAT.fat_cache]
  457.         mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
  458.  
  459.   write_next_fat:
  460.         push    eax
  461.         call    fs_write32_sys
  462.         test    eax, eax
  463.         pop     eax
  464.         jnz     write_fat_not_used
  465.  
  466.         add     eax, [ebp+FAT.SECTORS_PER_FAT]
  467.         dec     ecx
  468.         jnz     write_next_fat
  469.  
  470.   write_fat_not_used:
  471.         pop     ecx ebx eax
  472.         ret
  473.  
  474.  
  475.  
  476.  
  477.  
  478. bcd2bin:
  479. ;----------------------------------
  480. ; input  : AL=BCD number (eg. 0x11)
  481. ; output : AH=0
  482. ;          AL=decimal number (eg. 11)
  483. ;----------------------------------
  484.         xor     ah, ah
  485.         shl     ax, 4
  486.         shr     al, 4
  487.         aad
  488.         ret
  489.  
  490.  
  491. get_date_for_file:
  492. ;-----------------------------------------------------
  493. ; Get date from CMOS and pack day,month,year in AX
  494. ; DATE   bits  0..4   : day of month 0..31
  495. ;              5..8   : month of year 1..12
  496. ;              9..15  : count of years from 1980
  497. ;-----------------------------------------------------
  498.         mov     al, 0x7 ;day
  499.         out     0x70, al
  500.         in      al, 0x71
  501.         call    bcd2bin
  502.         ror     eax, 5
  503.  
  504.         mov     al, 0x8 ;month
  505.         out     0x70, al
  506.         in      al, 0x71
  507.         call    bcd2bin
  508.         ror     eax, 4
  509.  
  510.         mov     al, 0x9 ;year
  511.         out     0x70, al
  512.         in      al, 0x71
  513.         call    bcd2bin
  514.         add     ax, 20  ;because CMOS return only the two last
  515.                         ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
  516.         rol     eax, 9  ;need the difference with 1980 (eg. 2001-1980)
  517.         ret
  518.  
  519.  
  520. get_time_for_file:
  521. ;-----------------------------------------------------
  522. ; Get time from CMOS and pack hour,minute,second in AX
  523. ; TIME   bits  0..4   : second (the low bit is lost)
  524. ;              5..10  : minute 0..59
  525. ;              11..15 : hour 0..23
  526. ;-----------------------------------------------------
  527.         mov     al, 0x0 ;second
  528.         out     0x70, al
  529.         in      al, 0x71
  530.         call    bcd2bin
  531.         ror     eax, 6
  532.  
  533.         mov     al, 0x2 ;minute
  534.         out     0x70, al
  535.         in      al, 0x71
  536.         call    bcd2bin
  537.         ror     eax, 6
  538.  
  539.         mov     al, 0x4 ;hour
  540.         out     0x70, al
  541.         in      al, 0x71
  542.         call    bcd2bin
  543.         rol     eax, 11
  544.         ret
  545.  
  546.  
  547. set_current_time_for_entry:
  548. ;-----------------------------------------------------
  549. ; Set current time/date for file entry
  550. ; input  : ebx = file entry pointer
  551. ;-----------------------------------------------------
  552.         push    eax
  553.         call    get_time_for_file; update files date/time
  554.         mov     [ebx+22], ax
  555.         call    get_date_for_file
  556.         mov     [ebx+24], ax
  557.         pop     eax
  558.         ret
  559.  
  560.  
  561.  
  562. add_disk_free_space:
  563. ;-----------------------------------------------------
  564. ; input  : ecx = cluster count
  565. ; Note   : negative = remove clusters from free space
  566. ;          positive = add clusters to free space
  567. ;-----------------------------------------------------
  568.         test    ecx, ecx        ; no change
  569.         je      add_dfs_no
  570.         cmp     [ebp+FAT.fs_type], 32  ; free disk space only used by fat32
  571.         jne     add_dfs_no
  572.  
  573.         push    eax ebx
  574.         mov     eax, [ebp+FAT.ADR_FSINFO]
  575.         lea     ebx, [ebp+FAT.fsinfo_buffer]
  576.         call    fs_read32_sys
  577.         test    eax, eax
  578.         jnz     add_not_fs
  579.  
  580.         cmp     dword [ebx+0x1fc], 0xaa550000; check sector id
  581.         jne     add_not_fs
  582.  
  583.         add     [ebx+0x1e8], ecx
  584.         push    [ebp+FAT.fatStartScan]
  585.         pop     dword [ebx+0x1ec]
  586.         mov     eax, [ebp+FAT.ADR_FSINFO]
  587.         call    fs_write32_sys
  588. ;    jc    add_not_fs
  589.  
  590.   add_not_fs:
  591.         pop     ebx eax
  592.  
  593.   add_dfs_no:
  594.         ret
  595.  
  596.  
  597.  
  598. clear_cluster_chain:
  599. ;-----------------------------------------------------
  600. ; input  : eax = first cluster
  601. ;-----------------------------------------------------
  602.         push    eax ecx edx
  603.         xor     ecx, ecx        ; cluster count
  604.  
  605.   clean_new_chain:
  606.         cmp     eax, [ebp+FAT.LAST_CLUSTER]; end of file
  607.         ja      delete_OK
  608.         cmp     eax, 2          ; unfinished fat chain or zero length file
  609.         jb      delete_OK
  610.         cmp     eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
  611.         jz      delete_OK
  612.  
  613.         xor     edx, edx
  614.         call    set_FAT         ; clear fat entry
  615.         jc      access_denied_01
  616.  
  617.         inc     ecx             ; update cluster count
  618.         mov     eax, edx        ; old cluster
  619.         jmp     clean_new_chain
  620.  
  621.   delete_OK:
  622.         call    add_disk_free_space; add clusters to free disk space
  623.         clc
  624.   access_denied_01:
  625.         pop     edx ecx eax
  626.         ret
  627.  
  628.  
  629. if 0
  630. get_hd_info:
  631. ;-----------------------------------------------------------
  632. ; output : eax = 0 - ok
  633. ;                3 - unknown FS
  634. ;               10 - access denied
  635. ;          edx = cluster size in bytes
  636. ;          ebx = total clusters on disk
  637. ;          ecx = free clusters on disk
  638. ;-----------------------------------------------------------
  639.         cmp     [ebp+FAT.fs_type], 16
  640.         jz      info_fat_ok
  641.         cmp     [ebp+FAT.fs_type], 32
  642.         jz      info_fat_ok
  643.         xor     edx, edx
  644.         xor     ebx, ebx
  645.         xor     ecx, ecx
  646.         mov     eax, ERROR_UNKNOWN_FS
  647.         ret
  648.  
  649.   info_fat_ok:
  650. ;    call  reserve_hd1
  651.  
  652.         xor     ecx, ecx        ; count of free clusters
  653.         mov     eax, 2
  654.         mov     ebx, [ebp+FAT.LAST_CLUSTER]
  655.  
  656.   info_cluster:
  657.         push    eax
  658.         call    get_FAT         ; get cluster info
  659.         jc      info_access_denied
  660.  
  661.         test    eax, eax        ; is it free?
  662.         jnz     info_used       ; no
  663.         inc     ecx
  664.  
  665.   info_used:
  666.         pop     eax
  667.         inc     eax
  668.         cmp     eax, ebx        ; is above last cluster?
  669.         jbe     info_cluster    ; no. test next cluster
  670.  
  671.         dec     ebx             ; cluster count
  672.         imul    edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
  673.         xor     eax, eax
  674.         ret
  675.  
  676.   info_access_denied:
  677.         add     esp, 4
  678.         xor     edx, edx
  679.         xor     ebx, ebx
  680.         xor     ecx, ecx
  681.         mov     eax, ERROR_ACCESS_DENIED
  682.         ret
  683. end if
  684.  
  685. update_disk:
  686. ;-----------------------------------------------------------
  687. ; write changed fat and cache to disk
  688. ;-----------------------------------------------------------
  689.         cmp     [ebp+FAT.fat_change], 0 ; is fat changed?
  690.         je      upd_no_change
  691.  
  692.         call    write_fat_sector
  693.         jc      update_disk_acces_denied
  694.  
  695.   upd_no_change:
  696.  
  697.         push    esi
  698.         mov     esi, [ebp+PARTITION.Disk]
  699.         call    disk_sync
  700.         pop     esi
  701.   update_disk_acces_denied:
  702.         ret
  703.  
  704. fat_lock:
  705.         lea     ecx, [ebp+FAT.Lock]
  706.         jmp     mutex_lock
  707. fat_unlock:
  708.         lea     ecx, [ebp+FAT.Lock]
  709.         jmp     mutex_unlock
  710.  
  711. ; \begin{diamond}
  712. hd_find_lfn:
  713. ; in: ebp -> FAT structure
  714. ; in: esi+[esp+4] -> name
  715. ; out: CF=1 - file not found, eax=error code
  716. ;      else CF=0 and edi->direntry, eax=sector
  717. ; destroys eax
  718.         push    esi edi
  719.         push    0
  720.         push    0
  721.         push    fat16_root_first
  722.         push    fat16_root_next
  723.         mov     eax, [ebp+FAT.ROOT_CLUSTER]
  724.         cmp     [ebp+FAT.fs_type], 32
  725.         jz      .fat32
  726. .loop:
  727.         call    fat_find_lfn
  728.         jc      .notfound
  729.         cmp     byte [esi], 0
  730.         jz      .found
  731. .continue:
  732.         test    byte [edi+11], 10h
  733.         jz      .notfound
  734.         and     dword [esp+12], 0
  735.         mov     eax, [edi+20-2]
  736.         mov     ax, [edi+26]    ; cluster
  737. .fat32:
  738.         mov     [esp+8], eax
  739.         mov     dword [esp+4], fat_notroot_first
  740.         mov     dword [esp], fat_notroot_next
  741.         jmp     .loop
  742. .notfound:
  743.         add     esp, 16
  744.         pop     edi esi
  745.         stc
  746.         ret     4
  747. .found:
  748.         lea     eax, [esp+4+24]
  749.         cmp     dword [eax], 0
  750.         jz      @f
  751.         mov     esi, [eax]
  752.         and     dword [eax], 0
  753.         jmp     .continue
  754. @@:
  755.         lea     eax, [esp+8]
  756.         cmp     dword [eax], 0
  757.         jz      .root
  758.         call    fat_get_sector
  759.         jmp     .cmn
  760. .root:
  761.         mov     eax, [eax+4]
  762.         add     eax, [ebp+FAT.ROOT_START]
  763. .cmn:
  764.         add     esp, 20         ; CF=0
  765.         pop     esi
  766.         ret     4
  767.  
  768. ;----------------------------------------------------------------
  769. ; fat_Read - FAT16/32 implementation of reading a file
  770. ; in:  ebp = pointer to FAT structure
  771. ; in:  esi+[esp+4] = name
  772. ; in:  ebx = pointer to parameters from sysfunc 70
  773. ; out: eax, ebx = return values for sysfunc 70
  774. ;----------------------------------------------------------------
  775. fat_Read:
  776.         call    fat_lock
  777.         push    edi
  778.         cmp     byte [esi], 0
  779.         jnz     @f
  780. .noaccess:
  781.         pop     edi
  782. .noaccess_2:
  783.         call    fat_unlock
  784.         or      ebx, -1
  785.         mov     eax, ERROR_ACCESS_DENIED
  786.         ret
  787.  
  788. @@:
  789.         stdcall hd_find_lfn, [esp+4+4]
  790.         jnc     .found
  791.         pop     edi
  792.         push    eax
  793.         call    fat_unlock
  794.         pop     eax
  795.         or      ebx, -1
  796.         ret
  797.  
  798. .found:
  799.         test    byte [edi+11], 0x10; do not allow read directories
  800.         jnz     .noaccess
  801.         cmp     dword [ebx+8], 0
  802.         jz      @f
  803.         xor     ebx, ebx
  804. .reteof:
  805.         call    fat_unlock
  806.         mov     eax, ERROR_END_OF_FILE
  807.         pop     edi
  808.         ret
  809. @@:
  810.         mov     ecx, [ebx+12]   ; size
  811.         mov     edx, [ebx+16]   ; pointer
  812.         mov     ebx, [ebx+4]    ; file offset
  813.         push    edx
  814.         push    0
  815.         mov     eax, [edi+28]
  816.         sub     eax, ebx
  817.         jb      .eof
  818.         cmp     eax, ecx
  819.         jae     @f
  820.         mov     ecx, eax
  821.         mov     byte [esp], 6
  822. @@:
  823.         mov     eax, [edi+20-2]
  824.         mov     ax, [edi+26]
  825. ; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
  826. .new_cluster:
  827.         jecxz   .new_sector
  828.         cmp     eax, 2
  829.         jb      .eof
  830.         cmp     eax, [ebp+FAT.fatRESERVED]
  831.         jae     .eof
  832.         mov     [ebp+FAT.cluster_tmp], eax
  833.         dec     eax
  834.         dec     eax
  835.         mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
  836.         imul    eax, edi
  837.         add     eax, [ebp+FAT.DATA_START]
  838. .new_sector:
  839.         test    ecx, ecx
  840.         jz      .done
  841.         sub     ebx, 512
  842.         jae     .skip
  843.         add     ebx, 512
  844.         jnz     .force_buf
  845.         cmp     ecx, 512
  846.         jb      .force_buf
  847. ; we may read directly to given buffer
  848.         push    eax ebx
  849.         mov     ebx, edx
  850.         call    fs_read32_app
  851.         test    eax, eax
  852.         pop     ebx eax
  853.         jne     .noaccess_1
  854.         add     edx, 512
  855.         sub     ecx, 512
  856.         jmp     .skip
  857. .force_buf:
  858. ; we must read sector to temporary buffer and then copy it to destination
  859.         push    eax ebx
  860.         lea     ebx, [ebp+FAT.buffer]
  861.         call    fs_read32_app
  862.         test    eax, eax
  863.         mov     eax, ebx
  864.         pop     ebx
  865.         jne     .noaccess_3
  866.         add     eax, ebx
  867.         push    ecx
  868.         add     ecx, ebx
  869.         cmp     ecx, 512
  870.         jbe     @f
  871.         mov     ecx, 512
  872. @@:
  873.         sub     ecx, ebx
  874.         mov     ebx, edx
  875.         call    memmove
  876.         add     edx, ecx
  877.         sub     [esp], ecx
  878.         pop     ecx
  879.         pop     eax
  880.         xor     ebx, ebx
  881. .skip:
  882.         inc     eax
  883.         dec     edi
  884.         jnz     .new_sector
  885.         mov     eax, [ebp+FAT.cluster_tmp]
  886.         call    get_FAT
  887.         jc      .noaccess_1
  888.  
  889.         jmp     .new_cluster
  890. .noaccess_3:
  891.         pop     eax
  892. .noaccess_1:
  893.         pop     eax
  894.         push    ERROR_DEVICE
  895. .done:
  896.         mov     ebx, edx
  897.         call    fat_unlock
  898.         pop     eax edx edi
  899.         sub     ebx, edx
  900.         ret
  901. .eof:
  902.         mov     ebx, edx
  903.         pop     eax edx
  904.         sub     ebx, edx
  905.         jmp     .reteof
  906.  
  907. ;----------------------------------------------------------------
  908. ; fat_ReadFolder - FAT16/32 implementation of reading a folder
  909. ; in:  ebp = pointer to FAT structure
  910. ; in:  esi+[esp+4] = name
  911. ; in:  ebx = pointer to parameters from sysfunc 70
  912. ; out: eax, ebx = return values for sysfunc 70
  913. ;----------------------------------------------------------------
  914. fat_ReadFolder:
  915.         call    fat_lock
  916.         mov     eax, [ebp+FAT.ROOT_CLUSTER]
  917.         push    edi
  918.         cmp     byte [esi], 0
  919.         jz      .doit
  920.         stdcall hd_find_lfn, [esp+4+4]
  921.         jnc     .found
  922.         pop     edi
  923.         push    eax
  924.         call    fat_unlock
  925.         pop     eax
  926.         or      ebx, -1
  927.         ret
  928. .found:
  929.         test    byte [edi+11], 0x10     ; do not allow read files
  930.         jnz     .found_dir
  931.         pop     edi
  932.         call    fat_unlock
  933.         or      ebx, -1
  934.         mov     eax, ERROR_ACCESS_DENIED
  935.         ret
  936. .found_dir:
  937.         mov     eax, [edi+20-2]
  938.         mov     ax, [edi+26]    ; eax=cluster
  939. .doit:
  940.         push    esi
  941.         sub     esp, 262*2      ; reserve space for LFN
  942.         push    dword [ebx+8]   ; for fat_get_name: read ANSI/UNICODE name
  943.         mov     edx, [ebx+16]   ; pointer to buffer
  944. ; init header
  945.         push    eax
  946.         mov     edi, edx
  947.         mov     ecx, 32/4
  948.         xor     eax, eax
  949.         rep stosd
  950.         pop     eax
  951.         mov     byte [edx], 1   ; version
  952.         mov     esi, edi        ; esi points to BDFE
  953.         mov     ecx, [ebx+12]   ; number of blocks to read
  954.         mov     ebx, [ebx+4]    ; index of the first block
  955. .new_cluster:
  956.         mov     [ebp+FAT.cluster_tmp], eax
  957.         test    eax, eax
  958.         jnz     @f
  959.         cmp     [ebp+FAT.fs_type], 32
  960.         jz      .notfound
  961.         mov     eax, [ebp+FAT.ROOT_START]
  962.         push    [ebp+FAT.ROOT_SECTORS]
  963.         push    ebx
  964.         jmp     .new_sector
  965. @@:
  966.         dec     eax
  967.         dec     eax
  968.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  969.         push    [ebp+FAT.SECTORS_PER_CLUSTER]
  970.         add     eax, [ebp+FAT.DATA_START]
  971.         push    ebx
  972. .new_sector:
  973.         lea     ebx, [ebp+FAT.buffer]
  974.         mov     edi, ebx
  975.         push    eax
  976.         call    fs_read32_sys
  977.         test    eax, eax
  978.         pop     eax
  979.         jnz     .notfound2
  980.         add     ebx, 512
  981.         push    eax
  982. .l1:
  983.         push    ebp
  984.         lea     ebp, [esp+20]
  985.         call    fat_get_name
  986.         pop     ebp
  987.         jc      .l2
  988.         cmp     byte [edi+11], 0xF
  989.         jnz     .do_bdfe
  990.         add     edi, 0x20
  991.         cmp     edi, ebx
  992.         jb      .do_bdfe
  993.         pop     eax
  994.         inc     eax
  995.         dec     dword [esp+4]
  996.         jnz     @f
  997.         mov     eax, [ebp+FAT.cluster_tmp]
  998.         test    eax, eax
  999.         jz      .done
  1000.         call    get_FAT
  1001.         jc      .notfound2
  1002.         cmp     eax, 2
  1003.         jb      .done
  1004.         cmp     eax, [ebp+FAT.fatRESERVED]
  1005.         jae     .done
  1006.         push    eax
  1007.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1008.         mov     [esp+8], eax
  1009.         pop     eax
  1010.         mov     [ebp+FAT.cluster_tmp], eax
  1011.         dec     eax
  1012.         dec     eax
  1013.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1014.         add     eax, [ebp+FAT.DATA_START]
  1015. @@:
  1016.         lea     ebx, [ebp+FAT.buffer]
  1017.         mov     edi, ebx
  1018.         push    eax
  1019.         call    fs_read32_sys
  1020.         test    eax, eax
  1021.         pop     eax
  1022.         jnz     .notfound2
  1023.         add     ebx, 512
  1024.         push    eax
  1025. .do_bdfe:
  1026.         inc     dword [edx+8]   ; new file found
  1027.         dec     dword [esp+4]
  1028.         jns     .l2
  1029.         dec     ecx
  1030.         js      .l2
  1031.         inc     dword [edx+4]   ; new file block copied
  1032.         push    ebp
  1033.         lea     ebp, [esp+20]
  1034.         call    fat_entry_to_bdfe
  1035.         pop     ebp
  1036. .l2:
  1037.         add     edi, 0x20
  1038.         cmp     edi, ebx
  1039.         jb      .l1
  1040.         pop     eax
  1041.         inc     eax
  1042.         dec     dword [esp+4]
  1043.         jnz     .new_sector
  1044.         mov     eax, [ebp+FAT.cluster_tmp]
  1045.         test    eax, eax
  1046.         jz      .done
  1047.         call    get_FAT
  1048.         jc      .notfound2
  1049.         cmp     eax, 2
  1050.         jb      .done
  1051.         cmp     eax, [ebp+FAT.fatRESERVED]
  1052.         jae     .done
  1053.         push    eax
  1054.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1055.         mov     [esp+8], eax
  1056.         pop     eax
  1057.         pop     ebx
  1058.         add     esp, 4
  1059.         jmp     .new_cluster
  1060. .notfound2:
  1061.         add     esp, 8
  1062. .notfound:
  1063.         add     esp, 262*2+4
  1064.         pop     esi edi
  1065.         mov     ebx, [edx+4]
  1066.         call    fat_unlock
  1067.         mov     eax, ERROR_DEVICE
  1068.         ret
  1069. .done:
  1070.         add     esp, 262*2+4+8
  1071.         mov     ebx, [edx+4]
  1072.         xor     eax, eax
  1073.         dec     ecx
  1074.         js      @f
  1075.         mov     al, ERROR_END_OF_FILE
  1076. @@:
  1077.         push    eax
  1078.         call    fat_unlock
  1079.         pop     eax
  1080.         pop     esi edi
  1081.         ret
  1082.  
  1083. fat16_root_next:
  1084.         push    ecx
  1085.         lea     ecx, [ebp+FAT.buffer+0x200-0x20]
  1086.         cmp     edi, ecx
  1087.         jae     fat16_root_next_sector
  1088.         pop     ecx
  1089.         add     edi, 0x20
  1090.         ret     ; CF=0
  1091. fat16_root_next_sector:
  1092. ; read next sector
  1093.         push    [ebp+FAT.longname_sec2]
  1094.         pop     [ebp+FAT.longname_sec1]
  1095.         mov     ecx, [eax+4]
  1096.         push    ecx
  1097.         add     ecx, [ebp+FAT.ROOT_START]
  1098.         mov     [ebp+FAT.longname_sec2], ecx
  1099.         pop     ecx
  1100.         inc     ecx
  1101.         mov     [eax+4], ecx
  1102.         cmp     ecx, [ebp+FAT.ROOT_SECTORS]
  1103.         pop     ecx
  1104.         jb      fat16_root_first
  1105.         mov     eax, ERROR_FILE_NOT_FOUND
  1106.         stc
  1107.         ret
  1108. fat16_root_first:
  1109.         mov     eax, [eax+4]
  1110.         add     eax, [ebp+FAT.ROOT_START]
  1111.         push    ebx
  1112.         lea     edi, [ebp+FAT.buffer]
  1113.         mov     ebx, edi
  1114.         call    fs_read32_sys
  1115.         pop     ebx
  1116.         test    eax, eax
  1117.         jnz     .readerr
  1118.         ret     ; CF=0
  1119. .readerr:
  1120.         mov     eax, ERROR_DEVICE
  1121.         stc
  1122.         ret
  1123. .notfound:
  1124.         mov     eax, ERROR_FILE_NOT_FOUND
  1125.         stc
  1126.         ret
  1127. fat16_root_begin_write:
  1128.         push    edi eax
  1129.         call    fat16_root_first
  1130.         pop     eax edi
  1131.         ret
  1132. fat16_root_end_write:
  1133.         pusha
  1134.         mov     eax, [eax+4]
  1135.         add     eax, [ebp+FAT.ROOT_START]
  1136.         lea     ebx, [ebp+FAT.buffer]
  1137.         call    fs_write32_sys
  1138.         popa
  1139.         ret
  1140. fat16_root_next_write:
  1141.         push    ecx
  1142.         lea     ecx, [ebp+FAT.buffer+0x200]
  1143.         cmp     edi, ecx
  1144.         jae     @f
  1145.         pop     ecx
  1146.         ret
  1147. @@:
  1148.         call    fat16_root_end_write
  1149.         jmp     fat16_root_next_sector
  1150. fat16_root_extend_dir:
  1151.         stc
  1152.         ret
  1153.  
  1154. fat_notroot_next:
  1155.         push    ecx
  1156.         lea     ecx, [ebp+FAT.buffer+0x200-0x20]
  1157.         cmp     edi, ecx
  1158.         jae     fat_notroot_next_sector
  1159.         pop     ecx
  1160.         add     edi, 0x20
  1161.         ret     ; CF=0
  1162. fat_notroot_next_sector:
  1163.         push    [ebp+FAT.longname_sec2]
  1164.         pop     [ebp+FAT.longname_sec1]
  1165.         push    eax
  1166.         call    fat_get_sector
  1167.         mov     [ebp+FAT.longname_sec2], eax
  1168.         pop     eax
  1169.         mov     ecx, [eax+4]
  1170.         inc     ecx
  1171.         cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1172.         jae     fat_notroot_next_cluster
  1173.         mov     [eax+4], ecx
  1174.         jmp     @f
  1175. fat_notroot_next_cluster:
  1176.         push    eax
  1177.         mov     eax, [eax]
  1178.         call    get_FAT
  1179.         mov     ecx, eax
  1180.         pop     eax
  1181.         jc      fat_notroot_first.deverr
  1182.         cmp     ecx, 2
  1183.         jb      fat_notroot_next_err
  1184.         cmp     ecx, [ebp+FAT.fatRESERVED]
  1185.         jae     fat_notroot_next_err
  1186.         mov     [eax], ecx
  1187.         and     dword [eax+4], 0
  1188. @@:
  1189.         pop     ecx
  1190. fat_notroot_first:
  1191.         call    fat_get_sector
  1192.         push    ebx
  1193.         lea     edi, [ebp+FAT.buffer]
  1194.         mov     ebx, edi
  1195.         call    fs_read32_sys
  1196.         pop     ebx
  1197.         test    eax, eax
  1198.         jz      .ret ; CF=0
  1199.         push    ecx
  1200. .deverr:
  1201.         pop     ecx
  1202.         mov     eax, ERROR_DEVICE
  1203.         stc
  1204. .ret:
  1205.         ret
  1206. fat_notroot_next_err:
  1207.         pop     ecx
  1208.         mov     eax, ERROR_FILE_NOT_FOUND
  1209.         stc
  1210.         ret
  1211. fat_notroot_begin_write:
  1212.         push    eax edi
  1213.         call    fat_notroot_first
  1214.         pop     edi eax
  1215.         ret
  1216. fat_notroot_end_write:
  1217.         call    fat_get_sector
  1218.         push    ebx
  1219.         lea     ebx, [ebp+FAT.buffer]
  1220.         call    fs_write32_sys
  1221.         pop     ebx
  1222.         ret
  1223. fat_notroot_next_write:
  1224.         push    ecx
  1225.         lea     ecx, [ebp+FAT.buffer+0x200]
  1226.         cmp     edi, ecx
  1227.         jae     @f
  1228.         pop     ecx
  1229.         ret
  1230. @@:
  1231.         push    eax
  1232.         call    fat_notroot_end_write
  1233.         pop     eax
  1234.         jmp     fat_notroot_next_sector
  1235. fat_notroot_extend_dir:
  1236.         push    eax
  1237.         call    get_free_FAT
  1238.         jnc     .found
  1239.         pop     eax
  1240.         ret     ; CF=1
  1241. .found:
  1242.         push    edx
  1243.         mov     edx, [ebp+FAT.fatEND]
  1244.         call    set_FAT
  1245.         jc      .writeerr
  1246.         mov     edx, eax
  1247.         mov     eax, [esp+4]
  1248.         mov     eax, [eax]
  1249.         push    edx
  1250.         call    set_FAT
  1251.         pop     edx
  1252.         jnc     @f
  1253. .writeerr:
  1254.         pop     edx
  1255.         pop     eax
  1256.         stc
  1257.         ret
  1258. @@:
  1259.         push    ecx
  1260.         or      ecx, -1
  1261.         call    add_disk_free_space
  1262. ; zero new cluster
  1263.         mov     ecx, 512/4
  1264.         lea     edi, [ebp+FAT.buffer]
  1265.         push    edi
  1266.         xor     eax, eax
  1267.         rep stosd
  1268.         pop     edi
  1269.         pop     ecx
  1270.         mov     eax, [esp+4]
  1271.         mov     [eax], edx
  1272.         and     dword [eax+4], 0
  1273.         pop     edx
  1274.         mov     eax, [eax]
  1275.         dec     eax
  1276.         dec     eax
  1277.         push    ebx ecx
  1278.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1279.         imul    eax, ecx
  1280.         add     eax, [ebp+FAT.DATA_START]
  1281.         mov     ebx, edi
  1282. @@:
  1283.         push    eax
  1284.         call    fs_write32_sys
  1285.         pop     eax
  1286.         inc     eax
  1287.         loop    @b
  1288.         pop     ecx ebx eax
  1289.         clc
  1290.         ret
  1291.  
  1292. fat_get_sector:
  1293.         push    ecx
  1294.         mov     ecx, [eax]
  1295.         dec     ecx
  1296.         dec     ecx
  1297.         imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1298.         add     ecx, [ebp+FAT.DATA_START]
  1299.         add     ecx, [eax+4]
  1300.         mov     eax, ecx
  1301.         pop     ecx
  1302.         ret
  1303.  
  1304. fshrad:
  1305.         call    fat_unlock
  1306.         mov     eax, ERROR_ACCESS_DENIED
  1307.         xor     ebx, ebx
  1308.         ret
  1309.  
  1310. ;----------------------------------------------------------------
  1311. ; fat_CreateFolder - FAT16/32 implementation of creating a folder
  1312. ; in:  ebp = pointer to FAT structure
  1313. ; in:  esi+[esp+4] = name
  1314. ; in:  ebx = pointer to parameters from sysfunc 70
  1315. ; out: eax, ebx = return values for sysfunc 70
  1316. ;----------------------------------------------------------------
  1317. fat_CreateFolder:
  1318.         push    1
  1319.         jmp     fat_Rewrite.common
  1320.  
  1321. ;----------------------------------------------------------------
  1322. ; fat_Rewrite - FAT16/32 implementation of creating a new file
  1323. ; in:  ebp = pointer to FAT structure
  1324. ; in:  esi+[esp+4] = name
  1325. ; in:  ebx = pointer to parameters from sysfunc 70
  1326. ; out: eax, ebx = return values for sysfunc 70
  1327. ;----------------------------------------------------------------
  1328. fat_Rewrite:
  1329.         push    0
  1330. .common:
  1331.         call    fat_lock
  1332.         pop     eax
  1333.         cmp     byte [esi], 0
  1334.         jz      fshrad
  1335.         mov     ecx, [ebx+12]
  1336.         mov     edx, [ebx+16]
  1337.         pushad
  1338.         xor     edi, edi
  1339.         mov     edx, [esp+4+20h]
  1340.         push    esi
  1341.         test    edx, edx
  1342.         jz      @f
  1343.         mov     esi, edx
  1344. @@:
  1345.         lodsb
  1346.         test    al, al
  1347.         jz      @f
  1348.         cmp     al, '/'
  1349.         jnz     @b
  1350.         lea     edi, [esi-1]
  1351.         jmp     @b
  1352. @@:
  1353.         pop     esi
  1354.         test    edi, edi
  1355.         jnz     .noroot
  1356.         test    edx, edx
  1357.         jnz     .hasebp
  1358.         mov     edx, [ebp+FAT.ROOT_CLUSTER]
  1359.         cmp     [ebp+FAT.fs_type], 32
  1360.         jz      .pushnotroot
  1361.         xor     edx, edx
  1362.         push    edx
  1363.         push    fat16_root_extend_dir
  1364.         push    fat16_root_end_write
  1365.         push    fat16_root_next_write
  1366.         push    fat16_root_begin_write
  1367.         push    edx
  1368.         push    edx
  1369.         push    fat16_root_first
  1370.         push    fat16_root_next
  1371.         jmp     .common1
  1372. .hasebp:
  1373.         mov     eax, ERROR_ACCESS_DENIED
  1374.         cmp     byte [edx], 0
  1375.         jz      .ret1
  1376.         stdcall hd_find_lfn, 0
  1377.         mov     esi, [esp+4+20h]
  1378.         jc      .ret1
  1379.         jmp     .common0
  1380. .noroot:
  1381.         mov     eax, ERROR_ACCESS_DENIED
  1382.         cmp     byte [edi+1], 0
  1383.         jz      .ret1
  1384. ; check existence
  1385.         mov     byte [edi], 0
  1386.         push    edi
  1387.         stdcall hd_find_lfn, [esp+4+24h]
  1388.         pop     esi
  1389.         mov     byte [esi], '/'
  1390.         jnc     @f
  1391. .notfound0:
  1392.         mov     eax, ERROR_FILE_NOT_FOUND
  1393. .ret1:
  1394.         mov     [esp+28], eax
  1395.         call    fat_unlock
  1396.         popad
  1397.         xor     ebx, ebx
  1398.         ret
  1399. @@:
  1400.         inc     esi
  1401. .common0:
  1402.         test    byte [edi+11], 0x10     ; must be directory
  1403.         mov     eax, ERROR_ACCESS_DENIED
  1404.         jz      .ret1
  1405.         mov     edx, [edi+20-2]
  1406.         mov     dx, [edi+26]            ; ebp=cluster
  1407.         mov     eax, ERROR_FAT_TABLE
  1408.         cmp     edx, 2
  1409.         jb      .ret1
  1410. .pushnotroot:
  1411.         push    edx
  1412.         push    fat_notroot_extend_dir
  1413.         push    fat_notroot_end_write
  1414.         push    fat_notroot_next_write
  1415.         push    fat_notroot_begin_write
  1416.         push    0
  1417.         push    edx
  1418.         push    fat_notroot_first
  1419.         push    fat_notroot_next
  1420. .common1:
  1421.         call    fat_find_lfn
  1422.         jc      .notfound
  1423. ; found
  1424.         test    byte [edi+11], 10h
  1425.         jz      .exists_file
  1426. ; found directory; if we are creating directory, return OK,
  1427. ;                  if we are creating file, say "access denied"
  1428.         add     esp, 36
  1429.         call    fat_unlock
  1430.         popad
  1431.         test    al, al
  1432.         mov     eax, ERROR_ACCESS_DENIED
  1433.         jz      @f
  1434.         mov     al, 0
  1435. @@:
  1436.         xor     ebx, ebx
  1437.         ret
  1438. .exists_file:
  1439. ; found file; if we are creating directory, return "access denied",
  1440. ;             if we are creating file, delete existing file and continue
  1441.         cmp     byte [esp+36+28], 0
  1442.         jz      @f
  1443.         add     esp, 36
  1444.         call    fat_unlock
  1445.         popad
  1446.         mov     eax, ERROR_ACCESS_DENIED
  1447.         xor     ebx, ebx
  1448.         ret
  1449. @@:
  1450. ; delete FAT chain
  1451.         push    edi
  1452.         xor     eax, eax
  1453.         mov     dword [edi+28], eax     ; zero size
  1454.         xor     ecx, ecx
  1455.         mov     eax, [edi+20-2]
  1456.         mov     ax, [edi+26]
  1457.         mov     word [edi+20], cx
  1458.         mov     word [edi+26], cx
  1459.         test    eax, eax
  1460.         jz      .done1
  1461. @@:
  1462.         cmp     eax, [ebp+FAT.fatRESERVED]
  1463.         jae     .done1
  1464.         push    edx
  1465.         xor     edx, edx
  1466.         call    set_FAT
  1467.         mov     eax, edx
  1468.         pop     edx
  1469.         jc      .done1
  1470.         inc     ecx
  1471.         jmp     @b
  1472. .done1:
  1473.         pop     edi
  1474.         call    get_time_for_file
  1475.         mov     [edi+22], ax
  1476.         call    get_date_for_file
  1477.         mov     [edi+24], ax
  1478.         mov     [edi+18], ax
  1479.         or      byte [edi+11], 20h      ; set 'archive' attribute
  1480.         jmp     .doit
  1481. .notfound:
  1482. ; file is not found; generate short name
  1483.         call    fat_name_is_legal
  1484.         jc      @f
  1485.         add     esp, 36
  1486.         call    fat_unlock
  1487.         popad
  1488.         mov     eax, ERROR_FILE_NOT_FOUND
  1489.         xor     ebx, ebx
  1490.         ret
  1491. @@:
  1492.         sub     esp, 12
  1493.         mov     edi, esp
  1494.         call    fat_gen_short_name
  1495. .test_short_name_loop:
  1496.         push    esi edi ecx
  1497.         mov     esi, edi
  1498.         lea     eax, [esp+12+12+8]
  1499.         mov     edx, [eax+24]
  1500.         mov     [eax], edx
  1501.         and     dword [eax+4], 0
  1502.         call    dword [eax-4]
  1503.         jc      .found
  1504. .test_short_name_entry:
  1505.         cmp     byte [edi+11], 0xF
  1506.         jz      .test_short_name_cont
  1507.         mov     ecx, 11
  1508.         push    esi edi
  1509.         repz cmpsb
  1510.         pop     edi esi
  1511.         jz      .short_name_found
  1512. .test_short_name_cont:
  1513.         lea     eax, [esp+12+12+8]
  1514.         call    dword [eax-8]
  1515.         jnc     .test_short_name_entry
  1516.         jmp     .found
  1517. .short_name_found:
  1518.         pop     ecx edi esi
  1519.         call    fat_next_short_name
  1520.         jnc     .test_short_name_loop
  1521. .disk_full:
  1522.         add     esp, 12+36
  1523.         call    fat_unlock
  1524.         popa
  1525.         mov     eax, ERROR_DISK_FULL
  1526.         xor     ebx, ebx
  1527.         ret
  1528. .found:
  1529.         pop     ecx edi esi
  1530. ; now find space in directory
  1531. ; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
  1532.         mov     al, '~'
  1533.         push    ecx edi
  1534.         mov     ecx, 8
  1535.         repnz scasb
  1536.         movi    eax, 1     ; 1 entry
  1537.         jnz     .notilde
  1538. ; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
  1539.         xor     eax, eax
  1540. @@:
  1541.         cmp     byte [esi], 0
  1542.         jz      @f
  1543.         inc     esi
  1544.         inc     eax
  1545.         jmp     @b
  1546. @@:
  1547.         sub     esi, eax
  1548.         add     eax, 12+13
  1549.         mov     ecx, 13
  1550.         push    edx
  1551.         cdq
  1552.         div     ecx
  1553.         pop     edx
  1554. .notilde:
  1555.         push    -1
  1556.         push    -1
  1557.         push    -1
  1558. ; find <eax> successive entries in directory
  1559.         xor     ecx, ecx
  1560.         push    eax
  1561.         lea     eax, [esp+16+8+12+8]
  1562.         mov     edx, [eax+24]
  1563.         mov     [eax], edx
  1564.         and     dword [eax+4], 0
  1565.         call    dword [eax-4]
  1566.         pop     eax
  1567.         jnc     .scan_dir
  1568. .fsfrfe3:
  1569.         add     esp, 12+8+12+36
  1570.         call    fat_unlock
  1571.         popad
  1572.         mov     eax, ERROR_DEVICE
  1573.         xor     ebx, ebx
  1574.         ret
  1575. .scan_dir:
  1576.         cmp     byte [edi], 0
  1577.         jz      .free
  1578.         cmp     byte [edi], 0xE5
  1579.         jz      .free
  1580.         xor     ecx, ecx
  1581. .scan_cont:
  1582.         push    eax
  1583.         lea     eax, [esp+16+8+12+8]
  1584.         call    dword [eax-8]
  1585.         mov     edx, eax
  1586.         pop     eax
  1587.         jnc     .scan_dir
  1588.         cmp     edx, ERROR_DEVICE
  1589.         jz      .fsfrfe3
  1590.         push    eax
  1591.         lea     eax, [esp+16+8+12+8]
  1592.         call    dword [eax+20]          ; extend directory
  1593.         pop     eax
  1594.         jnc     .scan_dir
  1595.         add     esp, 12+8+12+36
  1596.         call    fat_unlock
  1597.         popad
  1598.         mov     eax, ERROR_DISK_FULL
  1599.         xor     ebx, ebx
  1600.         ret
  1601. .free:
  1602.         test    ecx, ecx
  1603.         jnz     @f
  1604.         mov     [esp], edi
  1605.         mov     ecx, [esp+12+8+12+8]
  1606.         mov     [esp+4], ecx
  1607.         mov     ecx, [esp+12+8+12+12]
  1608.         mov     [esp+8], ecx
  1609.         xor     ecx, ecx
  1610. @@:
  1611.         inc     ecx
  1612.         cmp     ecx, eax
  1613.         jb      .scan_cont
  1614. ; found!
  1615.         push    esi ecx
  1616. ; If creating a directory, allocate one data cluster now and fail immediately
  1617. ; if this is impossible. This prevents from creating an invalid directory entry
  1618. ; on a full disk.
  1619. ; yup, the argument is quite non-intuitive... but what should I do if
  1620. ; the entire function uses such arguments? BTW, it refers to al from pushad,
  1621. ; which in turn is filled with 0 in fat_Rewrite and 1 in fat_CreateFolder.
  1622.         cmp     byte [esp+8+12+8+12+36+28], 0
  1623.         jz      .no.preallocate.folder.data
  1624.         call    get_free_FAT
  1625.         jnc     @f
  1626.         add     esp, 8+12+8
  1627.         jmp     .disk_full
  1628. @@:
  1629.         mov     [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
  1630. .no.preallocate.folder.data:
  1631. ; calculate name checksum
  1632.         mov     esi, [esp+8+12]
  1633.         mov     ecx, 11
  1634.         xor     eax, eax
  1635. @@:
  1636.         ror     al, 1
  1637.         add     al, [esi]
  1638.         inc     esi
  1639.         loop    @b
  1640.         pop     ecx esi
  1641.         pop     edi
  1642.         pop     dword [esp+8+12+12]
  1643.         pop     dword [esp+8+12+12]
  1644. ; edi points to first entry in free chunk
  1645.         dec     ecx
  1646.         jz      .nolfn
  1647.         push    esi
  1648.         push    eax
  1649.         lea     eax, [esp+8+8+12+8]
  1650.         call    dword [eax+8]         ; begin write
  1651.         mov     al, 40h
  1652. .writelfn:
  1653.         or      al, cl
  1654.         mov     esi, [esp+4]
  1655.         push    ecx
  1656.         dec     ecx
  1657.         imul    ecx, 13
  1658.         add     esi, ecx
  1659.         stosb
  1660.         mov     cl, 5
  1661.         call    fs_RamdiskRewrite.read_symbols
  1662.         mov     ax, 0xF
  1663.         stosw
  1664.         mov     al, [esp+4]
  1665.         stosb
  1666.         mov     cl, 6
  1667.         call    fs_RamdiskRewrite.read_symbols
  1668.         xor     eax, eax
  1669.         stosw
  1670.         mov     cl, 2
  1671.         call    fs_RamdiskRewrite.read_symbols
  1672.         pop     ecx
  1673.         lea     eax, [esp+8+8+12+8]
  1674.         call    dword [eax+12]         ; next write
  1675.         xor     eax, eax
  1676.         loop    .writelfn
  1677.         pop     eax
  1678.         pop     esi
  1679. ;        lea     eax, [esp+8+12+8]
  1680. ;        call    dword [eax+16]          ; end write
  1681. .nolfn:
  1682.         xchg    esi, [esp]
  1683.         mov     ecx, 11
  1684.         rep movsb
  1685.         mov     word [edi], 20h         ; attributes
  1686.         sub     edi, 11
  1687.         pop     esi ecx
  1688.         add     esp, 12
  1689.         mov     byte [edi+13], 0        ; tenths of a second at file creation time
  1690.         call    get_time_for_file
  1691.         mov     [edi+14], ax            ; creation time
  1692.         mov     [edi+22], ax            ; last write time
  1693.         call    get_date_for_file
  1694.         mov     [edi+16], ax            ; creation date
  1695.         mov     [edi+24], ax            ; last write date
  1696.         mov     [edi+18], ax            ; last access date
  1697.         xor     ecx, ecx
  1698.         mov     word [edi+20], cx       ; high word of cluster
  1699.         mov     word [edi+26], cx       ; low word of cluster - to be filled
  1700.         mov     dword [edi+28], ecx     ; file size - to be filled
  1701.         cmp     byte [esp+36+28], cl
  1702.         jz      .doit
  1703. ; create directory
  1704.         mov     byte [edi+11], 10h      ; attributes: folder
  1705.         mov     esi, edi
  1706.         lea     eax, [esp+8]
  1707.         call    dword [eax+16]  ; flush directory
  1708.         mov     eax, [esp+36+20] ; extract saved cluster
  1709.         mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
  1710.         push    ecx
  1711.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1712.         shl     ecx, 9
  1713.         push    ecx
  1714.         push    edi
  1715.         jmp     .doit2
  1716. .doit:
  1717.         mov     esi, [esp+36+20]
  1718.         lea     eax, [esp+8]
  1719.         call    dword [eax+16]  ; flush directory
  1720.         push    ecx
  1721.         mov     ecx, [esp+4+36+24]
  1722.         push    ecx
  1723.         push    edi
  1724.         test    ecx, ecx
  1725.         jz      .done
  1726.         call    get_free_FAT
  1727.         jc      .diskfull
  1728. .doit2:
  1729.         push    eax
  1730.         mov     [edi+26], ax
  1731.         shr     eax, 16
  1732.         mov     [edi+20], ax
  1733.         lea     eax, [esp+16+8]
  1734.         call    dword [eax+16]  ; flush directory
  1735.         pop     eax
  1736.         push    edx
  1737.         mov     edx, [ebp+FAT.fatEND]
  1738.         call    set_FAT
  1739.         pop     edx
  1740. .write_cluster:
  1741.         push    eax
  1742.         dec     eax
  1743.         dec     eax
  1744.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1745.         add     eax, [ebp+FAT.DATA_START]
  1746.         push    [ebp+FAT.SECTORS_PER_CLUSTER]
  1747. ; write data
  1748. .write_sector:
  1749.         cmp     byte [esp+20+36+28], 0
  1750.         jnz     .writedir
  1751.         mov     ecx, 512
  1752.         cmp     dword [esp+12], ecx
  1753.         jb      .writeshort
  1754. ; we can write directly from given buffer
  1755.         mov     ebx, esi
  1756.         add     esi, ecx
  1757.         jmp     .writecommon
  1758. .writeshort:
  1759.         mov     ecx, [esp+12]
  1760.         push    ecx
  1761.         lea     edi, [ebp+FAT.buffer]
  1762.         mov     ebx, edi
  1763.         rep movsb
  1764. .writedircont:
  1765.         lea     ecx, [ebp+FAT.buffer+0x200]
  1766.         sub     ecx, edi
  1767.         push    eax
  1768.         xor     eax, eax
  1769.         rep stosb
  1770.         pop     eax
  1771.         pop     ecx
  1772. .writecommon:
  1773.         push    eax
  1774.         call    fs_write32_app
  1775.         test    eax, eax
  1776.         pop     eax
  1777.         jnz     .writeerr
  1778.         inc     eax
  1779.         sub     dword [esp+12], ecx
  1780.         jz      .writedone
  1781.         dec     dword [esp]
  1782.         jnz     .write_sector
  1783.         pop     eax
  1784. ; allocate new cluster
  1785.         pop     eax
  1786.         mov     ecx, eax
  1787.         call    get_free_FAT
  1788.         jc      .diskfull
  1789.         push    edx
  1790.         mov     edx, [ebp+FAT.fatEND]
  1791.         call    set_FAT
  1792.         xchg    eax, ecx
  1793.         mov     edx, ecx
  1794.         call    set_FAT
  1795.         pop     edx
  1796.         xchg    eax, ecx
  1797.         jmp     .write_cluster
  1798. .diskfull:
  1799.         mov     eax, ERROR_DISK_FULL
  1800.         jmp     .ret
  1801. .writeerr:
  1802.         pop     eax eax
  1803.         sub     esi, ecx
  1804.         mov     eax, ERROR_DEVICE
  1805.         jmp     .ret
  1806. .writedone:
  1807.         pop     eax eax
  1808. .done:
  1809.         xor     eax, eax
  1810. .ret:
  1811.         pop     edi ecx
  1812.         sub     esi, [esp+4+36+20]
  1813.         mov     [esp+4+36+28], eax
  1814.         mov     [esp+4+36+16], esi
  1815.         lea     eax, [esp+12]
  1816.         call    dword [eax+8]
  1817.         mov     [edi+28], esi
  1818.         call    dword [eax+16]
  1819.         mov     [esp+36+16], ebx
  1820.         lea     eax, [esi+511]
  1821.         shr     eax, 9
  1822.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1823.         lea     eax, [eax+ecx-1]
  1824.         xor     edx, edx
  1825.         div     ecx
  1826.         pop     ecx
  1827.         sub     ecx, eax
  1828.         call    add_disk_free_space
  1829.         add     esp, 36
  1830.         call    update_disk
  1831.         call    fat_unlock
  1832.         popad
  1833.         ret
  1834. .writedir:
  1835.         push    512
  1836.         lea     edi, [ebp+FAT.buffer]
  1837.         mov     ebx, edi
  1838.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1839.         shl     ecx, 9
  1840.         cmp     ecx, [esp+16]
  1841.         jnz     .writedircont
  1842.         dec     dword [esp+20]
  1843.         push    esi
  1844.         mov     ecx, 32/4
  1845.         rep movsd
  1846.         pop     esi
  1847.         mov     dword [edi-32], '.   '
  1848.         mov     dword [edi-32+4], '    '
  1849.         mov     dword [edi-32+8], '    '
  1850.         mov     byte [edi-32+11], 10h
  1851.         push    esi
  1852.         mov     ecx, 32/4
  1853.         rep movsd
  1854.         pop     esi
  1855.         mov     dword [edi-32], '..  '
  1856.         mov     dword [edi-32+4], '    '
  1857.         mov     dword [edi-32+8], '    '
  1858.         mov     byte [edi-32+11], 10h
  1859.         mov     ecx, [esp+20+36]
  1860.         cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
  1861.         jnz     @f
  1862.         xor     ecx, ecx
  1863. @@:
  1864.         mov     word [edi-32+26], cx
  1865.         shr     ecx, 16
  1866.         mov     [edi-32+20], cx
  1867.         jmp     .writedircont
  1868.  
  1869. fat_Write.access_denied:
  1870.         push    ERROR_ACCESS_DENIED
  1871. fat_Write.ret0:
  1872.         pop     eax
  1873.         xor     ebx, ebx
  1874.         ret
  1875.  
  1876. fat_Write.ret11:
  1877.         push    ERROR_DEVICE
  1878.         jmp     fat_Write.ret0
  1879.  
  1880. ;----------------------------------------------------------------
  1881. ; fat_Write - FAT16/32 implementation of writing to file
  1882. ; in:  ebp = pointer to FAT structure
  1883. ; in:  esi+[esp+4] = name
  1884. ; in:  ebx = pointer to parameters from sysfunc 70
  1885. ; out: eax, ebx = return values for sysfunc 70
  1886. ;----------------------------------------------------------------
  1887. fat_Write:
  1888.         cmp     byte [esi], 0
  1889.         jz      .access_denied
  1890.         call    fat_lock
  1891.         push    edi
  1892.         stdcall hd_find_lfn, [esp+4+4]
  1893.         jnc     .found
  1894.         pop     edi
  1895.         push    eax
  1896.         call    fat_unlock
  1897.         jmp     .ret0
  1898. .found:
  1899. ; FAT does not support files larger than 4GB
  1900.         cmp     dword [ebx+8], 0
  1901.         jz      @f
  1902. .eof:
  1903.         pop     edi
  1904.         push    ERROR_END_OF_FILE
  1905.         call    fat_unlock
  1906.         jmp     .ret0
  1907. @@:
  1908.         mov     ecx, [ebx+12]
  1909.         mov     edx, [ebx+16]
  1910.         mov     ebx, [ebx+4]
  1911. ; now edi points to direntry, ebx=start byte to write,
  1912. ; ecx=number of bytes to write, edx=data pointer
  1913.  
  1914. ; extend file if needed
  1915.         add     ecx, ebx
  1916.         jc      .eof    ; FAT does not support files larger than 4GB
  1917.         push    edx
  1918.         push    eax     ; save directory sector
  1919.         push    0       ; return value=0
  1920.  
  1921.         call    get_time_for_file
  1922.         mov     [edi+22], ax            ; last write time
  1923.         call    get_date_for_file
  1924.         mov     [edi+24], ax            ; last write date
  1925.         mov     [edi+18], ax            ; last access date
  1926.  
  1927.         push    dword [edi+28]          ; save current file size
  1928.         cmp     ecx, [edi+28]
  1929.         jbe     .length_ok
  1930.         cmp     ecx, ebx
  1931.         jz      .length_ok
  1932.         call    hd_extend_file
  1933.         jnc     .length_ok
  1934.         mov     [esp+4], eax
  1935. ; hd_extend_file can return three error codes: FAT table error, device error or disk full.
  1936. ; First two cases are fatal errors, in third case we may write some data
  1937.         cmp     al, ERROR_DISK_FULL
  1938.         jz      .disk_full
  1939.         call    fat_unlock
  1940.         pop     eax
  1941.         pop     eax
  1942.         pop     ecx
  1943.         pop     edx
  1944.         pop     edi
  1945.         xor     ebx, ebx
  1946.         ret
  1947. .disk_full:
  1948. ; correct number of bytes to write
  1949.         mov     ecx, [edi+28]
  1950.         cmp     ecx, ebx
  1951.         ja      .length_ok
  1952.         push    0
  1953. .ret:
  1954.         pop     eax
  1955.         sub     edx, [esp+12]
  1956.         mov     ebx, edx        ; ebx=number of written bytes
  1957.         call    update_disk
  1958.         test    eax, eax
  1959.         jz      @f
  1960.         mov     byte [esp+4], ERROR_DEVICE
  1961. @@:
  1962.         call    fat_unlock
  1963.         pop     eax
  1964.         pop     eax
  1965.         pop     ecx
  1966.         pop     edx
  1967.         pop     edi
  1968.         ret
  1969. .length_ok:
  1970.         mov     esi, [edi+28]
  1971.         mov     eax, [edi+20-2]
  1972.         mov     ax, [edi+26]
  1973.         mov     edi, eax        ; edi=current cluster
  1974.         push    0               ; current sector in cluster
  1975. ; save directory
  1976.         mov     eax, [esp+12]
  1977.         push    ebx
  1978.         lea     ebx, [ebp+FAT.buffer]
  1979.         call    fs_write32_sys
  1980.         pop     ebx
  1981.         test    eax, eax
  1982.         jz      @f
  1983. .device_err:
  1984.         mov     byte [esp+8], ERROR_DEVICE
  1985.         jmp     .ret
  1986. .fat_err:
  1987.         mov     byte [esp+8], ERROR_FAT_TABLE
  1988.         jmp     .ret
  1989. @@:
  1990.  
  1991. ; now ebx=start pos, ecx=end pos, both lie inside file
  1992.         sub     ecx, ebx
  1993.         jz      .ret
  1994. .write_loop:
  1995. ; skip unmodified sectors
  1996.         cmp     dword [esp+4], 0x200
  1997.         jb      .modify
  1998.         sub     ebx, 0x200
  1999.         jae     .skip
  2000.         add     ebx, 0x200
  2001. .modify:
  2002. ; get length of data in current sector
  2003.         push    ecx
  2004.         sub     ebx, 0x200
  2005.         jb      .hasdata
  2006.         neg     ebx
  2007.         xor     ecx, ecx
  2008.         jmp     @f
  2009. .hasdata:
  2010.         neg     ebx
  2011.         cmp     ecx, ebx
  2012.         jbe     @f
  2013.         mov     ecx, ebx
  2014. @@:
  2015. ; get current sector number
  2016.         mov     eax, edi
  2017.         dec     eax
  2018.         dec     eax
  2019.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2020.         add     eax, [ebp+FAT.DATA_START]
  2021.         add     eax, [esp+4]
  2022. ; load sector if needed
  2023.         cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
  2024.         jz      .noread
  2025.         cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
  2026.         jz      .noread
  2027.         cmp     ecx, esi        ; (same for the last sector)
  2028.         jz      .noread
  2029.         push    eax ebx
  2030.         lea     ebx, [ebp+FAT.buffer]
  2031.         call    fs_read32_app
  2032.         test    eax, eax
  2033.         pop     ebx eax
  2034.         jz      @f
  2035. .device_err2:
  2036.         pop     ecx
  2037.         jmp     .device_err
  2038. @@:
  2039. .noread:
  2040. ; zero uninitialized data if file was extended (because hd_extend_file does not this)
  2041.         push    eax ecx edi
  2042.         xor     eax, eax
  2043.         mov     ecx, 0x200
  2044.         sub     ecx, [esp+8+12]
  2045.         jbe     @f
  2046.         lea     edi, [ebp+FAT.buffer]
  2047.         add     edi, [esp+8+12]
  2048.         rep stosb
  2049. @@:
  2050. ; zero uninitialized data in the last sector
  2051.         mov     ecx, 0x200
  2052.         sub     ecx, esi
  2053.         jbe     @f
  2054.         lea     edi, [ebp+FAT.buffer+esi]
  2055.         rep stosb
  2056. @@:
  2057.         pop     edi ecx
  2058. ; copy new data
  2059.         mov     eax, edx
  2060.         neg     ebx
  2061.         jecxz   @f
  2062.         lea     ebx, [ebp+FAT.buffer+0x200+ebx]
  2063.         call    memmove
  2064.         xor     ebx, ebx
  2065. @@:
  2066.         pop     eax
  2067. ; save sector
  2068.         push    ebx
  2069.         lea     ebx, [ebp+FAT.buffer]
  2070.         call    fs_write32_app
  2071.         pop     ebx
  2072.         test    eax, eax
  2073.         jnz     .device_err2
  2074.         add     edx, ecx
  2075.         sub     [esp], ecx
  2076.         pop     ecx
  2077.         jz      .ret
  2078. .skip:
  2079. ; next sector
  2080.         pop     eax
  2081.         inc     eax
  2082.         push    eax
  2083.         cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2084.         jb      @f
  2085.         and     dword [esp], 0
  2086.         mov     eax, edi
  2087.         call    get_FAT
  2088.         mov     edi, eax
  2089.         jc      .device_err
  2090.         cmp     edi, 2
  2091.         jb      .fat_err
  2092.         cmp     edi, [ebp+FAT.fatRESERVED]
  2093.         jae     .fat_err
  2094. @@:
  2095.         sub     esi, 0x200
  2096.         jae     @f
  2097.         xor     esi, esi
  2098. @@:
  2099.         sub     dword [esp+4], 0x200
  2100.         jae     @f
  2101.         and     dword [esp+4], 0
  2102. @@:
  2103.         jmp     .write_loop
  2104.  
  2105. hd_extend_file.zero_size:
  2106.         xor     eax, eax
  2107.         jmp     hd_extend_file.start_extend
  2108.  
  2109. ; extends file on hd to given size (new data area is undefined)
  2110. ; in: edi->direntry, ecx=new size
  2111. ; out: CF=0 => OK, eax=0
  2112. ;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
  2113. hd_extend_file:
  2114.         push    esi
  2115.         mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
  2116.         imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
  2117.         push    ecx
  2118. ; find the last cluster of file
  2119.         mov     eax, [edi+20-2]
  2120.         mov     ax, [edi+26]
  2121.         mov     ecx, [edi+28]
  2122.         jecxz   .zero_size
  2123. .last_loop:
  2124.         sub     ecx, esi
  2125.         jbe     .last_found
  2126.         call    get_FAT
  2127.         jnc     @f
  2128. .device_err:
  2129.         pop     ecx
  2130. .device_err2:
  2131.         pop     esi
  2132.         push    ERROR_DEVICE
  2133. .ret_err:
  2134.         pop     eax
  2135.         stc
  2136.         ret
  2137. @@:
  2138.         cmp     eax, 2
  2139.         jb      .fat_err
  2140.         cmp     eax, [ebp+FAT.fatRESERVED]
  2141.         jb      .last_loop
  2142. .fat_err:
  2143.         pop     ecx esi
  2144.         push    ERROR_FAT_TABLE
  2145.         jmp     .ret_err
  2146. .last_found:
  2147.         push    eax
  2148.         call    get_FAT
  2149.         jnc     @f
  2150.         pop     eax
  2151.         jmp     .device_err
  2152. @@:
  2153.         cmp     eax, [ebp+FAT.fatRESERVED]
  2154.         pop     eax
  2155.         jb      .fat_err
  2156. ; set length to full number of clusters
  2157.         sub     [edi+28], ecx
  2158. .start_extend:
  2159.         pop     ecx
  2160. ; now do extend
  2161.         push    edx
  2162.         mov     edx, 2          ; start scan from cluster 2
  2163. .extend_loop:
  2164.         cmp     [edi+28], ecx
  2165.         jae     .extend_done
  2166. ; add new cluster
  2167.         push    eax
  2168.         call    get_free_FAT
  2169.         jc      .disk_full
  2170.         mov     edx, [ebp+FAT.fatEND]
  2171.         call    set_FAT
  2172.         mov     edx, eax
  2173.         pop     eax
  2174.         test    eax, eax
  2175.         jz      .first_cluster
  2176.         push    edx
  2177.         call    set_FAT
  2178.         pop     edx
  2179.         jmp     @f
  2180. .first_cluster:
  2181.         ror     edx, 16
  2182.         mov     [edi+20], dx
  2183.         ror     edx, 16
  2184.         mov     [edi+26], dx
  2185. @@:
  2186.         push    ecx
  2187.         mov     ecx, -1
  2188.         call    add_disk_free_space
  2189.         pop     ecx
  2190.         mov     eax, edx
  2191.         add     [edi+28], esi
  2192.         jmp     .extend_loop
  2193. .extend_done:
  2194.         mov     [edi+28], ecx
  2195.         pop     edx esi
  2196.         xor     eax, eax        ; CF=0
  2197.         ret
  2198. .device_err3:
  2199.         pop     edx
  2200.         jmp     .device_err2
  2201. .disk_full:
  2202.         pop     eax edx esi
  2203.         movi    eax, ERROR_DISK_FULL
  2204.         stc
  2205.         ret
  2206.  
  2207. ;----------------------------------------------------------------
  2208. ; fat_SetFileEnd - FAT16/32 implementation of setting end-of-file
  2209. ; in:  ebp = pointer to FAT structure
  2210. ; in:  esi+[esp+4] = name
  2211. ; in:  ebx = pointer to parameters from sysfunc 70
  2212. ; out: eax, ebx = return values for sysfunc 70
  2213. ;----------------------------------------------------------------
  2214. fat_SetFileEnd:
  2215.         call    fat_lock
  2216.         push    edi
  2217.         cmp     byte [esi], 0
  2218.         jnz     @f
  2219. .access_denied:
  2220.         push    ERROR_ACCESS_DENIED
  2221. .ret:
  2222.         call    fat_unlock
  2223.         pop     eax
  2224.         pop     edi
  2225.         ret
  2226. @@:
  2227.         stdcall hd_find_lfn, [esp+4+4]
  2228.         jnc     @f
  2229. .reteax:
  2230.         push    eax
  2231.         jmp     .ret
  2232. @@:
  2233. ; must not be directory
  2234.         test    byte [edi+11], 10h
  2235.         jnz     .access_denied
  2236. ; file size must not exceed 4 Gb
  2237.         cmp     dword [ebx+8], 0
  2238.         jz      @f
  2239.         push    ERROR_END_OF_FILE
  2240.         jmp     .ret
  2241. @@:
  2242.         push    eax     ; save directory sector
  2243. ; set file modification date/time to current
  2244.         call    fat_update_datetime
  2245.         mov     eax, [ebx+4]
  2246.         cmp     eax, [edi+28]
  2247.         jb      .truncate
  2248.         ja      .expand
  2249.         pop     eax
  2250.         lea     ebx, [ebp+FAT.buffer]
  2251.         call    fs_write32_sys
  2252.         test    eax, eax
  2253.         jz      @f
  2254.         push    ERROR_DEVICE
  2255.         jmp     .ret
  2256. @@:
  2257.         push    0
  2258.         jmp     .ret
  2259. .expand:
  2260.         push    ebx ebp ecx
  2261.         push    dword [edi+28]  ; save old size
  2262.         mov     ecx, eax
  2263.         call    hd_extend_file
  2264.         push    eax             ; return code
  2265.         jnc     .expand_ok
  2266.         cmp     al, ERROR_DISK_FULL
  2267.         jz      .disk_full
  2268. .pop_ret:
  2269.         call    update_disk
  2270.         pop     eax ecx ecx ebp ebx ecx
  2271.         jmp     .reteax
  2272. .expand_ok:
  2273. .disk_full:
  2274. ; save directory
  2275.         mov     eax, [edi+28]
  2276.         xchg    eax, [esp+20]
  2277.         lea     ebx, [ebp+FAT.buffer]
  2278.         call    fs_write32_sys
  2279.         test    eax, eax
  2280.         mov     eax, [edi+20-2]
  2281.         mov     ax, [edi+26]
  2282.         mov     edi, eax
  2283.         jz      @f
  2284. .pop_ret11:
  2285.         mov     byte [esp], ERROR_DEVICE
  2286.         jmp     .pop_ret
  2287. @@:
  2288.         test    edi, edi
  2289.         jz      .pop_ret
  2290. ; now zero new data
  2291.         push    0
  2292. ; edi=current cluster, [esp]=sector in cluster
  2293. ; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
  2294. .zero_loop:
  2295.         cmp     edi, 2
  2296.         jb      .error_fat
  2297.         cmp     edi, [ebp+FAT.fatRESERVED]
  2298.         jae     .error_fat
  2299.         sub     dword [esp+8], 0x200
  2300.         jae     .next_cluster
  2301.         lea     eax, [edi-2]
  2302.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2303.         add     eax, [ebp+FAT.DATA_START]
  2304.         add     eax, [esp]
  2305.         cmp     dword [esp+8], -0x200
  2306.         jz      .noread
  2307.         push    eax
  2308.         lea     ebx, [ebp+FAT.buffer]
  2309.         call    fs_read32_app
  2310.         test    eax, eax
  2311.         pop     eax
  2312.         jnz     .err_next
  2313. .noread:
  2314.         mov     ecx, [esp+8]
  2315.         neg     ecx
  2316.         push    edi
  2317.         lea     edi, [ebp+FAT.buffer+0x200]
  2318.         add     edi, [esp+12]
  2319.         push    eax
  2320.         xor     eax, eax
  2321.         mov     [esp+16], eax
  2322.         rep stosb
  2323.         pop     eax
  2324.         pop     edi
  2325.         call    fs_write32_app
  2326.         test    eax, eax
  2327.         jz      .next_cluster
  2328. .err_next:
  2329.         mov     byte [esp+4], ERROR_DEVICE
  2330. .next_cluster:
  2331.         pop     eax
  2332.         sub     dword [esp+20], 0x200
  2333.         jbe     .pop_ret
  2334.         inc     eax
  2335.         push    eax
  2336.         cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2337.         jb      .zero_loop
  2338.         and     dword [esp], 0
  2339.         mov     eax, edi
  2340.         call    get_FAT
  2341.         mov     edi, eax
  2342.         jnc     .zero_loop
  2343.         pop     eax
  2344.         jmp     .pop_ret11
  2345. .truncate:
  2346.         mov     [edi+28], eax
  2347.         push    ecx
  2348.         mov     ecx, [edi+20-2]
  2349.         mov     cx, [edi+26]
  2350.         push    eax
  2351.         test    eax, eax
  2352.         jz      .zero_size
  2353. ; find new last cluster
  2354. @@:
  2355.         cmp     ecx, 2
  2356.         jb      .error_fat2
  2357.         cmp     ecx, [ebp+FAT.fatRESERVED]
  2358.         jae     .error_fat2
  2359.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2360.         shl     eax, 9
  2361.         sub     [esp], eax
  2362.         jbe     @f
  2363.         mov     eax, ecx
  2364.         call    get_FAT
  2365.         mov     ecx, eax
  2366.         jnc     @b
  2367. .device_err3:
  2368.         pop     eax ecx eax edi
  2369.         call    update_disk
  2370.         call    fat_unlock
  2371.         movi    eax, ERROR_DEVICE
  2372.         ret
  2373. @@:
  2374. ; we will zero data at the end of last sector - remember it
  2375.         push    ecx
  2376. ; terminate FAT chain
  2377.         push    edx
  2378.         mov     eax, ecx
  2379.         mov     edx, [ebp+FAT.fatEND]
  2380.         call    set_FAT
  2381.         mov     eax, edx
  2382.         pop     edx
  2383.         jnc     @f
  2384. .device_err4:
  2385.         pop     ecx
  2386.         jmp     .device_err3
  2387. .zero_size:
  2388.         and     word [edi+20], 0
  2389.         and     word [edi+26], 0
  2390.         push    0
  2391.         mov     eax, ecx
  2392. @@:
  2393. ; delete FAT chain
  2394.         call    clear_cluster_chain
  2395.         jc      .device_err4
  2396. ; save directory
  2397.         mov     eax, [esp+12]
  2398.         push    ebx
  2399.         lea     ebx, [ebp+FAT.buffer]
  2400.         call    fs_write32_sys
  2401.         pop     ebx
  2402.         test    eax, eax
  2403.         jnz     .device_err4
  2404. ; zero last sector, ignore errors
  2405.         pop     ecx
  2406.         pop     eax
  2407.         dec     ecx
  2408.         imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2409.         add     ecx, [ebp+FAT.DATA_START]
  2410.         push    eax
  2411.         sar     eax, 9
  2412.         add     ecx, eax
  2413.         pop     eax
  2414.         and     eax, 0x1FF
  2415.         jz      .truncate_done
  2416.         push    ebx eax
  2417.         mov     eax, ecx
  2418.         lea     ebx, [ebp+FAT.buffer]
  2419.         call    fs_read32_app
  2420.         pop     eax
  2421.         lea     edi, [ebp+FAT.buffer+eax]
  2422.         push    ecx
  2423.         mov     ecx, 0x200
  2424.         sub     ecx, eax
  2425.         xor     eax, eax
  2426.         rep stosb
  2427.         pop     eax
  2428.         call    fs_write32_app
  2429.         pop     ebx
  2430. .truncate_done:
  2431.         pop     ecx eax edi
  2432.         call    update_disk
  2433.         call    fat_unlock
  2434.         xor     eax, eax
  2435.         ret
  2436. .error_fat:
  2437.         pop     eax
  2438.         mov     byte [esp], ERROR_FAT_TABLE
  2439.         jmp     .pop_ret
  2440. .error_fat2:
  2441.         pop     eax ecx eax edi
  2442.         call    update_disk
  2443.         call    fat_unlock
  2444.         movi    eax, ERROR_FAT_TABLE
  2445.         ret
  2446.  
  2447. ;----------------------------------------------------------------
  2448. ; fat_GetFileInfo - FAT16/32 implementation of getting file info
  2449. ; in:  ebp = pointer to FAT structure
  2450. ; in:  esi+[esp+4] = name
  2451. ; in:  ebx = pointer to parameters from sysfunc 70
  2452. ; out: eax, ebx = return values for sysfunc 70
  2453. ;----------------------------------------------------------------
  2454. fat_GetFileInfo:
  2455.         cmp     byte [esi], 0
  2456.         jnz     @f
  2457.         mov     eax, 2
  2458.         ret
  2459. @@:
  2460.         push    edi
  2461.         call    fat_lock
  2462.         stdcall hd_find_lfn, [esp+4+4]
  2463.         jc      .error
  2464.         push    ebp
  2465.         xor     ebp, ebp
  2466.         mov     esi, [ebx+16]
  2467.         mov     dword [esi+4], ebp
  2468.         call    fat_entry_to_bdfe2
  2469.         pop     ebp
  2470.         call    fat_unlock
  2471.         xor     eax, eax
  2472.         pop     edi
  2473.         ret
  2474. .error:
  2475.         push    eax
  2476.         call    fat_unlock
  2477.         pop     eax
  2478.         pop     edi
  2479.         ret
  2480.  
  2481. ;----------------------------------------------------------------
  2482. ; fat_SetFileInfo - FAT16/32 implementation of setting file info
  2483. ; in:  ebp = pointer to FAT structure
  2484. ; in:  esi+[esp+4] = name
  2485. ; in:  ebx = pointer to parameters from sysfunc 70
  2486. ; out: eax, ebx = return values for sysfunc 70
  2487. ;----------------------------------------------------------------
  2488. fat_SetFileInfo:
  2489.         cmp     byte [esi], 0
  2490.         jnz     @f
  2491.         mov     eax, 2
  2492.         ret
  2493. @@:
  2494.         push    edi
  2495.         call    fat_lock
  2496.         stdcall hd_find_lfn, [esp+4+4]
  2497.         jc      .error
  2498.         push    eax
  2499.         mov     edx, [ebx+16]
  2500.         call    bdfe_to_fat_entry
  2501.         pop     eax
  2502.         lea     ebx, [ebp+FAT.buffer]
  2503.         call    fs_write32_sys
  2504.         call    update_disk
  2505.         call    fat_unlock
  2506.         pop     edi
  2507.         xor     eax, eax
  2508.         ret
  2509. .error:
  2510.         push    eax
  2511.         call    fat_unlock
  2512.         pop     eax
  2513.         pop     edi
  2514.         ret
  2515.  
  2516. ;----------------------------------------------------------------
  2517. ; fat_Delete - FAT16/32 implementation of deleting a file/folder
  2518. ; in:  ebp = pointer to FAT structure
  2519. ; in:  esi+[esp+4] = name
  2520. ; in:  ebx = pointer to parameters from sysfunc 70
  2521. ; out: eax, ebx = return values for sysfunc 70
  2522. ;----------------------------------------------------------------
  2523. fat_Delete:
  2524.         call    fat_lock
  2525.         cmp     byte [esi], 0
  2526.         jnz     @f
  2527. ; cannot delete root!
  2528. .access_denied:
  2529.         push    ERROR_ACCESS_DENIED
  2530. .pop_ret:
  2531.         call    fat_unlock
  2532.         pop     eax
  2533.         xor     ebx, ebx
  2534.         ret
  2535. @@:
  2536.         and     [ebp+FAT.longname_sec1], 0
  2537.         and     [ebp+FAT.longname_sec2], 0
  2538.         push    edi
  2539.         stdcall hd_find_lfn, [esp+4+4]
  2540.         jnc     .found
  2541.         pop     edi
  2542.         push    ERROR_FILE_NOT_FOUND
  2543.         jmp     .pop_ret
  2544. .found:
  2545.         cmp     dword [edi], '.   '
  2546.         jz      .access_denied2
  2547.         cmp     dword [edi], '..  '
  2548.         jz      .access_denied2
  2549.         test    byte [edi+11], 10h
  2550.         jz      .dodel
  2551. ; we can delete only empty folders!
  2552.         pushad
  2553.         mov     esi, [edi+20-2]
  2554.         mov     si, [edi+26]
  2555.         xor     ecx, ecx
  2556.         lea     eax, [esi-2]
  2557.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2558.         add     eax, [ebp+FAT.DATA_START]
  2559.         lea     ebx, [ebp+FAT.buffer]
  2560.         call    fs_read32_sys
  2561.         test    eax, eax
  2562.         jnz     .err1
  2563.         lea     eax, [ebx+0x200]
  2564.         add     ebx, 2*0x20
  2565. .checkempty:
  2566.         cmp     byte [ebx], 0
  2567.         jz      .empty
  2568.         cmp     byte [ebx], 0xE5
  2569.         jnz     .notempty
  2570.         add     ebx, 0x20
  2571.         cmp     ebx, eax
  2572.         jb      .checkempty
  2573.         inc     ecx
  2574.         cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2575.         jb      @f
  2576.         mov     eax, esi
  2577.         call    get_FAT
  2578.         jc      .err1
  2579.         cmp     eax, 2
  2580.         jb      .error_fat
  2581.         cmp     eax, [ebp+FAT.fatRESERVED]
  2582.         jae     .empty
  2583.         mov     esi, eax
  2584.         xor     ecx, ecx
  2585. @@:
  2586.         lea     eax, [esi-2]
  2587.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2588.         add     eax, [ebp+FAT.DATA_START]
  2589.         add     eax, ecx
  2590.         lea     ebx, [ebp+FAT.buffer]
  2591.         call    fs_read32_sys
  2592.         test    eax, eax
  2593.         lea     eax, [ebx+0x200]
  2594.         jz      .checkempty
  2595. .err1:
  2596.         popad
  2597. .err2:
  2598.         pop     edi
  2599.         call    fat_unlock
  2600.         movi    eax, ERROR_DEVICE
  2601.         ret
  2602. .error_fat:
  2603.         popad
  2604.         pop     edi
  2605.         call    fat_unlock
  2606.         movi    eax, ERROR_FAT_TABLE
  2607.         ret
  2608. .notempty:
  2609.         popad
  2610. .access_denied2:
  2611.         pop     edi
  2612.         call    fat_unlock
  2613.         movi    eax, ERROR_ACCESS_DENIED
  2614.         ret
  2615. .empty:
  2616.         popad
  2617.         push    eax ebx
  2618.         lea     ebx, [ebp+FAT.buffer]
  2619.         call    fs_read32_sys
  2620.         test    eax, eax
  2621.         pop     ebx eax
  2622.         jnz     .err2
  2623. .dodel:
  2624.         push    eax
  2625.         mov     eax, [edi+20-2]
  2626.         mov     ax, [edi+26]
  2627.         xchg    eax, [esp]
  2628. ; delete folder entry
  2629.         mov     byte [edi], 0xE5
  2630. ; delete LFN (if present)
  2631. .lfndel:
  2632.         lea     edx, [ebp+FAT.buffer]
  2633.         cmp     edi, edx
  2634.         ja      @f
  2635.         cmp     [ebp+FAT.longname_sec2], 0
  2636.         jz      .lfndone
  2637.         push    [ebp+FAT.longname_sec2]
  2638.         push    [ebp+FAT.longname_sec1]
  2639.         pop     [ebp+FAT.longname_sec2]
  2640.         and     [ebp+FAT.longname_sec1], 0
  2641.         push    ebx
  2642.         mov     ebx, edx
  2643.         call    fs_write32_sys
  2644.         mov     eax, [esp+4]
  2645.         call    fs_read32_sys
  2646.         pop     ebx
  2647.         pop     eax
  2648.         lea     edi, [ebp+FAT.buffer+0x200]
  2649. @@:
  2650.         sub     edi, 0x20
  2651.         cmp     byte [edi], 0xE5
  2652.         jz      .lfndone
  2653.         cmp     byte [edi+11], 0xF
  2654.         jnz     .lfndone
  2655.         mov     byte [edi], 0xE5
  2656.         jmp     .lfndel
  2657. .lfndone:
  2658.         push    ebx
  2659.         lea     ebx, [ebp+FAT.buffer]
  2660.         call    fs_write32_sys
  2661.         pop     ebx
  2662. ; delete FAT chain
  2663.         pop     eax
  2664.         call    clear_cluster_chain
  2665.         call    update_disk
  2666.         call    fat_unlock
  2667.         pop     edi
  2668.         xor     eax, eax
  2669.         ret
  2670.  
  2671. ; \end{diamond}
  2672.