Function ntToWin32Namespace [src]
Similar to RtlNtPathNameToDosPathName but does not do any heap allocation.
The possible transformations are:
??\C:\Some\Path -> C:\Some\Path
??\UNC\server\share\foo -> \server\share\foo
If the path does not have the NT namespace prefix, then error.NotNtPath is returned.
Functionality is based on the ReactOS test cases found here:
https://github.com/reactos/reactos/blob/master/modules/rostests/apitests/ntdll/RtlNtPathNameToDosPathName.c
path should be encoded as WTF-16LE.
Prototype
pub fn ntToWin32Namespace(path: []const u16) !PathSpace
Parameters
path: []const u16
Example
test ntToWin32Namespace {
const L = std.unicode.utf8ToUtf16LeStringLiteral;
try testNtToWin32Namespace(L("UNC"), L("\\??\\UNC"));
try testNtToWin32Namespace(L("\\\\"), L("\\??\\UNC\\"));
try testNtToWin32Namespace(L("\\\\path1"), L("\\??\\UNC\\path1"));
try testNtToWin32Namespace(L("\\\\path1\\path2"), L("\\??\\UNC\\path1\\path2"));
try testNtToWin32Namespace(L(""), L("\\??\\"));
try testNtToWin32Namespace(L("C:"), L("\\??\\C:"));
try testNtToWin32Namespace(L("C:\\"), L("\\??\\C:\\"));
try testNtToWin32Namespace(L("C:\\test"), L("\\??\\C:\\test"));
try testNtToWin32Namespace(L("C:\\test\\"), L("\\??\\C:\\test\\"));
try std.testing.expectError(error.NotNtPath, ntToWin32Namespace(L("foo")));
try std.testing.expectError(error.NotNtPath, ntToWin32Namespace(L("C:\\test")));
try std.testing.expectError(error.NotNtPath, ntToWin32Namespace(L("\\\\.\\test")));
}
Source
pub fn ntToWin32Namespace(path: []const u16) !PathSpace {
if (path.len > PATH_MAX_WIDE) return error.NameTooLong;
var path_space: PathSpace = undefined;
const namespace_prefix = getNamespacePrefix(u16, path);
switch (namespace_prefix) {
.nt => {
var dest_index: usize = 0;
var after_prefix = path[4..]; // after the `\??\`
// The prefix \??\UNC\ means this is a UNC path, in which case the
// `\??\UNC\` should be replaced by `\\` (two backslashes)
// TODO: the "UNC" should technically be matched case-insensitively, but
// it's unlikely to matter since most/all paths passed into this
// function will have come from the OS meaning it should have
// the 'canonical' uppercase UNC.
const is_unc = after_prefix.len >= 4 and
std.mem.eql(u16, after_prefix[0..3], std.unicode.utf8ToUtf16LeStringLiteral("UNC")) and
std.fs.path.PathType.windows.isSep(u16, std.mem.littleToNative(u16, after_prefix[3]));
if (is_unc) {
path_space.data[0] = comptime std.mem.nativeToLittle(u16, '\\');
dest_index += 1;
// We want to include the last `\` of `\??\UNC\`
after_prefix = path[7..];
}
@memcpy(path_space.data[dest_index..][0..after_prefix.len], after_prefix);
path_space.len = dest_index + after_prefix.len;
path_space.data[path_space.len] = 0;
return path_space;
},
else => return error.NotNtPath,
}
}