| ... | @@ -1715,15 +1715,13 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { | ... | @@ -1715,15 +1715,13 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { |
| 1715 | | 1715 | |
| 1716 | /// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name. | 1716 | /// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name. |
| 1717 | /// See also `getenv`. | 1717 | /// See also `getenv`. |
| 1718 | /// This function first attempts a case-sensitive lookup. If no match is found, and `key` | 1718 | /// This function performs a Unicode-aware case-insensitive lookup using RtlEqualUnicodeString. |
| 1719 | /// is ASCII, then it attempts a second case-insensitive lookup. | | |
| 1720 | pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { | 1719 | pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { |
| 1721 | if (builtin.os.tag != .windows) { | 1720 | if (builtin.os.tag != .windows) { |
| 1722 | @compileError("std.os.getenvW is a Windows-only API"); | 1721 | @compileError("std.os.getenvW is a Windows-only API"); |
| 1723 | } | 1722 | } |
| 1724 | const key_slice = mem.sliceTo(key, 0); | 1723 | const key_slice = mem.sliceTo(key, 0); |
| 1725 | const ptr = windows.peb().ProcessParameters.Environment; | 1724 | const ptr = windows.peb().ProcessParameters.Environment; |
| 1726 | var ascii_match: ?[:0]const u16 = null; | | |
| 1727 | var i: usize = 0; | 1725 | var i: usize = 0; |
| 1728 | while (ptr[i] != 0) { | 1726 | while (ptr[i] != 0) { |
| 1729 | const key_start = i; | 1727 | const key_start = i; |
| ... | @@ -1737,22 +1735,25 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { | ... | @@ -1737,22 +1735,25 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { |
| 1737 | while (ptr[i] != 0) : (i += 1) {} | 1735 | while (ptr[i] != 0) : (i += 1) {} |
| 1738 | const this_value = ptr[value_start..i :0]; | 1736 | const this_value = ptr[value_start..i :0]; |
| 1739 | | 1737 | |
| 1740 | if (mem.eql(u16, key_slice, this_key)) return this_value; | 1738 | const key_string_bytes = @intCast(u16, key_slice.len * 2); |
| 1741 | | 1739 | const key_string = windows.UNICODE_STRING{ |
| 1742 | ascii_check: { | 1740 | .Length = key_string_bytes, |
| 1743 | if (ascii_match != null) break :ascii_check; | 1741 | .MaximumLength = key_string_bytes, |
| 1744 | if (key_slice.len != this_key.len) break :ascii_check; | 1742 | .Buffer = @intToPtr([*]u16, @ptrToInt(key)), |
| 1745 | for (key_slice) |a_c, key_index| { | 1743 | }; |
| 1746 | const a = math.cast(u8, a_c) catch break :ascii_check; | 1744 | const this_key_string_bytes = @intCast(u16, this_key.len * 2); |
| 1747 | const b = math.cast(u8, this_key[key_index]) catch break :ascii_check; | 1745 | const this_key_string = windows.UNICODE_STRING{ |
| 1748 | if (std.ascii.toLower(a) != std.ascii.toLower(b)) break :ascii_check; | 1746 | .Length = this_key_string_bytes, |
| 1749 | } | 1747 | .MaximumLength = this_key_string_bytes, |
| 1750 | ascii_match = this_value; | 1748 | .Buffer = this_key.ptr, |
| | 1749 | }; |
| | 1750 | if (windows.ntdll.RtlEqualUnicodeString(&key_string, &this_key_string, windows.TRUE) == windows.TRUE) { |
| | 1751 | return this_value; |
| 1751 | } | 1752 | } |
| 1752 | | 1753 | |
| 1753 | i += 1; // skip over null byte | 1754 | i += 1; // skip over null byte |
| 1754 | } | 1755 | } |
| 1755 | return ascii_match; | 1756 | return null; |
| 1756 | } | 1757 | } |
| 1757 | | 1758 | |
| 1758 | pub const GetCwdError = error{ | 1759 | pub const GetCwdError = error{ |