| ... | @@ -1883,19 +1883,23 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { | ... | @@ -1883,19 +1883,23 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { |
| 1883 | | 1883 | |
| 1884 | /// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name. | 1884 | /// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name. |
| 1885 | /// See also `getenv`. | 1885 | /// See also `getenv`. |
| 1886 | /// This function first attempts a case-sensitive lookup. If no match is found, and `key` | 1886 | /// This function performs a Unicode-aware case-insensitive lookup using RtlEqualUnicodeString. |
| 1887 | /// is ASCII, then it attempts a second case-insensitive lookup. | | |
| 1888 | pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { | 1887 | pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { |
| 1889 | if (builtin.os.tag != .windows) { | 1888 | if (builtin.os.tag != .windows) { |
| 1890 | @compileError("std.os.getenvW is a Windows-only API"); | 1889 | @compileError("std.os.getenvW is a Windows-only API"); |
| 1891 | } | 1890 | } |
| 1892 | const key_slice = mem.sliceTo(key, 0); | 1891 | const key_slice = mem.sliceTo(key, 0); |
| 1893 | const ptr = windows.peb().ProcessParameters.Environment; | 1892 | const ptr = windows.peb().ProcessParameters.Environment; |
| 1894 | var ascii_match: ?[:0]const u16 = null; | | |
| 1895 | var i: usize = 0; | 1893 | var i: usize = 0; |
| 1896 | while (ptr[i] != 0) { | 1894 | while (ptr[i] != 0) { |
| 1897 | const key_start = i; | 1895 | const key_start = i; |
| 1898 | | 1896 | |
| | 1897 | // There are some special environment variables that start with =, |
| | 1898 | // so we need a special case to not treat = as a key/value separator |
| | 1899 | // if it's the first character. |
| | 1900 | // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 |
| | 1901 | if (ptr[key_start] == '=') i += 1; |
| | 1902 | |
| 1899 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} | 1903 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} |
| 1900 | const this_key = ptr[key_start..i]; | 1904 | const this_key = ptr[key_start..i]; |
| 1901 | | 1905 | |
| ... | @@ -1905,22 +1909,25 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { | ... | @@ -1905,22 +1909,25 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { |
| 1905 | while (ptr[i] != 0) : (i += 1) {} | 1909 | while (ptr[i] != 0) : (i += 1) {} |
| 1906 | const this_value = ptr[value_start..i :0]; | 1910 | const this_value = ptr[value_start..i :0]; |
| 1907 | | 1911 | |
| 1908 | if (mem.eql(u16, key_slice, this_key)) return this_value; | 1912 | const key_string_bytes = @intCast(u16, key_slice.len * 2); |
| 1909 | | 1913 | const key_string = windows.UNICODE_STRING{ |
| 1910 | ascii_check: { | 1914 | .Length = key_string_bytes, |
| 1911 | if (ascii_match != null) break :ascii_check; | 1915 | .MaximumLength = key_string_bytes, |
| 1912 | if (key_slice.len != this_key.len) break :ascii_check; | 1916 | .Buffer = @intToPtr([*]u16, @ptrToInt(key)), |
| 1913 | for (key_slice) |a_c, key_index| { | 1917 | }; |
| 1914 | const a = math.cast(u8, a_c) catch break :ascii_check; | 1918 | const this_key_string_bytes = @intCast(u16, this_key.len * 2); |
| 1915 | const b = math.cast(u8, this_key[key_index]) catch break :ascii_check; | 1919 | const this_key_string = windows.UNICODE_STRING{ |
| 1916 | if (std.ascii.toLower(a) != std.ascii.toLower(b)) break :ascii_check; | 1920 | .Length = this_key_string_bytes, |
| 1917 | } | 1921 | .MaximumLength = this_key_string_bytes, |
| 1918 | ascii_match = this_value; | 1922 | .Buffer = this_key.ptr, |
| | 1923 | }; |
| | 1924 | if (windows.ntdll.RtlEqualUnicodeString(&key_string, &this_key_string, windows.TRUE) == windows.TRUE) { |
| | 1925 | return this_value; |
| 1919 | } | 1926 | } |
| 1920 | | 1927 | |
| 1921 | i += 1; // skip over null byte | 1928 | i += 1; // skip over null byte |
| 1922 | } | 1929 | } |
| 1923 | return ascii_match; | 1930 | return null; |
| 1924 | } | 1931 | } |
| 1925 | | 1932 | |
| 1926 | pub const GetCwdError = error{ | 1933 | pub const GetCwdError = error{ |