~smspillaz/nux/nux.fix_1036521

« back to all changes in this revision

Viewing changes to NuxCore/FileManager/NFileManagerWindows.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-01 19:25:37 UTC
  • Revision ID: neil.patel@canonical.com-20100901192537-mfz7rm6q262pewg6
Import and build NuxCore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "NKernel.h"
 
2
#include "Math/MathUtility.h"
 
3
 
 
4
NAMESPACE_BEGIN
 
5
 
 
6
// Choose the size so it is a power of 2. Example (size-1)= 11111111.
 
7
const t_int  NWindowsSerialFileReader::sBufferSize = 1024;
 
8
 
 
9
NWindowsSerialFileReader::NWindowsSerialFileReader(HANDLE InHandle, NOutputDevice& InError)
 
10
:   m_FileHandle    (InHandle)
 
11
,   m_Error         (InError)
 
12
,   m_FilePos       (0)
 
13
,   m_BufferBase    (0)
 
14
,   m_BufferCount   (0)
 
15
{
 
16
    m_Buffer = new BYTE[sBufferSize];
 
17
    m_FileSize = GetFileSize();
 
18
}
 
19
NWindowsSerialFileReader::~NWindowsSerialFileReader()
 
20
{
 
21
    INL_SAFE_DELETE_ARRAY(m_Buffer);
 
22
    if(m_FileHandle)
 
23
    {
 
24
        Close();
 
25
    }
 
26
}
 
27
 
 
28
bool NWindowsSerialFileReader::Precache(t_int PrecacheOffset, t_int PrecacheSize)
 
29
{
 
30
    // Only pre-cache at current position and avoid work if pre-caching same offset twice.
 
31
    if((m_FilePos == PrecacheOffset) && (!m_BufferBase || !m_BufferCount || m_BufferBase != m_FilePos))
 
32
    {
 
33
        m_BufferBase = m_FilePos;
 
34
        // (sBufferSize - 1) contains only '1', i.e 1111111111. 
 
35
        // So (m_FilePos & (sBufferSize-1)) is equal to m_FilePos if m_FilePos <= (sBufferSize-1).
 
36
        m_BufferCount = Min<t_s64>(Min<t_s64>(PrecacheSize, (t_int)(sBufferSize - (m_FilePos & (sBufferSize-1)))), m_FileSize - m_FilePos);
 
37
        t_u32 Count = 0;
 
38
        //GTotalBytesReadViaFileManager += m_BufferCount;
 
39
        ::ReadFile(m_FileHandle, m_Buffer, m_BufferCount, INL_REINTERPRET_CAST(DWORD*, &Count), NULL);
 
40
        if(Count != m_BufferCount)
 
41
        {
 
42
            m_ErrorCode = 1;
 
43
            m_Error.LogFunction(TEXT("ReadFile failed: Count=%i BufferCount=%i Error=%s"), Count, m_BufferCount, inlGetSystemErrorMessage());
 
44
        }
 
45
    }
 
46
    return TRUE;
 
47
}
 
48
 
 
49
t_s64 NWindowsSerialFileReader::Seek(t_s64 InPos, NSerializer::SeekPos seekpos)
 
50
{
 
51
    nuxAssert(InPos >= 0);
 
52
    nuxAssert(InPos <= m_FileSize);
 
53
 
 
54
    Flush();
 
55
    // Because we precache our reads, we must perform Seek accordingly.
 
56
    
 
57
    LARGE_INTEGER pos;
 
58
    pos.QuadPart = m_FilePos;
 
59
    LARGE_INTEGER filepos;
 
60
    filepos.QuadPart = 0;
 
61
    
 
62
    // Set the file pointer to m_FilePos.
 
63
    if(::SetFilePointerEx(m_FileHandle, pos, &filepos, FILE_BEGIN) == 0)
 
64
    {
 
65
        m_ErrorCode = 1;
 
66
        m_Error.LogFunction(TEXT("SetFilePointer Failed %i/%i: %i %s"), InPos, m_FileSize, m_FilePos, inlGetSystemErrorMessage());
 
67
    }
 
68
 
 
69
    // Now the file pointer is current with what we have read so far.
 
70
    pos.QuadPart = InPos;
 
71
    filepos.QuadPart = 0;
 
72
    if(::SetFilePointerEx(m_FileHandle, pos, &filepos, (seekpos == SeekStart) ? FILE_BEGIN : (seekpos == SeekCurrent) ? FILE_CURRENT : FILE_END) == 0)
 
73
    {
 
74
        m_ErrorCode = 1;
 
75
        m_Error.LogFunction(TEXT("SetFilePointer Failed %i/%i: %i %s"), InPos, m_FileSize, m_FilePos, inlGetSystemErrorMessage());
 
76
    }
 
77
    m_FilePos   = filepos.QuadPart;
 
78
    m_BufferBase  = 0;
 
79
    m_BufferCount = 0;
 
80
    Precache(m_FilePos, sBufferSize);
 
81
    return filepos.QuadPart;
 
82
}
 
83
 
 
84
t_s64 NWindowsSerialFileReader::Tell()
 
85
{
 
86
//     Flush();
 
87
//     LARGE_INTEGER pos;
 
88
//     LARGE_INTEGER filepos;
 
89
//     pos.QuadPart = 0;
 
90
//     ::SetFilePointerEx(m_FileHandle, pos, &filepos, FILE_CURRENT);
 
91
//     return filepos.QuadPart;
 
92
 
 
93
    return m_FilePos;
 
94
}
 
95
 
 
96
t_s64 NWindowsSerialFileReader::GetFileSize()
 
97
{
 
98
    nuxAssert(m_FileHandle);
 
99
    if(m_FileHandle == NULL)
 
100
        return -1;
 
101
 
 
102
    t_s64 Size = 0;
 
103
    if(::GetFileSizeEx(m_FileHandle, INL_REINTERPRET_CAST(PLARGE_INTEGER, &Size)) == 0)
 
104
    {
 
105
        Size = -1;
 
106
    }
 
107
    m_FileSize = Size > 0 ? Size : 0;
 
108
    return Size;
 
109
}
 
110
 
 
111
bool NWindowsSerialFileReader::Close()
 
112
{
 
113
    if(m_FileHandle)
 
114
    {
 
115
        CloseHandle(m_FileHandle);
 
116
    }
 
117
    m_FileHandle = NULL;
 
118
    return !m_ErrorCode;
 
119
}
 
120
 
 
121
void NWindowsSerialFileReader::SerializeFinal(void* Dest, t_u64 Length)
 
122
{
 
123
    nuxAssert(Dest);
 
124
    while(Length > 0)
 
125
    {
 
126
        t_int DataSize = Min<t_s64>(Length, m_BufferBase + m_BufferCount - m_FilePos);
 
127
        if(DataSize == 0)
 
128
        {
 
129
            if(Length >= sBufferSize)
 
130
            {
 
131
                t_int Count=0;
 
132
                //GTotalBytesReadViaFileManager += Length;              
 
133
                ReadFile(m_FileHandle, Dest, Length, (DWORD*)&Count, NULL);
 
134
                if(Count!=Length)
 
135
                {
 
136
                    m_ErrorCode = 1;
 
137
                    m_Error.LogFunction(TEXT("ReadFile failed: Count=%i Length=%i Error=%s"), Count, Length, inlGetSystemErrorMessage());
 
138
                }
 
139
                m_FilePos += Length;
 
140
                m_BufferBase += Length;
 
141
                return;
 
142
            }
 
143
            Precache(m_FilePos, t_s32_max);
 
144
            DataSize = Min<t_s64>(Length, m_BufferBase + m_BufferCount - m_FilePos);
 
145
            if(DataSize <= 0)
 
146
            {
 
147
                m_ErrorCode = 1;
 
148
                m_Error.LogFunction(TEXT("ReadFile beyond EOF %i+%i/%i"), m_FilePos, Length, m_FileSize);
 
149
            }
 
150
            if(m_ErrorCode)
 
151
                return;
 
152
        }
 
153
        Memcpy(Dest, m_Buffer + m_FilePos - m_BufferBase, DataSize);
 
154
        m_FilePos   += DataSize;
 
155
        Length      -= DataSize;
 
156
        Dest        = (BYTE*)Dest + DataSize;
 
157
    }
 
158
}
 
159
//////////////////////////////////////////////////////////////////////////
 
160
// Choose the size so it is a power of 2. Example (size-1)= 11111111.
 
161
const t_int  NWindowsSerialFileWriter::sBufferSize = 32;
 
162
//NCriticalSection NWindowsSerialFileWriter::m_CriticalSection;
 
163
 
 
164
NWindowsSerialFileWriter::NWindowsSerialFileWriter(HANDLE InHandle, NOutputDevice& InError)
 
165
:   m_FileHandle  (InHandle)
 
166
,   m_Error       (InError)
 
167
,   m_BufferCount (0)
 
168
{
 
169
    m_Pos = Tell();
 
170
    m_Buffer = new BYTE[sBufferSize];
 
171
}
 
172
 
 
173
NWindowsSerialFileWriter::~NWindowsSerialFileWriter()
 
174
{
 
175
    INL_SAFE_DELETE_ARRAY(m_Buffer);
 
176
    if(m_FileHandle)
 
177
        Close();
 
178
    m_FileHandle = NULL;
 
179
}
 
180
 
 
181
t_s64 NWindowsSerialFileWriter::Seek(t_s64 InPos, NSerializer::SeekPos seekpos)
 
182
{
 
183
    NScopeLock Scope(&m_CriticalSection);
 
184
    nuxAssert(m_FileHandle);
 
185
    if(m_FileHandle == NULL)
 
186
        return -1;
 
187
 
 
188
    _Flush();
 
189
    LARGE_INTEGER pos;
 
190
    pos.QuadPart = InPos;
 
191
    LARGE_INTEGER filepos;
 
192
    filepos.QuadPart = 0;
 
193
    if(::SetFilePointerEx(m_FileHandle, pos, &filepos, (seekpos == SeekStart) ? FILE_BEGIN : (seekpos == SeekCurrent) ? FILE_CURRENT : FILE_END) == 0)
 
194
    {
 
195
        m_ErrorCode = 1;
 
196
        m_Error.LogFunction(TEXT("SeekFailed"));
 
197
    }
 
198
    m_Pos = filepos.QuadPart;
 
199
        
 
200
    return filepos.QuadPart;
 
201
}
 
202
 
 
203
t_s64 NWindowsSerialFileWriter::Tell()
 
204
{
 
205
    NScopeLock Scope(&m_CriticalSection);
 
206
    nuxAssert(m_FileHandle);
 
207
    if(m_FileHandle == NULL)
 
208
        return -1;
 
209
 
 
210
    _Flush();
 
211
    LARGE_INTEGER pos;
 
212
    LARGE_INTEGER filepos;
 
213
    filepos.QuadPart = 0;
 
214
    pos.QuadPart = 0;
 
215
    ::SetFilePointerEx(m_FileHandle, pos, &filepos, FILE_CURRENT);
 
216
    return filepos.QuadPart;
 
217
}
 
218
 
 
219
bool NWindowsSerialFileWriter::Close()
 
220
{
 
221
    NScopeLock Scope(&m_CriticalSection);
 
222
    nuxAssert(m_FileHandle);
 
223
    if(m_FileHandle == NULL)
 
224
        return true;
 
225
 
 
226
    _Flush();
 
227
    if(m_FileHandle && !CloseHandle(m_FileHandle))
 
228
    {
 
229
        m_ErrorCode = 1;
 
230
        m_Error.LogFunction(TEXT("WriteFailed"));
 
231
    }
 
232
    m_FileHandle = NULL;
 
233
    return !m_ErrorCode;
 
234
}
 
235
 
 
236
t_s64 NWindowsSerialFileWriter::GetFileSize()
 
237
{
 
238
    nuxAssert(m_FileHandle);
 
239
    if(m_FileHandle == NULL)
 
240
        return -1;
 
241
 
 
242
    t_s64 Size = 0;
 
243
    if(::GetFileSizeEx(m_FileHandle, INL_REINTERPRET_CAST(PLARGE_INTEGER, &Size)) == 0)
 
244
    {
 
245
        Size = -1;
 
246
    }
 
247
    return Size;
 
248
}
 
249
 
 
250
void NWindowsSerialFileWriter::SerializeFinal(void* V, t_u64 Length)
 
251
{
 
252
    // This method is not re-entrant by itself. It relies on m_Buffer and other variables
 
253
    // that belong to this object. Therefore, it is not thread safe. We add a critical section
 
254
    // to make it thread safe.
 
255
 
 
256
    NScopeLock Scope(&m_CriticalSection);
 
257
    nuxAssert(m_FileHandle);
 
258
    nuxAssert(V);
 
259
 
 
260
    INL_RETURN_IF_NULL(m_FileHandle);
 
261
 
 
262
    m_Pos += Length;
 
263
    t_int FreeSpace;
 
264
    while(Length > (FreeSpace = sBufferSize - m_BufferCount))
 
265
    {
 
266
        // m_Buffer is Full. Write it to the file.
 
267
        Memcpy(m_Buffer + m_BufferCount, V, FreeSpace);
 
268
        m_BufferCount   += FreeSpace;
 
269
        Length          -= FreeSpace;
 
270
        V               = (BYTE*)V + FreeSpace;
 
271
        _Flush();
 
272
    }
 
273
    if(Length)
 
274
    {
 
275
        Memcpy(m_Buffer + m_BufferCount, V, Length);
 
276
        m_BufferCount += Length; // Count the number of Characters stored in m_Buffer.
 
277
    }
 
278
}
 
279
 
 
280
void NWindowsSerialFileWriter::Flush()
 
281
{
 
282
    NScopeLock Scope(&m_CriticalSection);
 
283
    nuxAssert(m_FileHandle);
 
284
    if(m_FileHandle == NULL)
 
285
        return;
 
286
    _Flush();
 
287
}
 
288
 
 
289
void NWindowsSerialFileWriter::_Flush()
 
290
{
 
291
    //GTotalBytesWrittenViaFileManager += m_BufferCount;
 
292
    if(m_BufferCount)
 
293
    {
 
294
        t_int Result=0;
 
295
        if(!WriteFile(m_FileHandle, m_Buffer, m_BufferCount, (DWORD*)&Result, NULL))
 
296
        {
 
297
            m_ErrorCode = 1;
 
298
            m_Error.LogFunction(TEXT("[NWindowsSerialFileWriter::_Flush] Write failed"));
 
299
        }
 
300
    }
 
301
    m_BufferCount = 0;
 
302
}
 
303
 
 
304
//////////////////////////////////////////////////////////////////////////
 
305
INL_IMPLEMENT_GLOBAL_OBJECT(NFileManagerWindows);
 
306
 
 
307
void NFileManagerWindows::Constructor()
 
308
{
 
309
}
 
310
 
 
311
void NFileManagerWindows::Destructor()
 
312
{
 
313
}
 
314
 
 
315
HANDLE NFileManagerWindows::CreateReadFileHandle(const TCHAR* Filename, DWORD Flags)
 
316
{
 
317
    DWORD  Access    = GENERIC_READ;
 
318
    DWORD  Create    = OPEN_EXISTING;
 
319
 
 
320
    DWORD  SharedModeFlags  = 0;
 
321
    SharedModeFlags |= (Flags & NSerializer::Read) ? FILE_SHARE_READ : 0;
 
322
    SharedModeFlags |= (Flags & NSerializer::Write) ? FILE_SHARE_WRITE : 0;
 
323
 
 
324
    HANDLE Handle    = ::CreateFile(Filename, Access, SharedModeFlags, NULL, Create, FILE_ATTRIBUTE_NORMAL, NULL);
 
325
    if(Handle == INVALID_HANDLE_VALUE)
 
326
    {
 
327
        if(Flags & NSerializer::OutputErrorIfFail)
 
328
            nuxError(TEXT("Failed to read file: %s"), Filename);
 
329
    }
 
330
    return Handle;
 
331
}
 
332
 
 
333
NSerializer* NFileManagerWindows::CreateFileReader(const TCHAR* Filename, DWORD Flags, NOutputDevice& Error)
 
334
{
 
335
    HANDLE Handle = CreateReadFileHandle(Filename, Flags);
 
336
    if(Handle == INVALID_HANDLE_VALUE)
 
337
    {
 
338
        return 0;
 
339
    }
 
340
    return new NWindowsSerialFileReader(Handle, Error);
 
341
}
 
342
 
 
343
HANDLE NFileManagerWindows::CreateWriteFileHandle(const TCHAR* Filename, DWORD Flags)
 
344
{
 
345
    if(Flags & NSerializer::OverWriteReadOnly)
 
346
    {
 
347
        ::SetFileAttributes(Filename, 0);
 
348
    }
 
349
 
 
350
    DWORD  Access    = GENERIC_WRITE;
 
351
    DWORD  SharedModeFlags  = 0;
 
352
    SharedModeFlags |= (Flags & NSerializer::Read) ? FILE_SHARE_READ : 0;
 
353
    SharedModeFlags |= (Flags & NSerializer::Write) ? FILE_SHARE_WRITE : 0;
 
354
 
 
355
    DWORD  Create    = 0;
 
356
    Create          |= (Flags & NSerializer::Append) ? OPEN_ALWAYS : 0;
 
357
    Create          |= (Flags & NSerializer::NoOverWrite) ? CREATE_NEW /*fail if the file already exist*/: CREATE_ALWAYS /*create the file if it does not exist*/;
 
358
    HANDLE Handle    = ::CreateFile(Filename, Access, SharedModeFlags, NULL, Create, FILE_ATTRIBUTE_NORMAL, NULL);
 
359
 
 
360
    t_int Pos = 0;
 
361
    if(Handle == INVALID_HANDLE_VALUE)
 
362
    {
 
363
        if(Flags & NSerializer::OutputErrorIfFail)
 
364
        {
 
365
            nuxError(TEXT("[NFileManagerWindows::CreateFileWriter] Failed to create file %s (GetLastError: %d)"), Filename, ::GetLastError());
 
366
        }
 
367
    }
 
368
    if((Flags & NSerializer::Append) && (Handle != INVALID_HANDLE_VALUE))
 
369
    {
 
370
        Pos = ::SetFilePointer(Handle, 0, 0, FILE_END);
 
371
    }
 
372
    return Handle;
 
373
}
 
374
 
 
375
NSerializer* NFileManagerWindows::CreateFileWriter(const TCHAR* Filename,
 
376
                                                   DWORD Flags,
 
377
                                                   NOutputDevice& Error)
 
378
{
 
379
    HANDLE Handle = CreateWriteFileHandle(Filename, Flags);
 
380
    if(Handle == INVALID_HANDLE_VALUE)
 
381
    {
 
382
        return 0;
 
383
    }
 
384
    return new NWindowsSerialFileWriter(Handle, Error);
 
385
}
 
386
 
 
387
/*!
 
388
    @return Size of the File. Return -1 if an error occurs.
 
389
*/
 
390
t_s64 NFileManagerWindows::FileSize(const TCHAR* Filename)
 
391
{
 
392
    HANDLE Handle = ::CreateFile(Filename, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 
393
    if(Handle == INVALID_HANDLE_VALUE)
 
394
    {
 
395
        LPVOID lpMsgBuf = 0;
 
396
        ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
 
397
            NULL,
 
398
            ::GetLastError(),
 
399
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
400
            (LPTSTR) &lpMsgBuf,
 
401
            0,
 
402
            NULL);
 
403
 
 
404
        nuxDebugMsg(TEXT("[NFileManagerWindows::FileSize] Failed to open file %s for attribute read (GetLastError: %d - %s)"), Filename, ::GetLastError(), lpMsgBuf);
 
405
 
 
406
        ::LocalFree(lpMsgBuf);
 
407
        return -1;
 
408
    }
 
409
    t_s64 Size = 0;
 
410
    if(::GetFileSizeEx(Handle, INL_REINTERPRET_CAST(PLARGE_INTEGER, &Size)) == 0)
 
411
    {
 
412
        Size = -1;
 
413
    }
 
414
    CloseHandle(Handle);
 
415
    return Size;
 
416
}
 
417
 
 
418
bool NFileManagerWindows::FileExist(const TCHAR* Filename)
 
419
{
 
420
    WIN32_FILE_ATTRIBUTE_DATA FileAttrData;
 
421
    if(::GetFileAttributesEx(Filename, GetFileExInfoStandard, INL_STATIC_CAST(void*, &FileAttrData)))
 
422
    {
 
423
        return true;
 
424
    }
 
425
    return false;
 
426
}
 
427
 
 
428
int NFileManagerWindows::Copy(const TCHAR* DestFile,
 
429
                                const TCHAR* SrcFile,
 
430
                                bool OverWriteExisting,
 
431
                                bool OverWriteReadOnly,
 
432
                                NFileTransferMonitor* Monitor)
 
433
{
 
434
    // In case file exist and OverWriteReadOnly is true, Remove the ReadOnly attribute from the file.
 
435
    if(OverWriteReadOnly)
 
436
    {
 
437
        ::SetFileAttributes(DestFile, FILE_ATTRIBUTE_NORMAL);
 
438
    }
 
439
    DWORD Flags = (OverWriteExisting ? 0 : COPY_FILE_FAIL_IF_EXISTS);
 
440
    BOOL* pCancel = NULL;
 
441
    if(Monitor)
 
442
        pCancel = &(Monitor->m_bCancel);
 
443
    if(::CopyFileEx(SrcFile, DestFile, NFileTransferMonitor::CopyProgressRoutine, INL_REINTERPRET_CAST(void*, Monitor), pCancel, Flags) == 0)
 
444
    {
 
445
        LPVOID lpMsgBuf = 0;
 
446
        ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
 
447
            NULL,
 
448
            ::GetLastError(),
 
449
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
450
            (LPTSTR)&lpMsgBuf,
 
451
            0,
 
452
            NULL);
 
453
 
 
454
        nuxDebugMsg(TEXT("[NFileManagerWindows::Copy] Error copying file from '%s' to '%s'(GetLastError: %d - %s)"), SrcFile, DestFile, ::GetLastError(), lpMsgBuf);
 
455
        ::LocalFree(lpMsgBuf);
 
456
        return false;
 
457
    }
 
458
    ::SetFileAttributes(DestFile, FILE_ATTRIBUTE_NORMAL);
 
459
    return true;
 
460
}
 
461
 
 
462
bool NFileManagerWindows::Delete(const TCHAR* Filename, bool OverWriteReadOnly)
 
463
{
 
464
    if(OverWriteReadOnly)
 
465
    {
 
466
        ::SetFileAttributes(Filename, FILE_ATTRIBUTE_NORMAL);
 
467
    }
 
468
    if((::DeleteFile(Filename) == 0) && (GetLastError() != ERROR_FILE_NOT_FOUND))
 
469
    {
 
470
        LPVOID lpMsgBuf = 0;
 
471
        ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
 
472
            NULL,
 
473
            ::GetLastError(),
 
474
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
475
            (LPTSTR) &lpMsgBuf,
 
476
            0,
 
477
            NULL);
 
478
 
 
479
        nuxDebugMsg(TEXT("[NFileManagerWindows::Delete] Error deleting file '%s' (GetLastError: %d - %s)"), Filename, ::GetLastError(), lpMsgBuf);
 
480
        ::LocalFree(lpMsgBuf);
 
481
        return false;
 
482
    }
 
483
    return true;
 
484
}
 
485
 
 
486
bool NFileManagerWindows::IsReadOnly(const TCHAR* Filename)
 
487
{
 
488
    WIN32_FILE_ATTRIBUTE_DATA FileAttrData;
 
489
    if(::GetFileAttributesEx(Filename, GetFileExInfoStandard, INL_STATIC_CAST(void*, &FileAttrData)))
 
490
    {
 
491
        return((FileAttrData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
 
492
    }
 
493
    else
 
494
    {
 
495
        nuxDebugMsg(TEXT("[NFileManagerWindows::IsReadOnly]: Error reading attributes for file '%s'"), Filename);
 
496
    }
 
497
    return false;
 
498
}
 
499
 
 
500
bool NFileManagerWindows::IsDirectory(const TCHAR* DirectoryName)
 
501
{
 
502
    WIN32_FILE_ATTRIBUTE_DATA FileAttrData;
 
503
    if(::GetFileAttributesEx(DirectoryName, GetFileExInfoStandard, INL_STATIC_CAST(void*, &FileAttrData)))
 
504
    {
 
505
        return ((FileAttrData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
 
506
    }
 
507
    else
 
508
    {
 
509
        nuxDebugMsg(TEXT("[NFileManagerWindows::IsDirectory]: Error reading attributes for directory '%s'"), DirectoryName);
 
510
    }
 
511
    return false;
 
512
}
 
513
 
 
514
bool NFileManagerWindows::IsHidden(const TCHAR* Filename)
 
515
{
 
516
    WIN32_FILE_ATTRIBUTE_DATA FileAttrData;
 
517
    if(::GetFileAttributesEx(Filename, GetFileExInfoStandard, INL_STATIC_CAST(void*, &FileAttrData)))
 
518
    {
 
519
        return ((FileAttrData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0);
 
520
    }
 
521
    else
 
522
    {
 
523
        nuxDebugMsg(TEXT("[NFileManagerWindows::IsHidden]: Error reading attributes for file '%s'"), Filename);
 
524
    }
 
525
    return false;
 
526
}
 
527
 
 
528
/*!
 
529
    @return TRUE is the file exist.
 
530
*/
 
531
bool NFileManagerWindows::GetFileAttribute(const TCHAR* Filename, bool& isDirectory, bool& isReadOnly, bool& isHidden, t_s64& Size)
 
532
{
 
533
    isDirectory = false;
 
534
    isReadOnly = false;
 
535
    isHidden = false;
 
536
    Size = 0;
 
537
    WIN32_FILE_ATTRIBUTE_DATA FileAttrData;
 
538
    if(::GetFileAttributesEx(Filename, GetFileExInfoStandard, (void*) &FileAttrData))
 
539
    {
 
540
        isDirectory = ((FileAttrData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
 
541
        isReadOnly = ((FileAttrData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
 
542
        isHidden = ((FileAttrData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0);
 
543
        Size = FileAttrData.nFileSizeLow | ((t_s64)(FileAttrData.nFileSizeHigh) << 32);
 
544
    }
 
545
    else
 
546
    {
 
547
        nuxDebugMsg(TEXT("[NFileManagerWindows::GetFileAttribute]: Error reading attributes for file '%s'"), Filename);
 
548
        return (0);
 
549
    }
 
550
    return TRUE;
 
551
}
 
552
 
 
553
bool NFileManagerWindows::Move(const TCHAR* Dest,
 
554
                               const TCHAR* Src,
 
555
                               bool Replace,
 
556
                               bool EvenIfReadOnly,
 
557
                               NFileTransferMonitor* Monitor)
 
558
{
 
559
    DWORD Flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_FAIL_IF_NOT_TRACKABLE;
 
560
    Flags |= (EvenIfReadOnly ? MOVEFILE_REPLACE_EXISTING : 0);
 
561
 
 
562
    BOOL* pCancel = NULL;
 
563
    if(Monitor)
 
564
        pCancel = &(Monitor->m_bCancel);
 
565
    if(::MoveFileWithProgress(Src, Dest, NFileTransferMonitor::CopyProgressRoutine, INL_REINTERPRET_CAST(void*, Monitor), Flags) != 0)
 
566
    {
 
567
        nuxDebugMsg(TEXT("[NFileManagerWindows::Move] Error moving file '%s' to '%s' (GetLastError: %d)"), Src, Dest, ::GetLastError());
 
568
        return false;
 
569
    }
 
570
    return true;
 
571
}
 
572
 
 
573
bool NFileManagerWindows::MakeDirectory(const TCHAR* Path, bool CreateCompletePath)
 
574
{
 
575
    if(CreateCompletePath)
 
576
    {
 
577
        return NFileManagerGeneric::MakeDirectory(Path, CreateCompletePath);
 
578
    }
 
579
    if((::CreateDirectory(Path, NULL) == 0) && (::GetLastError() != ERROR_ALREADY_EXISTS))
 
580
    {
 
581
        nuxDebugMsg(TEXT("[NFileManagerWindows::MakeDirectory] Error creating directory '%s' (GetLastError: %d)"), Path, ::GetLastError());
 
582
        return INL_ERROR;
 
583
    }
 
584
    return INL_OK;
 
585
}
 
586
 
 
587
bool NFileManagerWindows::DeleteDirectory(const TCHAR* Path, bool DeleteContentFirst)
 
588
{
 
589
    if(DeleteContentFirst)
 
590
    {
 
591
        return NFileManagerGeneric::DeleteDirectory(Path, DeleteContentFirst);
 
592
    }
 
593
    if((::RemoveDirectory(Path) == 0) && (::GetLastError() != ERROR_FILE_NOT_FOUND))
 
594
    {
 
595
        nuxDebugMsg(TEXT("[NFileManagerWindows::DeleteDirectory] Error deleting directory '%s' (GetLastError: %d)"), Path, ::GetLastError());
 
596
        return false;
 
597
    }
 
598
    return true;
 
599
}
 
600
 
 
601
void NFileManagerWindows::FindFiles(std::vector<NString>& Result, const TCHAR* Filename, bool Files, bool Directories)
 
602
{
 
603
    HANDLE Handle=INVALID_HANDLE_VALUE;
 
604
    WIN32_FIND_DATA SearchData;
 
605
    Handle = ::FindFirstFile(Filename, &SearchData);
 
606
    if(Handle != INVALID_HANDLE_VALUE)
 
607
    {
 
608
        do
 
609
        {
 
610
            if(Stricmp(SearchData.cFileName, TEXT(".")) &&
 
611
                Stricmp(SearchData.cFileName, TEXT("..")) &&
 
612
                !(SearchData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) &&
 
613
                !(SearchData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
 
614
 
 
615
            {
 
616
                if((SearchData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? Directories : Files)
 
617
                    Result.push_back(NString(SearchData.cFileName));
 
618
            }
 
619
        } while(::FindNextFile(Handle, &SearchData));
 
620
    }
 
621
    if(Handle != INVALID_HANDLE_VALUE)
 
622
        ::FindClose(Handle);
 
623
}
 
624
 
 
625
void NFileManagerWindows::ListFilesInDirectory(std::vector<NString>& Result, const TCHAR* DirName)
 
626
{
 
627
    WIN32_FIND_DATA SearchData;
 
628
    HANDLE Handle = INVALID_HANDLE_VALUE;
 
629
    NString DirectoryName = DirName;
 
630
    DirectoryName += TEXT("\\*");
 
631
    Handle = ::FindFirstFile(DirectoryName.GetTCharPtr(), &SearchData);
 
632
    if (Handle != INVALID_HANDLE_VALUE) 
 
633
    {
 
634
        // List all the other files in the directory.
 
635
        do
 
636
        {
 
637
            if(Stricmp(SearchData.cFileName,TEXT(".")) &&
 
638
                Stricmp(SearchData.cFileName,TEXT("..")) &&
 
639
                !(SearchData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) &&
 
640
                !(SearchData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
 
641
            {
 
642
                Result.push_back(NString(SearchData.cFileName));
 
643
            }
 
644
        } while(::FindNextFile(Handle, &SearchData));
 
645
    }
 
646
    if(Handle != INVALID_HANDLE_VALUE)
 
647
        ::FindClose(Handle);
 
648
}
 
649
 
 
650
double NFileManagerWindows::GetFileAgeSeconds(const TCHAR* Filename)
 
651
{
 
652
    struct _stat FileInfo;
 
653
    if(_tstat(Filename, &FileInfo) == 0)
 
654
    {
 
655
        time_t  CurrentTime,
 
656
            FileTime;   
 
657
        FileTime = FileInfo.st_mtime;
 
658
        time(&CurrentTime);
 
659
 
 
660
        return difftime(CurrentTime, FileTime);
 
661
    }
 
662
    return -1.0;
 
663
}
 
664
 
 
665
time_t NFileManagerWindows::GetFileLastModified(const TCHAR* Filename)
 
666
{
 
667
    struct _stat FileInfo;
 
668
    if(_tstat(Filename, &FileInfo) == 0)
 
669
    {
 
670
        time_t FileTime;        
 
671
        FileTime = FileInfo.st_mtime;
 
672
 
 
673
        return FileTime;
 
674
    }
 
675
    return -1;
 
676
}
 
677
 
 
678
// bool GetFileLastModified(const TCHAR* Filename, SYSTEMTIME& sysTime, bool bLocalTime)
 
679
// {
 
680
//     ZeroMemory(&sysTime, sizeof(SYSTEMTIME));
 
681
// 
 
682
//     DWORD dwAttr = ::GetFileAttributes(Filename);
 
683
// 
 
684
//     // files only
 
685
//     if (dwAttr == 0xFFFFFFFF)
 
686
//         return false;
 
687
// 
 
688
//     WIN32_FIND_DATA findFileData;
 
689
//     HANDLE hFind = ::FindFirstFile((LPTSTR)Filename, &findFileData);
 
690
// 
 
691
//     if (hFind == INVALID_HANDLE_VALUE)
 
692
//         return FALSE;
 
693
// 
 
694
//     ::FindClose(hFind);
 
695
// 
 
696
//     FILETIME ft = findFileData.ftLastWriteTime;
 
697
// 
 
698
//     if (bLocalTime)
 
699
//         ::FileTimeToLocalFileTime(&findFileData.ftLastWriteTime, &ft);
 
700
// 
 
701
//     ::FileTimeToSystemTime(&ft, &sysTime);
 
702
//     return true;
 
703
// }
 
704
 
 
705
bool NFileManagerWindows::SetDefaultDirectory()
 
706
{
 
707
    return CALL_OS_TCHAR_FUNCTION(SetCurrentDirectoryW(GetProgramDirectory()),SetCurrentDirectoryA(TCHAR_TO_ANSI(GetProgramDirectory().GetTCharPtr())))!=0;
 
708
}
 
709
 
 
710
NString NFileManagerWindows::GetCurrentDirectory()
 
711
{
 
712
#if UNICODE
 
713
    TCHAR Buffer[1024]=TEXT("");
 
714
    ::GetCurrentDirectoryW(INL_ARRAY_COUNT(Buffer),Buffer);
 
715
    return NString(Buffer);
 
716
#else
 
717
    ANSICHAR Buffer[1024]="";
 
718
    ::GetCurrentDirectoryA(INL_ARRAY_COUNT(Buffer),Buffer);
 
719
    return NString(Buffer);
 
720
#endif
 
721
}
 
722
 
 
723
bool NFileManagerWindows::GetTimeStamp(const TCHAR* Filename, FileTimeStamp& Timestamp)
 
724
{
 
725
    Memzero(&Timestamp, sizeof(Timestamp));
 
726
    struct _stat FileInfo;
 
727
    if(_tstat(Filename, &FileInfo) == 0)
 
728
    {
 
729
#ifdef WIN32_SECURE
 
730
        __time64_t FileTime;
 
731
        // FileTime represents seconds elapsed since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC).
 
732
        FileTime = FileInfo.st_mtime;
 
733
        tm pTime;
 
734
        // _gmtime64_s can express time up to 23:59:59, December 31, 3000, UTC
 
735
        _gmtime64_s(&pTime, &FileTime);
 
736
 
 
737
        Timestamp.Day       = pTime.tm_mday;
 
738
        Timestamp.DayOfWeek = pTime.tm_wday;
 
739
        Timestamp.DayOfYear = pTime.tm_yday;
 
740
        Timestamp.Hour      = pTime.tm_hour;
 
741
        Timestamp.Minute    = pTime.tm_min;
 
742
        Timestamp.Second    = pTime.tm_sec;
 
743
        Timestamp.Year      = pTime.tm_year + 1900;
 
744
#else
 
745
        time_t  FileTime;       
 
746
        // FileTime represents seconds elapsed since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC).
 
747
        FileTime = FileInfo.st_mtime;
 
748
        // gmtime can express time up to 03:14:07 January 19, 2038, UTC
 
749
        tm* pTime = gmtime(&FileTime);
 
750
 
 
751
        Timestamp.Day       = pTime->tm_mday;
 
752
        Timestamp.DayOfWeek = pTime->tm_wday;
 
753
        Timestamp.DayOfYear = pTime->tm_yday;
 
754
        Timestamp.Hour      = pTime->tm_hour;
 
755
        Timestamp.Minute    = pTime->tm_min;
 
756
        Timestamp.Second    = pTime->tm_sec;
 
757
        Timestamp.Year      = pTime->tm_year + 1900;
 
758
#endif
 
759
        return TRUE;
 
760
    }
 
761
    return FALSE;
 
762
}
 
763
 
 
764
NAMESPACE_END
 
765