/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a zlib-style license that can
 *  be found in the License.txt file in the root of the source tree.
 */
 
//---------------------------------------------------------------------------
#include "ZenLib/PreComp.h"
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
#include "ZenLib/Conf_Internal.h"
//---------------------------------------------------------------------------
 
#include "ZenLib/FileName.h"
//---------------------------------------------------------------------------
#ifdef ZENLIB_USEWX
    #include <wx/file.h>
    #include <wx/filename.h>
    #include <wx/utils.h>
#else //ZENLIB_USEWX
    #ifdef ZENLIB_STANDARD
        #ifdef WINDOWS
        #else
            #include <cstdio>
        #endif
        #include <sys/stat.h>
        #if !defined(WINDOWS)
            #include <unistd.h>
        #endif //!defined(WINDOWS)
        #include <fstream>
        using namespace std;
        #ifndef S_ISDIR
            #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
        #endif
        #ifndef S_ISREG
            #define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
        #endif
    #elif defined WINDOWS
        #undef __TEXT
        #include <windows.h>
        #ifdef WINDOWS_UWP
            #include <wrl.h>
            #include <windows.foundation.h>
            #include <windows.storage.h>
            #include <windows.storage.accesscache.h>
            using namespace Microsoft::WRL;
            using namespace Microsoft::WRL::Wrappers;
            using namespace ABI::Windows::Foundation;
            using namespace ABI::Windows::Foundation::Collections;
            using namespace ABI::Windows::Storage;
            using namespace ABI::Windows::Storage::Streams;
            using namespace ABI::Windows::Storage::FileProperties;
        #endif
    #endif
#endif //ZENLIB_USEWX
#include "ZenLib/OS_Utils.h"
#include "ZenLib/File.h"
 
//---------------------------------------------------------------------------
#ifdef WINDOWS_UWP
struct WrtFile
{
    ComPtr<IStorageFile> File;
    ComPtr<IRandomAccessStream> Buffer;
};
#endif
 
//---------------------------------------------------------------------------
namespace ZenLib
{
 
//---------------------------------------------------------------------------
// Debug
#ifdef ZENLIB_DEBUG
    #include <stdio.h>
    #include <windows.h>
    namespace ZenLib_File_Debug
    {
        FILE* F;
        std::string Debug;
        SYSTEMTIME st_In;
 
        void Debug_Open(bool Out)
        {
            F=fopen("C:\\Temp\\ZenLib_Debug.txt", "a+t");
            Debug.clear();
            SYSTEMTIME st;
            GetLocalTime( &st );
 
            char Duration[100];
            if (Out)
            {
                FILETIME ft_In;
                if (SystemTimeToFileTime(&st_In, &ft_In))
                {
                    FILETIME ft_Out;
                    if (SystemTimeToFileTime(&st, &ft_Out))
                    {
                        ULARGE_INTEGER UI_In;
                        UI_In.HighPart=ft_In.dwHighDateTime;
                        UI_In.LowPart=ft_In.dwLowDateTime;
 
                        ULARGE_INTEGER UI_Out;
                        UI_Out.HighPart=ft_Out.dwHighDateTime;
                        UI_Out.LowPart=ft_Out.dwLowDateTime;
 
                        ULARGE_INTEGER UI_Diff;
                        UI_Diff.QuadPart=UI_Out.QuadPart-UI_In.QuadPart;
 
                        FILETIME ft_Diff;
                        ft_Diff.dwHighDateTime=UI_Diff.HighPart;
                        ft_Diff.dwLowDateTime=UI_Diff.LowPart;
 
                        SYSTEMTIME st_Diff;
                        if (FileTimeToSystemTime(&ft_Diff, &st_Diff))
                        {
                            sprintf(Duration, "%02hd:%02hd:%02hd.%03hd", st_Diff.wHour, st_Diff.wMinute, st_Diff.wSecond, st_Diff.wMilliseconds);
                        }
                        else
                            strcpy(Duration, "            ");
                    }
                    else
                        strcpy(Duration, "            ");
 
                }
                else
                    strcpy(Duration, "            ");
            }
            else
            {
                st_In=st;
                strcpy(Duration, "            ");
            }
 
            fprintf(F,"                                       %02hd:%02hd:%02hd.%03hd %s", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, Duration);
        }
 
        void Debug_Close()
        {
            Debug += "\r\n";
            fwrite(Debug.c_str(), Debug.size(), 1, F); \
            fclose(F);
        }
    }
    using namespace ZenLib_File_Debug;
 
    #define ZENLIB_DEBUG1(_NAME,_TOAPPEND) \
        Debug_Open(false); \
        Debug+=", ";Debug+=_NAME; \
        _TOAPPEND; \
        Debug_Close();
 
    #define ZENLIB_DEBUG2(_NAME,_TOAPPEND) \
        Debug_Open(true); \
        Debug+=", ";Debug+=_NAME; \
        _TOAPPEND; \
        Debug_Close();
#else // ZENLIB_DEBUG
    #define ZENLIB_DEBUG1(_NAME,_TOAPPEND)
    #define ZENLIB_DEBUG2(_NAME,_TOAPPEND)
#endif // ZENLIB_DEBUG
 
//***************************************************************************
// Constructor/Destructor
//***************************************************************************
 
//---------------------------------------------------------------------------
File::File()
{
    #ifdef ZENLIB_USEWX
        File_Handle=NULL;
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            File_Handle=NULL;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                File_Handle=NULL;
            #else
                File_Handle=INVALID_HANDLE_VALUE;
            #endif
        #endif
    #endif //ZENLIB_USEWX
    Position=(int64u)-1;
    Size=(int64u)-1;
}
 
File::File(Ztring File_Name, access_t Access)
{
    #ifdef ZENLIB_USEWX
        File_Handle=NULL;
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            File_Handle=NULL;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                File_Handle=NULL;
            #else
                File_Handle=INVALID_HANDLE_VALUE;
            #endif
        #endif
    #endif //ZENLIB_USEWX
    Position=(int64u)-1;
    Size=(int64u)-1;
    Open(File_Name, Access);
}
 
//---------------------------------------------------------------------------
File::~File()
{
    Close();
}
 
//***************************************************************************
// Open/Close
//***************************************************************************
 
//---------------------------------------------------------------------------
bool File::Open (const tstring &File_Name_, access_t Access)
{
    Close();
 
    ZENLIB_DEBUG1(      "File Open",
                        Debug+=", File_Name="; Debug +=Ztring(File_Name_).To_UTF8();)
 
    File_Name=File_Name_;
 
    #ifdef ZENLIB_USEWX
        File_Handle=(void*)new wxFile();
        if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
        {
            //Sometime the file is locked for few milliseconds, we try again later
            wxMilliSleep(1000);
            if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
                //File is not openable
                return false;
        }
        return true;
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            /*
            int access;
            switch (Access)
            {
                case Access_Read         : access=O_BINARY|O_RDONLY          ; break;
                case Access_Write        : access=O_BINARY|O_WRONLY|O_CREAT|O_TRUNC  ; break;
                case Access_Read_Write   : access=O_BINARY|O_RDWR  |O_CREAT  ; break;
                case Access_Write_Append : access=O_BINARY|O_WRONLY|O_CREAT|O_APPEND ; break;
                default                  : access=0                          ;
            }
            #ifdef UNICODE
                File_Handle=open(File_Name.To_Local().c_str(), access);
            #else
                File_Handle=open(File_Name.c_str(), access);
            #endif //UNICODE
            return File_Handle!=-1;
            */
            ios_base::openmode mode;
            switch (Access)
            {
                case Access_Write        : mode=ios_base::binary|ios_base::in|ios_base::out; break;
                case Access_Read_Write   : mode=ios_base::binary|ios_base::in|ios_base::out; break;
                case Access_Write_Append : if (!Exists(File_Name))
                                                mode=ios_base::binary|ios_base::out;
                                           else
                                                mode=ios_base::binary|ios_base::out|ios_base::app;
                                           break;
                default                  : mode = ios_base::binary | ios_base::in;
            }
            #ifdef UNICODE
                File_Handle=new fstream(File_Name.To_Local().c_str(), mode);
            #else
                File_Handle=new fstream(File_Name.c_str(), mode);
            #endif //UNICODE
            if (!((fstream*)File_Handle)->is_open())
            {
                delete (fstream*)File_Handle; File_Handle=NULL;
                return false;
            }
            return true;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                File_Handle=new WrtFile();
 
                FileAccessMode Desired_Mode;
                StorageOpenOptions Share_Mode;
                switch (Access)
                {
                    case Access_Read: Desired_Mode=FileAccessMode_Read; Share_Mode=StorageOpenOptions_AllowReadersAndWriters; break;
                    case Access_Write:
                    case Access_Read_Write:
                    case Access_Write_Append: Desired_Mode=FileAccessMode_ReadWrite; Share_Mode=StorageOpenOptions_AllowReadersAndWriters; break;
                    default: Desired_Mode=FileAccessMode_Read; Share_Mode=StorageOpenOptions_None;
                }
 
                // Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
                File_Name.FindAndReplace(__T("/"), __T("\\"));
 
                if (FAILED(Get_File(HStringReference(File_Name.c_str(), (unsigned int)File_Name.size()), ((WrtFile*)File_Handle)->File)))
                {
                    if (Access==Access_Write || Access==Access_Read_Write || Access==Access_Write_Append)
                    {
                        if (!Create(File_Name, false))
                        {
                            ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
                            return false;
                        }
 
                        if (Access==Access_Write_Append)
                        {
                            Size_Get();
                            if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(Size)))
                            {
                                ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
                                return false;
                            }
                        }
 
                        return true;
                    }
 
                    ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
                    return false;
                }
 
                //IStorageFile don't provide OpenWithOptionsAsync
                ComPtr<IStorageFile2> File2;
                if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&File2))) || !File2)
                {
                    ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
                    return false;
                }
 
                ComPtr<IAsyncOperation<IRandomAccessStream*> > Async_Open;
                if (FAILED(File2->OpenWithOptionsAsync(Desired_Mode, Share_Mode, &Async_Open)) ||
                    FAILED(Await(Async_Open)) ||
                    FAILED(Async_Open->GetResults(&((WrtFile*)File_Handle)->Buffer))
                    || !((WrtFile*)File_Handle)->Buffer)
                {
                    ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
                    return false;
                }
 
                if (Access==Access_Write_Append)
                {
                    Size_Get();
                    if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(Size)))
                    {
                        ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
                        return false;
                    }
                }
                else
                    Position=0;
            #else
                DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
                switch (Access)
                {
                    case Access_Read         : dwDesiredAccess=FILE_READ_DATA; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_EXISTING;   break;
                    case Access_Write        : dwDesiredAccess=GENERIC_WRITE;   dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_ALWAYS;   break;
                    case Access_Read_Write   : dwDesiredAccess=FILE_READ_DATA|GENERIC_WRITE;   dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_ALWAYS;                    break;
                    case Access_Write_Append : dwDesiredAccess = FILE_APPEND_DATA; dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; dwCreationDisposition = OPEN_ALWAYS; break;
                    default                  : dwDesiredAccess=0;               dwShareMode=0;                                 dwCreationDisposition=0;             break;
                }
 
                #ifdef UNICODE
                    File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
                #else
                    File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
                #endif //UNICODE
                #if 0 //Disabled
                if (File_Handle==INVALID_HANDLE_VALUE)
                {
                    //Sometimes the file is locked for few milliseconds, we try again later
                    DWORD dw = GetLastError();
                    if (dw!=ERROR_FILE_NOT_FOUND)
                    {
                        /*
                        char lpMsgBuf[1000];
                        FormatMessageA(
                        FORMAT_MESSAGE_FROM_SYSTEM,
                        NULL,
                        dw,
                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                        lpMsgBuf,
                        1000, NULL );
                        */
                        Sleep(1000);
                        #ifdef UNICODE
                            File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
                        #else
                            File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
                        #endif //UNICODE
                    }
                }
                #endif //0
                if (File_Handle==INVALID_HANDLE_VALUE)
                {
                    ZENLIB_DEBUG2(      "File Open",
                                        Debug+=", returns 0";)
 
                    //File is not openable
                    return false;
                }
 
                ZENLIB_DEBUG2(      "File Open",
                                    Debug+=", returns 1";)
 
                if (Access == Access_Write_Append)
                    Size_Get();
                else
                    Position = 0;
            #endif
            return true;
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
bool File::Create (const Ztring &File_Name_, bool OverWrite)
{
    Close();
 
    ZENLIB_DEBUG1(      "File Create",
                        Debug+=", File_Name="; Debug +=Ztring(File_Name_).To_UTF8();)
 
    File_Name=File_Name_;
 
    #ifdef ZENLIB_USEWX
        File_Handle=(void*)new wxFile();
        if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
        {
            //Sometime the file is locked for few milliseconds, we try again later
            wxMilliSleep(3000);
            if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
                //File is not openable
                return false;
        }
        return true;
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            /*
            int access;
            switch (OverWrite)
            {
                case false        : access=O_BINARY|O_CREAT|O_WRONLY|O_EXCL ; break;
                default           : access=O_BINARY|O_CREAT|O_WRONLY|O_TRUNC; break;
            }
            #ifdef UNICODE
                File_Handle=open(File_Name.To_Local().c_str(), access);
            #else
                File_Handle=open(File_Name.c_str(), access);
            #endif //UNICODE
            return  File_Handle!=-1;
            */
            /*ios_base::openmode mode;
 
            switch (OverWrite)
            {
                //case false         : mode=          ; break;
                default                  : mode=0                            ; break;
            }*/
            ios_base::openmode access;
 
            if (!OverWrite && Exists(File_Name))
                return false;
 
            access=ios_base::binary|ios_base::in|ios_base::out|ios_base::trunc;
 
            #ifdef UNICODE
                File_Handle=new fstream(File_Name.To_Local().c_str(), access);
            #else
                File_Handle=new fstream(File_Name.c_str(), access);
            #endif //UNICODE
            return ((fstream*)File_Handle)->is_open();
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                File_Handle=new WrtFile();
 
                FileAccessMode Desired_Mode=FileAccessMode_ReadWrite;
                StorageOpenOptions Share_Mode=StorageOpenOptions_AllowReadersAndWriters;
                CreationCollisionOption Collision_Option=CreationCollisionOption_FailIfExists;
                if (OverWrite)
                    Collision_Option=CreationCollisionOption_ReplaceExisting;
 
                //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
                File_Name.FindAndReplace(__T("/"), __T("\\"));
 
                //Split file and folder
                tstring Destination_Dir=FileName::Path_Get(File_Name);
                tstring Destination_File=FileName::Name_Get(File_Name);
 
                //Open dst folder
                ComPtr<IStorageFolder> Folder;
                if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
                    return false;
 
                //Create file
                ComPtr<IAsyncOperation<StorageFile*> > Async_Create;
                ComPtr<IStorageFile> File;
                if (FAILED(Folder->CreateFileAsync(HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Create)) ||
                    FAILED(Await(Async_Create)) ||
                    FAILED(Async_Create->GetResults(&((WrtFile*)File_Handle)->File)) ||
                    !((WrtFile*)File_Handle)->File)
                    return false;
 
                //IStorageFile don't provide OpenWithOptionsAsync
                ComPtr<IStorageFile2> File2;
                if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&File2))) || !File2)
                    return false;
 
                ComPtr<IAsyncOperation<IRandomAccessStream*> > Async_Open_File;
                if (FAILED(File2->OpenWithOptionsAsync(Desired_Mode, Share_Mode, &Async_Open_File)) ||
                    FAILED(Await(Async_Open_File)) ||
                    FAILED(Async_Open_File->GetResults(&((WrtFile*)File_Handle)->Buffer)) ||
                    !((WrtFile*)File_Handle)->Buffer)
                    return false;
 
                return true;
            #else
                DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
                if (OverWrite) {
                    dwDesiredAccess=GENERIC_WRITE;
                    dwCreationDisposition=CREATE_ALWAYS;
                } else {
                    dwDesiredAccess=GENERIC_WRITE;
                    dwCreationDisposition=CREATE_NEW;
                }
                dwShareMode=0;
 
                #ifdef UNICODE
                    File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
                #else
                    File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
                #endif //UNICODE
                #if 0 //Disabled
                if (File_Handle==INVALID_HANDLE_VALUE)
                {
                    //Sometime the file is locked for few milliseconds, we try again later
                    Sleep(3000);
                    #ifdef UNICODE
                        File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
                    #else
                        File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
                    #endif //UNICODE
                }
                #endif //0
                if (File_Handle==INVALID_HANDLE_VALUE)
                {
                    ZENLIB_DEBUG2(      "File Create",
                                        Debug+=", returns 0";)
 
                    //File is not openable
                    return false;
                }
 
                ZENLIB_DEBUG2(      "File Create",
                                    Debug+=", returns 1";)
            #endif
            return true;
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
void File::Close ()
{
    #ifdef ZENLIB_DEBUG
        bool isOpen=false;
        #ifdef ZENLIB_USEWX
            if (File_Handle!=NULL)
        #else //ZENLIB_USEWX
            #ifdef ZENLIB_STANDARD
                if (File_Handle!=NULL)
            #elif defined WINDOWS
                #ifdef WINDOWS_UWP
                    if (File_Handle)
                #else
                    if (File_Handle!=INVALID_HANDLE_VALUE)
                #endif
            #endif
        #endif //ZENLIB_USEWX
            {
                ZENLIB_DEBUG1(      "File Close",
                                    Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8();)
                isOpen=true;
            }
    #endif
 
    #ifdef ZENLIB_USEWX
        delete (wxFile*)File_Handle; File_Handle=NULL;
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            //close(File_Handle); File_Handle=-1;
            delete (fstream*)File_Handle; File_Handle=NULL;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                delete(WrtFile*)File_Handle; File_Handle=NULL;
            #else
                CloseHandle(File_Handle); File_Handle=INVALID_HANDLE_VALUE;
            #endif
        #endif
    #endif //ZENLIB_USEWX
    Position=(int64u)-1;
    Size=(int64u)-1;
 
    #ifdef ZENLIB_DEBUG
        if (isOpen)
        {
            ZENLIB_DEBUG2(      "File Close",
                                )
        }
    #endif
}
 
//***************************************************************************
// Read/Write
//***************************************************************************
 
//---------------------------------------------------------------------------
size_t File::Read (int8u* Buffer, size_t Buffer_Size_Max)
{
    ZENLIB_DEBUG1("File Read",
        Debug += ", File_Name="; Debug += Ztring(File_Name).To_UTF8(); Debug += ", MaxSize="; Debug += Ztring::ToZtring(Buffer_Size_Max).To_UTF8())
 
#ifdef ZENLIB_USEWX
        if (File_Handle == NULL)
#else //ZENLIB_USEWX
    #ifdef ZENLIB_STANDARD
        if (File_Handle == NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                boolean Can_Read=FALSE;
                if (!File_Handle || !((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanRead(&Can_Read)) || !Can_Read)
            #else
                if (File_Handle == INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return 0;
 
    #ifdef ZENLIB_USEWX
        size_t ByteRead=((wxFile*)File_Handle)->Read(Buffer, Buffer_Size_Max);
        Position+=ByteRead;
        return ByteRead;
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            //return read((int)File_Handle, Buffer, Buffer_Size_Max);
            if (Position==(int64u)-1)
                Position_Get();
            if (Size==(int64u)-1)
                Size_Get();
            if (Position!=(int64u)-1 && Position+Buffer_Size_Max>Size)
                Buffer_Size_Max=(size_t)(Size-Position); //We don't want to enable eofbit (impossible to seek after)
            ((fstream*)File_Handle)->read((char*)Buffer, Buffer_Size_Max);
            size_t ByteRead=((fstream*)File_Handle)->gcount();
            Position+=ByteRead;
            return ByteRead;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                ComPtr<IInputStream> Stream;
                if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
                    return 0;
 
                ComPtr<IDataReaderFactory> Reader_Factory;
                if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), &Reader_Factory)) || !Reader_Factory)
                    return 0;
 
                ComPtr<IDataReader> Reader;
                if (FAILED(Reader_Factory->CreateDataReader(*Stream.GetAddressOf(), &Reader)) || !Reader)
                    return 0;
 
                UINT32 Readed=0;
                ComPtr<IAsyncOperation<UINT32> > Async_Read;
                if (FAILED(Reader->LoadAsync((UINT32)Buffer_Size_Max, &Async_Read)) ||
                    FAILED(Await(Async_Read)) ||
                    FAILED(Async_Read->GetResults(&Readed)))
                    return 0;
 
                if (FAILED(Reader->ReadBytes((UINT32)Buffer_Size_Max, (BYTE*)Buffer)))
                    return 0;
 
                Reader->DetachStream(&Stream);
 
                return (size_t)Readed;
            #else
                DWORD Buffer_Size;
                if (ReadFile(File_Handle, Buffer, (DWORD)Buffer_Size_Max, &Buffer_Size, NULL))
                {
                    Position+=Buffer_Size;
 
                    ZENLIB_DEBUG2(      "File Read",
                                        Debug+=", new position ";Debug+=Ztring::ToZtring(Position).To_UTF8();;Debug+=", returns ";Debug+=Ztring::ToZtring((int64u)Buffer_Size).To_UTF8();)
 
                    return Buffer_Size;
                }
                else
                {
                    ZENLIB_DEBUG2(      "File Read",
                                        Debug+=", returns 0";)
                    return 0;
                }
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
size_t File::Write (const int8u* Buffer, size_t Buffer_Size)
{
    #ifdef ZENLIB_USEWX
        if (File_Handle==NULL)
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            if (File_Handle==NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                boolean Can_Write=FALSE;
                if (!File_Handle || !((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanWrite(&Can_Write)) || !Can_Write)
            #else
                if (File_Handle==INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return 0;
 
    #ifdef ZENLIB_USEWX
        return ((wxFile*)File_Handle)->Write(Buffer, Buffer_Size);
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            //return write(File_Handle, Buffer, Buffer_Size);
            ((fstream*)File_Handle)->write((char*)Buffer, Buffer_Size);
            if (((fstream*)File_Handle)->bad())
            {
                Position=(int64u)-1;
                return 0;
            }
            else
            {
                if (Position!=(int64u)-1)
                    Position+=Buffer_Size;
                return Buffer_Size;
            }
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                ComPtr<IOutputStream> Stream;
                if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
                    return 0;
 
                ComPtr<IDataWriterFactory> Writer_Factory;
                if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(), &Writer_Factory)) || !Writer_Factory)
                    return 0;
 
                ComPtr<IDataWriter> Writer;
                if (FAILED(Writer_Factory->CreateDataWriter(*Stream.GetAddressOf(), &Writer)) || !Writer)
                    return 0;
 
                if (FAILED(Writer->WriteBytes((UINT32)Buffer_Size, (BYTE*)Buffer)))
                    return 0;
 
                UINT32 Written=0;
                ComPtr<IAsyncOperation<UINT32> > Async_Write;
                if (FAILED(Writer->StoreAsync(&Async_Write)) ||
                    FAILED(Await(Async_Write)) ||
                    FAILED(Async_Write->GetResults(&Written)))
                    return 0;
 
                Writer->DetachStream(&Stream);
 
                return (size_t)Written;
            #else
                DWORD Buffer_Size_Written;
                if (WriteFile(File_Handle, Buffer, (DWORD)Buffer_Size, &Buffer_Size_Written, NULL))
                {
                    if (Position!=(int64u)-1)
                        Position+=Buffer_Size_Written;
                    return Buffer_Size_Written;
                }
                else
                {
                    Position=(int64u)-1;
                    return 0;
                }
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
bool File::Truncate (int64u Offset)
{
    if (File_Handle==NULL)
        return false;
 
    #ifdef ZENLIB_USEWX
        return false; //Not supported
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            #if defined(WINDOWS)
                return false; //Not supported
            #else //defined(WINDOWS)
                //Need to close the file, use truncate, reopen it
                #if !defined(__ANDROID_API__) || __ANDROID_API__ >= 21
                if (Offset==(int64u)-1)
                    Offset=Position_Get();
                Ztring File_Name_Sav=File_Name;
                Close();
                truncate(File_Name_Sav.To_Local().c_str(), Offset);
                if (!Open(File_Name_Sav, Access_Read_Write))
                    return false;
                GoTo(0, FromEnd);
                return true;
                #else
                return false; //Not supported
                #endif
            #endif //!defined(WINDOWS)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                boolean Can_Write=FALSE;
                if (!((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanWrite(&Can_Write)) || !Can_Write)
                    return false;
 
                ComPtr<IOutputStream> Stream;
                if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
                    return false;
 
                if (Offset==(int64u)-1)
                {
                    if (FAILED(((WrtFile*)File_Handle)->Buffer->put_Size((UINT64)Position_Get())))
                        return false;
                }
                else
                {
                    if (FAILED(((WrtFile*)File_Handle)->Buffer->put_Size((UINT64)Offset)))
                        return false;
                }
 
                return true;
            #else
                if(Offset!=(int64u)-1 && Offset!=Position_Get())
                    if (!GoTo(Offset))
                        return false;
                SetEndOfFile(File_Handle);
                return true;
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
size_t File::Write (const Ztring &ToWrite)
{
    std::string AnsiString=ToWrite.To_UTF8();
    return Write((const int8u*)AnsiString.c_str(), AnsiString.size());
}
 
//***************************************************************************
// Moving
//***************************************************************************
 
//---------------------------------------------------------------------------
bool File::GoTo (int64s Position_ToMove, move_t MoveMethod)
{
    ZENLIB_DEBUG1(      "File GoTo",
                        Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8(); Debug+="File GoTo: "; Debug +=Ztring(File_Name).To_UTF8(); Debug+=", MoveMethod="; Debug +=Ztring::ToZtring(MoveMethod).To_UTF8(); Debug+=", MaxSize="; Debug +=Ztring::ToZtring(Position_ToMove).To_UTF8())
 
    #ifdef ZENLIB_USEWX
        if (File_Handle==NULL)
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            if (File_Handle==NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                if (!File_Handle || !((WrtFile*)File_Handle)->File || !((WrtFile*)File_Handle)->Buffer)
            #else
                if (File_Handle==INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return false;
 
    Position=(int64u)-1; //Disabling memory
    #ifdef ZENLIB_USEWX
        return ((wxFile*)File_Handle)->Seek(Position, (wxSeekMode)MoveMethod)!=wxInvalidOffset; //move_t and wxSeekMode are same
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            /*
            int fromwhere;
            switch (MoveMethod)
            {
                case FromBegin : fromwhere=SEEK_SET; break;
                case FromCurrent : fromwhere=SEEK_CUR; break;
                case FromEnd : fromwhere=SEEK_END; break;
                default : fromwhere=SEEK_CUR; break;
            }
            return lseek(File_Handle, Position, fromwhere)!=-1;
            */
            ios_base::seekdir dir;
            switch (MoveMethod)
            {
                case FromBegin   : dir=ios_base::beg; break;
                case FromCurrent : dir=ios_base::cur; break;
                case FromEnd     : dir=ios_base::end; break;
                default          : dir=ios_base::beg;
            }
            ((fstream*)File_Handle)->seekg((streamoff)Position_ToMove, dir);
            return !((fstream*)File_Handle)->fail();
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                UINT64 New_Position=0;
                switch (MoveMethod)
                {
                    case FromBegin   : New_Position=Position_ToMove; break;
                    case FromCurrent : New_Position=Position_Get()+Position_ToMove; break;
                    case FromEnd     : New_Position=Size_Get()-Position_ToMove; break;
                    default          : New_Position=Position_ToMove;
                }
 
                if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(New_Position)))
                    return false;
 
                return true;
            #else
                LARGE_INTEGER GoTo;
                GoTo.QuadPart=Position_ToMove;
                BOOL i=SetFilePointerEx(File_Handle, GoTo, NULL, MoveMethod);
 
                #ifdef ZENLIB_DEBUG
                    LARGE_INTEGER Temp; Temp.QuadPart=0;
                    SetFilePointerEx(File_Handle, Temp, &Temp, FILE_CURRENT);
                    ZENLIB_DEBUG2(      "File GoTo",
                                        Debug+=", new position ";Debug+=Ztring::ToZtring(Temp.QuadPart).To_UTF8();Debug+=", returns ";Debug+=i?'1':'0';)
                #endif //ZENLIB_DEBUG
 
                return i?true:false;
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
int64u File::Position_Get ()
{
    if (Position!=(int64u)-1)
        return Position;
 
    ZENLIB_DEBUG1(      "File Position_Get",
                        Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8())
 
    #ifdef ZENLIB_USEWX
        if (File_Handle==NULL)
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            if (File_Handle==NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                if (!File_Handle || !((WrtFile*)File_Handle)->File || !((WrtFile*)File_Handle)->Buffer)
            #else
                if (File_Handle == INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return (int64u)-1;
 
    #ifdef ZENLIB_USEWX
        return (int64u)-1;
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            Position=((fstream*)File_Handle)->tellg();
            return Position;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                if (FAILED(((WrtFile*)File_Handle)->Buffer->get_Position((UINT64*)&Position)))
                    return (int64u)-1;
            #else
                LARGE_INTEGER GoTo; GoTo.QuadPart=0;
                GoTo.LowPart=SetFilePointer(File_Handle, GoTo.LowPart, &GoTo.HighPart, FILE_CURRENT);
                Position=GoTo.QuadPart;
 
                ZENLIB_DEBUG2(      "File GoTo",
                                    Debug+=", new position ";Debug+=Ztring::ToZtring(GoTo.QuadPart).To_UTF8();Debug+=", returns 1";)
            #endif
            return Position;
        #endif
    #endif //ZENLIB_USEWX
}
 
//***************************************************************************
// Attributes
//***************************************************************************
 
//---------------------------------------------------------------------------
int64u File::Size_Get()
{
    #ifdef ZENLIB_USEWX
        if (File_Handle==NULL)
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            if (File_Handle==NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                if (!File_Handle || !((WrtFile*)File_Handle)->File)
            #else
                if (File_Handle==INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return 0;
 
    #ifdef ZENLIB_USEWX
        return ((wxFile*)File_Handle)->Length();
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            /*
            int CurrentPos=lseek(File_Handle, 0, SEEK_CUR);
            int64u File_Size;
            File_Size=lseek(File_Handle, 0, SEEK_END);
            lseek(File_Handle, CurrentPos, SEEK_SET);
            */
            fstream::pos_type CurrentPos=((fstream*)File_Handle)->tellg();
            if (CurrentPos!=(fstream::pos_type)-1)
            {
                ((fstream*)File_Handle)->seekg(0, ios_base::end);
                Size=((fstream*)File_Handle)->tellg();
                ((fstream*)File_Handle)->seekg(CurrentPos);
            }
            else
                Size=(int64u)-1;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                ComPtr<IStorageItem> Item;
                if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
                    return (int64u)-1;
 
                ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
                ComPtr<IBasicProperties> Properties;
                if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
                    FAILED(Await(Async_Properties)) ||
                    FAILED(Async_Properties->GetResults(&Properties)) ||
                    !Properties)
                    return (int64u)-1;
 
                if (FAILED(Properties->get_Size(&Size)))
                    return (int64u)-1;
            #else
                LARGE_INTEGER x = {0};
                BOOL bRet = ::GetFileSizeEx(File_Handle, &x);
                if (bRet == FALSE)
                    return (int64u)-1;
                Size=x.QuadPart;
            #endif
        #endif
            return Size;
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
Ztring File::Created_Get()
{
    #ifdef ZENLIB_USEWX
        if (File_Handle==NULL)
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            if (File_Handle==NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                if (!File_Handle || !((WrtFile*)File_Handle)->File)
            #else
                if (File_Handle==INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return Ztring();
 
    #ifdef ZENLIB_USEWX
        return __T(""); //Not implemented
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            return __T(""); //Not implemented
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                ComPtr<IStorageItem> Item;
                if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
                    return __T("");
 
                DateTime Time;
                if (FAILED(Item->get_DateCreated(&Time)))
                    return __T("");
 
                return Ztring().Date_From_Milliseconds_1601((int64u)(Time.UniversalTime/10000));
            #else
                FILETIME TimeFT;
                if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
                {
                    int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
                    Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
                    return Time;
                }
                else
                    return __T(""); //There was a problem
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
#if defined WINDOWS
static Ztring Calc_Time(const FILETIME& TimeFT)
{
    int64u Time64 = 0x100000000ULL * TimeFT.dwHighDateTime + TimeFT.dwLowDateTime;
    TIME_ZONE_INFORMATION Info;
    DWORD Result = GetTimeZoneInformation(&Info);
    if (Result != TIME_ZONE_ID_INVALID)
    {
        Time64 -= ((int64s)Info.Bias) * 60 * 1000 * 1000 * 10;
        if (Result == TIME_ZONE_ID_DAYLIGHT)
            Time64 -= ((int64s)Info.DaylightBias) * 60 * 1000 * 1000 * 10;
        else
            Time64 -= ((int64s)Info.StandardBias) * 60 * 1000 * 1000 * 10;
    }
    Ztring Time; Time.Date_From_Milliseconds_1601(Time64 / 10000);
    Time.FindAndReplace(__T("UTC "), __T(""));
    return Time;
}
#endif
//---------------------------------------------------------------------------
Ztring File::Created_Local_Get()
{
    #ifdef ZENLIB_USEWX
        if (File_Handle==NULL)
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            if (File_Handle==NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                if (!File_Handle || !((WrtFile*)File_Handle)->File)
            #else
                if (File_Handle==INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return Ztring();
 
    #ifdef ZENLIB_USEWX
        return __T(""); //Not implemented
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            return __T(""); //Not implemented
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                ComPtr<IStorageItem> Item;
                if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
                    return __T("");
 
                DateTime Time;
                if (FAILED(Item->get_DateCreated(&Time)))
                    return __T("");
 
                FILETIME File_Time;
                ULARGE_INTEGER Time_Union;
                Time_Union.QuadPart=(ULONGLONG)Time.UniversalTime;
                File_Time.dwHighDateTime=Time_Union.HighPart;
                File_Time.dwLowDateTime=Time_Union.LowPart;
 
                return Calc_Time(File_Time);
            #else
                FILETIME TimeFT;
                if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
                {
                    return Calc_Time(TimeFT);
                }
                else
                    return __T(""); //There was a problem
           #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
Ztring File::Modified_Get()
{
    #ifdef ZENLIB_USEWX
        if (File_Handle==NULL)
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            if (File_Handle==NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                if (!File_Handle || !((WrtFile*)File_Handle)->File)
            #else
                if (File_Handle==INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return Ztring();
 
    #ifdef ZENLIB_USEWX
        return __T(""); //Not implemented
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            struct stat Stat;
            int Result=stat(File_Name.To_Local().c_str(), &Stat);
            if (Result<0)
                return __T(""); //Error
            Ztring Time; Time.Date_From_Seconds_1970((int64s)Stat.st_mtime);
            return Time;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                ComPtr<IStorageItem> Item;
                if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
                    return __T("");
 
                ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
                ComPtr<IBasicProperties> Properties;
                if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
                    FAILED(Await(Async_Properties)) ||
                    FAILED(Async_Properties->GetResults(&Properties)) ||
                    !Properties)
                    return __T("");
 
                DateTime Time;
                if (FAILED(Properties->get_DateModified(&Time)) || Time.UniversalTime==0)
                    return __T("");
 
                return Ztring().Date_From_Milliseconds_1601((int64u)(Time.UniversalTime/10000));
            #else
                FILETIME TimeFT;
                if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
                {
                    int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
                    Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
                    return Time;
                }
                else
                    return __T(""); //There was a problem
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
Ztring File::Modified_Local_Get()
{
    #ifdef ZENLIB_USEWX
        if (File_Handle==NULL)
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            if (File_Handle==NULL)
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                if (!File_Handle || !((WrtFile*)File_Handle)->File)
            #else
                if (File_Handle==INVALID_HANDLE_VALUE)
            #endif
        #endif
    #endif //ZENLIB_USEWX
        return Ztring();
 
    #ifdef ZENLIB_USEWX
        return __T(""); //Not implemented
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            struct stat Stat;
            int Result=stat(File_Name.To_Local().c_str(), &Stat);
            if (Result<0)
                return __T(""); //Error
            Ztring Time; Time.Date_From_Seconds_1970_Local(Stat.st_mtime);
            return Time;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                ComPtr<IStorageItem> Item;
                if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
                    return __T("");
 
                ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
                ComPtr<IBasicProperties> Properties;
                if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
                    FAILED(Await(Async_Properties)) ||
                    FAILED(Async_Properties->GetResults(&Properties)) ||
                    !Properties)
                    return __T("");
 
                DateTime Time;
                if (FAILED(Properties->get_DateModified(&Time)) || Time.UniversalTime==0)
                    return __T("");
 
                FILETIME File_Time;
                ULARGE_INTEGER Time_Union;
                Time_Union.QuadPart=(ULONGLONG)Time.UniversalTime;
                File_Time.dwHighDateTime=Time_Union.HighPart;
                File_Time.dwLowDateTime=Time_Union.LowPart;
 
                return Calc_Time(File_Time);
            #else
                FILETIME TimeFT;
                if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
                {
                    return Calc_Time(TimeFT);
                }
                else
                    return __T(""); //There was a problem
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
bool File::Opened_Get()
{
    #ifdef ZENLIB_USEWX
        return File_Handle!=NULL;
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            //return File_Handle!=-1;
            return File_Handle!=NULL && ((fstream*)File_Handle)->is_open();
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                return File_Handle && ((WrtFile*)File_Handle)->File && ((WrtFile*)File_Handle)->Buffer;
            #else
                return File_Handle!=INVALID_HANDLE_VALUE;
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//***************************************************************************
// Helpers
//***************************************************************************
 
//---------------------------------------------------------------------------
int64u File::Size_Get(const Ztring &File_Name)
{
    File F(File_Name);
    return F.Size_Get();
}
 
//---------------------------------------------------------------------------
Ztring File::Created_Get(const Ztring &File_Name)
{
    File F(File_Name);
    return F.Created_Get();
}
 
//---------------------------------------------------------------------------
Ztring File::Modified_Get(const Ztring &File_Name)
{
    File F(File_Name);
    return F.Modified_Get();
}
 
//---------------------------------------------------------------------------
bool File::Exists(const Ztring &File_Name)
{
    ZENLIB_DEBUG1(      "File Exists",
                        Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8())
 
    #ifdef ZENLIB_USEWX
        wxFileName FN(File_Name.c_str());
        return FN.FileExists();
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            #if defined WINDOWS
                if (File_Name.find(__T('*'))!=std::string::npos || (File_Name.find(__T("\\\\?\\"))!=0 && File_Name.find(__T('?'))!=std::string::npos) || (File_Name.find(__T("\\\\?\\"))==0 && File_Name.find(__T('?'), 4)!=std::string::npos))
                    return false;
            #endif //defined WINDOWS
            struct stat buffer;
            int         status;
            #ifdef UNICODE
                status=stat(File_Name.To_Local().c_str(), &buffer);
            #else
                status=stat(File_Name.c_str(), &buffer);
            #endif //UNICODE
            return status==0 && S_ISREG(buffer.st_mode);
        #elif defined WINDOWS
            if (File_Name.find(__T('*'))!=std::string::npos || (File_Name.find(__T("\\\\?\\"))!=0 && File_Name.find(__T('?'))!=std::string::npos) || (File_Name.find(__T("\\\\?\\"))==0 && File_Name.find(__T('?'), 4)!=std::string::npos))
                return false;
            #ifdef WINDOWS_UWP
                //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
                Ztring File_Name_=File_Name;
                File_Name_.FindAndReplace(__T("/"), __T("\\"));
 
                //Try to access file directly
                ComPtr<IStorageFile> File;
                if (SUCCEEDED(Get_File(HStringReference(File_Name_.c_str(), (unsigned int)File_Name_.size()), File)))
                    return true;
 
                //Try directory access methods
                tstring Dir_=FileName::Path_Get(File_Name_);
                tstring File_=FileName::Name_Get(File_Name_);
 
                ComPtr<IStorageFolder> Folder;
                if (FAILED(Get_Folder(HStringReference(Dir_.c_str(), (unsigned int)Dir_.size()), Folder)))
                    return false;
 
                //IStorageFolder don't provide TryGetItemAsync
                ComPtr<IStorageFolder2> Folder2;
                if (FAILED(Folder->QueryInterface(IID_PPV_ARGS(&Folder2))) || !Folder2)
                    return false;
 
                ComPtr<IAsyncOperation<IStorageItem*> > Async_GetItem;
                ComPtr<IStorageItem> Item;
                ComPtr<IStorageFile> AsFile;
                if (SUCCEEDED(Folder2->TryGetItemAsync(HStringReference(File_.c_str(), (unsigned int)File_.size()).Get(), &Async_GetItem)) &&
                    SUCCEEDED(Await(Async_GetItem)) &&
                    SUCCEEDED(Async_GetItem->GetResults(&Item)) &&
                    Item &&
                    SUCCEEDED(Item.As(&AsFile)))
                    return true;
 
                return false;
            #else
                #ifdef UNICODE
                    DWORD FileAttributes=GetFileAttributesW(File_Name.c_str());
                #else
                    DWORD FileAttributes=GetFileAttributes(File_Name.c_str());
                #endif //UNICODE
 
                ZENLIB_DEBUG2(      "File Exists",
                                    Debug+=", File_Name="; Debug+=Ztring::ToZtring(((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY))?1:0).To_UTF8())
 
                return ((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY));
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
bool File::Copy(const Ztring &Source, const Ztring &Destination, bool OverWrite)
{
    #ifdef ZENLIB_USEWX
        return wxCopyFile(Source.c_str(), Destination.c_str(), OverWrite);
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            return false;
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                NameCollisionOption Collision_Option=NameCollisionOption_FailIfExists;
                if (OverWrite)
                    Collision_Option=NameCollisionOption_ReplaceExisting;
 
                //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
                Ztring Source_=Source;
                Source_.FindAndReplace(__T("/"), __T("\\"));
 
                Ztring Destination_=Destination;
                Destination_.FindAndReplace(__T("/"), __T("\\"));
 
                //Split destination file and folder
                tstring Destination_Dir=FileName::Path_Get(Destination_);
                tstring Destination_File=FileName::Name_Get(Destination_);
 
                //Open src file
                ComPtr<IStorageFile> File;
                if (FAILED(Get_File(HStringReference(Source_.c_str(), (unsigned int)Source_.size()), File)))
                    return false;
 
                //Open dst folder
                ComPtr<IStorageFolder> Folder;
                if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
                    return false;
 
                //Copy file
                ComPtr<IAsyncOperation<StorageFile*> > Async_Copy;
                ComPtr<IStorageFile> New_File;
                if (FAILED(File->CopyOverload(*Folder.GetAddressOf(), HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Copy)) ||
                    FAILED(Await(Async_Copy)) ||
                    FAILED(Async_Copy->GetResults(&New_File)) ||
                    !New_File)
                    return false;
 
                return true;
            #else
                #ifdef UNICODE
                    return CopyFileW(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
                #else
                    return CopyFile(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
                #endif //UNICODE
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
bool File::Move(const Ztring &Source, const Ztring &Destination, bool OverWrite)
{
    if (OverWrite && Exists(Source))
        Delete(Destination);
    #ifdef ZENLIB_USEWX
        if (OverWrite && Exists(Destination))
            wxRemoveFile(Destination.c_str());
        return wxRenameFile(Source.c_str(), Destination.c_str());
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            return !std::rename(Source.To_Local().c_str(), Destination.To_Local().c_str());
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                NameCollisionOption Collision_Option=NameCollisionOption_FailIfExists;
                if (OverWrite)
                    Collision_Option=NameCollisionOption_ReplaceExisting;
 
                //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
                Ztring Source_=Source;
                Source_.FindAndReplace(__T("/"), __T("\\"));
 
                Ztring Destination_=Destination;
                Destination_.FindAndReplace(__T("/"), __T("\\"));
 
                //Split destination file and folder
                tstring Destination_Dir=FileName::Path_Get(Destination_);
                tstring Destination_File=FileName::Name_Get(Destination_);
 
                //Open src file
                ComPtr<IStorageFile> File;
                if (FAILED(Get_File(HStringReference(Source_.c_str(), (unsigned int)Source_.size()), File)))
                    return false;
 
                //Open dst folder
                ComPtr<IStorageFolder> Folder;
                if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
                    return false;
 
                //Move file
                ComPtr<IAsyncAction> Async_Move;
                if (FAILED(File->MoveOverload(*Folder.GetAddressOf(), HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Move)) ||
                    FAILED(Await(Async_Move)) ||
                    FAILED(Async_Move->GetResults()))
                    return false;
 
                return true;
            #else
                #ifdef UNICODE
                    return MoveFileExW(Source.c_str(), Destination.c_str(), 0)!=0;
                #else
                    return MoveFileEx(Source.c_str(), Destination.c_str(), 0)!=0;
                #endif //UNICODE
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//---------------------------------------------------------------------------
bool File::Delete(const Ztring &File_Name)
{
    #ifdef ZENLIB_USEWX
        return wxRemoveFile(File_Name.c_str());
    #else //ZENLIB_USEWX
        #ifdef ZENLIB_STANDARD
            #ifdef UNICODE
                return unlink(File_Name.To_Local().c_str())==0;
            #else
                return unlink(File_Name.c_str())==0;
            #endif //UNICODE
        #elif defined WINDOWS
            #ifdef WINDOWS_UWP
                //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
                Ztring File_Name_=File_Name;
                File_Name_.FindAndReplace(__T("/"), __T("\\"));
 
                ComPtr<IStorageFile> File_;
                if (FAILED(Get_File(HStringReference(File_Name_.c_str(), (unsigned int)File_Name_.size()), File_)))
                    return false;
 
                ComPtr<IStorageItem> Item;
                if (FAILED(File_->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
                    return false;
 
                ComPtr<IAsyncAction> Async_Delete;
                if (FAILED(Item->DeleteAsync(StorageDeleteOption_Default, &Async_Delete)) ||
                    FAILED(Await(Async_Delete)) ||
                    FAILED(Async_Delete->GetResults()))
                    return false;
 
                return true;
            #else
                #ifdef UNICODE
                    return DeleteFileW(File_Name.c_str())!=0;
                #else
                    return DeleteFile(File_Name.c_str())!=0;
                #endif //UNICODE
            #endif
        #endif
    #endif //ZENLIB_USEWX
}
 
//***************************************************************************
//
//***************************************************************************
 
} //namespace

V303 The function 'SetFilePointer' is deprecated in the Win64 system. It is safer to use the 'SetFilePointerEx' function.

V525 The code contains the collection of similar blocks. Check items '3', '4', '4', '4' in lines 362, 363, 364, 365.

V688 The 'File_Name' function argument possesses the same name as one of the class members, which can result in a confusion.

V688 The 'File_Name' function argument possesses the same name as one of the class members, which can result in a confusion.

V688 The 'File_Name' function argument possesses the same name as one of the class members, which can result in a confusion.

V688 The 'File_Name' function argument possesses the same name as one of the class members, which can result in a confusion.