diff options
Diffstat (limited to 'third_party/rust/wio')
-rw-r--r-- | third_party/rust/wio/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/wio/Cargo.toml | 28 | ||||
-rw-r--r-- | third_party/rust/wio/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | third_party/rust/wio/LICENSE-MIT | 19 | ||||
-rw-r--r-- | third_party/rust/wio/README.md | 4 | ||||
-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 |
17 files changed, 919 insertions, 0 deletions
diff --git a/third_party/rust/wio/.cargo-checksum.json b/third_party/rust/wio/.cargo-checksum.json new file mode 100644 index 0000000000..3005879109 --- /dev/null +++ b/third_party/rust/wio/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"89d6e29e2d13fcf58de301fed58841998c9dd18dd2397f2404ba77ba3dd66730","LICENSE-APACHE":"b40930bbcf80744c86c46a12bc9da056641d722716c378f5659b9e555ef833e1","LICENSE-MIT":"5b19674a1db628a475850a131956ed49521b744e3dda8f5a94141f9aba681219","README.md":"d08ab02a40b9934719cc5f9083aae6b012b2535827048225484adca26776babd","src/apc.rs":"8baef3e1fde88c79c22fda4acc0c56183388a188251fd08b38d6e70eb6a4874f","src/com.rs":"419c855c84dbc93e0ffe9668ad1eece78a73504689c7986a0b27c57256f59659","src/console.rs":"d02d4c83083487159e9626159a27b2b99620d60c85fd01421af9a4d5b441cc16","src/error.rs":"0869b4b1bc731b2d66fc36c33c205d9c888ffc6a057dff61847185357c290f49","src/handle.rs":"322b7881466505c240552171d1b8db0c70fc85e05baf921129bc7ab0a4e54f90","src/lib.rs":"34be2562e1e006a2ada84fabeaf8bcfc3abf91b9f516faa291d58470bb638443","src/perf.rs":"0a50ec0b26bd9d3ec257d1b5fe02787337bc2053bb1e189864937a37ba5dea3d","src/pipe.rs":"671753d23dfbcd17ffcd1c1570beca3720502e9059ef5fde55d5f8e6413da1b3","src/sleep.rs":"63acd7e403b13f21f1a5add47ab79df61deab43b42db24c3570e2867bba454b7","src/thread.rs":"4ab1da513bfb0dc099ddaf7ce6622d46423007a7ec7a902064bf24b1805b63ae","src/ums.rs":"024f1513de1f72d6f8a796567f08f1a3ac728ab1a83ae94a9cd851f5d9d7e9b2","src/wide.rs":"443ef562870d316e1fd967ae9752c98cc9b7483abb0ad79b295628cc9440c3ad"},"package":"5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5"}
\ No newline at end of file diff --git a/third_party/rust/wio/Cargo.toml b/third_party/rust/wio/Cargo.toml new file mode 100644 index 0000000000..2e1c29ab2a --- /dev/null +++ b/third_party/rust/wio/Cargo.toml @@ -0,0 +1,28 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "wio" +version = "0.2.2" +authors = ["Peter Atashian <retep998@gmail.com>"] +include = ["/src/**/*", "/Cargo.toml", "/LICENSE-MIT", "/LICENSE-APACHE", "/build.rs", "/README.md"] +description = "Windows IO wrapper" +readme = "README.md" +keywords = ["windows", "ffi", "win32", "com"] +categories = ["api-bindings", "os::windows-apis"] +license = "MIT/Apache-2.0" +repository = "https://github.com/retep998/wio-rs" +[dependencies.winapi] +version = "0.3" +features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "minwindef", "processthreadsapi", "std", "unknwnbase", "wincon", "winnt"] +[dev-dependencies.rand] +version = "0.4" diff --git a/third_party/rust/wio/LICENSE-APACHE b/third_party/rust/wio/LICENSE-APACHE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/third_party/rust/wio/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/third_party/rust/wio/LICENSE-MIT b/third_party/rust/wio/LICENSE-MIT new file mode 100644 index 0000000000..796e929aa5 --- /dev/null +++ b/third_party/rust/wio/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright (c) 2015 The winapi-rs Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/rust/wio/README.md b/third_party/rust/wio/README.md new file mode 100644 index 0000000000..3a7a0a9dad --- /dev/null +++ b/third_party/rust/wio/README.md @@ -0,0 +1,4 @@ +# wio-rs # + +A middle-level wrapper around various things in Windows API. +Designed to be a very thin layer around Windows API to provide a safe Rusty API but without hiding any functionality. 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() + } +} |