How do I recursively create a folder in Win32?

Viewed 58020

I'm trying to create a function that takes the name of a directory (C:\foo\bar, or ..\foo\bar\..\baz, or \\someserver\foo\bar), and creates directories as necessary so that the whole path is created.

I am attempting a pretty naive implementation of this myself and it seems to be a string processing nightmare. There is / vs \, there is the special case of network shares which begin with \\ (also you can't attempt to mkdir() the first two levels of the path which are machine name and share name), and there is \.\ type nonsense that can exist in a path.

Does there exist a simple way to do this in C++?

14 Answers

With C++17, this can be done quite easily using std::filesystem::create_directories().

Example:

#include <filesystem>
...

const char* path = "C:\\foo\\bar";
std::filesystem::create_directories(path);

The below method helped me create several directories until achieving the whole path.

Let's say if you have:

C:\d1 and you pass C:\d1\d2\d3 as parameter.

This function would go ahead and create d2 inside d1 and d3 inside d2. Also, it won't mess with files that already exist in your d1 directory.

// HRESULT CreateDirectoryStructure(directoryPath)

std::wstring directoryPath;
directoryPath= L"C:\\d1\\d2\\d3\\";
hr = CreateDirectoryStructure(directoryPath);

//----------------------------------------------//

HRESULT
CreateDirectoryStructure(
    _In_ const std::wstring& directory_path
)
/*++

Routine Description:

    Creates the directory and all parent directories specified by the
    directory_path. The path should end with backslash.

Arguments:

    directory_path - path of the directory to be created.

Return Value:

    S_OK on success. On failure appropriate HRESULT is returned.

--*/
{
    HRESULT hr = S_OK;
    DWORD error = ERROR_SUCCESS;
    bool result = false;
    PWSTR normalized_path = NULL;
    PWSTR last_path = NULL;

    if (directory_path.size() == 0)
    {
        hr = ERROR_INVALID_PARAMETER;
        goto Cleanup;
    }
    normalized_path = _wcsdup(directory_path.c_str());
    //
    // Find the first directory separator since this returns the system root.
    //
    last_path = wcschr(normalized_path, L'\\');
    if (last_path != NULL)
    {
        last_path++;
    }

    //
    // Create all directories and subdirectories in the path.
    //
    while ((last_path = wcschr(last_path, L'\\')) != NULL)
    {
        *last_path = '\0';
        result = CreateDirectory(
            normalized_path,
            NULL);
        *last_path = L'\\';
        last_path++;
        if (result == false)
        {
            error = GetLastError();
            if(error != ERROR_ALREADY_EXISTS)
            {
                hr = HRESULT_FROM_WIN32(error);
                goto Cleanup;
            }
        }
    }

Cleanup:
    return hr;
}
Related