MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / FileCreateDir

Method FileCreateDir

source/script2.cpp:7961–8012  ·  view source on GitHub ↗

As of 2019-09-29, noinline reduces code size by over 20KB on VC++ 2019. Prior to merging Util_CreateDir with this, it wasn't inlined.

Source from the content-addressed store, hash-verified

7959// As of 2019-09-29, noinline reduces code size by over 20KB on VC++ 2019.
7960// Prior to merging Util_CreateDir with this, it wasn't inlined.
7961DECLSPEC_NOINLINE
7962bool Line::FileCreateDir(LPTSTR aDirSpec, LPTSTR aCanModifyDirSpec)
7963{
7964 if (!aDirSpec || !*aDirSpec)
7965 {
7966 SetLastError(ERROR_INVALID_PARAMETER);
7967 return false;
7968 }
7969
7970 DWORD attr = GetFileAttributes(aDirSpec);
7971 if (attr != 0xFFFFFFFF) // aDirSpec already exists.
7972 {
7973 SetLastError(ERROR_ALREADY_EXISTS);
7974 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; // Indicate success if it already exists as a dir.
7975 }
7976
7977 // If it has a backslash, make sure all its parent directories exist before we attempt
7978 // to create this directory:
7979 LPTSTR last_backslash = _tcsrchr(aDirSpec, '\\');
7980 if (last_backslash > aDirSpec // v1.0.48.04: Changed "last_backslash" to "last_backslash > aDirSpec" so that an aDirSpec with a leading \ (but no other backslashes), such as \dir, is supported.
7981 && last_backslash[-1] != ':') // v1.1.31.00: Don't attempt FileCreateDir("C:") since that's equivalent to either "C:\" or the working directory (which already exists), or FileCreateDir("\\?\C:") since it always fails.
7982 {
7983 LPTSTR parent_dir;
7984 if (aCanModifyDirSpec)
7985 {
7986 parent_dir = aDirSpec; // Caller provided a modifiable aDirSpec.
7987 *last_backslash = '\0'; // Temporarily terminate for parent directory.
7988 }
7989 else
7990 {
7991 // v1.1.31.00: Allocate a modifiable buffer to be used by all calls (supports long paths).
7992 parent_dir = (LPTSTR)_alloca((last_backslash - aDirSpec + 1) * sizeof(TCHAR));
7993 tcslcpy(parent_dir, aDirSpec, last_backslash - aDirSpec + 1); // Omits the last backslash.
7994 }
7995 bool exists = FileCreateDir(parent_dir, parent_dir); // Recursively create all needed ancestor directories.
7996 if (aCanModifyDirSpec)
7997 *last_backslash = '\\'; // Undo temporary termination.
7998
7999 // v1.0.44: Fixed ErrorLevel being set to 1 when the specified directory ends in a backslash. In such cases,
8000 // two calls were made to CreateDirectory for the same folder: the first without the backslash and then with
8001 // it. Since the directory already existed on the second call, ErrorLevel was wrongly set to 1 even though
8002 // everything succeeded. So now, when recursion finishes creating all the ancestors of this directory
8003 // our own layer here does not call CreateDirectory() when there's a trailing backslash because a previous
8004 // layer already did:
8005 if (!last_backslash[1] || !exists)
8006 return exists;
8007 }
8008
8009 // The above has recursively created all parent directories of aDirSpec if needed.
8010 // Now we can create aDirSpec.
8011 return CreateDirectory(aDirSpec, NULL);
8012}
8013
8014
8015

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected