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 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 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 method | Virtual memory | |
---|---|---|
reserved | comitted | |
At once load | filesize | filesize |
At once store | none | none |
Standard | none | none |
MemoryMapped | filesize | pagesize |
Streamed | buffersize | buffersize |
File access method at once loads entire file content into comitted memory, so it is suitable for small files only. The loaded/stored file doesn't need explicit opening nor closing.
This access method is equivalent to PHP functions file_get_contents, file_put_contents.
Access method enclose opens the file at its end for writing, appends the data and closes file in one operation.
Standard read/write methods only encapsulate API functions read/write and they can process files of any size. Example:
Memory mapped file access reserves memory for the entire file contents virtually loaded to memory.
Streamed (buffered) file access method allocates its own memory buffer to accelerate reading/writing of small pieces of data. This method is also suitable for processing text files line by line. Example:
Common limitations: This library cannot be used if special requirements are required, such as overlapped file access, other than normal file attributes, nonstandard share disposition, files bigger than 2 GB, filename longer than 260 characters.
Runtime procedures defined in this library use macros WinABI, Dispatch, status32.htm.
swinf64 HEAD INCLUDEHEAD1 winsfile.htm, wins.htm, winabi.htm, winscon.htm, status32.htm, cpuext.htm
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
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.
%^UNICODE
at macro invocation
but you may want to set this parameter to 0 even if %UNICODE is enabled and vice versa.FileNameParse %MACRO FileNamePtr,Size=-1, Unicode=%^UNICODE 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
theFile.Name
member.
EUROASM UNICODE=
option at macro invocation,
but you may want to set this parameter to 0 even if UNICODE is globally enabled, and vice versa..Name, .NameOffs, .ExtOffs, .Status:fi64StUnicode
of theFile
are set.SIZE# FILE64.Name
, i.e. MAX_PATH_SIZE=260 characters.FileAssign %MACRO theFile,Name$1,Name$2,,, Size=-1, Unicode=%^UNICODE %IF %#<2 ; > %ERROR ID=5941, 'File name missing in macro "FileAssign".' %EXITMACRO FileAssign %ENDIF 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
* ?
are allowed in the file name.
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 %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 %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 %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 %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 %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
FILE64.Name
is replaced
with the file found in directory. The file is not open.
WinABI FindClose,RDX
before terminating.
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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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$ %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 %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 %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 %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$ %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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$ %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