Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add windows API errors handling #80

Closed
gentoo90 opened this issue Apr 20, 2015 · 4 comments
Closed

Add windows API errors handling #80

gentoo90 opened this issue Apr 20, 2015 · 4 comments

Comments

@gentoo90
Copy link
Contributor

Many of WinAPI calls return error codes listed in winerror.rs which sometimes should be returned to user as Result.
Add appropriate data structures to prevent their reinvention in each crate which uses winapi.
Maybe something like:

#[derive(Debug)]
pub struct WinError {
    err: winapi::DWORD,
    message: String,
}

impl WinError {
    pub fn new(err: winapi::DWORD) -> WinError {
        WinError{ err: err, message: error_string(err)}
    }
}

pub type WinResult<T> = std::result::Result<T, WinError>;

// copycat of rust/src/libstd/sys/windows/os.rs::error_string
// `use std::sys::os::error_string` leads to
// error: function `error_string` is private.
// Get a detailed string description for the given error number
fn error_string(errnum: winapi::DWORD) -> String {
    let mut buf = [0 as winapi::WCHAR; 2048];
    unsafe {
        let res = kernel32::FormatMessageW(winapi::FORMAT_MESSAGE_FROM_SYSTEM |
                                 winapi::FORMAT_MESSAGE_IGNORE_INSERTS,
                                 ptr::null_mut(),
                                 errnum as winapi::DWORD,
                                 0,
                                 buf.as_mut_ptr(),
                                 buf.len() as winapi::DWORD,
                                 ptr::null_mut());
        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);
        }

        let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
        let msg = String::from_utf16(&buf[..b]);
        match msg {
            Ok(msg) => msg.trim_right().to_string(),
            Err(..) => format!("OS Error {} (FormatMessageW() returned \
                                invalid UTF-16)", errnum),
        }
    }
}

Usage:

fn use_winapi_call() -> winapi::WinResult<()> {
    match unsafe {
        advapi32::SomeApiCall(param) as winapi::DWORD
    } {
        0 => Ok(()),
        err => Err(winapi::WinError::new(err))
    }
}
@tomaka
Copy link
Contributor

tomaka commented Apr 20, 2015

Note that the official io::Error type already does this with GetLastError.

@gentoo90
Copy link
Contributor Author

Possible alternative, but doesn't show error's description when .unwrap()'ed :( . Only number.

@ghost
Copy link

ghost commented Jul 1, 2015

I agree that there should be reusable code for wrapping windows errors with better Rust constructs, but I don't think it belongs here. This is a direct binding to microsoft's API.

@retep998
Copy link
Owner

retep998 commented Jul 1, 2015

As of rust-lang/rust#26416 io::Error will now print out the error message on .unwrap().

@retep998 retep998 closed this as completed Jul 1, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants