2273 lines
40 KiB
PHP
2273 lines
40 KiB
PHP
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|||
|
;; ;;
|
|||
|
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
|
|||
|
;; Distributed under terms of the GNU General Public License ;;
|
|||
|
;; ;;
|
|||
|
;; RAMDISK functions ;;
|
|||
|
;; (C) 2004 Ville Turjanmaa, License: GPL ;;
|
|||
|
;; Addings by M.Lisovin ;;
|
|||
|
;; LFN support by diamond ;;
|
|||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|||
|
|
|||
|
$Revision$
|
|||
|
|
|||
|
|
|||
|
; calculate fat chain
|
|||
|
|
|||
|
calculatefatchain:
|
|||
|
|
|||
|
pushad
|
|||
|
|
|||
|
mov esi,RAMDISK+512
|
|||
|
mov edi,RAMDISK_FAT
|
|||
|
|
|||
|
fcnew:
|
|||
|
mov eax,dword [esi]
|
|||
|
mov ebx,dword [esi+4]
|
|||
|
mov ecx,dword [esi+8]
|
|||
|
mov edx,ecx
|
|||
|
shr edx,4 ;8 ok
|
|||
|
shr dx,4 ;7 ok
|
|||
|
xor ch,ch
|
|||
|
shld ecx,ebx,20 ;6 ok
|
|||
|
shr cx,4 ;5 ok
|
|||
|
shld ebx,eax,12
|
|||
|
and ebx,0x0fffffff ;4 ok
|
|||
|
shr bx,4 ;3 ok
|
|||
|
shl eax,4
|
|||
|
and eax,0x0fffffff ;2 ok
|
|||
|
shr ax,4 ;1 ok
|
|||
|
mov dword [edi],eax
|
|||
|
mov dword [edi+4],ebx
|
|||
|
mov dword [edi+8],ecx
|
|||
|
mov dword [edi+12],edx
|
|||
|
add edi,16
|
|||
|
add esi,12
|
|||
|
|
|||
|
cmp edi,RAMDISK_FAT+2856*2 ;2849 clusters
|
|||
|
jnz fcnew
|
|||
|
|
|||
|
popad
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
restorefatchain: ; restore fat chain
|
|||
|
|
|||
|
pushad
|
|||
|
|
|||
|
mov esi,RAMDISK_FAT
|
|||
|
mov edi,RAMDISK+512
|
|||
|
|
|||
|
fcnew2:
|
|||
|
mov eax,dword [esi]
|
|||
|
mov ebx,dword [esi+4]
|
|||
|
shl ax,4
|
|||
|
shl eax,4
|
|||
|
shl bx,4
|
|||
|
shr ebx,4
|
|||
|
shrd eax,ebx,8
|
|||
|
shr ebx,8
|
|||
|
mov dword [edi],eax
|
|||
|
mov word [edi+4],bx
|
|||
|
add edi,6
|
|||
|
add esi,8
|
|||
|
|
|||
|
cmp edi,RAMDISK+512+4278 ;4274 bytes - all used FAT
|
|||
|
jb fcnew2
|
|||
|
|
|||
|
mov esi,RAMDISK+512 ; duplicate fat chain
|
|||
|
mov edi,RAMDISK+512+0x1200
|
|||
|
mov ecx,1069 ;4274/4
|
|||
|
cld
|
|||
|
rep movsd
|
|||
|
|
|||
|
popad
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
ramdisk_free_space:
|
|||
|
;---------------------------------------------
|
|||
|
;
|
|||
|
; returns free space in edi
|
|||
|
; rewr.by Mihasik
|
|||
|
;---------------------------------------------
|
|||
|
|
|||
|
push eax ebx ecx
|
|||
|
|
|||
|
mov edi,RAMDISK_FAT ;start of FAT
|
|||
|
xor ax,ax ;Free cluster=0x0000 in FAT
|
|||
|
xor ebx,ebx ;counter
|
|||
|
mov ecx,2849 ;2849 clusters
|
|||
|
cld
|
|||
|
rdfs1:
|
|||
|
repne scasw
|
|||
|
jnz rdfs2 ;if last cluster not 0
|
|||
|
inc ebx
|
|||
|
test ecx, ecx
|
|||
|
jnz rdfs1
|
|||
|
rdfs2:
|
|||
|
shl ebx,9 ;free clusters*512
|
|||
|
mov edi,ebx
|
|||
|
|
|||
|
pop ecx ebx eax
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
expand_filename:
|
|||
|
;---------------------------------------------
|
|||
|
;
|
|||
|
; exapand filename with '.' to 11 character
|
|||
|
; eax - pointer to filename
|
|||
|
;---------------------------------------------
|
|||
|
|
|||
|
push esi edi ebx
|
|||
|
|
|||
|
mov edi,esp ; check for '.' in the name
|
|||
|
add edi,12+8
|
|||
|
|
|||
|
mov esi,eax
|
|||
|
|
|||
|
mov eax,edi
|
|||
|
mov [eax+0],dword ' '
|
|||
|
mov [eax+4],dword ' '
|
|||
|
mov [eax+8],dword ' '
|
|||
|
|
|||
|
flr1:
|
|||
|
|
|||
|
cmp [esi],byte '.'
|
|||
|
jne flr2
|
|||
|
mov edi,eax
|
|||
|
add edi,7
|
|||
|
jmp flr3
|
|||
|
|
|||
|
flr2:
|
|||
|
|
|||
|
mov bl,[esi]
|
|||
|
mov [edi],bl
|
|||
|
|
|||
|
flr3:
|
|||
|
|
|||
|
inc esi
|
|||
|
inc edi
|
|||
|
|
|||
|
mov ebx,eax
|
|||
|
add ebx,11
|
|||
|
|
|||
|
cmp edi,ebx
|
|||
|
jbe flr1
|
|||
|
|
|||
|
pop ebx edi esi
|
|||
|
ret
|
|||
|
|
|||
|
fileread:
|
|||
|
;----------------------------------------------------------------
|
|||
|
;
|
|||
|
; fileread - sys floppy
|
|||
|
;
|
|||
|
; eax points to filename 11 chars
|
|||
|
; ebx first wanted block ; 1+ ; if 0 then set to 1
|
|||
|
; ecx number of blocks to read ; 1+ ; if 0 then set to 1
|
|||
|
; edx mem location to return data
|
|||
|
; esi length of filename 12*X 0=root
|
|||
|
;
|
|||
|
; ret ebx = size or 0xffffffff file not found
|
|||
|
; eax = 0 ok read or other = errormsg
|
|||
|
;
|
|||
|
;--------------------------------------------------------------
|
|||
|
test ebx,ebx ;if ebx=0 - set to 1
|
|||
|
jnz frfl5
|
|||
|
inc ebx
|
|||
|
frfl5:
|
|||
|
test ecx,ecx ;if ecx=0 - set to 1
|
|||
|
jnz frfl6
|
|||
|
inc ecx
|
|||
|
frfl6:
|
|||
|
test esi,esi ; return ramdisk root
|
|||
|
jnz fr_noroot ;if not root
|
|||
|
cmp ebx,14 ;14 clusters=root dir
|
|||
|
ja oorr
|
|||
|
cmp ecx,14
|
|||
|
ja oorr
|
|||
|
jmp fr_do
|
|||
|
oorr:
|
|||
|
mov eax,5 ;out of root range (fnf)
|
|||
|
xor ebx,ebx
|
|||
|
dec ebx ;0xffffffff
|
|||
|
ret
|
|||
|
|
|||
|
fr_do: ;reading rootdir
|
|||
|
mov edi,edx
|
|||
|
dec ebx
|
|||
|
push edx
|
|||
|
mov edx,ecx
|
|||
|
add edx,ebx
|
|||
|
cmp edx,15 ;ebx+ecx=14+1
|
|||
|
pushf
|
|||
|
jbe fr_do1
|
|||
|
sub edx,14
|
|||
|
sub ecx,edx
|
|||
|
fr_do1:
|
|||
|
shl ebx,9
|
|||
|
mov esi,RAMDISK+512*19
|
|||
|
add esi,ebx
|
|||
|
shl ecx,7
|
|||
|
cld
|
|||
|
rep movsd
|
|||
|
popf
|
|||
|
pop edx
|
|||
|
jae fr_do2
|
|||
|
xor eax,eax ; ok read
|
|||
|
xor ebx,ebx
|
|||
|
ret
|
|||
|
fr_do2: ;if last cluster
|
|||
|
mov eax,6 ;end of file
|
|||
|
xor ebx,ebx
|
|||
|
ret
|
|||
|
|
|||
|
fr_noroot:
|
|||
|
|
|||
|
sub esp,32
|
|||
|
call expand_filename
|
|||
|
|
|||
|
dec ebx
|
|||
|
|
|||
|
push eax
|
|||
|
|
|||
|
push eax ebx ecx edx esi edi
|
|||
|
call rd_findfile
|
|||
|
je fifound
|
|||
|
add esp,32+28 ;if file not found
|
|||
|
ret
|
|||
|
|
|||
|
fifound:
|
|||
|
|
|||
|
mov ebx,[edi-11+28] ;file size
|
|||
|
mov [esp+20],ebx
|
|||
|
mov [esp+24],ebx
|
|||
|
add edi,0xf
|
|||
|
movzx eax,word [edi]
|
|||
|
mov edi,eax ;edi=cluster
|
|||
|
|
|||
|
frnew:
|
|||
|
|
|||
|
add eax,31 ;bootsector+2*fat+filenames
|
|||
|
shl eax,9 ;*512
|
|||
|
add eax,RAMDISK ;image base
|
|||
|
mov ebx,[esp+8]
|
|||
|
mov ecx,512 ;[esp+4]
|
|||
|
|
|||
|
cmp [esp+16],dword 0 ; wanted cluster ?
|
|||
|
jne frfl7
|
|||
|
call memmove
|
|||
|
add [esp+8],dword 512
|
|||
|
dec dword [esp+12] ; last wanted cluster ?
|
|||
|
je frnoread
|
|||
|
jmp frfl8
|
|||
|
frfl7:
|
|||
|
dec dword [esp+16]
|
|||
|
frfl8:
|
|||
|
movzx eax,word [edi*2+RAMDISK_FAT] ; find next cluster from FAT
|
|||
|
mov edi,eax
|
|||
|
cmp edi,4095 ;eof - cluster
|
|||
|
jz frnoread2
|
|||
|
|
|||
|
cmp [esp+24],dword 512 ;eof - size
|
|||
|
jb frnoread
|
|||
|
sub [esp+24],dword 512
|
|||
|
|
|||
|
jmp frnew
|
|||
|
|
|||
|
frnoread2:
|
|||
|
|
|||
|
cmp [esp+16],dword 0 ; eof without read ?
|
|||
|
je frnoread
|
|||
|
|
|||
|
pop edi esi edx ecx
|
|||
|
add esp,4
|
|||
|
pop ebx ; ebx <- eax : size of file
|
|||
|
add esp,36
|
|||
|
mov eax,6 ; end of file
|
|||
|
ret
|
|||
|
|
|||
|
frnoread:
|
|||
|
|
|||
|
pop edi esi edx ecx
|
|||
|
add esp,4
|
|||
|
pop ebx ; ebx <- eax : size of file
|
|||
|
add esp,36
|
|||
|
xor eax,eax ;read ok
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
rd_findfile:
|
|||
|
;by Mihasik
|
|||
|
;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
|
|||
|
|
|||
|
mov edi,RAMDISK+512*18+512 ;Point at directory
|
|||
|
cld
|
|||
|
rd_newsearch:
|
|||
|
mov esi,eax
|
|||
|
mov ecx,11
|
|||
|
rep cmpsb
|
|||
|
je rd_ff
|
|||
|
add cl,21
|
|||
|
add edi,ecx
|
|||
|
cmp edi,RAMDISK+512*33
|
|||
|
jb rd_newsearch
|
|||
|
mov eax,5 ;if file not found - eax=5
|
|||
|
xor ebx,ebx
|
|||
|
dec ebx ;ebx=0xffffffff and zf=0
|
|||
|
rd_ff:
|
|||
|
ret
|
|||
|
|
|||
|
; \begin{diamond}
|
|||
|
|
|||
|
uni2ansi_str:
|
|||
|
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
|
|||
|
; in: esi->source, edi->buffer (may be esi=edi)
|
|||
|
; destroys: eax,esi,edi
|
|||
|
lodsw
|
|||
|
test ax, ax
|
|||
|
jz .done
|
|||
|
cmp ax, 0x80
|
|||
|
jb .ascii
|
|||
|
cmp ax, 0x401
|
|||
|
jz .yo1
|
|||
|
cmp ax, 0x451
|
|||
|
jz .yo2
|
|||
|
cmp ax, 0x410
|
|||
|
jb .unk
|
|||
|
cmp ax, 0x440
|
|||
|
jb .rus1
|
|||
|
cmp ax, 0x450
|
|||
|
jb .rus2
|
|||
|
.unk:
|
|||
|
mov al, '_'
|
|||
|
jmp .doit
|
|||
|
.yo1:
|
|||
|
mov al, '<27>'
|
|||
|
jmp .doit
|
|||
|
.yo2:
|
|||
|
mov al, '<27>'
|
|||
|
jmp .doit
|
|||
|
.rus1:
|
|||
|
; 0x410-0x43F -> 0x80-0xAF
|
|||
|
add al, 0x70
|
|||
|
jmp .doit
|
|||
|
.rus2:
|
|||
|
; 0x440-0x44F -> 0xE0-0xEF
|
|||
|
add al, 0xA0
|
|||
|
.ascii:
|
|||
|
.doit:
|
|||
|
stosb
|
|||
|
jmp uni2ansi_str
|
|||
|
.done:
|
|||
|
mov byte [edi], 0
|
|||
|
ret
|
|||
|
|
|||
|
ansi2uni_char:
|
|||
|
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
|
|||
|
mov ah, 0
|
|||
|
; 0x00-0x7F - trivial map
|
|||
|
cmp al, 0x80
|
|||
|
jb .ret
|
|||
|
; 0x80-0xAF -> 0x410-0x43F
|
|||
|
cmp al, 0xB0
|
|||
|
jae @f
|
|||
|
add ax, 0x410-0x80
|
|||
|
.ret:
|
|||
|
ret
|
|||
|
@@:
|
|||
|
; 0xE0-0xEF -> 0x440-0x44F
|
|||
|
cmp al, 0xE0
|
|||
|
jb .unk
|
|||
|
cmp al, 0xF0
|
|||
|
jae @f
|
|||
|
add ax, 0x440-0xE0
|
|||
|
ret
|
|||
|
; 0xF0 -> 0x401
|
|||
|
; 0xF1 -> 0x451
|
|||
|
@@:
|
|||
|
cmp al, '<27>'
|
|||
|
jz .yo1
|
|||
|
cmp al, '<27>'
|
|||
|
jz .yo2
|
|||
|
.unk:
|
|||
|
mov al, '_' ; ah=0
|
|||
|
ret
|
|||
|
.yo1:
|
|||
|
mov ax, 0x401
|
|||
|
ret
|
|||
|
.yo2:
|
|||
|
mov ax, 0x451
|
|||
|
ret
|
|||
|
|
|||
|
char_toupper:
|
|||
|
; convert character to uppercase, using cp866 encoding
|
|||
|
; in: al=symbol
|
|||
|
; out: al=converted symbol
|
|||
|
cmp al, 'a'
|
|||
|
jb .ret
|
|||
|
cmp al, 'z'
|
|||
|
jbe .az
|
|||
|
cmp al, '<27>'
|
|||
|
jz .yo1
|
|||
|
cmp al, '<27>'
|
|||
|
jb .ret
|
|||
|
cmp al, '<27>'
|
|||
|
jb .rus1
|
|||
|
cmp al, '<27>'
|
|||
|
ja .ret
|
|||
|
; 0xE0-0xEF -> 0x90-0x9F
|
|||
|
sub al, '<27>'-'<27>'
|
|||
|
.ret:
|
|||
|
ret
|
|||
|
.rus1:
|
|||
|
; 0xA0-0xAF -> 0x80-0x8F
|
|||
|
.az:
|
|||
|
and al, not 0x20
|
|||
|
ret
|
|||
|
.yo1:
|
|||
|
; 0xF1 -> 0xF0
|
|||
|
dec ax
|
|||
|
ret
|
|||
|
|
|||
|
fat_get_name:
|
|||
|
; in: edi->FAT entry
|
|||
|
; out: CF=1 - no valid entry
|
|||
|
; else CF=0 and ebp->ASCIIZ-name
|
|||
|
; (maximum length of filename is 255 (wide) symbols without trailing 0,
|
|||
|
; but implementation requires buffer 261 words)
|
|||
|
; destroys eax
|
|||
|
cmp byte [edi], 0
|
|||
|
jz .no
|
|||
|
cmp byte [edi], 0xE5
|
|||
|
jnz @f
|
|||
|
.no:
|
|||
|
stc
|
|||
|
ret
|
|||
|
@@:
|
|||
|
cmp byte [edi+11], 0xF
|
|||
|
jz .longname
|
|||
|
test byte [edi+11], 8
|
|||
|
jnz .no
|
|||
|
push ecx
|
|||
|
push edi ebp
|
|||
|
test byte [ebp-4], 1
|
|||
|
jnz .unicode_short
|
|||
|
|
|||
|
mov eax, [edi]
|
|||
|
mov ecx, [edi+4]
|
|||
|
mov [ebp], eax
|
|||
|
mov [ebp+4], ecx
|
|||
|
|
|||
|
mov ecx, 8
|
|||
|
@@:
|
|||
|
cmp byte [ebp+ecx-1], ' '
|
|||
|
loope @b
|
|||
|
|
|||
|
mov eax, [edi+8]
|
|||
|
cmp al, ' '
|
|||
|
je .done
|
|||
|
shl eax, 8
|
|||
|
mov al, '.'
|
|||
|
|
|||
|
lea ebp, [ebp+ecx+1]
|
|||
|
mov [ebp], eax
|
|||
|
mov ecx, 3
|
|||
|
@@:
|
|||
|
rol eax, 8
|
|||
|
cmp al, ' '
|
|||
|
jne .done
|
|||
|
loop @b
|
|||
|
dec ebp
|
|||
|
.done:
|
|||
|
and byte [ebp+ecx+1], 0 ; CF=0
|
|||
|
pop ebp edi ecx
|
|||
|
ret
|
|||
|
.unicode_short:
|
|||
|
mov ecx, 8
|
|||
|
push ecx
|
|||
|
@@:
|
|||
|
mov al, [edi]
|
|||
|
inc edi
|
|||
|
call ansi2uni_char
|
|||
|
mov [ebp], ax
|
|||
|
inc ebp
|
|||
|
inc ebp
|
|||
|
loop @b
|
|||
|
pop ecx
|
|||
|
@@:
|
|||
|
cmp word [ebp-2], ' '
|
|||
|
jnz @f
|
|||
|
dec ebp
|
|||
|
dec ebp
|
|||
|
loop @b
|
|||
|
@@:
|
|||
|
mov word [ebp], '.'
|
|||
|
inc ebp
|
|||
|
inc ebp
|
|||
|
mov ecx, 3
|
|||
|
push ecx
|
|||
|
@@:
|
|||
|
mov al, [edi]
|
|||
|
inc edi
|
|||
|
call ansi2uni_char
|
|||
|
mov [ebp], ax
|
|||
|
inc ebp
|
|||
|
inc ebp
|
|||
|
loop @b
|
|||
|
pop ecx
|
|||
|
@@:
|
|||
|
cmp word [ebp-2], ' '
|
|||
|
jnz @f
|
|||
|
dec ebp
|
|||
|
dec ebp
|
|||
|
loop @b
|
|||
|
dec ebp
|
|||
|
dec ebp
|
|||
|
@@:
|
|||
|
and word [ebp], 0 ; CF=0
|
|||
|
pop ebp edi ecx
|
|||
|
ret
|
|||
|
.longname:
|
|||
|
; LFN
|
|||
|
mov al, byte [edi]
|
|||
|
and eax, 0x3F
|
|||
|
dec eax
|
|||
|
cmp al, 20
|
|||
|
jae .no ; ignore invalid entries
|
|||
|
mov word [ebp+260*2], 0 ; force null-terminating for orphans
|
|||
|
imul eax, 13*2
|
|||
|
add ebp, eax
|
|||
|
test byte [edi], 0x40
|
|||
|
jz @f
|
|||
|
mov word [ebp+13*2], 0
|
|||
|
@@:
|
|||
|
push eax
|
|||
|
; now copy name from edi to ebp ...
|
|||
|
mov eax, [edi+1]
|
|||
|
mov [ebp], eax ; symbols 1,2
|
|||
|
mov eax, [edi+5]
|
|||
|
mov [ebp+4], eax ; 3,4
|
|||
|
mov eax, [edi+9]
|
|||
|
mov [ebp+8], ax ; 5
|
|||
|
mov eax, [edi+14]
|
|||
|
mov [ebp+10], eax ; 6,7
|
|||
|
mov eax, [edi+18]
|
|||
|
mov [ebp+14], eax ; 8,9
|
|||
|
mov eax, [edi+22]
|
|||
|
mov [ebp+18], eax ; 10,11
|
|||
|
mov eax, [edi+28]
|
|||
|
mov [ebp+22], eax ; 12,13
|
|||
|
; ... done
|
|||
|
pop eax
|
|||
|
sub ebp, eax
|
|||
|
test eax, eax
|
|||
|
jz @f
|
|||
|
; if this is not first entry, more processing required
|
|||
|
stc
|
|||
|
ret
|
|||
|
@@:
|
|||
|
; if this is first entry:
|
|||
|
test byte [ebp-4], 1
|
|||
|
jnz .ret
|
|||
|
; buffer at ebp contains UNICODE name, convert it to ANSI
|
|||
|
push esi edi
|
|||
|
mov esi, ebp
|
|||
|
mov edi, ebp
|
|||
|
call uni2ansi_str
|
|||
|
pop edi esi
|
|||
|
.ret:
|
|||
|
clc
|
|||
|
ret
|
|||
|
|
|||
|
fat_compare_name:
|
|||
|
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
|
|||
|
; in: esi->name, ebp->name
|
|||
|
; out: if names match: ZF=1 and esi->next component of name
|
|||
|
; else: ZF=0, esi is not changed
|
|||
|
; destroys eax
|
|||
|
push ebp esi
|
|||
|
.loop:
|
|||
|
mov al, [ebp]
|
|||
|
inc ebp
|
|||
|
call char_toupper
|
|||
|
push eax
|
|||
|
lodsb
|
|||
|
call char_toupper
|
|||
|
cmp al, [esp]
|
|||
|
jnz .done
|
|||
|
pop eax
|
|||
|
test al, al
|
|||
|
jnz .loop
|
|||
|
dec esi
|
|||
|
pop eax
|
|||
|
pop ebp
|
|||
|
xor eax, eax ; set ZF flag
|
|||
|
ret
|
|||
|
.done:
|
|||
|
cmp al, '/'
|
|||
|
jnz @f
|
|||
|
cmp byte [esp], 0
|
|||
|
jnz @f
|
|||
|
mov [esp+4], esi
|
|||
|
@@:
|
|||
|
pop eax
|
|||
|
pop esi ebp
|
|||
|
ret
|
|||
|
|
|||
|
fat_time_to_bdfe:
|
|||
|
; in: eax=FAT time
|
|||
|
; out: eax=BDFE time
|
|||
|
push ecx edx
|
|||
|
mov ecx, eax
|
|||
|
mov edx, eax
|
|||
|
shr eax, 11
|
|||
|
shl eax, 16 ; hours
|
|||
|
and edx, 0x1F
|
|||
|
add edx, edx
|
|||
|
mov al, dl ; seconds
|
|||
|
shr ecx, 5
|
|||
|
and ecx, 0x3F
|
|||
|
mov ah, cl ; minutes
|
|||
|
pop edx ecx
|
|||
|
ret
|
|||
|
|
|||
|
fat_date_to_bdfe:
|
|||
|
push ecx edx
|
|||
|
mov ecx, eax
|
|||
|
mov edx, eax
|
|||
|
shr eax, 9
|
|||
|
add ax, 1980
|
|||
|
shl eax, 16 ; year
|
|||
|
and edx, 0x1F
|
|||
|
mov al, dl ; day
|
|||
|
shr ecx, 5
|
|||
|
and ecx, 0xF
|
|||
|
mov ah, cl ; month
|
|||
|
pop edx ecx
|
|||
|
ret
|
|||
|
|
|||
|
bdfe_to_fat_time:
|
|||
|
push edx
|
|||
|
mov edx, eax
|
|||
|
shr eax, 16
|
|||
|
and dh, 0x3F
|
|||
|
shl eax, 6
|
|||
|
or al, dh
|
|||
|
shr dl, 1
|
|||
|
and dl, 0x1F
|
|||
|
shl eax, 5
|
|||
|
or al, dl
|
|||
|
pop edx
|
|||
|
ret
|
|||
|
|
|||
|
bdfe_to_fat_date:
|
|||
|
push edx
|
|||
|
mov edx, eax
|
|||
|
shr eax, 16
|
|||
|
sub ax, 1980
|
|||
|
and dh, 0xF
|
|||
|
shl eax, 4
|
|||
|
or al, dh
|
|||
|
and dl, 0x1F
|
|||
|
shl eax, 5
|
|||
|
or al, dl
|
|||
|
pop edx
|
|||
|
ret
|
|||
|
|
|||
|
fat_entry_to_bdfe:
|
|||
|
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
|
|||
|
; destroys eax
|
|||
|
mov eax, [ebp-4]
|
|||
|
mov [esi+4], eax ; ASCII/UNICODE name
|
|||
|
fat_entry_to_bdfe2:
|
|||
|
movzx eax, byte [edi+11]
|
|||
|
mov [esi], eax ; attributes
|
|||
|
movzx eax, word [edi+14]
|
|||
|
call fat_time_to_bdfe
|
|||
|
mov [esi+8], eax ; creation time
|
|||
|
movzx eax, word [edi+16]
|
|||
|
call fat_date_to_bdfe
|
|||
|
mov [esi+12], eax ; creation date
|
|||
|
and dword [esi+16], 0 ; last access time is not supported on FAT
|
|||
|
movzx eax, word [edi+18]
|
|||
|
call fat_date_to_bdfe
|
|||
|
mov [esi+20], eax ; last access date
|
|||
|
movzx eax, word [edi+22]
|
|||
|
call fat_time_to_bdfe
|
|||
|
mov [esi+24], eax ; last write time
|
|||
|
movzx eax, word [edi+24]
|
|||
|
call fat_date_to_bdfe
|
|||
|
mov [esi+28], eax ; last write date
|
|||
|
mov eax, [edi+28]
|
|||
|
mov [esi+32], eax ; file size (low dword)
|
|||
|
xor eax, eax
|
|||
|
mov [esi+36], eax ; file size (high dword)
|
|||
|
test ebp, ebp
|
|||
|
jz .ret
|
|||
|
push ecx edi
|
|||
|
lea edi, [esi+40]
|
|||
|
mov esi, ebp
|
|||
|
test byte [esi-4], 1
|
|||
|
jz .ansi
|
|||
|
mov ecx, 260/2
|
|||
|
rep movsd
|
|||
|
mov [edi-2], ax
|
|||
|
@@:
|
|||
|
mov esi, edi
|
|||
|
pop edi ecx
|
|||
|
.ret:
|
|||
|
ret
|
|||
|
.ansi:
|
|||
|
mov ecx, 264/4
|
|||
|
rep movsd
|
|||
|
mov [edi-1], al
|
|||
|
jmp @b
|
|||
|
|
|||
|
bdfe_to_fat_entry:
|
|||
|
; convert BDFE at edx to FAT entry at edi
|
|||
|
; destroys eax
|
|||
|
; attributes byte
|
|||
|
test byte [edi+11], 8 ; volume label?
|
|||
|
jnz @f
|
|||
|
mov al, [edx]
|
|||
|
and al, 0x27
|
|||
|
and byte [edi+11], 0x10
|
|||
|
or byte [edi+11], al
|
|||
|
@@:
|
|||
|
mov eax, [edx+8]
|
|||
|
call bdfe_to_fat_time
|
|||
|
mov [edi+14], ax ; creation time
|
|||
|
mov eax, [edx+12]
|
|||
|
call bdfe_to_fat_date
|
|||
|
mov [edi+16], ax ; creation date
|
|||
|
mov eax, [edx+20]
|
|||
|
call bdfe_to_fat_date
|
|||
|
mov [edi+18], ax ; last access date
|
|||
|
mov eax, [edx+24]
|
|||
|
call bdfe_to_fat_time
|
|||
|
mov [edi+22], ax ; last write time
|
|||
|
mov eax, [edx+28]
|
|||
|
call bdfe_to_fat_date
|
|||
|
mov [edi+24], ax ; last write date
|
|||
|
ret
|
|||
|
|
|||
|
ramdisk_root_first:
|
|||
|
mov edi, RAMDISK+512*19
|
|||
|
clc
|
|||
|
ret
|
|||
|
ramdisk_root_next:
|
|||
|
add edi, 0x20
|
|||
|
cmp edi, RAMDISK+512*33
|
|||
|
cmc
|
|||
|
ret
|
|||
|
|
|||
|
ramdisk_root_extend_dir:
|
|||
|
stc
|
|||
|
ret
|
|||
|
|
|||
|
uglobal
|
|||
|
; this is for delete support
|
|||
|
rd_prev_sector dd ?
|
|||
|
rd_prev_prev_sector dd ?
|
|||
|
endg
|
|||
|
|
|||
|
ramdisk_notroot_next:
|
|||
|
add edi, 0x20
|
|||
|
test edi, 0x1FF
|
|||
|
jz ramdisk_notroot_next_sector
|
|||
|
ret ; CF=0
|
|||
|
ramdisk_notroot_next_sector:
|
|||
|
push ecx
|
|||
|
mov ecx, [eax]
|
|||
|
push [rd_prev_sector]
|
|||
|
pop [rd_prev_prev_sector]
|
|||
|
mov [rd_prev_sector], ecx
|
|||
|
mov ecx, [ecx*2+RAMDISK_FAT]
|
|||
|
and ecx, 0xFFF
|
|||
|
cmp ecx, 2849
|
|||
|
jae ramdisk_notroot_first.err2
|
|||
|
mov [eax], ecx
|
|||
|
pop ecx
|
|||
|
ramdisk_notroot_first:
|
|||
|
mov eax, [eax]
|
|||
|
cmp eax, 2
|
|||
|
jb .err
|
|||
|
cmp eax, 2849
|
|||
|
jae .err
|
|||
|
shl eax, 9
|
|||
|
lea edi, [eax+(31 shl 9)+RAMDISK]
|
|||
|
clc
|
|||
|
ret
|
|||
|
.err2:
|
|||
|
pop ecx
|
|||
|
.err:
|
|||
|
stc
|
|||
|
ret
|
|||
|
ramdisk_notroot_next_write:
|
|||
|
test edi, 0x1FF
|
|||
|
jz ramdisk_notroot_next_sector
|
|||
|
ramdisk_root_next_write:
|
|||
|
ret
|
|||
|
|
|||
|
ramdisk_notroot_extend_dir:
|
|||
|
pusha
|
|||
|
xor eax, eax
|
|||
|
mov edi, RAMDISK_FAT
|
|||
|
mov ecx, 2849
|
|||
|
repnz scasw
|
|||
|
jnz .notfound
|
|||
|
mov word [edi-2], 0xFFF
|
|||
|
sub edi, RAMDISK_FAT
|
|||
|
shr edi, 1
|
|||
|
dec edi
|
|||
|
mov eax, [esp+28]
|
|||
|
mov ecx, [eax]
|
|||
|
mov [RAMDISK_FAT+ecx*2], di
|
|||
|
mov [eax], edi
|
|||
|
shl edi, 9
|
|||
|
add edi, (31 shl 9)+RAMDISK
|
|||
|
mov [esp], edi
|
|||
|
xor eax, eax
|
|||
|
mov ecx, 128
|
|||
|
rep stosd
|
|||
|
popa
|
|||
|
clc
|
|||
|
ret
|
|||
|
.notfound:
|
|||
|
popa
|
|||
|
stc
|
|||
|
ret
|
|||
|
|
|||
|
rd_find_lfn:
|
|||
|
; in: esi+ebp -> name
|
|||
|
; out: CF=1 - file not found
|
|||
|
; else CF=0 and edi->direntry
|
|||
|
push esi edi
|
|||
|
push 0
|
|||
|
push ramdisk_root_first
|
|||
|
push ramdisk_root_next
|
|||
|
.loop:
|
|||
|
call fat_find_lfn
|
|||
|
jc .notfound
|
|||
|
cmp byte [esi], 0
|
|||
|
jz .found
|
|||
|
.continue:
|
|||
|
test byte [edi+11], 10h
|
|||
|
jz .notfound
|
|||
|
movzx eax, word [edi+26]
|
|||
|
mov [esp+8], eax
|
|||
|
mov dword [esp+4], ramdisk_notroot_first
|
|||
|
mov dword [esp], ramdisk_notroot_next
|
|||
|
test eax, eax
|
|||
|
jnz .loop
|
|||
|
mov dword [esp+4], ramdisk_root_first
|
|||
|
mov dword [esp], ramdisk_notroot_next
|
|||
|
jmp .loop
|
|||
|
.notfound:
|
|||
|
add esp, 12
|
|||
|
pop edi esi
|
|||
|
stc
|
|||
|
ret
|
|||
|
.found:
|
|||
|
test ebp, ebp
|
|||
|
jz @f
|
|||
|
mov esi, ebp
|
|||
|
xor ebp, ebp
|
|||
|
jmp .continue
|
|||
|
@@:
|
|||
|
mov eax, [esp+8]
|
|||
|
add esp, 16 ; CF=0
|
|||
|
pop esi
|
|||
|
ret
|
|||
|
|
|||
|
;----------------------------------------------------------------
|
|||
|
;
|
|||
|
; fs_RamdiskRead - LFN variant for reading sys floppy
|
|||
|
;
|
|||
|
; esi points to filename
|
|||
|
; ebx pointer to 64-bit number = first wanted byte, 0+
|
|||
|
; may be ebx=0 - start from first byte
|
|||
|
; ecx number of bytes to read, 0+
|
|||
|
; edx mem location to return data
|
|||
|
;
|
|||
|
; ret ebx = bytes read or 0xffffffff file not found
|
|||
|
; eax = 0 ok read or other = errormsg
|
|||
|
;
|
|||
|
;--------------------------------------------------------------
|
|||
|
fs_RamdiskRead:
|
|||
|
cmp byte [esi], 0
|
|||
|
jnz @f
|
|||
|
or ebx, -1
|
|||
|
mov eax, 10 ; access denied
|
|||
|
ret
|
|||
|
@@:
|
|||
|
push edi
|
|||
|
call rd_find_lfn
|
|||
|
jnc .found
|
|||
|
pop edi
|
|||
|
or ebx, -1
|
|||
|
mov eax, 5 ; file not found
|
|||
|
ret
|
|||
|
.found:
|
|||
|
test ebx, ebx
|
|||
|
jz .l1
|
|||
|
cmp dword [ebx+4], 0
|
|||
|
jz @f
|
|||
|
xor ebx, ebx
|
|||
|
.reteof:
|
|||
|
mov eax, 6 ; EOF
|
|||
|
pop edi
|
|||
|
ret
|
|||
|
@@:
|
|||
|
mov ebx, [ebx]
|
|||
|
.l1:
|
|||
|
push ecx edx
|
|||
|
push 0
|
|||
|
mov eax, [edi+28]
|
|||
|
sub eax, ebx
|
|||
|
jb .eof
|
|||
|
cmp eax, ecx
|
|||
|
jae @f
|
|||
|
mov ecx, eax
|
|||
|
mov byte [esp], 6 ; EOF
|
|||
|
@@:
|
|||
|
movzx edi, word [edi+26] ; cluster
|
|||
|
.new:
|
|||
|
jecxz .done
|
|||
|
test edi, edi
|
|||
|
jz .eof
|
|||
|
cmp edi, 0xFF8
|
|||
|
jae .eof
|
|||
|
lea eax, [edi+31] ; bootsector+2*fat+filenames
|
|||
|
shl eax, 9 ; *512
|
|||
|
add eax, RAMDISK ; image base
|
|||
|
; now eax points to data of cluster
|
|||
|
sub ebx, 512
|
|||
|
jae .skip
|
|||
|
lea eax, [eax+ebx+512]
|
|||
|
neg ebx
|
|||
|
push ecx
|
|||
|
cmp ecx, ebx
|
|||
|
jbe @f
|
|||
|
mov ecx, ebx
|
|||
|
@@:
|
|||
|
mov ebx, edx
|
|||
|
call memmove
|
|||
|
add edx, ecx
|
|||
|
sub [esp], ecx
|
|||
|
pop ecx
|
|||
|
xor ebx, ebx
|
|||
|
.skip:
|
|||
|
movzx edi, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT
|
|||
|
jmp .new
|
|||
|
.eof:
|
|||
|
mov ebx, edx
|
|||
|
pop eax edx ecx
|
|||
|
sub ebx, edx
|
|||
|
jmp .reteof
|
|||
|
.done:
|
|||
|
mov ebx, edx
|
|||
|
pop eax edx ecx edi
|
|||
|
sub ebx, edx
|
|||
|
ret
|
|||
|
|
|||
|
;----------------------------------------------------------------
|
|||
|
;
|
|||
|
; fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
|
|||
|
;
|
|||
|
; esi points to filename; only root is folder on ramdisk
|
|||
|
; ebx pointer to structure 32-bit number = first wanted block
|
|||
|
; & flags (bitfields)
|
|||
|
; flags: bit 0: 0=ANSI names, 1=UNICODE names
|
|||
|
; ecx number of blocks to read, 0+
|
|||
|
; edx mem location to return data
|
|||
|
;
|
|||
|
; ret ebx = size or 0xffffffff file not found
|
|||
|
; eax = 0 ok read or other = errormsg
|
|||
|
;
|
|||
|
;--------------------------------------------------------------
|
|||
|
fs_RamdiskReadFolder:
|
|||
|
push edi
|
|||
|
cmp byte [esi], 0
|
|||
|
jz .root
|
|||
|
call rd_find_lfn
|
|||
|
jnc .found
|
|||
|
pop edi
|
|||
|
or ebx, -1
|
|||
|
mov eax, ERROR_FILE_NOT_FOUND
|
|||
|
ret
|
|||
|
.found:
|
|||
|
test byte [edi+11], 0x10
|
|||
|
jnz .found_dir
|
|||
|
pop edi
|
|||
|
or ebx, -1
|
|||
|
mov eax, ERROR_ACCESS_DENIED
|
|||
|
ret
|
|||
|
.found_dir:
|
|||
|
movzx eax, word [edi+26]
|
|||
|
add eax, 31
|
|||
|
push 0
|
|||
|
jmp .doit
|
|||
|
.root:
|
|||
|
mov eax, 19
|
|||
|
push 14
|
|||
|
.doit:
|
|||
|
push esi ecx ebp
|
|||
|
sub esp, 262*2 ; reserve space for LFN
|
|||
|
mov ebp, esp
|
|||
|
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names
|
|||
|
mov ebx, [ebx]
|
|||
|
; init header
|
|||
|
push eax ecx
|
|||
|
mov edi, edx
|
|||
|
mov ecx, 32/4
|
|||
|
xor eax, eax
|
|||
|
rep stosd
|
|||
|
mov byte [edx], 1 ; version
|
|||
|
pop ecx eax
|
|||
|
mov esi, edi ; esi points to block of data of folder entry (BDFE)
|
|||
|
.main_loop:
|
|||
|
mov edi, eax
|
|||
|
shl edi, 9
|
|||
|
add edi, RAMDISK
|
|||
|
push eax
|
|||
|
.l1:
|
|||
|
call fat_get_name
|
|||
|
jc .l2
|
|||
|
cmp byte [edi+11], 0xF
|
|||
|
jnz .do_bdfe
|
|||
|
add edi, 0x20
|
|||
|
test edi, 0x1FF
|
|||
|
jnz .do_bdfe
|
|||
|
pop eax
|
|||
|
inc eax
|
|||
|
dec byte [esp+262*2+16]
|
|||
|
jz .done
|
|||
|
jns @f
|
|||
|
; read next sector from FAT
|
|||
|
mov eax, [(eax-31-1)*2+RAMDISK_FAT]
|
|||
|
and eax, 0xFFF
|
|||
|
cmp eax, 0xFF8
|
|||
|
jae .done
|
|||
|
add eax, 31
|
|||
|
mov byte [esp+262*2+16], 0
|
|||
|
@@:
|
|||
|
mov edi, eax
|
|||
|
shl edi, 9
|
|||
|
add edi, RAMDISK
|
|||
|
push eax
|
|||
|
.do_bdfe:
|
|||
|
inc dword [edx+8] ; new file found
|
|||
|
dec ebx
|
|||
|
jns .l2
|
|||
|
dec ecx
|
|||
|
js .l2
|
|||
|
inc dword [edx+4] ; new file block copied
|
|||
|
call fat_entry_to_bdfe
|
|||
|
.l2:
|
|||
|
add edi, 0x20
|
|||
|
test edi, 0x1FF
|
|||
|
jnz .l1
|
|||
|
pop eax
|
|||
|
inc eax
|
|||
|
dec byte [esp+262*2+16]
|
|||
|
jz .done
|
|||
|
jns @f
|
|||
|
; read next sector from FAT
|
|||
|
mov eax, [(eax-31-1)*2+RAMDISK_FAT]
|
|||
|
and eax, 0xFFF
|
|||
|
cmp eax, 0xFF8
|
|||
|
jae .done
|
|||
|
add eax, 31
|
|||
|
mov byte [esp+262*2+16], 0
|
|||
|
@@:
|
|||
|
jmp .main_loop
|
|||
|
.done:
|
|||
|
add esp, 262*2+4
|
|||
|
pop ebp
|
|||
|
mov ebx, [edx+4]
|
|||
|
xor eax, eax
|
|||
|
dec ecx
|
|||
|
js @f
|
|||
|
mov al, ERROR_END_OF_FILE
|
|||
|
@@:
|
|||
|
pop ecx esi edi edi
|
|||
|
ret
|
|||
|
|
|||
|
iglobal
|
|||
|
label fat_legal_chars byte
|
|||
|
; 0 = not allowed
|
|||
|
; 1 = allowed only in long names
|
|||
|
; 3 = allowed
|
|||
|
times 32 db 0
|
|||
|
; ! " # $ % & ' ( ) * + , - . /
|
|||
|
db 1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
|
|||
|
; 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
|
|||
|
db 3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
|
|||
|
; @ A B C D E F G H I J K L M N O
|
|||
|
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
|
|||
|
; P Q R S T U V W X Y Z [ \ ] ^ _
|
|||
|
db 3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
|
|||
|
; ` a b c d e f g h i j k l m n o
|
|||
|
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
|
|||
|
; p q r s t u v w x y z { | } ~
|
|||
|
db 3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
|
|||
|
endg
|
|||
|
|
|||
|
fat_name_is_legal:
|
|||
|
; in: esi->(long) name
|
|||
|
; out: CF set <=> legal
|
|||
|
; destroys eax
|
|||
|
push esi
|
|||
|
xor eax, eax
|
|||
|
@@:
|
|||
|
lodsb
|
|||
|
test al, al
|
|||
|
jz .done
|
|||
|
cmp al, 80h
|
|||
|
jae .big
|
|||
|
test [fat_legal_chars+eax], 1
|
|||
|
jnz @b
|
|||
|
.err:
|
|||
|
pop esi
|
|||
|
clc
|
|||
|
ret
|
|||
|
.big:
|
|||
|
; 0x80-0xAF, 0xE0-0xEF
|
|||
|
cmp al, 0xB0
|
|||
|
jb @b
|
|||
|
cmp al, 0xE0
|
|||
|
jb .err
|
|||
|
cmp al, 0xF0
|
|||
|
jb @b
|
|||
|
jmp .err
|
|||
|
.done:
|
|||
|
sub esi, [esp]
|
|||
|
cmp esi, 257
|
|||
|
pop esi
|
|||
|
ret
|
|||
|
|
|||
|
fat_next_short_name:
|
|||
|
; in: edi->8+3 name
|
|||
|
; out: name corrected
|
|||
|
; CF=1 <=> error
|
|||
|
pushad
|
|||
|
mov ecx, 8
|
|||
|
mov al, '~'
|
|||
|
std
|
|||
|
push edi
|
|||
|
add edi, 7
|
|||
|
repnz scasb
|
|||
|
pop edi
|
|||
|
cld
|
|||
|
jz .tilde
|
|||
|
; tilde is not found, insert "~1" at end
|
|||
|
add edi, 6
|
|||
|
cmp word [edi], ' '
|
|||
|
jnz .insert_tilde
|
|||
|
@@: dec edi
|
|||
|
cmp byte [edi], ' '
|
|||
|
jz @b
|
|||
|
inc edi
|
|||
|
.insert_tilde:
|
|||
|
mov word [edi], '~1'
|
|||
|
popad
|
|||
|
clc
|
|||
|
ret
|
|||
|
.tilde:
|
|||
|
push edi
|
|||
|
add edi, 7
|
|||
|
xor ecx, ecx
|
|||
|
@@:
|
|||
|
; after tilde may be only digits and trailing spaces
|
|||
|
cmp byte [edi], '~'
|
|||
|
jz .break
|
|||
|
cmp byte [edi], ' '
|
|||
|
jz .space
|
|||
|
cmp byte [edi], '9'
|
|||
|
jnz .found
|
|||
|
dec edi
|
|||
|
jmp @b
|
|||
|
.space:
|
|||
|
dec edi
|
|||
|
inc ecx
|
|||
|
jmp @b
|
|||
|
.found:
|
|||
|
inc byte [edi]
|
|||
|
add dword [esp], 8
|
|||
|
jmp .zerorest
|
|||
|
.break:
|
|||
|
jecxz .noplace
|
|||
|
inc edi
|
|||
|
mov al, '1'
|
|||
|
@@:
|
|||
|
xchg al, [edi]
|
|||
|
inc edi
|
|||
|
cmp al, ' '
|
|||
|
mov al, '0'
|
|||
|
jnz @b
|
|||
|
.succ:
|
|||
|
pop edi
|
|||
|
popad
|
|||
|
clc
|
|||
|
ret
|
|||
|
.noplace:
|
|||
|
dec edi
|
|||
|
cmp edi, [esp]
|
|||
|
jz .err
|
|||
|
add dword [esp], 8
|
|||
|
mov word [edi], '~1'
|
|||
|
inc edi
|
|||
|
inc edi
|
|||
|
@@:
|
|||
|
mov byte [edi], '0'
|
|||
|
.zerorest:
|
|||
|
inc edi
|
|||
|
cmp edi, [esp]
|
|||
|
jb @b
|
|||
|
pop edi
|
|||
|
popad
|
|||
|
;clc ; automatically
|
|||
|
ret
|
|||
|
.err:
|
|||
|
pop edi
|
|||
|
popad
|
|||
|
stc
|
|||
|
ret
|
|||
|
|
|||
|
fat_gen_short_name:
|
|||
|
; in: esi->long name
|
|||
|
; edi->buffer (8+3=11 chars)
|
|||
|
; out: buffer filled
|
|||
|
pushad
|
|||
|
mov eax, ' '
|
|||
|
push edi
|
|||
|
stosd
|
|||
|
stosd
|
|||
|
stosd
|
|||
|
pop edi
|
|||
|
xor eax, eax
|
|||
|
push 8
|
|||
|
pop ebx
|
|||
|
lea ecx, [edi+8]
|
|||
|
.loop:
|
|||
|
lodsb
|
|||
|
test al, al
|
|||
|
jz .done
|
|||
|
call char_toupper
|
|||
|
cmp al, ' '
|
|||
|
jz .space
|
|||
|
cmp al, 80h
|
|||
|
ja .big
|
|||
|
test [fat_legal_chars+eax], 2
|
|||
|
jnz .symbol
|
|||
|
.inv_symbol:
|
|||
|
mov al, '_'
|
|||
|
or bh, 1
|
|||
|
.symbol:
|
|||
|
cmp al, '.'
|
|||
|
jz .dot
|
|||
|
.normal_symbol:
|
|||
|
dec bl
|
|||
|
jns .store
|
|||
|
mov bl, 0
|
|||
|
.space:
|
|||
|
or bh, 1
|
|||
|
jmp .loop
|
|||
|
.store:
|
|||
|
stosb
|
|||
|
jmp .loop
|
|||
|
.big:
|
|||
|
cmp al, 0xB0
|
|||
|
jb .normal_symbol
|
|||
|
cmp al, 0xE0
|
|||
|
jb .inv_symbol
|
|||
|
cmp al, 0xF0
|
|||
|
jb .normal_symbol
|
|||
|
jmp .inv_symbol
|
|||
|
.dot:
|
|||
|
test bh, 2
|
|||
|
jz .firstdot
|
|||
|
pop ebx
|
|||
|
add ebx, edi
|
|||
|
sub ebx, ecx
|
|||
|
push ebx
|
|||
|
cmp ebx, ecx
|
|||
|
jb @f
|
|||
|
pop ebx
|
|||
|
push ecx
|
|||
|
@@:
|
|||
|
cmp edi, ecx
|
|||
|
jbe .skip
|
|||
|
@@:
|
|||
|
dec edi
|
|||
|
mov al, [edi]
|
|||
|
dec ebx
|
|||
|
mov [ebx], al
|
|||
|
mov byte [edi], ' '
|
|||
|
cmp edi, ecx
|
|||
|
ja @b
|
|||
|
.skip:
|
|||
|
mov bh, 3
|
|||
|
jmp @f
|
|||
|
.firstdot:
|
|||
|
cmp bl, 8
|
|||
|
jz .space
|
|||
|
push edi
|
|||
|
or bh, 2
|
|||
|
@@:
|
|||
|
mov edi, ecx
|
|||
|
mov bl, 3
|
|||
|
jmp .loop
|
|||
|
.done:
|
|||
|
test bh, 2
|
|||
|
jz @f
|
|||
|
pop edi
|
|||
|
@@:
|
|||
|
lea edi, [ecx-8]
|
|||
|
test bh, 1
|
|||
|
jz @f
|
|||
|
call fat_next_short_name
|
|||
|
@@:
|
|||
|
popad
|
|||
|
ret
|
|||
|
|
|||
|
;----------------------------------------------------------------
|
|||
|
;
|
|||
|
; fs_RamdiskRewrite - LFN variant for writing ramdisk
|
|||
|
; fs_RamdiskCreateFolder - create folder on ramdisk
|
|||
|
;
|
|||
|
; esi points to file/folder name
|
|||
|
; ebx ignored (reserved)
|
|||
|
; ecx number of bytes to write, 0+ (ignored for folders)
|
|||
|
; edx mem location to data (ignored for folders)
|
|||
|
;
|
|||
|
; ret ebx = number of written bytes
|
|||
|
; eax = 0 ok read or other = errormsg
|
|||
|
;
|
|||
|
;--------------------------------------------------------------
|
|||
|
@@:
|
|||
|
mov eax, ERROR_ACCESS_DENIED
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
|
|||
|
fs_RamdiskCreateFolder:
|
|||
|
mov al, 1 ; create folder
|
|||
|
jmp fs_RamdiskRewrite.common
|
|||
|
|
|||
|
fs_RamdiskRewrite:
|
|||
|
xor eax, eax ; create file
|
|||
|
.common:
|
|||
|
cmp byte [esi], 0
|
|||
|
jz @b
|
|||
|
pushad
|
|||
|
xor edi, edi
|
|||
|
push esi
|
|||
|
test ebp, ebp
|
|||
|
jz @f
|
|||
|
mov esi, ebp
|
|||
|
@@:
|
|||
|
lodsb
|
|||
|
test al, al
|
|||
|
jz @f
|
|||
|
cmp al, '/'
|
|||
|
jnz @b
|
|||
|
lea edi, [esi-1]
|
|||
|
jmp @b
|
|||
|
@@:
|
|||
|
pop esi
|
|||
|
test edi, edi
|
|||
|
jnz .noroot
|
|||
|
test ebp, ebp
|
|||
|
jnz .hasebp
|
|||
|
push ramdisk_root_extend_dir
|
|||
|
push ramdisk_root_next_write
|
|||
|
push edi
|
|||
|
push ramdisk_root_first
|
|||
|
push ramdisk_root_next
|
|||
|
jmp .common1
|
|||
|
.hasebp:
|
|||
|
mov eax, ERROR_ACCESS_DENIED
|
|||
|
cmp byte [ebp], 0
|
|||
|
jz .ret1
|
|||
|
push ebp
|
|||
|
xor ebp, ebp
|
|||
|
call rd_find_lfn
|
|||
|
pop esi
|
|||
|
jc .notfound0
|
|||
|
jmp .common0
|
|||
|
.noroot:
|
|||
|
mov eax, ERROR_ACCESS_DENIED
|
|||
|
cmp byte [edi+1], 0
|
|||
|
jz .ret1
|
|||
|
; check existence
|
|||
|
mov byte [edi], 0
|
|||
|
push edi
|
|||
|
call rd_find_lfn
|
|||
|
pop esi
|
|||
|
mov byte [esi], '/'
|
|||
|
jnc @f
|
|||
|
.notfound0:
|
|||
|
mov eax, ERROR_FILE_NOT_FOUND
|
|||
|
.ret1:
|
|||
|
mov [esp+28], eax
|
|||
|
popad
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
@@:
|
|||
|
inc esi
|
|||
|
.common0:
|
|||
|
test byte [edi+11], 0x10 ; must be directory
|
|||
|
mov eax, ERROR_ACCESS_DENIED
|
|||
|
jz .ret1
|
|||
|
movzx ebp, word [edi+26] ; ebp=cluster
|
|||
|
mov eax, ERROR_FAT_TABLE
|
|||
|
cmp ebp, 2
|
|||
|
jb .ret1
|
|||
|
cmp ebp, 2849
|
|||
|
jae .ret1
|
|||
|
push ramdisk_notroot_extend_dir
|
|||
|
push ramdisk_notroot_next_write
|
|||
|
push ebp
|
|||
|
push ramdisk_notroot_first
|
|||
|
push ramdisk_notroot_next
|
|||
|
.common1:
|
|||
|
call fat_find_lfn
|
|||
|
jc .notfound
|
|||
|
; found
|
|||
|
test byte [edi+11], 10h
|
|||
|
jz .exists_file
|
|||
|
; found directory; if we are creating directory, return OK,
|
|||
|
; if we are creating file, say "access denied"
|
|||
|
add esp, 20
|
|||
|
popad
|
|||
|
test al, al
|
|||
|
mov eax, ERROR_ACCESS_DENIED
|
|||
|
jz @f
|
|||
|
mov al, 0
|
|||
|
@@:
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
.exists_file:
|
|||
|
; found file; if we are creating directory, return "access denied",
|
|||
|
; if we are creating file, delete existing file and continue
|
|||
|
cmp byte [esp+20+28], 0
|
|||
|
jz @f
|
|||
|
add esp, 20
|
|||
|
popad
|
|||
|
mov eax, ERROR_ACCESS_DENIED
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
@@:
|
|||
|
; delete FAT chain
|
|||
|
push edi
|
|||
|
xor eax, eax
|
|||
|
mov dword [edi+28], eax ; zero size
|
|||
|
xchg ax, word [edi+26] ; start cluster
|
|||
|
test eax, eax
|
|||
|
jz .done1
|
|||
|
@@:
|
|||
|
cmp eax, 0xFF8
|
|||
|
jae .done1
|
|||
|
lea edi, [RAMDISK_FAT + eax*2] ; position in FAT
|
|||
|
xor eax, eax
|
|||
|
xchg ax, [edi]
|
|||
|
jmp @b
|
|||
|
.done1:
|
|||
|
pop edi
|
|||
|
call get_time_for_file
|
|||
|
mov [edi+22], ax
|
|||
|
call get_date_for_file
|
|||
|
mov [edi+24], ax
|
|||
|
mov [edi+18], ax
|
|||
|
or byte [edi+11], 20h ; set 'archive' attribute
|
|||
|
jmp .doit
|
|||
|
.notfound:
|
|||
|
; file is not found; generate short name
|
|||
|
call fat_name_is_legal
|
|||
|
jc @f
|
|||
|
add esp, 20
|
|||
|
popad
|
|||
|
mov eax, ERROR_FILE_NOT_FOUND
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
@@:
|
|||
|
sub esp, 12
|
|||
|
mov edi, esp
|
|||
|
call fat_gen_short_name
|
|||
|
.test_short_name_loop:
|
|||
|
push esi edi ecx
|
|||
|
mov esi, edi
|
|||
|
lea eax, [esp+12+12+8]
|
|||
|
mov [eax], ebp
|
|||
|
call dword [eax-4]
|
|||
|
jc .found
|
|||
|
.test_short_name_entry:
|
|||
|
cmp byte [edi+11], 0xF
|
|||
|
jz .test_short_name_cont
|
|||
|
mov ecx, 11
|
|||
|
push esi edi
|
|||
|
repz cmpsb
|
|||
|
pop edi esi
|
|||
|
jz .short_name_found
|
|||
|
.test_short_name_cont:
|
|||
|
lea eax, [esp+12+12+8]
|
|||
|
call dword [eax-8]
|
|||
|
jnc .test_short_name_entry
|
|||
|
jmp .found
|
|||
|
.short_name_found:
|
|||
|
pop ecx edi esi
|
|||
|
call fat_next_short_name
|
|||
|
jnc .test_short_name_loop
|
|||
|
.disk_full:
|
|||
|
add esp, 12+20
|
|||
|
popad
|
|||
|
mov eax, ERROR_DISK_FULL
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
.found:
|
|||
|
pop ecx edi esi
|
|||
|
; now find space in directory
|
|||
|
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
|
|||
|
mov al, '~'
|
|||
|
push ecx edi
|
|||
|
mov ecx, 8
|
|||
|
repnz scasb
|
|||
|
push 1
|
|||
|
pop eax ; 1 entry
|
|||
|
jnz .notilde
|
|||
|
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
|
|||
|
xor eax, eax
|
|||
|
@@:
|
|||
|
cmp byte [esi], 0
|
|||
|
jz @f
|
|||
|
inc esi
|
|||
|
inc eax
|
|||
|
jmp @b
|
|||
|
@@:
|
|||
|
sub esi, eax
|
|||
|
add eax, 12+13
|
|||
|
mov ecx, 13
|
|||
|
push edx
|
|||
|
cdq
|
|||
|
div ecx
|
|||
|
pop edx
|
|||
|
.notilde:
|
|||
|
push -1
|
|||
|
push -1
|
|||
|
; find <eax> successive entries in directory
|
|||
|
xor ecx, ecx
|
|||
|
push eax
|
|||
|
lea eax, [esp+12+8+12+8]
|
|||
|
mov [eax], ebp
|
|||
|
call dword [eax-4]
|
|||
|
pop eax
|
|||
|
.scan_dir:
|
|||
|
cmp byte [edi], 0
|
|||
|
jz .free
|
|||
|
cmp byte [edi], 0xE5
|
|||
|
jz .free
|
|||
|
xor ecx, ecx
|
|||
|
.scan_cont:
|
|||
|
push eax
|
|||
|
lea eax, [esp+12+8+12+8]
|
|||
|
call dword [eax-8]
|
|||
|
pop eax
|
|||
|
jnc .scan_dir
|
|||
|
push eax
|
|||
|
lea eax, [esp+12+8+12+8]
|
|||
|
call dword [eax+8] ; extend directory
|
|||
|
pop eax
|
|||
|
jnc .scan_dir
|
|||
|
add esp, 8+8+12+20
|
|||
|
popad
|
|||
|
mov eax, ERROR_DISK_FULL
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
.free:
|
|||
|
test ecx, ecx
|
|||
|
jnz @f
|
|||
|
mov [esp], edi
|
|||
|
mov ecx, [esp+8+8+12+8]
|
|||
|
mov [esp+4], ecx
|
|||
|
xor ecx, ecx
|
|||
|
@@:
|
|||
|
inc ecx
|
|||
|
cmp ecx, eax
|
|||
|
jb .scan_cont
|
|||
|
; found!
|
|||
|
; calculate name checksum
|
|||
|
push esi ecx
|
|||
|
mov esi, [esp+8+8]
|
|||
|
mov ecx, 11
|
|||
|
xor eax, eax
|
|||
|
@@:
|
|||
|
ror al, 1
|
|||
|
add al, [esi]
|
|||
|
inc esi
|
|||
|
loop @b
|
|||
|
pop ecx esi
|
|||
|
pop edi
|
|||
|
pop dword [esp+8+12+8]
|
|||
|
; edi points to last entry in free chunk
|
|||
|
dec ecx
|
|||
|
jz .nolfn
|
|||
|
push esi
|
|||
|
push eax
|
|||
|
mov al, 40h
|
|||
|
.writelfn:
|
|||
|
or al, cl
|
|||
|
mov esi, [esp+4]
|
|||
|
push ecx
|
|||
|
dec ecx
|
|||
|
imul ecx, 13
|
|||
|
add esi, ecx
|
|||
|
stosb
|
|||
|
mov cl, 5
|
|||
|
call .read_symbols
|
|||
|
mov ax, 0xF
|
|||
|
stosw
|
|||
|
mov al, [esp+4]
|
|||
|
stosb
|
|||
|
mov cl, 6
|
|||
|
call .read_symbols
|
|||
|
xor eax, eax
|
|||
|
stosw
|
|||
|
mov cl, 2
|
|||
|
call .read_symbols
|
|||
|
pop ecx
|
|||
|
lea eax, [esp+8+8+12+8]
|
|||
|
call dword [eax+4] ; next write
|
|||
|
xor eax, eax
|
|||
|
loop .writelfn
|
|||
|
pop eax
|
|||
|
pop esi
|
|||
|
.nolfn:
|
|||
|
xchg esi, [esp]
|
|||
|
mov ecx, 11
|
|||
|
rep movsb
|
|||
|
mov word [edi], 20h ; attributes
|
|||
|
sub edi, 11
|
|||
|
pop esi ecx
|
|||
|
add esp, 12
|
|||
|
mov byte [edi+13], 0 ; tenths of a second at file creation time
|
|||
|
call get_time_for_file
|
|||
|
mov [edi+14], ax ; creation time
|
|||
|
mov [edi+22], ax ; last write time
|
|||
|
call get_date_for_file
|
|||
|
mov [edi+16], ax ; creation date
|
|||
|
mov [edi+24], ax ; last write date
|
|||
|
mov [edi+18], ax ; last access date
|
|||
|
and word [edi+20], 0 ; high word of cluster
|
|||
|
and word [edi+26], 0 ; low word of cluster - to be filled
|
|||
|
and dword [edi+28], 0 ; file size - to be filled
|
|||
|
cmp byte [esp+20+28], 0
|
|||
|
jz .doit
|
|||
|
; create directory
|
|||
|
mov byte [edi+11], 10h ; attributes: folder
|
|||
|
mov ecx, 32*2
|
|||
|
mov edx, edi
|
|||
|
.doit:
|
|||
|
push edx
|
|||
|
push ecx
|
|||
|
push edi
|
|||
|
add edi, 26 ; edi points to low word of cluster
|
|||
|
push edi
|
|||
|
jecxz .done
|
|||
|
mov ecx, 2849
|
|||
|
mov edi, RAMDISK_FAT
|
|||
|
.write_loop:
|
|||
|
; allocate new cluster
|
|||
|
xor eax, eax
|
|||
|
repnz scasw
|
|||
|
jnz .disk_full2
|
|||
|
dec edi
|
|||
|
dec edi
|
|||
|
|
|||
|
; lea eax, [edi-(RAMDISK_FAT)]
|
|||
|
|
|||
|
mov eax, edi
|
|||
|
sub eax, RAMDISK_FAT
|
|||
|
|
|||
|
shr eax, 1 ; eax = cluster
|
|||
|
mov word [edi], 0xFFF ; mark as last cluster
|
|||
|
xchg edi, [esp]
|
|||
|
stosw
|
|||
|
pop edi
|
|||
|
push edi
|
|||
|
inc ecx
|
|||
|
; write data
|
|||
|
cmp byte [esp+16+20+28], 0
|
|||
|
jnz .writedir
|
|||
|
shl eax, 9
|
|||
|
add eax, RAMDISK+31*512
|
|||
|
.writefile:
|
|||
|
mov ebx, edx
|
|||
|
xchg eax, ebx
|
|||
|
push ecx
|
|||
|
mov ecx, 512
|
|||
|
cmp dword [esp+12], ecx
|
|||
|
jae @f
|
|||
|
mov ecx, [esp+12]
|
|||
|
@@:
|
|||
|
call memmove
|
|||
|
add edx, ecx
|
|||
|
sub [esp+12], ecx
|
|||
|
pop ecx
|
|||
|
jnz .write_loop
|
|||
|
.done:
|
|||
|
mov ebx, edx
|
|||
|
pop edi edi ecx edx
|
|||
|
sub ebx, edx
|
|||
|
mov [edi+28], ebx
|
|||
|
add esp, 20
|
|||
|
mov [esp+16], ebx
|
|||
|
popad
|
|||
|
xor eax, eax
|
|||
|
ret
|
|||
|
.disk_full2:
|
|||
|
mov ebx, edx
|
|||
|
pop edi edi ecx edx
|
|||
|
sub ebx, edx
|
|||
|
mov [edi+28], ebx
|
|||
|
add esp, 20
|
|||
|
mov [esp+16], ebx
|
|||
|
popad
|
|||
|
push ERROR_DISK_FULL
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
.writedir:
|
|||
|
mov edi, eax
|
|||
|
shl edi, 9
|
|||
|
add edi, RAMDISK+31*512
|
|||
|
mov esi, edx
|
|||
|
mov ecx, 32/4
|
|||
|
push ecx
|
|||
|
rep movsd
|
|||
|
mov dword [edi-32], '. '
|
|||
|
mov dword [edi-32+4], ' '
|
|||
|
mov dword [edi-32+8], ' '
|
|||
|
mov byte [edi-32+11], 10h
|
|||
|
mov word [edi-32+26], ax
|
|||
|
mov esi, edx
|
|||
|
pop ecx
|
|||
|
rep movsd
|
|||
|
mov dword [edi-32], '.. '
|
|||
|
mov dword [edi-32+4], ' '
|
|||
|
mov dword [edi-32+8], ' '
|
|||
|
mov byte [edi-32+11], 10h
|
|||
|
mov eax, [esp+16+8]
|
|||
|
mov word [edi-32+26], ax
|
|||
|
xor eax, eax
|
|||
|
mov ecx, (512-32*2)/4
|
|||
|
rep stosd
|
|||
|
pop edi edi ecx edx
|
|||
|
add esp, 20
|
|||
|
popad
|
|||
|
xor eax, eax
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
|
|||
|
.read_symbol:
|
|||
|
or ax, -1
|
|||
|
test esi, esi
|
|||
|
jz .retFFFF
|
|||
|
lodsb
|
|||
|
test al, al
|
|||
|
jnz ansi2uni_char
|
|||
|
xor eax, eax
|
|||
|
xor esi, esi
|
|||
|
.retFFFF:
|
|||
|
ret
|
|||
|
|
|||
|
.read_symbols:
|
|||
|
call .read_symbol
|
|||
|
stosw
|
|||
|
loop .read_symbols
|
|||
|
ret
|
|||
|
|
|||
|
;----------------------------------------------------------------
|
|||
|
;
|
|||
|
; fs_RamdiskWrite - LFN variant for writing to sys floppy
|
|||
|
;
|
|||
|
; esi points to filename
|
|||
|
; ebx pointer to 64-bit number = first wanted byte, 0+
|
|||
|
; may be ebx=0 - start from first byte
|
|||
|
; ecx number of bytes to write, 0+
|
|||
|
; edx mem location to data
|
|||
|
;
|
|||
|
; ret ebx = bytes written (maybe 0)
|
|||
|
; eax = 0 ok write or other = errormsg
|
|||
|
;
|
|||
|
;--------------------------------------------------------------
|
|||
|
@@:
|
|||
|
push ERROR_ACCESS_DENIED
|
|||
|
fs_RamdiskWrite.ret0:
|
|||
|
pop eax
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
|
|||
|
fs_RamdiskWrite:
|
|||
|
cmp byte [esi], 0
|
|||
|
jz @b
|
|||
|
pushad
|
|||
|
call rd_find_lfn
|
|||
|
jnc .found
|
|||
|
popad
|
|||
|
push ERROR_FILE_NOT_FOUND
|
|||
|
jmp .ret0
|
|||
|
.found:
|
|||
|
; must not be directory
|
|||
|
test byte [edi+11], 10h
|
|||
|
jz @f
|
|||
|
popad
|
|||
|
push ERROR_ACCESS_DENIED
|
|||
|
jmp .ret0
|
|||
|
@@:
|
|||
|
; FAT does not support files larger than 4GB
|
|||
|
test ebx, ebx
|
|||
|
jz .l1
|
|||
|
cmp dword [ebx+4], 0
|
|||
|
jz @f
|
|||
|
.eof:
|
|||
|
popad
|
|||
|
push ERROR_END_OF_FILE
|
|||
|
jmp .ret0
|
|||
|
@@:
|
|||
|
mov ebx, [ebx]
|
|||
|
.l1:
|
|||
|
; now edi points to direntry, ebx=start byte to write,
|
|||
|
; ecx=number of bytes to write, edx=data pointer
|
|||
|
call fat_update_datetime
|
|||
|
|
|||
|
; extend file if needed
|
|||
|
add ecx, ebx
|
|||
|
jc .eof ; FAT does not support files larger than 4GB
|
|||
|
push 0 ; return value=0
|
|||
|
cmp ecx, [edi+28]
|
|||
|
jbe .length_ok
|
|||
|
cmp ecx, ebx
|
|||
|
jz .length_ok
|
|||
|
call ramdisk_extend_file
|
|||
|
jnc .length_ok
|
|||
|
; ramdisk_extend_file can return two error codes: FAT table error or disk full.
|
|||
|
; First case is fatal error, in second case we may write some data
|
|||
|
mov [esp], eax
|
|||
|
cmp al, ERROR_DISK_FULL
|
|||
|
jz .disk_full
|
|||
|
pop eax
|
|||
|
mov [esp+28], eax
|
|||
|
popad
|
|||
|
xor ebx, ebx
|
|||
|
ret
|
|||
|
.disk_full:
|
|||
|
; correct number of bytes to write
|
|||
|
mov ecx, [edi+28]
|
|||
|
cmp ecx, ebx
|
|||
|
ja .length_ok
|
|||
|
.ret:
|
|||
|
pop eax
|
|||
|
mov [esp+28], eax ; eax=return value
|
|||
|
sub edx, [esp+20]
|
|||
|
mov [esp+16], edx ; ebx=number of written bytes
|
|||
|
popad
|
|||
|
ret
|
|||
|
.length_ok:
|
|||
|
; now ebx=start pos, ecx=end pos, both lie inside file
|
|||
|
sub ecx, ebx
|
|||
|
jz .ret
|
|||
|
movzx edi, word [edi+26] ; starting cluster
|
|||
|
.write_loop:
|
|||
|
sub ebx, 0x200
|
|||
|
jae .next_cluster
|
|||
|
push ecx
|
|||
|
neg ebx
|
|||
|
cmp ecx, ebx
|
|||
|
jbe @f
|
|||
|
mov ecx, ebx
|
|||
|
@@:
|
|||
|
mov eax, edi
|
|||
|
shl eax, 9
|
|||
|
add eax, RAMDISK+31*512+0x200
|
|||
|
sub eax, ebx
|
|||
|
mov ebx, eax
|
|||
|
mov eax, edx
|
|||
|
call memmove
|
|||
|
xor ebx, ebx
|
|||
|
add edx, ecx
|
|||
|
sub [esp], ecx
|
|||
|
pop ecx
|
|||
|
jz .ret
|
|||
|
.next_cluster:
|
|||
|
movzx edi, word [edi*2+RAMDISK_FAT]
|
|||
|
jmp .write_loop
|
|||
|
|
|||
|
ramdisk_extend_file.zero_size:
|
|||
|
xor eax, eax
|
|||
|
jmp ramdisk_extend_file.start_extend
|
|||
|
|
|||
|
; extends file on ramdisk to given size, new data area is filled by 0
|
|||
|
; in: edi->direntry, ecx=new size
|
|||
|
; out: CF=0 => OK, eax=0
|
|||
|
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
|
|||
|
ramdisk_extend_file:
|
|||
|
push ecx
|
|||
|
; find the last cluster of file
|
|||
|
movzx eax, word [edi+26] ; first cluster
|
|||
|
mov ecx, [edi+28]
|
|||
|
jecxz .zero_size
|
|||
|
@@:
|
|||
|
sub ecx, 0x200
|
|||
|
jbe @f
|
|||
|
mov eax, [eax*2+RAMDISK_FAT]
|
|||
|
and eax, 0xFFF
|
|||
|
jz .fat_err
|
|||
|
cmp eax, 0xFF8
|
|||
|
jb @b
|
|||
|
.fat_err:
|
|||
|
pop ecx
|
|||
|
push ERROR_FAT_TABLE
|
|||
|
pop eax
|
|||
|
stc
|
|||
|
ret
|
|||
|
@@:
|
|||
|
push eax
|
|||
|
mov eax, [eax*2+RAMDISK_FAT]
|
|||
|
and eax, 0xFFF
|
|||
|
cmp eax, 0xFF8
|
|||
|
pop eax
|
|||
|
jb .fat_err
|
|||
|
; set length to full number of sectors and make sure that last sector is zero-padded
|
|||
|
sub [edi+28], ecx
|
|||
|
push eax edi
|
|||
|
mov edi, eax
|
|||
|
shl edi, 9
|
|||
|
lea edi, [edi+RAMDISK+31*512+0x200+ecx]
|
|||
|
neg ecx
|
|||
|
xor eax, eax
|
|||
|
rep stosb
|
|||
|
pop edi eax
|
|||
|
.start_extend:
|
|||
|
pop ecx
|
|||
|
; now do extend
|
|||
|
push edx esi
|
|||
|
mov esi, RAMDISK_FAT+2*2 ; start scan from cluster 2
|
|||
|
mov edx, 2847 ; number of clusters to scan
|
|||
|
.extend_loop:
|
|||
|
cmp [edi+28], ecx
|
|||
|
jae .extend_done
|
|||
|
; add new sector
|
|||
|
push ecx
|
|||
|
mov ecx, edx
|
|||
|
push edi
|
|||
|
mov edi, esi
|
|||
|
jecxz .disk_full
|
|||
|
push eax
|
|||
|
xor eax, eax
|
|||
|
repnz scasw
|
|||
|
pop eax
|
|||
|
jnz .disk_full
|
|||
|
mov word [edi-2], 0xFFF
|
|||
|
mov esi, edi
|
|||
|
mov edx, ecx
|
|||
|
sub edi, RAMDISK_FAT
|
|||
|
shr edi, 1
|
|||
|
dec edi ; now edi=new cluster
|
|||
|
test eax, eax
|
|||
|
jz .first_cluster
|
|||
|
mov [RAMDISK_FAT+eax*2], di
|
|||
|
jmp @f
|
|||
|
.first_cluster:
|
|||
|
pop eax ; eax->direntry
|
|||
|
push eax
|
|||
|
mov [eax+26], di
|
|||
|
@@:
|
|||
|
push edi
|
|||
|
shl edi, 9
|
|||
|
add edi, RAMDISK+31*512
|
|||
|
xor eax, eax
|
|||
|
mov ecx, 512/4
|
|||
|
rep stosd
|
|||
|
pop eax ; eax=new cluster
|
|||
|
pop edi ; edi->direntry
|
|||
|
pop ecx ; ecx=required size
|
|||
|
add dword [edi+28], 0x200
|
|||
|
jmp .extend_loop
|
|||
|
.extend_done:
|
|||
|
mov [edi+28], ecx
|
|||
|
pop esi edx
|
|||
|
xor eax, eax ; CF=0
|
|||
|
ret
|
|||
|
.disk_full:
|
|||
|
pop edi ecx
|
|||
|
pop esi edx
|
|||
|
stc
|
|||
|
push ERROR_DISK_FULL
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
fat_update_datetime:
|
|||
|
call get_time_for_file
|
|||
|
mov [edi+22], ax ; last write time
|
|||
|
call get_date_for_file
|
|||
|
mov [edi+24], ax ; last write date
|
|||
|
mov [edi+18], ax ; last access date
|
|||
|
ret
|
|||
|
|
|||
|
;----------------------------------------------------------------
|
|||
|
;
|
|||
|
; fs_RamdiskSetFileEnd - set end of file on ramdisk
|
|||
|
;
|
|||
|
; esi points to filename
|
|||
|
; ebx points to 64-bit number = new file size
|
|||
|
; ecx ignored (reserved)
|
|||
|
; edx ignored (reserved)
|
|||
|
;
|
|||
|
; ret eax = 0 ok or other = errormsg
|
|||
|
;
|
|||
|
;--------------------------------------------------------------
|
|||
|
fs_RamdiskSetFileEnd:
|
|||
|
cmp byte [esi], 0
|
|||
|
jnz @f
|
|||
|
.access_denied:
|
|||
|
push ERROR_ACCESS_DENIED
|
|||
|
jmp .ret
|
|||
|
@@:
|
|||
|
push edi
|
|||
|
call rd_find_lfn
|
|||
|
jnc @f
|
|||
|
pop edi
|
|||
|
push ERROR_FILE_NOT_FOUND
|
|||
|
.ret:
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
@@:
|
|||
|
; must not be directory
|
|||
|
test byte [edi+11], 10h
|
|||
|
jz @f
|
|||
|
pop edi
|
|||
|
jmp .access_denied
|
|||
|
@@:
|
|||
|
; file size must not exceed 4Gb
|
|||
|
cmp dword [ebx+4], 0
|
|||
|
jz @f
|
|||
|
pop edi
|
|||
|
push ERROR_END_OF_FILE
|
|||
|
jmp .ret
|
|||
|
@@:
|
|||
|
; set file modification date/time to current
|
|||
|
call fat_update_datetime
|
|||
|
mov eax, [ebx]
|
|||
|
cmp eax, [edi+28]
|
|||
|
jb .truncate
|
|||
|
ja .expand
|
|||
|
pop edi
|
|||
|
xor eax, eax
|
|||
|
ret
|
|||
|
.expand:
|
|||
|
push ecx
|
|||
|
mov ecx, eax
|
|||
|
call ramdisk_extend_file
|
|||
|
pop ecx
|
|||
|
pop edi
|
|||
|
ret
|
|||
|
.truncate:
|
|||
|
mov [edi+28], eax
|
|||
|
push ecx
|
|||
|
movzx ecx, word [edi+26]
|
|||
|
test eax, eax
|
|||
|
jz .zero_size
|
|||
|
; find new last sector
|
|||
|
@@:
|
|||
|
sub eax, 0x200
|
|||
|
jbe @f
|
|||
|
movzx ecx, word [RAMDISK_FAT+ecx*2]
|
|||
|
jmp @b
|
|||
|
@@:
|
|||
|
; zero data at the end of last sector
|
|||
|
push ecx
|
|||
|
mov edi, ecx
|
|||
|
shl edi, 9
|
|||
|
lea edi, [edi+RAMDISK+31*512+eax+0x200]
|
|||
|
mov ecx, eax
|
|||
|
neg ecx
|
|||
|
xor eax, eax
|
|||
|
rep stosb
|
|||
|
pop ecx
|
|||
|
; terminate FAT chain
|
|||
|
lea ecx, [RAMDISK_FAT+ecx+ecx]
|
|||
|
push dword [ecx]
|
|||
|
mov word [ecx], 0xFFF
|
|||
|
pop ecx
|
|||
|
and ecx, 0xFFF
|
|||
|
jmp .delete
|
|||
|
.zero_size:
|
|||
|
and word [edi+26], 0
|
|||
|
.delete:
|
|||
|
; delete FAT chain starting with ecx
|
|||
|
; mark all clusters as free
|
|||
|
cmp ecx, 0xFF8
|
|||
|
jae .deleted
|
|||
|
lea ecx, [RAMDISK_FAT+ecx+ecx]
|
|||
|
push dword [ecx]
|
|||
|
and word [ecx], 0
|
|||
|
pop ecx
|
|||
|
and ecx, 0xFFF
|
|||
|
jmp .delete
|
|||
|
.deleted:
|
|||
|
pop ecx
|
|||
|
pop edi
|
|||
|
xor eax, eax
|
|||
|
ret
|
|||
|
|
|||
|
fs_RamdiskGetFileInfo:
|
|||
|
cmp byte [esi], 0
|
|||
|
jnz @f
|
|||
|
mov eax, 2 ; unsupported
|
|||
|
ret
|
|||
|
@@:
|
|||
|
push edi
|
|||
|
call rd_find_lfn
|
|||
|
fs_GetFileInfo_finish:
|
|||
|
jnc @f
|
|||
|
pop edi
|
|||
|
mov eax, ERROR_FILE_NOT_FOUND
|
|||
|
ret
|
|||
|
@@:
|
|||
|
push esi ebp
|
|||
|
xor ebp, ebp
|
|||
|
mov esi, edx
|
|||
|
and dword [esi+4], 0
|
|||
|
call fat_entry_to_bdfe2
|
|||
|
pop ebp esi
|
|||
|
pop edi
|
|||
|
xor eax, eax
|
|||
|
ret
|
|||
|
|
|||
|
fs_RamdiskSetFileInfo:
|
|||
|
cmp byte [esi], 0
|
|||
|
jnz @f
|
|||
|
mov eax, 2 ; unsupported
|
|||
|
ret
|
|||
|
@@:
|
|||
|
push edi
|
|||
|
call rd_find_lfn
|
|||
|
jnc @f
|
|||
|
pop edi
|
|||
|
mov eax, ERROR_FILE_NOT_FOUND
|
|||
|
ret
|
|||
|
@@:
|
|||
|
call bdfe_to_fat_entry
|
|||
|
pop edi
|
|||
|
xor eax, eax
|
|||
|
ret
|
|||
|
|
|||
|
;----------------------------------------------------------------
|
|||
|
;
|
|||
|
; fs_RamdiskDelete - delete file or empty folder from ramdisk
|
|||
|
;
|
|||
|
; esi points to filename
|
|||
|
;
|
|||
|
; ret eax = 0 ok or other = errormsg
|
|||
|
;
|
|||
|
;--------------------------------------------------------------
|
|||
|
fs_RamdiskDelete:
|
|||
|
cmp byte [esi], 0
|
|||
|
jnz @f
|
|||
|
; cannot delete root!
|
|||
|
.access_denied:
|
|||
|
push ERROR_ACCESS_DENIED
|
|||
|
.pop_ret:
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
@@:
|
|||
|
and [rd_prev_sector], 0
|
|||
|
and [rd_prev_prev_sector], 0
|
|||
|
push edi
|
|||
|
call rd_find_lfn
|
|||
|
jnc .found
|
|||
|
pop edi
|
|||
|
push ERROR_FILE_NOT_FOUND
|
|||
|
jmp .pop_ret
|
|||
|
.found:
|
|||
|
cmp dword [edi], '. '
|
|||
|
jz .access_denied2
|
|||
|
cmp dword [edi], '.. '
|
|||
|
jz .access_denied2
|
|||
|
test byte [edi+11], 10h
|
|||
|
jz .dodel
|
|||
|
; we can delete only empty folders!
|
|||
|
movzx eax, word [edi+26]
|
|||
|
push ebx
|
|||
|
mov ebx, eax
|
|||
|
shl ebx, 9
|
|||
|
add ebx, RAMDISK + 31*0x200 + 2*0x20
|
|||
|
.checkempty:
|
|||
|
cmp byte [ebx], 0
|
|||
|
jz .empty
|
|||
|
cmp byte [ebx], 0xE5
|
|||
|
jnz .notempty
|
|||
|
add ebx, 0x20
|
|||
|
test ebx, 0x1FF
|
|||
|
jnz .checkempty
|
|||
|
movzx eax, word [RAMDISK_FAT + eax*2]
|
|||
|
test eax, eax
|
|||
|
jz .empty
|
|||
|
mov ebx, eax
|
|||
|
shl ebx, 9
|
|||
|
add ebx, RAMDISK + 31*0x200
|
|||
|
jmp .checkempty
|
|||
|
.notempty:
|
|||
|
pop ebx
|
|||
|
.access_denied2:
|
|||
|
pop edi
|
|||
|
jmp .access_denied
|
|||
|
.empty:
|
|||
|
pop ebx
|
|||
|
.dodel:
|
|||
|
movzx eax, word [edi+26]
|
|||
|
; delete folder entry
|
|||
|
mov byte [edi], 0xE5
|
|||
|
; delete LFN (if present)
|
|||
|
.lfndel:
|
|||
|
test edi, 0x1FF
|
|||
|
jnz @f
|
|||
|
cmp [rd_prev_sector], 0
|
|||
|
jz @f
|
|||
|
cmp [rd_prev_sector], -1
|
|||
|
jz .lfndone
|
|||
|
mov edi, [rd_prev_sector]
|
|||
|
push [rd_prev_prev_sector]
|
|||
|
pop [rd_prev_sector]
|
|||
|
or [rd_prev_prev_sector], -1
|
|||
|
shl edi, 9
|
|||
|
add edi, RAMDISK + 31*0x200 + 0x200
|
|||
|
@@:
|
|||
|
sub edi, 0x20
|
|||
|
cmp byte [edi], 0xE5
|
|||
|
jz .lfndone
|
|||
|
cmp byte [edi+11], 0xF
|
|||
|
jnz .lfndone
|
|||
|
mov byte [edi], 0xE5
|
|||
|
jmp .lfndel
|
|||
|
.lfndone:
|
|||
|
; delete FAT chain
|
|||
|
test eax, eax
|
|||
|
jz .done
|
|||
|
lea eax, [RAMDISK_FAT + eax*2]
|
|||
|
push dword [eax]
|
|||
|
and word [eax], 0
|
|||
|
pop eax
|
|||
|
and eax, 0xFFF
|
|||
|
jmp .lfndone
|
|||
|
.done:
|
|||
|
pop edi
|
|||
|
xor eax, eax
|
|||
|
ret
|
|||
|
|
|||
|
; \end{diamond}
|