1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#![cfg(windows)]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(test, allow(dead_code))]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![allow(unused_imports)]
#![allow(unused_macros)]
// Note(Lokathor): Please always sort return expressions so that the success
// case is given first, and then the error case second. Use whatever type of
// conditional expression is required to ensure this.
#![allow(clippy::if_not_else)]
// You generally need to have read MSDN to make sense of the unsafe here.
#![allow(clippy::missing_safety_doc)]

//! Easier wrappers for Win32 API stuff, safe when possible.
//!
//! # Cargo Features
//!
//! Essentially all content in this library is feature gated. Each module below
//! is named after the related module in `winapi`, and has its own feature gate.
//!
//! These docs are generated with all features active, but in your projects
//! you'll need to activate the features you want.

extern crate alloc;
use alloc::{string::String, vec, vec::Vec};

use core::{
  convert::TryFrom,
  ffi::c_void,
  marker::PhantomData,
  mem::size_of,
  ops::Deref,
  ptr::{null, null_mut, NonNull},
};

use chlorine::pick;

macro_rules! mk_newtype_bitflag32 {
  ($mask:ident, $getter:ident, $wither:ident, $setter:ident) => {
    #[allow(missing_docs)]
    #[inline]
    pub const fn $getter(self) -> bool {
      (self.0) & $mask > 0
    }
    #[allow(missing_docs)]
    #[inline]
    pub const fn $wither(self, new_val: bool) -> Self {
      Self(self.0 ^ (((new_val as u32).wrapping_neg() ^ self.0) & $mask))
    }
    #[allow(missing_docs)]
    #[inline]
    pub fn $setter(&mut self, new_val: bool) {
      *self = self.$wither(new_val);
    }
  };
}

/// Cast an optional shared ref to a raw const pointer.
#[inline]
#[allow(dead_code)]
pub(crate) fn opt_to_ptr<T>(opt: Option<&T>) -> *const T {
  unsafe { core::mem::transmute(opt) }
}

/// Cast an optional unique ref to a raw mut pointer.
#[inline]
#[allow(dead_code)]
pub(crate) fn opt_to_mut_ptr<T>(opt: Option<&mut T>) -> *mut T {
  unsafe { core::mem::transmute(opt) }
}

/// Allocates a utf-16 version of the `&str` given.
///
/// **Note:** This will not filter any null characters (`'\0'`) that are in the
/// string. If you have an internal null Windows might think it means the end of
/// the string and not see your full string, which will probably make it do
/// something you don't want.
#[inline]
pub fn wide(s: &str) -> Vec<u16> {
  s.encode_utf16().collect()
}

/// Allocates a utf-16, null-terminated version of the `&str` given.
///
/// **Note:** This will not filter any null characters (`'\0'`) that are in the
/// string. If you have an internal null Windows will think it means the end of
/// the string and not see your full string, which will probably make it do
/// something you don't want.
#[inline]
pub fn wide_null(s: &str) -> Vec<u16> {
  s.encode_utf16().chain(Some(0)).collect()
}

//

pick! {
  if #[cfg(feature = "consoleapi")] {
    pub mod consoleapi;
    pub use consoleapi::*;
  }
}

pick! {
  if #[cfg(feature = "errhandlingapi")] {
    pub mod errhandlingapi;
    pub use errhandlingapi::*;
  }
}

pick! {
  if #[cfg(feature = "handleapi")] {
    pub mod handleapi;
    pub use handleapi::*;
  }
}

pick! {
  if #[cfg(feature = "libloaderapi")] {
    pub mod libloaderapi;
    pub use libloaderapi::*;
  }
}

pick! {
  if #[cfg(feature = "minwinbase")] {
    pub mod minwinbase;
    pub use minwinbase::*;
  }
}

pick! {
  if #[cfg(feature = "minwindef")] {
    pub mod minwindef;
    pub use minwindef::*;
  }
}

pick! {
  if #[cfg(feature = "processenv")] {
    pub mod processenv;
    pub use processenv::*;
  }
}

pick! {
  if #[cfg(feature = "processthreadsapi")] {
    pub mod processthreadsapi;
    pub(crate) use processthreadsapi::*;
  }
}

pick! {
  if #[cfg(feature = "profileapi")] {
    pub mod profileapi;
    pub use profileapi::*;
  }
}

pick! {
  if #[cfg(feature = "winbase")] {
    pub mod winbase;
    pub use winbase::*;
  }
}

pick! {
  if #[cfg(feature = "wincon")] {
    pub mod wincon;
    pub use wincon::*;
  }
}

pick! {
  if #[cfg(feature = "wincontypes")] {
    pub mod wincontypes;
    pub use wincontypes::*;
  }
}

pick! {
  if #[cfg(feature = "windef")] {
    pub mod windef;
    pub use windef::*;
  }
}

pick! {
  if #[cfg(feature = "winerror")] {
    pub mod winerror;
    pub use winerror::*;
  }
}

pick! {
  if #[cfg(feature = "wingdi")] {
    pub mod wingdi;
    pub use wingdi::*;
  }
}

pick! {
  if #[cfg(feature = "winnt")] {
    pub mod winnt;
    pub use winnt::*;
  }
}

pick! {
  if #[cfg(feature = "winuser")] {
    pub mod winuser;
    pub use winuser::*;
  }
}