Subversion Repositories Kolibri OS

Rev

Rev 4287 | Rev 5565 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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