about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-02-03 03:44:05 +0000
committerbors <bors@rust-lang.org>2015-02-03 03:44:05 +0000
commit7858cb432d3f2efc0374424cb2b51518f697c172 (patch)
treebccd460a861e61f758d2d459cb9da02b1ad8792b /src/libstd/sys/windows
parenteaf4c5c784637f3df8bdebc6ec21dbd4bc69420a (diff)
parent9ece22ee00033cdf0b6b418c451112c92c8ad922 (diff)
downloadrust-7858cb432d3f2efc0374424cb2b51518f697c172.tar.gz
rust-7858cb432d3f2efc0374424cb2b51518f697c172.zip
Auto merge of #21872 - alexcrichton:rollup, r=alexcrichton
Diffstat (limited to 'src/libstd/sys/windows')
-rw-r--r--src/libstd/sys/windows/backtrace.rs34
-rw-r--r--src/libstd/sys/windows/c.rs190
-rw-r--r--src/libstd/sys/windows/fs.rs20
-rw-r--r--src/libstd/sys/windows/handle.rs31
-rw-r--r--src/libstd/sys/windows/mod.rs111
-rw-r--r--src/libstd/sys/windows/mutex.rs2
-rw-r--r--src/libstd/sys/windows/os.rs453
-rw-r--r--src/libstd/sys/windows/pipe.rs18
-rw-r--r--src/libstd/sys/windows/process.rs32
-rw-r--r--src/libstd/sys/windows/rwlock.rs3
-rw-r--r--src/libstd/sys/windows/stack_overflow.rs10
-rw-r--r--src/libstd/sys/windows/sync.rs2
-rw-r--r--src/libstd/sys/windows/tcp.rs9
-rw-r--r--src/libstd/sys/windows/thread.rs2
-rw-r--r--src/libstd/sys/windows/thread_local.rs3
-rw-r--r--src/libstd/sys/windows/timer.rs2
-rw-r--r--src/libstd/sys/windows/tty.rs5
17 files changed, 573 insertions, 354 deletions
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs
index 1be1a412ffa..66712b9e3a1 100644
--- a/src/libstd/sys/windows/backtrace.rs
+++ b/src/libstd/sys/windows/backtrace.rs
@@ -7,29 +7,31 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-/// As always, windows has something very different than unix, we mainly want
-/// to avoid having to depend too much on libunwind for windows.
-///
-/// If you google around, you'll find a fair bit of references to built-in
-/// functions to get backtraces on windows. It turns out that most of these are
-/// in an external library called dbghelp. I was unable to find this library
-/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
-/// of it.
-///
-/// You'll also find that there's a function called CaptureStackBackTrace
-/// mentioned frequently (which is also easy to use), but sadly I didn't have a
-/// copy of that function in my mingw install (maybe it was broken?). Instead,
-/// this takes the route of using StackWalk64 in order to walk the stack.
+
+//! As always, windows has something very different than unix, we mainly want
+//! to avoid having to depend too much on libunwind for windows.
+//!
+//! If you google around, you'll find a fair bit of references to built-in
+//! functions to get backtraces on windows. It turns out that most of these are
+//! in an external library called dbghelp. I was unable to find this library
+//! via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
+//! of it.
+//!
+//! You'll also find that there's a function called CaptureStackBackTrace
+//! mentioned frequently (which is also easy to use), but sadly I didn't have a
+//! copy of that function in my mingw install (maybe it was broken?). Instead,
+//! this takes the route of using StackWalk64 in order to walk the stack.
+
+#![allow(dead_code)]
 
 use dynamic_lib::DynamicLibrary;
 use ffi;
-use core::ops::Index;
 use intrinsics;
 use old_io::{IoResult, Writer};
 use libc;
 use mem;
 use ops::Drop;
-use option::Option::{Some, None};
+use option::Option::{Some};
 use path::Path;
 use ptr;
 use result::Result::{Ok, Err};
@@ -296,7 +298,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
     // According to windows documentation, all dbghelp functions are
     // single-threaded.
     static LOCK: StaticMutex = MUTEX_INIT;
-    let _g = unsafe { LOCK.lock() };
+    let _g = LOCK.lock();
 
     // Open up dbghelp.dll, we don't link to it explicitly because it can't
     // always be found. Additionally, it's nice having fewer dependencies.
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index da3b7ee2f2f..0355565cf00 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -10,17 +10,21 @@
 
 //! C definitions used by libnative that don't belong in liblibc
 
-#![allow(overflowing_literals)]
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
+#![allow(bad_style, dead_code, overflowing_literals)]
 
 use libc;
-use prelude::v1::*;
 
-pub const WSADESCRIPTION_LEN: uint = 256;
-pub const WSASYS_STATUS_LEN: uint = 128;
+pub use self::GET_FILEEX_INFO_LEVELS::*;
+pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
+pub use libc::consts::os::extra::{
+    FILE_ATTRIBUTE_READONLY,
+    FILE_ATTRIBUTE_DIRECTORY,
+};
+
+pub const WSADESCRIPTION_LEN: usize = 256;
+pub const WSASYS_STATUS_LEN: usize = 128;
 pub const FIONBIO: libc::c_long = 0x8004667e;
-pub const FD_SETSIZE: uint = 64;
+pub const FD_SETSIZE: usize = 64;
 pub const MSG_DONTWAIT: libc::c_int = 0;
 pub const ERROR_ILLEGAL_CHARACTER: libc::c_int = 582;
 pub const ENABLE_ECHO_INPUT: libc::DWORD = 0x4;
@@ -32,12 +36,15 @@ pub const ENABLE_QUICK_EDIT_MODE: libc::DWORD = 0x40;
 pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT;
 
 pub const FD_ACCEPT: libc::c_long = 0x08;
-pub const FD_MAX_EVENTS: uint = 10;
+pub const FD_MAX_EVENTS: usize = 10;
 pub const WSA_INFINITE: libc::DWORD = libc::INFINITE;
 pub const WSA_WAIT_TIMEOUT: libc::DWORD = libc::consts::os::extra::WAIT_TIMEOUT;
 pub const WSA_WAIT_EVENT_0: libc::DWORD = libc::consts::os::extra::WAIT_OBJECT_0;
 pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED;
 
+pub const ERROR_NO_MORE_FILES: libc::DWORD = 18;
+pub const TOKEN_READ: libc::DWORD = 0x20008;
+
 #[repr(C)]
 #[cfg(target_arch = "x86")]
 pub struct WSADATA {
@@ -80,7 +87,7 @@ pub struct fd_set {
 }
 
 pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) {
-    set.fd_array[set.fd_count as uint] = s;
+    set.fd_array[set.fd_count as usize] = s;
     set.fd_count += 1;
 }
 
@@ -110,6 +117,69 @@ pub struct CONSOLE_SCREEN_BUFFER_INFO {
 }
 pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
 
+#[repr(C)]
+pub struct WIN32_FILE_ATTRIBUTE_DATA {
+    pub dwFileAttributes: libc::DWORD,
+    pub ftCreationTime: libc::FILETIME,
+    pub ftLastAccessTime: libc::FILETIME,
+    pub ftLastWriteTime: libc::FILETIME,
+    pub nFileSizeHigh: libc::DWORD,
+    pub nFileSizeLow: libc::DWORD,
+}
+
+#[repr(C)]
+pub struct BY_HANDLE_FILE_INFORMATION {
+    pub dwFileAttributes: libc::DWORD,
+    pub ftCreationTime: libc::FILETIME,
+    pub ftLastAccessTime: libc::FILETIME,
+    pub ftLastWriteTime: libc::FILETIME,
+    pub dwVolumeSerialNumber: libc::DWORD,
+    pub nFileSizeHigh: libc::DWORD,
+    pub nFileSizeLow: libc::DWORD,
+    pub nNumberOfLinks: libc::DWORD,
+    pub nFileIndexHigh: libc::DWORD,
+    pub nFileIndexLow: libc::DWORD,
+}
+
+pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
+
+#[repr(C)]
+pub enum GET_FILEEX_INFO_LEVELS {
+    GetFileExInfoStandard,
+    GetFileExMaxInfoLevel
+}
+
+#[repr(C)]
+pub enum FILE_INFO_BY_HANDLE_CLASS {
+    FileBasicInfo                   = 0,
+    FileStandardInfo                = 1,
+    FileNameInfo                    = 2,
+    FileRenameInfo                  = 3,
+    FileDispositionInfo             = 4,
+    FileAllocationInfo              = 5,
+    FileEndOfFileInfo               = 6,
+    FileStreamInfo                  = 7,
+    FileCompressionInfo             = 8,
+    FileAttributeTagInfo            = 9,
+    FileIdBothDirectoryInfo         = 10, // 0xA
+    FileIdBothDirectoryRestartInfo  = 11, // 0xB
+    FileIoPriorityHintInfo          = 12, // 0xC
+    FileRemoteProtocolInfo          = 13, // 0xD
+    FileFullDirectoryInfo           = 14, // 0xE
+    FileFullDirectoryRestartInfo    = 15, // 0xF
+    FileStorageInfo                 = 16, // 0x10
+    FileAlignmentInfo               = 17, // 0x11
+    FileIdInfo                      = 18, // 0x12
+    FileIdExtdDirectoryInfo         = 19, // 0x13
+    FileIdExtdDirectoryRestartInfo  = 20, // 0x14
+    MaximumFileInfoByHandlesClass
+}
+
+#[repr(C)]
+pub struct FILE_END_OF_FILE_INFO {
+    pub EndOfFile: libc::LARGE_INTEGER,
+}
+
 #[link(name = "ws2_32")]
 extern "system" {
     pub fn WSAStartup(wVersionRequested: libc::WORD,
@@ -156,31 +226,29 @@ extern "system" {
 }
 
 pub mod compat {
-    use intrinsics::{atomic_store_relaxed, transmute};
-    use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
     use prelude::v1::*;
+
     use ffi::CString;
+    use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
+    use sync::atomic::{AtomicUsize, Ordering};
 
     extern "system" {
         fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
         fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
     }
 
-    // store_func() is idempotent, so using relaxed ordering for the atomics
-    // should be enough.  This way, calling a function in this compatibility
-    // layer (after it's loaded) shouldn't be any slower than a regular DLL
-    // call.
-    unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) {
+    fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
+                  fallback: usize) -> usize {
         let mut module: Vec<u16> = module.utf16_units().collect();
         module.push(0);
         let symbol = CString::from_slice(symbol.as_bytes());
-        let handle = GetModuleHandleW(module.as_ptr());
-        let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr()));
-        atomic_store_relaxed(ptr, if func == 0 {
-            fallback
-        } else {
-            func
-        })
+        let func = unsafe {
+            let handle = GetModuleHandleW(module.as_ptr());
+            GetProcAddress(handle, symbol.as_ptr()) as usize
+        };
+        let value = if func == 0 {fallback} else {func};
+        ptr.store(value, Ordering::SeqCst);
+        value
     }
 
     /// Macro for creating a compatibility fallback for a Windows function
@@ -192,29 +260,36 @@ pub mod compat {
     /// })
     /// ```
     ///
-    /// Note that arguments unused by the fallback implementation should not be called `_` as
-    /// they are used to be passed to the real function if available.
+    /// Note that arguments unused by the fallback implementation should not be
+    /// called `_` as they are used to be passed to the real function if
+    /// available.
     macro_rules! compat_fn {
         ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
                                       -> $rettype:ty { $fallback:expr }) => (
             #[inline(always)]
             pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
-                static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk;
-
-                extern "system" fn thunk($($argname: $argtype),*) -> $rettype {
-                    unsafe {
-                        ::sys::c::compat::store_func(&mut ptr as *mut _ as *mut uint,
-                                                    stringify!($module),
-                                                    stringify!($symbol),
-                                                    fallback as uint);
-                        ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
-                    }
+                use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+                use mem;
+
+                static PTR: AtomicUsize = ATOMIC_USIZE_INIT;
+
+                fn load() -> usize {
+                    ::sys::c::compat::store_func(&PTR,
+                                                 stringify!($module),
+                                                 stringify!($symbol),
+                                                 fallback as usize)
                 }
 
                 extern "system" fn fallback($($argname: $argtype),*)
                                             -> $rettype { $fallback }
 
-                ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
+                let addr = match PTR.load(Ordering::SeqCst) {
+                    0 => load(),
+                    n => n,
+                };
+                let f: extern "system" fn($($argtype),*) -> $rettype =
+                    mem::transmute(addr);
+                f($($argname),*)
             }
         )
     }
@@ -229,10 +304,7 @@ pub mod compat {
         use libc::c_uint;
         use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
         use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
-
-        extern "system" {
-            fn SetLastError(dwErrCode: DWORD);
-        }
+        use sys::c::SetLastError;
 
         compat_fn! {
             kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
@@ -282,4 +354,42 @@ extern "system" {
         hConsoleOutput: libc::HANDLE,
         lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO,
     ) -> libc::BOOL;
+
+    pub fn GetFileAttributesExW(lpFileName: libc::LPCWSTR,
+                                fInfoLevelId: GET_FILEEX_INFO_LEVELS,
+                                lpFileInformation: libc::LPVOID) -> libc::BOOL;
+    pub fn RemoveDirectoryW(lpPathName: libc::LPCWSTR) -> libc::BOOL;
+    pub fn SetFileAttributesW(lpFileName: libc::LPCWSTR,
+                              dwFileAttributes: libc::DWORD) -> libc::BOOL;
+    pub fn GetFileAttributesW(lpFileName: libc::LPCWSTR) -> libc::DWORD;
+    pub fn GetFileInformationByHandle(hFile: libc::HANDLE,
+                            lpFileInformation: LPBY_HANDLE_FILE_INFORMATION)
+                            -> libc::BOOL;
+
+    pub fn SetLastError(dwErrCode: libc::DWORD);
+    pub fn GetCommandLineW() -> *mut libc::LPCWSTR;
+    pub fn LocalFree(ptr: *mut libc::c_void);
+    pub fn CommandLineToArgvW(lpCmdLine: *mut libc::LPCWSTR,
+                              pNumArgs: *mut libc::c_int) -> *mut *mut u16;
+    pub fn SetFileTime(hFile: libc::HANDLE,
+                       lpCreationTime: *const libc::FILETIME,
+                       lpLastAccessTime: *const libc::FILETIME,
+                       lpLastWriteTime: *const libc::FILETIME) -> libc::BOOL;
+    pub fn SetFileInformationByHandle(hFile: libc::HANDLE,
+                    FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
+                    lpFileInformation: libc::LPVOID,
+                    dwBufferSize: libc::DWORD) -> libc::BOOL;
+    pub fn GetTempPathW(nBufferLength: libc::DWORD,
+                        lpBuffer: libc::LPCWSTR) -> libc::DWORD;
+    pub fn OpenProcessToken(ProcessHandle: libc::HANDLE,
+                            DesiredAccess: libc::DWORD,
+                            TokenHandle: *mut libc::HANDLE) -> libc::BOOL;
+    pub fn GetCurrentProcess() -> libc::HANDLE;
+}
+
+#[link(name = "userenv")]
+extern "system" {
+    pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE,
+                                    lpProfileDir: libc::LPCWSTR,
+                                    lpcchSize: *mut libc::DWORD) -> libc::BOOL;
 }
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 80cdf9782f2..304d7e01532 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -10,20 +10,15 @@
 
 //! Blocking Windows-based file I/O
 
-use alloc::arc::Arc;
 use libc::{self, c_int};
 
 use mem;
-use sys::os::fill_utf16_buf_and_decode;
-use path;
 use ptr;
-use str;
 use old_io;
 
 use prelude::v1::*;
 use sys;
-use sys::os;
-use sys_common::{keep_going, eof, mkerr_libc};
+use sys_common::{mkerr_libc};
 
 use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
 use old_io::{IoResult, IoError, FileStat, SeekStyle};
@@ -262,7 +257,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
             let mut more_files = 1 as libc::BOOL;
             while more_files != 0 {
                 {
-                    let filename = os::truncate_utf16_at_nul(&wfd.cFileName);
+                    let filename = super::truncate_utf16_at_nul(&wfd.cFileName);
                     match String::from_utf16(filename) {
                         Ok(filename) => paths.push(Path::new(filename)),
                         Err(..) => {
@@ -368,19 +363,12 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
     }
     // Specify (sz - 1) because the documentation states that it's the size
     // without the null pointer
-    let ret = fill_utf16_buf_and_decode(|buf, sz| unsafe {
+    let ret = super::fill_utf16_buf(|buf, sz| unsafe {
         GetFinalPathNameByHandleW(handle,
                                   buf as *const u16,
                                   sz - 1,
                                   libc::VOLUME_NAME_DOS)
-    });
-    let ret = match ret {
-        Some(ref s) if s.starts_with(r"\\?\") => { // "
-            Ok(Path::new(&s[4..]))
-        }
-        Some(s) => Ok(Path::new(s)),
-        None => Err(super::last_error()),
-    };
+    }, super::os2path);
     assert!(unsafe { libc::CloseHandle(handle) } != 0);
     return ret;
 }
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
new file mode 100644
index 00000000000..6737eeef125
--- /dev/null
+++ b/src/libstd/sys/windows/handle.rs
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use prelude::v1::*;
+
+use libc::{self, HANDLE};
+
+pub struct Handle(HANDLE);
+
+unsafe impl Send for Handle {}
+unsafe impl Sync for Handle {}
+
+impl Handle {
+    pub fn new(handle: HANDLE) -> Handle {
+        Handle(handle)
+    }
+}
+
+impl Drop for Handle {
+    fn drop(&mut self) {
+        unsafe { let _ = libc::CloseHandle(self.0); }
+    }
+}
+
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index e8b65c9b64e..8dd467eba9e 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -11,18 +11,14 @@
 #![allow(missing_docs)]
 #![allow(non_camel_case_types)]
 #![allow(non_snake_case)]
-#![allow(unused_imports)]
-#![allow(dead_code)]
-#![allow(unused_unsafe)]
-#![allow(unused_mut)]
-
-extern crate libc;
 
 use prelude::v1::*;
 
-use num;
+use ffi::OsStr;
+use libc;
 use mem;
 use old_io::{self, IoResult, IoError};
+use os::windows::OsStrExt;
 use sync::{Once, ONCE_INIT};
 
 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
@@ -38,9 +34,10 @@ macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
 
 pub mod backtrace;
 pub mod c;
-pub mod ext;
 pub mod condvar;
+pub mod ext;
 pub mod fs;
+pub mod handle;
 pub mod helper_signal;
 pub mod mutex;
 pub mod os;
@@ -48,12 +45,12 @@ pub mod os_str;
 pub mod pipe;
 pub mod process;
 pub mod rwlock;
-pub mod sync;
 pub mod stack_overflow;
+pub mod sync;
 pub mod tcp;
-pub mod time;
 pub mod thread;
 pub mod thread_local;
+pub mod time;
 pub mod timer;
 pub mod tty;
 pub mod udp;
@@ -158,7 +155,7 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval {
 
 pub fn wouldblock() -> bool {
     let err = os::errno();
-    err == libc::WSAEWOULDBLOCK as uint
+    err == libc::WSAEWOULDBLOCK as i32
 }
 
 pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
@@ -191,17 +188,93 @@ pub fn unimpl() -> IoError {
     }
 }
 
-pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
+fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
     match s {
-        Some(s) => Ok({
-            let mut s = s.utf16_units().collect::<Vec<u16>>();
-            s.push(0);
-            s
-        }),
+        Some(s) => Ok(to_utf16_os(OsStr::from_str(s))),
         None => Err(IoError {
             kind: old_io::InvalidInput,
             desc: "valid unicode input required",
-            detail: None
-        })
+            detail: None,
+        }),
+    }
+}
+
+fn to_utf16_os(s: &OsStr) -> Vec<u16> {
+    let mut v: Vec<_> = s.encode_wide().collect();
+    v.push(0);
+    v
+}
+
+// Many Windows APIs follow a pattern of where we hand the a buffer and then
+// they will report back to us how large the buffer should be or how many bytes
+// currently reside in the buffer. This function is an abstraction over these
+// functions by making them easier to call.
+//
+// The first callback, `f1`, is yielded a (pointer, len) pair which can be
+// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case).
+// The closure is expected to return what the syscall returns which will be
+// interpreted by this function to determine if the syscall needs to be invoked
+// again (with more buffer space).
+//
+// Once the syscall has completed (errors bail out early) the second closure is
+// yielded the data which has been read from the syscall. The return value
+// from this closure is then the return value of the function.
+fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> IoResult<T>
+    where F1: FnMut(*mut u16, libc::DWORD) -> libc::DWORD,
+          F2: FnOnce(&[u16]) -> T
+{
+    // Start off with a stack buf but then spill over to the heap if we end up
+    // needing more space.
+    let mut stack_buf = [0u16; 512];
+    let mut heap_buf = Vec::new();
+    unsafe {
+        let mut n = stack_buf.len();
+        loop {
+            let buf = if n <= stack_buf.len() {
+                &mut stack_buf[]
+            } else {
+                let extra = n - heap_buf.len();
+                heap_buf.reserve(extra);
+                heap_buf.set_len(n);
+                &mut heap_buf[]
+            };
+
+            // This function is typically called on windows API functions which
+            // will return the correct length of the string, but these functions
+            // also return the `0` on error. In some cases, however, the
+            // returned "correct length" may actually be 0!
+            //
+            // To handle this case we call `SetLastError` to reset it to 0 and
+            // then check it again if we get the "0 error value". If the "last
+            // error" is still 0 then we interpret it as a 0 length buffer and
+            // not an actual error.
+            c::SetLastError(0);
+            let k = match f1(buf.as_mut_ptr(), n as libc::DWORD) {
+                0 if libc::GetLastError() == 0 => 0,
+                0 => return Err(IoError::last_error()),
+                n => n,
+            } as usize;
+            if k == n && libc::GetLastError() ==
+                            libc::ERROR_INSUFFICIENT_BUFFER as libc::DWORD {
+                n *= 2;
+            } else if k >= n {
+                n = k;
+            } else {
+                return Ok(f2(&buf[..k]))
+            }
+        }
+    }
+}
+
+fn os2path(s: &[u16]) -> Path {
+    // FIXME: this should not be a panicking conversion (aka path reform)
+    Path::new(String::from_utf16(s).unwrap())
+}
+
+pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
+    match v.iter().position(|c| *c == 0) {
+        // don't include the 0
+        Some(i) => &v[..i],
+        None => v
     }
 }
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index 828ad795ed3..75495efc7cb 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -38,8 +38,6 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
 
 impl Mutex {
     #[inline]
-    pub unsafe fn new() -> Mutex { MUTEX_INIT }
-    #[inline]
     pub unsafe fn lock(&self) {
         ffi::AcquireSRWLockExclusive(self.inner.get())
     }
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index a82259ad5ec..c71e2d057c3 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -10,48 +10,32 @@
 
 //! Implementation of `std::os` functionality for Windows
 
-// FIXME: move various extern bindings from here into liblibc or
-// something similar
+#![allow(bad_style)]
 
 use prelude::v1::*;
+use os::windows::*;
 
+use error::Error as StdError;
+use ffi::{OsString, OsStr, AsOsStr};
 use fmt;
-use old_io::{IoResult, IoError};
-use iter::repeat;
-use libc::{c_int, c_void};
-use libc;
-use os;
-use path::BytesContainer;
+use iter::Range;
+use libc::types::os::arch::extra::LPWCH;
+use libc::{self, c_int, c_void};
+use mem;
+use old_io::{IoError, IoResult};
 use ptr;
 use slice;
+use sys::c;
 use sys::fs::FileDesc;
+use sys::handle::Handle as RawHandle;
 
-use os::TMPBUF_SZ;
-use libc::types::os::arch::extra::DWORD;
+use libc::funcs::extra::kernel32::{
+    GetEnvironmentStringsW,
+    FreeEnvironmentStringsW
+};
 
-const BUF_BYTES : uint = 2048u;
-
-/// Return a slice of `v` ending at (and not including) the first NUL
-/// (0).
-pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
-    match v.iter().position(|c| *c == 0) {
-        // don't include the 0
-        Some(i) => &v[..i],
-        None => v
-    }
-}
-
-pub fn errno() -> uint {
-    use libc::types::os::arch::extra::DWORD;
-
-    #[link_name = "kernel32"]
-    extern "system" {
-        fn GetLastError() -> DWORD;
-    }
-
-    unsafe {
-        GetLastError() as uint
-    }
+pub fn errno() -> i32 {
+    unsafe { libc::GetLastError() as i32 }
 }
 
 /// Get a detailed string description for the given error number
@@ -80,7 +64,7 @@ pub fn error_string(errnum: i32) -> String {
     // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
     let langId = 0x0800 as DWORD;
 
-    let mut buf = [0 as WCHAR; TMPBUF_SZ];
+    let mut buf = [0 as WCHAR; 2048];
 
     unsafe {
         let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
@@ -94,200 +78,170 @@ pub fn error_string(errnum: i32) -> String {
         if res == 0 {
             // Sometimes FormatMessageW can fail e.g. system doesn't like langId,
             let fm_err = errno();
-            return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err);
+            return format!("OS Error {} (FormatMessageW() returned error {})",
+                           errnum, fm_err);
         }
 
-        let msg = String::from_utf16(truncate_utf16_at_nul(&buf));
+        let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
+        let msg = String::from_utf16(&buf[..b]);
         match msg {
-            Ok(msg) => format!("OS Error {}: {}", errnum, msg),
+            Ok(msg) => msg,
             Err(..) => format!("OS Error {} (FormatMessageW() returned \
                                 invalid UTF-16)", errnum),
         }
     }
 }
 
-pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
-    // Windows pipes work subtly differently than unix pipes, and their
-    // inheritance has to be handled in a different way that I do not
-    // fully understand. Here we explicitly make the pipe non-inheritable,
-    // which means to pass it to a subprocess they need to be duplicated
-    // first, as in std::run.
-    let mut fds = [0; 2];
-    match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint,
-                     (libc::O_BINARY | libc::O_NOINHERIT) as c_int) {
-        0 => {
-            assert!(fds[0] != -1 && fds[0] != 0);
-            assert!(fds[1] != -1 && fds[1] != 0);
-            Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
-        }
-        _ => Err(IoError::last_error()),
-    }
+pub struct Env {
+    base: LPWCH,
+    cur: LPWCH,
 }
 
-pub fn fill_utf16_buf_and_decode<F>(mut f: F) -> Option<String> where
-    F: FnMut(*mut u16, DWORD) -> DWORD,
-{
-    unsafe {
-        let mut n = TMPBUF_SZ as DWORD;
-        let mut res = None;
-        let mut done = false;
-        while !done {
-            let mut buf: Vec<u16> = repeat(0u16).take(n as uint).collect();
-            let k = f(buf.as_mut_ptr(), n);
-            if k == (0 as DWORD) {
-                done = true;
-            } else if k == n &&
-                      libc::GetLastError() ==
-                      libc::ERROR_INSUFFICIENT_BUFFER as DWORD {
-                n *= 2 as DWORD;
-            } else if k >= n {
-                n = k;
-            } else {
-                done = true;
-            }
-            if k != 0 && done {
-                let sub = &buf[.. (k as uint)];
-                // We want to explicitly catch the case when the
-                // closure returned invalid UTF-16, rather than
-                // set `res` to None and continue.
-                let s = String::from_utf16(sub).ok()
-                    .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16");
-                res = Some(s)
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        unsafe {
+            if *self.cur == 0 { return None }
+            let p = &*self.cur;
+            let mut len = 0;
+            while *(p as *const _).offset(len) != 0 {
+                len += 1;
             }
+            let p = p as *const u16;
+            let s = slice::from_raw_buf(&p, len as usize);
+            self.cur = self.cur.offset(len + 1);
+
+            let (k, v) = match s.iter().position(|&b| b == '=' as u16) {
+                Some(n) => (&s[..n], &s[n+1..]),
+                None => (s, &[][]),
+            };
+            Some((OsStringExt::from_wide(k), OsStringExt::from_wide(v)))
         }
-        return res;
     }
 }
 
-pub fn getcwd() -> IoResult<Path> {
-    use libc::DWORD;
-    use libc::GetCurrentDirectoryW;
-    use old_io::OtherIoError;
+impl Drop for Env {
+    fn drop(&mut self) {
+        unsafe { FreeEnvironmentStringsW(self.base); }
+    }
+}
 
-    let mut buf = [0 as u16; BUF_BYTES];
+pub fn env() -> Env {
     unsafe {
-        if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD {
-            return Err(IoError::last_error());
+        let ch = GetEnvironmentStringsW();
+        if ch as usize == 0 {
+            panic!("failure getting env string from OS: {}",
+                   IoError::last_error());
         }
+        Env { base: ch, cur: ch }
     }
+}
 
-    match String::from_utf16(truncate_utf16_at_nul(&buf)) {
-        Ok(ref cwd) => Ok(Path::new(cwd)),
-        Err(..) => Err(IoError {
-            kind: OtherIoError,
-            desc: "GetCurrentDirectoryW returned invalid UTF-16",
-            detail: None,
-        }),
-    }
+pub struct SplitPaths<'a> {
+    data: EncodeWide<'a>,
+    must_yield: bool,
 }
 
-pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
-    use libc::funcs::extra::kernel32::{
-        GetEnvironmentStringsW,
-        FreeEnvironmentStringsW
-    };
-    let ch = GetEnvironmentStringsW();
-    if ch as uint == 0 {
-        panic!("os::env() failure getting env string from OS: {}",
-               os::last_os_error());
+pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
+    SplitPaths {
+        data: unparsed.encode_wide(),
+        must_yield: true,
     }
-    // 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();
-    let mut i = 0;
-    while *ch.offset(i) != 0 {
-        let p = &*ch.offset(i);
-        let mut len = 0;
-        while *(p as *const _).offset(len) != 0 {
-            len += 1;
-        }
-        let p = p as *const u16;
-        let s = slice::from_raw_buf(&p, len as uint);
-        result.push(String::from_utf16_lossy(s).into_bytes());
-        i += len as int + 1;
-    }
-    FreeEnvironmentStringsW(ch);
-    result
 }
 
-pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
-    // On Windows, the PATH environment variable is semicolon separated.  Double
-    // quotes are used as a way of introducing literal semicolons (since
-    // c:\some;dir is a valid Windows path). Double quotes are not themselves
-    // permitted in path names, so there is no way to escape a double quote.
-    // Quoted regions can appear in arbitrary locations, so
-    //
-    //   c:\foo;c:\som"e;di"r;c:\bar
-    //
-    // Should parse as [c:\foo, c:\some;dir, c:\bar].
-    //
-    // (The above is based on testing; there is no clear reference available
-    // for the grammar.)
-
-    let mut parsed = Vec::new();
-    let mut in_progress = Vec::new();
-    let mut in_quote = false;
-
-    for b in unparsed.iter() {
-        match *b {
-            b';' if !in_quote => {
-                parsed.push(Path::new(in_progress.as_slice()));
-                in_progress.truncate(0)
-            }
-            b'"' => {
+impl<'a> Iterator for SplitPaths<'a> {
+    type Item = Path;
+    fn next(&mut self) -> Option<Path> {
+        // On Windows, the PATH environment variable is semicolon separated.
+        // Double quotes are used as a way of introducing literal semicolons
+        // (since c:\some;dir is a valid Windows path). Double quotes are not
+        // themselves permitted in path names, so there is no way to escape a
+        // double quote.  Quoted regions can appear in arbitrary locations, so
+        //
+        //   c:\foo;c:\som"e;di"r;c:\bar
+        //
+        // Should parse as [c:\foo, c:\some;dir, c:\bar].
+        //
+        // (The above is based on testing; there is no clear reference available
+        // for the grammar.)
+
+
+        let must_yield = self.must_yield;
+        self.must_yield = false;
+
+        let mut in_progress = Vec::new();
+        let mut in_quote = false;
+        for b in self.data.by_ref() {
+            if b == '"' as u16 {
                 in_quote = !in_quote;
+            } else if b == ';' as u16 && !in_quote {
+                self.must_yield = true;
+                break
+            } else {
+                in_progress.push(b)
             }
-            _  => {
-                in_progress.push(*b);
-            }
+        }
+
+        if !must_yield && in_progress.is_empty() {
+            None
+        } else {
+            Some(super::os2path(&in_progress[]))
         }
     }
-    parsed.push(Path::new(in_progress));
-    parsed
 }
 
-pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+#[derive(Show)]
+pub struct JoinPathsError;
+
+pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
+    where I: Iterator<Item=T>, T: AsOsStr
+{
     let mut joined = Vec::new();
-    let sep = b';';
+    let sep = b';' as u16;
 
-    for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
+    for (i, path) in paths.enumerate() {
+        let path = path.as_os_str();
         if i > 0 { joined.push(sep) }
-        if path.contains(&b'"') {
-            return Err("path segment contains `\"`");
-        } else if path.contains(&sep) {
-            joined.push(b'"');
-            joined.push_all(path);
-            joined.push(b'"');
+        let v = path.encode_wide().collect::<Vec<u16>>();
+        if v.contains(&(b'"' as u16)) {
+            return Err(JoinPathsError)
+        } else if v.contains(&sep) {
+            joined.push(b'"' as u16);
+            joined.push_all(&v[]);
+            joined.push(b'"' as u16);
         } else {
-            joined.push_all(path);
+            joined.push_all(&v[]);
         }
     }
 
-    Ok(joined)
+    Ok(OsStringExt::from_wide(&joined[]))
 }
 
-pub fn load_self() -> Option<Vec<u8>> {
-    unsafe {
-        fill_utf16_buf_and_decode(|buf, sz| {
-            libc::GetModuleFileNameW(ptr::null_mut(), buf, sz)
-        }).map(|s| s.to_string().into_bytes())
+impl fmt::Display for JoinPathsError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "path segment contains `\"`".fmt(f)
     }
 }
 
+impl StdError for JoinPathsError {
+    fn description(&self) -> &str { "failed to join paths" }
+}
+
+pub fn current_exe() -> IoResult<Path> {
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        libc::GetModuleFileNameW(ptr::null_mut(), buf, sz)
+    }, super::os2path)
+}
+
+pub fn getcwd() -> IoResult<Path> {
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        libc::GetCurrentDirectoryW(sz, buf)
+    }, super::os2path)
+}
+
 pub fn chdir(p: &Path) -> IoResult<()> {
-    let mut p = p.as_str().unwrap().utf16_units().collect::<Vec<u16>>();
+    let mut p = p.as_os_str().encode_wide().collect::<Vec<_>>();
     p.push(0);
 
     unsafe {
@@ -298,39 +252,124 @@ pub fn chdir(p: &Path) -> IoResult<()> {
     }
 }
 
-pub fn page_size() -> uint {
-    use mem;
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    let k = super::to_utf16_os(k);
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz)
+    }, |buf| {
+        OsStringExt::from_wide(buf)
+    }).ok()
+}
+
+pub fn setenv(k: &OsStr, v: &OsStr) {
+    let k = super::to_utf16_os(k);
+    let v = super::to_utf16_os(v);
+
     unsafe {
-        let mut info = mem::zeroed();
-        libc::GetSystemInfo(&mut info);
+        if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 {
+            panic!("failed to set env: {}", IoError::last_error());
+        }
+    }
+}
 
-        return info.dwPageSize as uint;
+pub fn unsetenv(n: &OsStr) {
+    let v = super::to_utf16_os(n);
+    unsafe {
+        if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 {
+            panic!("failed to unset env: {}", IoError::last_error());
+        }
     }
 }
 
-#[cfg(test)]
-mod tests {
-    use super::truncate_utf16_at_nul;
+pub struct Args {
+    range: Range<isize>,
+    cur: *mut *mut u16,
+}
 
-    #[test]
-    fn test_truncate_utf16_at_nul() {
-        let v = [];
-        let b: &[u16] = &[];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+impl Iterator for Args {
+    type Item = OsString;
+    fn next(&mut self) -> Option<OsString> {
+        self.range.next().map(|i| unsafe {
+            let ptr = *self.cur.offset(i);
+            let mut len = 0;
+            while *ptr.offset(len) != 0 { len += 1; }
+
+            // Push it onto the list.
+            let ptr = ptr as *const u16;
+            let buf = slice::from_raw_buf(&ptr, len as usize);
+            OsStringExt::from_wide(buf)
+        })
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
+}
 
-        let v = [0, 2, 3];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+impl Drop for Args {
+    fn drop(&mut self) {
+        unsafe { c::LocalFree(self.cur as *mut c_void); }
+    }
+}
 
-        let v = [1, 0, 3];
-        let b: &[u16] = &[1];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+pub fn args() -> Args {
+    unsafe {
+        let mut nArgs: c_int = 0;
+        let lpCmdLine = c::GetCommandLineW();
+        let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
 
-        let v = [1, 2, 0];
-        let b: &[u16] = &[1, 2];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+        Args { cur: szArgList, range: range(0, nArgs as isize) }
+    }
+}
 
-        let v = [1, 2, 3];
-        let b: &[u16] = &[1, 2, 3];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+pub fn page_size() -> usize {
+    unsafe {
+        let mut info = mem::zeroed();
+        libc::GetSystemInfo(&mut info);
+        return info.dwPageSize as usize;
+    }
+}
+
+pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
+    // Windows pipes work subtly differently than unix pipes, and their
+    // inheritance has to be handled in a different way that I do not
+    // fully understand. Here we explicitly make the pipe non-inheritable,
+    // which means to pass it to a subprocess they need to be duplicated
+    // first, as in std::run.
+    let mut fds = [0; 2];
+    match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint,
+    (libc::O_BINARY | libc::O_NOINHERIT) as c_int) {
+        0 => {
+            assert!(fds[0] != -1 && fds[0] != 0);
+            assert!(fds[1] != -1 && fds[1] != 0);
+            Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
+        }
+        _ => Err(IoError::last_error()),
     }
 }
+
+pub fn temp_dir() -> Path {
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        c::GetTempPathW(sz, buf)
+    }, super::os2path).unwrap()
+}
+
+pub fn home_dir() -> Option<Path> {
+    getenv("HOME".as_os_str()).or_else(|| {
+        getenv("USERPROFILE".as_os_str())
+    }).map(|os| {
+        // FIXME: OsString => Path
+        Path::new(os.to_str().unwrap())
+    }).or_else(|| unsafe {
+        let me = c::GetCurrentProcess();
+        let mut token = ptr::null_mut();
+        if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
+            return None
+        }
+        let _handle = RawHandle::new(token);
+        super::fill_utf16_buf(|buf, mut sz| {
+            match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
+                0 if libc::GetLastError() != 0 => 0,
+                0 => sz,
+                n => n as libc::DWORD,
+            }
+        }, super::os2path).ok()
+    })
+}
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index 0bc2a827272..1f228b7d32e 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -352,7 +352,7 @@ impl UnixStream {
 
     fn cancel_io(&self) -> IoResult<()> {
         match unsafe { c::CancelIoEx(self.handle(), ptr::null_mut()) } {
-            0 if os::errno() == libc::ERROR_NOT_FOUND as uint => {
+            0 if os::errno() == libc::ERROR_NOT_FOUND as i32 => {
                 Ok(())
             }
             0 => Err(super::last_error()),
@@ -374,7 +374,7 @@ impl UnixStream {
         // acquire the lock.
         //
         // See comments in close_read() about why this lock is necessary.
-        let guard = unsafe { self.inner.lock.lock() };
+        let guard = self.inner.lock.lock();
         if self.read_closed() {
             return Err(eof())
         }
@@ -392,7 +392,7 @@ impl UnixStream {
 
         // If our errno doesn't say that the I/O is pending, then we hit some
         // legitimate error and return immediately.
-        if os::errno() != libc::ERROR_IO_PENDING as uint {
+        if os::errno() != libc::ERROR_IO_PENDING as i32 {
             return Err(super::last_error())
         }
 
@@ -417,7 +417,7 @@ impl UnixStream {
             // If we succeeded, or we failed for some reason other than
             // CancelIoEx, return immediately
             if ret != 0 { return Ok(bytes_read as uint) }
-            if os::errno() != libc::ERROR_OPERATION_ABORTED as uint {
+            if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 {
                 return Err(super::last_error())
             }
 
@@ -450,7 +450,7 @@ impl UnixStream {
             // going after we woke up.
             //
             // See comments in close_read() about why this lock is necessary.
-            let guard = unsafe { self.inner.lock.lock() };
+            let guard = self.inner.lock.lock();
             if self.write_closed() {
                 return Err(epipe())
             }
@@ -465,7 +465,7 @@ impl UnixStream {
             drop(guard);
 
             if ret == 0 {
-                if err != libc::ERROR_IO_PENDING as uint {
+                if err != libc::ERROR_IO_PENDING as i32 {
                     return Err(decode_error_detailed(err as i32))
                 }
                 // Process a timeout if one is pending
@@ -481,7 +481,7 @@ impl UnixStream {
                 // aborted, then check to see if the write half was actually
                 // closed or whether we woke up from the read half closing.
                 if ret == 0 {
-                    if os::errno() != libc::ERROR_OPERATION_ABORTED as uint {
+                    if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 {
                         return Err(super::last_error())
                     }
                     if !wait_succeeded.is_ok() {
@@ -525,14 +525,14 @@ impl UnixStream {
         // close_read() between steps 1 and 2. By atomically executing steps 1
         // and 2 with a lock with respect to close_read(), we're guaranteed that
         // no thread will erroneously sit in a read forever.
-        let _guard = unsafe { self.inner.lock.lock() };
+        let _guard = self.inner.lock.lock();
         self.inner.read_closed.store(true, Ordering::SeqCst);
         self.cancel_io()
     }
 
     pub fn close_write(&mut self) -> IoResult<()> {
         // see comments in close_read() for why this lock is necessary
-        let _guard = unsafe { self.inner.lock.lock() };
+        let _guard = self.inner.lock.lock();
         self.inner.write_closed.store(true, Ordering::SeqCst);
         self.cancel_io()
     }
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 3d66718d00b..3ca735f7fdf 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -10,28 +10,27 @@
 
 use prelude::v1::*;
 
+use collections::hash_map::Hasher;
 use collections;
+use env;
 use ffi::CString;
 use hash::Hash;
-use collections::hash_map::Hasher;
+use libc::{pid_t, c_void};
+use libc;
+use mem;
 use old_io::fs::PathExtensions;
-use old_io::process::{ProcessExit, ExitStatus, ExitSignal};
+use old_io::process::{ProcessExit, ExitStatus};
 use old_io::{IoResult, IoError};
 use old_io;
-use libc::{pid_t, c_void, c_int};
-use libc;
-use mem;
 use os;
 use path::BytesContainer;
 use ptr;
 use str;
-use sys::fs::FileDesc;
 use sync::{StaticMutex, MUTEX_INIT};
+use sys::fs::FileDesc;
 
-use sys::fs;
-use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
-use sys_common::helper_thread::Helper;
-use sys_common::{AsInner, mkerr_libc, timeout};
+use sys::timer;
+use sys_common::{AsInner, timeout};
 
 pub use sys_common::ProcessConfig;
 
@@ -106,6 +105,7 @@ impl Process {
         return ret;
     }
 
+    #[allow(deprecated)]
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
@@ -128,7 +128,7 @@ impl Process {
         use libc::funcs::extra::msvcrt::get_osfhandle;
 
         use mem;
-        use iter::{Iterator, IteratorExt};
+        use iter::IteratorExt;
         use str::StrExt;
 
         if cfg.gid().is_some() || cfg.uid().is_some() {
@@ -142,14 +142,14 @@ impl Process {
         // To have the spawning semantics of unix/windows stay the same, we need to
         // read the *child's* PATH if one is provided. See #15149 for more details.
         let program = cfg.env().and_then(|env| {
-            for (key, v) in env.iter() {
+            for (key, v) in env {
                 if b"PATH" != key.container_as_bytes() { continue }
 
                 // Split the value and test each path to see if the
                 // program exists.
-                for path in os::split_paths(v.container_as_bytes()).into_iter() {
+                for path in os::split_paths(v.container_as_bytes()) {
                     let path = path.join(cfg.program().as_bytes())
-                                   .with_extension(os::consts::EXE_EXTENSION);
+                                   .with_extension(env::consts::EXE_EXTENSION);
                     if path.exists() {
                         return Some(CString::from_slice(path.as_vec()))
                     }
@@ -372,7 +372,7 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String {
     let mut cmd = String::new();
     append_arg(&mut cmd, str::from_utf8(prog.as_bytes()).ok()
                              .expect("expected program name to be utf-8 encoded"));
-    for arg in args.iter() {
+    for arg in args {
         cmd.push(' ');
         append_arg(&mut cmd, str::from_utf8(arg.as_bytes()).ok()
                                 .expect("expected argument to be utf-8 encoded"));
@@ -437,7 +437,7 @@ fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
         Some(env) => {
             let mut blk = Vec::new();
 
-            for pair in env.iter() {
+            for pair in env {
                 let kv = format!("{}={}",
                                  pair.0.container_as_str().unwrap(),
                                  pair.1.container_as_str().unwrap());
diff --git a/src/libstd/sys/windows/rwlock.rs b/src/libstd/sys/windows/rwlock.rs
index 88ce85c39f6..76fe352ed77 100644
--- a/src/libstd/sys/windows/rwlock.rs
+++ b/src/libstd/sys/windows/rwlock.rs
@@ -19,9 +19,6 @@ pub const RWLOCK_INIT: RWLock = RWLock {
 
 impl RWLock {
     #[inline]
-    pub unsafe fn new() -> RWLock { RWLOCK_INIT }
-
-    #[inline]
     pub unsafe fn read(&self) {
         ffi::AcquireSRWLockShared(self.inner.get())
     }
diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs
index 0cb4c573ae3..b0410701ee1 100644
--- a/src/libstd/sys/windows/stack_overflow.rs
+++ b/src/libstd/sys/windows/stack_overflow.rs
@@ -14,7 +14,7 @@ use ptr;
 use mem;
 use libc;
 use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
-use sys_common::{stack, thread_info};
+use sys_common::stack;
 
 pub struct Handler {
     _data: *mut libc::c_void
@@ -30,14 +30,6 @@ impl Drop for Handler {
     fn drop(&mut self) {}
 }
 
-// get_task_info is called from an exception / signal handler.
-// It returns the guard page of the current task or 0 if that
-// guard page doesn't exist. None is returned if there's currently
-// no local task.
-unsafe fn get_task_guard_page() -> uint {
-    thread_info::stack_guard()
-}
-
 // This is initialized in init() and only read from after
 static mut PAGE_SIZE: uint = 0;
 
diff --git a/src/libstd/sys/windows/sync.rs b/src/libstd/sys/windows/sync.rs
index d60646b7db9..7614104c98b 100644
--- a/src/libstd/sys/windows/sync.rs
+++ b/src/libstd/sys/windows/sync.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc::{BOOL, DWORD, c_void, LPVOID, c_ulong};
+use libc::{BOOL, DWORD, LPVOID, c_ulong};
 use libc::types::os::arch::extra::BOOLEAN;
 
 pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs
index 64e440331c1..4804ca510cb 100644
--- a/src/libstd/sys/windows/tcp.rs
+++ b/src/libstd/sys/windows/tcp.rs
@@ -14,12 +14,11 @@ use libc;
 use mem;
 use ptr;
 use prelude::v1::*;
-use super::{last_error, last_net_error, retry, sock_t};
+use super::{last_error, last_net_error, sock_t};
 use sync::Arc;
 use sync::atomic::{AtomicBool, Ordering};
-use sys::fs::FileDesc;
 use sys::{self, c, set_nonblocking, wouldblock, timer};
-use sys_common::{self, timeout, eof, net};
+use sys_common::{timeout, eof, net};
 
 pub use sys_common::net::TcpStream;
 
@@ -202,10 +201,6 @@ impl TcpAcceptor {
         Err(eof())
     }
 
-    pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        net::sockname(self.socket(), libc::getsockname)
-    }
-
     pub fn set_timeout(&mut self, timeout: Option<u64>) {
         self.deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
     }
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index a94adcb3bc7..a38dc9b2d34 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::prelude::*;
-
 use boxed::Box;
 use cmp;
 use mem;
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
index 0f8ceed39a6..54a32e43daf 100644
--- a/src/libstd/sys/windows/thread_local.rs
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -233,6 +233,7 @@ unsafe extern "system" fn on_tls_callback(h: LPVOID,
     }
 }
 
+#[allow(dead_code)] // actually called above
 unsafe fn run_dtors() {
     let mut any_run = true;
     for _ in 0..5 {
@@ -248,7 +249,7 @@ unsafe fn run_dtors() {
             DTOR_LOCK.unlock();
             ret
         };
-        for &(key, dtor) in dtors.iter() {
+        for &(key, dtor) in &dtors {
             let ptr = TlsGetValue(key);
             if !ptr.is_null() {
                 TlsSetValue(key, ptr::null_mut());
diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs
index 34f3c418c55..d156dd801f9 100644
--- a/src/libstd/sys/windows/timer.rs
+++ b/src/libstd/sys/windows/timer.rs
@@ -28,8 +28,6 @@ use ptr;
 
 use old_io::IoResult;
 use sync::mpsc::{channel, Sender, Receiver, TryRecvError};
-use sys::c;
-use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
 
 helper_init! { static HELPER: Helper<Req> }
diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs
index 6ecabfa9853..f02c8e49f41 100644
--- a/src/libstd/sys/windows/tty.rs
+++ b/src/libstd/sys/windows/tty.rs
@@ -38,7 +38,7 @@ use str::from_utf8;
 use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS};
 use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT};
 use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
-use super::c::{ERROR_ILLEGAL_CHARACTER, CONSOLE_SCREEN_BUFFER_INFO};
+use super::c::{CONSOLE_SCREEN_BUFFER_INFO};
 use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode};
 use super::c::{GetConsoleScreenBufferInfo};
 
@@ -155,9 +155,6 @@ impl TTY {
                      (info.srWindow.Bottom + 1 - info.srWindow.Top) as int)),
         }
     }
-
-    // Let us magically declare this as a TTY
-    pub fn isatty(&self) -> bool { true }
 }
 
 impl Drop for TTY {