|
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 namespace NFind { |
|
17 |
|
18 static const TCHAR kDot = TEXT('.'); |
|
19 |
|
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 } |
|
28 |
|
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 |
|
39 |
|
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 } |
|
56 |
|
57 #ifndef _UNICODE |
|
58 |
|
59 static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } |
|
60 |
|
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 } |
|
77 |
|
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 |
|
95 |
|
96 //////////////////////////////// |
|
97 // CFindFile |
|
98 |
|
99 bool CFindFile::Close() |
|
100 { |
|
101 if(!_handleAllocated) |
|
102 return true; |
|
103 bool result = BOOLToBool(::FindClose(_handle)); |
|
104 _handleAllocated = !result; |
|
105 return result; |
|
106 } |
|
107 |
|
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 } |
|
117 |
|
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 |
|
140 |
|
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 } |
|
149 |
|
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 |
|
170 |
|
171 bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) |
|
172 { |
|
173 CFindFile finder; |
|
174 return finder.FindFirst(wildcard, fileInfo); |
|
175 } |
|
176 |
|
177 #ifndef _UNICODE |
|
178 bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) |
|
179 { |
|
180 CFindFile finder; |
|
181 return finder.FindFirst(wildcard, fileInfo); |
|
182 } |
|
183 #endif |
|
184 |
|
185 bool DoesFileExist(LPCTSTR name) |
|
186 { |
|
187 CFileInfo fileInfo; |
|
188 return FindFile(name, fileInfo); |
|
189 } |
|
190 |
|
191 #ifndef _UNICODE |
|
192 bool DoesFileExist(LPCWSTR name) |
|
193 { |
|
194 CFileInfoW fileInfo; |
|
195 return FindFile(name, fileInfo); |
|
196 } |
|
197 #endif |
|
198 |
|
199 ///////////////////////////////////// |
|
200 // CEnumerator |
|
201 |
|
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 } |
|
209 |
|
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 } |
|
220 |
|
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 } |
|
231 |
|
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 } |
|
240 |
|
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 } |
|
251 |
|
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 } |
|
262 |
|
263 #endif |
|
264 |
|
265 //////////////////////////////// |
|
266 // CFindChangeNotification |
|
267 |
|
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 } |
|
277 |
|
278 HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, |
|
279 DWORD notifyFilter) |
|
280 { |
|
281 _handle = ::FindFirstChangeNotification(pathName, |
|
282 BoolToBOOL(watchSubtree), notifyFilter); |
|
283 return _handle; |
|
284 } |
|
285 |
|
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 |
|
295 |
|
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 } |
|
325 |
|
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 |
|
362 |
|
363 #endif |
|
364 |
|
365 }}} |