Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
1 // Windows/FileFind.cpp
3 #include "StdAfx.h"
5 #include "FileFind.h"
6 #ifndef _UNICODE
7 #include "../Common/StringConvert.h"
8 #endif
10 #ifndef _UNICODE
11 extern bool g_IsNT;
12 #endif
14 namespace NWindows {
15 namespace NFile {
16 namespace NFind {
18 static const TCHAR kDot = TEXT('.');
20 bool CFileInfo::IsDots() const
21 {
22 if (!IsDirectory() || Name.IsEmpty())
23 return false;
24 if (Name[0] != kDot)
25 return false;
26 return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
27 }
29 #ifndef _UNICODE
30 bool CFileInfoW::IsDots() const
31 {
32 if (!IsDirectory() || Name.IsEmpty())
33 return false;
34 if (Name[0] != kDot)
35 return false;
36 return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
37 }
38 #endif
40 static void ConvertWIN32_FIND_DATA_To_FileInfo(
41 const WIN32_FIND_DATA &findData,
42 CFileInfo &fileInfo)
43 {
44 fileInfo.Attributes = findData.dwFileAttributes;
45 fileInfo.CreationTime = findData.ftCreationTime;
46 fileInfo.LastAccessTime = findData.ftLastAccessTime;
47 fileInfo.LastWriteTime = findData.ftLastWriteTime;
48 fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow;
49 fileInfo.Name = findData.cFileName;
50 #ifndef _WIN32_WCE
51 fileInfo.ReparseTag = findData.dwReserved0;
52 #else
53 fileInfo.ObjectID = findData.dwOID;
54 #endif
55 }
57 #ifndef _UNICODE
59 static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
61 static void ConvertWIN32_FIND_DATA_To_FileInfo(
62 const WIN32_FIND_DATAW &findData,
63 CFileInfoW &fileInfo)
64 {
65 fileInfo.Attributes = findData.dwFileAttributes;
66 fileInfo.CreationTime = findData.ftCreationTime;
67 fileInfo.LastAccessTime = findData.ftLastAccessTime;
68 fileInfo.LastWriteTime = findData.ftLastWriteTime;
69 fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow;
70 fileInfo.Name = findData.cFileName;
71 #ifndef _WIN32_WCE
72 fileInfo.ReparseTag = findData.dwReserved0;
73 #else
74 fileInfo.ObjectID = findData.dwOID;
75 #endif
76 }
78 static void ConvertWIN32_FIND_DATA_To_FileInfo(
79 const WIN32_FIND_DATA &findData,
80 CFileInfoW &fileInfo)
81 {
82 fileInfo.Attributes = findData.dwFileAttributes;
83 fileInfo.CreationTime = findData.ftCreationTime;
84 fileInfo.LastAccessTime = findData.ftLastAccessTime;
85 fileInfo.LastWriteTime = findData.ftLastWriteTime;
86 fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow;
87 fileInfo.Name = GetUnicodeString(findData.cFileName, GetCurrentCodePage());
88 #ifndef _WIN32_WCE
89 fileInfo.ReparseTag = findData.dwReserved0;
90 #else
91 fileInfo.ObjectID = findData.dwOID;
92 #endif
93 }
94 #endif
96 ////////////////////////////////
97 // CFindFile
99 bool CFindFile::Close()
100 {
101 if(!_handleAllocated)
102 return true;
103 bool result = BOOLToBool(::FindClose(_handle));
104 _handleAllocated = !result;
105 return result;
106 }
108 bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo)
109 {
110 Close();
111 WIN32_FIND_DATA findData;
112 _handle = ::FindFirstFile(wildcard, &findData);
113 if (_handleAllocated = (_handle != INVALID_HANDLE_VALUE))
114 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
115 return _handleAllocated;
116 }
118 #ifndef _UNICODE
119 bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo)
120 {
121 Close();
122 if (g_IsNT)
123 {
124 WIN32_FIND_DATAW findData;
125 _handle = ::FindFirstFileW(wildcard, &findData);
126 if (_handleAllocated = (_handle != INVALID_HANDLE_VALUE))
127 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
128 }
129 else
130 {
131 WIN32_FIND_DATAA findData;
132 _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard,
133 GetCurrentCodePage()), &findData);
134 if (_handleAllocated = (_handle != INVALID_HANDLE_VALUE))
135 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
136 }
137 return _handleAllocated;
138 }
139 #endif
141 bool CFindFile::FindNext(CFileInfo &fileInfo)
142 {
143 WIN32_FIND_DATA findData;
144 bool result = BOOLToBool(::FindNextFile(_handle, &findData));
145 if (result)
146 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
147 return result;
148 }
150 #ifndef _UNICODE
151 bool CFindFile::FindNext(CFileInfoW &fileInfo)
152 {
153 if (g_IsNT)
154 {
155 WIN32_FIND_DATAW findData;
156 if (!::FindNextFileW(_handle, &findData))
157 return false;
158 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
159 }
160 else
161 {
162 WIN32_FIND_DATAA findData;
163 if (!::FindNextFileA(_handle, &findData))
164 return false;
165 ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
166 }
167 return true;
168 }
169 #endif
171 bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo)
172 {
173 CFindFile finder;
174 return finder.FindFirst(wildcard, fileInfo);
175 }
177 #ifndef _UNICODE
178 bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo)
179 {
180 CFindFile finder;
181 return finder.FindFirst(wildcard, fileInfo);
182 }
183 #endif
185 bool DoesFileExist(LPCTSTR name)
186 {
187 CFileInfo fileInfo;
188 return FindFile(name, fileInfo);
189 }
191 #ifndef _UNICODE
192 bool DoesFileExist(LPCWSTR name)
193 {
194 CFileInfoW fileInfo;
195 return FindFile(name, fileInfo);
196 }
197 #endif
199 /////////////////////////////////////
200 // CEnumerator
202 bool CEnumerator::NextAny(CFileInfo &fileInfo)
203 {
204 if(_findFile.IsHandleAllocated())
205 return _findFile.FindNext(fileInfo);
206 else
207 return _findFile.FindFirst(_wildcard, fileInfo);
208 }
210 bool CEnumerator::Next(CFileInfo &fileInfo)
211 {
212 while(true)
213 {
214 if(!NextAny(fileInfo))
215 return false;
216 if(!fileInfo.IsDots())
217 return true;
218 }
219 }
221 bool CEnumerator::Next(CFileInfo &fileInfo, bool &found)
222 {
223 if (Next(fileInfo))
224 {
225 found = true;
226 return true;
227 }
228 found = false;
229 return (::GetLastError() == ERROR_NO_MORE_FILES);
230 }
232 #ifndef _UNICODE
233 bool CEnumeratorW::NextAny(CFileInfoW &fileInfo)
234 {
235 if(_findFile.IsHandleAllocated())
236 return _findFile.FindNext(fileInfo);
237 else
238 return _findFile.FindFirst(_wildcard, fileInfo);
239 }
241 bool CEnumeratorW::Next(CFileInfoW &fileInfo)
242 {
243 while(true)
244 {
245 if(!NextAny(fileInfo))
246 return false;
247 if(!fileInfo.IsDots())
248 return true;
249 }
250 }
252 bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found)
253 {
254 if (Next(fileInfo))
255 {
256 found = true;
257 return true;
258 }
259 found = false;
260 return (::GetLastError() == ERROR_NO_MORE_FILES);
261 }
263 #endif
265 ////////////////////////////////
266 // CFindChangeNotification
268 bool CFindChangeNotification::Close()
269 {
270 if(_handle == INVALID_HANDLE_VALUE || _handle == 0)
271 return true;
272 bool result = BOOLToBool(::FindCloseChangeNotification(_handle));
273 if (result)
274 _handle = INVALID_HANDLE_VALUE;
275 return result;
276 }
278 HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree,
279 DWORD notifyFilter)
280 {
281 _handle = ::FindFirstChangeNotification(pathName,
282 BoolToBOOL(watchSubtree), notifyFilter);
283 return _handle;
284 }
286 #ifndef _UNICODE
287 HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree,
288 DWORD notifyFilter)
289 {
290 if (g_IsNT)
291 return (_handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter));
292 return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);
293 }
294 #endif
296 #ifndef _WIN32_WCE
297 bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)
298 {
299 driveStrings.Clear();
300 UINT32 size = GetLogicalDriveStrings(0, NULL);
301 if(size == 0)
302 return false;
303 CSysString buffer;
304 UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size));
305 if(newSize == 0)
306 return false;
307 if(newSize > size)
308 return false;
309 CSysString string;
310 for(UINT32 i = 0; i < newSize; i++)
311 {
312 TCHAR c = buffer[i];
313 if(c == TEXT('\0'))
314 {
315 driveStrings.Add(string);
316 string.Empty();
317 }
318 else
319 string += c;
320 }
321 if(!string.IsEmpty())
322 return false;
323 return true;
324 }
326 #ifndef _UNICODE
327 bool MyGetLogicalDriveStrings(UStringVector &driveStrings)
328 {
329 driveStrings.Clear();
330 if (g_IsNT)
331 {
332 UINT32 size = GetLogicalDriveStringsW(0, NULL);
333 if (size == 0)
334 return false;
335 UString buffer;
336 UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size));
337 if(newSize == 0)
338 return false;
339 if(newSize > size)
340 return false;
341 UString string;
342 for(UINT32 i = 0; i < newSize; i++)
343 {
344 WCHAR c = buffer[i];
345 if(c == L'\0')
346 {
347 driveStrings.Add(string);
348 string.Empty();
349 }
350 else
351 string += c;
352 }
353 return string.IsEmpty();
354 }
355 CSysStringVector driveStringsA;
356 bool res = MyGetLogicalDriveStrings(driveStringsA);
357 for (int i = 0; i < driveStringsA.Size(); i++)
358 driveStrings.Add(GetUnicodeString(driveStringsA[i]));
359 return res;
360 }
361 #endif
363 #endif
365 }}}