| ... | ... | @@ -1883,19 +1883,23 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { |
| 1883 | 1883 | |
| 1884 | 1884 | /// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name. |
| 1885 | 1885 | /// See also `getenv`. |
| 1886 | | /// This function first attempts a case-sensitive lookup. If no match is found, and `key` |
| 1887 | | /// is ASCII, then it attempts a second case-insensitive lookup. |
| 1886 | /// This function performs a Unicode-aware case-insensitive lookup using RtlEqualUnicodeString. |
| 1888 | 1887 | pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { |
| 1889 | 1888 | if (builtin.os.tag != .windows) { |
| 1890 | 1889 | @compileError("std.os.getenvW is a Windows-only API"); |
| 1891 | 1890 | } |
| 1892 | 1891 | const key_slice = mem.sliceTo(key, 0); |
| 1893 | 1892 | const ptr = windows.peb().ProcessParameters.Environment; |
| 1894 | | var ascii_match: ?[:0]const u16 = null; |
| 1895 | 1893 | var i: usize = 0; |
| 1896 | 1894 | while (ptr[i] != 0) { |
| 1897 | 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 | 1903 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} |
| 1900 | 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 | 1909 | while (ptr[i] != 0) : (i += 1) {} |
| 1906 | 1910 | const this_value = ptr[value_start..i :0]; |
| 1907 | 1911 | |
| 1908 | | if (mem.eql(u16, key_slice, this_key)) return this_value; |
| 1909 | | |
| 1910 | | ascii_check: { |
| 1911 | | if (ascii_match != null) break :ascii_check; |
| 1912 | | if (key_slice.len != this_key.len) break :ascii_check; |
| 1913 | | for (key_slice) |a_c, key_index| { |
| 1914 | | const a = math.cast(u8, a_c) catch break :ascii_check; |
| 1915 | | const b = math.cast(u8, this_key[key_index]) catch break :ascii_check; |
| 1916 | | if (std.ascii.toLower(a) != std.ascii.toLower(b)) break :ascii_check; |
| 1917 | | } |
| 1918 | | ascii_match = this_value; |
| 1912 | const key_string_bytes = @intCast(u16, key_slice.len * 2); |
| 1913 | const key_string = windows.UNICODE_STRING{ |
| 1914 | .Length = key_string_bytes, |
| 1915 | .MaximumLength = key_string_bytes, |
| 1916 | .Buffer = @intToPtr([*]u16, @ptrToInt(key)), |
| 1917 | }; |
| 1918 | const this_key_string_bytes = @intCast(u16, this_key.len * 2); |
| 1919 | const this_key_string = windows.UNICODE_STRING{ |
| 1920 | .Length = this_key_string_bytes, |
| 1921 | .MaximumLength = this_key_string_bytes, |
| 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 | 1928 | i += 1; // skip over null byte |
| 1922 | 1929 | } |
| 1923 | | return ascii_match; |
| 1930 | return null; |
| 1924 | 1931 | } |
| 1925 | 1932 | |
| 1926 | 1933 | pub const GetCwdError = error{ |