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.
| 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. |
| 7961 | DECLSPEC_NOINLINE |
| 7962 | bool 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 |
nothing calls this directly
no outgoing calls
no test coverage detected