EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

winfile.htm
Class
FILE
Encoding
FileStatusEnc
Macros
FileAppend
FileAssign
FileClose
FileCreate
FileDelete
FileEach
FileEnclose
FileEnclose$
FileEncloseLn
FileExists?
FileLoad
FileMapCreate
FileMapOpen
FileMkDir
FileMove
FileNameParse
FileOpen
FileRead
FileReset
FileStore
FileStreamAppend
FileStreamCreate
FileStreamOpen
FileStreamRead
FileStreamReadByte
FileStreamReadLn
FileStreamWrite
FileStreamWriteByte
FileStreamWriteWord
FileStreamWriteDword
FileStreamWrite$
FileStreamWriteLn
FileWrite
FileWrite$
FileWriteLn

This macrolibrary implements file access which encapsulates WinAPI calls for most typical file operations in 32bit Windows.

File Access methodOpenData transferClose
standard readFileOpen FileReadFileClose
standard writeFileCreate FileWrite, FileWriteLn, FileWrite$FileClose
standard write at the end of fileFileAppend FileWrite, FileWriteLn, FileWrite$FileClose
memory mapped readFileMapOpen- FileClose
memory mapped writeFileMapCreate -FileClose
buffered readFileStreamOpen FileStreamReadByte, FileStreamRead, FileStreamReadLn FileClose
buffered writeFileStreamCreate FileStreamWriteByte, FileStreamWriteWord, FileStreamWriteDword, FileStreamWrite, FileStreamWriteLn, FileStreamWrite$FileClose
buffered write at end of fileFileStreamAppend FileStreamWriteByte, FileStreamWriteWord, FileStreamWriteDword, FileStreamWrite, FileStreamWriteLn, FileStreamWrite$FileClose
read file at once - FileLoad FileClose
write file at once - FileStore-
append to file - FileEnclose, FileEncloseLn, FileEnclose$-
special functionsFileReset FileNameParse, FileAssign, FileMove, FileExists?, 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. When CF=1, EAX returns the error code as obtained from GetLastError().

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 after the data. Macro names suffixed with ~$ write NULL character after the data.

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.

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 WinAPI functions ReadFile/WriteFile and they can process files of any size. Example:

[.bss] InpFile DS FILE OutFile DS FILE Record: DB 512 * BYTE [.text] FileAssign InpFile, ="Input.dat" FileAssign OutFile, ="Output.dat" FileOpen InpFile JC .InpError: FileCreate OutFile JC .OutError: .Next: FileRead InpFile, Record, SIZE# Record JC .InpError: JZ .EOF: CALL ModifyRecord FileWrite OutFile, Record, SIZE# Record JC .OutError: JMP .Next: .InpError: StdOutput ="Error reading ",InpFile.Name TerminateProgram ErrorLevel=8 .OutError: StdOutput ="Error writing ",OutFile.Name TerminateProgram ErrorLevel=8 .EOF: FileClose OutFile, InpFile TerminateProgram ErrorLevel=0

Memory mapped file access allocates memory and the entire file contents is virtually loaded to memory. File shouldn't be bigger than the available virtual memory (physical memory plus swap size). Memory mapped files are shared globally in OS and they can be used for interprocess communication.

Buffered (streamed) 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:

FileAssign InpFile, ="Input.txt" FileAssign OutFile, ="Output.txt" FileStreamOpen InpFile JC .Error: FileStreamCreate OutFile JC .Error: .Next: FileStreamReadLn InpFile JC .Error: JZ .EOF: MOV ECX,EAX ; line size MOV EDI,aLine REP MOVSB CALL ModifyLine FileStreamWrite OutFile, aLine, EAX JC .Error: JMP .Next: .EOF: FileClose OutFile, InpFile

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.


winfile HEAD
 INCLUDEHEAD1 winsfile.htm, winapi.htm, status32.htm, cpuext.htm
FILE
structure keeps information about the file status. Variable with FILE structure should be defined for each file used in program, either statically (in .data segment) or cleared when defined on stack or .bss. Pointer to a FILE structured variable is passed as the first parameter to all macros in this library.
FILE      STRUC
 .Ptr       DD  0 ; Pointer to the file content in memory-mapped|buffered data.
 .Top       DD  0 ; Pointer to the end of the memory-mapped|buffered data.
 .BufPtr    DD  0 ; Pointer to the memory-map|allocated buffer.
 .BufSize   DD  0 ; Size of memory map|buffer.
 .Pos       DD  0 ; Zero based offset of the file position.
 .Size      DD  0 ; File size in bytes.
 .Handle    DD -1 ; Handle to open file.
 .MapHandle DD -1 ; Handle to file mapping.
 .Status    DD  0 ; File status flags, see FileStatusEnc.
 .NameOffs  DD  0 ; Offset of the filename without path inside the .Name. Zero if no path in .Name.
 .ExtOffs   DD  0 ; Offset of the file extension inside the .Name.
 .Name      D MAX_PATH_SIZE * U ; Zero terminated WIDE|ANSI file name.
 ENDSTRUC FILE
FileStatusEnc
Definition of flags which describe FILE.Status.
fileFound        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.
FileNameParse FileNamePtr, Size= -1, Unicode=%^UNICODE
FileNameParse will analyze string with complete FileName, which may contain path, name, extension, and return pointers to the name without path and to the file extension.
Name starts behind the last slash /, backslash \ or colon:. If no such characters exists, the whole input string is name.
File extension starts at the last point . in the name. If there is no point in name, extension is empty.
Input
FileNamePtr is pointer to a string of ANSII or WIDE characters.
Size=-1 is the size of input string in bytes. By default it is unlimited and the string must be zero terminated in this case.
Unicode=%^UNICODE specifies whether the FileNamePtr string is ANSI or WIDE. By default it copies the value of system variable %^UNICODE at macro invocation but you may want to set this parameter to 0 even if %UNICODE is enabled and vice versa.
Output
EAX is pointer to the start of name without path.
ECX is pointer to the start of extension.
EDX points behind the last FileName character.
Path starts at %FileNamePtr, size=EAX - OFFSET#FileNamePtr
Name starts at EAX, size=ECX - EAX
Extension starts at ECX, size=EDX - ECX
Error
-
Depend on
Dispatch
Examples
%FileNamePtr │ │ │ │ "D:\path.ext\nam.part1.txt" "\plain" "./.profile" "name" │ │ │ │ │ │ │ │ │ EAX │ │ EAX │ EAX │ EAX │ ECX │ ECX ECX │ ECX EDX EDX EDX EDX
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
FileAssign theFile, Name$1, Name$2,,,Size=-1, Unicode=%^UNICODE
Macro FileAssign associates file name with the FILE data object. Name of the file is copied to theFile.Name member.
The file must be assigned with file name before it is created or opened. FileAssign can concatenate the filename from several input strings, e.g. path, name, extension.
Input
theFile is pointer to a FILE structured memory variable.
Name$* is pointer to a zero terminated string with the file name or its part. It needs not be zero terminated when Size= is expicitly specified. Filename will be concatenated when more than one string is provided.
Name$1 may also be 0 or pointer to an empty string. The file is then assigned to standard input or output.
Device name, such as COM1, LPT1, NULL, may be assigned instead of a disk file.
Size= applies to all input strings. Size is unlimited by default and the strings must be zero terminated in this case.
Unicode=%^UNICODE specifies whether the Name$ strings are ANSI or WIDE. By default it copies the current status of 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.
Output
Members of theFile .Name, .NameOffs, .ExtOffs, .Status:fileStUnicode of theFile are set.
Error
CF=1 if the concatenated name length exceeds SIZE# FILE.Name, i.e. MAX_PATH_SIZE=260 characters.
Depends on
FileNameParse
Examples
File1 DS FILE Path$ DB "C:\Text\",0 Name$ DB "Some",0 Ext$ DB ".txt",0 [.text] FileAssign File1,Path$,Name$,Ext$ FileAssign File1,=U"\\Server\Share\File.txt",Unicode=1 FileAssign File1,0 ; Standard output, by default redirected to console. FileAssign File1,="CON" ; Output to system console, not redirectable.
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
FileExists? theFile
will test if the given file with assigned name exists on disk. File may be opened or closed. Wildcard characters * ? are allowed in the file name.
This macro can test the presence of a directory, too.
Input
theFile is pointer to FILE object with assigned name.
Output
CF=1 if the file|directory does not exist.
CF=0 ZF=1 if the file exists
CF=0 ZF=0 if the directory exists
Example
FileExists? =".\Config.ini" JC ErrorIniNotFound
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 theFile
will parse the file name and create all directories in its path if they didn't exist.
The last portion of assigned name is treated as directory only if
it is terminated with backslash.
Input
theFile is pointer to FILE object with assigned name.
Output
CF=0
EAX=0 if the directory was created or it existed before.
Error

CF=1
EAX=last error if CreateDirectory failed.
Example
FileAssign SomeFile, ="C:\D1\D2\file.txt" FileMkDir SomeFile ; will create folders C:\D1 and C:\D1\D2 FileAssign SomeFile, ="C:\D1\D2\file.txt\" FileMkDir SomeFile ; will create folders C:\D1, C:\D1\D2 and C:\D1\D2\file.txt
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
FileEach theFile, CallbackProc
Macro FileEach expects the file object assigned with file name which can contain wildcard characters * and ?. FileEach will resolve the mask and performs callback procedure with each such filename. If no file matches the mask, CallbackProc is never called.
Input
theFile is a pointer to FILE object which must have assigned the requested file path and file name mask.
CallbackProc is the address of callback procedure.
Output
EAX=content of EAX at the last CallbackProc exit, or 0 if the CallbackProc was never called.
CallbackProc
is called with register calling convention. CallbackProc should return CF=0 to let FileEach continue with the next file otherwise FileEach stops searching.
CallbackProc input registers:
EBX=%theFile where the mask in FILE.Name is replaced with the file found in directory. The file is not open.
EDX=Find handle, as returned from WinAPI function FindFirstFile().
If CallbackProc aborts the program instead of returning to FileEach, it should also close this FindHandle using WinAPI FindClose,EDX before terminating.
ESI=pointer to the file name without path inside EBX+FILE.Name. The string is ANSI or WIDE, depending on what mask was assigned to %theFile.
EDI=pointer to WIN32_FIND_DATA structure which contains attributes of the found file.
EBP=EBP at FileEach macro entry. This allows to address local stack variables of the procedure which invoked FileEach.
Other registers are undefined at CallbackProc entry.
CallbackProc output registers:
EAX is passed through. FileEach returns EAX value from the last called CallbackProc, or 0 if it was never called.
CF=0 to continue with the next file
CF=1 to break further searching. FileEach discards the WIN32_FIND_DATA structure pointed to with EDI and exits but the actual file name without wildcards assigned to %theFile remains intact.
CallbackProc may destroy any GP register.
Depends on
FileNameParse
Example
MyFile DS FILE FileAssign MyFile,="D:\Dir\*.* FileEach MyFile, ListFile TerminateProgram ListFile PROC StdOutput ESI CLC RET ENDP ListFile
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 theFile
will allocate memory buffer on Windows heap, open the file, read entire file content to memory and then close the file.
Although the file handle is closed immediately, you should always use FileClose to free allocated buffer when the file content is no longer needed.
Input
theFile is pointer to an assigned existing FILE object.
Output
CF=0
EAX= file size,
ESI= pointer to the file contents in allocated memory.
Error
CF=1
EAX= errorCode as returned from GetLastError,
ESI= is undefined.
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 theFile, DataPtr, DataSize
Macro FileStore will open the file, write data and close the file.
Input
theFile is pointer to an assigned unopened FILE object,
DataPtr is pointer to the data to be written,
DataSize is size of the data in bytes, i.e. future file size.
Output
CF=0
EAX= is the data size of written data.
Error
CF=1
EAX= is error code returned by GetLastError.
Example
FileStore File1, MyDataPtr, MyDataEnd-MyDataPtr
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
FileEncloseRT
is a runtime defining macro used internally by FileEnclose, FileEncloseLn, FileEnclose$.
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 theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data at the end of existing file or creates a new one and then closes the file.
Multiple data can be appended with one invocation.
The file should be assigned but not open.
Input
theFile is pointer to FILE object with assigned name,
DataPtr is pointer to the data to be written,
DataSize is size of the data in bytes.
Output
CF=0
EAX= it total written size in bytes.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileEncloseRT
Example
FileEnclose LogFile,Datum,SIZE#Datum
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 theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data at the end of existing file or creates a new one and then closes the file.
Multiple data can be appended with one invocation.
When all data have been written, it appends end-of-line characters CR+LF to the file.
The file should be assigned but not open.
Input
theFile is pointer to FILE object with assigned name,
DataPtr is pointer to the data to be written,
DataSize is size of the data in bytes.
Output
CF=0
EAX= it total written size in bytes, including CR+LF.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileEncloseRT
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$ theFile, DataPtr$1, DataPtr$2,,,
This macro writes one or more zero-terminated data strings at the end of existing file or it creates a new one and then closes the file.
The file should be assigned but not open.
Multiple strings can be appended with one invocation. The terminating NULL is not written.
Input
theFile is pointer to FILE object with assigned name,
DataPtr$* are pointers to zero-terminated ANSI strings. Terminating zeroes are not written to the file.
Output
CF=0
EAX= total written size.
Error
CF=1
EAX= is errorCode as returned by GetLastError.
Example
FileEnclose$ LogFile, Time$, =" Job started"
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$
FileOpen theFile
opens the assigned file for reading.
Input
theFile is pointer to a FILE object.
Output
CF=0
EAX= file size.
Error
CF=1
EAX= errorCode as returned from GetLastError.
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+fileFound
     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 theFile, Position
Macro FileReset will reset internal file pointers to a new Position in the file.
Input
theFile is pointer to a FILE object, which must have been opened with FileOpen, FileMapOpen or FileStreamOpen.
Position specifies the number of bytes from the beginning of theFile. Zero is used if omitted.
Output
CF=0
EAX=Position
Error
CF=1
EAX= error code if SetFilePointer failed.
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 theFile, DataPtr, DataSize
reads from an opened file to the memory provided by caller.
Input
theFile is pointer to a FILE object opened for reading.
DataPtr is pointer where the data will be read,
DataSize is requested number of bytes.
Output
CF=0
ZF=0
EAX= the actually read size (may be less than DataSize if the file is not large enough).
End of file
CF=0
ZF=1
EAX=0 if all data have been read from the file (EOF).
Error
CF=1
EAX= errorCode as returned from GetLastError.
Example
FileRead InpFile,aLine,80 JC .ErrorReadingFile JZ .EOF
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 theFile
creates a new file or rewrites an existing file for writing.
Input
theFile is pointer to a FILE object.
Output
CF=0
EAX=0 (size of just rewritten file).
Error
CF=1
EAX=errorCode as returned from GetLastError.
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 theFile
Macro FileAppend creates a new file or opens an existing file for writing and sets file pointer to its end.
Input
theFile is pointer to a FILE object.
Output
CF=0
EAX= file size.
Error
CF=1
EAX=errorCode as returned from GetLastError.
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
is a runtime defining macro used internally by FileWrite, FileWriteLn, FileWrite$.
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 theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data to the file previously opened for writing with FileCreate or FileAppend.
Multiple data may be written in one macro invocation.
Input
theFile is pointer to an open FILE object,
DataPtr* points to the data to be written,
DataSize* is the size of data in bytes.
Output
CF=0
EAX=total written size in bytes.
Error
CF=1
EAX=errorCode as returned from GetLastError.
Depends on
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 theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
Macro FileWriteLn writes data to the file previously opened for writing with FileCreate or FileAppend.
Multiple data may be written in one macro invocation. End of line CR+LF characters are written in the end.
Input
theFile is pointer to an open FILE object,
DataPtr* points to the data to be written,
DataSize* is size of data in bytes.
Output
CF=0
EAX= is the total written size including CR+LF.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileWriteRT
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$ theFile, DataPtr$1, DataPtr$2,,,
This macro writes zero terminated ANSI string(s) to the file previously opened for writing with FileCreate or FileAppend.
Multiple strings may be written in one macro invocation. The terminating zeros are not written to the file.
Input
theFile is pointer to an open FILE object,
DataPtr$* are pointers to zero terminated strings to be written.
Output
CF=0
EAX= total written size in bytes.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileWriteRT
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$
FileMapOpen theFile
opens an existing file for reading and creates file mapping to memory.
Content of the file will be available for reading and pointed to with ESI.
The file must not be assigned with device or empty name.
Input
theFile is pointer to a FILE object.
Output
CF=0
EAX= file size,
ESI= pointer to the memory mapped file contents.
Error
CF=1
ESI=0
EAX= errorCode as returned fomr GetLastError.
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+fileFound
     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 theFile, FileSize
Macro FileMapCreate will create or rewrite an existing file for writing and create file mapping. Size of the file being created must be specified with FileSize.
File content may be copied to the mapped memory returned in EDI but not more than FileSize bytes.
The file must not be assigned with device or empty name.
Input
theFile is pointer to a FILE object.
FileSize is the size of memory mapped file. It may be omitted when FileMapCreate opens an existing file.
Output
CF=0
EAX=FileSize
EDI= is pointer to the memory mapped file content.
Error
CF=1
EDI=0
EAX= errorCode as returned from GetLastError.
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 theFile, BufSize=16K
This macro opens an existing file for reading and allocates memory buffer from OS heap. Buffer will be read from file on the FileStreamRead* request.
Input
theFile is pointer to a FILE object.
BuffSize= specifies the buffer size.
Output
CF=0
EAX= file size.
Error
CF=1
EAX= errorCode as returned from GetLastError.
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
FileStreamReadByte theFile
reads one byte from the file opened with FileStreamOpen.
Input
theFile is pointer to a FILE object.
Output
CF=0
ZF=0
AL= the byte read from file. Upper 3 bytes in EAX are preserved.
End of file
CF=0
ZF=1
AL=0 when there are no more bytes in the file (EOF).
Error
CF=1
EAX= errorCode as returned from GetLastError.
Remark
if CF=0
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
FileStreamRead theFile, DataPtr, DataSize
reads data from the file opened with FileStreamOpen.
Input
theFile is pointer to a FILE object.
DataPtr points to a memory area allocated by the caller,
DataSize is amount of bytes to read.
Output
CF=0
ZF=0
EAX= how many bytes was read (may be less the DataSize).
End of file
CF=0
ZF=1
EAX= 0 when there are no more bytes in the file (EOF).
error
CF=1
EAX= errorCode as returned from GetLastError.
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 theFile
reads one physical line from the file opened with FileStreamOpen.
Line is always terminated with LF character (except for the last line in the file).
Size of any line in file should not exceed the size of buffer allocated with FileStreamOpen. Longer lines will be
read per partes.
Input
theFile is pointer to a FILE object.
Output
CF=0
ZF=0
EAX= line size (never bigger than theFILE.BufSize)
ESI= pointer to the line in buffer.
End of file
CF=0
ZF=1
EAX=0 when there are no more data in file (EOF).
error
CF=1
EAX= errorCode as returned from GetLastError.
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
FileStreamCreate theFile, BufSize=16K
This macro creates a new file or rewrites an existing file for writing and allocates memory buffer from OS heap. The buffer will be automatically written to file every time it is completely filled with FileStreamWrite*.
Input
theFile is pointer to a FILE object,
BuffSize= specifies the buffer size.
Output
CF=0
EAX=0 (size of just rewritten file).
error
CF=1
EAX= errorCode as returned from GetLastError.
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 theFile, BufSize=16K
This macro creates a new file or rewrites an existing file for writing at its end and allocates memory buffer from heap. Buffer will be written to file every time it is completely filled with FileStreamWrite*.
Input
theFile is pointer to a FILE object,
BuffSize= specifies the buffer size.
Output
CF=0
EAX= is the old file size.
Error
CF=1
EAX= errorCode as returned from GetLastError.
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
FileFlush theFile
is a service macro used internally in FileClose, FileStreamWrite* to write the contents of file buffer on disk. There is no reason to invoke this macro explicitly by the programmer.
Output
CF=0
EAX= is unchanged.
Error
CF=1
EAX= errorCode as returned from GetLastError.
FileFlush %MACRO theFile
 ; OUT: CF=1 EAX=error     CF=0 EAX=unchanged
      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
FileStreamWriteRT
is a runtime defining macro used internally by FileStreamWrite*.
Macro returns CF=0, EAX=total written size, or CF=error
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
FileStreamWriteByte theFile
This macro writes one byte from AL to the file opened with FileStreamCreate or FileStreamAppend.
Input
theFile is pointer to a FILE object,
AL contains the data byte to write.
Output
CF=0, registers unchanged.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileFlush
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 theFile
This macro writes one word from AX to the file opened with FileStreamCreate or FileStreamAppend.
Input
theFile is pointer to a FILE object,
AX contains the data word to write.
Output
CF=0, registers unchanged.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileFlush
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 theFile
This macro writes one doubleword from EAX to the file opened with FileStreamCreate or FileStreamAppend.
Input
theFile is pointer to a FILE object,
EAX contains the data word to write.
Output
CF=0, registers unchanged.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileFlush
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
FileStreamWrite theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data to the file previously opened with FileStreamCreate or FileStreamAppend.
Multiple data portions may be written in one macro invocation.
Input
theFile is pointer to an open FILE object,
DataPtr* is pointer to the data to be written,
DataSize* is the size of the data in bytes to be written. It may be bigger than the buffer size specified on opening the file.
Output
CF=0
EAX= Total written size in bytes.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
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 theFile, DataPtr1, DataSize1, DataPtr2, DataSize2,,,
This macro writes data to the file previously opened with FileStreamCreate or FileStreamAppend.
Multiple data portions may be written in one macro invocation. End of line CR+LF characters are written in the end.
Input
theFile is pointer to an open FILE object,
DataPtr* is pointer to the data to be written,
DataSize* is the size of the data to be written, including the CR+LF. It may be bigger than the buffer size specified on opening the file.
Output
CF=0
EAX= total written size including CR+LF.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileStreamWriteRT
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$ theFile, DataPtr$1, DataPtr$2,,,
This macro writes zero terminated ANSI string(s) to the file previously opened with FileStreamCreate or FileStreamAppend.
Multiple strings may be written in one macro invocation. The terminating zeros are not written to the file.
Input
theFile is pointer to an open FILE object,
DataPtr$* are pointers to the zero terminated strings to be written.
Output
CF=0
EAX= total written size.
Error
CF=1
EAX= errorCode as returned from GetLastError.
Depends on
FileStreamWriteRT
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$
FileMove SourceFile, DestinationFile
FileMove renames directory on the same volume or moves the source file to the destination. Files will be closed first, if necessarry. The destination file will be erased if it existed before.
Directories in the destination file name will be maked, if necessarry. Both files must have been assigned with either WIDE or ANSI name.
Input
SourceFile and DestinationFile are pointers to assigned FILE objects.
Output
CF=0
EAX=0
Error
CF=1
EAX= error as returned from GetLastError.
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
FileClose theFile1, theFile2,,,
Macro FileClose will flush and deallocate the buffer, close file mapping, close the file, clear pointers in the FILE structure.
FileClose does not clear the name assignment, so the closed file may be reopen with the same name without invoking FileAssign again.
Input
theFile is pointer to a FILE object. More than one file may be specified simultaneously.
Output
-
Error
-
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
FileDelete theFile1, theFile2,,,
will close and erase the disk file(s).
FileDelete does not clear the name assignment, so the deleted file may be reopen with the same name without invoking FileAssign again.
Input
theFile is pointer to a FILEobject. More than one file may be specified simultaneously.
Output
CF=0,
EAX=0 if the last file was succesfully deleted.
Error
CF=1
EAX= error as returned from GetLastError.
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
      MOV EAX,0
      JNZ .OK:
      WinAPI GetLastError
.ErrorEAX:
      STC
.OK:  MOV [ESP+28],EAX ; ReturnEAX
     POPAD
     RET 4
   ENDPROC1 FileDelete@RT::
 %ENDMACRO FileDelete
  ENDHEAD winfile

▲Back to the top▲