CreatePath - Full Path Creation (wstring version)

Environment: Visual C++

This is a simple function I wrote in order to deal with creating complete (multi-level) paths.

The function works recursively, and uses std::wstring, but can actaully work on any basic_string -based string. It can deal with trailing slashes (eg. "c:\temp\" vs. "c:\temp"), as well as network locations (eg. "\\machine\shared").

You might notice the call to SetLastError(). The reason is to make it easy to verify what went wrong in case of an error - instead of handling exceptions and/or error strings, all you have to do is call GetLastError() if the function returns false.

You can use the function to make sure a directory exists before creating a file in it:

  std::wstring wsFileName;
  int pos = wsFileName.find_last_of(L"\\");
  if (0 <= pos)
    std::wstring wsPath = wsFileName.substr(0, pos);

    if (CreatePath(wsPath))
      CreateFileW(wsFileName.c_str(), ...);
      std::wcout << L"Error #" << GetLastError() << std::endl;

Here is the source code:
bool CreatePath(std::wstring &wsPath)
  DWORD attr;
  int pos;
  bool result = true;

  // Check for trailing slash:
  pos = wsPath.find_last_of(SLASH);
  if (wsPath.length() == pos + 1)  // last character is "\"

  // Look for existing object:
  attr = GetFileAttributesW(wsPath.c_str());
  if (0xFFFFFFFF == attr)  // doesn't exist yet - create it!
    pos = wsPath.find_last_of(SLASH);
    if (0 < pos)
      // Create parent dirs:
      result = CreatePath(wsPath.substr(0, pos));
    // Create node:
    result = result && CreateDirectoryW(wsPath.c_str(), NULL);
  else if (FILE_ATTRIBUTE_DIRECTORY != attr)
  {  // object already exists, but is not a dir
    result = false;

  return result;


Download source - < 1Kb


  • yFxhAE gp Og Efp lrYb Pr

    Posted by YCtBTCuwiU on 01/27/2013 03:51am

    buy generic viagra buy cheap viagra online us - viagra stories

  • This is my piece of code for the same prupose. You forgot an important thing.

    Posted by Legacy on 02/13/2004 12:00am

    Originally posted by: My code

    I think my code is better and more efficient.
    Don't forget to consider other language.
    The '\\' caracter may be part of multibyte character in other language like Chinese.
    Use CharNextExA instead.

    void LoopCreateDirectory(LPSTR dpath)
    LPSTR pname;
    for( LPSTR pdir=pname=dpath; *pdir; pdir=CharNextExA(CP_ACP,pdir,0))

  • Problem with GetFileAttributes and similar functions

    Posted by Legacy on 10/25/2002 12:00am

    Originally posted by: Madbawa

    These functions have a problem when the supplied path contains a double slash ('\\') somewhere in the middle. I deliberately put the \\ to test invalid paths, but sadly it doesn't give an INVALID_HANDLE or NULL pointer.

  • Similar but cheaper and faster iterative solution

    Posted by Legacy on 06/10/2002 12:00am

    Originally posted by: Arbesto Pelta


    Reading the code implemented by Assaf Tzur-El. I see that it is a recursive algorithm,
    and that every recursive call has the cost of construct a new string
    in the stack.

    Well I know that maybe this is not a critical question but I think it is a pity the
    recusion overload unnecessarily.

    I propose the next similar but iterative solution,



    The code...

    bool CreatePath(const char* PathToCreate)
    char Path[_MAX_PATH];
    // Copy path because we have to modify it
    // First add an ending slash
    char* Pos = strrchr(Path,'\\');
    if (!Pos || Pos[1]!=0)
    // From the first slash to the last check and create path
    // Exception : Jump initial duble slashed UNC host name and include first directory
    if (Path[0]=='\\' && Path[1]=='\\')
    // Find slash ending the host name
    Pos = strchr(Path+2,'\\');
    // Find slash after the first directory (after the host name)
    if (Pos)
    Pos = strchr(Pos+1,'\\');
    Pos = strchr(Path,'\\');
    bool AllOk = true;
    while (Pos && AllOk)
    // Cut the string
    *Pos = 0;
    // Check if exist this piece of path
    if (GetFileAttributes(Path)==-1)
    if (GetLastError()==ERROR_FILE_NOT_FOUND)
    AllOk = CreateDirectory(Path,NULL)==TRUE;
    AllOk = false;
    // Recover the character deleted
    *Pos = '\\';
    // Find next slash
    Pos = strchr(Pos+1,'\\');
    // Return true if finally the path was created or exist
    // (if not was created see LastError)
    return AllOk;

  • Funny no one mentioned it so far...

    Posted by Legacy on 06/09/2002 12:00am

    Originally posted by: Assaf Tzur-El

    ... but you might create yourself a small bug if you try to use the wsPath parameter after the function returns. The function takes its string parameter by reference, but it's NOT const, so the path might be changed inside the function. If you rely on the path staying the same, you might have a bug (your own bug, by the way, not mine - you should always check const-ness :) )

    The fix is simple - remove the reference char, and make the function look like this:
    bool CreatePath(std::wstring wsPath)

    Please note that if the function should be thread-safe and you are using Microsoft's STL, you should explicitly copy the string before passing it to the function. The reason is MS's obscene handling of reference counter for strings, which is NOT thread-safe. Feel free to email me for more information about this.

    Share and Enjoy,

  • Use MakeSureDirectoryPathExists

    Posted by Legacy on 01/16/2002 12:00am

    Originally posted by: Andrew

    Why not?

    BOOL MakeSureDirectoryPathExists(PCSTR DirPath);

    See MSDN Platform SDK

  • Why BOOL and GetLastError?

    Posted by Legacy on 01/16/2002 12:00am

    Originally posted by: NortonNealson

    Nice function, but I have a more general question.

    What makes you return a BOOL and then when FALSE require the caller to call GetLastError instead of just returning an error number or zero for success?

    I have nothing against using Get/SetLastError but feel it should be used when the return value cannot be used to indicate success and an error number. For example a function that returns a pointer or a handle where a NULL is often used to indicate failure.

    This may just be a coding style and is my opinion. I'm interested in hearing what you and others think about this.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Moving from an on-premises environment to Office 365 does not remove the need to plan for disruptions or reduce the business risk requirements for protecting email services. If anything, some risks increase with a move to the cloud. Read how to ease the transition every business faces if considering or already migrating to cloud email. This white paper discusses: Setting expectations when migrating to Office 365 Understanding the implications of relying solely on Exchange Online security Necessary archiving …

  • Anthony Christie, the Chief Marketing Officer for Level Communications, is responsible for customer experience, worldwide marketing and product management. In this informative asset, he shares his insights into why a private network connection to cloud-bases applications is the right decision for your enterprise. Download now to find out more.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date