misc/libphysfs/lzma/CPP/Windows/FileFind.cpp
changeset 13904 99b265e0d1d0
parent 13903 5f819b90d479
child 13905 b172a5d40eee
equal deleted inserted replaced
13903:5f819b90d479 13904:99b265e0d1d0
     1 // Windows/FileFind.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 
       
     5 #include "FileFind.h"
       
     6 #ifndef _UNICODE
       
     7 #include "../Common/StringConvert.h"
       
     8 #endif
       
     9 
       
    10 #ifndef _UNICODE
       
    11 extern bool g_IsNT;
       
    12 #endif
       
    13 
       
    14 namespace NWindows {
       
    15 namespace NFile {
       
    16 
       
    17 #if defined(WIN_LONG_PATH) && defined(_UNICODE)
       
    18 #define WIN_LONG_PATH2
       
    19 #endif
       
    20 
       
    21 bool GetLongPath(LPCWSTR fileName, UString &res);
       
    22 
       
    23 namespace NFind {
       
    24 
       
    25 static const TCHAR kDot = TEXT('.');
       
    26 
       
    27 bool CFileInfo::IsDots() const
       
    28 { 
       
    29   if (!IsDirectory() || Name.IsEmpty())
       
    30     return false;
       
    31   if (Name[0] != kDot)
       
    32     return false;
       
    33   return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
       
    34 }
       
    35 
       
    36 #ifndef _UNICODE
       
    37 bool CFileInfoW::IsDots() const
       
    38 { 
       
    39   if (!IsDirectory() || Name.IsEmpty())
       
    40     return false;
       
    41   if (Name[0] != kDot)
       
    42     return false;
       
    43   return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
       
    44 }
       
    45 #endif
       
    46 
       
    47 static void ConvertWIN32_FIND_DATA_To_FileInfo(
       
    48     const WIN32_FIND_DATA &findData,
       
    49     CFileInfo &fileInfo)
       
    50 {
       
    51   fileInfo.Attributes = findData.dwFileAttributes; 
       
    52   fileInfo.CreationTime = findData.ftCreationTime;  
       
    53   fileInfo.LastAccessTime = findData.ftLastAccessTime; 
       
    54   fileInfo.LastWriteTime = findData.ftLastWriteTime;
       
    55   fileInfo.Size  = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; 
       
    56   fileInfo.Name = findData.cFileName;
       
    57   #ifndef _WIN32_WCE
       
    58   fileInfo.ReparseTag = findData.dwReserved0;
       
    59   #else
       
    60   fileInfo.ObjectID = findData.dwOID;
       
    61   #endif
       
    62 }
       
    63 
       
    64 #ifndef _UNICODE
       
    65 
       
    66 static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } 
       
    67 
       
    68 static void ConvertWIN32_FIND_DATA_To_FileInfo(
       
    69     const WIN32_FIND_DATAW &findData,
       
    70     CFileInfoW &fileInfo)
       
    71 {
       
    72   fileInfo.Attributes = findData.dwFileAttributes; 
       
    73   fileInfo.CreationTime = findData.ftCreationTime;  
       
    74   fileInfo.LastAccessTime = findData.ftLastAccessTime; 
       
    75   fileInfo.LastWriteTime = findData.ftLastWriteTime;
       
    76   fileInfo.Size  = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; 
       
    77   fileInfo.Name = findData.cFileName;
       
    78   #ifndef _WIN32_WCE
       
    79   fileInfo.ReparseTag = findData.dwReserved0;
       
    80   #else
       
    81   fileInfo.ObjectID = findData.dwOID;
       
    82   #endif
       
    83 }
       
    84 
       
    85 static void ConvertWIN32_FIND_DATA_To_FileInfo(
       
    86     const WIN32_FIND_DATA &findData,
       
    87     CFileInfoW &fileInfo)
       
    88 {
       
    89   fileInfo.Attributes = findData.dwFileAttributes; 
       
    90   fileInfo.CreationTime = findData.ftCreationTime;  
       
    91   fileInfo.LastAccessTime = findData.ftLastAccessTime; 
       
    92   fileInfo.LastWriteTime = findData.ftLastWriteTime;
       
    93   fileInfo.Size  = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; 
       
    94   fileInfo.Name = GetUnicodeString(findData.cFileName, GetCurrentCodePage());
       
    95   #ifndef _WIN32_WCE
       
    96   fileInfo.ReparseTag = findData.dwReserved0;
       
    97   #else
       
    98   fileInfo.ObjectID = findData.dwOID;
       
    99   #endif
       
   100 }
       
   101 #endif
       
   102   
       
   103 ////////////////////////////////
       
   104 // CFindFile
       
   105 
       
   106 bool CFindFile::Close()
       
   107 {
       
   108   if (_handle == INVALID_HANDLE_VALUE)
       
   109     return true;
       
   110   if (!::FindClose(_handle))
       
   111     return false;
       
   112   _handle = INVALID_HANDLE_VALUE;
       
   113   return true;
       
   114 }
       
   115 
       
   116           
       
   117 bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo)
       
   118 {
       
   119   if (!Close())
       
   120     return false;
       
   121   WIN32_FIND_DATA findData;
       
   122   _handle = ::FindFirstFile(wildcard, &findData);
       
   123   #ifdef WIN_LONG_PATH2
       
   124   if (_handle == INVALID_HANDLE_VALUE)
       
   125   {
       
   126     UString longPath;
       
   127     if (GetLongPath(wildcard, longPath))
       
   128       _handle = ::FindFirstFileW(longPath, &findData);
       
   129   }
       
   130   #endif
       
   131   if (_handle == INVALID_HANDLE_VALUE)
       
   132     return false;
       
   133   ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
       
   134   return true;
       
   135 }
       
   136 
       
   137 #ifndef _UNICODE
       
   138 bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo)
       
   139 {
       
   140   if (!Close())
       
   141     return false;
       
   142   if (g_IsNT)
       
   143   {
       
   144     WIN32_FIND_DATAW findData;
       
   145     _handle = ::FindFirstFileW(wildcard, &findData);
       
   146     #ifdef WIN_LONG_PATH
       
   147     if (_handle == INVALID_HANDLE_VALUE)
       
   148     {
       
   149       UString longPath;
       
   150       if (GetLongPath(wildcard, longPath))
       
   151         _handle = ::FindFirstFileW(longPath, &findData);
       
   152     }
       
   153     #endif
       
   154     if (_handle != INVALID_HANDLE_VALUE)
       
   155       ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
       
   156   }
       
   157   else
       
   158   {
       
   159     WIN32_FIND_DATAA findData;
       
   160     _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, 
       
   161         GetCurrentCodePage()), &findData);
       
   162     if (_handle != INVALID_HANDLE_VALUE)
       
   163       ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
       
   164   }
       
   165   return (_handle != INVALID_HANDLE_VALUE);
       
   166 }
       
   167 #endif
       
   168 
       
   169 bool CFindFile::FindNext(CFileInfo &fileInfo)
       
   170 {
       
   171   WIN32_FIND_DATA findData;
       
   172   bool result = BOOLToBool(::FindNextFile(_handle, &findData));
       
   173   if (result)
       
   174     ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
       
   175   return result;
       
   176 }
       
   177 
       
   178 #ifndef _UNICODE
       
   179 bool CFindFile::FindNext(CFileInfoW &fileInfo)
       
   180 {
       
   181   if (g_IsNT)
       
   182   {
       
   183     WIN32_FIND_DATAW findData;
       
   184     if (!::FindNextFileW(_handle, &findData))
       
   185       return false;
       
   186     ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
       
   187   }
       
   188   else
       
   189   {
       
   190     WIN32_FIND_DATAA findData;
       
   191     if (!::FindNextFileA(_handle, &findData))
       
   192       return false;
       
   193     ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
       
   194   }
       
   195   return true;
       
   196 }
       
   197 #endif
       
   198 
       
   199 bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo)
       
   200 {
       
   201   CFindFile finder;
       
   202   return finder.FindFirst(wildcard, fileInfo);
       
   203 }
       
   204 
       
   205 #ifndef _UNICODE
       
   206 bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo)
       
   207 {
       
   208   CFindFile finder;
       
   209   return finder.FindFirst(wildcard, fileInfo);
       
   210 }
       
   211 #endif
       
   212 
       
   213 bool DoesFileExist(LPCTSTR name)
       
   214 {
       
   215   CFileInfo fileInfo;
       
   216   return FindFile(name, fileInfo);
       
   217 }
       
   218 
       
   219 #ifndef _UNICODE
       
   220 bool DoesFileExist(LPCWSTR name)
       
   221 {
       
   222   CFileInfoW fileInfo;
       
   223   return FindFile(name, fileInfo);
       
   224 }
       
   225 #endif
       
   226 
       
   227 /////////////////////////////////////
       
   228 // CEnumerator
       
   229 
       
   230 bool CEnumerator::NextAny(CFileInfo &fileInfo)
       
   231 {
       
   232   if (_findFile.IsHandleAllocated())
       
   233     return _findFile.FindNext(fileInfo);
       
   234   else
       
   235     return _findFile.FindFirst(_wildcard, fileInfo);
       
   236 }
       
   237 
       
   238 bool CEnumerator::Next(CFileInfo &fileInfo)
       
   239 {
       
   240   for (;;)
       
   241   {
       
   242     if (!NextAny(fileInfo))
       
   243       return false;
       
   244     if (!fileInfo.IsDots())
       
   245       return true;
       
   246   }
       
   247 }
       
   248 
       
   249 bool CEnumerator::Next(CFileInfo &fileInfo, bool &found)
       
   250 {
       
   251   if (Next(fileInfo))
       
   252   {
       
   253     found = true;
       
   254     return true;
       
   255   }
       
   256   found = false;
       
   257   return (::GetLastError() == ERROR_NO_MORE_FILES);
       
   258 }
       
   259 
       
   260 #ifndef _UNICODE
       
   261 bool CEnumeratorW::NextAny(CFileInfoW &fileInfo)
       
   262 {
       
   263   if (_findFile.IsHandleAllocated())
       
   264     return _findFile.FindNext(fileInfo);
       
   265   else
       
   266     return _findFile.FindFirst(_wildcard, fileInfo);
       
   267 }
       
   268 
       
   269 bool CEnumeratorW::Next(CFileInfoW &fileInfo)
       
   270 {
       
   271   for (;;)
       
   272   {
       
   273     if (!NextAny(fileInfo))
       
   274       return false;
       
   275     if (!fileInfo.IsDots())
       
   276       return true;
       
   277   }
       
   278 }
       
   279 
       
   280 bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found)
       
   281 {
       
   282   if (Next(fileInfo))
       
   283   {
       
   284     found = true;
       
   285     return true;
       
   286   }
       
   287   found = false;
       
   288   return (::GetLastError() == ERROR_NO_MORE_FILES);
       
   289 }
       
   290 
       
   291 #endif
       
   292 
       
   293 ////////////////////////////////
       
   294 // CFindChangeNotification
       
   295 // FindFirstChangeNotification can return 0. MSDN doesn't tell about it.
       
   296 
       
   297 bool CFindChangeNotification::Close()
       
   298 {
       
   299   if (!IsHandleAllocated())
       
   300     return true;
       
   301   if (!::FindCloseChangeNotification(_handle))
       
   302     return false;
       
   303   _handle = INVALID_HANDLE_VALUE;
       
   304   return true;
       
   305 }
       
   306            
       
   307 HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter)
       
   308 {
       
   309   _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter);
       
   310   #ifdef WIN_LONG_PATH2
       
   311   if (!IsHandleAllocated())
       
   312   {
       
   313     UString longPath;
       
   314     if (GetLongPath(pathName, longPath))
       
   315       _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
       
   316   }
       
   317   #endif
       
   318   return _handle;
       
   319 }
       
   320 
       
   321 #ifndef _UNICODE
       
   322 HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter)
       
   323 {
       
   324   if (!g_IsNT)
       
   325     return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);
       
   326   _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter);
       
   327   #ifdef WIN_LONG_PATH
       
   328   if (!IsHandleAllocated())
       
   329   {
       
   330     UString longPath;
       
   331     if (GetLongPath(pathName, longPath))
       
   332       _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
       
   333   }
       
   334   #endif
       
   335   return _handle;
       
   336 }
       
   337 #endif
       
   338 
       
   339 #ifndef _WIN32_WCE
       
   340 bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)
       
   341 {
       
   342   driveStrings.Clear();
       
   343   UINT32 size = GetLogicalDriveStrings(0, NULL); 
       
   344   if (size == 0)
       
   345     return false;
       
   346   CSysString buffer;
       
   347   UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); 
       
   348   if (newSize == 0)
       
   349     return false;
       
   350   if (newSize > size)
       
   351     return false;
       
   352   CSysString string;
       
   353   for(UINT32 i = 0; i < newSize; i++)
       
   354   {
       
   355     TCHAR c = buffer[i];
       
   356     if (c == TEXT('\0'))
       
   357     {
       
   358       driveStrings.Add(string);
       
   359       string.Empty();
       
   360     }
       
   361     else
       
   362       string += c;
       
   363   }
       
   364   if (!string.IsEmpty())
       
   365     return false;
       
   366   return true;
       
   367 }
       
   368 
       
   369 #ifndef _UNICODE
       
   370 bool MyGetLogicalDriveStrings(UStringVector &driveStrings)
       
   371 {
       
   372   driveStrings.Clear();
       
   373   if (g_IsNT)
       
   374   {
       
   375     UINT32 size = GetLogicalDriveStringsW(0, NULL); 
       
   376     if (size == 0)
       
   377       return false;
       
   378     UString buffer;
       
   379     UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); 
       
   380     if (newSize == 0)
       
   381       return false;
       
   382     if (newSize > size)
       
   383       return false;
       
   384     UString string;
       
   385     for(UINT32 i = 0; i < newSize; i++)
       
   386     {
       
   387       WCHAR c = buffer[i];
       
   388       if (c == L'\0')
       
   389       {
       
   390         driveStrings.Add(string);
       
   391         string.Empty();
       
   392       }
       
   393       else
       
   394         string += c;
       
   395     }
       
   396     return string.IsEmpty();
       
   397   }
       
   398   CSysStringVector driveStringsA;
       
   399   bool res = MyGetLogicalDriveStrings(driveStringsA);
       
   400   for (int i = 0; i < driveStringsA.Size(); i++)
       
   401     driveStrings.Add(GetUnicodeString(driveStringsA[i]));
       
   402   return res;
       
   403 }
       
   404 #endif
       
   405 
       
   406 #endif
       
   407 
       
   408 }}}