1 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
2  *
3  *  Use of this source code is governed by a zlib-style license that can
4  *  be found in the License.txt file in the root of the source tree.
5  */
6 
7 //---------------------------------------------------------------------------
8 #include "ZenLib/PreComp.h"
9 #ifdef __BORLANDC__
10     #pragma hdrstop
11 #endif
12 //---------------------------------------------------------------------------
13 
14 //---------------------------------------------------------------------------
15 #include "ZenLib/Conf_Internal.h"
16 //---------------------------------------------------------------------------
17 
18 #include "ZenLib/FileName.h"
19 //---------------------------------------------------------------------------
20 #ifdef ZENLIB_USEWX
21     #include <wx/file.h>
22     #include <wx/filename.h>
23     #include <wx/utils.h>
24 #else //ZENLIB_USEWX
25     #ifdef ZENLIB_STANDARD
26         #ifdef WINDOWS
27         #else
28             #include <cstdio>
29         #endif
30         #include <sys/stat.h>
31         #if !defined(WINDOWS)
32             #include <unistd.h>
33         #endif //!defined(WINDOWS)
34         #include <fstream>
35         using namespace std;
36         #ifndef S_ISDIR
37             #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
38         #endif
39         #ifndef S_ISREG
40             #define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
41         #endif
42     #elif defined WINDOWS
43         #undef __TEXT
44         #include <windows.h>
45         #ifdef WINDOWS_UWP
46             #include <wrl.h>
47             #include <windows.foundation.h>
48             #include <windows.storage.h>
49             #include <windows.storage.accesscache.h>
50             using namespace Microsoft::WRL;
51             using namespace Microsoft::WRL::Wrappers;
52             using namespace ABI::Windows::Foundation;
53             using namespace ABI::Windows::Foundation::Collections;
54             using namespace ABI::Windows::Storage;
55             using namespace ABI::Windows::Storage::Streams;
56             using namespace ABI::Windows::Storage::FileProperties;
57         #endif
58     #endif
59 #endif //ZENLIB_USEWX
60 #include "ZenLib/OS_Utils.h"
61 #include "ZenLib/File.h"
62 
63 //---------------------------------------------------------------------------
64 #ifdef WINDOWS_UWP
65 struct WrtFile
66 {
67     ComPtr<IStorageFile> File;
68     ComPtr<IRandomAccessStream> Buffer;
69 };
70 #endif
71 
72 //---------------------------------------------------------------------------
73 namespace ZenLib
74 {
75 
76 //---------------------------------------------------------------------------
77 // Debug
78 #ifdef ZENLIB_DEBUG
79     #include <stdio.h>
80     #include <windows.h>
81     namespace ZenLib_File_Debug
82     {
83         FILE* F;
84         std::string Debug;
85         SYSTEMTIME st_In;
86 
Debug_Open(bool Out)87         void Debug_Open(bool Out)
88         {
89             F=fopen("C:\\Temp\\ZenLib_Debug.txt", "a+t");
90             Debug.clear();
91             SYSTEMTIME st;
92             GetLocalTime( &st );
93 
94             char Duration[100];
95             if (Out)
96             {
97                 FILETIME ft_In;
98                 if (SystemTimeToFileTime(&st_In, &ft_In))
99                 {
100                     FILETIME ft_Out;
101                     if (SystemTimeToFileTime(&st, &ft_Out))
102                     {
103                         ULARGE_INTEGER UI_In;
104                         UI_In.HighPart=ft_In.dwHighDateTime;
105                         UI_In.LowPart=ft_In.dwLowDateTime;
106 
107                         ULARGE_INTEGER UI_Out;
108                         UI_Out.HighPart=ft_Out.dwHighDateTime;
109                         UI_Out.LowPart=ft_Out.dwLowDateTime;
110 
111                         ULARGE_INTEGER UI_Diff;
112                         UI_Diff.QuadPart=UI_Out.QuadPart-UI_In.QuadPart;
113 
114                         FILETIME ft_Diff;
115                         ft_Diff.dwHighDateTime=UI_Diff.HighPart;
116                         ft_Diff.dwLowDateTime=UI_Diff.LowPart;
117 
118                         SYSTEMTIME st_Diff;
119                         if (FileTimeToSystemTime(&ft_Diff, &st_Diff))
120                         {
121                             sprintf(Duration, "%02hd:%02hd:%02hd.%03hd", st_Diff.wHour, st_Diff.wMinute, st_Diff.wSecond, st_Diff.wMilliseconds);
122                         }
123                         else
124                             strcpy(Duration, "            ");
125                     }
126                     else
127                         strcpy(Duration, "            ");
128 
129                 }
130                 else
131                     strcpy(Duration, "            ");
132             }
133             else
134             {
135                 st_In=st;
136                 strcpy(Duration, "            ");
137             }
138 
139             fprintf(F,"                                       %02hd:%02hd:%02hd.%03hd %s", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, Duration);
140         }
141 
Debug_Close()142         void Debug_Close()
143         {
144             Debug += "\r\n";
145             fwrite(Debug.c_str(), Debug.size(), 1, F); \
146             fclose(F);
147         }
148     }
149     using namespace ZenLib_File_Debug;
150 
151     #define ZENLIB_DEBUG1(_NAME,_TOAPPEND) \
152         Debug_Open(false); \
153         Debug+=", ";Debug+=_NAME; \
154         _TOAPPEND; \
155         Debug_Close();
156 
157     #define ZENLIB_DEBUG2(_NAME,_TOAPPEND) \
158         Debug_Open(true); \
159         Debug+=", ";Debug+=_NAME; \
160         _TOAPPEND; \
161         Debug_Close();
162 #else // ZENLIB_DEBUG
163     #define ZENLIB_DEBUG1(_NAME,_TOAPPEND)
164     #define ZENLIB_DEBUG2(_NAME,_TOAPPEND)
165 #endif // ZENLIB_DEBUG
166 
167 //***************************************************************************
168 // Constructor/Destructor
169 //***************************************************************************
170 
171 //---------------------------------------------------------------------------
File()172 File::File()
173 {
174     #ifdef ZENLIB_USEWX
175         File_Handle=NULL;
176     #else //ZENLIB_USEWX
177         #ifdef ZENLIB_STANDARD
178             File_Handle=NULL;
179         #elif defined WINDOWS
180             #ifdef WINDOWS_UWP
181                 File_Handle=NULL;
182             #else
183                 File_Handle=INVALID_HANDLE_VALUE;
184             #endif
185         #endif
186     #endif //ZENLIB_USEWX
187     Position=(int64u)-1;
188     Size=(int64u)-1;
189 }
190 
File(Ztring File_Name,access_t Access)191 File::File(Ztring File_Name, access_t Access)
192 {
193     #ifdef ZENLIB_USEWX
194         File_Handle=NULL;
195     #else //ZENLIB_USEWX
196         #ifdef ZENLIB_STANDARD
197             File_Handle=NULL;
198         #elif defined WINDOWS
199             #ifdef WINDOWS_UWP
200                 File_Handle=NULL;
201             #else
202                 File_Handle=INVALID_HANDLE_VALUE;
203             #endif
204         #endif
205     #endif //ZENLIB_USEWX
206     Position=(int64u)-1;
207     Size=(int64u)-1;
208     Open(File_Name, Access);
209 }
210 
211 //---------------------------------------------------------------------------
~File()212 File::~File()
213 {
214     Close();
215 }
216 
217 //***************************************************************************
218 // Open/Close
219 //***************************************************************************
220 
221 //---------------------------------------------------------------------------
Open(const tstring & File_Name_,access_t Access)222 bool File::Open (const tstring &File_Name_, access_t Access)
223 {
224     Close();
225 
226     ZENLIB_DEBUG1(      "File Open",
227                         Debug+=", File_Name="; Debug +=Ztring(File_Name_).To_UTF8();)
228 
229     File_Name=File_Name_;
230 
231     #ifdef ZENLIB_USEWX
232         File_Handle=(void*)new wxFile();
233         if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
234         {
235             //Sometime the file is locked for few milliseconds, we try again later
236             wxMilliSleep(1000);
237             if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
238                 //File is not openable
239                 return false;
240         }
241         return true;
242     #else //ZENLIB_USEWX
243         #ifdef ZENLIB_STANDARD
244             /*
245             int access;
246             switch (Access)
247             {
248                 case Access_Read         : access=O_BINARY|O_RDONLY          ; break;
249                 case Access_Write        : access=O_BINARY|O_WRONLY|O_CREAT|O_TRUNC  ; break;
250                 case Access_Read_Write   : access=O_BINARY|O_RDWR  |O_CREAT  ; break;
251                 case Access_Write_Append : access=O_BINARY|O_WRONLY|O_CREAT|O_APPEND ; break;
252                 default                  : access=0                          ;
253             }
254             #ifdef UNICODE
255                 File_Handle=open(File_Name.To_Local().c_str(), access);
256             #else
257                 File_Handle=open(File_Name.c_str(), access);
258             #endif //UNICODE
259             return File_Handle!=-1;
260             */
261             ios_base::openmode mode;
262             switch (Access)
263             {
264                 case Access_Write        : mode=ios_base::binary|ios_base::in|ios_base::out; break;
265                 case Access_Read_Write   : mode=ios_base::binary|ios_base::in|ios_base::out; break;
266                 case Access_Write_Append : if (!Exists(File_Name))
267                                                 mode=ios_base::binary|ios_base::out;
268                                            else
269                                                 mode=ios_base::binary|ios_base::out|ios_base::app;
270                                            break;
271                 default                  : mode = ios_base::binary | ios_base::in;
272             }
273             #ifdef UNICODE
274                 File_Handle=new fstream(File_Name.To_Local().c_str(), mode);
275             #else
276                 File_Handle=new fstream(File_Name.c_str(), mode);
277             #endif //UNICODE
278             if (!((fstream*)File_Handle)->is_open())
279             {
280                 delete (fstream*)File_Handle; File_Handle=NULL;
281                 return false;
282             }
283             return true;
284         #elif defined WINDOWS
285             #ifdef WINDOWS_UWP
286                 File_Handle=new WrtFile();
287 
288                 FileAccessMode Desired_Mode;
289                 StorageOpenOptions Share_Mode;
290                 switch (Access)
291                 {
292                     case Access_Read: Desired_Mode=FileAccessMode_Read; Share_Mode=StorageOpenOptions_AllowReadersAndWriters; break;
293                     case Access_Write:
294                     case Access_Read_Write:
295                     case Access_Write_Append: Desired_Mode=FileAccessMode_ReadWrite; Share_Mode=StorageOpenOptions_AllowReadersAndWriters; break;
296                     default: Desired_Mode=FileAccessMode_Read; Share_Mode=StorageOpenOptions_None;
297                 }
298 
299                 // Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
300                 File_Name.FindAndReplace(__T("/"), __T("\\"));
301 
302                 if (FAILED(Get_File(HStringReference(File_Name.c_str(), (unsigned int)File_Name.size()), ((WrtFile*)File_Handle)->File)))
303                 {
304                     if (Access==Access_Write || Access==Access_Read_Write || Access==Access_Write_Append)
305                     {
306                         if (!Create(File_Name, false))
307                         {
308                             ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
309                             return false;
310                         }
311 
312                         if (Access==Access_Write_Append)
313                         {
314                             Size_Get();
315                             if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(Size)))
316                             {
317                                 ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
318                                 return false;
319                             }
320                         }
321 
322                         return true;
323                     }
324 
325                     ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
326                     return false;
327                 }
328 
329                 //IStorageFile don't provide OpenWithOptionsAsync
330                 ComPtr<IStorageFile2> File2;
331                 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&File2))) || !File2)
332                 {
333                     ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
334                     return false;
335                 }
336 
337                 ComPtr<IAsyncOperation<IRandomAccessStream*> > Async_Open;
338                 if (FAILED(File2->OpenWithOptionsAsync(Desired_Mode, Share_Mode, &Async_Open)) ||
339                     FAILED(Await(Async_Open)) ||
340                     FAILED(Async_Open->GetResults(&((WrtFile*)File_Handle)->Buffer))
341                     || !((WrtFile*)File_Handle)->Buffer)
342                 {
343                     ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
344                     return false;
345                 }
346 
347                 if (Access==Access_Write_Append)
348                 {
349                     Size_Get();
350                     if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(Size)))
351                     {
352                         ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
353                         return false;
354                     }
355                 }
356                 else
357                     Position=0;
358             #else
359                 DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
360                 switch (Access)
361                 {
362                     case Access_Read         : dwDesiredAccess=FILE_READ_DATA; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_EXISTING;   break;
363                     case Access_Write        : dwDesiredAccess=GENERIC_WRITE;   dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_ALWAYS;   break;
364                     case Access_Read_Write   : dwDesiredAccess=FILE_READ_DATA|GENERIC_WRITE;   dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_ALWAYS;                    break;
365                     case Access_Write_Append : dwDesiredAccess = FILE_APPEND_DATA; dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; dwCreationDisposition = OPEN_ALWAYS; break;
366                     default                  : dwDesiredAccess=0;               dwShareMode=0;                                 dwCreationDisposition=0;             break;
367                 }
368 
369                 #ifdef UNICODE
370                     File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
371                 #else
372                     File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
373                 #endif //UNICODE
374                 #if 0 //Disabled
375                 if (File_Handle==INVALID_HANDLE_VALUE)
376                 {
377                     //Sometimes the file is locked for few milliseconds, we try again later
378                     DWORD dw = GetLastError();
379                     if (dw!=ERROR_FILE_NOT_FOUND)
380                     {
381                         /*
382                         char lpMsgBuf[1000];
383                         FormatMessageA(
384                         FORMAT_MESSAGE_FROM_SYSTEM,
385                         NULL,
386                         dw,
387                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
388                         lpMsgBuf,
389                         1000, NULL );
390                         */
391                         Sleep(1000);
392                         #ifdef UNICODE
393                             File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
394                         #else
395                             File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
396                         #endif //UNICODE
397                     }
398                 }
399                 #endif //0
400                 if (File_Handle==INVALID_HANDLE_VALUE)
401                 {
402                     ZENLIB_DEBUG2(      "File Open",
403                                         Debug+=", returns 0";)
404 
405                     //File is not openable
406                     return false;
407                 }
408 
409                 ZENLIB_DEBUG2(      "File Open",
410                                     Debug+=", returns 1";)
411 
412                 if (Access == Access_Write_Append)
413                     Size_Get();
414                 else
415                     Position = 0;
416             #endif
417             return true;
418         #endif
419     #endif //ZENLIB_USEWX
420 }
421 
422 //---------------------------------------------------------------------------
Create(const Ztring & File_Name_,bool OverWrite)423 bool File::Create (const Ztring &File_Name_, bool OverWrite)
424 {
425     Close();
426 
427     ZENLIB_DEBUG1(      "File Create",
428                         Debug+=", File_Name="; Debug +=Ztring(File_Name_).To_UTF8();)
429 
430     File_Name=File_Name_;
431 
432     #ifdef ZENLIB_USEWX
433         File_Handle=(void*)new wxFile();
434         if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
435         {
436             //Sometime the file is locked for few milliseconds, we try again later
437             wxMilliSleep(3000);
438             if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
439                 //File is not openable
440                 return false;
441         }
442         return true;
443     #else //ZENLIB_USEWX
444         #ifdef ZENLIB_STANDARD
445             /*
446             int access;
447             switch (OverWrite)
448             {
449                 case false        : access=O_BINARY|O_CREAT|O_WRONLY|O_EXCL ; break;
450                 default           : access=O_BINARY|O_CREAT|O_WRONLY|O_TRUNC; break;
451             }
452             #ifdef UNICODE
453                 File_Handle=open(File_Name.To_Local().c_str(), access);
454             #else
455                 File_Handle=open(File_Name.c_str(), access);
456             #endif //UNICODE
457             return  File_Handle!=-1;
458             */
459             /*ios_base::openmode mode;
460 
461             switch (OverWrite)
462             {
463                 //case false         : mode=          ; break;
464                 default                  : mode=0                            ; break;
465             }*/
466             ios_base::openmode access;
467 
468             if (!OverWrite && Exists(File_Name))
469                 return false;
470 
471             access=ios_base::binary|ios_base::in|ios_base::out|ios_base::trunc;
472 
473             #ifdef UNICODE
474                 File_Handle=new fstream(File_Name.To_Local().c_str(), access);
475             #else
476                 File_Handle=new fstream(File_Name.c_str(), access);
477             #endif //UNICODE
478             return ((fstream*)File_Handle)->is_open();
479         #elif defined WINDOWS
480             #ifdef WINDOWS_UWP
481                 File_Handle=new WrtFile();
482 
483                 FileAccessMode Desired_Mode=FileAccessMode_ReadWrite;
484                 StorageOpenOptions Share_Mode=StorageOpenOptions_AllowReadersAndWriters;
485                 CreationCollisionOption Collision_Option=CreationCollisionOption_FailIfExists;
486                 if (OverWrite)
487                     Collision_Option=CreationCollisionOption_ReplaceExisting;
488 
489                 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
490                 File_Name.FindAndReplace(__T("/"), __T("\\"));
491 
492                 //Split file and folder
493                 tstring Destination_Dir=FileName::Path_Get(File_Name);
494                 tstring Destination_File=FileName::Name_Get(File_Name);
495 
496                 //Open dst folder
497                 ComPtr<IStorageFolder> Folder;
498                 if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
499                     return false;
500 
501                 //Create file
502                 ComPtr<IAsyncOperation<StorageFile*> > Async_Create;
503                 ComPtr<IStorageFile> File;
504                 if (FAILED(Folder->CreateFileAsync(HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Create)) ||
505                     FAILED(Await(Async_Create)) ||
506                     FAILED(Async_Create->GetResults(&((WrtFile*)File_Handle)->File)) ||
507                     !((WrtFile*)File_Handle)->File)
508                     return false;
509 
510                 //IStorageFile don't provide OpenWithOptionsAsync
511                 ComPtr<IStorageFile2> File2;
512                 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&File2))) || !File2)
513                     return false;
514 
515                 ComPtr<IAsyncOperation<IRandomAccessStream*> > Async_Open_File;
516                 if (FAILED(File2->OpenWithOptionsAsync(Desired_Mode, Share_Mode, &Async_Open_File)) ||
517                     FAILED(Await(Async_Open_File)) ||
518                     FAILED(Async_Open_File->GetResults(&((WrtFile*)File_Handle)->Buffer)) ||
519                     !((WrtFile*)File_Handle)->Buffer)
520                     return false;
521 
522                 return true;
523             #else
524                 DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
525                 if (OverWrite) {
526                     dwDesiredAccess=GENERIC_WRITE;
527                     dwCreationDisposition=CREATE_ALWAYS;
528                 } else {
529                     dwDesiredAccess=GENERIC_WRITE;
530                     dwCreationDisposition=CREATE_NEW;
531                 }
532                 dwShareMode=0;
533 
534                 #ifdef UNICODE
535                     File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
536                 #else
537                     File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
538                 #endif //UNICODE
539                 #if 0 //Disabled
540                 if (File_Handle==INVALID_HANDLE_VALUE)
541                 {
542                     //Sometime the file is locked for few milliseconds, we try again later
543                     Sleep(3000);
544                     #ifdef UNICODE
545                         File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
546                     #else
547                         File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
548                     #endif //UNICODE
549                 }
550                 #endif //0
551                 if (File_Handle==INVALID_HANDLE_VALUE)
552                 {
553                     ZENLIB_DEBUG2(      "File Create",
554                                         Debug+=", returns 0";)
555 
556                     //File is not openable
557                     return false;
558                 }
559 
560                 ZENLIB_DEBUG2(      "File Create",
561                                     Debug+=", returns 1";)
562             #endif
563             return true;
564         #endif
565     #endif //ZENLIB_USEWX
566 }
567 
568 //---------------------------------------------------------------------------
Close()569 void File::Close ()
570 {
571     #ifdef ZENLIB_DEBUG
572         bool isOpen=false;
573         #ifdef ZENLIB_USEWX
574             if (File_Handle!=NULL)
575         #else //ZENLIB_USEWX
576             #ifdef ZENLIB_STANDARD
577                 if (File_Handle!=NULL)
578             #elif defined WINDOWS
579                 #ifdef WINDOWS_UWP
580                     if (File_Handle)
581                 #else
582                     if (File_Handle!=INVALID_HANDLE_VALUE)
583                 #endif
584             #endif
585         #endif //ZENLIB_USEWX
586             {
587                 ZENLIB_DEBUG1(      "File Close",
588                                     Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8();)
589                 isOpen=true;
590             }
591     #endif
592 
593     #ifdef ZENLIB_USEWX
594         delete (wxFile*)File_Handle; File_Handle=NULL;
595     #else //ZENLIB_USEWX
596         #ifdef ZENLIB_STANDARD
597             //close(File_Handle); File_Handle=-1;
598             delete (fstream*)File_Handle; File_Handle=NULL;
599         #elif defined WINDOWS
600             #ifdef WINDOWS_UWP
601                 delete(WrtFile*)File_Handle; File_Handle=NULL;
602             #else
603                 CloseHandle(File_Handle); File_Handle=INVALID_HANDLE_VALUE;
604             #endif
605         #endif
606     #endif //ZENLIB_USEWX
607     Position=(int64u)-1;
608     Size=(int64u)-1;
609 
610     #ifdef ZENLIB_DEBUG
611         if (isOpen)
612         {
613             ZENLIB_DEBUG2(      "File Close",
614                                 )
615         }
616     #endif
617 }
618 
619 //***************************************************************************
620 // Read/Write
621 //***************************************************************************
622 
623 //---------------------------------------------------------------------------
Read(int8u * Buffer,size_t Buffer_Size_Max)624 size_t File::Read (int8u* Buffer, size_t Buffer_Size_Max)
625 {
626     ZENLIB_DEBUG1("File Read",
627         Debug += ", File_Name="; Debug += Ztring(File_Name).To_UTF8(); Debug += ", MaxSize="; Debug += Ztring::ToZtring(Buffer_Size_Max).To_UTF8())
628 
629 #ifdef ZENLIB_USEWX
630         if (File_Handle == NULL)
631 #else //ZENLIB_USEWX
632     #ifdef ZENLIB_STANDARD
633         if (File_Handle == NULL)
634         #elif defined WINDOWS
635             #ifdef WINDOWS_UWP
636                 boolean Can_Read=FALSE;
637                 if (!File_Handle || !((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanRead(&Can_Read)) || !Can_Read)
638             #else
639                 if (File_Handle == INVALID_HANDLE_VALUE)
640             #endif
641         #endif
642     #endif //ZENLIB_USEWX
643         return 0;
644 
645     #ifdef ZENLIB_USEWX
646         size_t ByteRead=((wxFile*)File_Handle)->Read(Buffer, Buffer_Size_Max);
647         Position+=ByteRead;
648         return ByteRead;
649     #else //ZENLIB_USEWX
650         #ifdef ZENLIB_STANDARD
651             //return read((int)File_Handle, Buffer, Buffer_Size_Max);
652             if (Position==(int64u)-1)
653                 Position_Get();
654             if (Size==(int64u)-1)
655                 Size_Get();
656             if (Position!=(int64u)-1 && Position+Buffer_Size_Max>Size)
657                 Buffer_Size_Max=(size_t)(Size-Position); //We don't want to enable eofbit (impossible to seek after)
658             ((fstream*)File_Handle)->read((char*)Buffer, Buffer_Size_Max);
659             size_t ByteRead=((fstream*)File_Handle)->gcount();
660             Position+=ByteRead;
661             return ByteRead;
662         #elif defined WINDOWS
663             #ifdef WINDOWS_UWP
664                 ComPtr<IInputStream> Stream;
665                 if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
666                     return 0;
667 
668                 ComPtr<IDataReaderFactory> Reader_Factory;
669                 if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), &Reader_Factory)) || !Reader_Factory)
670                     return 0;
671 
672                 ComPtr<IDataReader> Reader;
673                 if (FAILED(Reader_Factory->CreateDataReader(*Stream.GetAddressOf(), &Reader)) || !Reader)
674                     return 0;
675 
676                 UINT32 Readed=0;
677                 ComPtr<IAsyncOperation<UINT32> > Async_Read;
678                 if (FAILED(Reader->LoadAsync((UINT32)Buffer_Size_Max, &Async_Read)) ||
679                     FAILED(Await(Async_Read)) ||
680                     FAILED(Async_Read->GetResults(&Readed)))
681                     return 0;
682 
683                 if (FAILED(Reader->ReadBytes((UINT32)Buffer_Size_Max, (BYTE*)Buffer)))
684                     return 0;
685 
686                 Reader->DetachStream(&Stream);
687 
688                 return (size_t)Readed;
689             #else
690                 DWORD Buffer_Size;
691                 if (ReadFile(File_Handle, Buffer, (DWORD)Buffer_Size_Max, &Buffer_Size, NULL))
692                 {
693                     Position+=Buffer_Size;
694 
695                     ZENLIB_DEBUG2(      "File Read",
696                                         Debug+=", new position ";Debug+=Ztring::ToZtring(Position).To_UTF8();;Debug+=", returns ";Debug+=Ztring::ToZtring((int64u)Buffer_Size).To_UTF8();)
697 
698                     return Buffer_Size;
699                 }
700                 else
701                 {
702                     ZENLIB_DEBUG2(      "File Read",
703                                         Debug+=", returns 0";)
704                     return 0;
705                 }
706             #endif
707         #endif
708     #endif //ZENLIB_USEWX
709 }
710 
711 //---------------------------------------------------------------------------
Write(const int8u * Buffer,size_t Buffer_Size)712 size_t File::Write (const int8u* Buffer, size_t Buffer_Size)
713 {
714     #ifdef ZENLIB_USEWX
715         if (File_Handle==NULL)
716     #else //ZENLIB_USEWX
717         #ifdef ZENLIB_STANDARD
718             if (File_Handle==NULL)
719         #elif defined WINDOWS
720             #ifdef WINDOWS_UWP
721                 boolean Can_Write=FALSE;
722                 if (!File_Handle || !((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanWrite(&Can_Write)) || !Can_Write)
723             #else
724                 if (File_Handle==INVALID_HANDLE_VALUE)
725             #endif
726         #endif
727     #endif //ZENLIB_USEWX
728         return 0;
729 
730     #ifdef ZENLIB_USEWX
731         return ((wxFile*)File_Handle)->Write(Buffer, Buffer_Size);
732     #else //ZENLIB_USEWX
733         #ifdef ZENLIB_STANDARD
734             //return write(File_Handle, Buffer, Buffer_Size);
735             ((fstream*)File_Handle)->write((char*)Buffer, Buffer_Size);
736             if (((fstream*)File_Handle)->bad())
737             {
738                 Position=(int64u)-1;
739                 return 0;
740             }
741             else
742             {
743                 if (Position!=(int64u)-1)
744                     Position+=Buffer_Size;
745                 return Buffer_Size;
746             }
747         #elif defined WINDOWS
748             #ifdef WINDOWS_UWP
749                 ComPtr<IOutputStream> Stream;
750                 if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
751                     return 0;
752 
753                 ComPtr<IDataWriterFactory> Writer_Factory;
754                 if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(), &Writer_Factory)) || !Writer_Factory)
755                     return 0;
756 
757                 ComPtr<IDataWriter> Writer;
758                 if (FAILED(Writer_Factory->CreateDataWriter(*Stream.GetAddressOf(), &Writer)) || !Writer)
759                     return 0;
760 
761                 if (FAILED(Writer->WriteBytes((UINT32)Buffer_Size, (BYTE*)Buffer)))
762                     return 0;
763 
764                 UINT32 Written=0;
765                 ComPtr<IAsyncOperation<UINT32> > Async_Write;
766                 if (FAILED(Writer->StoreAsync(&Async_Write)) ||
767                     FAILED(Await(Async_Write)) ||
768                     FAILED(Async_Write->GetResults(&Written)))
769                     return 0;
770 
771                 Writer->DetachStream(&Stream);
772 
773                 return (size_t)Written;
774             #else
775                 DWORD Buffer_Size_Written;
776                 if (WriteFile(File_Handle, Buffer, (DWORD)Buffer_Size, &Buffer_Size_Written, NULL))
777                 {
778                     if (Position!=(int64u)-1)
779                         Position+=Buffer_Size_Written;
780                     return Buffer_Size_Written;
781                 }
782                 else
783                 {
784                     Position=(int64u)-1;
785                     return 0;
786                 }
787             #endif
788         #endif
789     #endif //ZENLIB_USEWX
790 }
791 
792 //---------------------------------------------------------------------------
Truncate(int64u Offset)793 bool File::Truncate (int64u Offset)
794 {
795     if (File_Handle==NULL)
796         return false;
797 
798     #ifdef ZENLIB_USEWX
799         return false; //Not supported
800     #else //ZENLIB_USEWX
801         #ifdef ZENLIB_STANDARD
802             #if defined(WINDOWS)
803                 return false; //Not supported
804             #else //defined(WINDOWS)
805                 //Need to close the file, use truncate, reopen it
806                 #if !defined(__ANDROID_API__) || __ANDROID_API__ >= 21
807                 if (Offset==(int64u)-1)
808                     Offset=Position_Get();
809                 Ztring File_Name_Sav=File_Name;
810                 Close();
811                 truncate(File_Name_Sav.To_Local().c_str(), Offset);
812                 if (!Open(File_Name_Sav, Access_Read_Write))
813                     return false;
814                 GoTo(0, FromEnd);
815                 return true;
816                 #else
817                 return false; //Not supported
818                 #endif
819             #endif //!defined(WINDOWS)
820         #elif defined WINDOWS
821             #ifdef WINDOWS_UWP
822                 boolean Can_Write=FALSE;
823                 if (!((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanWrite(&Can_Write)) || !Can_Write)
824                     return false;
825 
826                 ComPtr<IOutputStream> Stream;
827                 if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
828                     return false;
829 
830                 if (Offset==(int64u)-1)
831                 {
832                     if (FAILED(((WrtFile*)File_Handle)->Buffer->put_Size((UINT64)Position_Get())))
833                         return false;
834                 }
835                 else
836                 {
837                     if (FAILED(((WrtFile*)File_Handle)->Buffer->put_Size((UINT64)Offset)))
838                         return false;
839                 }
840 
841                 return true;
842             #else
843                 if(Offset!=(int64u)-1 && Offset!=Position_Get())
844                     if (!GoTo(Offset))
845                         return false;
846                 SetEndOfFile(File_Handle);
847                 return true;
848             #endif
849         #endif
850     #endif //ZENLIB_USEWX
851 }
852 
853 //---------------------------------------------------------------------------
Write(const Ztring & ToWrite)854 size_t File::Write (const Ztring &ToWrite)
855 {
856     std::string AnsiString=ToWrite.To_UTF8();
857     return Write((const int8u*)AnsiString.c_str(), AnsiString.size());
858 }
859 
860 //***************************************************************************
861 // Moving
862 //***************************************************************************
863 
864 //---------------------------------------------------------------------------
GoTo(int64s Position_ToMove,move_t MoveMethod)865 bool File::GoTo (int64s Position_ToMove, move_t MoveMethod)
866 {
867     ZENLIB_DEBUG1(      "File GoTo",
868                         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())
869 
870     #ifdef ZENLIB_USEWX
871         if (File_Handle==NULL)
872     #else //ZENLIB_USEWX
873         #ifdef ZENLIB_STANDARD
874             if (File_Handle==NULL)
875         #elif defined WINDOWS
876             #ifdef WINDOWS_UWP
877                 if (!File_Handle || !((WrtFile*)File_Handle)->File || !((WrtFile*)File_Handle)->Buffer)
878             #else
879                 if (File_Handle==INVALID_HANDLE_VALUE)
880             #endif
881         #endif
882     #endif //ZENLIB_USEWX
883         return false;
884 
885     Position=(int64u)-1; //Disabling memory
886     #ifdef ZENLIB_USEWX
887         return ((wxFile*)File_Handle)->Seek(Position, (wxSeekMode)MoveMethod)!=wxInvalidOffset; //move_t and wxSeekMode are same
888     #else //ZENLIB_USEWX
889         #ifdef ZENLIB_STANDARD
890             /*
891             int fromwhere;
892             switch (MoveMethod)
893             {
894                 case FromBegin : fromwhere=SEEK_SET; break;
895                 case FromCurrent : fromwhere=SEEK_CUR; break;
896                 case FromEnd : fromwhere=SEEK_END; break;
897                 default : fromwhere=SEEK_CUR; break;
898             }
899             return lseek(File_Handle, Position, fromwhere)!=-1;
900             */
901             ios_base::seekdir dir;
902             switch (MoveMethod)
903             {
904                 case FromBegin   : dir=ios_base::beg; break;
905                 case FromCurrent : dir=ios_base::cur; break;
906                 case FromEnd     : dir=ios_base::end; break;
907                 default          : dir=ios_base::beg;
908             }
909             ((fstream*)File_Handle)->seekg((streamoff)Position_ToMove, dir);
910             return !((fstream*)File_Handle)->fail();
911         #elif defined WINDOWS
912             #ifdef WINDOWS_UWP
913                 UINT64 New_Position=0;
914                 switch (MoveMethod)
915                 {
916                     case FromBegin   : New_Position=Position_ToMove; break;
917                     case FromCurrent : New_Position=Position_Get()+Position_ToMove; break;
918                     case FromEnd     : New_Position=Size_Get()-Position_ToMove; break;
919                     default          : New_Position=Position_ToMove;
920                 }
921 
922                 if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(New_Position)))
923                     return false;
924 
925                 return true;
926             #else
927                 LARGE_INTEGER GoTo;
928                 GoTo.QuadPart=Position_ToMove;
929                 BOOL i=SetFilePointerEx(File_Handle, GoTo, NULL, MoveMethod);
930 
931                 #ifdef ZENLIB_DEBUG
932                     LARGE_INTEGER Temp; Temp.QuadPart=0;
933                     SetFilePointerEx(File_Handle, Temp, &Temp, FILE_CURRENT);
934                     ZENLIB_DEBUG2(      "File GoTo",
935                                         Debug+=", new position ";Debug+=Ztring::ToZtring(Temp.QuadPart).To_UTF8();Debug+=", returns ";Debug+=i?'1':'0';)
936                 #endif //ZENLIB_DEBUG
937 
938                 return i?true:false;
939             #endif
940         #endif
941     #endif //ZENLIB_USEWX
942 }
943 
944 //---------------------------------------------------------------------------
Position_Get()945 int64u File::Position_Get ()
946 {
947     if (Position!=(int64u)-1)
948         return Position;
949 
950     ZENLIB_DEBUG1(      "File Position_Get",
951                         Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8())
952 
953     #ifdef ZENLIB_USEWX
954         if (File_Handle==NULL)
955     #else //ZENLIB_USEWX
956         #ifdef ZENLIB_STANDARD
957             if (File_Handle==NULL)
958         #elif defined WINDOWS
959             #ifdef WINDOWS_UWP
960                 if (!File_Handle || !((WrtFile*)File_Handle)->File || !((WrtFile*)File_Handle)->Buffer)
961             #else
962                 if (File_Handle == INVALID_HANDLE_VALUE)
963             #endif
964         #endif
965     #endif //ZENLIB_USEWX
966         return (int64u)-1;
967 
968     #ifdef ZENLIB_USEWX
969         return (int64u)-1;
970     #else //ZENLIB_USEWX
971         #ifdef ZENLIB_STANDARD
972             Position=((fstream*)File_Handle)->tellg();
973             return Position;
974         #elif defined WINDOWS
975             #ifdef WINDOWS_UWP
976                 if (FAILED(((WrtFile*)File_Handle)->Buffer->get_Position((UINT64*)&Position)))
977                     return (int64u)-1;
978             #else
979                 LARGE_INTEGER GoTo; GoTo.QuadPart=0;
980                 GoTo.LowPart=SetFilePointer(File_Handle, GoTo.LowPart, &GoTo.HighPart, FILE_CURRENT);
981                 Position=GoTo.QuadPart;
982 
983                 ZENLIB_DEBUG2(      "File GoTo",
984                                     Debug+=", new position ";Debug+=Ztring::ToZtring(GoTo.QuadPart).To_UTF8();Debug+=", returns 1";)
985             #endif
986             return Position;
987         #endif
988     #endif //ZENLIB_USEWX
989 }
990 
991 //***************************************************************************
992 // Attributes
993 //***************************************************************************
994 
995 //---------------------------------------------------------------------------
Size_Get()996 int64u File::Size_Get()
997 {
998     #ifdef ZENLIB_USEWX
999         if (File_Handle==NULL)
1000     #else //ZENLIB_USEWX
1001         #ifdef ZENLIB_STANDARD
1002             if (File_Handle==NULL)
1003         #elif defined WINDOWS
1004             #ifdef WINDOWS_UWP
1005                 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1006             #else
1007                 if (File_Handle==INVALID_HANDLE_VALUE)
1008             #endif
1009         #endif
1010     #endif //ZENLIB_USEWX
1011         return 0;
1012 
1013     #ifdef ZENLIB_USEWX
1014         return ((wxFile*)File_Handle)->Length();
1015     #else //ZENLIB_USEWX
1016         #ifdef ZENLIB_STANDARD
1017             /*
1018             int CurrentPos=lseek(File_Handle, 0, SEEK_CUR);
1019             int64u File_Size;
1020             File_Size=lseek(File_Handle, 0, SEEK_END);
1021             lseek(File_Handle, CurrentPos, SEEK_SET);
1022             */
1023             fstream::pos_type CurrentPos=((fstream*)File_Handle)->tellg();
1024             if (CurrentPos!=(fstream::pos_type)-1)
1025             {
1026                 ((fstream*)File_Handle)->seekg(0, ios_base::end);
1027                 Size=((fstream*)File_Handle)->tellg();
1028                 ((fstream*)File_Handle)->seekg(CurrentPos);
1029             }
1030             else
1031                 Size=(int64u)-1;
1032         #elif defined WINDOWS
1033             #ifdef WINDOWS_UWP
1034                 ComPtr<IStorageItem> Item;
1035                 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1036                     return (int64u)-1;
1037 
1038                 ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
1039                 ComPtr<IBasicProperties> Properties;
1040                 if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
1041                     FAILED(Await(Async_Properties)) ||
1042                     FAILED(Async_Properties->GetResults(&Properties)) ||
1043                     !Properties)
1044                     return (int64u)-1;
1045 
1046                 if (FAILED(Properties->get_Size(&Size)))
1047                     return (int64u)-1;
1048             #else
1049                 LARGE_INTEGER x = {0};
1050                 BOOL bRet = ::GetFileSizeEx(File_Handle, &x);
1051                 if (bRet == FALSE)
1052                     return (int64u)-1;
1053                 Size=x.QuadPart;
1054             #endif
1055         #endif
1056             return Size;
1057     #endif //ZENLIB_USEWX
1058 }
1059 
1060 //---------------------------------------------------------------------------
Created_Get()1061 Ztring File::Created_Get()
1062 {
1063     #ifdef ZENLIB_USEWX
1064         if (File_Handle==NULL)
1065     #else //ZENLIB_USEWX
1066         #ifdef ZENLIB_STANDARD
1067             if (File_Handle==NULL)
1068         #elif defined WINDOWS
1069             #ifdef WINDOWS_UWP
1070                 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1071             #else
1072                 if (File_Handle==INVALID_HANDLE_VALUE)
1073             #endif
1074         #endif
1075     #endif //ZENLIB_USEWX
1076         return Ztring();
1077 
1078     #ifdef ZENLIB_USEWX
1079         return __T(""); //Not implemented
1080     #else //ZENLIB_USEWX
1081         #ifdef ZENLIB_STANDARD
1082             return __T(""); //Not implemented
1083         #elif defined WINDOWS
1084             #ifdef WINDOWS_UWP
1085                 ComPtr<IStorageItem> Item;
1086                 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1087                     return __T("");
1088 
1089                 DateTime Time;
1090                 if (FAILED(Item->get_DateCreated(&Time)))
1091                     return __T("");
1092 
1093                 return Ztring().Date_From_Milliseconds_1601((int64u)(Time.UniversalTime/10000));
1094             #else
1095                 FILETIME TimeFT;
1096                 if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
1097                 {
1098                     int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
1099                     Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
1100                     return Time;
1101                 }
1102                 else
1103                     return __T(""); //There was a problem
1104             #endif
1105         #endif
1106     #endif //ZENLIB_USEWX
1107 }
1108 
1109 //---------------------------------------------------------------------------
1110 #if defined WINDOWS
Calc_Time(const FILETIME & TimeFT)1111 static Ztring Calc_Time(const FILETIME& TimeFT)
1112 {
1113     int64u Time64 = 0x100000000ULL * TimeFT.dwHighDateTime + TimeFT.dwLowDateTime;
1114     TIME_ZONE_INFORMATION Info;
1115     DWORD Result = GetTimeZoneInformation(&Info);
1116     if (Result != TIME_ZONE_ID_INVALID)
1117     {
1118         Time64 -= ((int64s)Info.Bias) * 60 * 1000 * 1000 * 10;
1119         if (Result == TIME_ZONE_ID_DAYLIGHT)
1120             Time64 -= ((int64s)Info.DaylightBias) * 60 * 1000 * 1000 * 10;
1121         else
1122             Time64 -= ((int64s)Info.StandardBias) * 60 * 1000 * 1000 * 10;
1123     }
1124     Ztring Time; Time.Date_From_Milliseconds_1601(Time64 / 10000);
1125     Time.FindAndReplace(__T("UTC "), __T(""));
1126     return Time;
1127 }
1128 #endif
1129 //---------------------------------------------------------------------------
Created_Local_Get()1130 Ztring File::Created_Local_Get()
1131 {
1132     #ifdef ZENLIB_USEWX
1133         if (File_Handle==NULL)
1134     #else //ZENLIB_USEWX
1135         #ifdef ZENLIB_STANDARD
1136             if (File_Handle==NULL)
1137         #elif defined WINDOWS
1138             #ifdef WINDOWS_UWP
1139                 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1140             #else
1141                 if (File_Handle==INVALID_HANDLE_VALUE)
1142             #endif
1143         #endif
1144     #endif //ZENLIB_USEWX
1145         return Ztring();
1146 
1147     #ifdef ZENLIB_USEWX
1148         return __T(""); //Not implemented
1149     #else //ZENLIB_USEWX
1150         #ifdef ZENLIB_STANDARD
1151             return __T(""); //Not implemented
1152         #elif defined WINDOWS
1153             #ifdef WINDOWS_UWP
1154                 ComPtr<IStorageItem> Item;
1155                 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1156                     return __T("");
1157 
1158                 DateTime Time;
1159                 if (FAILED(Item->get_DateCreated(&Time)))
1160                     return __T("");
1161 
1162                 FILETIME File_Time;
1163                 ULARGE_INTEGER Time_Union;
1164                 Time_Union.QuadPart=(ULONGLONG)Time.UniversalTime;
1165                 File_Time.dwHighDateTime=Time_Union.HighPart;
1166                 File_Time.dwLowDateTime=Time_Union.LowPart;
1167 
1168                 return Calc_Time(File_Time);
1169             #else
1170                 FILETIME TimeFT;
1171                 if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
1172                 {
1173                     return Calc_Time(TimeFT);
1174                 }
1175                 else
1176                     return __T(""); //There was a problem
1177            #endif
1178         #endif
1179     #endif //ZENLIB_USEWX
1180 }
1181 
1182 //---------------------------------------------------------------------------
Modified_Get()1183 Ztring File::Modified_Get()
1184 {
1185     #ifdef ZENLIB_USEWX
1186         if (File_Handle==NULL)
1187     #else //ZENLIB_USEWX
1188         #ifdef ZENLIB_STANDARD
1189             if (File_Handle==NULL)
1190         #elif defined WINDOWS
1191             #ifdef WINDOWS_UWP
1192                 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1193             #else
1194                 if (File_Handle==INVALID_HANDLE_VALUE)
1195             #endif
1196         #endif
1197     #endif //ZENLIB_USEWX
1198         return Ztring();
1199 
1200     #ifdef ZENLIB_USEWX
1201         return __T(""); //Not implemented
1202     #else //ZENLIB_USEWX
1203         #ifdef ZENLIB_STANDARD
1204             struct stat Stat;
1205             int Result=stat(File_Name.To_Local().c_str(), &Stat);
1206             if (Result<0)
1207                 return __T(""); //Error
1208             Ztring Time; Time.Date_From_Seconds_1970((int64s)Stat.st_mtime);
1209             return Time;
1210         #elif defined WINDOWS
1211             #ifdef WINDOWS_UWP
1212                 ComPtr<IStorageItem> Item;
1213                 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1214                     return __T("");
1215 
1216                 ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
1217                 ComPtr<IBasicProperties> Properties;
1218                 if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
1219                     FAILED(Await(Async_Properties)) ||
1220                     FAILED(Async_Properties->GetResults(&Properties)) ||
1221                     !Properties)
1222                     return __T("");
1223 
1224                 DateTime Time;
1225                 if (FAILED(Properties->get_DateModified(&Time)) || Time.UniversalTime==0)
1226                     return __T("");
1227 
1228                 return Ztring().Date_From_Milliseconds_1601((int64u)(Time.UniversalTime/10000));
1229             #else
1230                 FILETIME TimeFT;
1231                 if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
1232                 {
1233                     int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
1234                     Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
1235                     return Time;
1236                 }
1237                 else
1238                     return __T(""); //There was a problem
1239             #endif
1240         #endif
1241     #endif //ZENLIB_USEWX
1242 }
1243 
1244 //---------------------------------------------------------------------------
Modified_Local_Get()1245 Ztring File::Modified_Local_Get()
1246 {
1247     #ifdef ZENLIB_USEWX
1248         if (File_Handle==NULL)
1249     #else //ZENLIB_USEWX
1250         #ifdef ZENLIB_STANDARD
1251             if (File_Handle==NULL)
1252         #elif defined WINDOWS
1253             #ifdef WINDOWS_UWP
1254                 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1255             #else
1256                 if (File_Handle==INVALID_HANDLE_VALUE)
1257             #endif
1258         #endif
1259     #endif //ZENLIB_USEWX
1260         return Ztring();
1261 
1262     #ifdef ZENLIB_USEWX
1263         return __T(""); //Not implemented
1264     #else //ZENLIB_USEWX
1265         #ifdef ZENLIB_STANDARD
1266             struct stat Stat;
1267             int Result=stat(File_Name.To_Local().c_str(), &Stat);
1268             if (Result<0)
1269                 return __T(""); //Error
1270             Ztring Time; Time.Date_From_Seconds_1970_Local(Stat.st_mtime);
1271             return Time;
1272         #elif defined WINDOWS
1273             #ifdef WINDOWS_UWP
1274                 ComPtr<IStorageItem> Item;
1275                 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1276                     return __T("");
1277 
1278                 ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
1279                 ComPtr<IBasicProperties> Properties;
1280                 if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
1281                     FAILED(Await(Async_Properties)) ||
1282                     FAILED(Async_Properties->GetResults(&Properties)) ||
1283                     !Properties)
1284                     return __T("");
1285 
1286                 DateTime Time;
1287                 if (FAILED(Properties->get_DateModified(&Time)) || Time.UniversalTime==0)
1288                     return __T("");
1289 
1290                 FILETIME File_Time;
1291                 ULARGE_INTEGER Time_Union;
1292                 Time_Union.QuadPart=(ULONGLONG)Time.UniversalTime;
1293                 File_Time.dwHighDateTime=Time_Union.HighPart;
1294                 File_Time.dwLowDateTime=Time_Union.LowPart;
1295 
1296                 return Calc_Time(File_Time);
1297             #else
1298                 FILETIME TimeFT;
1299                 if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
1300                 {
1301                     return Calc_Time(TimeFT);
1302                 }
1303                 else
1304                     return __T(""); //There was a problem
1305             #endif
1306         #endif
1307     #endif //ZENLIB_USEWX
1308 }
1309 
1310 //---------------------------------------------------------------------------
Opened_Get()1311 bool File::Opened_Get()
1312 {
1313     #ifdef ZENLIB_USEWX
1314         return File_Handle!=NULL;
1315     #else //ZENLIB_USEWX
1316         #ifdef ZENLIB_STANDARD
1317             //return File_Handle!=-1;
1318             return File_Handle!=NULL && ((fstream*)File_Handle)->is_open();
1319         #elif defined WINDOWS
1320             #ifdef WINDOWS_UWP
1321                 return File_Handle && ((WrtFile*)File_Handle)->File && ((WrtFile*)File_Handle)->Buffer;
1322             #else
1323                 return File_Handle!=INVALID_HANDLE_VALUE;
1324             #endif
1325         #endif
1326     #endif //ZENLIB_USEWX
1327 }
1328 
1329 //***************************************************************************
1330 // Helpers
1331 //***************************************************************************
1332 
1333 //---------------------------------------------------------------------------
Size_Get(const Ztring & File_Name)1334 int64u File::Size_Get(const Ztring &File_Name)
1335 {
1336     File F(File_Name);
1337     return F.Size_Get();
1338 }
1339 
1340 //---------------------------------------------------------------------------
Created_Get(const Ztring & File_Name)1341 Ztring File::Created_Get(const Ztring &File_Name)
1342 {
1343     File F(File_Name);
1344     return F.Created_Get();
1345 }
1346 
1347 //---------------------------------------------------------------------------
Modified_Get(const Ztring & File_Name)1348 Ztring File::Modified_Get(const Ztring &File_Name)
1349 {
1350     File F(File_Name);
1351     return F.Modified_Get();
1352 }
1353 
1354 //---------------------------------------------------------------------------
Exists(const Ztring & File_Name)1355 bool File::Exists(const Ztring &File_Name)
1356 {
1357     ZENLIB_DEBUG1(      "File Exists",
1358                         Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8())
1359 
1360     #ifdef ZENLIB_USEWX
1361         wxFileName FN(File_Name.c_str());
1362         return FN.FileExists();
1363     #else //ZENLIB_USEWX
1364         #ifdef ZENLIB_STANDARD
1365             #if defined WINDOWS
1366                 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))
1367                     return false;
1368             #endif //defined WINDOWS
1369             struct stat buffer;
1370             int         status;
1371             #ifdef UNICODE
1372                 status=stat(File_Name.To_Local().c_str(), &buffer);
1373             #else
1374                 status=stat(File_Name.c_str(), &buffer);
1375             #endif //UNICODE
1376             return status==0 && S_ISREG(buffer.st_mode);
1377         #elif defined WINDOWS
1378             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))
1379                 return false;
1380             #ifdef WINDOWS_UWP
1381                 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
1382                 Ztring File_Name_=File_Name;
1383                 File_Name_.FindAndReplace(__T("/"), __T("\\"));
1384 
1385                 //Try to access file directly
1386                 ComPtr<IStorageFile> File;
1387                 if (SUCCEEDED(Get_File(HStringReference(File_Name_.c_str(), (unsigned int)File_Name_.size()), File)))
1388                     return true;
1389 
1390                 //Try directory access methods
1391                 tstring Dir_=FileName::Path_Get(File_Name_);
1392                 tstring File_=FileName::Name_Get(File_Name_);
1393 
1394                 ComPtr<IStorageFolder> Folder;
1395                 if (FAILED(Get_Folder(HStringReference(Dir_.c_str(), (unsigned int)Dir_.size()), Folder)))
1396                     return false;
1397 
1398                 //IStorageFolder don't provide TryGetItemAsync
1399                 ComPtr<IStorageFolder2> Folder2;
1400                 if (FAILED(Folder->QueryInterface(IID_PPV_ARGS(&Folder2))) || !Folder2)
1401                     return false;
1402 
1403                 ComPtr<IAsyncOperation<IStorageItem*> > Async_GetItem;
1404                 ComPtr<IStorageItem> Item;
1405                 ComPtr<IStorageFile> AsFile;
1406                 if (SUCCEEDED(Folder2->TryGetItemAsync(HStringReference(File_.c_str(), (unsigned int)File_.size()).Get(), &Async_GetItem)) &&
1407                     SUCCEEDED(Await(Async_GetItem)) &&
1408                     SUCCEEDED(Async_GetItem->GetResults(&Item)) &&
1409                     Item &&
1410                     SUCCEEDED(Item.As(&AsFile)))
1411                     return true;
1412 
1413                 return false;
1414             #else
1415                 #ifdef UNICODE
1416                     DWORD FileAttributes=GetFileAttributesW(File_Name.c_str());
1417                 #else
1418                     DWORD FileAttributes=GetFileAttributes(File_Name.c_str());
1419                 #endif //UNICODE
1420 
1421                 ZENLIB_DEBUG2(      "File Exists",
1422                                     Debug+=", File_Name="; Debug+=Ztring::ToZtring(((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY))?1:0).To_UTF8())
1423 
1424                 return ((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY));
1425             #endif
1426         #endif
1427     #endif //ZENLIB_USEWX
1428 }
1429 
1430 //---------------------------------------------------------------------------
Copy(const Ztring & Source,const Ztring & Destination,bool OverWrite)1431 bool File::Copy(const Ztring &Source, const Ztring &Destination, bool OverWrite)
1432 {
1433     #ifdef ZENLIB_USEWX
1434         return wxCopyFile(Source.c_str(), Destination.c_str(), OverWrite);
1435     #else //ZENLIB_USEWX
1436         #ifdef ZENLIB_STANDARD
1437             return false;
1438         #elif defined WINDOWS
1439             #ifdef WINDOWS_UWP
1440                 NameCollisionOption Collision_Option=NameCollisionOption_FailIfExists;
1441                 if (OverWrite)
1442                     Collision_Option=NameCollisionOption_ReplaceExisting;
1443 
1444                 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
1445                 Ztring Source_=Source;
1446                 Source_.FindAndReplace(__T("/"), __T("\\"));
1447 
1448                 Ztring Destination_=Destination;
1449                 Destination_.FindAndReplace(__T("/"), __T("\\"));
1450 
1451                 //Split destination file and folder
1452                 tstring Destination_Dir=FileName::Path_Get(Destination_);
1453                 tstring Destination_File=FileName::Name_Get(Destination_);
1454 
1455                 //Open src file
1456                 ComPtr<IStorageFile> File;
1457                 if (FAILED(Get_File(HStringReference(Source_.c_str(), (unsigned int)Source_.size()), File)))
1458                     return false;
1459 
1460                 //Open dst folder
1461                 ComPtr<IStorageFolder> Folder;
1462                 if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
1463                     return false;
1464 
1465                 //Copy file
1466                 ComPtr<IAsyncOperation<StorageFile*> > Async_Copy;
1467                 ComPtr<IStorageFile> New_File;
1468                 if (FAILED(File->CopyOverload(*Folder.GetAddressOf(), HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Copy)) ||
1469                     FAILED(Await(Async_Copy)) ||
1470                     FAILED(Async_Copy->GetResults(&New_File)) ||
1471                     !New_File)
1472                     return false;
1473 
1474                 return true;
1475             #else
1476                 #ifdef UNICODE
1477                     return CopyFileW(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
1478                 #else
1479                     return CopyFile(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
1480                 #endif //UNICODE
1481             #endif
1482         #endif
1483     #endif //ZENLIB_USEWX
1484 }
1485 
1486 //---------------------------------------------------------------------------
Move(const Ztring & Source,const Ztring & Destination,bool OverWrite)1487 bool File::Move(const Ztring &Source, const Ztring &Destination, bool OverWrite)
1488 {
1489     if (OverWrite && Exists(Source))
1490         Delete(Destination);
1491     #ifdef ZENLIB_USEWX
1492         if (OverWrite && Exists(Destination))
1493             wxRemoveFile(Destination.c_str());
1494         return wxRenameFile(Source.c_str(), Destination.c_str());
1495     #else //ZENLIB_USEWX
1496         #ifdef ZENLIB_STANDARD
1497             return !std::rename(Source.To_Local().c_str(), Destination.To_Local().c_str());
1498         #elif defined WINDOWS
1499             #ifdef WINDOWS_UWP
1500                 NameCollisionOption Collision_Option=NameCollisionOption_FailIfExists;
1501                 if (OverWrite)
1502                     Collision_Option=NameCollisionOption_ReplaceExisting;
1503 
1504                 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
1505                 Ztring Source_=Source;
1506                 Source_.FindAndReplace(__T("/"), __T("\\"));
1507 
1508                 Ztring Destination_=Destination;
1509                 Destination_.FindAndReplace(__T("/"), __T("\\"));
1510 
1511                 //Split destination file and folder
1512                 tstring Destination_Dir=FileName::Path_Get(Destination_);
1513                 tstring Destination_File=FileName::Name_Get(Destination_);
1514 
1515                 //Open src file
1516                 ComPtr<IStorageFile> File;
1517                 if (FAILED(Get_File(HStringReference(Source_.c_str(), (unsigned int)Source_.size()), File)))
1518                     return false;
1519 
1520                 //Open dst folder
1521                 ComPtr<IStorageFolder> Folder;
1522                 if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
1523                     return false;
1524 
1525                 //Move file
1526                 ComPtr<IAsyncAction> Async_Move;
1527                 if (FAILED(File->MoveOverload(*Folder.GetAddressOf(), HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Move)) ||
1528                     FAILED(Await(Async_Move)) ||
1529                     FAILED(Async_Move->GetResults()))
1530                     return false;
1531 
1532                 return true;
1533             #else
1534                 #ifdef UNICODE
1535                     return MoveFileExW(Source.c_str(), Destination.c_str(), 0)!=0;
1536                 #else
1537                     return MoveFileEx(Source.c_str(), Destination.c_str(), 0)!=0;
1538                 #endif //UNICODE
1539             #endif
1540         #endif
1541     #endif //ZENLIB_USEWX
1542 }
1543 
1544 //---------------------------------------------------------------------------
Delete(const Ztring & File_Name)1545 bool File::Delete(const Ztring &File_Name)
1546 {
1547     #ifdef ZENLIB_USEWX
1548         return wxRemoveFile(File_Name.c_str());
1549     #else //ZENLIB_USEWX
1550         #ifdef ZENLIB_STANDARD
1551             #ifdef UNICODE
1552                 return unlink(File_Name.To_Local().c_str())==0;
1553             #else
1554                 return unlink(File_Name.c_str())==0;
1555             #endif //UNICODE
1556         #elif defined WINDOWS
1557             #ifdef WINDOWS_UWP
1558                 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
1559                 Ztring File_Name_=File_Name;
1560                 File_Name_.FindAndReplace(__T("/"), __T("\\"));
1561 
1562                 ComPtr<IStorageFile> File_;
1563                 if (FAILED(Get_File(HStringReference(File_Name_.c_str(), (unsigned int)File_Name_.size()), File_)))
1564                     return false;
1565 
1566                 ComPtr<IStorageItem> Item;
1567                 if (FAILED(File_->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1568                     return false;
1569 
1570                 ComPtr<IAsyncAction> Async_Delete;
1571                 if (FAILED(Item->DeleteAsync(StorageDeleteOption_Default, &Async_Delete)) ||
1572                     FAILED(Await(Async_Delete)) ||
1573                     FAILED(Async_Delete->GetResults()))
1574                     return false;
1575 
1576                 return true;
1577             #else
1578                 #ifdef UNICODE
1579                     return DeleteFileW(File_Name.c_str())!=0;
1580                 #else
1581                     return DeleteFile(File_Name.c_str())!=0;
1582                 #endif //UNICODE
1583             #endif
1584         #endif
1585     #endif //ZENLIB_USEWX
1586 }
1587 
1588 //***************************************************************************
1589 //
1590 //***************************************************************************
1591 
1592 } //namespace
1593