Why is it that when I call RtlDosPathNameToNtPathName_U
on the path \\?\C:
, instead of getting back
\??\C:
I get back
\??\C:\\\?\C:
which is clearly incorrect?
Code snippet (in D):
struct CurDir { UnicodeString DosPath; HANDLE Handle;开发者_StackOverflow中文版 }
extern (Windows) static bool RtlDosPathNameToNtPathName_U(
in const(wchar)* DosPathName, out UnicodeString NtPathName,
out const(wchar)* NtFileNamePart, out CurDir DirectoryInfo);
wchar[] toNtPath(const(wchar)[] path)
{
UnicodeString ntPath;
CurDir curDir;
const(wchar)* fileNamePart;
enforce(RtlDosPathNameToNtPathName_U(path.ptr, ntPath,
fileNamePart, curDir));
try
{ return ntPath.Buffer[0 .. ntPath.Length / ntPath.Buffer[0].sizeof].dup; }
finally { RtlFreeHeap(RtlGetProcessHeap(), 0, ntPath.Buffer); }
}
writeln(toNtPath(r"\\?\C:")); //Returns the weird string
Update:
I figured out the problem -- see my answer.
RtlDosPathNameToNtPathName_U
is giving you the correct output. The reason you see a weird-looking character in the middle is because UNICODE_STRING
s are not required to be null-terminated (which I'm sure you know already). The file name \??\C:\
is a completely valid native-format file name. I suspect what you really want is to prepend the device name instead of just referring to the GLOBAL??
directory like what RtlDosPathNameToNtPathName_U
has done.
To do that, simply call NtQuerySymbolicLinkObject
on \??\x:
, where x is the drive letter that the path is using, and prepend the result. If it's a UNC path, prepend \Device\Mup
. And so on for the other types of paths (if there are any).
I figured out the problem myself, with @wj32's help: I'd totally forgotten that the input to RtlDosPathNameToNtPathName_U
needed to be null-terminated, and my code didn't handle that properly. Thanks for everyone's help!
精彩评论