Search code examples
c++winapidirectoryparent

RemoveDirectory() function in win32 api doesn't remove parent directory after removing subdirectories


I'm having a problem removing a directory after it's subfolders / files have been removed. I'm using FindFirstFile, FindNextFile, RemoveDirectory, etc. For instance I have this directory:

C:\Users\user\Desktop\SearchFile\ipch\searchfile-e3798fd4\some-files-here.ipch

After my program runs, it's left with this

C:\Users\user\Desktop\SearchFile\ipch

As you can see it deletes all files in searchfile-e3798fd4 and removes the directory, but leaves the parent directory 'ipch', which i want deleted as well. This is my full current code:

#include <Windows.h>
#include <wchar.h>
#include <stdio.h>

bool DeleteDirectory( const wchar_t *sDir )
{
    WIN32_FIND_DATA fdFile;
    HANDLE hFind;
    wchar_t sPath[ MAX_PATH * 10 ];

    wsprintf( sPath, L"%s\\*.*", sDir );

    if( ( hFind = FindFirstFile( sPath, &fdFile ) ) == INVALID_HANDLE_VALUE )
    {
        return false;
    }

    do
    {
        if( wcscmp( fdFile.cFileName, L"." ) != 0 &&
            wcscmp( fdFile.cFileName, L".." ) != 0 )
        {
            wsprintf( sPath, L"%s\\%s", sDir, fdFile.cFileName );

            if( fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
            {
                // Is Directory
                RemoveDirectory( sPath );
                DeleteDirectory( sPath );
            }
        }
    } while( FindNextFile( hFind, &fdFile ) );

    FindClose( hFind );
    return true;
}
bool DeleteFiles( const wchar_t *sDir, WIN32_FIND_DATA fdFile, HANDLE hFind )
{
    wchar_t sPath[ MAX_PATH * 10 ];

    wsprintf( sPath, L"%s\\*.*", sDir );

    if( ( hFind = FindFirstFile( sPath, &fdFile ) ) == INVALID_HANDLE_VALUE )
    {
        MessageBox( NULL, L"123", L"123", MB_OK );
        return false;
    }

    do
    {
        if( wcscmp( fdFile.cFileName, L"." ) != 0 &&
            wcscmp( fdFile.cFileName, L".." ) != 0 )
        {
            wsprintf( sPath, L"%s\\%s", sDir, fdFile.cFileName );

            if( fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
            {
                // Is Directory
                DeleteFiles( sPath, fdFile, hFind );
            }
            else
            {
                // Is File
                DeleteFile( sPath );
            }
        }
    } while( FindNextFile( hFind, &fdFile ) );


    FindClose( hFind );
    return true;
}
bool DeleteFolderContents( const wchar_t *sDir )
{
    WIN32_FIND_DATA fdFile;
    HANDLE hFind = NULL;
    wchar_t sPath[ MAX_PATH * 10 ];

    wsprintf( sPath, L"%s\\*.*", sDir );

    if( ( hFind = FindFirstFile( sPath, &fdFile ) ) == INVALID_HANDLE_VALUE )
    {
        MessageBox( NULL, L"", L"", MB_OK );
        return false;
    }

    do
    {
        if( wcscmp( fdFile.cFileName, L"." ) != 0 &&
            wcscmp( fdFile.cFileName, L".." ) != 0 )
        {
            wsprintf( sPath, L"%s\\%s", sDir, fdFile.cFileName );

            if( fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
            {
                // Is Directory
                if( wcscmp( fdFile.cFileName, L"Debug" ) == 0 ||
                    wcscmp( fdFile.cFileName, L"Release" ) == 0 ||
                    wcscmp( fdFile.cFileName, L"ipch" ) == 0 )
                {
                    DeleteFiles( sPath, fdFile, hFind );
                }
                DeleteFolderContents( sPath );
            }
        }
    } while( FindNextFile( hFind, &fdFile ) );

    FindClose( hFind );
    return true;
}
bool ListDirectoryContents( const wchar_t *sDir )
{
    WIN32_FIND_DATA fdFile;
    HANDLE hFind = NULL;
    wchar_t sPath[ MAX_PATH * 10 ];

    wsprintf( sPath, L"%s\\*.*", sDir );

    if( ( hFind = FindFirstFile( sPath, &fdFile ) ) == INVALID_HANDLE_VALUE )
    {
        MessageBox( NULL, L"Path not found", L"Error", MB_OK | MB_ICONERROR );
        return false;
    }

    do
    {
        if( wcscmp( fdFile.cFileName, L"." ) != 0 &&
            wcscmp( fdFile.cFileName, L".." ) != 0 )
        {
            wsprintf( sPath, L"%s\\%s", sDir, fdFile.cFileName );

            if( fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
            {
                // Is Directory
                if( wcscmp( fdFile.cFileName, L"Debug" ) == 0 ||
                    wcscmp( fdFile.cFileName, L"Release" ) == 0 ||
                    wcscmp( fdFile.cFileName, L"ipch" ) == 0 )
                {
                    // Working in debug folder
                    wprintf( L"[+] %s\n", sPath );
                }
                ListDirectoryContents( sPath );
            }
            else
            {
                // Is File
                wprintf( L"[-] %s\n", sPath );
            }
        }
    } while( FindNextFile( hFind, &fdFile ) );

    FindClose( hFind );
    return true;
}
int main()
{
    wchar_t pathName[] = L"C:\\Users\\user\\Desktop\\SearcFile\\";

    // List Directory Contents
    ListDirectoryContents( pathName );
    wprintf( L"\n" );
    system("pause");

    // Delete Folder Contents
    DeleteFolderContents( pathName );
    DeleteDirectory( pathName );
    wprintf( L"\n" );
    system("pause");

    ListDirectoryContents( pathName );
    wprintf( L"\n" );
    system("pause");

    return 0;
}

I'm aware that the problem exists where I actually RemoveDirectory( sPath ); Because that function is called it sees that ipch isn't empty, therefore doesn't delete it. then recursives and continues on.


Solution

  • You have three problems with your recursion, making it not match the algorithm Tim describes:

    1. You are trying to delete the directory before the contents. But RemoveDirectory only deletes empty directories.
    2. You (attempt to) delete subdirectories, but leave files in place. This also will prevent removal of the directory.
    3. You never delete the original directory.

    Moving the RemoveDirectory call from inside the loop to the end of the function will solve these problems.