Reputation: 653
I'm using CreateFile to open device. Everything is ok untill device name is too long.
In documentation it is said:
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 Files, Paths, and Namespaces.
I'm trying to use CreateFileW and prepend "\\?\" to the path, but getting invalid handle and
The system cannot find the path specified.
in GetLastError().
So, is this trick valid only for filenames, not for device names? Are there any other ways to avoid this problem?
UPD1: Device name without prepend looks like:
\\.\devicename\EndsBy:\name1.exe|EndsBy:\name2.exe.
Code:
CreateFileW(path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0));
Upvotes: 4
Views: 3110
Reputation: 36308
Some things to try:
You can usually replace \\.\
with \\?\
; it is my understanding that this will not always work, but I don't know what the rules are.
If you're on Windows 8 try using CreateFile2
with the \\.\
format; the documentation doesn't mention a path length limitation.
Try contacting the vendor of the device driver, who should have realized that this would be a problem and hopefully has a workaround.
Try using DefineDosDevice
to create an alias for your long path, and opening \\.\myalias
with CreateFile
. I'm not sure of the proper syntax for the path you're aliasing, but you can use QueryDosDevice
to look at the existing aliases for guidance. I believe you will want to use the DDD_RAW_TARGET_PATH
flag.
Failing all that, you may need to resort to NtCreateFile
. You should be able to use CreateFile
to open \\.\devicename
and then use that handle as the root directory for the call to NtCreateFile
. The downside here is that the API is not guaranteed to remain compatible in future versions of Windows.
Upvotes: 2
Reputation: 16896
The \\?
prefix sends paths straight to the file-system with no preprocessing.
The \\.
prefix bypasses the file namespace and uses the Win32 device namespace.
They have separate purposes and cannot be mixed together.
You can try this yourself. For example, this will open the null device:
HANDLE hDevice = ::CreateFileW(L"\\\\.\\NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
But if you change the path to L"\\\\?\\\\.\\NUL"
it will fail.
To answer your question, yes, prefixing paths with \\?
is only valid for file-system paths.
Upvotes: 4