| OLD | NEW |
| (Empty) |
| 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 (!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 } | |
| 35 | |
| 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 | |
| 46 | |
| 47 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileI
nfo &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 } | |
| 61 | |
| 62 #ifndef _UNICODE | |
| 63 | |
| 64 static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP :
CP_OEMCP; } | |
| 65 | |
| 66 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFile
InfoW &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 } | |
| 80 | |
| 81 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileI
nfoW &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 | |
| 96 | |
| 97 //////////////////////////////// | |
| 98 // CFindFile | |
| 99 | |
| 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 } | |
| 109 | |
| 110 | |
| 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 } | |
| 130 | |
| 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 | |
| 162 | |
| 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 } | |
| 171 | |
| 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 | |
| 192 | |
| 193 bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) | |
| 194 { | |
| 195 CFindFile finder; | |
| 196 return finder.FindFirst(wildcard, fileInfo); | |
| 197 } | |
| 198 | |
| 199 #ifndef _UNICODE | |
| 200 bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) | |
| 201 { | |
| 202 CFindFile finder; | |
| 203 return finder.FindFirst(wildcard, fileInfo); | |
| 204 } | |
| 205 #endif | |
| 206 | |
| 207 bool DoesFileExist(LPCTSTR name) | |
| 208 { | |
| 209 CFileInfo fileInfo; | |
| 210 return FindFile(name, fileInfo); | |
| 211 } | |
| 212 | |
| 213 #ifndef _UNICODE | |
| 214 bool DoesFileExist(LPCWSTR name) | |
| 215 { | |
| 216 CFileInfoW fileInfo; | |
| 217 return FindFile(name, fileInfo); | |
| 218 } | |
| 219 #endif | |
| 220 | |
| 221 ///////////////////////////////////// | |
| 222 // CEnumerator | |
| 223 | |
| 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 } | |
| 231 | |
| 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 } | |
| 242 | |
| 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 } | |
| 253 | |
| 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 } | |
| 262 | |
| 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 } | |
| 273 | |
| 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 } | |
| 284 | |
| 285 #endif | |
| 286 | |
| 287 //////////////////////////////// | |
| 288 // CFindChangeNotification | |
| 289 // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. | |
| 290 | |
| 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 } | |
| 300 | |
| 301 HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, D
WORD notifyFilter) | |
| 302 { | |
| 303 _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), no
tifyFilter); | |
| 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 } | |
| 314 | |
| 315 #ifndef _UNICODE | |
| 316 HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, D
WORD notifyFilter) | |
| 317 { | |
| 318 if (!g_IsNT) | |
| 319 return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), w
atchSubtree, notifyFilter); | |
| 320 _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), n
otifyFilter); | |
| 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 | |
| 332 | |
| 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 } | |
| 362 | |
| 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 | |
| 399 | |
| 400 #endif | |
| 401 | |
| 402 }}} | |
| OLD | NEW |