diff options
| author | bors <bors@rust-lang.org> | 2014-05-13 16:01:48 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-05-13 16:01:48 -0700 |
| commit | cb115ac2d4f57d8b590c8d46d8f9e2958ed9a527 (patch) | |
| tree | 125dfe2d8e2f62ac6ce9b51e32b80b485086f2b8 /src/libstd | |
| parent | 5ad42b3ae97fd363b1a13c43305995fe139fc8ef (diff) | |
| parent | b8e3f3a41715a7de7e32eb32456aa25132c8ff46 (diff) | |
| download | rust-cb115ac2d4f57d8b590c8d46d8f9e2958ed9a527.tar.gz rust-cb115ac2d4f57d8b590c8d46d8f9e2958ed9a527.zip | |
auto merge of #14075 : Rufflewind/rust/patch-3, r=alexcrichton
- Use Unicode-aware versions of `CreateProcess` (Fixes #13815) and `Get/FreeEnvironmentStrings`.
- Includes a helper function `os::win32::as_mut_utf16_p`, which does the same thing as `os::win32::as_utf16_p` except the pointer is mutable.
- Fixed `make_command_line` to handle Unicode correctly.
- Tests for the above.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/os.rs | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/src/libstd/os.rs b/src/libstd/os.rs index f7324dc08b6..0a920a275ac 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -31,7 +31,7 @@ use clone::Clone; use container::Container; use libc; -use libc::{c_char, c_void, c_int}; +use libc::{c_void, c_int}; use option::{Some, None, Option}; use os; use ops::Drop; @@ -49,6 +49,8 @@ use vec::Vec; #[cfg(unix)] use c_str::ToCStr; +#[cfg(unix)] +use libc::c_char; #[cfg(windows)] use str::OwnedStr; @@ -141,10 +143,14 @@ pub mod win32 { } pub fn as_utf16_p<T>(s: &str, f: |*u16| -> T) -> T { + as_mut_utf16_p(s, |t| { f(t as *u16) }) + } + + pub fn as_mut_utf16_p<T>(s: &str, f: |*mut u16| -> T) -> T { let mut t = s.to_utf16(); // Null terminate before passing on. t.push(0u16); - f(t.as_ptr()) + f(t.as_mut_ptr()) } } @@ -182,22 +188,42 @@ pub fn env_as_bytes() -> Vec<(~[u8],~[u8])> { unsafe { #[cfg(windows)] unsafe fn get_env_pairs() -> Vec<~[u8]> { - use c_str; + use slice::raw; use libc::funcs::extra::kernel32::{ - GetEnvironmentStringsA, - FreeEnvironmentStringsA + GetEnvironmentStringsW, + FreeEnvironmentStringsW }; - let ch = GetEnvironmentStringsA(); + let ch = GetEnvironmentStringsW(); if ch as uint == 0 { fail!("os::env() failure getting env string from OS: {}", os::last_os_error()); } + // Here, we lossily decode the string as UTF16. + // + // The docs suggest that the result should be in Unicode, but + // Windows doesn't guarantee it's actually UTF16 -- it doesn't + // validate the environment string passed to CreateProcess nor + // SetEnvironmentVariable. Yet, it's unlikely that returning a + // raw u16 buffer would be of practical use since the result would + // be inherently platform-dependent and introduce additional + // complexity to this code. + // + // Using the non-Unicode version of GetEnvironmentStrings is even + // worse since the result is in an OEM code page. Characters that + // can't be encoded in the code page would be turned into question + // marks. let mut result = Vec::new(); - c_str::from_c_multistring(ch as *c_char, None, |cstr| { - result.push(cstr.as_bytes_no_nul().to_owned()); - }); - FreeEnvironmentStringsA(ch); + let mut i = 0; + while *ch.offset(i) != 0 { + let p = &*ch.offset(i); + let len = ptr::position(p, |c| *c == 0); + raw::buf_as_slice(p, len, |s| { + result.push(str::from_utf16_lossy(s).into_bytes()); + }); + i += len as int + 1; + } + FreeEnvironmentStringsW(ch); result } #[cfg(unix)] |
