view src/win32/7zip/7z/CPP/Windows/FileFind.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
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 {
17 #if defined(WIN_LONG_PATH) && defined(_UNICODE)
18 #define WIN_LONG_PATH2
19 #endif
21 bool GetLongPath(LPCWSTR fileName, UString &res);
23 namespace NFind {
25 static const TCHAR kDot = TEXT('.');
27 bool CFileInfo::IsDots() const
28 {
29 if (!IsDir() || 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 }
36 #ifndef _UNICODE
37 bool CFileInfoW::IsDots() const
38 {
39 if (!IsDir() || 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
47 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)
48 {
49 fi.Attrib = fd.dwFileAttributes;
50 fi.CTime = fd.ftCreationTime;
51 fi.ATime = fd.ftLastAccessTime;
52 fi.MTime = fd.ftLastWriteTime;
53 fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow;
54 fi.Name = fd.cFileName;
55 #ifndef _WIN32_WCE
56 fi.ReparseTag = fd.dwReserved0;
57 #else
58 fi.ObjectID = fd.dwOID;
59 #endif
60 }
62 #ifndef _UNICODE
64 static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
66 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi)
67 {
68 fi.Attrib = fd.dwFileAttributes;
69 fi.CTime = fd.ftCreationTime;
70 fi.ATime = fd.ftLastAccessTime;
71 fi.MTime = fd.ftLastWriteTime;
72 fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow;
73 fi.Name = fd.cFileName;
74 #ifndef _WIN32_WCE
75 fi.ReparseTag = fd.dwReserved0;
76 #else
77 fi.ObjectID = fd.dwOID;
78 #endif
79 }
81 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi)
82 {
83 fi.Attrib = fd.dwFileAttributes;
84 fi.CTime = fd.ftCreationTime;
85 fi.ATime = fd.ftLastAccessTime;
86 fi.MTime = fd.ftLastWriteTime;
87 fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow;
88 fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage());
89 #ifndef _WIN32_WCE
90 fi.ReparseTag = fd.dwReserved0;
91 #else
92 fi.ObjectID = fd.dwOID;
93 #endif
94 }
95 #endif
97 ////////////////////////////////
98 // CFindFile
100 bool CFindFile::Close()
101 {
102 if (_handle == INVALID_HANDLE_VALUE)
103 return true;
104 if (!::FindClose(_handle))
105 return false;
106 _handle = INVALID_HANDLE_VALUE;
107 return true;
108 }
111 bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo)
112 {
113 if (!Close())
114 return false;
115 WIN32_FIND_DATA fd;
116 _handle = ::FindFirstFile(wildcard, &fd);
117 #ifdef WIN_LONG_PATH2
118 if (_handle == INVALID_HANDLE_VALUE)
119 {
120 UString longPath;
121 if (GetLongPath(wildcard, longPath))
122 _handle = ::FindFirstFileW(longPath, &fd);
123 }
124 #endif
125 if (_handle == INVALID_HANDLE_VALUE)
126 return false;
127 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
128 return true;
129 }
131 #ifndef _UNICODE
132 bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo)
133 {
134 if (!Close())
135 return false;
136 if (g_IsNT)
137 {
138 WIN32_FIND_DATAW fd;
139 _handle = ::FindFirstFileW(wildcard, &fd);
140 #ifdef WIN_LONG_PATH
141 if (_handle == INVALID_HANDLE_VALUE)
142 {
143 UString longPath;
144 if (GetLongPath(wildcard, longPath))
145 _handle = ::FindFirstFileW(longPath, &fd);
146 }
147 #endif
148 if (_handle != INVALID_HANDLE_VALUE)
149 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
150 }
151 else
152 {
153 WIN32_FIND_DATAA fd;
154 _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard,
155 GetCurrentCodePage()), &fd);
156 if (_handle != INVALID_HANDLE_VALUE)
157 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
158 }
159 return (_handle != INVALID_HANDLE_VALUE);
160 }
161 #endif
163 bool CFindFile::FindNext(CFileInfo &fileInfo)
164 {
165 WIN32_FIND_DATA fd;
166 bool result = BOOLToBool(::FindNextFile(_handle, &fd));
167 if (result)
168 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
169 return result;
170 }
172 #ifndef _UNICODE
173 bool CFindFile::FindNext(CFileInfoW &fileInfo)
174 {
175 if (g_IsNT)
176 {
177 WIN32_FIND_DATAW fd;
178 if (!::FindNextFileW(_handle, &fd))
179 return false;
180 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
181 }
182 else
183 {
184 WIN32_FIND_DATAA fd;
185 if (!::FindNextFileA(_handle, &fd))
186 return false;
187 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
188 }
189 return true;
190 }
191 #endif
193 bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo)
194 {
195 CFindFile finder;
196 return finder.FindFirst(wildcard, fileInfo);
197 }
199 #ifndef _UNICODE
200 bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo)
201 {
202 CFindFile finder;
203 return finder.FindFirst(wildcard, fileInfo);
204 }
205 #endif
207 bool DoesFileExist(LPCTSTR name)
208 {
209 CFileInfo fileInfo;
210 return FindFile(name, fileInfo);
211 }
213 #ifndef _UNICODE
214 bool DoesFileExist(LPCWSTR name)
215 {
216 CFileInfoW fileInfo;
217 return FindFile(name, fileInfo);
218 }
219 #endif
221 /////////////////////////////////////
222 // CEnumerator
224 bool CEnumerator::NextAny(CFileInfo &fileInfo)
225 {
226 if (_findFile.IsHandleAllocated())
227 return _findFile.FindNext(fileInfo);
228 else
229 return _findFile.FindFirst(_wildcard, fileInfo);
230 }
232 bool CEnumerator::Next(CFileInfo &fileInfo)
233 {
234 for (;;)
235 {
236 if (!NextAny(fileInfo))
237 return false;
238 if (!fileInfo.IsDots())
239 return true;
240 }
241 }
243 bool CEnumerator::Next(CFileInfo &fileInfo, bool &found)
244 {
245 if (Next(fileInfo))
246 {
247 found = true;
248 return true;
249 }
250 found = false;
251 return (::GetLastError() == ERROR_NO_MORE_FILES);
252 }
254 #ifndef _UNICODE
255 bool CEnumeratorW::NextAny(CFileInfoW &fileInfo)
256 {
257 if (_findFile.IsHandleAllocated())
258 return _findFile.FindNext(fileInfo);
259 else
260 return _findFile.FindFirst(_wildcard, fileInfo);
261 }
263 bool CEnumeratorW::Next(CFileInfoW &fileInfo)
264 {
265 for (;;)
266 {
267 if (!NextAny(fileInfo))
268 return false;
269 if (!fileInfo.IsDots())
270 return true;
271 }
272 }
274 bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found)
275 {
276 if (Next(fileInfo))
277 {
278 found = true;
279 return true;
280 }
281 found = false;
282 return (::GetLastError() == ERROR_NO_MORE_FILES);
283 }
285 #endif
287 ////////////////////////////////
288 // CFindChangeNotification
289 // FindFirstChangeNotification can return 0. MSDN doesn't tell about it.
291 bool CFindChangeNotification::Close()
292 {
293 if (!IsHandleAllocated())
294 return true;
295 if (!::FindCloseChangeNotification(_handle))
296 return false;
297 _handle = INVALID_HANDLE_VALUE;
298 return true;
299 }
301 HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter)
302 {
303 _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter);
304 #ifdef WIN_LONG_PATH2
305 if (!IsHandleAllocated())
306 {
307 UString longPath;
308 if (GetLongPath(pathName, longPath))
309 _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
310 }
311 #endif
312 return _handle;
313 }
315 #ifndef _UNICODE
316 HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter)
317 {
318 if (!g_IsNT)
319 return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);
320 _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter);
321 #ifdef WIN_LONG_PATH
322 if (!IsHandleAllocated())
323 {
324 UString longPath;
325 if (GetLongPath(pathName, longPath))
326 _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
327 }
328 #endif
329 return _handle;
330 }
331 #endif
333 #ifndef _WIN32_WCE
334 bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)
335 {
336 driveStrings.Clear();
337 UINT32 size = GetLogicalDriveStrings(0, NULL);
338 if (size == 0)
339 return false;
340 CSysString buffer;
341 UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size));
342 if (newSize == 0)
343 return false;
344 if (newSize > size)
345 return false;
346 CSysString string;
347 for (UINT32 i = 0; i < newSize; i++)
348 {
349 TCHAR c = buffer[i];
350 if (c == TEXT('\0'))
351 {
352 driveStrings.Add(string);
353 string.Empty();
354 }
355 else
356 string += c;
357 }
358 if (!string.IsEmpty())
359 return false;
360 return true;
361 }
363 #ifndef _UNICODE
364 bool MyGetLogicalDriveStrings(UStringVector &driveStrings)
365 {
366 driveStrings.Clear();
367 if (g_IsNT)
368 {
369 UINT32 size = GetLogicalDriveStringsW(0, NULL);
370 if (size == 0)
371 return false;
372 UString buffer;
373 UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size));
374 if (newSize == 0)
375 return false;
376 if (newSize > size)
377 return false;
378 UString string;
379 for (UINT32 i = 0; i < newSize; i++)
380 {
381 WCHAR c = buffer[i];
382 if (c == L'\0')
383 {
384 driveStrings.Add(string);
385 string.Empty();
386 }
387 else
388 string += c;
389 }
390 return string.IsEmpty();
391 }
392 CSysStringVector driveStringsA;
393 bool res = MyGetLogicalDriveStrings(driveStringsA);
394 for (int i = 0; i < driveStringsA.Size(); i++)
395 driveStrings.Add(GetUnicodeString(driveStringsA[i]));
396 return res;
397 }
398 #endif
400 #endif
402 }}}