Upload 2.0.2
[physicsfs] / lzma / CPP / Windows / FileFind.cpp
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 }}}