1 // Windows/FileFind.cpp
7 #include "../Common/StringConvert.h"
17 #if defined(WIN_LONG_PATH) && defined(_UNICODE)
18 #define WIN_LONG_PATH2
21 bool GetLongPath(LPCWSTR fileName, UString &res);
25 static const TCHAR kDot = TEXT('.');
27 bool CFileInfo::IsDots() const
29 if (!IsDirectory() || Name.IsEmpty())
33 return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
37 bool CFileInfoW::IsDots() const
39 if (!IsDirectory() || Name.IsEmpty())
43 return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
47 static void ConvertWIN32_FIND_DATA_To_FileInfo(
48 const WIN32_FIND_DATA &findData,
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;
58 fileInfo.ReparseTag = findData.dwReserved0;
60 fileInfo.ObjectID = findData.dwOID;
66 static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
68 static void ConvertWIN32_FIND_DATA_To_FileInfo(
69 const WIN32_FIND_DATAW &findData,
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;
79 fileInfo.ReparseTag = findData.dwReserved0;
81 fileInfo.ObjectID = findData.dwOID;
85 static void ConvertWIN32_FIND_DATA_To_FileInfo(
86 const WIN32_FIND_DATA &findData,
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());
96 fileInfo.ReparseTag = findData.dwReserved0;
98 fileInfo.ObjectID = findData.dwOID;
103 ////////////////////////////////
106 bool CFindFile::Close()
108 if (_handle == INVALID_HANDLE_VALUE)
110 if (!::FindClose(_handle))
112 _handle = INVALID_HANDLE_VALUE;
117 bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo)
121 WIN32_FIND_DATA findData;
122 _handle = ::FindFirstFile(wildcard, &findData);
123 #ifdef WIN_LONG_PATH2
124 if (_handle == INVALID_HANDLE_VALUE)
127 if (GetLongPath(wildcard, longPath))
128 _handle = ::FindFirstFileW(longPath, &findData);
131 if (_handle == INVALID_HANDLE_VALUE)
133 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
138 bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo)
144 WIN32_FIND_DATAW findData;
145 _handle = ::FindFirstFileW(wildcard, &findData);
147 if (_handle == INVALID_HANDLE_VALUE)
150 if (GetLongPath(wildcard, longPath))
151 _handle = ::FindFirstFileW(longPath, &findData);
154 if (_handle != INVALID_HANDLE_VALUE)
155 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
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);
165 return (_handle != INVALID_HANDLE_VALUE);
169 bool CFindFile::FindNext(CFileInfo &fileInfo)
171 WIN32_FIND_DATA findData;
172 bool result = BOOLToBool(::FindNextFile(_handle, &findData));
174 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
179 bool CFindFile::FindNext(CFileInfoW &fileInfo)
183 WIN32_FIND_DATAW findData;
184 if (!::FindNextFileW(_handle, &findData))
186 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
190 WIN32_FIND_DATAA findData;
191 if (!::FindNextFileA(_handle, &findData))
193 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
199 bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo)
202 return finder.FindFirst(wildcard, fileInfo);
206 bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo)
209 return finder.FindFirst(wildcard, fileInfo);
213 bool DoesFileExist(LPCTSTR name)
216 return FindFile(name, fileInfo);
220 bool DoesFileExist(LPCWSTR name)
223 return FindFile(name, fileInfo);
227 /////////////////////////////////////
230 bool CEnumerator::NextAny(CFileInfo &fileInfo)
232 if (_findFile.IsHandleAllocated())
233 return _findFile.FindNext(fileInfo);
235 return _findFile.FindFirst(_wildcard, fileInfo);
238 bool CEnumerator::Next(CFileInfo &fileInfo)
242 if (!NextAny(fileInfo))
244 if (!fileInfo.IsDots())
249 bool CEnumerator::Next(CFileInfo &fileInfo, bool &found)
257 return (::GetLastError() == ERROR_NO_MORE_FILES);
261 bool CEnumeratorW::NextAny(CFileInfoW &fileInfo)
263 if (_findFile.IsHandleAllocated())
264 return _findFile.FindNext(fileInfo);
266 return _findFile.FindFirst(_wildcard, fileInfo);
269 bool CEnumeratorW::Next(CFileInfoW &fileInfo)
273 if (!NextAny(fileInfo))
275 if (!fileInfo.IsDots())
280 bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found)
288 return (::GetLastError() == ERROR_NO_MORE_FILES);
293 ////////////////////////////////
294 // CFindChangeNotification
295 // FindFirstChangeNotification can return 0. MSDN doesn't tell about it.
297 bool CFindChangeNotification::Close()
299 if (!IsHandleAllocated())
301 if (!::FindCloseChangeNotification(_handle))
303 _handle = INVALID_HANDLE_VALUE;
307 HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter)
309 _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter);
310 #ifdef WIN_LONG_PATH2
311 if (!IsHandleAllocated())
314 if (GetLongPath(pathName, longPath))
315 _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
322 HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter)
325 return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);
326 _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter);
328 if (!IsHandleAllocated())
331 if (GetLongPath(pathName, longPath))
332 _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
340 bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)
342 driveStrings.Clear();
343 UINT32 size = GetLogicalDriveStrings(0, NULL);
347 UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size));
353 for(UINT32 i = 0; i < newSize; i++)
358 driveStrings.Add(string);
364 if (!string.IsEmpty())
370 bool MyGetLogicalDriveStrings(UStringVector &driveStrings)
372 driveStrings.Clear();
375 UINT32 size = GetLogicalDriveStringsW(0, NULL);
379 UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size));
385 for(UINT32 i = 0; i < newSize; i++)
390 driveStrings.Add(string);
396 return string.IsEmpty();
398 CSysStringVector driveStringsA;
399 bool res = MyGetLogicalDriveStrings(driveStringsA);
400 for (int i = 0; i < driveStringsA.Size(); i++)
401 driveStrings.Add(GetUnicodeString(driveStringsA[i]));