It is necessary to implement a search for files / folders in subdirectories. Path is the path to the source folder, argument b is the search mask. The problem is that the algorithm goes through all the folders and subdirectories on the disk, but only finds files from the original Path packs.

 void FindFileRecursive(string & Path, char *b, HWND fList) { bool flag = false; static int i = 0; WIN32_FIND_DATA FindData; string Mask = Path + "*"; HANDLE fFind = FindFirstFile(Mask.c_str(), &FindData); if (INVALID_HANDLE_VALUE != fFind) { do { if (Find::IsNotDotName(&FindData.cFileName[0])) { string FullPath = Path + &FindData.cFileName[0] + "\\"; if (Find::IsDirectory(FindData.dwFileAttributes)) FindFileRecursive(FullPath, b, fList); else { _finddata_t fd; int OK = _findfirst(FullPath.c_str(), &fd); int result = OK; INT i = 0; while (result != -1) { char *q = NULL; if (b[0] == '*') { ++b; flag = true; } if (flag) q = strstr(fd.name, b); if (strncmp(b, fd.name, strlen(fd.name)) == 0 || q != NULL) { LVITEM LvItem; memset(&LvItem, 0, sizeof(LvItem)); LvItem.mask = LVIF_TEXT; LvItem.cchTextMax = 256; LvItem.iItem = i; LvItem.iSubItem = 0; LvItem.pszText = fd.name; SendMessage(fList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); char Temp[100]; LvItem.iSubItem = 2; sprintf_s(Temp, "%s", fd.name); LvItem.pszText = Temp; SendMessage(fList, LVM_SETITEM, 0, (LPARAM)&LvItem); LvItem.iSubItem = 3; sprintf_s(Temp, "%f", fd.size); LvItem.pszText = "0"; if (fd.size != NULL) LvItem.pszText = Temp; SendMessage(fList, LVM_SETITEM, 0, (LPARAM)&LvItem); LvItem.iSubItem = 1; ctime_s(Temp, 30, &fd.time_write); LvItem.pszText = Temp; SendMessage(fList, LVM_SETITEM, 0, (LPARAM)&LvItem); i++; } result = _findnext(OK, &fd); } } } } while (NULL != FindNextFile(fFind, &FindData)); } FindClose(fFind); } 
  • Do you remember to add bekslesh to the end of the road? Put a breakpoint and see what comes into the function. - VladD
  • @VladD, added bekslesh, and now in the debugger you can see that the recursion works and the program runs in folders. As I understand the problem in int OK = _findfirst (FullPath.c_str (), & fd), OK is always -1, although the path in findfirst is passed like it’s right: "C: \\ $ Recycle.Bin \\ S-1-5-21 -1037564483-3546990408-930324707-1001 \\ $ I41I3N0 \ * " - Lightness
  • Well, on $Recycle.Bin , the program may simply not have access rights (check in Explorer). Do not forget after receiving -1 to check errno , there is a really happened error. And with the rest of the directories there is no problem? - VladD
  • @VladD, problem with all directories - Lightness
  • What about errno ? - VladD

1 answer 1

From the beginning, I recommend that you use this ad to use WinApi functions:

 typedef std::basic_string<TCHAR> StdString; 

You have an error in filtering files, there is something dark there. Why do you do it manually when FindFirstFile can do it all perfectly. Here’s what the function should look like:

 void ScanFolder(const StdString & folder, const StdString & mask, DWORD attrs, HWND fList) { WIN32_FIND_DATA find_data = {0}; HANDLE find_handle = FindFirstFile( (folder + mask).c_str() , &find_data ); if(INVALID_HANDLE_VALUE == find_handle) { // ругаемся return; } else { do { if( (attrs & find_data.dwFileAttributes) && !Find::IsNotDotName(find_data.cFileName) ) { // обрабатываем найденое } } while(FindNextFile(find_handle, &find_data)) FindClose(find_handle); } } void FindFileRecursive(StdString start_path, const StdString & mask, DWORD attrs, HWND fList) { start_path = rtrim(start_path) + _T(\\); ScanFolder(start_path, mask, attrs, fList); WIN32_FIND_DATA folder_data = {0}; HANDLE folder_find = FindFirstFileEx ( (start_path + _T("*")).c_str() , FindExInfoStandard , &folder_data , FindExSearchLimitToDirectories // ищем папки , NULL , FIND_FIRST_EX_LARGE_FETCH ); if(INVALID_HANDLE_VALUE == folder_find) { // ругаемся return; } else { do { if( (FILE_ATTRIBUTE_DIRECTORY & folder_data.dwFileAttributes) && !Find::IsNotDotName(folder_data.cFileName) ) { FindFileRecursive( start_path + folder_data.cFileName , mask , attrs , fList ); } } while(FindNextFile(folder_find, &folder_data)) FindClose(folder_find); } } 

Line trim function (taken from here ):

  static inline StdString & rtrim(StdString & s) { s.erase ( std::find_if( s.rbegin() , s.rend() , std::not1(std::ptr_fun<int, int>(std::isspace))).base() , s.end() ); return s; }