EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

winf64.htm
Class
FILE64
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 64bit Windows . See also equivalent homonymous macroinstructions in winf32.htm, linf32.htm, linf64.htm.

File Access methodOpenData transferClose
read file at once - FileLoad FileClose
write file at once - FileStore-
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
append to file - FileEnclose, FileEncloseLn, FileEnclose$-
special functionsFileReset FileAssign, FileExists?, FileNameParse, FileMove, FileMkDir, FileEach FileDelete

Macros return the results in registers, usually RAX. 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 FILE64 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 methodVirtual memory
reservedcomitted
At once loadfilesizefilesize
At once storenonenone
Standardnonenone
MemoryMappedfilesizepagesize
Streamedbuffersizebuffersize

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 FILE64 OutFile DS FILE64 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 RCX,RAX ; line size MOV RDI,aLine REP MOVSB CALL ModifyLine FileStreamWrite OutFile, aLine, RAX 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 WinABI, Dispatch, status32.htm.

s
winf64 HEAD
 INCLUDEHEAD1 winsfile.htm, wins.htm, winabi.htm, winscon.htm, status32.htm, cpuext.htm
FILE64
structure keeps information about the file status. Variable with FILE64 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 FILE64 structured variable is passed as the first parameter to all macros in this library.
FILE64      STRUC
 .Ptr       DQ  Q ; Pointer to the file content in memory-mapped|buffered data.
 .Top       DQ  Q ; Pointer to the end of the memory-mapped|buffered data.
 .BufPtr    DQ  Q ; Pointer to the memory-map|allocated buffer.
 .BufSize   DQ  Q ; Size of memory map|buffer.
 .Pos       DQ  Q ; Zero based offset of the file position.
 .Size      DQ  Q ; File size in bytes.
 .Handle    DQ  Q ; Handle to the opened file.
 .MapHandle DQ  Q ; Handle to the file mapping.
 .Status    DD  D ; File status flags, see FileStatusEnc.
 .NameOffs  DD  D ; Offset of the filename without path inside the .Name. Zero if no path in .Name.
 .ExtOffs   DD  D ; Offset of the file extension inside the .Name.
 .Name      D MAX_PATH_SIZE * U ; Zero terminated WIDE|ANSI file name.
 ENDSTRUC FILE64
FileStatusEnc
Definition of flags which describe FILE64.Status.
fi64StFound      EQU 0x00000010 ; File was once succesfully opened.
fi64StAppend     EQU 0x00100000 ; Created file should move its pointer to the end.
fi64StStdIO      EQU 0x00200000 ; FILE64.Handle is standard input|output.
fi64StAllocated  EQU 0x00400000 ; FILE64.BufPtr is pointer to the allocated memory.
fi64StUnicode    EQU 0x00800000 ; FILE64.Name is in WIDE characters.
fi64StMapCreated EQU 0x01000000 ; FILE64.MapHandle is valid for writing.
fi64StMapOpened  EQU 0x02000000 ; FILE64.MapHandle is valid for reading.
fi64StMapped     EQU 0x04000000 ; FILE64.Ptr is pointer to the mapped memory.
fi64StCreated    EQU 0x10000000 ; FILE64.Handle is valid for writing.
fi64StOpened     EQU 0x20000000 ; FILE64.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
RAX is pointer to the start of name without path.
RCX is pointer to the start of extension.
RDX points behind the last FileName character.
Path starts at %FileNamePtr, size=RAX - OFFSET#FileNamePtr
Name starts at RAX, size=RCX - RAX
Extension starts at RCX, size=RDX - RCX
Error
-
Examples
%FileNamePtr │ │ │ │ "D:\path.ext\nam.part1.txt" "\plain" "./.profile" "name" │ │ │ │ │ │ │ │ │ RAX │ │ RAX │ RAX │ RAX │ RCX │ RCX RCX │ RCX RDX RDX RDX RDX
FileNameParse %MACRO FileNamePtr,Size=-1, Unicode=%^UNICODE
    PUSHQ %Size,%FileNamePtr
    %IF %Unicode
       CALL FileNameParseW64@RT::
FileNameParseW64@RT:: PROC1
    PUSH RAX,RCX,RDX,RSI
     MOV RSI,[RSP+40] ; %FileNamePtr.
     MOV RDX,[RSP+48] ; %Size.
     SUB RCX,RCX
     TEST RDX
     JS .UnlimitedSize:
     ADD RDX,RSI ; End of input string.
.UnlimitedSize:
     MOV [RSP+24],RCX ; Returned RAX.
     MOV [RSP+16],RCX ; Returned RCX.
     MOV [RSP+08],RCX ; Returned RDX.
.NextChar:
     CMP RSI,RDX
     JNB .E0:
     LODSW
     Dispatch AX,58,92,47,46,0 ; colon, backslash, slash, dot, NULL
     ; Ordinary character.
     LEA RAX,[RSI-2]
     CMP [RSP+24],RCX          ; ReturnedRAX.
     JNZ .NextChar:
     MOV [RSP+24],RAX          ; ReturnedRAX.
     JMP .NextChar:
.46: ; dot .
     LEA RAX,[RSI-2]
     MOV [RSP+16],RAX          ; ReturnedRCX.
     CMP [RSP+24],RCX          ; ReturnedRAX.
     JNE .NextChar:
     MOV [RSP+24],RAX          ; ReturnedRAX.
     JMP .NextChar:
.47: ; Colon, slash, backslash.
.58:
.92: MOV [RSP+24],RSI          ; ReturnedRAX.
     MOV [RSP+16],RCX          ; ReturnedRCX.
     JMP .NextChar:
 .0: DEC RSI,RSI ; Unichar NULL.
 .E0:MOV [RSP+08],RSI          ; ReturnedRDX.
     CMP [RSP+16],RCX          ; ReturnedRCX.
     JNE .E1:
     MOV [RSP+16],RSI          ; ReturnedRCX.
 .E1:CMP [RSP+24],RCX          ; ReturnedRAX.
     JNE .E2:
     MOV RAX,[RSP+16]          ; ReturnedRCX.
     MOV [RSP+24],RAX          ; ReturnedRAX.
 .E2:POP RSI,RDX,RCX,RAX
    RET 2*8
   ENDPROC1 FileNameParseW64@RT::
    %ELSE ; ANSI variant.
     CALL FileNameParseA64@RT::
FileNameParseA64@RT:: PROC1
    PUSH RAX,RCX,RDX,RSI
     MOV RSI,[RSP+40] ; %FileNamePtr.
     MOV RDX,[RSP+48] ; %Size.
     SUB RCX,RCX
     TEST RDX
     JS .UnlimitedSize:
     ADD RDX,RSI ; End of input string.
 .UnlimitedSize:
     MOV [RSP+24],RCX
     MOV [RSP+16],RCX
     MOV [RSP+08],RCX
 .NextChar:
     CMP RSI,RDX
     JNB .E0:
     LODSB
     Dispatch AL,58,92,47,46,0 ; colon, backslash, slash, dot, NULL.
     ; Ordinary character.
     LEA RAX,[RSI-1]
     CMP [RSP+24],RCX
     JNZ .NextChar:
     MOV [RSP+24],RAX
     JMP .NextChar:
.46: ; dot .
     LEA RAX,[RSI-1]
     MOV [RSP+16],RAX
     CMP [RSP+24],RCX
     JNE .NextChar:
     MOV [RSP+24],RAX
     JMP .NextChar:
.47: ; colon, slash, backslash
.58:
.92: MOV [RSP+24],RSI
     MOV [RSP+16],RCX
     JMP .NextChar:
.0:  DEC RSI ; Byte NULL.
 .E0:MOV [RSP+08],RSI
     CMP [RSP+16],RCX
     JNE .E1:
     MOV [RSP+16],RSI
 .E1:CMP [RSP+24],RCX
     JNE .E2:
     MOV RAX,[RSP+16]
     MOV [RSP+24],RAX
 .E2:POP RSI,RDX,RCX,RAX
    RET 2*8
   ENDPROC1 FileNameParseA64@RT::
  %ENDIF ; %Unicode
 %ENDMACRO FileNameParse
FileAssign theFile, Name$1, Name$2,,,Size=-1, Unicode=%^UNICODE
Macro FileAssign associates file name with the FILE64 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 FILE64 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:fi64StUnicode of theFile are set.
Error
CF=1 if the concatenated name length exceeds SIZE# FILE64.Name, i.e. MAX_PATH_SIZE=260 characters.
Depends on
FileNameParse
Examples
File1 DS FILE64 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
   PUSHQ 0 ; Mark the end of arguments.
   ArgNr %FOR %#..2,STEP=-1
     PUSHQ %*{%ArgNr}
   %ENDFOR ArgNr
   PUSHQ %Size, %theFile, RSP
   ADDQ [RSP],8*(%#+2)
   %IF %Unicode
     CALL FileAssignW64@RT::
FileAssignW64@RT:: PROC1 ; Wide variant.
   PUSH RAX,RCX,RDX,RBX,RBP,RSI,RDI
    MOV RBX,[RSP+72] ; %theFile
    LEA RBP,[RSP+88] ; %Name$1
    LEA RDI,[RBX+FILE64.Name]
    SetSt   [RBX+FILE64.Status],fi64StUnicode
    LEA RDX,[RDI+MAX_PATH_SIZE-2]
.10:XCHG RBP,RSI
    LODSQ            ; Offset of source string.
    MOV RBP,RAX
    XCHG RSI,RBP
    TEST RAX         ; No more macro arguments (zero marker)?
    JZ .50:
    MOV RCX,[RSP+80] ; %Size.
    SAR RCX,1 ; Size in unichars.
    JZ .10:
.20:LODSW
    CMP AX,0
    JE .10:
    CMP RDI,RDX
    JNB .40:
    STOSW
    LOOP .20:
    JMP .10:
.40:SUB EAX,EAX
    STC ; Overflow.
.50:MOV RCX,RDI
    STOSW
    LEA RDX,[RBX+FILE64.Name]
    PUSHFQ
     SUB RCX,RDX
     FileNameParse RDX,Size=RCX,Unicode=1
     LEA RDX,[RBX+FILE64.Name]
     SUB RAX,RDX
     SUB RCX,RDX
     MOV [RBX+FILE64.NameOffs],EAX
     MOV [RBX+FILE64.ExtOffs],ECX
    POPFQ
   POP RDI,RSI,RBP,RBX,RDX,RCX,RAX
   RET
ENDPROC1 FileAssignW64@RT::
   %ELSE ; ANSI.
     CALL FileAssignA64@RT::
FileAssignA64@RT:: PROC1 ; ANSI variant.
   PUSH RAX,RCX,RDX,RBX,RBP,RSI,RDI
    MOV RBX,[RSP+72] ; %theFile
    LEA RBP,[RSP+88] ; %Name$1
    LEA RDI,[RBX+FILE64.Name]
    RstSt   [RBX+FILE64.Status],fi64StUnicode
    LEA RDX,[RDI+MAX_PATH_SIZE]
.10:XCHG RBP,RSI
    LODSQ                 ; Offset of source string.
    MOV RBP,RAX
    XCHG RSI,RBP
    TEST RAX
    JZ .50:
    MOV RCX,[RSP+80]      ; %Size.
    JRCXZ .10:
.20:LODSB
    CMP AL,0
    JE .10:
    CMP RDI,RDX
    JNB .40:
    STOSB
    LOOP .20:
    JMP .10:
.40:SUB EAX,EAX
    STC ; Overflow.
.50:MOV RCX,RDI
    STOSB
    LEA RDX,[RBX+FILE64.Name]
    PUSHFQ
      SUB RCX,RDX
      FileNameParse RDX,Size=RCX,Unicode=0
      LEA RDX,[RBX+FILE64.Name]
      SUB RAX,RDX
      SUB RCX,RDX
      MOV [RBX+FILE64.NameOffs],EAX
      MOV [RBX+FILE64.ExtOffs],ECX
    POPFQ
   POP RDI,RSI,RBP,RBX,RDX,RCX,RAX
   RET
ENDPROC1 FileAssignA64@RT::
   %ENDIF
   POP RSP
%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 FILE64 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
     PUSHQ %theFile
     CALL FileExists?64@RT::
FileExists?64@RT:: PROC1
    IMPORT FindFirstFileA,FindFirstFileW
    PUSH RAX,RBX,RSI,RDI
     MOV RBX,[RSP+40] ; theFile
     LEA RSI,[RBX+FILE64.Name]
     SUB RSP,SIZE# WIN32_FIND_DATAW
     MOV RDI,RSP
     LEA RAX,[FindFirstFileW::]      ; WinABI function thunk.
     JSt [RBX+FILE64.Status],fi64StUnicode,.20
     LEA RAX,[FindFirstFileA::]      ; WinABI function thunk.
 .20:WinABI RAX,RSI,RDI, Fastmode=No ; FindFirstFile.
 .30:CMP RAX,INVALID_HANDLE_VALUE
     STC
     JE .90
     WinABI FindClose,RAX,Fastmode=No
     TEST [RDI+WIN32_FIND_DATAW.FileAttributes],FILE_ATTRIBUTE_DIRECTORY
 .90:LEA RSP,[RSP+SIZE# WIN32_FIND_DATAW]
    POP RDI,RSI,RBX,RAX
    RET 1*8
  ENDPROC1 FileExists?64@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 FILE64 object with assigned name.
Output
CF=0
RAX=0 if the directory was created or if it existed before.
Error
CF=1
RAX=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
     PUSHQ %theFile
     CALL FileMkDir64@RT::
FileMkDir64@RT:: PROC1
   PUSH RCX,RDX,RBX,RBP,RSI,RDI
    MOV RBP,RSP
    MOV RBX,[RBP+56]        ; RBX=Pointer to %theFile structure FILE64.
    SUB RSP,SIZE#WIN32_FIND_DATAW
    MOV RDX,RSP             ; RDX=Local FindData structure.
    SUB RSP,2* MAX_PATH_SIZE
    MOV RDI,RSP             ; RSP=LocalVar for the copy of directory name.
    LEA RSI,[RBX+FILE64.Name]
    MOV CX,'\'
    MOVW [RSI+SIZE#FILE64.Name-2],0 ; Zero terminate MAX_PATH_SIZE for safety.
    JSt [RBX+FILE64.Status],fi64StUnicode,.50:
    ; ANSI variant.
    LODSB
    CMP AL,0
    JE .Done:
    CMP AL,CL
    JNE .30:
    CMP [RSI],CL            ; Test the case "\\server\share\dir\file".
    JNE .30:
    STOSB
    LODSB
.10:STOSB
    LODSB
    CMP AL,0
    JE .Done:
    CMP AL,CL
    JNE .10:
.20:STOSB
    LODSB
    CMP AL,0
    JE .Done:
    CMP AL,CL
    JNE .20:
.30:STOSB
    LODSB
    CMP AL,0
    JE .Done:
    CMP AL,CL
    JNE .30:
    CMPB [RDI-1],':'        ; Test the case "D:\dir\file".
    JE .30:
    SUB EAX,EAX
    STOSB                   ; Temporary terminate folder name.
    MOV RAX,RSP             ; Local copy of directory name.
    WinABI FindFirstFileA,RAX,RDX,Fastmode=No
    CMP RAX,INVALID_HANDLE_VALUE
    JE .35:
    WinABI FindClose,RAX,Fastmode=No
    JSt [RDX+WIN32_FIND_DATAA.FileAttributes],FILE_ATTRIBUTE_DIRECTORY,.40:
.35:MOV RAX,RSP             ; Local copy of directory name.
    WinABI CreateDirectoryA,RAX,0,Fastmode=No
    TEST RAX
    JZ .Error:
.40:DEC RDI                 ; Remove temporary zero-terminator.
    MOV EAX,ECX
    JMP .30:
.50: ; WIDE variant.
    LODSW
    CMP AX,0
    JE .Done:
    CMP AX,CX
    JNE .80:
    CMP [RSI],CX           ; Test the case "\\server\share\dir\file".
    JNE .80:
    STOSW
    LODSW
.60:STOSW
    LODSW
    CMP AX,0
    JE .Done:
    CMP AX,CX
    JNE .60:
.70:STOSW
    LODSW
    CMP AX,0
    JE .Done:
    CMP AX,CX
    JNE .70:
.80:STOSW
    LODSW
    CMP AX,0
    JE .Done:
    CMP AX,CX
    JNE .80:
    CMPW [EDI-2],':'        ; Test the case "D:\dir\file".
    JE .80:
    SUB EAX,EAX
    STOSW                   ; Temporary terminate folder name.
    MOV RAX,RSP             ; Local copy of directory name.
    WinABI FindFirstFileW,RAX,RDX,Fastmode=No
    CMP RAX,INVALID_HANDLE_VALUE
    JE .85:
    WinABI FindClose,RAX,Fastmode=No
    JSt [RDX+WIN32_FIND_DATAW.FileAttributes],FILE_ATTRIBUTE_DIRECTORY,.90:
.85:MOV RAX,RSP             ; Local copy of directory name.
    WinABI CreateDirectoryW,RAX,0,Fastmode=No
    TEST RAX
    JNZ .90:
.Error:WinABI GetLastError,Fastmode=No
    STC
    JMP .Ret:
.90:DEC RDI,RDI             ; Remove temporary zero-terminator.
    MOV EAX,ECX
    JMP .80:
.Done:SUB EAX,EAX
.Ret:MOV RSP,RBP
   POP RDI,RSI,RBP,RBX,RDX,RCX
   RET 1*8
 ENDPROC1 FileMkDir64@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=0.
Error
CF=1
RAX= errorCode as returned from GetLastError.
FileFlush %MACRO theFile
 ; OUT: CF=1 EAX=error     CF=0 EAX=unchanged
      PUSHQ %theFile
      CALL FileFlush64@RT::
FileFlush64@RT:: PROC1
   PUSH RCX,RDX,RBX,RSI,RDI
    MOV RBX,[RSP+48]       ; theFile.
    MOV RAX,0xE0070004     ; File is not opened.
    JNSt [RBX+FILE64.Status],fi64StAllocated,.ErrorRAX:
    JNSt [RBX+FILE64.Status],fi64StCreated,  .ErrorRAX:
    MOV RDI,[RBX+FILE64.Ptr]
    MOV RSI,[RBX+FILE64.BufPtr]
    MOV [RBX+FILE64.Ptr],RSI
    SUB RDI,RSI
    PUSH RDX
     MOV RDX,RSP
     WinABI WriteFile,[RBX+FILE64.Handle],RSI,RDI,RDX,0,Fastmode=No
    POP RDX                 ; Written size.
    TEST RAX
    JZ .EndWithLastError:
    XOR EAX,EAX
    CMP RDI,RDX
    JE .Ret:
.EndWithLastError:
     WinABI GetLastError,Fastmode=No
.ErrorRAX:
     STC
.Ret:POP RDI,RSI,RBX,RDX,RCX
     RET 1*8
 ENDPROC1 FileFlush64@RT::
%ENDMACRO FileFlush
FileClose theFile1, theFile2,,,
Macro FileClose will flush and deallocate the buffer, close file mapping, close the file, clear pointers in the FILE64 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 FILE64 object. More than one file may be specified simultaneously.
Output
-
Error
-
FileClose %MACRO theFile1
  ArgNr %FOR 1..%#
       PUSHQ %*{%ArgNr}
       CALL FileClose64@RT::
     %ENDFOR ArgNr
FileClose64@RT:: PROC1
     PUSH RBX,RSI,RDI
      MOV RBX,[ESP+32]      ; theFile
      SUB ESI,ESI
      MOV RDI,INVALID_HANDLE_VALUE
      JNSt [RBX+FILE64.Status],fi64StAllocated,.10:
      FileFlush RBX
      WinABI GlobalFree,[RBX+FILE64.BufPtr],Fastmode=No
      RstSt [RBX+FILE64.Status],fi64StAllocated
 .10: MOV [RBX+FILE64.BufPtr],RSI
      MOV [RBX+FILE64.BufSize],RSI
      JNSt [RBX+FILE64.Status],fi64StMapped,.20:
      WinABI UnmapViewOfFile,[RBX+FILE64.Ptr],Fastmode=No
      RstSt [RBX+FILE64.Status],fi64StMapped
 .20: MOV [RBX+FILE64.Ptr],RSI
      MOV [RBX+FILE64.Top],RSI
      JNSt [RBX+FILE64.Status],fi64StMapOpened|fi64StMapCreated,.30:
      WinABI CloseHandle,[RBX+FILE64.MapHandle],Fastmode=No
 .30: RstSt [RBX+FILE64.Status],fi64StMapOpened|fi64StMapCreated
      MOV [RBX+FILE64.MapHandle],RDI
      JNSt [RBX+FILE64.Status],fi64StOpened|fi64StCreated,.40:
      JSt  [RBX+FILE64.Status],fi64StStdIO,.40
      WinABI CloseHandle,[RBX+FILE64.Handle],Fastmode=No
 .40: RstSt [RBX+FILE64.Status],fi64StOpened|fi64StCreated|fi64StAppend
      MOV [RBX+FILE64.Handle],RDI
     POP RDI,RSI,RBX
     RET 1*8
   ENDPROC1 FileClose64@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 FILE64 objects.
Output
CF=0
RAX=0
Error
CF=1
RAX= error as returned from GetLastError.
Depends on
FileMkDir FileClose
FileMove %MACRO SourceFile, DestinationFile
       PUSHQ %DestinationFile, %SourceFile
       CALL FileMove64@RT::
FileMove64@RT:: PROC1
     IMPORT MoveFileExA,MoveFileExW
     PUSH RDX,RBX,RSI,RDI
      MOV RSI,[RSP+40]            ; SourceFile
      MOV RDI,[RSP+48]            ; DestinationFile
      MOV EAX,[RSI+FILE64.Status]
      MOV EDX,[RDI+FILE64.Status]
      MOV EBX,fi64StUnicode
      AND EAX,EBX
      AND EDX,EBX
      CMP EAX,EDX
      MOV RAX,0xC008007B ; Error 123: invalid filename.
      JNE .ErrorRAX:              ; Different width of strings.
      FileClose RSI,RDI
      FileMkDir RDI
      JC .ErrorRAX:
      LEA RSI,[RSI+FILE64.Name]
      LEA RDI,[RDI+FILE64.Name]
      LEA RAX,[MoveFileExW]
      JSt EDX,fi64StUnicode,.30:
      LEA RAX,[MoveFileExA]
 .30: WinABI RAX,RSI,RDI,MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED,Fastmode=No
      TEST RAX
      MOV EAX,0
      JNZ .Ret:
      WinABI GetLastError,Fastmode=No
.ErrorRAX:
      STC
.Ret:POP RDI,RSI,RBX,RDX
     RET 2*8
   ENDPROC1 FileMove64@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 FILE64object. More than one file may be specified simultaneously.
Output
CF=0,
RAX=0 if the last file was succesfully deleted.
Error
CF=1
RAX= error as returned from GetLastError.
Depends on
FileClose
FileDelete %MACRO theFile1
  ArgNr %FOR 1..%#
       PUSHQ %*{%ArgNr}
       CALL FileDelete64@RT::
     %ENDFOR ArgNr
FileDelete64@RT:: PROC1
     IMPORT DeleteFileA,DeleteFileW
     PUSH RBX,RSI
      MOV RBX,[RSP+24]     ; theFile.
      FileClose RBX
      LEA RSI,[RBX+FILE64.Name]
      LEA RAX,[DeleteFileW]
      JSt [RBX+FILE64.Status],fi64StUnicode,.30:
      LEA RAX,[DeleteFileA]
 .30: WinABI RAX,RSI,Fastmode=No
      TEST RAX
      JNZ .OK:
      WinABI GetLastError,Fastmode=No
      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: POP RSI,RBX
     RET 1*8
   ENDPROC1 FileDelete64@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 FILE64 object which must have assigned the requested file path and file name mask.
CallbackProc is the address of callback procedure.
Output
RAX=content of RAX 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:
RBX=pointer to %theFile where the mask in FILE64.Name is replaced with the file found in directory. The file is not open.
RDX=Find handle, as returned from WinABI function FindFirstFile().
If CallbackProc aborts the program instead of returning to FileEach, it should also close this FindHandle using WinABI FindClose,RDX before terminating.
RSI=pointer to the file name without path inside RBX+FILE64.Name. The string is zero-terminated ANSI or WIDE, depending on what mask was assigned to %theFile.
RDI=pointer to WIN32_FIND_DATA structure which contains attributes of the found file.
RBP=RBP 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:
RAX is passed through. FileEach returns RAX 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 FILE64 FileAssign MyFile,="D:\Dir\*.* FileEach MyFile, ListFile TerminateProgram ListFile PROC StdOutput RSI, Eol=Yes CLC RET ENDP ListFile
FileEach %MACRO theFile, CallbackProc
     LEA RAX,[%CallbackProc]
     PUSH RAX
     LEA RAX,[%theFile]
     PUSH RAX
     CALL FileEach64@RT::
FileEach64@RT: PROC1
     IMPORT FindFirstFileA,FindFirstFileW,FindNextFileA,FindNextFileW
     PUSHQ 0,RCX,RDX,RBX,RSI,RDI
      MOV RBX,[RSP+56]               ; RBX=theFile.
      SUB RSP,SIZE# WIN32_FIND_DATAW
      MOV RDI,RSP                    ; RDI=Local WIN32_FIND_DATA structure.
      LEA RSI,[RBX+FILE64.Name]
      LEA RAX,[FindFirstFileW]
      JSt [RBX+FILE64.Status],fi64StUnicode, .10:
      LEA RAX,[FindFirstFileA]
.10:  WinABI RAX,RSI,RDI,Fastmode=No
      MOV RDX,RAX                    ; RDX=FindHandle.
      CMP RAX,INVALID_HANDLE_VALUE
      JE .90:
.20:  ; Copy resolved name to FILE64.
      LEA RSI,[RDI+WIN32_FIND_DATAW.FileName] ; Identical for WIN32_FIND_DATAA.FileName.
      LEA RDI,[RBX+FILE64.Name]
      MOVZX RAX,[RBX+FILE64.NameOffs]; Path size.
      ADD RDI,RAX                    ; RDI=^wildcarded mask without path.
      LEA RCX,[RBX+FILE64.Name + SIZE# FILE64.Name]
      SUB RCX,RDI
      REP MOVSB                      ; Copy resolved name to FILE64.
      ; Prepare GPRs for CallbackProc.
      LEA RSI,[RBX+FILE64.Name]
      ADD RSI,RAX                    ; RSI=^resolved name without path.
      MOV RDI,RSP                    ; RDI=Local WIN32_FIND_DATA structure.
      MOV RAX,[RSP+64+SIZE#WIN32_FIND_DATAW] ; RAX=^CallbackProc.
      PUSH RDX,RBX
       CALL RAX                      ; Perform the callback with resolved FILE64.
      POP RBX,RDX
      MOV [RSP+40+SIZE#WIN32_FIND_DATAW],RAX ; Value returned from CallbackProc.
      JC .90:                        ; Abort next files if CallbackProc returned CF.
      MOV RDI,RSP
      LEA RAX,[FindNextFileW]
      JSt [RBX+FILE64.Status],fi64StUnicode, .80:
      LEA RAX,[FindNextFileA]
.80:  WinABI RAX,RDX,RDI,Fastmode=No
      TEST RAX
      JNZ .20:                       ; The next file.
.90:  WinABI FindClose,RDX,Fastmode=No
      ADD RSP,SIZE# WIN32_FIND_DATAW
     POP RDI,RSI,RBX,RDX,RCX,RAX
     RET 2*8
 ENDPROC1 FileEach64@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 contents is no longer needed.
Input
theFile is pointer to FILE64 assigned with filename.
Output
CF=0
RAX= file size,
RSI= pointer to the file contents in dynamically allocated memory.
Error
CF=1
RAX= errorCode as returned from GetLastError,
RSI= is undefined.
FileLoad %MACRO theFile
    PUSHQ %theFile
    CALL FileLoad64@RT::
FileLoad64@RT:: PROC1
    IMPORT CreateFileA,CreateFileW
    PUSH RCX,RDX,RBX,RSI,RDI
     MOV RBX,[RSP+48]           ; %theFile.
     LEA RDX,[RBX+FILE64.Name]
     SUB ESI,ESI
     MOV RDI,INVALID_HANDLE_VALUE
     MOV [RBX+FILE64.Ptr],RSI
     MOV [RBX+FILE64.Top],RSI
     MOV [RBX+FILE64.BufPtr],RSI
     MOV [RBX+FILE64.BufSize],RSI
     MOV [RBX+FILE64.Pos],RSI
     MOV [RBX+FILE64.Size],RSI
     LEA RAX,[CreateFileW]
     JSt [RBX+FILE64.Status],fi64StUnicode,.10:
     LEA RAX,[CreateFileA]
 .10:WinABI RAX,RDX,GENERIC_READ,FILE_SHARE_READ,RSI, \
            OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,RSI,Fastmode=No
     MOV [RBX+FILE64.Handle],RAX
     CMP RAX,RDI
     JE .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StOpened
     WinABI GetFileSize,RAX,RSI,Fastmode=No
     CMP RAX,RDI
     JE .EndWithLastError:
     MOV [RBX+FILE64.Size],RAX
     MOV [RBX+FILE64.Top],RAX
     MOV [RBX+FILE64.BufSize],RAX
     WinABI GlobalAlloc,GMEM_FIXED,RAX,Fastmode=No
     MOV [RBX+FILE64.Ptr],RAX
     ADD [RBX+FILE64.Top],RAX
     MOV [RBX+FILE64.BufPtr],RAX
     TEST RAX
     JZ .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StAllocated
     MOV [RSP+8],RAX      ; ReturnRSI.
     PUSH RCX
      MOV RCX,RSP
      WinABI ReadFile,[RBX+FILE64.Handle],RAX,[RBX+FILE64.Size],RCX,0,Fastmode=No
     POP RCX
     ADD [RBX+FILE64.Pos],RCX
     TEST RAX
     JZ .EndWithLastError:
     MOV RAX,[RBX+FILE64.Size]
     CMP RAX,RCX
     JE .EndWithRAX
     MOV EAX,0xE0070026
     JMP .ErrorEAX
 .EndWithLastError:
     WinABI GetLastError,Fastmode=No
 .ErrorEAX: STC
 .EndWithRAX:
     PUSH RAX
      PUSHFD
       JNSt [RBX+FILE64.Status],fi64StOpened,.90:
       WinABI CloseHandle,[RBX+FILE64.Handle],Fastmode=No
 .90:  RstSt [RBX+FILE64.Status],fi64StOpened
       MOV [RBX+FILE64.Handle],RDI
      POPFD
     POP RAX
    POP RDI,RSI,RBX,RDX,RCX
    RET 1*8
  ENDPROC1 FileLoad64@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 FILE64 object,
DataPtr is pointer to the data to be written,
DataSize is size of the data in bytes, i.e. the future file size.
Output
CF=0
RAX= is the data size of written data.
Error
CF=1
RAX= is error code returned by GetLastError.
Example
FileAssign File1,="C:\Temp\MyFile1.txt" FileStore File1, MyDataPtr, MyDataEnd-MyDataPtr File1 DS FILE64
FileStore %MACRO theFile,DataPtr,DataSize
      PUSHQ %DataSize,%DataPtr,%theFile
      CALL FileStore64@RT::
FileStore64@RT:: PROC1
    IMPORT CreateFileA,CreateFileW
    PUSH RCX,RDX,RBX,RSI,RDI
     MOV RBX,[RSP+48]           ; theFile.
     MOV RAX,[RSP+56]           ; DataPtr.
     MOV RCX,[RSP+64]           ; DataSize.
     MOV [RBX+FILE64.Ptr],RAX
     MOV [RBX+FILE64.Top],RAX
     MOV [RBX+FILE64.Size],RCX
     ADD [RBX+FILE64.Top],RCX
     SUB ESI,ESI
     MOV RDI,INVALID_HANDLE_VALUE
     MOV [RBX+FILE64.Pos],RSI
     LEA RDX,[RBX+FILE64.Name]
     LEA RAX,[CreateFileW]
     JSt [RBX+FILE64.Status],fi64StUnicode,.10:
     LEA RAX,[CreateFileA]
 .10:WinABI RAX,RDX,GENERIC_WRITE,FILE_SHARE_READ,RSI, \
            CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,RSI,Fastmode=No
     MOV [RBX+FILE64.Handle],RAX
     CMP RAX,RDI
     JE .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StCreated
     PUSH RCX
      MOV RCX,RSP
      WinABI WriteFile,RAX,[RBX+FILE64.Ptr],[RBX+FILE64.Size],RCX,RSI,Fastmode=No
     POP RCX
     ADD [RBX+FILE64.Pos],RCX
     TEST RAX
     JZ .EndWithLastError:
     MOV RAX,[RBX+FILE64.Size]
     CMP RAX,RCX
     JE .EndWithRAX
     MOV EAX,0xE0070000 + 39 ; "The disk is full."
     JMP .ErrorEAX
 .EndWithLastError:
     WinABI GetLastError,Fastmode=No
 .ErrorEAX: STC
 .EndWithRAX:
     PUSHFD
      JNSt [RBX+FILE64.Status],fi64StCreated,.90:
      WinABI CloseHandle,[RBX+FILE64.Handle],Fastmode=No
 .90: RstSt [RBX+FILE64.Status],fi64StCreated
      MOV [RBX+FILE64.Handle],RDI
     POPFD
    POP RDI,RSI,RBX,RDX,RCX
    RET 3*8
  ENDPROC1 FileStore64@RT::
 %ENDMACRO FileStore
FileOpen theFile
opens the assigned file for reading.
Input
theFile is pointer to a FILE64 object.
Output
CF=0
RAX= file size.
Error
CF=1
RAX= errorCode as returned from GetLastError.
FileOpen %MACRO theFile
         PUSHQ %theFile
         CALL FileOpen64@RT::
FileOpen64@RT:: PROC1
    IMPORT CreateFileA,CreateFileW
    PUSHQ RCX,RDX,RBX,RSI,RDI
     MOV RBX,[RSP+48]           ; theFile.
     LEA RDX,[RBX+FILE64.Name]
     SUB ESI,ESI
     MOV RDI,INVALID_HANDLE_VALUE
     MOV [RBX+FILE64.Size],RSI
     MOV [RBX+FILE64.Pos],RSI
     MOV [RBX+FILE64.Ptr],RSI
     MOV [RBX+FILE64.Top],RSI
     RstSt [RBX+FILE64.Status],fi64StStdIO
     LEA RAX,[CreateFileW]
     JSt [RBX+FILE64.Status],fi64StUnicode,.30:
     LEA RAX,[CreateFileA]
     CMPB [RDX],0
     JNE .40:
 .20:SetSt [RBX+FILE64.Status],fi64StStdIO
     WinABI GetStdHandle,STD_INPUT_HANDLE,Fastmode=No
     JMP .50:
 .30:CMPW [RDX],0
     JE .20:
 .40:WinABI RAX,RDX,GENERIC_READ,FILE_SHARE_READ,RSI, \
            OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,RSI,Fastmode=No
 .50:MOV [RBX+FILE64.Handle],RAX
     CMP RAX,RDI
     JE .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StOpened + fi64StFound
     MOV RCX,RAX
     SUB EAX,EAX
     JSt [RBX+FILE64.Status],fi64StStdIO,.EndWithRAX:
     WinABI GetFileSize,RCX,RSI,Fastmode=No
     CMP RAX,RDI
     JE .EndWithLastError:
     MOV [RBX+FILE64.Size],RAX
     CLC
     JMP .EndWithRAX
 .EndWithLastError:
     WinABI GetLastError,Fastmode=No
     STC
 .EndWithRAX:
    POP RDI,RSI,RBX,RDX,RCX
    RET 1*8
  ENDPROC1 FileOpen64@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 FILE64 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
RAX=Position
Error
CF=1
RAX= error code if SetFilePointer failed.
FileReset %MACRO theFile, Position
     %IF "%Position" === ""
       PUSHQ 0
     %ELSE
       PUSHQ %Position
     %ENDIF
     PUSHQ %theFile
     CALL FileReset64@RT::
FileReset64@RT:: PROC1
     PUSH RDX,RBX
      MOV RBX,[RSP+24]       ; theFile.
      MOV RDI,[RSP+32]       ; Position.
      MOV RAX,0xE0070004     ; Error: File is not opened.
      JNSt [RBX+FILE64.Status],fi64StOpened, .ErrorRAX:
      WinABI SetFilePointer,[RBX+FILE64.Handle],RDI,0,FILE_BEGIN,Fastmode=No
      INC EAX
      JZ .EndWithLastError:
      MOV [RBX+FILE64.Pos],EDI
      MOV RAX,[RBX+FILE64.BufPtr]
      MOV [RBX+FILE64.Ptr],RAX
      JSt [RBX+FILE64.Status],fi64StMapOpened,.80:
      MOV [RBX+FILE64.Top],RAX
      JMPS .90:
 .EndWithLastError:
      WinABI GetLastError,Fastmode=No
 .ErrorRAX: STC
      JMPS .90:
 .80: ADD [RBX+FILE64.Ptr],RDI
 .90:POP RBX,RDI
     RET 2*8
    ENDPROC1 FileReset64@RT::
 %ENDMACRO FileReset
FileRead theFile, DataPtr, DataSize
reads from an opened file to the memory provided by caller.
Input
theFile is pointer to a FILE64 object opened for reading.
DataPtr is pointer where the data will be read,
DataSize is requested number of bytes.
Output
CF=0
ZF=0
RAX= the actually read size (may be less than DataSize if the file is not large enough).
End of file
CF=0
ZF=1
RAX=0 if all data have been read from the file (EOF).
Error
CF=1
RAX= errorCode as returned from GetLastError.
Example
FileRead InpFile,aLine,80 JC .ErrorReadingFile JZ .EOF
FileRead %MACRO theFile,DataPtr,DataSize
       PUSHQ %DataSize,%DataPtr,%theFile
       CALL FileRead64@RT::
FileRead64@RT:: PROC1
    PUSH RCX,RBX,RSI
     MOV RBX,[RSP+32]           ; theFile.
     MOV RSI,[RSP+40]           ; DataPtr.
     MOV RCX,[RSP+48]           ; DataSize.
     MOV RAX,0xE0070004         ; File is not open.
     JNSt [RBX+FILE64.Status],fi64StOpened, .ErrorRAX:
     PUSH RAX
       MOV RAX,RSP
       WinABI ReadFile,[RBX+FILE64.Handle],RSI,RCX,RAX,0,Fastmode=No
       TEST EAX
     POP RAX
     JZ .EndWithLastError:
     ADD [RBX+FILE64.Pos],RAX
     TEST RAX
     JMP .EndWithRAX
.EndWithLastError:
     WinABI GetLastError,Fastmode=No
.ErrorRAX:
     STC
.EndWithRAX:
    POP RSI,RBX,RCX
    RET 3*8
  ENDPROC1 FileRead64@RT::
 %ENDMACRO FileRead
FileCreate theFile
creates a new file or rewrites an existing file for writing.
Input
theFile is pointer to a FILE64 object.
Output
CF=0
RAX=0 (size of just rewritten file).
Error
CF=1
EAX=errorCode as returned from GetLastError.
FileCreate %MACRO theFile
         PUSHQ %theFile
         CALL FileCreate64@RT::
FileCreate64@RT:: PROC1
    IMPORT CreateFileA,CreateFileW
    PUSH RCX,RDX,RBX,RSI,RDI
     MOV RBX,[RSP+48]                ; theFile.
     LEA RDX,[RBX+FILE64.Name]
     SUB ESI,ESI
     MOV RDI,INVALID_HANDLE_VALUE
     MOV [RBX+FILE64.Size],RSI
     MOV [RBX+FILE64.Pos],RSI
     MOV [RBX+FILE64.Ptr],RSI
     MOV [RBX+FILE64.Top],RSI
     RstSt [RBX+FILE64.Status],fi64StStdIO
     LEA RAX,[CreateFileW]
     JSt [RBX+FILE64.Status],fi64StUnicode,.30:
     LEA RAX,[CreateFileA]          ; ANSI version.
     CMPB [RDX],0
     JNE .40:
 .20:SetSt [RBX+FILE64.Status],fi64StStdIO
     WinABI GetStdHandle,STD_OUTPUT_HANDLE,Fastmode=No
     JMP .60:
 .30:CMPW [RDX],0                   ; WIDE version.
     JE .20:
 .40:MOV RCX,OPEN_ALWAYS
     JSt [RBX+FILE64.Status],fi64StAppend,.50:
     MOV RCX,CREATE_ALWAYS
     MOV RSI,FILE_ATTRIBUTE_NORMAL
 .50:WinABI RAX,RDX,GENERIC_WRITE,FILE_SHARE_READ,0,RCX,RSI,0,Fastmode=No
 .60:MOV [RBX+FILE64.Handle],RAX
     CMP RAX,RDI
     JE .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StCreated
     MOV RCX,RAX
     SUB EAX,EAX
     JSt [RBX+FILE64.Status],fi64StStdIO, .EndWithRAX:
     SUB ESI,ESI
     WinABI GetFileSize,RCX,RSI,Fastmode=No
     CMP RAX,RDI
     JE .EndWithLastError:
     MOV [RBX+FILE64.Size],RAX
     JNSt [RBX+FILE64.Status],fi64StAppend,.EndWithRAX:
     MOV [RBX+FILE64.Pos],RAX
     WinABI SetFilePointer,[RBX+FILE64.Handle],RSI,RSI,FILE_END,Fastmode=No
     CMP RDI,RAX
     JA .EndWithRAX:
.EndWithLastError:
     WinABI GetLastError,Fastmode=No
     STC
.EndWithRAX:
    POP RDI,RSI,RBX,RDX,RCX
    RET 1*8
   ENDPROC1 FileCreate64@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 FILE64 object.
Output
CF=0
RAX= file size.
Error
CF=1
RAX=errorCode as returned from GetLastError.
Depends on
FileCreate
FileAppend %MACRO theFile
       PUSHQ %theFile
       CALL FileAppend64@RT::
 FileAppend64@RT:: PROC1
     PUSH RBX
       MOV RBX,[RSP+16]            ; theFile.
       SetSt [RBX+FILE64.Status],fi64StAppend
       FileCreate RBX
     POP RBX
     RET 1*8
   ENDPROC1 FileAppend64@RT::
 %ENDMACRO FileAppend
FileWriteRT
is a runtime defining macro used internally by FileWrite, FileWriteLn, FileWrite$.
Returns RAX=total written size.
FileWriteRT %MACRO ; Common runtime procedure declaration for macros FileWrite*
FileWrite64@RT: PROC1
     PUSHQ 0,RCX,RDX,RBX,RSI
      MOV RBX,[RSP+56]                  ; theFile.
      LEA RSI,[RSP+64]                  ; Address of 1st string ptr.
      MOV RAX,0xE0070004                ; File is not opened.
      JNSt [RBX+FILE64.Status],fi64StCreated, .ErrorRAX:
.Next:LODSQ                             ; DataPtr.
      MOV RDX,RAX
      TEST RAX
      JZ .Ret:                          ; End of data. CF=0, ZF=1.
      LODSQ                             ; DataSize.
      MOV RCX,RAX
      PUSH RAX
        MOV RAX,RSP
        WinABI WriteFile,[RBX+FILE64.Handle],RDX,RCX,RAX,0,Fastmode=No
        TEST RAX
      POP RAX                          ; Written size.
      JZ .GetLastError:
      ADD [RSP+32],RAX                 ; %ReturnRAX.
      ADD [RBX+FILE64.Pos],RAX
      ADD [RBX+FILE64.Size],RAX
      JMP .Next:
.GetLastError:
      WinABI GetLastError,Fastmode=No
.ErrorRAX:
      STC
      MOV [RSP+32],RAX
.Ret:POP RSI,RBX,RDX,RCX,RAX
     RET
FileWrite$size64@RT:
     PUSH RCX,RDI
      SUB ECX,ECX
      SUB EAX,EAX
      DEC RCX
      MOV RDI,[RSP+24]                ; DataPtr
      REPNE SCASB
      SUB RAX,RCX
      SUB RAX,2
      MOV [RSP+32],RAX                ; DataSize
     POP RDI,RCX
     RET
  ENDPROC1 FileWrite64@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 FILE64 object,
DataPtr* points to the data to be written,
DataSize* is the size of data in bytes.
Output
CF=0
RAX=total written size in bytes.
Error
CF=1
RAX=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
    PUSHQ 0 ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-2
      PUSHQ %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
     ADDQ [RSP],(%#+1)*8
     CALL FileWrite64@RT
    POP RSP
    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 FILE64 object,
DataPtr* points to the data to be written,
DataSize* is size of data in bytes.
Output
CF=0
RAX= is the total written size including CR+LF.
Error
CF=1
RAX= 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
    PUSHQ 0x00000A0D                  ; CR+LF.
    PUSHQ 0                           ; Mark the end of arguments.
    PUSHQ 2                           ; Size of CR+LF.
    PUSH RSP
    ADDQ [RSP],2*8                    ; Pointer to CR+LF.
    ArgNr %FOR %#..2, STEP=-2
      PUSHQ %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
     ADDQ [RSP],(%#+4)*8
     CALL FileWrite64@RT
    POP RSP
    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 FILE64 object,
DataPtr$* are pointers to zero terminated strings to be written.
Output
CF=0
RAX= total written size in bytes.
Error
CF=1
RAX= errorCode as returned from GetLastError.
Depends on
FileWriteRT
FileWrite$ %MACRO theFile,DataPtr1,DataPtr2,DataPtr3,,,
    PUSHQ 0 ; Mark the end of arguments
    ArgNr %FOR %#..2,STEP=-1
      PUSHQ RAX,%*{%ArgNr}
      CALL FileWrite$size64@RT
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
     ADDQ [RSP],2 * %# * 8
     CALL FileWrite64@RT
    POP RSP
    FileWriteRT         ; Invoke the common runtime macro.
  %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*
FileEnclose64@RT:: PROC1
     PUSHQ 0,RCX,RDX,RBX,RSI,RDI
      MOV RBX,[RSP+64]         ; theFile.
      SetSt [RBX+FILE64.Status],fi64StAppend
      FileCreate RBX
      JC .ErrorRAX:
      LEA RSI,[RSP+72]         ; Pointer to the 1st string pointer.
 .10: LODSQ                    ; DataPtr.
      MOV RDX,RAX
      TEST RAX
      JZ .90:                  ; End of data.
      LODSQ                    ; DataSize.
      MOV RCX,RAX
      PUSH RDI                 ; Make room for written size.
        MOV RDI,RSP
        WinABI WriteFile,[RBX+FILE64.Handle],RDX,RCX,RDI,0,Fastmode=No
      POP RDI                  ; Written size.
      ADD [RSP+40],RDI         ; %ReturnEAX.
      ADD [RBX+FILE64.Pos],RDI
      ADD [RBX+FILE64.Size],RDI
      TEST RAX                 ; WriteFile result.
      JNZ .10:                 ; If OK, write the next Data.
      WinABI GetLastError,Fastmode=No
 .ErrorRAX:
      STC
      MOV [RSP+28],RAX         ; %ReturnEAX.
 .90: PUSHFQ
        FileClose RBX
      POPFQ
     POP RDI,RSI,RBX,RDX,RCX,RAX
     RET
 FileEnclose$size64@RT::       ; Subprocedure for zero-terminated strings.
     PUSH RAX,RCX,RDI
      SUB ECX,ECX
      SUB EAX,EAX
      DEC RCX
      MOV RDI,[RSP+32]         ; DataPtr.
      REPNE SCASB
      SUB RAX,RCX
      SUB RAX,2
      MOV [RSP+40],RAX         ; DataSize.
     POP RDI,RCX,RAX
     RET
  ENDPROC1 FileEnclose64@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 FILE64 object with assigned name,
DataPtr* is pointer to the data to be written,
DataSize* is size of the data in bytes.
Output
CF=0
RAX= it total written size in bytes.
Error
CF=1
RAX= 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
    PUSHQ 0 ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-2
      PUSHQ %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
    ADDQ [RSP],(%#+1)*8
    CALL FileEnclose64@RT
    POP RSP
    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 FILE64 object with assigned name,
DataPtr* is pointer to the data to be written,
DataSize* is size of the data in bytes.
Output
CF=0
RAX= it total written size in bytes, including CR+LF.
Error
CF=1
RAX= 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
    PUSHQ 0x00000A0D        ; CR+LF
    PUSHQ 0                 ; Mark the end of arguments.
    PUSHQ 2                 ; Size of CR+LF.
    PUSH RSP
    ADDQ [RSP],2*8          ; Pointer to CR+LF.
    ArgNr %FOR %#..2,STEP=-2
      PUSHQ %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
     ADDQ [RSP],8*(%#+4)
     CALL FileEnclose64@RT
    POP RSP
    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 FILE64 object with assigned name,
DataPtr$* are pointers to zero-terminated ANSI strings. Terminating zeroes are not written to the file.
Output
CF=0
RAX= total written size.
Error
CF=1
RAX= is errorCode as returned by GetLastError.
Depends on
FileEncloseRT
Example
FileEnclose$ LogFile, Time$, =B" Job started"
FileEnclose$ %MACRO theFile,DataPtr1,DataPtr2,DataPtr3,,,
    PUSHQ 0 ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-1
      PUSHQ RAX,%*{%ArgNr}
      CALL FileEnclose$size64@RT ; Get length of string and write it to the stack.
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
     ADDQ [RSP],2 * %# * 8
     CALL FileEnclose64@RT
    POP RSP
    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 RSI.
The file must not be assigned with device or empty name.
Input
theFile is pointer to a FILE64 object.
Output
CF=0
RAX= file size,
RSI= pointer to the memory mapped file contents.
Error
CF=1
RSI=0
RAX= errorCode as returned fomr GetLastError.
FileMapOpen %MACRO theFile
       PUSHQ %theFile
       CALL FileMapOpen64@RT::
FileMapOpen64@RT:: PROC1
    IMPORT CreateFileA,CreateFileW,CreateFileMappingA,CreateFileMappingW
    PUSH RAX,RCX,RDX,RBX,RSI,RDI
     MOV RBX,[RSP+56]            ; theFile.
     LEA RDX,[RBX+FILE64.Name]
     SUB ESI,ESI
     MOV RDI,INVALID_HANDLE_VALUE
     MOV [RBX+FILE64.Ptr],RSI
     MOV [RBX+FILE64.Top],RSI
     MOV [RBX+FILE64.BufPtr],RSI
     MOV [RBX+FILE64.BufSize],RSI
     MOV [RBX+FILE64.Size],RSI
     MOV [RBX+FILE64.Pos],RSI
     MOV [RBX+FILE64.Handle],RDI
     MOV [RSP+08],RSI            ; ReturnRSI.
     LEA RAX,[CreateFileW]
     JSt [RBX+FILE64.Status],fi64StUnicode,.30:
     LEA RAX,[CreateFileA]       ; ANSI variant.
     CMPB [RDX],0
     JNE .40:
.20: MOV RAX,0xC0070000+123      ; "The file name is incorrect."
     JMP .ErrorRAX:
.30: CMPW [RDX],0                ; WIDE variant.
     JE .20:
.40: WinABI RAX,RDX,GENERIC_READ,FILE_SHARE_READ,RSI, \
           OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,RSI,Fastmode=No
     MOV [RBX+FILE64.Handle],RAX
     CMP RAX,RDI
     JE .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StOpened + fi64StFound
     WinABI GetFileSize,RAX,RSI,Fastmode=No
     CMP RAX,RDI
     JE .EndWithLastError:
     MOV [RBX+FILE64.Size],RAX
     MOV [RBX+FILE64.BufSize],RAX
     MOV [RBX+FILE64.Top],RAX
     MOV [RSP+40],RAX             ; ReturnRAX.
     LEA RAX,[CreateFileMappingW]
     JSt [RBX+FILE64.Status],fi64StUnicode,.50:
     LEA RAX,[CreateFileMappingA]
.50: WinABI RAX,[RBX+FILE64.Handle],RSI,PAGE_READONLY,RSI,RSI,RSI,Fastmode=No
     MOV [RBX+FILE64.MapHandle],RAX
     TEST RAX
     JZ .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StMapOpened
     WinABI MapViewOfFile,RAX,FILE_MAP_READ,RSI,RSI,RSI
     MOV [RBX+FILE64.Ptr],RAX
     MOV [RSP+08],RAX            ; ReturnRSI.
     ADD [RBX+FILE64.Top],RAX
     MOV [RBX+FILE64.BufPtr],RAX
     TEST RAX
     JZ .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StMapped
     JMP .Ret:
.EndWithLastError:
     WinABI GetLastError,Fastmode=No
.ErrorRAX:
     STC
     MOV [RSP+40],EAX           ; ReturnRAX.
.Ret:POP RDI,RSI,RBX,RDX,RCX,RAX
    RET 1*8
  ENDPROC1 FileMapOpen64@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 RDI but not more than FileSize bytes.
The file must not be assigned with device or empty name.
Input
theFile is pointer to a FILE64 object.
FileSize is the size of memory mapped file. It may be omitted when FileMapCreate opens an existing file.
Output
CF=0
RAX=FileSize
RDI= is pointer to the memory mapped file content.
Error
CF=1
RDI=0
RAX= errorCode as returned from GetLastError.
FileMapCreate %MACRO theFile,FileSize
       %IF %# > 1
         PUSHQ %FileSize
       %ELSE
         PUSHQ 0
       %ENDIF
       PUSHQ %theFile
       CALL FileMapCreate64@RT::
FileMapCreate64@RT:: PROC1
     IMPORT CreateFileA,CreateFileW,CreateFileMappingA,CreateFileMappingW
     PUSH RCX,RDX,RBX,RSI,0
      MOV RBX,[RSP+48]               ; theFile.
      LEA RDX,[RBX+FILE64.Name]
      SUB ESI,ESI
      MOV RDI,INVALID_HANDLE_VALUE
      RstSt [RBX+FILE64.Status],fi64StAppend
      MOV [RBX+FILE64.Ptr],RSI
      MOV [RBX+FILE64.Top],RSI
      MOV [RBX+FILE64.BufPtr],RSI
      MOV [RBX+FILE64.BufSize],RSI
      MOV [RBX+FILE64.Size],RSI
      MOV [RBX+FILE64.Pos],RSI
      MOV [RBX+FILE64.Handle],RDI
      LEA RAX,[CreateFileW]
      JSt [RBX+FILE64.Status],fi64StUnicode,.30:
      LEA RAX,[CreateFileA]
      CMPB [RDX],0
      JNE .40:
 .20: MOV RAX,0xC0070000+123 ; "Error: The file name is incorrect."
      JMP .ErrorRAX:
 .30: CMPW [RDX],0
      JE .20:
 .40: WinABI RAX,RDX,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE, \
             RSI,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,RSI,Fastmode=No
      MOV [RBX+FILE64.Handle],RAX
      CMP RAX,RDI
      JE .EndWithLastError:
      SetSt [RBX+FILE64.Status],fi64StCreated
      MOV RCX,[RSP+56]        ; FileSize.
      TEST RCX
      JNZ .45:
      WinABI GetFileSize,[RBX+FILE64.Handle],RCX,Fastmode=No
      MOV RCX,RAX
      INC RAX
      JZ .EndWithLastError:
 .45: MOV [RBX+FILE64.Size],RCX
      MOV [RBX+FILE64.BufSize],RCX
      MOV [RBX+FILE64.Top],RCX
      LEA RAX,[CreateFileMappingW]
      JSt [RBX+FILE64.Status],fi64StUnicode,.50:
      LEA RAX,[CreateFileMappingA]
 .50: WinABI RAX,[RBX+FILE64.Handle],RSI,PAGE_READWRITE,RSI,RCX,RSI,Fastmode=No
      MOV [RBX+FILE64.MapHandle],RAX
      TEST RAX
      JZ .EndWithLastError:
      SetSt [RBX+FILE64.Status],fi64StMapCreated
      WinABI MapViewOfFile,RAX,FILE_MAP_WRITE,RSI,RSI,RSI,Fastmode=No
      MOV [RBX+FILE64.Ptr],RAX
      ADD [RBX+FILE64.Top],RAX
      MOV [RBX+FILE64.BufPtr],RAX
      MOV [RSP+00],RAX          ; ReturnRDI.
      TEST RAX
      JZ .EndWithLastError:
      SetSt [RBX+FILE64.Status],fi64StMapped
      MOV RAX,RCX
      JMP .Ret:
.EndWithLastError:
      WinABI GetLastError,Fastmode=No
.ErrorRAX:
      STC
.Ret:POP RDI,RSI,RBX,RDX,RCX
     RET 2*8
   ENDPROC1 FileMapCreate64@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 FILE64 object.
BuffSize= specifies the buffer size.
Output
CF=0
RAX= file size.
Error
CF=1
RAX= errorCode as returned from GetLastError.
Depends on
FileOpen
FileStreamOpen %MACRO theFile,BufSize=16K
       PUSH %BufSize,%theFile
       CALL FileStreamOpen64@RT::
FileStreamOpen64@RT:: PROC1
     PUSH RCX,RBX
      MOV RBX,[RSP+24]       ; theFile.
      MOV RCX,[RSP+32]       ; BufSize.
      MOV [RBX+FILE64.BufSize],RCX
      WinABI GlobalAlloc,GMEM_FIXED,RCX,Fastmode=No
      TEST RAX
      JZ .EndWithLastError:
      MOV [RBX+FILE64.BufPtr],RAX
      MOV RDI,RAX
      SetSt [RBX+FILE64.Status],fi64StAllocated
      FileOpen RBX
      MOV [RBX+FILE64.Ptr],RDI
      MOV [RBX+FILE64.Top],RDI
      JNC .EndWithRAX
.EndWithLastError:
      WinABI GetLastError,Fastmode=No
      STC
.EndWithRAX:
     POP RBX,RCX
     RET 2*8
  ENDPROC1 FileStreamOpen64@RT::
 %ENDMACRO FileStreamOpen
FileStreamRead theFile, DataPtr, DataSize
reads data from the file opened with FileStreamOpen.
Input
theFile is pointer to a FILE64 object.
DataPtr points to a memory area allocated by the caller,
DataSize is amount of bytes to read.
Output
CF=0
ZF=0
RAX= how many bytes was read (may be less the DataSize).
End of file
CF=0
ZF=1
RAX= 0 when there are no more bytes in the file (EOF).
error
CF=1
RAX= errorCode as returned from GetLastError.
FileStreamRead %MACRO theFile,DataPtr,DataSize
       PUSHQ %DataSize,%DataPtr,%theFile
       CALL FileStreamRead64@RT::
FileStreamRead64@RT:: PROC1
      PUSH RCX,RDX,RBX,RSI,RDI
        SUB EDX,EDX
        MOV RBX,[RSP+48]          ; theFile.
        MOV RDI,[RSP+56]          ; DataPtr.
 .10:   MOV RSI,[RBX+FILE64.Ptr]
 .20:   MOV RCX,[RBX+FILE64.Top]
        SUB RCX,RSI
        JNA .50:
        CMP RCX,[RSP+64]          ; DataSize.
        JA .30:
        SUB [RSP+64],RCX          ; DataSize.
        ADD RDX,RCX
        REP MOVSB
        MOV [RBX+FILE64.Ptr],RSI
        JMP .20:
 .30:   MOV RCX,[RSP+64]          ; DataSize.
        ADD RDX,RCX
        REP MOVSB
        MOV [RBX+FILE64.Ptr],RSI
        JMP .70:
 .50:   MOV RSI,[RBX+FILE64.BufPtr]
        MOV [RBX+FILE64.Ptr],RSI
        MOV [RBX+FILE64.Top],RSI
        PUSH RCX
          MOV RCX,RSP
          WinABI ReadFile,[RBX+FILE64.Handle],RSI,[RBX+FILE64.BufSize],RCX,0,Fastmode=No
        POP RCX
        TEST RAX
        JZ .EndWithLastError:
        JRCXZ .70:                ; EOF
        ADD [RBX+FILE64.Top],RCX
        JMP .20:
 .70:   MOV RAX,RDX
        ADD [RBX+FILE64.Pos],RDX
        TEST RAX
        JMP .EndWithRAX           ; ZF if RAX=0.
.EndWithLastError:
        WinABI GetLastError,Fastmode=No
.ErrorRAX:
        STC
.EndWithRAX:
.90: POP RDI,RSI,RBX,RDX,RCX
      RET 3*8
  ENDPROC1 FileStreamRead64@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 FILE64 object.
Output
CF=0
ZF=0
RAX= line size (never bigger than the FILE64.BufSize)
RSI= pointer to the line in buffer.
End of file
CF=0
ZF=1
RAX=0 when there are no more data in file (EOF).
error
CF=1
RAX= errorCode as returned from GetLastError.
FileStreamReadLn %MACRO theFile
      PUSHQ %theFile
      CALL FileStreamReadLn64@RT::
FileStreamReadLn64@RT:: PROC1
    PUSH 0,RCX,RDX,RBX,RSI,RDI
      MOV RBX,[RSP+56]          ; theFile.
      MOV RAX,0xE0070004        ; File is not open.
      JNSt [RBX+FILE64.Status],fi64StOpened,.ErrorRAX:
      JNSt [RBX+FILE64.Status],fi64StAllocated,.ErrorRAX:
      MOV RDI,[RBX+FILE64.Ptr]
      MOV RCX,[RBX+FILE64.Top]
.10:  MOV [RSP+08],RDI         ; ReturnRSI.
      MOV RDX,RDI
      SUB RCX,RDI
      JNA .30:
      MOV AL,10 ; LineFeed
      REPNE SCASB
      JE .50:
      CMP RDX,[RBX+FILE64.BufPtr]
      JE .50:
      ; When the 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 RDX,RDI
      WinABI SetFilePointer,[RBX+FILE64.Handle],RDX,0,FILE_CURRENT,Fastmode=No
.30:  MOV RDI,[RBX+FILE64.BufPtr]
      MOV [RBX+FILE64.Ptr],RDI
      MOV [RBX+FILE64.Top],RDI
      PUSH RCX
       MOV RCX,RSP
       WinABI ReadFile,[RBX+FILE64.Handle],RDI,[RBX+FILE64.BufSize],RCX,0,Fastmode=No
      POP RCX
      TEST RAX
      JZ .EndWithLastError:
      JRCXZ .70:                  ; EOF
      ADD RCX,RDI
      MOV [RBX+FILE64.Top],RCX
      JMP .10:
.50:  MOV [RBX+FILE64.Ptr],RDI
      SUB RDI,RDX
      MOV [RSP+40],RDI            ; ReturnRAX.
      ADD [RBX+FILE64.Pos],RDI
      JMP .90:
.70:  SUB EAX,EAX
      JMP .EndWithRAX:
.EndWithLastError:
      WinABI GetLastError,Fastmode=No
.ErrorRAX:
      STC
.EndWithRAX:
      MOV [RSP+40],RAX            ; ReturnRAX.
.90:POP RDI,RSI,RBX,RDX,RCX,RAX
    RET 1*8
 ENDPROC1 FileStreamReadLn64@RT::
%ENDMACRO FileStreamReadLn
FileStreamReadByte theFile
reads one byte from the file opened with FileStreamOpen.
Input
theFile is pointer to a FILE64 object.
Output
CF=0
ZF=0
AL= the byte read from file. Upper 7 bytes in RAX are preserved.
End of file
CF=0
ZF=1
AL=0 when there are no more bytes in the file (EOF).
Error
CF=1
RAX= errorCode as returned from GetLastError.
FileStreamReadByte %MACRO theFile
     PUSHQ %theFile
     CALL FileStreamReadByte64@RT::
FileStreamReadByte64@RT:: PROC1
     PUSH RAX,RCX,RBX,RSI,RDI
      MOV RBX,[RSP+48]
 .10: MOV RSI,[RBX+FILE64.Ptr]
      CMP RSI,[RBX+FILE64.Top]
      JB .50:                      ; Buffer is not empty.
      MOV RAX,0xE0070004           ; File is not open.
      JNSt [RBX+FILE64.Status],fi64StOpened,.ErrorRAX:
      JNSt [RBX+FILE64.Status],fi64StAllocated,.ErrorRAX:
      MOV RDI,[RBX+FILE64.BufPtr]
      MOV [RBX+FILE64.Ptr],EDI
      MOV [RBX+FILE64.Top],EDI
      PUSH RCX
       MOV RCX,RSP
       WinABI ReadFile,[RBX+FILE64.Handle],RDI,[RBX+FILE64.BufSize],RCX,0,Fastmode=No
      POP RCX
      TEST RAX
      JZ .EndWithLastError:
      ADD [RBX+FILE64.Top],RCX
      TEST RCX
      JNZ .10
      MOV RAX,[RSP+32]      ; ReturnRAX.
      XOR AL,AL             ; Set ZF=1.
      JMP .EndWithRAX:
.EndWithLastError:
      WinABI GetLastError,Fastmode=No
.ErrorRAX:
      STC
      JMP .EndWithRAX:
 .50: MOV RAX,[RSP+32]      ; ReturnRAX.
      LODSB
      MOV [RBX+FILE64.Ptr],RSI
      INCQ [RBX+FILE64.Pos]
      CLC
.EndWithRAX:
      MOV [RSP+32],RAX
     POP RDI,RSI,RBX,RCX,RAX
     RET 1*8
  ENDPROC1 FileStreamReadByte64@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 FILE64 object,
BuffSize= specifies the buffer size.
Output
CF=0
RAX=0 (size of just rewritten file).
Error
CF=1
RAX= errorCode as returned from GetLastError.
Depends on
FileCreate
FileStreamCreate %MACRO theFile,BufSize=16K
       PUSHQ %BufSize,%theFile
       CALL FileStreamCreate64@RT::
FileStreamCreate64@RT:: PROC1
    PUSH RCX,RBX,RSI,RDI
     MOV RBX,[RSP+40]          ; theFile.
     MOV RCX,[RSP+48]          ; BufSize.
     MOV [RBX+FILE64.BufSize],RCX
     MOV RDI,RCX
     WinABI GlobalAlloc,GMEM_FIXED,RCX,Fastmode=No
     TEST RAX
     JZ .EndWithLastError:
     SetSt [RBX+FILE64.Status],fi64StAllocated
     MOV [RBX+FILE64.BufPtr],RAX
     ADD RDI,RAX
     MOV RSI,RAX
     FileCreate RBX
     MOV [RBX+FILE64.Ptr],RSI
     MOV [RBX+FILE64.Top],RDI
     JNC .EndWithRAX
.EndWithLastError:
     WinABI GetLastError,Fastmode=No
     STC
.EndWithRAX:
    POP RDI,RSI,RBX,RCX
    RET 2*8
  ENDPROC1 FileStreamCreate64@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 FILE64 object,
BuffSize= specifies the buffer size.
Output
CF=0
RAX= is the old file size.
Error
CF=1
RAX= errorCode as returned from GetLastError.
Depends on
FileStreamCreate
FileStreamAppend %MACRO theFile,BufSize=16K
       PUSHQ %BufSize,%theFile
       CALL FileStreamAppend64@RT::
FileStreamAppend64@RT:: PROC1
     PUSH RBX,RCX
       MOV RBX,[RSP+24] ; theFile.
       MOV RCX,[RSP+32] ; BufSize.
       SetSt [RBX+FILE64.Status],fi64StAppend
       FileStreamCreate RBX,RCX
     POP RCX,RBX
     RET 2*8
   ENDPROC1 FileStreamAppend64@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 FILE64 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
      PUSHQ %theFile
      CALL FileStreamWriteByte64@RT::
FileStreamWriteByte64@RT:: PROC1
    PUSH RAX,RCX,RDX,RBX,RDI
     MOV RBX,[RSP+48]          ; theFile.
.10: MOV RDI,[RBX+FILE64.Ptr]
     CMP RDI,[RBX+FILE64.Top]
     JB .50:
     FileFlush RBX             ; If buffer is full.
     JNC .10:
     MOV [RSP+32],RAX          ; ReturnRAX.
     JMP .90:
.50: STOSB
     MOV RAX,[RBX+FILE64.Pos]
     MOV [RBX+FILE64.Ptr],RDI
     ADD RAX,1
     MOV [RBX+FILE64.Pos],RAX
     MOV [RBX+FILE64.Size],RAX
     CLC
.90:POP RDI,RBX,RDX,RCX,RAX
    RET 1*8
 ENDPROC1 FileStreamWriteByte64@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 FILE64 object,
AX contains the data word to write.
Output
CF=0, registers unchanged.
Error
CF=1
RAX= errorCode as returned from GetLastError.
Depends on
FileFlush
FileStreamWriteWord %MACRO theFile
      PUSHQ %theFile
      CALL FileStreamWriteWord64@RT::
FileStreamWriteWord64@RT:: PROC1
    PUSH RAX,RCX,RDX,RBX,RDI
     MOV RBX,[RSP+48]          ; theFile.
.10: MOV RDI,[RBX+FILE64.Ptr]
     LEA RDX,[RDI+1]
     CMP RDX,[RBX+FILE64.Top]
     JB .50
     FileFlush RBX             ; If buffer full.
     JNC .10:
     MOV [RSP+32],RAX          ; ReturnRAX.
     JMP .90:
.50: STOSW
     MOV RAX,[RBX+FILE64.Pos]
     MOV [RBX+FILE64.Ptr],RDI
     ADD RAX,2
     MOV [RBX+FILE64.Pos],RAX
     MOV [RBX+FILE64.Size],RAX
     CLC
.90:POP RDI,RBX,RDX,RCX,RAX
    RET 1*8
 ENDPROC1 FileStreamWriteWord64@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 FILE64 object,
EAX contains the data word to write.
Output
CF=0, registers unchanged.
Error
CF=1
RAX= errorCode as returned from GetLastError.
Depends on
FileFlush
FileStreamWriteDword %MACRO theFile
      PUSHQ %theFile
      CALL FileStreamWriteDword64@RT::
FileStreamWriteDword64@RT:: PROC1
    PUSH RAX,RCX,RDX,RBX,RDI
     MOV RBX,[RSP+48]           ; theFile.
.10: MOV RDI,[RBX+FILE64.Ptr]
     LEA RDX,[RDI+3]
     CMP RDX,[RBX+FILE64.Top]
     JB .50
     FileFlush RBX              ; If buffer full.
     JNC .10:
     MOV [RSP+32],RAX           ; ReturnRAX.
     JMP .90:
.50: STOSD
     MOV RAX,[RBX+FILE64.Pos]
     MOV [RBX+FILE64.Ptr],RDI
     ADD RAX,4
     MOV [RBX+FILE64.Pos],RAX
     MOV [RBX+FILE64.Size],RAX
     CLC
.90:POP RDI,RBX,RDX,RCX,RAX
    RET 1*8
 ENDPROC1 FileStreamWriteDword64@RT::
%ENDMACRO FileStreamWriteDword
FileStreamWriteRT
is a runtime defining macro used internally by FileStreamWrite*.
Macro returns CF=0, RAX=total written size, or CF=error
Depends on
FileFlush
FileStreamWriteRT %MACRO ; Common runtime procedure for macros FileStreamWrite*
FileStreamWrite64@RT: PROC1
    PUSHQ 0,RCX,RDX,RBX,RBP,RSI,RDI
     MOV RBX,[RSP+72]             ; theFile.
     LEA RSI,[RSP+80]             ; Pointer to Data1Ptr.
     MOV RAX,0xE0070004           ; File was not opened.
     JNSt [RBX+FILE64.Status],fi64StCreated,.ErrorRAX:
     JNSt [RBX+FILE64.Status],fi64StAllocated,.ErrorRAX:
     SUB EAX,EAX
     MOV [RSP+48],EAX             ; ReturnRAX
.Next:LODSQ                        ; DataPtr.
     MOV RBP,RAX
     TEST RAX
     JZ .Ret:                     ; End of data.
     LODSQ                        ; DataSize.
     MOV RDX,RAX
     ADD [RSP+48],RAX             ; ReturnRAX
     CALL .FileStreamStoreData:
     JNC .Next:
.ErrorRAX:
     STC
     MOV [RSP+48],RAX             ; ReturnRAX
.Ret:POP RDI,RSI,RBP,RBX,RDX,RCX,RAX
    RET
.FileStreamStoreData: ; Copy data to FileStream buffer
; INP: RBX=^FILE64, RBP=DataPtr, RDX=DataSize.
; OUT: CF=error, RAX=error, EBX,ESI preserved, FILE64 updated.
    PUSH RSI
     MOV RSI,RBP
.S1: TEST RDX
     JZ .S9
.S2: MOV RCX,[RBX+FILE64.Top]
     MOV RDI,[RBX+FILE64.Ptr]
     SUB RCX,RDI
     JNZ .S3
     FileFlush RBX
     JNC .S2:
     JMP .S9:
.S3: CMP RCX,RDX
     JBE .S4:
     MOV RCX,RDX
.S4: SUB RDX,RCX
     ADD [RBX+FILE64.Ptr],RCX
     ADD [RBX+FILE64.Pos],RCX
     ADD [RBX+FILE64.Size],RCX
     REP MOVSB
     JMP .S1:
.S9:POP RSI
    RET
FileStreamWrite$size64@RT::
    PUSH RAX,RCX,RDI
     SUB ECX,ECX
     SUB EAX,EAX
     DEC RCX
     MOV RDI,[RSP+32] ; DataPtr
     REPNE SCASB
     SUB RAX,RCX
     SUB RAX,2
     MOV [RSP+40],RAX ; DataSize
    POP RDI,RCX,RAX
    RET
 ENDPROC1 FileStreamWrite64@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 FILE64 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 at opening the file.
Output
CF=0
RAX= Total written size in bytes.
Error
CF=1
RAX= 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
    PUSHQ 0 ; Mark the end of arguments.
    ArgNr %FOR %#..2,STEP=-2
      PUSHQ %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
     ADDQ [RSP],(%#+1)*8
     CALL FileStreamWrite64@RT
    POP RSP
    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 FILE64 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
RAX= total written size including CR+LF.
Error
CF=1
RAX= 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
    PUSHQ 0x00000A0D               ; CR+LF.
    PUSHQ 0                        ; Mark the end of arguments.
    PUSHQ 2                        ; Size of CR+LF.
    PUSH  RSP
    ADDD [RSP],2*8                 ; Pointer to CR+LF.
    ArgNr %FOR %#..2,STEP=-2
      PUSHQ %*{%ArgNr}, %*{%ArgNr-1}
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
     ADDQ [RSP],(%#+4)*8
     CALL FileStreamWrite64@RT
    POP RSP
    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 ASCIIZ strings may be written in one macro invocation. The terminating zeros are not written to the file.
Input
theFile is pointer to an open FILE64 object,
DataPtr$* are pointers to the zero terminated strings to be written.
Output
CF=0
RAX= total written size.
Error
CF=1
RAX= errorCode as returned from GetLastError.
Depends on
FileStreamWriteRT
FileStreamWrite$ %MACRO theFile,DataPtr1,DataPtr2,DataPtr3,,,
    PUSHQ 0 ; mark end of arguments
    ArgNr %FOR %#..2,STEP=-1
      PUSHQ RAX,%*{%ArgNr}
      CALL FileStreamWrite$size64@RT::
    %ENDFOR ArgNr
    PUSHQ %theFile
    PUSH RSP
     ADDQ [RSP],2 * %# * 8
     CALL FileStreamWrite64@RT
    POP RSP
    FileStreamWriteRT             ; Invoke the common runtime macro.
  %ENDMACRO FileStreamWrite$
  ENDHEAD winf64

▲Back to the top▲