How to change the current directory to a long path - winapi

Although it is documented to handle the \\?\ prefix, SetCurrentDirectory() apparently isn't able to do this (see here). Passing a path that is longer than 260 characters always returns ERROR_FILENAME_EXCED_RANGE even though I included the \\?\ prefix. Tested on Windows 7.
This makes me wonder how I can change the current directory to a path that is longer than 260 characters. Do I have to break that long path down into pieces of max. 260 characters each and call SetCurrentDirectory() on each of those pieces, or what is the recommended way of dealing with this problem?
NB: I know that on Windows 10 the problem can be solved by setting adding the longPathAware stuff in the manifest and setting the corresponding registry flag. However, I'm specifically looking for a solution that works on Windows 7 and 8 as well.

Related

Retrieving a long path from "\Device\HarddiskVolume1\Progra~1"

I'm writing a ProcessExplorer-like tool that shows all open files in the system.
Calling the NtQueryObject(,ObjectNameInformation,,,) gives me a path that looks like \Device\HarddiskVolume1\Users\ADMINI~1\AppData\Local\Temp\FXSAPIDebugLogFile.txt, so it is an NT device path that sometimes has shortened segments (ADMINI~1 in this case).
I don't really need to convert this path to a "standard" one (like C:\Users), but I need to expand it to a long form, so it should look like \Device\HarddiskVolume1\Users\Administrator\AppData\Local\Temp\FXSAPIDebugLogFile.txt. Besides, converting a device path to a standard one won't even be possible if the volume doesn't have a mountpoint.
I need a solution that works from Windows XP onwards.
Unfortunately, the most obvious method - using the GetLongPathNameW function doesn't work with a path like this, it returns a ERROR_INVALID_NAME for a path like this.
I tried different path prefixes: \\?\, \\.\, \??\, \\.\GLOBALROOT\ - none of this helped.
FindFirstFileW also doesn't accept a path like this on Vista.
It's strange, because the CreateFile function works with a \Device\HarddiskVolume path just fine.
Also I found, that if I remove the Device word from the path, making it \\.\HarddiskVolume1\Users\ADMINI~1\AppData\Local\Temp\FXSAPIDebugLogFile.txt, the GetLongPathNameW actually returns a correct long path. Unfortunately, this doesn't work on Windows XP/Vista.
I'd like to know if there is another method, that will work on Windows XP too.

What is the name of the "\\?\" construct in windows?

I had to help someone delete a folder that had weird characters in it that caused the path to be re-interepeted as a different path:
c:\test. -> c:\test
It took me a while to recall the \\?\ construct, since I have no idea what it's called or how to search for it. Once I remembered it, though, it was easy:
\\?\c:\test. -> c:\test.
What is the name of this construct, that I (and others) may search for it?
I don't think it has an official name in widespread use, so I doubt that you'll get very far in any searches. It is described here: https://msdn.microsoft.com/en-gb/library/windows/desktop/aa365247.aspx#maxpath
The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters. This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters). To specify an extended-length path, use the "\\?\" prefix. For example, "\\?\D:\very long path".
For this usage it might be called the extended-length path prefix. However the prefix serves other purposes, most specifically suppressing user mode path canonicalisation, the purpose that you were availing yourself of.
As you can see from comments to this answer, there are lots of varied opinions on the most suitable name. I think that we can all agree that there is no single officially used name for this thing!

"TCHAR cFileName[MAX_PATH];" - mistake in the MSDN library?

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365740%28v=vs.85%29.aspx
cFileName
The name of the file.
The value of MAX_PATH is the same as almost the same as _MAX_FNAME, but using the first is misleading in this case. Anyway, if they meant the full path with name, should it be cFileName[MAX_PATH+_MAX_FNAME];? What was the purpose of using MAX_PATH?
The MAX_PATH constant represents the maximum length of an entire path, including the file name and the extension. It is irrelevant whether it is a relative path, a fully-qualified path, or even just a file name; they all have the same maximum length.
Thus, you would never see MAX_PATH + _MAX_FNAME because that would exceed the maximum length allowed for a path.
You'll find pretty much everything you ever wanted to know about paths in Win32 in this article. Note that some APIs (these will generally be called out explicitly in the docs ) accept long path names, indicated with a special prefix, which are not subject to the limitations of MAX_PATH.
The function signature is correct in this case. Sometimes, though, there are snippets of sample code on MSDN that accompany the docs, and this sample code ranges anywhere from stylistically curious to an utter abomination. It's always worth using a good healthy dose of common sense when trying to adapt sample code you find.
There's no mistake here. In Windows APIs that are subject to limits on length, the maximum length of a name is (usually) MAX_PATH. It doesn't matter whether the name is a fully specified absolute path, a relative path, or just a file name, the length limit is still MAX_PATH.
It may well be that the underlying file system has different limits. It's perfectly plausible that the native file system limit could be less than 260. But if the API declares a limit of 260 characters, then that's the limit when using that particular API.
If ever you think that the MSDN library is incorrect, it's easy enough to check. Take a look at the definition in the Windows header file and compare it with that given in the MSDN library. Invariably you will find that the MSDN library is accurate.

What does "\\?\" means before a path?

I'm having a look at the code of FastCopy, where I want to add a few features.
Internally, it seems that FastCopy stores its paths with a \\?\ before the path. eg. \\?\c:\Program Files\Adobe. These paths are passed on directly to Windows API functions like DeleteFile, RemoveDirectory, etc. so it seems Windows understands the format.
But what do these extra characters mean and why do FastCopy stores them that way?
The thing that's probably most relevant for FastCopy is that it allows you to work with file names more than ~256 characters long.
If memory serves, it also prevents Windows from parsing a file name looking for things like \\server\file to access a shared file (though you can still use \\?\UNC\whatever), but that's probably not what's really intended/relevant here.
You are referring to Long UNC paths : https://en.wikipedia.org/wiki/Path_%28computing%29 Hope that helps.
Generally that means it's supporting long file names - names up to about 32K in length.
It can also be used to specify UNC paths, e.g. \\?\UNC\server\share.
Without that support Fastcopy wouldn't be able to access all files properly.
More detail at http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx

How to create directories in windows with path length greater than 256

I have several level of directories in the folder path. when the path exceeds 256, then I could not create a sub-folder or file from it. Is there any chance to build paths more than this length.
Can anyone help me out.
In fact the limit on path strings is 260 characters. The underlying OS, these days, can support much longer path names, up to 32,767 characters. In order to name a path with a long name you need to use the magic \\?\ prefix, and use the Unicode version of the API.
However, many tools don't support such long names. A classic example of such a tool is Explorer which won't let you create objects with names longer than 260 characters. Because of this I strongly advise you to avoid creating such long names—doing so will save you much heartache in the long run.
This should get you started: http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx#maxpath
Sadly it's an issue that I don't think will be going away any time soon, so you'd do well to familiarize yourself with that stuff.
As an aside, if you have access to robocopy (comes packaged with Windows Vista and 7, but is also available for XP), which supports long paths, you could create your files/subfolders in a higher-up folder and then use robocopy to move the subfolder to its desired location deeper in the folder tree.
According to the documentation here http://msdn.microsoft.com/en-us/library/Aa365247, the maximum length is actually about 32,000, but most windows APIs still limit you to MAX_PATH which is 260. There are some unicode APIs that let you go beyond the 260 limit.
See here, http://msdn.microsoft.com/en-us/library/aa363856.
In the ANSI version of this function, the name is limited to MAX_PATH characters. 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.
This is an addendum to the answers above. I extracted only a summary to what I think is relevant, from Microsoft's official documentation:
Maximum Path Length Limitation
In the Windows API (with some exceptions), the maximum length for a path is MAX_PATH,
which is defined as 260 characters. A local path is structured in the following order:
drive letter, colon, backslash, name components separated by backslashes, and a terminating null character.
Example: "D:\some 256-character-path-string" -> 256
Using long paths
The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters.
To specify an extended-length path, use the "\?" prefix. For example, "\?\D:\very long path".
Relative paths
Relative paths are always limited to a total of MAX_PATH characters.
Enable Long Paths in Win10
Starting in Windows 10.1607, MAX_PATH limitations have been removed from common Win32 file and directory functions.
However, you must opt-in to the new behavior.
From Microsoft documentation:
https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#maximum-path-length-limitation
Warning for Delphi users:
There is a problem in IOUtils. It cannot be used in conjunction with Max_Path. It uses InternalCheckDirPathParam all over the place!
Details: TDirectory.GetDirectoryRoot does not handle correctly paths of Max_Path characters

Resources