0

The aim is to code a utility in C++ using the function:

BOOL WINAPI CreateDirectoryW(_In_ LPCTSTR lpPathName, _In_opt_LPSECURITY_ATTRIBUTES lpSecurityAttributes)

The only successful attempt found so far appears to be a in a Perl script, but getting that to work is another question. This script trials the prefix

my $path = '\\\\?\\' 

but it has been observed elsewhere that using "\\?\UNC\" is more reliable. Any code blocks would be welcome.

Edit: Also, as the original question title indicated, the problem is moving the folder to another location (other than a relative path). Can this path be moved with MoveFileEx?

Community
  • 1
  • 1
Laurie Stearn
  • 959
  • 1
  • 13
  • 34
  • The UNC form is for network drives. And yes, MoveFileEx should accept long file names (provided you're using the wide-character version). – Harry Johnston Aug 06 '15 at 23:31
  • [Wrename](https://msdn.microsoft.com/en-us/library/zw5t957f(v=vs.100).aspx) might be a better option as it works for operations on another drive. – Laurie Stearn Aug 07 '15 at 07:19
  • Maybe not. Well then how then is a Unicode directory moved across drives/filesystems? – Laurie Stearn Aug 07 '15 at 07:27
  • 1
    The kernel doesn't provide any functions that move a directory tree between filesystems. The shell API, e.g., IFileOperation::MoveItem, might be able to do so, but I'm not sure. – Harry Johnston Aug 07 '15 at 22:24

2 Answers2

3

The following is from the MSDN documentation on the CreateDirectory function.

There is a default string size limit for paths of 248 characters. This limit is related to how the CreateDirectory function parses paths.

To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\?\" to the path. For more information, see Naming a File.

Note that in C++, as in Perl, it is necessary to escape the \ characters in the source code unless you use Raw String Literals. Thus it would be "\\?\" in the source code.

Here is a quick example of how to do it.

BOOL CreatDirWithVeryLongName()
{
    BOOL ret = ::CreateDirectoryW(L"\\\\?\\C:\\This is an example directory that has an extreemly long name that is more than 248 characters in length to serve as an example of how to go beyond the normal limit - Note that you will not be able to see it in Windows Explorer due to the fact that it is limited to displaying files with fewer than 260 characters in the name", NULL);
    return ret;
}
Benilda Key
  • 2,836
  • 1
  • 22
  • 34
  • Thanks for the heads up (or heads down), but any code blocks would be useful. (edited question slightly) – Laurie Stearn Aug 06 '15 at 14:34
  • The MSDN documentation gives you all you need. If you have ever used create directory before, this is no different. Just prepend the prefix to the string. – Benilda Key Aug 06 '15 at 14:38
  • Ok, So all I need is something like [MSDN's attributes code](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365522(v=vs.85).aspx) to modify, right? – Laurie Stearn Aug 06 '15 at 14:44
  • 1
    For reference, I don't think that code will actually work as posted - using the \\?\ prefix allows the overall path length to be up to 32,767 characters, but there is still a limit (255 characters?) to the length of each individual component in the path. – Harry Johnston Aug 07 '15 at 22:19
  • The curious thing is that on a Unicode build in C, FindNextFileW picks up all first level directories on the C drive with L"\\\\?\\C:\*" Then there is no way of telling if the first folder of a string of nested folders just created with L"\\\\?\\C:\\" is a "long" path other than by its length. – Laurie Stearn Oct 11 '15 at 06:43
  • The create fails with error [cannot find path specified](http://stackoverflow.com/questions/33018732/could-not-find-path-specified-createdirectoryw). However, the file system sets a flag when recycling a path of say 250 chars long with a "too long" warning. The deleted file is truncated to the last folder under 260. `L"\\\\\?\\"` with an extra escape for `?` has the same effect.Is it an idea to schedule this before explorer starts on boot? Possible answer: PreprocessorDefinitions from `_WIN32` to `_Win64_`. – Laurie Stearn Oct 18 '15 at 12:02
0

This creates and deletes nested long paths, but does not move them.
Moving essentially implies creating a new tree where the main coding challenge is dealing with paths that have different permissions or attributes.

Laurie Stearn
  • 959
  • 1
  • 13
  • 34