From d6c539194c32c363b7a32681eed82446f991befb Mon Sep 17 00:00:00 2001
From: Christofer Nolander <christofer.nolander@gmail.com>
Date: Fri, 14 Apr 2023 16:19:28 +0200
Subject: [PATCH] windows: support UNC paths

Fixes #8205 and #12729.

The old method of prepending `\??\` at the start of the DOS path
produced invalid strings for UNC paths (such as those found in WSL).
Instead, we rely on the conversion routine in ntdll, which should handle
all current and future edge cases properly.
---
 lib/std/os/windows.zig | 43 +++++++++++++-----------------------------
 1 file changed, 13 insertions(+), 30 deletions(-)

diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index 1e6f717bb2ec..b2554f0ca10b 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -1980,37 +1980,20 @@ pub fn cStrToPrefixedFileW(s: [*:0]const u8) !PathSpace {
 pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace {
     // TODO https://github.com/ziglang/zig/issues/2765
     var path_space: PathSpace = undefined;
-    const prefix = "\\??\\";
-    const prefix_index: usize = if (mem.startsWith(u8, s, prefix)) prefix.len else 0;
-    for (s[prefix_index..]) |byte| {
-        switch (byte) {
-            '*', '?', '"', '<', '>', '|' => return error.BadPathName,
-            else => {},
-        }
-    }
-    const prefix_u16 = [_]u16{ '\\', '?', '?', '\\' };
-    const start_index = if (prefix_index > 0 or !std.fs.path.isAbsolute(s)) 0 else blk: {
-        mem.copy(u16, path_space.data[0..], prefix_u16[0..]);
-        break :blk prefix_u16.len;
-    };
-    path_space.len = start_index + try std.unicode.utf8ToUtf16Le(path_space.data[start_index..], s);
-    if (path_space.len > path_space.data.len) return error.NameTooLong;
-    path_space.len = start_index + (normalizePath(u16, path_space.data[start_index..path_space.len]) catch |err| switch (err) {
-        error.TooManyParentDirs => {
-            if (!std.fs.path.isAbsolute(s)) {
-                var temp_path: PathSpace = undefined;
-                temp_path.len = try std.unicode.utf8ToUtf16Le(&temp_path.data, s);
-                std.debug.assert(temp_path.len == path_space.len);
-                temp_path.data[path_space.len] = 0;
-                path_space.len = prefix_u16.len + try getFullPathNameW(&temp_path.data, path_space.data[prefix_u16.len..]);
-                mem.copy(u16, &path_space.data, &prefix_u16);
-                std.debug.assert(path_space.data[path_space.len] == 0);
-                return path_space;
-            }
-            return error.BadPathName;
-        },
-    });
+
+    path_space.len = try std.unicode.utf8ToUtf16Le(&path_space.data, s);
     path_space.data[path_space.len] = 0;
+
+    var out: UNICODE_STRING = undefined;
+    if (ntdll.RtlDosPathNameToNtPathName_U(path_space.span(), &out, null, null) == FALSE)
+        return error.BadPathName;
+    defer ntdll.RtlFreeUnicodeString(&out);
+
+    const out_path = out.Buffer[0 .. out.Length / 2];
+    mem.copy(u16, path_space.data[0..], out_path);
+    path_space.len = out.Length / 2;
+    path_space.data[path_space.len] = 0;
+
     return path_space;
 }