michael@0: // Windows/FileFind.cpp michael@0: michael@0: #include "StdAfx.h" michael@0: michael@0: #include "FileFind.h" michael@0: #ifndef _UNICODE michael@0: #include "../Common/StringConvert.h" michael@0: #endif michael@0: michael@0: #ifndef _UNICODE michael@0: extern bool g_IsNT; michael@0: #endif michael@0: michael@0: namespace NWindows { michael@0: namespace NFile { michael@0: namespace NFind { michael@0: michael@0: static const TCHAR kDot = TEXT('.'); michael@0: michael@0: bool CFileInfo::IsDots() const michael@0: { michael@0: if (!IsDirectory() || Name.IsEmpty()) michael@0: return false; michael@0: if (Name[0] != kDot) michael@0: return false; michael@0: return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: bool CFileInfoW::IsDots() const michael@0: { michael@0: if (!IsDirectory() || Name.IsEmpty()) michael@0: return false; michael@0: if (Name[0] != kDot) michael@0: return false; michael@0: return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); michael@0: } michael@0: #endif michael@0: michael@0: static void ConvertWIN32_FIND_DATA_To_FileInfo( michael@0: const WIN32_FIND_DATA &findData, michael@0: CFileInfo &fileInfo) michael@0: { michael@0: fileInfo.Attributes = findData.dwFileAttributes; michael@0: fileInfo.CreationTime = findData.ftCreationTime; michael@0: fileInfo.LastAccessTime = findData.ftLastAccessTime; michael@0: fileInfo.LastWriteTime = findData.ftLastWriteTime; michael@0: fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; michael@0: fileInfo.Name = findData.cFileName; michael@0: #ifndef _WIN32_WCE michael@0: fileInfo.ReparseTag = findData.dwReserved0; michael@0: #else michael@0: fileInfo.ObjectID = findData.dwOID; michael@0: #endif michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: michael@0: static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } michael@0: michael@0: static void ConvertWIN32_FIND_DATA_To_FileInfo( michael@0: const WIN32_FIND_DATAW &findData, michael@0: CFileInfoW &fileInfo) michael@0: { michael@0: fileInfo.Attributes = findData.dwFileAttributes; michael@0: fileInfo.CreationTime = findData.ftCreationTime; michael@0: fileInfo.LastAccessTime = findData.ftLastAccessTime; michael@0: fileInfo.LastWriteTime = findData.ftLastWriteTime; michael@0: fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; michael@0: fileInfo.Name = findData.cFileName; michael@0: #ifndef _WIN32_WCE michael@0: fileInfo.ReparseTag = findData.dwReserved0; michael@0: #else michael@0: fileInfo.ObjectID = findData.dwOID; michael@0: #endif michael@0: } michael@0: michael@0: static void ConvertWIN32_FIND_DATA_To_FileInfo( michael@0: const WIN32_FIND_DATA &findData, michael@0: CFileInfoW &fileInfo) michael@0: { michael@0: fileInfo.Attributes = findData.dwFileAttributes; michael@0: fileInfo.CreationTime = findData.ftCreationTime; michael@0: fileInfo.LastAccessTime = findData.ftLastAccessTime; michael@0: fileInfo.LastWriteTime = findData.ftLastWriteTime; michael@0: fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; michael@0: fileInfo.Name = GetUnicodeString(findData.cFileName, GetCurrentCodePage()); michael@0: #ifndef _WIN32_WCE michael@0: fileInfo.ReparseTag = findData.dwReserved0; michael@0: #else michael@0: fileInfo.ObjectID = findData.dwOID; michael@0: #endif michael@0: } michael@0: #endif michael@0: michael@0: //////////////////////////////// michael@0: // CFindFile michael@0: michael@0: bool CFindFile::Close() michael@0: { michael@0: if(!_handleAllocated) michael@0: return true; michael@0: bool result = BOOLToBool(::FindClose(_handle)); michael@0: _handleAllocated = !result; michael@0: return result; michael@0: } michael@0: michael@0: bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) michael@0: { michael@0: Close(); michael@0: WIN32_FIND_DATA findData; michael@0: _handle = ::FindFirstFile(wildcard, &findData); michael@0: if (_handleAllocated = (_handle != INVALID_HANDLE_VALUE)) michael@0: ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); michael@0: return _handleAllocated; michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) michael@0: { michael@0: Close(); michael@0: if (g_IsNT) michael@0: { michael@0: WIN32_FIND_DATAW findData; michael@0: _handle = ::FindFirstFileW(wildcard, &findData); michael@0: if (_handleAllocated = (_handle != INVALID_HANDLE_VALUE)) michael@0: ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); michael@0: } michael@0: else michael@0: { michael@0: WIN32_FIND_DATAA findData; michael@0: _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, michael@0: GetCurrentCodePage()), &findData); michael@0: if (_handleAllocated = (_handle != INVALID_HANDLE_VALUE)) michael@0: ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); michael@0: } michael@0: return _handleAllocated; michael@0: } michael@0: #endif michael@0: michael@0: bool CFindFile::FindNext(CFileInfo &fileInfo) michael@0: { michael@0: WIN32_FIND_DATA findData; michael@0: bool result = BOOLToBool(::FindNextFile(_handle, &findData)); michael@0: if (result) michael@0: ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); michael@0: return result; michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: bool CFindFile::FindNext(CFileInfoW &fileInfo) michael@0: { michael@0: if (g_IsNT) michael@0: { michael@0: WIN32_FIND_DATAW findData; michael@0: if (!::FindNextFileW(_handle, &findData)) michael@0: return false; michael@0: ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); michael@0: } michael@0: else michael@0: { michael@0: WIN32_FIND_DATAA findData; michael@0: if (!::FindNextFileA(_handle, &findData)) michael@0: return false; michael@0: ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); michael@0: } michael@0: return true; michael@0: } michael@0: #endif michael@0: michael@0: bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) michael@0: { michael@0: CFindFile finder; michael@0: return finder.FindFirst(wildcard, fileInfo); michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) michael@0: { michael@0: CFindFile finder; michael@0: return finder.FindFirst(wildcard, fileInfo); michael@0: } michael@0: #endif michael@0: michael@0: bool DoesFileExist(LPCTSTR name) michael@0: { michael@0: CFileInfo fileInfo; michael@0: return FindFile(name, fileInfo); michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: bool DoesFileExist(LPCWSTR name) michael@0: { michael@0: CFileInfoW fileInfo; michael@0: return FindFile(name, fileInfo); michael@0: } michael@0: #endif michael@0: michael@0: ///////////////////////////////////// michael@0: // CEnumerator michael@0: michael@0: bool CEnumerator::NextAny(CFileInfo &fileInfo) michael@0: { michael@0: if(_findFile.IsHandleAllocated()) michael@0: return _findFile.FindNext(fileInfo); michael@0: else michael@0: return _findFile.FindFirst(_wildcard, fileInfo); michael@0: } michael@0: michael@0: bool CEnumerator::Next(CFileInfo &fileInfo) michael@0: { michael@0: while(true) michael@0: { michael@0: if(!NextAny(fileInfo)) michael@0: return false; michael@0: if(!fileInfo.IsDots()) michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) michael@0: { michael@0: if (Next(fileInfo)) michael@0: { michael@0: found = true; michael@0: return true; michael@0: } michael@0: found = false; michael@0: return (::GetLastError() == ERROR_NO_MORE_FILES); michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) michael@0: { michael@0: if(_findFile.IsHandleAllocated()) michael@0: return _findFile.FindNext(fileInfo); michael@0: else michael@0: return _findFile.FindFirst(_wildcard, fileInfo); michael@0: } michael@0: michael@0: bool CEnumeratorW::Next(CFileInfoW &fileInfo) michael@0: { michael@0: while(true) michael@0: { michael@0: if(!NextAny(fileInfo)) michael@0: return false; michael@0: if(!fileInfo.IsDots()) michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) michael@0: { michael@0: if (Next(fileInfo)) michael@0: { michael@0: found = true; michael@0: return true; michael@0: } michael@0: found = false; michael@0: return (::GetLastError() == ERROR_NO_MORE_FILES); michael@0: } michael@0: michael@0: #endif michael@0: michael@0: //////////////////////////////// michael@0: // CFindChangeNotification michael@0: michael@0: bool CFindChangeNotification::Close() michael@0: { michael@0: if(_handle == INVALID_HANDLE_VALUE || _handle == 0) michael@0: return true; michael@0: bool result = BOOLToBool(::FindCloseChangeNotification(_handle)); michael@0: if (result) michael@0: _handle = INVALID_HANDLE_VALUE; michael@0: return result; michael@0: } michael@0: michael@0: HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, michael@0: DWORD notifyFilter) michael@0: { michael@0: _handle = ::FindFirstChangeNotification(pathName, michael@0: BoolToBOOL(watchSubtree), notifyFilter); michael@0: return _handle; michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, michael@0: DWORD notifyFilter) michael@0: { michael@0: if (g_IsNT) michael@0: return (_handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter)); michael@0: return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); michael@0: } michael@0: #endif michael@0: michael@0: #ifndef _WIN32_WCE michael@0: bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) michael@0: { michael@0: driveStrings.Clear(); michael@0: UINT32 size = GetLogicalDriveStrings(0, NULL); michael@0: if(size == 0) michael@0: return false; michael@0: CSysString buffer; michael@0: UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); michael@0: if(newSize == 0) michael@0: return false; michael@0: if(newSize > size) michael@0: return false; michael@0: CSysString string; michael@0: for(UINT32 i = 0; i < newSize; i++) michael@0: { michael@0: TCHAR c = buffer[i]; michael@0: if(c == TEXT('\0')) michael@0: { michael@0: driveStrings.Add(string); michael@0: string.Empty(); michael@0: } michael@0: else michael@0: string += c; michael@0: } michael@0: if(!string.IsEmpty()) michael@0: return false; michael@0: return true; michael@0: } michael@0: michael@0: #ifndef _UNICODE michael@0: bool MyGetLogicalDriveStrings(UStringVector &driveStrings) michael@0: { michael@0: driveStrings.Clear(); michael@0: if (g_IsNT) michael@0: { michael@0: UINT32 size = GetLogicalDriveStringsW(0, NULL); michael@0: if (size == 0) michael@0: return false; michael@0: UString buffer; michael@0: UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); michael@0: if(newSize == 0) michael@0: return false; michael@0: if(newSize > size) michael@0: return false; michael@0: UString string; michael@0: for(UINT32 i = 0; i < newSize; i++) michael@0: { michael@0: WCHAR c = buffer[i]; michael@0: if(c == L'\0') michael@0: { michael@0: driveStrings.Add(string); michael@0: string.Empty(); michael@0: } michael@0: else michael@0: string += c; michael@0: } michael@0: return string.IsEmpty(); michael@0: } michael@0: CSysStringVector driveStringsA; michael@0: bool res = MyGetLogicalDriveStrings(driveStringsA); michael@0: for (int i = 0; i < driveStringsA.Size(); i++) michael@0: driveStrings.Add(GetUnicodeString(driveStringsA[i])); michael@0: return res; michael@0: } michael@0: #endif michael@0: michael@0: #endif michael@0: michael@0: }}}