Skip to main content

fenestroj/
lib.rs

1#![cfg(windows)]
2#![cfg_attr(not(test), no_std)]
3#![cfg_attr(test, allow(dead_code))]
4#![warn(missing_docs)]
5#![warn(missing_debug_implementations)]
6#![allow(unused_imports)]
7#![allow(unused_macros)]
8// Note(Lokathor): Please always sort return expressions so that the success
9// case is given first, and then the error case second. Use whatever type of
10// conditional expression is required to ensure this.
11#![allow(clippy::if_not_else)]
12// You generally need to have read MSDN to make sense of the unsafe here.
13#![allow(clippy::missing_safety_doc)]
14
15//! Easier wrappers for Win32 API stuff, safe when possible.
16//!
17//! # Cargo Features
18//!
19//! Essentially all content in this library is feature gated. Each module below
20//! is named after the related module in `winapi`, and has its own feature gate.
21//!
22//! These docs are generated with all features active, but in your projects
23//! you'll need to activate the features you want.
24
25extern crate alloc;
26use alloc::{string::String, vec, vec::Vec};
27
28use core::{
29  convert::TryFrom,
30  ffi::c_void,
31  marker::PhantomData,
32  mem::size_of,
33  ops::Deref,
34  ptr::{null, null_mut, NonNull},
35};
36
37use chlorine::pick;
38
39macro_rules! mk_newtype_bitflag32 {
40  ($mask:ident, $getter:ident, $wither:ident, $setter:ident) => {
41    #[allow(missing_docs)]
42    #[inline]
43    pub const fn $getter(self) -> bool {
44      (self.0) & $mask > 0
45    }
46    #[allow(missing_docs)]
47    #[inline]
48    pub const fn $wither(self, new_val: bool) -> Self {
49      Self(self.0 ^ (((new_val as u32).wrapping_neg() ^ self.0) & $mask))
50    }
51    #[allow(missing_docs)]
52    #[inline]
53    pub fn $setter(&mut self, new_val: bool) {
54      *self = self.$wither(new_val);
55    }
56  };
57}
58
59/// Cast an optional shared ref to a raw const pointer.
60#[inline]
61#[allow(dead_code)]
62pub(crate) fn opt_to_ptr<T>(opt: Option<&T>) -> *const T {
63  unsafe { core::mem::transmute(opt) }
64}
65
66/// Cast an optional unique ref to a raw mut pointer.
67#[inline]
68#[allow(dead_code)]
69pub(crate) fn opt_to_mut_ptr<T>(opt: Option<&mut T>) -> *mut T {
70  unsafe { core::mem::transmute(opt) }
71}
72
73/// Allocates a utf-16 version of the `&str` given.
74///
75/// **Note:** This will not filter any null characters (`'\0'`) that are in the
76/// string. If you have an internal null Windows might think it means the end of
77/// the string and not see your full string, which will probably make it do
78/// something you don't want.
79#[inline]
80pub fn wide(s: &str) -> Vec<u16> {
81  s.encode_utf16().collect()
82}
83
84/// Allocates a utf-16, null-terminated version of the `&str` given.
85///
86/// **Note:** This will not filter any null characters (`'\0'`) that are in the
87/// string. If you have an internal null Windows will think it means the end of
88/// the string and not see your full string, which will probably make it do
89/// something you don't want.
90#[inline]
91pub fn wide_null(s: &str) -> Vec<u16> {
92  s.encode_utf16().chain(Some(0)).collect()
93}
94
95//
96
97pick! {
98  if #[cfg(feature = "consoleapi")] {
99    pub mod consoleapi;
100    pub use consoleapi::*;
101  }
102}
103
104pick! {
105  if #[cfg(feature = "errhandlingapi")] {
106    pub mod errhandlingapi;
107    pub use errhandlingapi::*;
108  }
109}
110
111pick! {
112  if #[cfg(feature = "handleapi")] {
113    pub mod handleapi;
114    pub use handleapi::*;
115  }
116}
117
118pick! {
119  if #[cfg(feature = "libloaderapi")] {
120    pub mod libloaderapi;
121    pub use libloaderapi::*;
122  }
123}
124
125pick! {
126  if #[cfg(feature = "minwinbase")] {
127    pub mod minwinbase;
128    pub use minwinbase::*;
129  }
130}
131
132pick! {
133  if #[cfg(feature = "minwindef")] {
134    pub mod minwindef;
135    pub use minwindef::*;
136  }
137}
138
139pick! {
140  if #[cfg(feature = "processenv")] {
141    pub mod processenv;
142    pub use processenv::*;
143  }
144}
145
146pick! {
147  if #[cfg(feature = "processthreadsapi")] {
148    pub mod processthreadsapi;
149    pub(crate) use processthreadsapi::*;
150  }
151}
152
153pick! {
154  if #[cfg(feature = "profileapi")] {
155    pub mod profileapi;
156    pub use profileapi::*;
157  }
158}
159
160pick! {
161  if #[cfg(feature = "winbase")] {
162    pub mod winbase;
163    pub use winbase::*;
164  }
165}
166
167pick! {
168  if #[cfg(feature = "wincon")] {
169    pub mod wincon;
170    pub use wincon::*;
171  }
172}
173
174pick! {
175  if #[cfg(feature = "wincontypes")] {
176    pub mod wincontypes;
177    pub use wincontypes::*;
178  }
179}
180
181pick! {
182  if #[cfg(feature = "windef")] {
183    pub mod windef;
184    pub use windef::*;
185  }
186}
187
188pick! {
189  if #[cfg(feature = "winerror")] {
190    pub mod winerror;
191    pub use winerror::*;
192  }
193}
194
195pick! {
196  if #[cfg(feature = "wingdi")] {
197    pub mod wingdi;
198    pub use wingdi::*;
199  }
200}
201
202pick! {
203  if #[cfg(feature = "winnt")] {
204    pub mod winnt;
205    pub use winnt::*;
206  }
207}
208
209pick! {
210  if #[cfg(feature = "winuser")] {
211    pub mod winuser;
212    pub use winuser::*;
213  }
214}