| Index | Manual | Download | Source | Macros | Embedded word Case ins.
Sitemap | Links | Forum | Tests | Projects

# winf32.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 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:

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

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:

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 ; EAX=Line size, ESI=pointer to the line in buffer. MOV EDI,WorkLine REP MOVSB CALL ModifyWorkLine FileStreamWrite OutFile, WorkLine, EAX JC .Error: JMP .Next: .EOF: FileClose OutFile, InpFile

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
  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  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

FileStatusEnc
  Definition of flags which describe `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.

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
  -
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

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
          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 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
  -
Depends on
  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: MOV [EBX+FILE.Handle],EDI
          MOV ESI,fileStFound+fileStStdIO+fileStUnicode
          AND ESI,[EBX+FILE.Status]
          MOV [EBX+FILE.Status],ESI
         POPAD
         RET 4
       ENDPROC1 FileClose@RT:
     %ENDMACRO FileClose

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.
Depends on
  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 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.
Depends on
  FileClose

    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

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

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+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 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.
Depends on
  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
  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$

FileEncloseRT
  is a runtime defining macro used internally by FileEnclose, FileEncloseLn, FileEnclose$.
Depends on
  FileCreate, FileClose

    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"
Depends on
  FileEncloseRT

    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 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+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
         TEST EAX
         JZ .End:
         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.
Depends on
  FileOpen

    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 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

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

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.
Depends on
  FileCreate

    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.
Depends on
  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 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
          MOV EDX,EAX
          FileFlush EBX ; If buffer full.
          JC .40:
          MOV EAX,EDX
          JMP .10:
     .40: 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
          MOV EDX,EAX
          FileFlush EBX ; If buffer full.
          JC .40:
          MOV EAX,EDX
          JMP .10:
     .40: 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
          MOV EDX,EAX
          FileFlush EBX ; If buffer full.
          JC .10:
          MOV EAX,EDX
          JMP .10:
     .40: 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
  is a runtime defining macro used internally by FileStreamWrite*.
  Macro returns CF=0, EAX=total written size, or CF=error
Depends on
  FileFlush

    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 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$

      ENDHEAD winf32

▲Back to the top▲