SearchDir()

Share Your Own Code Samples With the World

Moderators: g3nuin3, SpeedWing, WhiteHat, mezzo

SearchDir()

Postby L. Spiro » Mon Jan 08, 2007 10:49 am

Code: Select all
// This function will search the specified directory for the specified
//  wildcard-string file name.  iSubDirSearchDepth indicates the number of
//  subdirectories deep the search will go.  For example, passing 0 will search
//  only the directory passed in pcPath, while passing 1 will search pcPath
//  and all its folders, but none of those folders’ folders.
// Passing -1 will search all subdirectories of all subdirectories.

// This function fails if you do not put a slash/backslash at the end of pcPath.
INT SearchDir( const CHAR * pcPath, const CHAR * pcFile, INT iSubDirSearchDepth ) {
    // To search directories we use two searches.
    //  One for the files the user wants and one to go into directories (if
    //  iSubDirSearchDepth is not 0).
    // For the first search, create the final path based on what the user wants
    //  to find.
    CHAR szFinal[MAX_PATH];
    SNPrintF( szFinal, MAX_PATH, "%s%s", pcPath, pcFile );

    // The structure to accept the return from Find*File().
    WIN32_FIND_DATA wfdFind;

    // Now the actual search handle used to find the files the user wants.
    // This search will not go into subdirectories because not all subdirectories
    //  will be matched by the wildcard string in pcFile.
    // In other words, if the user wants to find all files named “*.mp3”, this
    //  search will not find all subdirectories unless they all end with “.mp3”,
    //  which is highly unlikely.

    // So the search is broken into two parts.
    // First we create a scan string to match only what the user wants and we ignore
    //  folders that are returned during this scan.
    // Then we create a second search which will simply replace pcFile with “*” and
    //  will allow us to find all subdirectories.
    // We call this function recursively on all subdirectories, ignore the files
    //  returned by that scan.


    // Keep track of how many we find.
    INT iFound = 0;

    // Get the handle for the search for the files the user wants.
    HANDLE hFind = FindFirstFile( szFinal, &wfdFind );

    // If the handle is not invalid, continue.
    if ( (DWORD)hFind != (DWORD)INVALID_HANDLE_VALUE ) {
        while ( hFind ) {
            // “.” and “..” can be returned, so ignore them.
            if ( StrCmp( wfdFind.cFileName, "." ) != 0 && StrCmp( wfdFind.cFileName, ".." ) != 0 ) {
                // If it is a directory, ignore it for now.  We will get to it in our second
                //  search.  Check that the FILE_ATTRIBUTE_DIRECTORY flag is NOT set.
                if ( (wfdFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
                    // If we come here it is a file, not a directory.
                    // Increase the found count and print the file name.
                    iFound++;

                    // Optionally print the file we found.
                    // This will be very slow if many files are found!

                    // Otherwise, replace this with your own code for operating on
                    //  wfdFind.cFileName.

                    CHAR szFile[MAX_PATH];
                    SNPrintF( szFile, MAX_PATH, "%s%s", pcPath, wfdFind.cFileName );
                    PrintF( "%s", szFile );
                }
            }

            // Get the next file.
            if ( !FindNextFile( hFind, &wfdFind ) ) {
                // No next file?  Close the handle and leave the loop.
                FindClose( hFind );
                hFind = NULL;
                break;
            }
        }
    }   // hFind != INVALID_HANDLE_VALUE


    // If we are not to search subdirectories, we are done.
    if ( iSubDirSearchDepth == 0 ) { return iFound; }

    // If we come here, it means we are supposed to search subdirectories too.
    // The only way to get all subdirectories is to remake the scan string using
    //  “*”.
    SNPrintF( szFinal, MAX_PATH, "%s*", pcPath );
    hFind = FindFirstFile( szFinal, &wfdFind );
    if ( (DWORD)hFind != (DWORD)INVALID_HANDLE_VALUE ) {
        while ( hFind ) {
            if ( StrCmp( wfdFind.cFileName, "." ) != 0 && StrCmp( wfdFind.cFileName, ".." ) != 0 ) {
                // This time we only care about directories
                if ( wfdFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
                    // Recompile the string and pass it right back to this function in a
                    //  recursive call.
                    CHAR szDir[MAX_PATH];
                    SNPrintF( szDir, MAX_PATH, "%s%s\\", pcPath, wfdFind.cFileName );
                    //PrintF( "%s", szDir );

                    // Call ourself and add the return.
                    // Pass iSubDirSearchDepth - 1 since we are going one folder deeper.
                    iFound += SearchDir( szDir, pcFile, iSubDirSearchDepth - 1 );
                }
            }

            // Get the next file.
            if ( !FindNextFile( hFind, &wfdFind ) ) {
                FindClose( hFind );
                hFind = NULL;
                break;
            }
        }
    }   // hFind != INVALID_HANDLE_VALUE

    // We are done, and iFound contains the total matching files.
    return iFound;
}




Pass the directory (must end with “\\” in the code) and the wildcard filename to match.
Then pass the number of directories deep you want to search, or -1 to search all of them.

The return is the total files found.
It will print all found files as well, which is what will slow things down if you find a lot of files.
You should replace the printing code with whatever you want to actually do with the files.


The script works very quickly (unless you print all files).
Normally it can scan your entire hard drive in only a few seconds, but huge drives with tons of files may take longer.
You can shorten the time by only scanning a few folders deep.



Also, you can run this search on a seperate thread to avoid locking up Memory Hacking Software and to add a “Cancel” feature.

I will leave this feature up to you as a challenge, however I will supply a code example on using CreateThread() to do this.



This is my example on how to call this function:
Code: Select all
VOID On_HK_0( DWORD dwP1, DWORD dwP2 ) {
    Clear();
    PrintF( "Found %u files.", SearchDir( "C:\\", "*.mp3", 4 ) + SearchDir( "D:\\", "*.mp3", 4 ) );
}



L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Return to Code Submissions

Who is online

Users browsing this forum: No registered users and 0 guests

cron