; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "Fresh artistic license."         |
;|_______________________________________________________________________________________|
;
;  Description: Files manipulation library. Win32 part.
;
;  Target OS: Win32
;
;  Dependencies:
;
;  Notes:
;_________________________________________________________________________________________

fsFromBegin     = FILE_BEGIN
fsFromEnd       = FILE_END
fsFromCurrent   = FILE_CURRENT

if used STDIN | used STDOUT | used STDERR

initialize InitStdHandles
begin
  if used STDIN
        invoke  GetStdHandle, STD_INPUT_HANDLE
        mov     [__std_handles], eax
  end if

  if used STDOUT
        invoke  GetStdHandle, STD_OUTPUT_HANDLE
        mov     [__std_handles+4], eax
  end if

  if used STDERR
        invoke  GetStdHandle, STD_ERROR_HANDLE
        mov     [__std_handles+8], eax
  end if
        return
endp

end if

;--------------------------------------
; if CF = 0, eax is handle to the file.
; if CF = 1, eax is error code.
;--------------------------------------
proc FileOpen, .filename
begin
        push    edx ecx

if GlobalAPI eq unicode
        stdcall utf8ToWideChar, [.filename]
        push    eax
else
        stdcall StrPtr, [.filename]
end if
        invoke  CreateFile, eax, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0

if GlobalAPI eq unicode
        stdcall FreeMem ; from the stack
end if

        cmp     eax, INVALID_HANDLE_VALUE
        je      .error

        clc
        pop     ecx edx
        return

.error:
        invoke  GetLastError
        stc
        pop     ecx edx
        return
endp



proc FileCreate, .filename
begin
        push    edx ecx

if GlobalAPI eq unicode
        stdcall utf8ToWideChar, [.filename]
        push    eax
else
        stdcall StrPtr, [.filename]
end if
        invoke  CreateFile, eax, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0

if GlobalAPI eq unicode
        stdcall FreeMem ; from the stack
end if
        cmp     eax, INVALID_HANDLE_VALUE
        je      .error

        clc
        pop     ecx edx
        return

.error:
        invoke  GetLastError
        stc
        pop     ecx edx
        return
endp




proc FileClose, .handle
begin
        push    edx ecx eax
        invoke  CloseHandle, [.handle]
        test    eax, eax
        jz      .error

        clc
        pop     eax ecx edx
        return

.error:
        pop     eax
        invoke  GetLastError
        stc
        pop     ecx edx
        return
endp


; returns 32bit file size in eax
proc FileSize, .handle
begin
        push    edx ecx

        xor     eax, eax
        invoke  GetFileSize, [.handle], eax
        cmp     eax, -1
        je      .error

        clc
        pop     ecx edx
        return

.error:
        invoke  GetLastError
        stc
        pop     ecx edx
        return
endp



proc FileRead, .handle, .buffer, .count
.read dd ?
begin
        push    edx ecx

        lea     eax, [.read]
        invoke  ReadFile, [.handle], [.buffer], [.count], eax, 0
        test    eax, eax
        jz      .error

        mov     eax, [.read]
        clc
        pop     ecx edx
        return

.error:
        invoke  GetLastError
        stc
        pop     ecx edx
        return
endp




proc FileWrite, .handle, .buffer, .count
.bytes dd ?
begin
        push    edx ecx

        lea     ecx, [.bytes]
        invoke  WriteFile, [.handle], [.buffer], [.count], ecx, NULL
        test    eax, eax
        jz      .error

        mov     eax, [.bytes]
        clc
        pop     ecx edx
        return

.error:
        invoke  GetLastError
        stc
        pop     ecx edx
        return
endp




;----------------------------------------------------
; if CF = 0, eax is the new possition in the file
; if CF = 1, eax is error code.
;----------------------------------------------------
proc FileSeek, .handle, .dist, .direction
begin
        push    edx ecx
        invoke  SetFilePointer, [.handle], [.dist], 0, [.direction]
        cmp     eax, -1
        je      .error

        clc
        pop     ecx edx
        return

.error:
        invoke  GetLastError
        stc
        pop     ecx edx
        return
endp



;----------------------------------------------------
; if CF = 0 - the file was deleted
; if CF = 1, eax is error code.
;----------------------------------------------------
proc FileDelete, .filename
begin
        push    ecx edx eax

if GlobalAPI eq unicode
        stdcall utf8ToWideChar, [.filename]
        push    eax
else
        stdcall StrPtr, [.filename]
end if
        invoke  DeleteFile, eax

if GlobalAPI eq unicode
        stdcall FreeMem ; from the stack
end if
        test    eax, eax
        jz      .error
        clc
        pop     eax edx ecx
        return

.error:
        pop     eax
        invoke  GetLastError
        stc
        pop     edx ecx
        return
endp







proc GetErrorString, .code
.buff dd ?
begin
        push    edx ecx
        lea     eax, [.buff]

        if GlobalAPI eq ascii
          invoke  FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, 0, [.code], LANG_NEUTRAL or SUBLANG_DEFAULT, eax, 0, 0
        else
          invoke  FormatMessageA, FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, 0, [.code], LANG_NEUTRAL or SUBLANG_DEFAULT, eax, 0, 0
        end if
        mov     eax, [.buff]
        clc
        pop     ecx edx
        return
endp



proc FreeErrorString, .ptrString
begin
        push    edx ecx
        invoke  LocalFree, [.ptrString]
        pop     ecx edx
        return
endp
