31
31
use clone:: Clone ;
32
32
use container:: Container ;
33
33
use libc;
34
- use libc:: { c_char , c_void, c_int} ;
34
+ use libc:: { c_void, c_int} ;
35
35
use option:: { Some , None , Option } ;
36
36
use os;
37
37
use ops:: Drop ;
@@ -49,6 +49,8 @@ use vec::Vec;
49
49
50
50
#[ cfg( unix) ]
51
51
use c_str:: ToCStr ;
52
+ #[ cfg( unix) ]
53
+ use libc:: c_char;
52
54
#[ cfg( windows) ]
53
55
use str:: OwnedStr ;
54
56
@@ -186,22 +188,42 @@ pub fn env_as_bytes() -> Vec<(~[u8],~[u8])> {
186
188
unsafe {
187
189
#[ cfg( windows) ]
188
190
unsafe fn get_env_pairs ( ) -> Vec < ~[ u8 ] > {
189
- use c_str ;
191
+ use slice :: raw ;
190
192
191
193
use libc:: funcs:: extra:: kernel32:: {
192
- GetEnvironmentStringsA ,
193
- FreeEnvironmentStringsA
194
+ GetEnvironmentStringsW ,
195
+ FreeEnvironmentStringsW
194
196
} ;
195
- let ch = GetEnvironmentStringsA ( ) ;
197
+ let ch = GetEnvironmentStringsW ( ) ;
196
198
if ch as uint == 0 {
197
199
fail ! ( "os::env() failure getting env string from OS: {}" ,
198
200
os:: last_os_error( ) ) ;
199
201
}
202
+ // Here, we lossily decode the string as UTF16.
203
+ //
204
+ // The docs suggest that the result should be in Unicode, but
205
+ // Windows doesn't guarantee it's actually UTF16 -- it doesn't
206
+ // validate the environment string passed to CreateProcess nor
207
+ // SetEnvironmentVariable. Yet, it's unlikely that returning a
208
+ // raw u16 buffer would be of practical use since the result would
209
+ // be inherently platform-dependent and introduce additional
210
+ // complexity to this code.
211
+ //
212
+ // Using the non-Unicode version of GetEnvironmentStrings is even
213
+ // worse since the result is in an OEM code page. Characters that
214
+ // can't be encoded in the code page would be turned into question
215
+ // marks.
200
216
let mut result = Vec :: new ( ) ;
201
- c_str:: from_c_multistring ( ch as * c_char , None , |cstr| {
202
- result. push ( cstr. as_bytes_no_nul ( ) . to_owned ( ) ) ;
203
- } ) ;
204
- FreeEnvironmentStringsA ( ch) ;
217
+ let mut i = 0 ;
218
+ while * ch. offset ( i) != 0 {
219
+ let p = & * ch. offset ( i) ;
220
+ let len = ptr:: position ( p, |c| * c == 0 ) ;
221
+ raw:: buf_as_slice ( p, len, |s| {
222
+ result. push ( str:: from_utf16_lossy ( s) . into_bytes ( ) ) ;
223
+ } ) ;
224
+ i += len as int + 1 ;
225
+ }
226
+ FreeEnvironmentStringsW ( ch) ;
205
227
result
206
228
}
207
229
#[ cfg( unix) ]
0 commit comments