diff options
Diffstat (limited to 'third_party/rust/wio/src')
-rw-r--r-- | third_party/rust/wio/src/apc.rs | 39 | ||||
-rw-r--r-- | third_party/rust/wio/src/com.rs | 79 | ||||
-rw-r--r-- | third_party/rust/wio/src/console.rs | 270 | ||||
-rw-r--r-- | third_party/rust/wio/src/error.rs | 18 | ||||
-rw-r--r-- | third_party/rust/wio/src/handle.rs | 71 | ||||
-rw-r--r-- | third_party/rust/wio/src/lib.rs | 20 | ||||
-rw-r--r-- | third_party/rust/wio/src/perf.rs | 17 | ||||
-rw-r--r-- | third_party/rust/wio/src/pipe.rs | 16 | ||||
-rw-r--r-- | third_party/rust/wio/src/sleep.rs | 23 | ||||
-rw-r--r-- | third_party/rust/wio/src/thread.rs | 51 | ||||
-rw-r--r-- | third_party/rust/wio/src/ums.rs | 3 | ||||
-rw-r--r-- | third_party/rust/wio/src/wide.rs | 59 |
12 files changed, 666 insertions, 0 deletions
diff --git a/third_party/rust/wio/src/apc.rs b/third_party/rust/wio/src/apc.rs new file mode 100644 index 0000000000..21dcef2974 --- /dev/null +++ b/third_party/rust/wio/src/apc.rs @@ -0,0 +1,39 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use {Result, k32, last_error, w}; +use std::os::windows::io::{AsRawHandle}; +use thread::{Thread}; + +pub fn queue<T>(func: T, thread: &Thread) -> Result<()> where T: FnOnce() + 'static { + unsafe extern "system" fn helper<T: FnOnce() + 'static>(thing: w::ULONG_PTR) { + let func = Box::from_raw(thing as *mut T); + func() + } + let thing = Box::into_raw(Box::new(func)) as w::ULONG_PTR; + match unsafe { k32::QueueUserAPC(Some(helper::<T>), thread.as_raw_handle(), thing) } { + 0 => { + // If it fails we still need to deallocate the function + unsafe { Box::from_raw(thing as *mut T) }; + last_error() + }, + _ => Ok(()), + } +} +pub fn queue_current<T>(func: T) -> Result<()> where T: FnOnce() + 'static { + unsafe extern "system" fn helper<T: FnOnce() + 'static>(thing: w::ULONG_PTR) { + let func = Box::from_raw(thing as *mut T); + func() + } + let thing = Box::into_raw(Box::new(func)) as w::ULONG_PTR; + match unsafe { k32::QueueUserAPC(Some(helper::<T>), k32::GetCurrentThread(), thing) } { + 0 => { + // If it fails we still need to deallocate the function + unsafe { Box::from_raw(thing as *mut T) }; + last_error() + }, + _ => Ok(()), + } +} diff --git a/third_party/rust/wio/src/com.rs b/third_party/rust/wio/src/com.rs new file mode 100644 index 0000000000..d94d3d35cf --- /dev/null +++ b/third_party/rust/wio/src/com.rs @@ -0,0 +1,79 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use std::fmt::{Debug, Error as FmtError, Formatter}; +use std::mem::forget; +use std::ops::Deref; +use std::ptr::{NonNull, null_mut}; +use winapi::Interface; +use winapi::um::unknwnbase::IUnknown; + +// ComPtr to wrap COM interfaces sanely +#[repr(transparent)] +pub struct ComPtr<T>(NonNull<T>); +impl<T> ComPtr<T> { + /// Creates a `ComPtr` to wrap a raw pointer. + /// It takes ownership over the pointer which means it does __not__ call `AddRef`. + /// `T` __must__ be a COM interface that inherits from `IUnknown`. + pub unsafe fn from_raw(ptr: *mut T) -> ComPtr<T> where T: Interface { + ComPtr(NonNull::new(ptr).expect("ptr should not be null")) + } + /// Casts up the inheritance chain + pub fn up<U>(self) -> ComPtr<U> where T: Deref<Target=U>, U: Interface { + unsafe { ComPtr::from_raw(self.into_raw() as *mut U) } + } + /// Extracts the raw pointer. + /// You are now responsible for releasing it yourself. + pub fn into_raw(self) -> *mut T { + let p = self.0.as_ptr(); + forget(self); + p + } + /// For internal use only. + fn as_unknown(&self) -> &IUnknown { + unsafe { &*(self.as_raw() as *mut IUnknown) } + } + /// Performs QueryInterface fun. + pub fn cast<U>(&self) -> Result<ComPtr<U>, i32> where U: Interface { + let mut obj = null_mut(); + let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) }; + if err < 0 { return Err(err); } + Ok(unsafe { ComPtr::from_raw(obj as *mut U) }) + } + /// Obtains the raw pointer without transferring ownership. + /// Do __not__ release this pointer because it is still owned by the `ComPtr`. + pub fn as_raw(&self) -> *mut T { + self.0.as_ptr() + } +} +impl<T> Deref for ComPtr<T> { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*self.as_raw() } + } +} +impl<T> Clone for ComPtr<T> where T: Interface { + fn clone(&self) -> Self { + unsafe { + self.as_unknown().AddRef(); + ComPtr::from_raw(self.as_raw()) + } + } +} +impl<T> Debug for ComPtr<T> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "{:?}", self.0) + } +} +impl<T> Drop for ComPtr<T> { + fn drop(&mut self) { + unsafe { self.as_unknown().Release(); } + } +} +impl<T> PartialEq<ComPtr<T>> for ComPtr<T> where T: Interface { + fn eq(&self, other: &ComPtr<T>) -> bool { + self.0 == other.0 + } +} diff --git a/third_party/rust/wio/src/console.rs b/third_party/rust/wio/src/console.rs new file mode 100644 index 0000000000..a7d9fa7989 --- /dev/null +++ b/third_party/rust/wio/src/console.rs @@ -0,0 +1,270 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use error::{Error, Result}; +use handle::Handle; +use std::{ + mem::{size_of_val, zeroed}, + os::windows::io::FromRawHandle, + ptr::{null, null_mut}, +}; +use wide::ToWide; +use winapi::{ + um::{ + consoleapi::{AllocConsole, GetConsoleCP, GetConsoleOutputCP, GetNumberOfConsoleInputEvents, ReadConsoleInputW}, + fileapi::{CreateFileW, OPEN_EXISTING}, + handleapi::INVALID_HANDLE_VALUE, + wincon::{AttachConsole, CHAR_INFO, CONSOLE_FONT_INFOEX, CONSOLE_SCREEN_BUFFER_INFO, CONSOLE_SCREEN_BUFFER_INFOEX, CONSOLE_TEXTMODE_BUFFER, COORD, CreateConsoleScreenBuffer, FlushConsoleInputBuffer, FOCUS_EVENT, FreeConsole, GetConsoleScreenBufferInfo, GetConsoleScreenBufferInfoEx, GetCurrentConsoleFont, INPUT_RECORD, KEY_EVENT, MENU_EVENT, MOUSE_EVENT, SetConsoleActiveScreenBuffer, SetConsoleCP, SetConsoleOutputCP, SetConsoleScreenBufferInfoEx, SMALL_RECT, WINDOW_BUFFER_SIZE_EVENT, WriteConsoleOutputW}, + winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE, HANDLE}, + }, + shared::minwindef::{DWORD, FALSE}, +}; + +pub struct ScreenBuffer(Handle); +impl ScreenBuffer { + pub fn new() -> Result<ScreenBuffer> { + let handle = unsafe { CreateConsoleScreenBuffer( + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + null(), CONSOLE_TEXTMODE_BUFFER, null_mut(), + )}; + if handle == INVALID_HANDLE_VALUE { return Error::last() } + unsafe { Ok(ScreenBuffer(Handle::new(handle))) } + } + /// Gets the actual active console screen buffer + pub fn from_conout() -> Result<ScreenBuffer> { + let handle = unsafe { CreateFileW( + "CONOUT$".to_wide_null().as_ptr(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, null_mut(), OPEN_EXISTING, + 0, null_mut(), + )}; + if handle == INVALID_HANDLE_VALUE { return Error::last() } + unsafe { Ok(ScreenBuffer(Handle::new(handle))) } + } + pub fn set_active(&self) -> Result<()> { + let res = unsafe { SetConsoleActiveScreenBuffer(*self.0) }; + if res == 0 { return Error::last() } + Ok(()) + } + pub fn info(&self) -> Result<ScreenBufferInfo> { + let mut info = ScreenBufferInfo(unsafe { zeroed() }); + let res = unsafe { GetConsoleScreenBufferInfo(*self.0, &mut info.0) }; + if res == 0 { return Error::last() } + Ok(info) + } + pub fn info_ex(&self) -> Result<ScreenBufferInfoEx> { + let mut info: CONSOLE_SCREEN_BUFFER_INFOEX = unsafe { zeroed() }; + info.cbSize = size_of_val(&info) as u32; + let res = unsafe { GetConsoleScreenBufferInfoEx(*self.0, &mut info) }; + if res == 0 { return Error::last() } + // Yes, this is important + info.srWindow.Right += 1; + info.srWindow.Bottom += 1; + Ok(ScreenBufferInfoEx(info)) + } + pub fn set_info_ex(&self, mut info: ScreenBufferInfoEx) -> Result<()> { + let res = unsafe { SetConsoleScreenBufferInfoEx(*self.0, &mut info.0) }; + if res == 0 { return Error::last() } + Ok(()) + } + // pub fn font_ex(&self) -> Result<FontEx> { + // unsafe { + // let mut info = zeroed(); + // info.cbSize = size_of_val(&info); + // let res = GetCurrentConsoleFontEx(*self.0, w::FALSE, &mut info); + // if res == 0 { return Error::last() } + // Ok(FontEx(info)) + // } + // } + pub fn write_output(&self, buf: &[CharInfo], size: (i16, i16), pos: (i16, i16)) -> Result<()> { + assert!(buf.len() == (size.0 as usize) * (size.1 as usize)); + let mut rect = SMALL_RECT { + Left: pos.0, + Top: pos.1, + Right: pos.0 + size.0, + Bottom: pos.1 + size.1, + }; + let size = COORD { X: size.0, Y: size.1 }; + let pos = COORD { X: 0, Y: 0 }; + let res = unsafe { WriteConsoleOutputW( + *self.0, buf.as_ptr() as *const CHAR_INFO, size, pos, &mut rect + )}; + if res == 0 { return Error::last() } + Ok(()) + } + pub fn font_size(&self) -> Result<(i16, i16)> { + unsafe { + let mut font = zeroed(); + let res = GetCurrentConsoleFont(*self.0, FALSE, &mut font); + if res == 0 { return Error::last() } + Ok((font.dwFontSize.X, font.dwFontSize.Y)) + } + } +} +impl FromRawHandle for ScreenBuffer { + unsafe fn from_raw_handle(handle: HANDLE) -> ScreenBuffer { + ScreenBuffer(Handle::new(handle)) + } +} +pub struct InputBuffer(Handle); +impl InputBuffer { + /// Gets the actual active console input buffer + pub fn from_conin() -> Result<InputBuffer> { + let handle = unsafe { CreateFileW( + "CONIN$".to_wide_null().as_ptr(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, null_mut(), OPEN_EXISTING, + 0, null_mut(), + )}; + if handle == INVALID_HANDLE_VALUE { Error::last() } + else { unsafe { Ok(InputBuffer::from_raw_handle(handle)) } } + } + /// The number of input that is available to read + pub fn available_input(&self) -> Result<u32> { + let mut num = 0; + let res = unsafe { GetNumberOfConsoleInputEvents(*self.0, &mut num) }; + if res == 0 { return Error::last() } + Ok(num) + } + /// Reads a bunch of input events + pub fn read_input(&self) -> Result<Vec<Input>> { + let mut buf: [INPUT_RECORD; 0x1000] = unsafe { zeroed() }; + let mut size = 0; + let res = unsafe { ReadConsoleInputW( + *self.0, buf.as_mut_ptr(), buf.len() as DWORD, &mut size, + )}; + if res == 0 { return Error::last() } + Ok(buf[..(size as usize)].iter().map(|input| { + unsafe { match input.EventType { + KEY_EVENT => { + let e = input.Event.KeyEvent(); + Input::Key { + key_down: e.bKeyDown != 0, + repeat_count: e.wRepeatCount, + key_code: e.wVirtualKeyCode, + scan_code: e.wVirtualScanCode, + wide_char: *e.uChar.UnicodeChar(), + control_key_state: e.dwControlKeyState, + } + }, + MOUSE_EVENT => { + let e = input.Event.MouseEvent(); + Input::Mouse { + position: (e.dwMousePosition.X, e.dwMousePosition.Y), + button_state: e.dwButtonState, + control_key_state: e.dwControlKeyState, + event_flags: e.dwEventFlags, + } + }, + WINDOW_BUFFER_SIZE_EVENT => { + let s = input.Event.WindowBufferSizeEvent().dwSize; + Input::WindowBufferSize(s.X, s.Y) + }, + MENU_EVENT => Input::Menu(input.Event.MenuEvent().dwCommandId), + FOCUS_EVENT => Input::Focus(input.Event.FocusEvent().bSetFocus != 0), + e => unreachable!("invalid event type: {}", e), + } } + }).collect()) + } + /// Clears all pending input + pub fn flush_input(&self) -> Result<()> { + let res = unsafe { FlushConsoleInputBuffer(*self.0) }; + if res == 0 { return Error::last() } + Ok(()) + } +} +impl FromRawHandle for InputBuffer { + unsafe fn from_raw_handle(handle: HANDLE) -> InputBuffer { + InputBuffer(Handle::from_raw_handle(handle)) + } +} +#[repr(transparent)] #[derive(Copy, Clone)] +pub struct ScreenBufferInfo(CONSOLE_SCREEN_BUFFER_INFO); +impl ScreenBufferInfo { + pub fn size(&self) -> (i16, i16) { + (self.0.dwSize.X, self.0.dwSize.Y) + } +} +#[repr(transparent)] #[derive(Copy, Clone)] +pub struct ScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX); +impl ScreenBufferInfoEx { + pub fn raw_mut(&mut self) -> &mut CONSOLE_SCREEN_BUFFER_INFOEX { + &mut self.0 + } +} +#[repr(transparent)] #[derive(Copy, Clone)] +pub struct FontInfoEx(CONSOLE_FONT_INFOEX); +#[derive(Copy, Clone)] +pub enum Input { + Key { + key_down: bool, + repeat_count: u16, + key_code: u16, + scan_code: u16, + wide_char: u16, + control_key_state: u32, + }, + Mouse { + position: (i16, i16), + button_state: u32, + control_key_state: u32, + event_flags: u32, + }, + WindowBufferSize(i16, i16), + Menu(u32), + Focus(bool), +} +#[repr(transparent)] #[derive(Copy, Clone)] +pub struct CharInfo(CHAR_INFO); +impl CharInfo { + pub fn new(ch: u16, attr: u16) -> CharInfo { + let mut ci: CHAR_INFO = unsafe { zeroed() }; + unsafe { *ci.Char.UnicodeChar_mut() = ch }; + ci.Attributes = attr; + CharInfo(ci) + } + pub fn character(&self) -> u16 { unsafe { *self.0.Char.UnicodeChar() } } + pub fn attributes(&self) -> u16 { self.0.Attributes } +} +/// Allocates a console if the process does not already have a console. +pub fn alloc() -> Result<()> { + match unsafe { AllocConsole() } { + 0 => Error::last(), + _ => Ok(()), + } +} +/// Detaches the process from its current console. +pub fn free() -> Result<()> { + match unsafe { FreeConsole() } { + 0 => Error::last(), + _ => Ok(()), + } +} +/// Attaches the process to the console of the specified process. +/// Pass None to attach to the console of the parent process. +pub fn attach(processid: Option<u32>) -> Result<()> { + match unsafe { AttachConsole(processid.unwrap_or(-1i32 as u32)) } { + 0 => Error::last(), + _ => Ok(()), + } +} +/// Gets the current input code page +pub fn input_code_page() -> u32 { + unsafe { GetConsoleCP() } +} +/// Gets the current output code page +pub fn output_code_page() -> u32 { + unsafe { GetConsoleOutputCP() } +} +/// Sets the current input code page +pub fn set_input_code_page(code: u32) -> Result<()> { + let res = unsafe { SetConsoleCP(code) }; + if res == 0 { return Error::last() } + Ok(()) +} +/// Sets the current output code page +pub fn set_output_code_page(code: u32) -> Result<()> { + let res = unsafe { SetConsoleOutputCP(code) }; + if res == 0 { return Error::last() } + Ok(()) +} diff --git a/third_party/rust/wio/src/error.rs b/third_party/rust/wio/src/error.rs new file mode 100644 index 0000000000..4d321c1c8d --- /dev/null +++ b/third_party/rust/wio/src/error.rs @@ -0,0 +1,18 @@ +// 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.
+// All files in the project carrying such notice may not be copied, modified, or distributed
+// except according to those terms.
+use std::result;
+use winapi::shared::minwindef::DWORD;
+use winapi::um::errhandlingapi::GetLastError;
+#[derive(Clone, Copy, Debug)]
+pub struct Error(DWORD);
+impl Error {
+ pub fn code(&self) -> u32 { self.0 }
+ pub fn last<T>() -> Result<T> {
+ Err(Error(unsafe { GetLastError() }))
+ }
+}
+
+pub type Result<T> = result::Result<T, Error>;
diff --git a/third_party/rust/wio/src/handle.rs b/third_party/rust/wio/src/handle.rs new file mode 100644 index 0000000000..e19e950b6b --- /dev/null +++ b/third_party/rust/wio/src/handle.rs @@ -0,0 +1,71 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use error::{Error, Result}; +use std::{ + ops::Deref, + os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle}, + ptr::null_mut, +}; +use winapi::{ + um::{ + handleapi::{CloseHandle, DuplicateHandle}, + processthreadsapi::GetCurrentProcess, + winnt::{DUPLICATE_SAME_ACCESS, HANDLE}, + }, + shared::minwindef::FALSE, +}; + +pub struct Handle(HANDLE); +impl Handle { + // Takes ownership of the handle + pub unsafe fn new(handle: HANDLE) -> Handle { + Handle(handle) + } + pub fn close(self) -> Result<()> { + match unsafe { CloseHandle(self.into_raw_handle()) } { + 0 => Error::last(), + _ => Ok(()), + } + } + // Duplicates the handle without taking ownership + pub unsafe fn duplicate_from(handle: HANDLE) -> Result<Handle> { + let mut new_handle = null_mut(); + let res = DuplicateHandle( + GetCurrentProcess(), handle, GetCurrentProcess(), + &mut new_handle, 0, FALSE, DUPLICATE_SAME_ACCESS, + ); + match res { + 0 => Error::last(), + _ => Ok(Handle(new_handle)), + } + } +} +impl AsRawHandle for Handle { + fn as_raw_handle(&self) -> HANDLE { + self.0 + } +} +impl Deref for Handle { + type Target = HANDLE; + fn deref(&self) -> &HANDLE { &self.0 } +} +impl Drop for Handle { + fn drop(&mut self) { + let ret = unsafe { CloseHandle(self.0) }; + let err: Result<()> = Error::last(); + assert!(ret != 0, "{:?}", err); + } +} +impl FromRawHandle for Handle { + unsafe fn from_raw_handle(handle: HANDLE) -> Handle { + Handle(handle) + } +} +impl IntoRawHandle for Handle { + fn into_raw_handle(self) -> HANDLE { + self.0 + } +} diff --git a/third_party/rust/wio/src/lib.rs b/third_party/rust/wio/src/lib.rs new file mode 100644 index 0000000000..c50d002a27 --- /dev/null +++ b/third_party/rust/wio/src/lib.rs @@ -0,0 +1,20 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +#![cfg(windows)] +extern crate winapi; + +// pub mod apc; +pub mod com; +// pub mod console; +pub mod error; +// pub mod handle; +// pub mod perf; +// pub mod pipe; +// pub mod sleep; +// pub mod thread; +pub mod wide; + +pub use error::{Error, Result}; diff --git a/third_party/rust/wio/src/perf.rs b/third_party/rust/wio/src/perf.rs new file mode 100644 index 0000000000..0c00a06420 --- /dev/null +++ b/third_party/rust/wio/src/perf.rs @@ -0,0 +1,17 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use {k32}; + +pub fn frequency() -> i64 { + let mut freq = 0; + unsafe { k32::QueryPerformanceFrequency(&mut freq) }; + freq +} +pub fn counter() -> i64 { + let mut count = 0; + unsafe { k32::QueryPerformanceCounter(&mut count) }; + count +} diff --git a/third_party/rust/wio/src/pipe.rs b/third_party/rust/wio/src/pipe.rs new file mode 100644 index 0000000000..f0fe255022 --- /dev/null +++ b/third_party/rust/wio/src/pipe.rs @@ -0,0 +1,16 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use handle::{Handle}; + +pub struct NamedPipe(Handle); +impl NamedPipe { + //fn create(name: &[u16], access: Access, ) +} +pub enum Access { + Inbound, + Outbound, + Duplex, +} diff --git a/third_party/rust/wio/src/sleep.rs b/third_party/rust/wio/src/sleep.rs new file mode 100644 index 0000000000..bfe2cda5fa --- /dev/null +++ b/third_party/rust/wio/src/sleep.rs @@ -0,0 +1,23 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use {k32, w}; + +pub fn sleep(ms: u32) { + unsafe { k32::Sleep(ms) } +} +#[derive(Debug, Eq, PartialEq)] +pub enum WakeReason { + TimedOut, + CallbacksFired, +} +pub fn sleep_alertable(ms: u32) -> WakeReason { + let ret = unsafe { k32::SleepEx(ms, w::TRUE) }; + match ret { + 0 => WakeReason::TimedOut, + w::WAIT_IO_COMPLETION => WakeReason::CallbacksFired, + _ => unreachable!("SleepEx returned weird value of {:?}", ret), + } +} diff --git a/third_party/rust/wio/src/thread.rs b/third_party/rust/wio/src/thread.rs new file mode 100644 index 0000000000..417247b78b --- /dev/null +++ b/third_party/rust/wio/src/thread.rs @@ -0,0 +1,51 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use {Result, k32, last_error, w}; +use handle::{Handle}; +use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle}; +use std::thread::{JoinHandle}; + +pub struct Thread(Handle); +impl Thread { + pub fn current() -> Result<Thread> { + unsafe { Handle::duplicate_from(k32::GetCurrentThread()).map(Thread) } + } + /// Returns the old affinity mask on success + pub fn set_affinity_mask(&self, mask: usize) -> Result<usize> { + let res = unsafe { + k32::SetThreadAffinityMask(*self.0, mask as w::ULONG_PTR) + }; + match res { + 0 => last_error(), + prev => Ok(prev as usize), + } + } +} +impl<T> From<JoinHandle<T>> for Thread { + fn from(o: JoinHandle<T>) -> Thread { + unsafe { Thread::from_raw_handle(o.into_raw_handle()) } + } +} +impl<'a, T> From<&'a JoinHandle<T>> for Thread { + fn from(o: &'a JoinHandle<T>) -> Thread { + unsafe { Thread::from_raw_handle(o.as_raw_handle()) } + } +} +impl AsRawHandle for Thread { + fn as_raw_handle(&self) -> w::HANDLE { + self.0.as_raw_handle() + } +} +impl IntoRawHandle for Thread { + fn into_raw_handle(self) -> w::HANDLE { + self.0.into_raw_handle() + } +} +impl FromRawHandle for Thread { + unsafe fn from_raw_handle(handle: w::HANDLE) -> Thread { + Thread(Handle::from_raw_handle(handle)) + } +} diff --git a/third_party/rust/wio/src/ums.rs b/third_party/rust/wio/src/ums.rs new file mode 100644 index 0000000000..3100036867 --- /dev/null +++ b/third_party/rust/wio/src/ums.rs @@ -0,0 +1,3 @@ +// Copyright © 2016, Peter Atashian +// Licensed under the MIT License <LICENSE.md> +use {k32, w};
\ No newline at end of file diff --git a/third_party/rust/wio/src/wide.rs b/third_party/rust/wio/src/wide.rs new file mode 100644 index 0000000000..0b4d9fe416 --- /dev/null +++ b/third_party/rust/wio/src/wide.rs @@ -0,0 +1,59 @@ +// 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. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use std::ffi::{OsStr, OsString}; +use std::os::windows::ffi::{OsStrExt, OsStringExt}; +use std::path::PathBuf; +use std::slice::from_raw_parts; + +pub trait ToWide { + fn to_wide(&self) -> Vec<u16>; + fn to_wide_null(&self) -> Vec<u16>; +} +impl<T> ToWide for T where T: AsRef<OsStr> { + #[inline] + fn to_wide(&self) -> Vec<u16> { + self.as_ref().encode_wide().collect() + } + #[inline] + fn to_wide_null(&self) -> Vec<u16> { + self.as_ref().encode_wide().chain(Some(0)).collect() + } +} +pub trait FromWide where Self: Sized { + fn from_wide(wide: &[u16]) -> Self; + #[inline] + fn from_wide_null(wide: &[u16]) -> Self { + let len = wide.iter().take_while(|&&c| c != 0).count(); + Self::from_wide(&wide[..len]) + } + #[inline] + unsafe fn from_wide_ptr(wide: *const u16, len: usize) -> Self { + assert!(!wide.is_null()); + Self::from_wide(from_raw_parts(wide, len)) + } + #[inline] + unsafe fn from_wide_ptr_null(wide: *const u16) -> Self { + assert!(!wide.is_null()); + for i in 0.. { + if *wide.offset(i) == 0 { + return Self::from_wide_ptr(wide, i as usize) + } + } + unreachable!() + } +} +impl FromWide for OsString { + #[inline] + fn from_wide(wide: &[u16]) -> OsString { + OsStringExt::from_wide(wide) + } +} +impl FromWide for PathBuf { + #[inline] + fn from_wide(wide: &[u16]) -> PathBuf { + <OsString as OsStringExt>::from_wide(wide).into() + } +} |