void File::List(StringList& rList, const std::string& sMask /*= "*" */, int nAttrs /*= AttributeAnyFile | AttributeDirectory */) { rList.clear(); #ifdef WIN32 _finddata_t stSearchData; // search record intptr_t nFile = _findfirst((m_sPath + "\\" + sMask).c_str(), &stSearchData); if (nFile != -1) { do { if (!IsDots(stSearchData.name) && (((nAttrs & AttributeDirectory) != 0) && (stSearchData.attrib & _A_SUBDIR) != 0) || ((nAttrs & AttributeAnyFile) != 0)) { rList.push_back(stSearchData.name); } } while (!_findnext(nFile, &stSearchData)); _findclose(nFile); } #else DIR* pDir = opendir(m_sPath.c_str()); if (pDir) { struct stat stStat; dirent* pstDirent = NULL; unsigned nMask = ((nAttrs & AttributeDirectory) ? S_IFDIR : 0) | ((nAttrs & AttributeRegularFile) ? S_IFREG : 0) | ((nAttrs & AttributeOtherFile) ? (S_IFMT & (~(S_IFREG | S_IFDIR))) : 0); while((pstDirent = readdir(pDir)) != NULL) { if (!IsDots(pstDirent->d_name) && !fnmatch(sMask.c_str(), pstDirent->d_name, 0) && !lstat(((m_sPath + "/") + pstDirent->d_name).c_str(), &stStat) && (stStat.st_mode & nMask) == (stStat.st_mode & S_IFMT)) { rList.push_back(pstDirent->d_name); } } closedir(pDir); } #endif }
static bool ScanFiles(File::Visitor &visitor, Path sPath, const TCHAR* filter = _T("*")) { TCHAR DirPath[MAX_PATH]; TCHAR FileName[MAX_PATH]; if (sPath != nullptr) // e.g. "/test/data/something" _tcscpy(DirPath, sPath.c_str()); else DirPath[0] = 0; // "/test/data/something/" _tcscat(DirPath, _T(DIR_SEPARATOR_S)); _tcscpy(FileName, DirPath); // "/test/data/something/*.igc" _tcscat(FileName, filter); // Find the first matching file WIN32_FIND_DATA FindFileData; HANDLE hFind = FindFirstFile(FileName, &FindFileData); // If no matching file found -> return false if (hFind == INVALID_HANDLE_VALUE) return false; // Loop through remaining matching files while (true) { if (!IsDots(FindFileData.cFileName) && !(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && checkFilter(FindFileData.cFileName, filter)) { // "/test/data/something/" _tcscpy(FileName, DirPath); // "/test/data/something/blubb.txt" _tcscat(FileName, FindFileData.cFileName); // Call visitor with the file that was found visitor.Visit(Path(FileName), Path(FindFileData.cFileName)); } // Look for next matching file if (!FindNextFile(hFind, &FindFileData)) { if (GetLastError() == ERROR_NO_MORE_FILES) // No more files/folders // -> Jump out of the loop break; else { // Some error occured // -> Close the handle and return false FindClose(hFind); return false; } } } // Close the file handle FindClose(hFind); return true; }
static bool GetNextFileData(FileRange& Range) { do { ++Range.CurFileIndex; } while (Range.CurFileIndex < Range.GlobData.gl_pathc && IsDots(Range.GlobData.gl_pathv[Range.CurFileIndex])); if (Range.CurFileIndex >= Range.GlobData.gl_pathc) { Range.GlobData.gl_pathc = 0; return false; } auto Path = Range.GlobData.gl_pathv[Range.CurFileIndex]; auto MaybeAttributes = GetAttributes(Path); if (!MaybeAttributes) { Range.Handle = nullptr; Range.ErrorCode = errno; return false; } auto& Attributes = *MaybeAttributes; FileData& dest = Range.Data; dest.Attributes = Attributes.Attributes; dest.CreationTime = Attributes.CreationTime; dest.LastAccessTime = Attributes.LastAccessTime; dest.LastModifiedTime = Attributes.LastModifiedTime; dest.Size = Attributes.Size; std::string PathCopy = Path; strcpy_safe(dest.Name, basename(PathCopy.c_str())); return true; }
BOOL DeleteDirectory(const char* sPath) { HANDLE hFind; // file handle WIN32_FIND_DATAA FindFileData; char DirPath[MAX_PATH]; char FileName[MAX_PATH]; strcpy(DirPath,sPath); strcat(DirPath,"\\*"); // searching all files strcpy(FileName,sPath); strcat(FileName,"\\"); hFind = FindFirstFileA(DirPath,&FindFileData); // find the first file if(hFind == INVALID_HANDLE_VALUE) return FALSE; strcpy(DirPath,FileName); bool bSearch = true; while(bSearch) { // until we finds an entry if(FindNextFileA(hFind,&FindFileData)) { if(IsDots(FindFileData.cFileName)) continue; strcat(FileName,FindFileData.cFileName); if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { // we have found a directory, recurse if(!DeleteDirectory(FileName)) { FindClose(hFind); return FALSE; // directory couldn't be deleted } RemoveDirectoryA(FileName); // remove the empty directory strcpy(FileName,DirPath); } else { if(!DeleteFileA(FileName)) { // delete the file FindClose(hFind); return FALSE; } strcpy(FileName,DirPath); } } else { if(GetLastError() == ERROR_NO_MORE_FILES) // no more files there bSearch = false; else { // some error occured, close the handle and return FALSE FindClose(hFind); return FALSE; } } } FindClose(hFind); // closing file handle return RemoveDirectoryA(sPath); // remove the empty directory }
BOOL CSimpleFileFind::FindNextFileNoDots() { BOOL result; do { result = FindNextFile(); } while (result && IsDots()); return result; }
UINT64 GetDirectorySizeInternal(OBJECT_ATTRIBUTES ObjectAttributes) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return 0; UINT64 Space = 0; byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; ObjectAttributes.RootDirectory = hFile; ObjectAttributes.ObjectName = &TempFileName; while (ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) { if (IsReparseTagNameSurrogate(FileInfo.EaSize)) continue; } else { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; } TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; Space += GetDirectorySizeInternal(ObjectAttributes); } else { Space += FileInfo.AllocationSize.QuadPart; } } NtClose(hFile); return Space; }
static bool GetNextFileData(FileRange& Range) { _finddata_t fd; int find_ret; do { find_ret = _findnext(reinterpret_cast<intptr_t>(Range.Handle.get()), &fd); } while (find_ret != -1 && IsDots(fd.name)); if (find_ret == -1) { auto err = errno; Range.ErrorCode = err == ENOENT ? 0 : err; Range.Handle = nullptr; return false; } CopyFileData(Range.Data, fd); return true; }
FileSeq::FileSeq (char const * pattern) :_atEnd (false), _handle (::FindFirstFile (pattern, &_data)) { if (_handle == INVALID_HANDLE_VALUE) { int err = ::GetLastError (); if (err == ERROR_FILE_NOT_FOUND) { _atEnd = true; Win::ClearError (); } else { throw Win::Exception ("Cannot list files."); } } // skip "." and ".." directories while (!AtEnd () && IsFolder () && IsDots ()) Advance (); }
FileRange Glob(const char* Pattern) { FileRange ret; _finddata_t fd; auto SearchHandle = _findfirst(Pattern, &fd); if (SearchHandle != -1) { ret.Handle = FileRange::HandleType(reinterpret_cast<void*>(SearchHandle)); if (IsDots(fd.name)) GetNextFileData(ret); else CopyFileData(ret.Data, fd); } else { ret.Handle = nullptr; ret.ErrorCode = errno; } return ret; }
static bool ScanDirectories(File::Visitor &visitor, bool recursive, Path sPath, const TCHAR* filter = _T("*")) { #ifdef HAVE_POSIX DIR *dir = opendir(sPath.c_str()); if (dir == nullptr) return false; TCHAR FileName[MAX_PATH]; _tcscpy(FileName, sPath.c_str()); size_t FileNameLength = _tcslen(FileName); FileName[FileNameLength++] = '/'; struct dirent *ent; while ((ent = readdir(dir)) != nullptr) { // omit '.', '..' and any other files/directories starting with '.' if (*ent->d_name == _T('.')) continue; _tcscpy(FileName + FileNameLength, ent->d_name); struct stat st; if (stat(FileName, &st) < 0) continue; if (S_ISDIR(st.st_mode) && recursive) ScanDirectories(visitor, true, Path(FileName), filter); else { int flags = 0; #ifdef FNM_CASEFOLD flags = FNM_CASEFOLD; #endif if (S_ISREG(st.st_mode) && fnmatch(filter, ent->d_name, flags) == 0) visitor.Visit(Path(FileName), Path(ent->d_name)); } } closedir(dir); #else /* !HAVE_POSIX */ TCHAR DirPath[MAX_PATH]; TCHAR FileName[MAX_PATH]; if (sPath != nullptr) { // e.g. "/test/data/something" _tcscpy(DirPath, sPath.c_str()); _tcscpy(FileName, sPath.c_str()); } else { DirPath[0] = 0; FileName[0] = 0; } // Scan for files in "/test/data/something" ScanFiles(visitor, Path(FileName), filter); // If we are not scanning recursive we are done now if (!recursive) return true; // "test/data/something/" _tcscat(DirPath, _T(DIR_SEPARATOR_S)); // "test/data/something/*" _tcscat(FileName, _T(DIR_SEPARATOR_S "*")); // Find the first file WIN32_FIND_DATA FindFileData; HANDLE hFind = FindFirstFile(FileName, &FindFileData); // If no file found -> return false if (hFind == INVALID_HANDLE_VALUE) return false; // Loop through remaining files while (true) { if (!IsDots(FindFileData.cFileName) && (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { // "test/data/something/" _tcscpy(FileName, DirPath); // "test/data/something/SUBFOLDER" _tcscat(FileName, FindFileData.cFileName); // Scan subfolder for matching files too ScanDirectories(visitor, true, Path(FileName), filter); } // Look for next file/folder if (!FindNextFile(hFind, &FindFileData)) { if (GetLastError() == ERROR_NO_MORE_FILES) // No more files/folders // -> Jump out of the loop break; else { // Some error occured // -> Close the handle and return false FindClose(hFind); return false; } } } // Close the file handle FindClose(hFind); #endif /* !HAVE_POSIX */ return true; }
static BOOL SearchDriverRecursive( IN PDEVINSTDATA DevInstData, IN LPCWSTR Path) { WIN32_FIND_DATAW wfd; WCHAR DirPath[MAX_PATH]; WCHAR FileName[MAX_PATH]; WCHAR FullPath[MAX_PATH]; WCHAR LastDirPath[MAX_PATH] = L""; WCHAR PathWithPattern[MAX_PATH]; BOOL ok = TRUE; BOOL retval = FALSE; HANDLE hFindFile = INVALID_HANDLE_VALUE; wcscpy(DirPath, Path); if (DirPath[wcslen(DirPath) - 1] != '\\') wcscat(DirPath, L"\\"); wcscpy(PathWithPattern, DirPath); wcscat(PathWithPattern, L"\\*"); for (hFindFile = FindFirstFileW(PathWithPattern, &wfd); ok && hFindFile != INVALID_HANDLE_VALUE; ok = FindNextFileW(hFindFile, &wfd)) { wcscpy(FileName, wfd.cFileName); if (IsDots(FileName)) continue; if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* Recursive search */ wcscpy(FullPath, DirPath); wcscat(FullPath, FileName); if (SearchDriverRecursive(DevInstData, FullPath)) { retval = TRUE; /* We continue the search for a better driver */ } } else { LPCWSTR pszExtension = GetFileExt(FileName); if ((_wcsicmp(pszExtension, L".inf") == 0) && (wcscmp(LastDirPath, DirPath) != 0)) { wcscpy(LastDirPath, DirPath); if (wcslen(DirPath) > MAX_PATH) /* Path is too long to be searched */ continue; if (SearchDriver(DevInstData, DirPath, NULL)) { retval = TRUE; /* We continue the search for a better driver */ } } } } if (hFindFile != INVALID_HANDLE_VALUE) FindClose(hFindFile); return retval; }
bool File::IsDots(const std::string& sName) { return IsDots(sName.c_str()); }
NTSTATUS DeleteDirectoryInternal(OBJECT_ATTRIBUTES ObjectAttributes) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return Status; byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; ObjectAttributes.RootDirectory = hFile; ObjectAttributes.ObjectName = &TempFileName; NTSTATUS Error = 0; while (ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if ((FileInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT)) { if (IsReparseTagNameSurrogate(FileInfo.EaSize)) goto StartDelete; } else { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; } if (Error = DeleteDirectoryInternal(ObjectAttributes)) { goto OnError; } } StartDelete: if (FileInfo.FileAttributes&FILE_ATTRIBUTE_READONLY) { //取消只读属性 if (Error = NtSetFileAttributes(&ObjectAttributes, FileInfo.FileAttributes^FILE_ATTRIBUTE_READONLY)) { goto OnError; } } if (Error = NtDeleteFile2(&ObjectAttributes)) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_READONLY) { //删除失败恢复只读属性 NtSetFileAttributes(&ObjectAttributes, FileInfo.FileAttributes); } OnError: Status = Error; } } //End: NtClose(hFile); return Status; }
NTSTATUS NtCopyDirectory(OBJECT_ATTRIBUTES ExistingDirectoryPath, OBJECT_ATTRIBUTES NewDirectoryPath) { HANDLE hExistingFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hExistingFile, SYNCHRONIZE | FILE_LIST_DIRECTORY| FILE_READ_ATTRIBUTES, &ExistingDirectoryPath, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return Status; HANDLE hNewFile; Status = NtCreateFile(&hNewFile, SYNCHRONIZE | FILE_LIST_DIRECTORY| FILE_WRITE_ATTRIBUTES, &NewDirectoryPath, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, NULL); if (Status == 0) { byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; NewDirectoryPath.RootDirectory = hNewFile; ExistingDirectoryPath.RootDirectory = hExistingFile; ExistingDirectoryPath.ObjectName = NewDirectoryPath.ObjectName = &TempFileName; byte FileBuffer[1024]; FILE_BASIC_INFORMATION BaseInfo; while (ZwQueryDirectoryFile(hExistingFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; Status = NtCopyDirectory(ExistingDirectoryPath, NewDirectoryPath); } else { HANDLE hExistingFile; Status = NtOpenFile(&hExistingFile, FILE_GENERIC_READ, &ExistingDirectoryPath, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) break; HANDLE hNewFile; Status = NtCreateFile(&hNewFile, SYNCHRONIZE | FILE_GENERIC_WRITE, &NewDirectoryPath, &IoStatusBlock, NULL, FileInfo.FileAttributes, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, NULL); if (Status) { NtClose(hExistingFile); break; } DWORD cbData; while (true) { if (!ReadFile(hExistingFile, FileBuffer, sizeof(FileBuffer), &cbData, NULL)) { Status = GetLastError_s(); break; } if (!cbData) break; WriteFile(hNewFile, FileBuffer, cbData, &cbData, NULL); } if (NtQueryInformationFile(hExistingFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation)==0) { NtSetInformationFile(hNewFile,&IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation); } NtClose(hNewFile); NtClose(hExistingFile); } } if (NtQueryInformationFile(hExistingFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation) == 0) { NtSetInformationFile(hNewFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation); } NtClose(hNewFile); } NtClose(hExistingFile); return Status; }
bool GetFileCount( const LPCWSTR& in_lpszPathW, DWORD& io_iCount, std::vector<std::wstring>& io_VecFiles, std::list<std::wstring>& in_SkippedExtensions, const bool in_bDontRecurse = false) { _ASSERT(in_lpszPathW); std::wstring strPathW(in_lpszPathW); _ASSERT( strPathW.length() ); if(!PathIsDirectoryW(in_lpszPathW)) return false; if( strPathW.length()) { if( strPathW[ strPathW.length() - 1 ] == L'\\' ) { strPathW += L"*.*"; } else { strPathW += L"\\*.*"; } } TRACEW2(L"Doing a findfile on [%s] count is [%d]\n", strPathW.c_str(), io_iCount); WIN32_FIND_DATAW fileData={0}; //The first handle returns a valid file handle which is not the case with CFileFind::FindFile() HANDLE hFind = FindFirstFileW(strPathW.c_str(), &fileData); if(hFind != INVALID_HANDLE_VALUE) { BOOL bWorking = true; std::wstring filePath = ExtractDirectoryW(strPathW); while(bWorking) { const std::wstring fileName(fileData.cFileName); if( ( (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && IsDots(fileName) ) || (fileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { bWorking = FindNextFileW(hFind, &fileData); continue; } if(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if(!in_bDontRecurse) { TRACEW2(L"Doing a recursive GetFileCount on [%s] count is [%d]\n", fileData.cFileName, io_iCount); GetFileCount( (filePath + fileName).c_str(), io_iCount, io_VecFiles, in_SkippedExtensions); } else { TRACE0("Not doing a recurse, in_bDontRecurse is true"); } } else { if(in_SkippedExtensions.size()) { // There's something in the list // Look for the current extension in the list, if it's there do not increment the counter const std::wstring extension (getExtensionW(fileName).c_str()); TRACEW2(L"Gonna look for extension [%s] of file [%s] in the list of excluded extension\n", extension.c_str(), fileName.c_str()); std::list<std::wstring>::const_iterator i = std::find(in_SkippedExtensions.begin(), in_SkippedExtensions.end(), extension); if(i == in_SkippedExtensions.end()) // extension not in list { io_VecFiles.push_back(filePath + fileName); ++io_iCount; } else { TRACEW1(L"Skipped file [%s], it matched a skipped extension\n", fileName.c_str()); } } else { io_VecFiles.push_back(filePath + fileName); ++io_iCount; } } bWorking = FindNextFileW(hFind,&fileData); } FindClose(hFind); } return true; }
BOOL DeleteDirectory(const TCHAR* sPath) { HANDLE hFind; // file handle WIN32_FIND_DATA FindFileData; TCHAR DirPath[MAX_PATH]; TCHAR FileName[MAX_PATH]; _tcscpy(DirPath,sPath); _tcscat(DirPath,"\\*"); // searching all files _tcscpy(FileName,sPath); _tcscat(FileName,"\\"); // find the first file hFind = FindFirstFile(DirPath,&FindFileData); if(hFind == INVALID_HANDLE_VALUE) return FALSE; _tcscpy(DirPath,FileName); bool bSearch = true; while(bSearch) // until we find an entry { if(FindNextFile(hFind,&FindFileData)) { if(IsDots(FindFileData.cFileName)) continue; _tcscat(FileName,FindFileData.cFileName); if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { // we have found a directory, recurse if(!DeleteDirectory(FileName)) { FindClose(hFind); return FALSE; // directory couldn't be deleted } // remove the empty directory RemoveDirectory(FileName); _tcscpy(FileName,DirPath); } else { if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) // change read-only file mode _chmod(FileName, _S_IWRITE); if(!DeleteFile(FileName)) { // delete the file FindClose(hFind); return FALSE; } _tcscpy(FileName,DirPath); } } else // no more files there { if(GetLastError() == ERROR_NO_MORE_FILES) bSearch = false; else { // some error occurred; close the handle and return FALSE FindClose(hFind); return FALSE; } } } FindClose(hFind); // close the file handle return RemoveDirectory(sPath); // remove the empty directory }
UINT64 GetDirectoryAllocationSizeInternal(OBJECT_ATTRIBUTES ObjectAttributes, std::map<UINT64, DWORD>& FileMap) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return 0; UINT64 Space = 0; byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; Status = -1; ObjectAttributes.RootDirectory = hFile; ObjectAttributes.ObjectName = &TempFileName; FILE_STANDARD_INFORMATION FileStandardInfo; FILE_INTERNAL_INFORMATION FileInternalInfo; while (ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) { if (IsReparseTagNameSurrogate(FileInfo.EaSize)) continue; } else { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; } Space += GetDirectoryAllocationSizeInternal(ObjectAttributes, FileMap); } else { if (NtGetFileId(&ObjectAttributes, &FileStandardInfo, &FileInternalInfo)) continue; if (FileStandardInfo.NumberOfLinks != 1) { auto T = FileMap.insert(std::pair<UINT64, DWORD>(FileInternalInfo.IndexNumber.QuadPart, FileStandardInfo.NumberOfLinks)).first; if (--(T->second)) continue; } Space += FileInfo.AllocationSize.QuadPart; } } NtClose(hFile); return Space; }
BOOL IsNotDots() { return IsDots() ? FALSE : TRUE; }