diff options
| author | bors <bors@rust-lang.org> | 2017-05-11 22:37:38 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-05-11 22:37:38 +0000 |
| commit | 39bcd6f425426bfacd7de9fe0378df4bd9263d00 (patch) | |
| tree | 02ae46e982f6faebac2ced6743c7afd06bdf08b6 /src/libstd/sys | |
| parent | e40beb3af162e676e40704854dd6547ee8d4cf60 (diff) | |
| parent | 71de9dbe5bc823a9603318c9cf92f58d7f5eb6f9 (diff) | |
| download | rust-39bcd6f425426bfacd7de9fe0378df4bd9263d00.tar.gz rust-39bcd6f425426bfacd7de9fe0378df4bd9263d00.zip | |
Auto merge of #41684 - jethrogb:feature/ntstatus, r=alexcrichton
Windows io::Error: also format NTSTATUS error codes `NTSTATUS` errors may be encoded as `HRESULT`, see [[MS-ERREF]](https://msdn.microsoft.com/en-us/library/cc231198.aspx). These error codes can still be formatted using `FormatMessageW` but require some different parameters to be passed in. I wasn't sure if this needed a test and if so, how to test it. Presumably we wouldn't want to make our tests dependent on localization-dependent strings returned from `FormatMessageW`. Users that get an `err: NTSTATUS` will need to do `io::Error::from_raw_os_error(err|0x1000_0000)` (the equivalent of [`HRESULT_FROM_NT`](https://msdn.microsoft.com/en-us/library/ms693780(VS.85).aspx))
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/windows/c.rs | 3 | ||||
| -rw-r--r-- | src/libstd/sys/windows/os.rs | 38 |
2 files changed, 38 insertions, 3 deletions
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 5e46069cf7d..1646f8cce72 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -199,7 +199,10 @@ pub const ERROR_TIMEOUT: DWORD = 0x5B4; pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE; +pub const FACILITY_NT_BIT: DWORD = 0x1000_0000; + pub const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000; +pub const FORMAT_MESSAGE_FROM_HMODULE: DWORD = 0x00000800; pub const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200; pub const TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF; diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 7e28dd1e259..a51b458451e 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -32,7 +32,7 @@ pub fn errno() -> i32 { } /// Gets a detailed string description for the given error number. -pub fn error_string(errnum: i32) -> String { +pub fn error_string(mut errnum: i32) -> String { // This value is calculated from the macro // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT) let langId = 0x0800 as c::DWORD; @@ -40,9 +40,27 @@ pub fn error_string(errnum: i32) -> String { let mut buf = [0 as c::WCHAR; 2048]; unsafe { - let res = c::FormatMessageW(c::FORMAT_MESSAGE_FROM_SYSTEM | + let mut module = ptr::null_mut(); + let mut flags = 0; + + // NTSTATUS errors may be encoded as HRESULT, which may returned from + // GetLastError. For more information about Windows error codes, see + // `[MS-ERREF]`: https://msdn.microsoft.com/en-us/library/cc231198.aspx + if (errnum & c::FACILITY_NT_BIT as i32) != 0 { + // format according to https://support.microsoft.com/en-us/help/259693 + const NTDLL_DLL: &'static [u16] = &['N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _, + '.' as _, 'D' as _, 'L' as _, 'L' as _, 0]; + module = c::GetModuleHandleW(NTDLL_DLL.as_ptr()); + + if module != ptr::null_mut() { + errnum ^= c::FACILITY_NT_BIT as i32; + flags = c::FORMAT_MESSAGE_FROM_HMODULE; + } + } + + let res = c::FormatMessageW(flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS, - ptr::null_mut(), + module, errnum as c::DWORD, langId, buf.as_mut_ptr(), @@ -299,3 +317,17 @@ pub fn home_dir() -> Option<PathBuf> { pub fn exit(code: i32) -> ! { unsafe { c::ExitProcess(code as c::UINT) } } + +#[cfg(test)] +mod tests { + use io::Error; + use sys::c; + + // tests `error_string` above + #[test] + fn ntstatus_error() { + const STATUS_UNSUCCESSFUL: u32 = 0xc000_0001; + assert!(!Error::from_raw_os_error((STATUS_UNSUCCESSFUL | c::FACILITY_NT_BIT) as _) + .to_string().contains("FormatMessageW() returned error")); + } +} |
