This library contains wrapper macros which encapsulate WinAPI calls for most typical file operations in 32bit Windows . See also equivalent homonymous macroinstructions in winf64.htm, linf32.htm, linf64.htm.
| File Access method | Open | Data transfer | Close |
|---|---|---|---|
| read file at once | - | FileLoad | FileClose |
| write file at once | - | FileStore | - |
| standard read | FileOpen | FileRead | FileClose |
| standard write | FileCreate | FileWrite, FileWriteLn, FileWrite$ | FileClose |
| standard write at the end of file | FileAppend | FileWrite, FileWriteLn, FileWrite$ | FileClose |
| memory mapped read | FileMapOpen | - | FileClose |
| memory mapped write | FileMapCreate | - | FileClose |
| buffered read | FileStreamOpen | FileStreamReadByte, FileStreamRead, FileStreamReadLn | FileClose |
| buffered write | FileStreamCreate | FileStreamWriteByte, FileStreamWriteWord, FileStreamWriteDword, FileStreamWrite, FileStreamWriteLn, FileStreamWrite$ | FileClose |
| buffered write at end of file | FileStreamAppend | FileStreamWriteByte, FileStreamWriteWord, FileStreamWriteDword, FileStreamWrite, FileStreamWriteLn, FileStreamWrite$ | FileClose |
| append to file | - | FileEnclose, FileEncloseLn, FileEnclose$ | - |
| special functions | FileReset | FileAssign, FileExists?, FileNameParse, FileMove, FileMkDir, FileEach | FileDelete |
Macros return the results in registers, usually EAX. Other registers do not change. CF is set when error occurs, ZF is set at the end of file, DF must be always reset. Other flags are undefined.
Association of the FILE object with the name of file is provided separately, using the macro FileAssign. File must be assigned before opening.
Macro names suffixed with ~Ln write CR+LF characters after the data. Macro names suffixed with ~$ expect NULL-terminated input data.
Acces methods at once, stream, memory-map allocate dynamic virtual memory. It will be freed in FileClose.
| Access method | Virtual memory | |
|---|---|---|
| reserved | comitted | |
| At once load | filesize | filesize |
| At once store | none | none |
| Standard | none | none |
| MemoryMapped | filesize | pagesize |
| Streamed | buffersize | buffersize |
File access method at once loads entire file content into comitted memory, so it is suitable for small files only. The loaded/stored file doesn't need explicit opening nor closing.
This access method is equivalent to PHP functions file_get_contents, file_put_contents.
Access method enclose opens the file at its end for writing, appends the data and closes file in one operation.
Standard read/write methods only encapsulate API functions read/write and they can process files of any size. Example:
Memory mapped file access reserves memory for the entire file contents virtually loaded to memory.
Streamed (buffered) file access method allocates its own memory buffer to accelerate reading/writing of small pieces of data. This method is also suitable for processing text files line by line. Example:
Common limitations: This library cannot be used if special requirements are required, such as overlapped file access, other than normal file attributes, nonstandard share disposition, files bigger than 2 GB, filename longer than 260 characters.
Runtime procedures defined in this library use macros WinAPI, Dispatch, status32.htm.
winf32 HEAD INCLUDEHEAD1 winsfile.htm, wins.htm, winscon.htm, winapi.htm, status32.htm, cpuext.htm
FILE STRUC .Ptr DD DWORD ; Pointer to the file content in memory-mapped|buffered data. .Top DD DWORD ; Pointer to the end of the memory-mapped|buffered data. .BufPtr DD DWORD ; Pointer to the memory-map|allocated buffer. .BufSize DD DWORD ; Size of memory map|buffer. .Pos DD DWORD ; Zero based offset of the file position. .Size DD DWORD ; File size in bytes. .Handle DD DWORD ; Handle to the opened file. Initialize with INVALID_HANDLE_VALUE = -1. .MapHandle DD DWORD ; Handle to the file mapping. Initialize with INVALID_HANDLE_VALUE = -1. .Status DD DWORD ; File status flags, see FileStatusEnc. .NameOffs DD DWORD ; Offset of the filename without path inside the .Name. Zero if no path in .Name. .ExtOffs DD DWORD ; Offset of the file extension inside the .Name. .Name D MAX_PATH_SIZE * U ; Zero terminated WIDE|ANSI file name. ENDSTRUC FILE
FILE.Status.fileStFound EQU 0x00000010 ; File was once succesfully opened. fileStAppend EQU 0x00100000 ; Created file should move its pointer to the end. fileStStdIO EQU 0x00200000 ; FILE.Handle is standard input|output. fileStAllocated EQU 0x00400000 ; FILE.BufPtr is pointer to the allocated memory. fileStUnicode EQU 0x00800000 ; FILE.Name is in WIDE characters. fileStMapCreated EQU 0x01000000 ; FILE.MapHandle is valid for writing. fileStMapOpened EQU 0x02000000 ; FILE.MapHandle is valid for reading. fileStMapped EQU 0x04000000 ; FILE.Ptr is pointer to the mapped memory. fileStCreated EQU 0x10000000 ; FILE.Handle is valid for writing. fileStOpened EQU 0x20000000 ; FILE.Handle is valid for reading.
%^UNICODE at macro invocation
but you may want to set this parameter to 0 even if %UNICODE is enabled and vice versa.
FileNameParse %MACRO FileNamePtr,Size=-1, Unicode=%^UNICODE
PUSHD %Size,%FileNamePtr
%IF %Unicode
CALL FileNameParseW@RT:
FileNameParseW@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV ESI,[%Param1] ; %FileNamePtr.
MOV EDX,[%Param2] ; %Size.
SUB ECX,ECX
TEST EDX
JS .UnlimitedSize:
ADD EDX,ESI ; End of input string.
.UnlimitedSize:
MOV [%ReturnEAX],ECX
MOV [%ReturnECX],ECX
MOV [%ReturnEDX],ECX
.NextChar:
CMP ESI,EDX
JNB .E0:
LODSW
Dispatch AX,58,92,47,46,0 ; colon, backslash, slash, dot, NULL
; Ordinary character.
LEA EAX,[ESI-2]
CMP [%ReturnEAX],ECX
JNZ .NextChar:
MOV [%ReturnEAX],EAX
JMP .NextChar:
.46: ; dot .
LEA EAX,[ESI-2]
MOV [%ReturnECX],EAX
CMP [%ReturnEAX],ECX
JNE .NextChar:
MOV [%ReturnEAX],EAX
JMP .NextChar:
.47: ; Colon, slash, backslash.
.58:
.92: MOV [%ReturnEAX],ESI
MOV [%ReturnECX],ECX
JMP .NextChar:
.0: DEC ESI ; Unichar NULL.
DEC ESI
.E0:MOV [%ReturnEDX],ESI
CMP [%ReturnECX],ECX
JNE .E1:
MOV [%ReturnECX],ESI
.E1:CMP [%ReturnEAX],ECX
JNE .E2:
MOV EAX,[%ReturnECX]
MOV [%ReturnEAX],EAX
.E2:POPAD
RET 8
ENDPROC1 FileNameParseW@RT:
%ELSE ; ANSI variant.
CALL FileNameParseA@RT:
FileNameParseA@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV ESI,[%Param1] ; %FileNamePtr.
MOV EDX,[%Param2] ; %Size.
SUB ECX,ECX
TEST EDX
JS .UnlimitedSize:
ADD EDX,ESI ; End of input string.
.UnlimitedSize:
MOV [%ReturnEAX],ECX
MOV [%ReturnECX],ECX
MOV [%ReturnEDX],ECX
.NextChar:
CMP ESI,EDX
JNB .E0:
LODSB
Dispatch AL,58,92,47,46,0 ; colon, backslash, slash, dot, NULL.
; Ordinary character
LEA EAX,[ESI-1]
CMP [%ReturnEAX],ECX
JNZ .NextChar:
MOV [%ReturnEAX],EAX
JMP .NextChar:
.46: ; dot .
LEA EAX,[ESI-1]
MOV [%ReturnECX],EAX
CMP [%ReturnEAX],ECX
JNE .NextChar:
MOV [%ReturnEAX],EAX
JMP .NextChar:
.47: ; colon, slash, backslash
.58:
.92: MOV [%ReturnEAX],ESI
MOV [%ReturnECX],ECX
JMP .NextChar:
.0: DEC ESI ; Byte NULL.
.E0:MOV [%ReturnEDX],ESI
CMP [%ReturnECX],ECX
JNE .E1:
MOV [%ReturnECX],ESI
.E1:CMP [%ReturnEAX],ECX
JNE .E2:
MOV EAX,[%ReturnECX]
MOV [%ReturnEAX],EAX
.E2:POPAD
RET 8
ENDPROC1 FileNameParseA@RT:
%ENDIF ; %Unicode
%ENDMACRO FileNameParse
theFile.Name member.
EUROASM UNICODE=
option at macro invocation,
but you may want to set this parameter to 0 even if UNICODE is globally enabled, and vice versa..Name, .NameOffs, .ExtOffs, .Status:fileStUnicode of theFile are set.SIZE# FILE.Name, i.e. MAX_PATH_SIZE=260 characters.
FileAssign %MACRO theFile,Name$1,Name$2,,, Size=-1, Unicode=%^UNICODE
%IF %#<2 ; >
%ERROR ID=5941, 'File name missing in macro "FileAssign".'
%EXITMACRO FileAssign
%ENDIF
PUSHD 0 ; Mark the end of arguments.
ArgNr %FOR %#..2,STEP=-1
PUSHD %*{%ArgNr}
%ENDFOR ArgNr
PUSHD %Size, %theFile, ESP
ADDD [ESP],4*(%#+2)
%IF %Unicode
CALL FileAssignW@RT:
FileAssignW@RT: PROC1 ; Wide variant.
PUSHAD
MOV EBX,[ESP+40] ; %theFile
LEA EBP,[ESP+48] ; %Name$1
LEA EDI,[EBX+FILE.Name]
SetSt [EBX+FILE.Status],fileStUnicode
LEA EDX,[EDI+MAX_PATH_SIZE-2]
.10:XCHG EBP,ESI
LODSD ; Offset of source string.
MOV EBP,EAX
XCHG ESI,EBP
TEST EAX ; No more macro arguments (zero marker)?
JZ .50:
MOV ECX,[ESP+44] ; %Size.
SAR ECX,1 ; Size in unichars.
.20:LODSW
CMP AX,0
JE .10:
CMP EDI,EDX
JNB .40:
STOSW
LOOP .20:
JMP .10:
.40:SUB EAX,EAX
STC ; Overflow.
.50:MOV ECX,EDI
STOSW
LEA EDX,[EBX+FILE.Name]
PUSHFD
SUB ECX,EDX
FileNameParse EDX,Size=ECX,Unicode=1
LEA EDX,[EBX+FILE.Name]
SUB EAX,EDX
SUB ECX,EDX
MOV [EBX+FILE.NameOffs],EAX
MOV [EBX+FILE.ExtOffs],ECX
POPFD
POPAD
RET
ENDPROC1 FileAssignW@RT:
%ELSE ; ANSI.
CALL FileAssignA@RT:
FileAssignA@RT: PROC1 ; ANSI variant.
PUSHAD
MOV EBX,[ESP+40] ; %theFile
LEA EBP,[ESP+48] ; %Name$1
LEA EDI,[EBX+FILE.Name]
RstSt [EBX+FILE.Status],fileStUnicode
LEA EDX,[EDI+MAX_PATH_SIZE]
.10:XCHG EBP,ESI
LODSD ; Offset of source string.
MOV EBP,EAX
XCHG ESI,EBP
TEST EAX
JZ .50:
MOV ECX,[ESP+44] ; %Size.
.20:LODSB
CMP AL,0
JE .10:
CMP EDI,EDX
JNB .40:
STOSB
LOOP .20:
JMP .10:
.40:SUB EAX,EAX
STC ; Overflow.
.50:MOV ECX,EDI
STOSB
LEA EDX,[EBX+FILE.Name]
PUSHFD
SUB ECX,EDX
FileNameParse EDX,Size=ECX,Unicode=0
LEA EDX,[EBX+FILE.Name]
SUB EAX,EDX
SUB ECX,EDX
MOV [EBX+FILE.NameOffs],EAX
MOV [EBX+FILE.ExtOffs],ECX
POPFD
POPAD
RET
ENDPROC1 FileAssignA@RT:
%ENDIF
POP ESP
%ENDMACRO FileAssign
* ? are allowed in the file name.
FileExists? %MACRO theFile
PUSHD %theFile
CALL FileExists?@RT:
FileExists?@RT: PROC1
IMPORT FindFirstFileA,FindFirstFileW
PUSHAD
MOV EBP,ESP
MOV EBX,[EBP+36] ; theFile
LEA ESI,[EBX+FILE.Name]
SUB ESP,SIZE# WIN32_FIND_DATAW
MOV EDI,ESP
MOV EAX,FindFirstFileW: ; WinAPI function thunk.
JSt [EBX+FILE.Status],fileStUnicode,.20
MOV EAX,FindFirstFileA: ; WinAPI function thunk.
.20:WinAPI EAX,ESI,EDI ; FindFirstFile.
.30:CMP EAX,INVALID_HANDLE_VALUE
STC
JE .90
WinAPI FindClose,EAX
TEST [EDI+WIN32_FIND_DATAW.FileAttributes],FILE_ATTRIBUTE_DIRECTORY
.90:MOV ESP,EBP
POPAD
RET 4
ENDPROC1 FileExists?@RT:
%ENDMACRO FileExists?
FileMkDir %MACRO theFile
PUSHD %theFile
CALL FileMkDir@RT:
FileMkDir@RT: PROC1
PUSHAD
MOV EBP,ESP
SUB ESP,SIZE#WIN32_FIND_DATAW + 4
%FileMkDirEntry %SET EBP-4
MOV [%FileMkDirEntry],ESP,DATA=DWORD
SUB ESP,2*MAX_PATH_SIZE
MOV EBX,[EBP+36] ; %theFile
MOV EDI,ESP ; directory name copy
LEA ESI,[EBX+FILE.Name]
MOV CX,'\'
MOVW [ESI+SIZE#FILE.Name-2],0
JSt [EBX+FILE.Status],fileStUnicode,.50:
; ANSI variant.
LODSB
CMP AL,0
JE .95:
CMP AL,CL
JNE .30:
CMP [ESI],CL
JNE .30:
STOSB ; \\server\share\dir\file
LODSB
.10:STOSB
LODSB
CMP AL,0
JE .95:
CMP AL,CL
JNE .10:
.20:STOSB
LODSB
CMP AL,0
JE .95:
CMP AL,CL
JNE .20:
.30:STOSB
LODSB
CMP AL,0
JE .95:
CMP AL,CL
JNE .30:
CMPB [EDI-1],':' ; D:\dir\file
JE .30:
SUB EAX,EAX
STOSB ; Temporary terminate folder name.
MOV EAX,ESP
WinAPI FindFirstFileA,EAX,[%FileMkDirEntry]
CMP EAX,INVALID_HANDLE_VALUE
JE .35:
WinAPI FindClose,EAX
MOV EDX,[%FileMkDirEntry]
JSt [EDX+WIN32_FIND_DATAW.FileAttributes],FILE_ATTRIBUTE_DIRECTORY,.40:
.35:MOV EAX,ESP
WinAPI CreateDirectoryA,EAX,0
TEST EAX
JNZ .40:
WinAPI GetLastError
STC
JMP .99:
.40:DEC EDI ; Remove temporary zero-termination.
MOV AL,'\'
MOV ECX,EAX
JMP .30:
.50: ; WIDE variant.
LODSW
CMP AX,0
JE .95:
CMP AX,CX
JNE .80:
CMP [ESI],CX
JNE .80:
STOSW ; \\server\share\dir\file
LODSW
.60:STOSW
LODSW
CMP AX,0
JE .95:
CMP AX,CX
JNE .60:
.70:STOSW
LODSW
CMP AX,0
JE .95:
CMP AX,CX
JNE .70:
.80:STOSW
LODSW
CMP AX,0
JE .95:
CMP AX,CX
JNE .80:
CMPW [EDI-2],':' ; D:\dir\file
JE .80:
SUB EAX,EAX
STOSW ; Temporary terminate folder name.
MOV EAX,ESP
WinAPI FindFirstFileW,EAX,[%FileMkDirEntry]
CMP EAX,INVALID_HANDLE_VALUE
JE .85:
WinAPI FindClose,EAX
MOV EDX,[%FileMkDirEntry]
JSt [EDX+WIN32_FIND_DATAW.FileAttributes],FILE_ATTRIBUTE_DIRECTORY,.90:
.85:MOV EAX,ESP
WinAPI CreateDirectoryW,EAX,0
TEST EAX
JNZ .90:
WinAPI GetLastError
STC
JMP .99:
.90:DEC EDI ; Remove temporary zero-termination.
DEC EDI
MOV AX,'\'
MOV ECX,EAX
JMP .80:
.95:SUB EAX,EAX
.99:MOV [%ReturnEAX],EAX
MOV ESP,EBP
POPAD
RET 4
ENDPROC1 FileMkDir@RT:
%ENDMACRO FileMkDir
FileFlush %MACRO theFile
PUSHD %theFile
CALL FileFlush@RT:
FileFlush@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
MOV EAX,0xE0070004 ; File is not opened.
JNSt [EBX+FILE.Status],fileStAllocated,.ErrorEAX:
JNSt [EBX+FILE.Status],fileStCreated, .ErrorEAX:
MOV EDI,[EBX+FILE.Ptr]
MOV ESI,[EBX+FILE.BufPtr]
MOV [EBX+FILE.Ptr],ESI
SUB EDI,ESI
PUSH EDX
MOV EDX,ESP
WinAPI WriteFile,[EBX+FILE.Handle],ESI,EDI,EDX,0
POP EDX ; written size
TEST EAX
JZ .EndWithLastError:
CMP EDI,EDX
JE .90:
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX:
STC
MOV [%ReturnEAX],EAX
.90:POPAD
RET 4
ENDPROC1 FileFlush@RT:
%ENDMACRO FileFlush
FileClose %MACRO theFile1
ArgNr %FOR 1..%#
PUSHD %*{%ArgNr}
CALL FileClose@RT:
%ENDFOR ArgNr
FileClose@RT: PROC1
PUSHAD
MOV EBX,[ESP+36] ; theFile
SUB ESI,ESI
MOV EDI,INVALID_HANDLE_VALUE
JNSt [EBX+FILE.Status],fileStAllocated,.10:
FileFlush EBX
WinAPI GlobalFree,[EBX+FILE.BufPtr]
RstSt [EBX+FILE.Status],fileStAllocated
.10: MOV [EBX+FILE.BufPtr],ESI
MOV [EBX+FILE.BufSize],ESI
JNSt [EBX+FILE.Status],fileStMapped,.20:
WinAPI UnmapViewOfFile,[EBX+FILE.Ptr]
RstSt [EBX+FILE.Status],fileStMapped
.20: MOV [EBX+FILE.Ptr],ESI
MOV [EBX+FILE.Top],ESI
JNSt [EBX+FILE.Status],fileStMapOpened|fileStMapCreated,.30:
WinAPI CloseHandle,[EBX+FILE.MapHandle]
.30: RstSt [EBX+FILE.Status],fileStMapOpened|fileStMapCreated
MOV [EBX+FILE.MapHandle],EDI
JNSt [EBX+FILE.Status],fileStOpened|fileStCreated,.40:
JSt [EBX+FILE.Status],fileStStdIO,.40
WinAPI CloseHandle,[EBX+FILE.Handle]
.40: RstSt [EBX+FILE.Status],fileStOpened|fileStCreated|fileStAppend
MOV [EBX+FILE.Handle],EDI
POPAD
RET 4
ENDPROC1 FileClose@RT:
%ENDMACRO FileClose
FileMove %MACRO SourceFile, DestinationFile
PUSHD %DestinationFile, %SourceFile
CALL FileMove@RT:
FileMove@RT: PROC1
IMPORT MoveFileExA,MoveFileExW
PUSHAD
MOV ESI,[ESP+36] ; SourceFile
MOV EDI,[ESP+40] ; DestinationFile
MOV EAX,[ESI+FILE.Status]
MOV EDX,[EDI+FILE.Status]
MOV EBX,fileStUnicode
AND EAX,EBX
AND EDX,EBX
CMP EAX,EDX
MOV EAX,0xC008007B ; Error 123: invalid filename.
STC
JNE .ErrorEAX: ; Error - different width of strings.
FileClose ESI,EDI
FileMkDir EDI
JC .ErrorEAX:
LEA ESI,[ESI+FILE.Name]
LEA EDI,[EDI+FILE.Name]
MOV EAX,MoveFileExW:
JSt EDX,fileStUnicode,.30:
MOV EAX,MoveFileExA:
.30: WinAPI EAX,ESI,EDI,MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED
TEST EAX
MOV EAX,0
JNZ .OK:
WinAPI GetLastError
.ErrorEAX:
STC
.OK: MOV [ESP+28],EAX ; ReturnEAX
POPAD
RET 8
ENDPROC1 FileMove@RT:
%ENDMACRO FileMove
FileDelete %MACRO theFile1
ArgNr %FOR 1..%#
PUSHD %*{%ArgNr}
CALL FileDelete@RT:
%ENDFOR ArgNr
FileDelete@RT: PROC1
IMPORT DeleteFileA,DeleteFileW
PUSHAD
MOV EBX,[ESP+36] ; theFile
FileClose EBX
LEA ESI,[EBX+FILE.Name]
MOV EAX,DeleteFileW:
JSt [EBX+FILE.Status],fileStUnicode,.30:
MOV EAX,DeleteFileA:
.30: WinAPI EAX,ESI
TEST EAX
JNZ .OK:
WinAPI GetLastError
CMP EAX,2 ; ERROR_FILE_NOT_FOUND
JE .OK:
CMP EAX,3 ; ERROR_PATH_NOT_FOUND
JE .OK:
STC
JMPS .90:
.OK: XOR EAX,EAX
.90: MOV [ESP+28],EAX ; ReturnEAX
POPAD
RET 4
ENDPROC1 FileDelete@RT:
%ENDMACRO FileDelete
FILE.Name is replaced
with the file found in directory. The file is not open.
WinAPI FindClose,EDX before terminating.
FileEach %MACRO theFile, CallbackProc
PUSHD %CallbackProc, %theFile
CALL FileEach@RT:
FileEach@RT: PROC1
IMPORT FindFirstFileA,FindFirstFileW,FindNextFileA,FindNextFileW
PUSHAD
MOV EBP,ESP
SUB ESP,SIZE#WIN32_FIND_DATAW + 8
%FileEachSearchRec %SET EBP-SIZE#WIN32_FIND_DATAW
%FileEachFindHandle %SET EBP-SIZE#WIN32_FIND_DATAW-4
%FileEachNamePtr %SET EBP-SIZE#WIN32_FIND_DATAW-8
MOV EBX,[%Param1]
MOVD [%ReturnEAX],0
LEA ESI,[%FileEachSearchRec]
LEA ECX,[EBX+FILE.Name]
MOV EAX,FindFirstFileW:
JSt [EBX+FILE.Status],fileStUnicode,.20:
MOV EAX,FindFirstFileA:
.20: WinAPI EAX,ECX,ESI ; FindFirstFile.
MOV [%FileEachFindHandle],EAX
CMP EAX,INVALID_HANDLE_VALUE
JE .90:
.30: LEA EDI,[EBX+FILE.Name]
LEA ESI,[EDI+MAX_PATH_SIZE]
JSt [EBX+FILE.Status],fileStUnicode,.50:
FileNameParse EDI,Size=MAX_PATH_SIZE,Unicode=0
SUB ESI,EAX
MOV ECX,ESI
JNA .70:
MOV EDI,EAX
LEA ESI,[%FileEachSearchRec]
MOV [%FileEachNamePtr],EAX
LEA ESI,[ESI+WIN32_FIND_DATAA.FileName]
.40: LODSB
STOSB
CMP AL,0
LOOPNE .40:
LEA EDI,[EBX+FILE.Name]
FileNameParse EDI,Size=MAX_PATH_SIZE,Unicode=0
SUB EAX,EDI
MOV [EBX+FILE.NameOffs],EAX
SUB ECX,EDI
MOV [EBX+FILE.ExtOffs],ECX
JMP .70:
.50: LEA ESI,[EDI+2*MAX_PATH_SIZE]
FileNameParse EDI,Size=2*MAX_PATH_SIZE,Unicode=1
SUB ESI,EAX
MOV ECX,ESI
JNA .70:
MOV EDI,EAX
LEA ESI,[%FileEachSearchRec]
MOV [%FileEachNamePtr],EAX
LEA ESI,[ESI+WIN32_FIND_DATAW.FileName]
.60: LODSW
STOSW
CMP AX,0
LOOPNE .60:
LEA EDI,[EBX+FILE.Name]
FileNameParse EDI,Size=2*MAX_PATH_SIZE,Unicode=1
SUB EAX,EDI
MOV [EBX+FILE.NameOffs],EAX
SUB ECX,EDI
MOV [EBX+FILE.ExtOffs],ECX
.70: LEA EDI,[%FileEachSearchRec]
MOV ESI,[%FileEachNamePtr]
MOV EDX,[%FileEachFindHandle]
MOV EBX,[%Param1]
MOV EAX,[%Param2]
PUSH EBP
MOV EBP,[%ReturnEBP]
CALL EAX ; CallbackProc
POP EBP
MOV [%ReturnEAX],EAX
MOV EDI,[%FileEachFindHandle]
JC .90: ; CF from CallbackProc
MOV EBX,[%Param1]
MOV EAX,FindNextFileW:
JSt [EBX+FILE.Status],fileStUnicode,.80:
MOV EAX,FindNextFileA:
.80: LEA ESI,[%FileEachSearchRec]
WinAPI EAX,EDI,ESI ; FindNextFile
TEST EAX
JNZ .30:
.90: WinAPI FindClose,[%FileEachFindHandle]
MOV ESP,EBP
POPAD
RET 8
ENDPROC1 FileEach@RT:
%ENDMACRO FileEach
FileLoad %MACRO theFile
PUSHD %theFile
CALL FileLoad@RT:
FileLoad@RT: PROC1
IMPORT CreateFileA,CreateFileW
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
LEA EDX,[EBX+FILE.Name]
SUB ESI,ESI
MOV EDI,INVALID_HANDLE_VALUE
MOV [EBX+FILE.Ptr],ESI
MOV [EBX+FILE.Top],ESI
MOV [EBX+FILE.BufPtr],ESI
MOV [EBX+FILE.BufSize],ESI
MOV [EBX+FILE.Pos],ESI
MOV [EBX+FILE.Size],ESI
MOV EAX,CreateFileW:
JSt [EBX+FILE.Status],fileStUnicode,.10:
MOV EAX,CreateFileA:
.10:WinAPI EAX,EDX,GENERIC_READ,FILE_SHARE_READ,ESI, \
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,ESI
MOV [EBX+FILE.Handle],EAX
CMP EAX,EDI
JE .EndWithLastError:
SetSt [EBX+FILE.Status],fileStOpened
WinAPI GetFileSize,EAX,ESI
CMP EAX,EDI
JE .EndWithLastError:
MOV [EBX+FILE.Size],EAX
MOV [EBX+FILE.Top],EAX
MOV [EBX+FILE.BufSize],EAX
MOV [%ReturnEAX],EAX
WinAPI GlobalAlloc,GMEM_FIXED,EAX
MOV [EBX+FILE.Ptr],EAX
ADD [EBX+FILE.Top],EAX
MOV [EBX+FILE.BufPtr],EAX
CMP EAX,ESI
JE .EndWithLastError:
SetSt [EBX+FILE.Status],fileStAllocated
MOV [%ReturnESI],EAX
PUSH ECX
MOV ECX,ESP
WinAPI ReadFile,[EBX+FILE.Handle],EAX,[EBX+FILE.Size],ECX,ESI
POP ECX
ADD [EBX+FILE.Pos],ECX
TEST EAX
JZ .EndWithLastError:
MOV EAX,[EBX+FILE.Size]
CMP EAX,ECX
JE .EndWithEAX
MOV EAX,0xE0070026
JMP .ErrorEAX
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX: STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
PUSHFD
JNSt [EBX+FILE.Status],fileStOpened,.90:
WinAPI CloseHandle,[EBX+FILE.Handle]
.90: RstSt [EBX+FILE.Status],fileStOpened
MOV [EBX+FILE.Handle],EDI
POPFD
POPAD
RET 4
ENDPROC1 FileLoad@RT:
%ENDMACRO FileLoad
FileStore %MACRO theFile,DataPtr,DataSize
PUSHD %DataSize,%DataPtr,%theFile
CALL FileStore@RT:
FileStore@RT: PROC1
IMPORT CreateFileA,CreateFileW
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
MOV EAX,[%Param2]
MOV ECX,[%Param3]
MOV [EBX+FILE.Ptr],EAX
MOV [EBX+FILE.Top],EAX
MOV [EBX+FILE.Size],ECX
ADD [EBX+FILE.Top],ECX
MOV [%ReturnEAX],ECX
SUB ESI,ESI
MOV EDI,INVALID_HANDLE_VALUE
MOV [EBX+FILE.Pos],ESI
LEA EDX,[EBX+FILE.Name]
MOV EAX,CreateFileW:
JSt [EBX+FILE.Status],fileStUnicode,.10:
MOV EAX,CreateFileA:
.10:WinAPI EAX,EDX,GENERIC_WRITE,FILE_SHARE_READ,ESI, \
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,ESI
MOV [EBX+FILE.Handle],EAX
CMP EAX,EDI
JE .EndWithLastError:
SetSt [EBX+FILE.Status],fileStCreated
PUSH ECX
MOV ECX,ESP
WinAPI WriteFile,EAX,[EBX+FILE.Ptr],[EBX+FILE.Size],ECX,ESI
POP ECX
ADD [EBX+FILE.Pos],ECX
TEST EAX
JZ .EndWithLastError:
MOV EAX,[EBX+FILE.Size]
CMP EAX,ECX
JE .EndWithEAX
MOV EAX,0xE0070000 + 39 ; "The disk is full."
JMP .ErrorEAX
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX: STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
PUSHFD
JNSt [EBX+FILE.Status],fileStCreated,.90:
WinAPI CloseHandle,[EBX+FILE.Handle]
.90: RstSt [EBX+FILE.Status],fileStCreated
MOV [EBX+FILE.Handle],EDI
POPFD
POPAD
RET 12
ENDPROC1 FileStore@RT:
%ENDMACRO FileStore
FileOpen %MACRO theFile
PUSHD %theFile
CALL FileOpen@RT:
FileOpen@RT: PROC1
IMPORT CreateFileA,CreateFileW
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
LEA EDX,[EBX+FILE.Name]
SUB ESI,ESI
MOV EDI,INVALID_HANDLE_VALUE
MOV [EBX+FILE.Size],ESI
MOV [EBX+FILE.Pos],ESI
MOV [EBX+FILE.Ptr],ESI
MOV [EBX+FILE.Top],ESI
RstSt [EBX+FILE.Status],fileStStdIO
MOV EAX,CreateFileW:
JSt [EBX+FILE.Status],fileStUnicode,.30:
MOV EAX,CreateFileA:
CMPB [EDX],0
JNE .40:
.20:SetSt [EBX+FILE.Status],fileStStdIO
WinAPI GetStdHandle,STD_INPUT_HANDLE
JMP .50:
.30:CMPW [EDX],0
JE .20:
.40:WinAPI EAX,EDX,GENERIC_READ,FILE_SHARE_READ,ESI, \
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,ESI
.50:MOV [EBX+FILE.Handle],EAX
CMP EAX,EDI
JE .EndWithLastError:
SetSt [EBX+FILE.Status],fileStOpened+fileStFound
MOV ECX,EAX
SUB EAX,EAX
JSt [EBX+FILE.Status],fileStStdIO,.EndWithEAX:
WinAPI GetFileSize,ECX,ESI
CMP EAX,EDI
JE .EndWithLastError:
MOV [EBX+FILE.Size],EAX
CLC
JMP .EndWithEAX
.EndWithLastError:
WinAPI GetLastError
STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
POPAD
RET 4
ENDPROC1 FileOpen@RT:
%ENDMACRO FileOpen
FileReset %MACRO theFile, Position
%IF "%Position" === ""
PUSHD 0
%ELSE
PUSHD %Position
%ENDIF
PUSHD %theFile
CALL FileReset@RT:
FileReset@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
MOV EDI,[%Param2]
MOV EAX,0xE0070004 ; File is not opened.
MOV [%ReturnEAX],EDI
JNSt [EBX+FILE.Status],fileStOpened,.ErrorEAX:
WinAPI SetFilePointer,[EBX+FILE.Handle],EDI,0,FILE_BEGIN
INC EAX
JZ .EndWithLastError:
MOV [EBX+FILE.Pos],EDI
MOV EAX,[EBX+FILE.BufPtr]
MOV [EBX+FILE.Ptr],EAX
JSt [EBX+FILE.Status],fileStMapOpened,.30:
MOV [EBX+FILE.Top],EAX
JMPS .90:
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX: STC
MOV [%ReturnEAX],EAX
JMPS .90:
.30: ADD [EBX+FILE.Ptr],EDI
.90:POPAD
RET 8
ENDPROC1 FileReset@RT:
%ENDMACRO FileReset
FileRead %MACRO theFile,DataPtr,DataSize
PUSHD %DataSize,%DataPtr,%theFile
CALL FileRead@RT:
FileRead@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
MOV EAX,0xE0070004 ; File is not open.
JNSt [EBX+FILE.Status],fileStOpened,.ErrorEAX:
PUSH ECX
MOV ECX,ESP
WinAPI ReadFile,[EBX+FILE.Handle],[%Param2],[%Param3],ECX,0
POP ECX
TEST EAX
JZ .EndWithLastError:
MOV EAX,ECX
ADD [EBX+FILE.Pos],EAX
TEST EAX
JMP .EndWithEAX
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX:
STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
POPAD
RET 12
ENDPROC1 FileRead@RT:
%ENDMACRO FileRead
FileCreate %MACRO theFile
PUSHD %theFile
CALL FileCreate@RT:
FileCreate@RT: PROC1
IMPORT CreateFileA,CreateFileW
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
LEA EDX,[EBX+FILE.Name]
SUB ESI,ESI
MOV EDI,INVALID_HANDLE_VALUE
MOV [EBX+FILE.Size],ESI
MOV [EBX+FILE.Pos],ESI
MOV [EBX+FILE.Ptr],ESI
MOV [EBX+FILE.Top],ESI
RstSt [EBX+FILE.Status],fileStStdIO
MOV EAX,CreateFileW:
JSt [EBX+FILE.Status],fileStUnicode,.30:
MOV EAX,CreateFileA:
CMPB [EDX],0
JNE .40:
.20:SetSt [EBX+FILE.Status],fileStStdIO
WinAPI GetStdHandle,STD_OUTPUT_HANDLE
JMP .60:
.30:CMPW [EDX],0
JE .20:
.40:MOV ECX,OPEN_ALWAYS
JSt [EBX+FILE.Status],fileStAppend,.50:
MOV ECX,CREATE_ALWAYS
MOV ESI,FILE_ATTRIBUTE_NORMAL
.50:WinAPI EAX,EDX,GENERIC_WRITE,FILE_SHARE_READ,0,ECX,ESI,0
.60:MOV [EBX+FILE.Handle],EAX
CMP EAX,EDI
JE .EndWithLastError:
SetSt [EBX+FILE.Status],fileStCreated
MOV ECX,EAX
SUB EAX,EAX
JSt [EBX+FILE.Status],fileStStdIO,.EndWithEAX:
XOR ESI,ESI
WinAPI GetFileSize,ECX,ESI
CMP EAX,EDI
JE .EndWithLastError:
MOV [EBX+FILE.Size],EAX
JNSt [EBX+FILE.Status],fileStAppend,.EndWithEAX:
MOV [EBX+FILE.Pos],EAX
WinAPI SetFilePointer,[EBX+FILE.Handle],ESI,ESI,FILE_END
CMP EDI,EAX
JA .EndWithEAX:
.EndWithLastError:
WinAPI GetLastError
STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
POPAD
RET 4
ENDPROC1 FileCreate@RT:
%ENDMACRO FileCreate
FileAppend %MACRO theFile
PUSHD %theFile
CALL FileAppend@RT:
FileAppend@RT: PROC1
PUSH EBX
MOV EBX,[ESP+8] ; theFile
SetSt [EBX+FILE.Status],fileStAppend
FileCreate EBX
POP EBX
RET 4
ENDPROC1 FileAppend@RT:
%ENDMACRO FileAppend
FileWriteRT %MACRO ; Common runtime procedure declaration for macros FileWrite*
FileWrite@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[ESP+40] ; theFile
LEA ESI,[ESP+44] ; 1st string ptr.
MOV EAX,0xE0070004 ; File is not opened.
JNSt [EBX+FILE.Status],fileStCreated, .ErrorEAX:
SUB EDI,EDI
MOV [ESP+28],EDI ; %Return EAX.
.10: LODSD ; DataPtr
MOV EDX,EAX
TEST EAX
JZ .90 ; End of data.
LODSD ; DataSize.
MOV ECX,EAX
PUSH EBP,EBP
MOV EBP,ESP
WinAPI WriteFile,[EBX+FILE.Handle],EDX,ECX,EBP,EDI
POP EBP ; written size
ADD [ESP+32],EBP ; %ReturnEAX
ADD [EBX+FILE.Pos],EBP
ADD [EBX+FILE.Size],EBP
POP EBP
TEST EAX
JNZ .10:
WinAPI GetLastError
.ErrorEAX:
STC
MOV [%ReturnEAX],EAX
.90:POPAD
RET
FileWrite$size@RT:
PUSH ECX,EDI
SUB ECX,ECX
SUB EAX,EAX
DEC ECX
MOV EDI,[ESP+12] ; DataPtr
REPNE SCASB
SUB EAX,ECX
SUB EAX,2
MOV [ESP+16],EAX ; DataSize
POP EDI,ECX
RET
ENDPROC1 FileWrite@RT:
%ENDMACRO FileWriteRT
FileWrite %MACRO theFile,DataPtr,DataSize,,,,
%IF %# & 1 = 0
%ERROR ID=5944, 'Macro "FileWrite" expects odd number of arguments.'
%EXITMACRO FileWrite
%ENDIF
PUSHD 0 ; Mark the end of arguments.
ArgNr %FOR %#..2,STEP=-2
PUSHD %*{%ArgNr}, %*{%ArgNr-1}
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],4*(%#+1)
CALL FileWrite@RT
POP ESP
FileWriteRT ; Invoke the common runtime macro.
%ENDMACRO FileWrite
FileWriteLn %MACRO theFile,DataPtr,DataSize,,,
%IF %# & 1 = 0
%ERROR ID=5945, 'Macro "FileWriteLn" expects odd number of arguments.'
%EXITMACRO FileWriteLn
%ENDIF
PUSHD 0x00000A0D ; CR+LF.
PUSHD 0 ; Mark the end of arguments.
PUSHD 2 ; Size of CR+LF.
PUSHD ESP
ADDD [ESP],8 ; Pointer to CR+LF.
ArgNr %FOR %#..2,STEP=-2
PUSHD %*{%ArgNr}, %*{%ArgNr-1}
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],4*(%#+4)
CALL FileWrite@RT
POP ESP
FileWriteRT ; Invoke the common runtime macro.
%ENDMACRO FileWriteLn
FileWrite$ %MACRO theFile,DataPtr1,DataPtr2,DataPtr3,,,
PUSHD 0 ; Mark the end of arguments
ArgNr %FOR %#..2,STEP=-1
PUSHD EAX,%*{%ArgNr}
CALL FileWrite$size@RT
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],8*%#
CALL FileWrite@RT
POP ESP
FileWriteRT
%ENDMACRO FileWrite$
FileEncloseRT %MACRO ; Common RT procedure declaration for macros FileEnclose*
FileEnclose@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[ESP+40] ; theFile
SetSt [EBX+FILE.Status],fileStAppend
FileCreate EBX
JC .ErrorEAX:
LEA ESI,[ESP+44] ; Pointer to 1st string pointer.
SUB EDI,EDI
MOV [ESP+28],EDI ; %ReturnEAX.
.10: LODSD ; DataPtr.
MOV EDX,EAX
TEST EAX
JZ .90 ; End of data.
LODSD ; DataSize.
MOV ECX,EAX
PUSH EBP
PUSH EBP ; Make room for written size.
MOV EBP,ESP
WinAPI WriteFile,[EBX+FILE.Handle],EDX,ECX,EBP,EDI
POP EBP ; Written size.
ADD [ESP+32],EBP ; %ReturnEAX.
ADD [EBX+FILE.Pos],EBP
ADD [EBX+FILE.Size],EBP
POP EBP ; Restore frame.
TEST EAX ; WriteFile result.
JNZ .10: ; If OK, write the next Data.
WinAPI GetLastError
.ErrorEAX:
STC
MOV [ESP+28],EAX ; %ReturnEAX.
.90: PUSHFD
FileClose EBX
POPFD
POPAD
RET
FileEnclose$size@RT: ; Subprocedure for zero-terminated strings.
PUSH EAX,ECX,EDI
SUB ECX,ECX
SUB EAX,EAX
DEC ECX
MOV EDI,[ESP+16] ; DataPtr.
REPNE SCASB
SUB EAX,ECX
SUB EAX,2
MOV [ESP+20],EAX ; DataSize.
POP EDI,ECX,EAX
RET
ENDPROC1 FileEnclose@RT:
%ENDMACRO FileEncloseRT
FileEnclose %MACRO theFile,DataPtr,DataSize,,,,
%IF %# & 1 = 0
%ERROR ID=5942, 'Macro "FileEnclose" expects odd number of arguments.'
%EXITMACRO FileEnclose
%ENDIF
PUSHD 0 ; Mark the end of arguments.
ArgNr %FOR %#..2,STEP=-2
PUSHD %*{%ArgNr}, %*{%ArgNr-1}
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],4*(%#+1)
CALL FileEnclose@RT
POP ESP
FileEncloseRT ; Invoke the common runtime macro.
%ENDMACRO FileEnclose
FileEncloseLn %MACRO theFile,DataPtr,DataSize,DataPtr2,DataSize2,,,
%IF %# & 1 = 0
%ERROR ID=5943, 'Macro "FileEncloseLn" expects odd number of arguments.'
%EXITMACRO FileEncloseLn
%ENDIF
PUSHD 0x00000A0D ; CR+LF
PUSHD 0 ; Mark the end of arguments.
PUSHD 2 ; Size of CR+LF.
PUSHD ESP
ADDD [ESP],8 ; Pointer to CR+LF.
ArgNr %FOR %#..2,STEP=-2
PUSHD %*{%ArgNr}, %*{%ArgNr-1}
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],4*(%#+4)
CALL FileEnclose@RT
POP ESP
FileEncloseRT ; Invoke the common runtime macro.
%ENDMACRO FileEncloseLn
FileEnclose$ %MACRO theFile,DataPtr1,DataPtr2,DataPtr3,,,
PUSHD 0 ; Mark the end of arguments.
ArgNr %FOR %#..2,STEP=-1
PUSHD EAX,%*{%ArgNr}
CALL FileEnclose$size@RT ; Using subprocedure in FileEncloseRT get datasize to EAX.
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],8 * %#
CALL FileEnclose@RT
POP ESP
FileEncloseRT ; Invoke the common runtime macro.
%ENDMACRO FileEnclose$
FileMapOpen %MACRO theFile
PUSHD %theFile
CALL FileMapOpen@RT:
FileMapOpen@RT: PROC1
IMPORT CreateFileA,CreateFileW,CreateFileMappingA,CreateFileMappingW
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
LEA EDX,[EBX+FILE.Name]
SUB ESI,ESI
MOV EDI,INVALID_HANDLE_VALUE
MOV [EBX+FILE.Ptr],ESI
MOV [EBX+FILE.Top],ESI
MOV [EBX+FILE.BufPtr],ESI
MOV [EBX+FILE.BufSize],ESI
MOV [EBX+FILE.Size],ESI
MOV [EBX+FILE.Pos],ESI
MOV [EBX+FILE.Handle],EDI
MOV [%ReturnESI],ESI
MOV EAX,CreateFileW:
JSt [EBX+FILE.Status],fileStUnicode,.30:
MOV EAX,CreateFileA:
CMPB [EDX],0
JNE .40:
.20: MOV EAX,0xC0070000+123 ; "The file name is incorrect."
JMP .ErrorEAX:
.30: CMPW [EDX],0
JE .20:
.40: WinAPI EAX,EDX,GENERIC_READ,FILE_SHARE_READ,ESI, \
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,ESI
MOV [EBX+FILE.Handle],EAX
CMP EAX,EDI
JE .EndWithLastError:
SetSt [EBX+FILE.Status],fileStOpened+fileStFound
WinAPI GetFileSize,EAX,ESI
CMP EAX,EDI
JE .EndWithLastError:
MOV [EBX+FILE.Size],EAX
MOV [EBX+FILE.BufSize],EAX
MOV [EBX+FILE.Top],EAX
MOV [%ReturnEAX],EAX
MOV EAX,CreateFileMappingW:
JSt [EBX+FILE.Status],fileStUnicode,.50:
MOV EAX,CreateFileMappingA:
.50: WinAPI EAX,[EBX+FILE.Handle],ESI,PAGE_READONLY,ESI,ESI,ESI
MOV [EBX+FILE.MapHandle],EAX
TEST EAX
JZ .EndWithLastError:
SetSt [EBX+FILE.Status],fileStMapOpened
WinAPI MapViewOfFile,EAX,FILE_MAP_READ,ESI,ESI,ESI
MOV [EBX+FILE.Ptr],EAX
MOV [%ReturnESI],EAX
ADD [EBX+FILE.Top],EAX
MOV [EBX+FILE.BufPtr],EAX
TEST EAX
JZ .EndWithLastError:
SetSt [EBX+FILE.Status],fileStMapped
JMP .End:
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX:
STC
MOV [%ReturnEAX],EAX
.End:
POPAD
RET 4
ENDPROC1 FileMapOpen@RT:
%ENDMACRO FileMapOpen
FileMapCreate %MACRO theFile,FileSize
%IF %# > 1
PUSHD %FileSize
%ELSE
PUSHD 0
%ENDIF
PUSHD %theFile
CALL FileMapCreate@RT:
FileMapCreate@RT: PROC1
IMPORT CreateFileA,CreateFileW,CreateFileMappingA,CreateFileMappingW
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
LEA EDX,[EBX+FILE.Name]
SUB ESI,ESI
MOV EDI,INVALID_HANDLE_VALUE
MOV [%ReturnEDI],ESI
RstSt [EBX+FILE.Status],fileStAppend
MOV [EBX+FILE.Ptr],ESI
MOV [EBX+FILE.Top],ESI
MOV [EBX+FILE.BufPtr],ESI
MOV [EBX+FILE.BufSize],ESI
MOV [EBX+FILE.Size],ESI
MOV [EBX+FILE.Pos],ESI
MOV [EBX+FILE.Handle],EDI
MOV EAX,CreateFileW:
JSt [EBX+FILE.Status],fileStUnicode,.30:
MOV EAX,CreateFileA:
CMPB [EDX],0
JNE .40:
.20: MOV EAX,0xC0070000+123 ; "Error: The file name is incorrect."
JMP .ErrorEAX:
.30: CMPW [EDX],0
JE .20:
.40: WinAPI EAX,EDX,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE, \
ESI,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,ESI
MOV [EBX+FILE.Handle],EAX
CMP EAX,EDI
JE .EndWithLastError:
SetSt [EBX+FILE.Status],fileStCreated
MOV ECX,[%Param2]
TEST ECX
JNZ .45:
WinAPI GetFileSize,[EBX+FILE.Handle],ECX
MOV ECX,EAX
INC EAX
JZ .EndWithLastError:
.45: MOV [EBX+FILE.Size],ECX
MOV [EBX+FILE.BufSize],ECX
MOV [EBX+FILE.Top],ECX
MOV [%ReturnEAX],ECX
MOV EAX,CreateFileMappingW:
JSt [EBX+FILE.Status],fileStUnicode,.50:
MOV EAX,CreateFileMappingA:
.50: WinAPI EAX,[EBX+FILE.Handle],ESI,PAGE_READWRITE,ESI,ECX,ESI
MOV [EBX+FILE.MapHandle],EAX
TEST EAX
JZ .EndWithLastError:
SetSt [EBX+FILE.Status],fileStMapCreated
WinAPI MapViewOfFile,EAX,FILE_MAP_WRITE,ESI,ESI,ESI
MOV [EBX+FILE.Ptr],EAX
ADD [EBX+FILE.Top],EAX
MOV [EBX+FILE.BufPtr],EAX
MOV [%ReturnEDI],EAX
TEST EAX
JZ .EndWithLastError:
SetSt [EBX+FILE.Status],fileStMapped
JMP .End:
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX:
STC
MOV [%ReturnEAX],EAX
.End:
POPAD
RET 8
ENDPROC1 FileMapCreate@RT:
%ENDMACRO FileMapCreate
FileStreamOpen %MACRO theFile,BufSize=16K
PUSHD %BufSize,%theFile
CALL FileStreamOpen@RT:
FileStreamOpen@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
MOV ECX,[%Param2]
MOV [EBX+FILE.BufSize],ECX
WinAPI GlobalAlloc,GMEM_FIXED,ECX
TEST EAX
JZ .EndWithLastError:
MOV [EBX+FILE.BufPtr],EAX
MOV EDI,EAX
SetSt [EBX+FILE.Status],fileStAllocated
FileOpen EBX
MOV [EBX+FILE.Ptr],EDI
MOV [EBX+FILE.Top],EDI
JNC .EndWithEAX
.EndWithLastError:
WinAPI GetLastError
STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
POPAD
RET 8
ENDPROC1 FileStreamOpen@RT:
%ENDMACRO FileStreamOpen
FileStreamRead %MACRO theFile,DataPtr,DataSize
PUSHD %DataSize,%DataPtr,%theFile
CALL FileStreamRead@RT:
FileStreamRead@RT: PROC1
PUSHAD
MOV EBP,ESP
SUB EDX,EDX
MOV EBX,[%Param1]
MOV EDI,[%Param2]
MOV [%ReturnEAX],EDX
.10: MOV ESI,[EBX+FILE.Ptr]
.20: MOV ECX,[EBX+FILE.Top]
SUB ECX,ESI
JNA .50:
CMP ECX,[%Param3]
JA .30:
SUB [%Param3],ECX
ADD EDX,ECX
REP MOVSB
MOV [EBX+FILE.Ptr],ESI
JMP .20:
.30: MOV ECX,[%Param3]
ADD EDX,ECX
REP MOVSB
MOV [EBX+FILE.Ptr],ESI
JMP .70:
.50: MOV ESI,[EBX+FILE.BufPtr]
MOV [EBX+FILE.Ptr],ESI
MOV [EBX+FILE.Top],ESI
PUSH ECX
MOV ECX,ESP
WinAPI ReadFile,[EBX+FILE.Handle],ESI,[EBX+FILE.BufSize],ECX,0
POP ECX
TEST EAX
JZ .EndWithLastError:
JECXZ .70: ; EOF
ADD [EBX+FILE.Top],ECX
JMP .20:
.70: MOV EAX,EDX
ADD [EBX+FILE.Pos],EDX
TEST EAX
JMP .EndWithEAX ; ZF if EAX=0
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX:
STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
.90: POPAD
RET 12
ENDPROC1 FileStreamRead@RT:
%ENDMACRO FileStreamRead
FileStreamReadLn %MACRO theFile
PUSHD %theFile
CALL FileStreamReadLn@RT:
FileStreamReadLn@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
MOV EAX,0xE0070004 ; not open
JNSt [EBX+FILE.Status],fileStOpened,.ErrorEAX:
JNSt [EBX+FILE.Status],fileStAllocated,.ErrorEAX:
MOV EDI,[EBX+FILE.Ptr]
MOV ECX,[EBX+FILE.Top]
.10: MOV [%ReturnESI],EDI
MOV EDX,EDI
SUB ECX,EDI
JNA .30:
MOV AL,10 ; LineFeed
REPNE SCASB
JE .50:
CMP EDX,[EBX+FILE.BufPtr]
JE .50:
; When end of line is out of buffer and start of line is not
; at buffer's beginning, the buffer will be reloaded with the current line.
SUB EDX,EDI
WinAPI SetFilePointer,[EBX+FILE.Handle],EDX,0,FILE_CURRENT
.30: MOV EDI,[EBX+FILE.BufPtr]
MOV [EBX+FILE.Ptr],EDI
MOV [EBX+FILE.Top],EDI
PUSH ECX
MOV ECX,ESP
WinAPI ReadFile,[EBX+FILE.Handle],EDI,[EBX+FILE.BufSize],ECX,0
POP ECX
TEST EAX
JZ .EndWithLastError:
JECXZ .70: ; EOF
ADD ECX,EDI
MOV [EBX+FILE.Top],ECX
JMP .10:
.50: MOV [EBX+FILE.Ptr],EDI
SUB EDI,EDX
MOV [%ReturnEAX],EDI
ADD [EBX+FILE.Pos],EDI
JMP .90:
.70: SUB EAX,EAX
JMP .EndWithEAX:
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX:
STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
.90:POPAD
RET 4
ENDPROC1 FileStreamReadLn@RT:
%ENDMACRO FileStreamReadLn
FileStreamReadByte %MACRO theFile
PUSHD %theFile
CALL FileStreamReadByte@RT:
FileStreamReadByte@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
.10: MOV ESI,[EBX+FILE.Ptr]
CMP ESI,[EBX+FILE.Top]
JB .50:
MOV EAX,0xE0070004 ; not open
JNSt [EBX+FILE.Status],fileStOpened,.ErrorEAX:
JNSt [EBX+FILE.Status],fileStAllocated,.ErrorEAX:
MOV EDI,[EBX+FILE.BufPtr]
MOV [EBX+FILE.Ptr],EDI
MOV [EBX+FILE.Top],EDI
PUSH ECX
MOV ECX,ESP
WinAPI ReadFile,[EBX+FILE.Handle],EDI,[EBX+FILE.BufSize],ECX,0
POP ECX
TEST EAX
JZ .EndWithLastError:
ADD [EBX+FILE.Top],ECX
TEST ECX
JNZ .10
MOV EAX,[%ReturnEAX]
XOR AL,AL ; ZF=1
JMP .EndWithEAX:
.EndWithLastError:
WinAPI GetLastError
.ErrorEAX:
STC
JMP .EndWithEAX:
.50: MOV EAX,[%ReturnEAX]
LODSB
MOV [EBX+FILE.Ptr],ESI
INCD [EBX+FILE.Pos]
CLC
.EndWithEAX:
MOV [%ReturnEAX],EAX
POPAD
RET 4
ENDPROC1 FileStreamReadByte@RT:
%ENDMACRO FileStreamReadByte
FileStreamCreate %MACRO theFile,BufSize=16K
PUSHD %BufSize,%theFile
CALL FileStreamCreate@RT:
FileStreamCreate@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
MOV ECX,[%Param2]
MOV [EBX+FILE.BufSize],ECX
MOV EDI,ECX
WinAPI GlobalAlloc,GMEM_FIXED,ECX
TEST EAX
JZ .EndWithLastError:
SetSt [EBX+FILE.Status],fileStAllocated
MOV [EBX+FILE.BufPtr],EAX
ADD EDI,EAX
MOV ESI,EAX
FileCreate EBX
MOV [EBX+FILE.Ptr],ESI
MOV [EBX+FILE.Top],EDI
JNC .EndWithEAX
.EndWithLastError:
WinAPI GetLastError
STC
.EndWithEAX:
MOV [%ReturnEAX],EAX
POPAD
RET 8
ENDPROC1 FileStreamCreate@RT:
%ENDMACRO FileStreamCreate
FileStreamAppend %MACRO theFile,BufSize=16K
PUSHD %BufSize,%theFile
CALL FileStreamAppend@RT:
FileStreamAppend@RT: PROC1
PUSH EBX,ECX
MOV EBX,[ESP+12] ; theFile
MOV ECX,[ESP+16] ; BufSize
SetSt [EBX+FILE.Status],fileStAppend
FileStreamCreate EBX,ECX
POP ECX,EBX
RET 8
ENDPROC1 FileStreamAppend@RT:
%ENDMACRO FileStreamAppend
FileStreamWriteByte %MACRO theFile
PUSHD %theFile
CALL FileStreamWriteByte@RT:
FileStreamWriteByte@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
.10: MOV EDI,[EBX+FILE.Ptr]
CMP EDI,[EBX+FILE.Top]
JB .50
FileFlush EBX ; If buffer full.
JNC .10:
MOV [%ReturnEAX],EAX
JMP .90:
.50: STOSB
MOV EAX,[EBX+FILE.Pos]
MOV [EBX+FILE.Ptr],EDI
ADD EAX,1
MOV [EBX+FILE.Pos],EAX
MOV [EBX+FILE.Size],EAX
CLC
.90:POPAD
RET 4
ENDPROC1 FileStreamWriteByte@RT:
%ENDMACRO FileStreamWriteByte
FileStreamWriteWord %MACRO theFile
PUSHD %theFile
CALL FileStreamWriteWord@RT:
FileStreamWriteWord@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
.10: MOV EDI,[EBX+FILE.Ptr]
LEA EDX,[EDI+1]
CMP EDX,[EBX+FILE.Top]
JB .50
FileFlush EBX ; If buffer full.
JNC .10:
MOV [%ReturnEAX],EAX
JMP .90:
.50: STOSW
MOV EAX,[EBX+FILE.Pos]
MOV [EBX+FILE.Ptr],EDI
ADD EAX,2
MOV [EBX+FILE.Pos],EAX
MOV [EBX+FILE.Size],EAX
CLC
.90:POPAD
RET 4
ENDPROC1 FileStreamWriteWord@RT:
%ENDMACRO FileStreamWriteWord
FileStreamWriteDword %MACRO theFile
PUSHD %theFile
CALL FileStreamWriteDword@RT:
FileStreamWriteDword@RT: PROC1
PUSHAD
MOV EBP,ESP
MOV EBX,[%Param1]
.10: MOV EDI,[EBX+FILE.Ptr]
LEA EDX,[EDI+3]
CMP EDX,[EBX+FILE.Top]
JB .50
FileFlush EBX ; If buffer full.
JNC .10:
MOV [%ReturnEAX],EAX
JMP .90:
.50: STOSD
MOV EAX,[EBX+FILE.Pos]
MOV [EBX+FILE.Ptr],EDI
ADD EAX,4
MOV [EBX+FILE.Pos],EAX
MOV [EBX+FILE.Size],EAX
CLC
.90:POPAD
RET 4
ENDPROC1 FileStreamWriteDword@RT:
%ENDMACRO FileStreamWriteDword
FileStreamWriteRT %MACRO ; Common runtime procedure for macros FileStreamWrite*
FileStreamWrite@RT: PROC1
PUSHAD
MOV EBX,[ESP+40] ; theFile
LEA ESI,[ESP+44] ; 1st string pointer.
MOV EAX,0xE0070004 ; File was not opened.
JNSt [EBX+FILE.Status],fileStCreated,.ErrorEAX:
JNSt [EBX+FILE.Status],fileStAllocated,.ErrorEAX:
SUB EAX,EAX
MOV [ESP+28],EAX ; %Return EAX
.10: LODSD ; DataPtr
MOV EBP,EAX
TEST EAX
JZ .90 ; end of data
LODSD ; DataSize
MOV EDX,EAX
ADD [ESP+28],EAX ; %ReturnEAX
CALL .FileStreamStoreData:
JNC .10
.ErrorEAX:
STC
MOV [ESP+28],EAX
.90:POPAD
RET
.FileStreamStoreData: ; Copy data to FileStream buffer
; INP: EBX=FILE EBP=DataPtr EDX=DataSize
; OUT: CF=error EAX=error EBX,ESI preserved FILE updated
PUSH ESI
MOV ESI,EBP
.S1: TEST EDX
JZ .S9
.S2: MOV ECX,[EBX+FILE.Top]
MOV EDI,[EBX+FILE.Ptr]
SUB ECX,EDI
JNZ .S3
FileFlush EBX
JNC .S2:
JMP .S9:
.S3: CMP ECX,EDX
JBE .S4:
MOV ECX,EDX
.S4: SUB EDX,ECX
ADD [EBX+FILE.Ptr],ECX
ADD [EBX+FILE.Pos],ECX
ADD [EBX+FILE.Size],ECX
REP MOVSB
JMP .S1:
.S9:POP ESI
RET
FileStreamWrite$size@RT:
PUSH EAX,ECX,EDI
SUB ECX,ECX
SUB EAX,EAX
DEC ECX
MOV EDI,[ESP+16] ; DataPtr
REPNE SCASB
SUB EAX,ECX
SUB EAX,2
MOV [ESP+20],EAX ; DataSize
POP EDI,ECX,EAX
RET
ENDPROC1 FileStreamWrite@RT:
%ENDMACRO FileStreamWriteRT
FileStreamWrite %MACRO theFile,DataPtr,DataSize,DataPtr2,DataSize2,,,
%IF %# & 1 = 0
%ERROR ID=5946, 'Macro "FileStreamWrite" expects odd number of arguments.'
%EXITMACRO FileStreamWrite
%ENDIF
PUSHD 0 ; Mark the end of arguments.
ArgNr %FOR %#..2,STEP=-2
PUSHD %*{%ArgNr}, %*{%ArgNr-1}
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],4*(%#+1)
CALL FileStreamWrite@RT
POP ESP
FileStreamWriteRT ; Invoke the common runtime macro.
%ENDMACRO FileStreamWrite
FileStreamWriteLn %MACRO theFile,DataPtr,DataSize,DataPtr2,DataSize2,,,
%IF %# & 1 = 0
%ERROR ID=5947, 'Macro "FileStreamWriteLn" expects odd number of arguments.'
%EXITMACRO FileStreamWriteLn
%ENDIF
PUSHD 0x00000A0D ; CR+LF.
PUSHD 0 ; Mark the end of arguments.
PUSHD 2
PUSHD ESP
ADDD [ESP],8 ; Pointer to CR+LF.
ArgNr %FOR %#..2,STEP=-2
PUSHD %*{%ArgNr}, %*{%ArgNr-1}
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],4*(%#+4)
CALL FileStreamWrite@RT
POP ESP
FileStreamWriteRT
%ENDMACRO FileStreamWriteLn ; Invoke the common runtime macro.
FileStreamWrite$ %MACRO theFile,DataPtr1,DataPtr2,DataPtr3,,,
PUSHD 0 ; mark end of arguments
ArgNr %FOR %#..2,STEP=-1
PUSHD EAX,%*{%ArgNr}
CALL FileStreamWrite$size@RT
%ENDFOR ArgNr
PUSHD %theFile
PUSH ESP
ADDD [ESP],8*%#
CALL FileStreamWrite@RT
POP ESP
FileStreamWriteRT ; Invoke the common runtime macro.
%ENDMACRO FileStreamWrite$
ENDHEAD winf32