Bug 1853084 - Upgrade mio to 0.8.8. r=emilio,supply-chain-reviewers

Now that windows-sys is vendored, we can upgrade mio to a version that
uses it.

Differential Revision: https://phabricator.services.mozilla.com/D188154
This commit is contained in:
Mike Hommey 2023-09-18 19:55:21 +00:00
parent 4b2bb2c544
commit f0ee4a497a
102 changed files with 2781 additions and 21822 deletions

31
Cargo.lock generated
View file

@ -260,7 +260,7 @@ dependencies = [
"libc",
"log",
"memmap2",
"mio 0.8.0",
"mio 0.8.8",
"scopeguard",
"serde",
"serde_bytes",
@ -2159,7 +2159,6 @@ dependencies = [
"mdns_service",
"midir_impl",
"mime-guess-ffi",
"mio 0.8.0",
"moz_asserts",
"mozannotation_client",
"mozannotation_server",
@ -2199,7 +2198,6 @@ dependencies = [
"webext_storage_bridge",
"webrender_bindings",
"wgpu_bindings",
"windows-sys",
"wpf-gpu-raster",
"xpcom",
]
@ -3481,15 +3479,14 @@ dependencies = [
[[package]]
name = "mio"
version = "0.8.0"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"log",
"miow",
"ntapi 0.3.999",
"winapi",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
]
[[package]]
@ -3935,22 +3932,6 @@ dependencies = [
"nsstring",
]
[[package]]
name = "ntapi"
version = "0.3.999"
dependencies = [
"ntapi 0.4.0",
]
[[package]]
name = "ntapi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"
dependencies = [
"winapi",
]
[[package]]
name = "num-derive"
version = "0.4.0"
@ -5530,7 +5511,7 @@ dependencies = [
"bytes",
"libc",
"memchr",
"mio 0.8.0",
"mio 0.8.8",
"num_cpus",
"pin-project-lite",
"socket2",

View file

@ -137,9 +137,6 @@ wasi = { path = "build/rust/wasi" }
bindgen_0_63 = { package = "bindgen", path = "build/rust/bindgen-0.63" }
bindgen = { path = "build/rust/bindgen" }
# Patch ntapi 0.3 to 0.4
ntapi = { path = "build/rust/ntapi" }
# Patch nix 0.24 to 0.26
nix = { path = "build/rust/nix" }

View file

@ -1,11 +0,0 @@
[package]
name = "ntapi"
version = "0.3.999"
edition = "2018"
license = "MPL-2.0"
[lib]
path = "lib.rs"
[dependencies.ntapi]
version = "0.4"

View file

@ -1,5 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
pub use ntapi::*;

View file

@ -2200,6 +2200,11 @@ who = "Bobby Holley <bobbyholley@gmail.com>"
criteria = "safe-to-run"
delta = "0.6.21 -> 0.6.23"
[[audits.mio]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.8.0 -> 0.8.6"
[[audits.moz_cbor]]
who = "Bobby Holley <bobbyholley@gmail.com>"
criteria = "safe-to-deploy"

View file

@ -938,6 +938,12 @@ criteria = "safe-to-deploy"
delta = "0.7.1 -> 0.8.0"
notes = "This was a small update to the crate which has to do with Rust language features and compiler versions, no substantial changes."
[[audits.bytecode-alliance.audits.mio]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
delta = "0.8.6 -> 0.8.8"
notes = "Mostly OS portability updates along with some minor bugfixes."
[[audits.bytecode-alliance.audits.peeking_take_while]]
who = "Nick Fitzgerald <fitzgen@gmail.com>"
criteria = "safe-to-deploy"

File diff suppressed because one or more lines are too long

View file

@ -1,3 +1,126 @@
# 0.8.8
## Fixed
* Fix compilation on WASI (https://github.com/tokio-rs/mio/pull/1676).
# 0.8.7
## Added
* Add/fix support for tvOS and watchOS, Mio should now build for tvOS and
watchOS, but we don't have a CI setup yet
(https://github.com/tokio-rs/mio/pull/1658).
## Changed
* Made the `log` dependency optional behind the `log` feature flag (enabled by
default). Users that disabled Mio's default features will now not see any
logging from Mio, enabling the `log` feature will fix that. This was done in
response to the `log` crate increasing it's MSRV to v1.60, see
https://github.com/rust-lang/log/pull/552
(https://github.com/tokio-rs/mio/pull/1673).
* Update windows-sys dependency to v0.48
(https://github.com/tokio-rs/mio/pull/1663).
## Fixed
* Fix overflow in `Poll::poll` when using `Duration::MAX` as timeout
(https://github.com/tokio-rs/mio/pull/1657).
# 0.8.6
## Added
* `Interest::PRIORITY` on Linux and Android, to trigger `Event::is_priority`
(https://github.com/tokio-rs/mio/pull/1647).
## Changed
* Updated windows-sys to 0.45
(https://github.com/tokio-rs/mio/pull/1644).
* We started testing with sanitizers on the CI
(https://github.com/tokio-rs/mio/pull/1648).
## Fixed
* A number of potential fd leaks when setup resulted in an error right after
creation (https://github.com/tokio-rs/mio/pull/1636).
* Less truncating for timeout values in `Poll::poll`
(https://github.com/tokio-rs/mio/pull/1642).
# 0.8.5
## Changed
* Updated `windows-sys` to 0.42.0
(https://github.com/tokio-rs/mio/pull/1624).
* Officially document Wine as not supported, some people claimed it worked,
other claims it doesn't, but nobody stepped up to fix the problem
(https://github.com/tokio-rs/mio/pull/1596).
* Switch to GitHub Actions
(https://github.com/tokio-rs/mio/pull/1598, https://github.com/tokio-rs/mio/pull/1601).
* Documented the current Poll::poll time behaviour
(https://github.com/tokio-rs/mio/pull/1603).
## Fixed
* Timeout less than one millisecond becoming zero millsiconds
(https://github.com/tokio-rs/mio/pull/1615, https://github.com/tokio-rs/mio/pull/1616)
* Undefined reference to `epoll\_create1` on Android API level < 21.
(https://github.com/tokio-rs/mio/pull/1590).
# 0.8.4
## Added
* Support `Registery::try_clone` on `wasm32-wasi`
(https://github.com/tokio-rs/mio/pull/1576).
* Add docs about polling without registering event sources
(https://github.com/tokio-rs/mio/pull/1585).
# 0.8.3
## Changed
* Replace `winapi` dependency with `windows-sys`.
(https://github.com/tokio-rs/mio/pull/1556).
* Future proofed the kevent ABI for FreeBSD
(https://github.com/tokio-rs/mio/pull/1572).
## Fixed
* Improved support for Redox, making it possible to run on stable Rust
(https://github.com/tokio-rs/mio/pull/1555).
* Don't ignore EAGAIN in UDS connect call
(https://github.com/tokio-rs/mio/pull/1564).
* Documentation of `TcpStream::connect`
(https://github.com/tokio-rs/mio/pull/1565).
# 0.8.2
## Added
* Experimental support for Redox.
# 0.8.1
## Added
* Add `try_io` method to all I/O types (#1551). This execute a user defined I/O
closure while updating Mio's internal state ensuring that the I/O type
receives more events if it hits a WouldBlock error. This is added to the
following types:
* `TcpStream`
* `UdpSocket`
* `UnixDatagram`
* `UnixStream`
* `unix::pipe::Sender`
* `unix::pipe::Receiver`
* Basic, experimental support for `wasm32-wasi` target (#1549). Note that a lot
of time type are still missing, e.g. the `Waker`, and may never be possible to
implement.
# 0.8.0
## Removed
@ -8,6 +131,7 @@
* udp (replaced with "net" feature).
* uds (replaced with "net" feature).
* pipe (replaced with "os-ext" feature).
* os-util (replaced with "os-ext" feature).
* `TcpSocket` type
(https://github.com/tokio-rs/mio/commit/02e9be41f27daf822575444fdd2b3067433a5996).
The socket2 crate provides all the functionality and more.

133
third_party/rust/mio/Cargo.lock generated vendored
View file

@ -8,18 +8,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "env_logger"
version = "0.8.4"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
dependencies = [
"log",
]
[[package]]
name = "getrandom"
version = "0.2.3"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
@ -28,66 +28,46 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.107"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "log"
version = "0.4.14"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "mio"
version = "0.8.0"
version = "0.8.8"
dependencies = [
"env_logger",
"libc",
"log",
"miow",
"ntapi",
"rand",
"winapi",
]
[[package]]
name = "miow"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
"winapi",
]
[[package]]
name = "ntapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
dependencies = [
"winapi",
"wasi",
"windows-sys",
]
[[package]]
name = "ppv-lite86"
version = "0.2.15"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "rand"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
@ -102,46 +82,81 @@ dependencies = [
[[package]]
name = "rand_core"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core",
]
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
"windows-targets",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"

View file

@ -12,53 +12,116 @@
[package]
edition = "2018"
name = "mio"
version = "0.8.0"
authors = ["Carl Lerche <me@carllerche.com>", "Thomas de Zeeuw <thomasdezeeuw@gmail.com>", "Tokio Contributors <team@tokio.rs>"]
include = ["Cargo.toml", "LICENSE", "README.md", "CHANGELOG.md", "src/**/*.rs", "examples/**/*.rs"]
description = "Lightweight non-blocking IO"
version = "0.8.8"
authors = [
"Carl Lerche <me@carllerche.com>",
"Thomas de Zeeuw <thomasdezeeuw@gmail.com>",
"Tokio Contributors <team@tokio.rs>",
]
include = [
"Cargo.toml",
"LICENSE",
"README.md",
"CHANGELOG.md",
"src/**/*.rs",
"examples/**/*.rs",
]
description = "Lightweight non-blocking I/O."
homepage = "https://github.com/tokio-rs/mio"
readme = "README.md"
keywords = ["io", "async", "non-blocking"]
keywords = [
"io",
"async",
"non-blocking",
]
categories = ["asynchronous"]
license = "MIT"
repository = "https://github.com/tokio-rs/mio"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
targets = ["aarch64-apple-ios", "aarch64-linux-android", "x86_64-apple-darwin", "x86_64-pc-windows-msvc", "x86_64-unknown-dragonfly", "x86_64-unknown-freebsd", "x86_64-unknown-illumos", "x86_64-unknown-linux-gnu", "x86_64-unknown-netbsd", "x86_64-unknown-openbsd"]
rustdoc-args = [
"--cfg",
"docsrs",
]
targets = [
"aarch64-apple-ios",
"aarch64-linux-android",
"wasm32-wasi",
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
"x86_64-unknown-dragonfly",
"x86_64-unknown-freebsd",
"x86_64-unknown-illumos",
"x86_64-unknown-linux-gnu",
"x86_64-unknown-netbsd",
"x86_64-unknown-openbsd",
]
[package.metadata.playground]
features = ["os-poll", "os-ext", "net"]
features = [
"os-poll",
"os-ext",
"net",
]
[[example]]
name = "tcp_server"
required-features = ["os-poll", "net"]
required-features = [
"os-poll",
"net",
]
[[example]]
name = "tcp_listenfd_server"
required-features = [
"os-poll",
"net",
]
[[example]]
name = "udp_server"
required-features = ["os-poll", "net"]
required-features = [
"os-poll",
"net",
]
[dependencies.log]
version = "0.4.8"
optional = true
[dev-dependencies.env_logger]
version = "0.8.4"
version = "0.9.3"
default-features = false
[dev-dependencies.rand]
version = "0.8"
[features]
default = []
default = ["log"]
net = []
os-ext = ["os-poll"]
os-ext = [
"os-poll",
"windows-sys/Win32_System_Pipes",
"windows-sys/Win32_Security",
]
os-poll = []
[target."cfg(target_os = \"wasi\")".dependencies.libc]
version = "0.2.121"
[target."cfg(target_os = \"wasi\")".dependencies.wasi]
version = "0.11.0"
[target."cfg(unix)".dependencies.libc]
version = "0.2.86"
[target."cfg(windows)".dependencies.miow]
version = "0.3.6"
version = "0.2.121"
[target."cfg(windows)".dependencies.ntapi]
version = "0.3"
[target."cfg(windows)".dependencies.winapi]
version = "0.3"
features = ["winsock2", "mswsock"]
[target."cfg(windows)".dependencies.windows-sys]
version = "0.48"
features = [
"Win32_Foundation",
"Win32_Networking_WinSock",
"Win32_Storage_FileSystem",
"Win32_System_IO",
"Win32_System_WindowsProgramming",
]

View file

@ -1,4 +1,4 @@
# Mio Metal IO
# Mio Metal I/O
Mio is a fast, low-level I/O library for Rust focusing on non-blocking APIs and
event notification for building high performance I/O apps with as little
@ -6,23 +6,22 @@ overhead as possible over the OS abstractions.
[![Crates.io][crates-badge]][crates-url]
[![MIT licensed][mit-badge]][mit-url]
[![Build Status][azure-badge]][azure-url]
[![Build Status][actions-badge]][actions-url]
[![Build Status][cirrus-badge]][cirrus-url]
[crates-badge]: https://img.shields.io/crates/v/mio.svg
[crates-url]: https://crates.io/crates/mio
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
[mit-url]: LICENSE
[azure-badge]: https://dev.azure.com/tokio-rs/Tokio/_apis/build/status/tokio-rs.mio?branchName=master
[azure-url]: https://dev.azure.com/tokio-rs/Tokio/_build/latest?definitionId=2&branchName=master
[actions-badge]: https://github.com/tokio-rs/mio/workflows/CI/badge.svg
[actions-url]: https://github.com/tokio-rs/mio/actions?query=workflow%3ACI+branch%3Amaster
[cirrus-badge]: https://api.cirrus-ci.com/github/tokio-rs/mio.svg
[cirrus-url]: https://cirrus-ci.com/github/tokio-rs/mio
**API documentation**
* [master](https://tokio-rs.github.io/mio/doc/mio/)
* [v0.8](https://docs.rs/mio/^0.8)
* [v0.7](https://docs.rs/mio/^0.7)
* [v0.6](https://docs.rs/mio/^0.6)
This is a low level library, if you are looking for something easier to get
started with, see [Tokio](https://tokio.rs).
@ -33,7 +32,7 @@ To use `mio`, first add this to your `Cargo.toml`:
```toml
[dependencies]
mio = "0.7"
mio = "0.8"
```
Next we can start using Mio. The following is quick introduction using
@ -135,11 +134,9 @@ Currently supported platforms:
* Linux
* NetBSD
* OpenBSD
* Solaris
* Windows
* iOS
* macOS
* Wine (version 6.11+, see [issue #1444])
There are potentially others. If you find that Mio works on another
platform, submit a PR to update the list!
@ -152,13 +149,16 @@ The Windows implementation for polling sockets is using the [wepoll] strategy.
This uses the Windows AFD system to access socket readiness events.
[wepoll]: https://github.com/piscisaureus/wepoll
[issue #1444]: https://github.com/tokio-rs/mio/issues/1444
### Unsupported
* Haiku, see [issue #1472]
* Solaris, see [issue #1152]
* Wine, see [issue #1444]
[issue #1472]: https://github.com/tokio-rs/mio/issues/1472
[issue #1152]: https://github.com/tokio-rs/mio/issues/1152
[issue #1444]: https://github.com/tokio-rs/mio/issues/1444
## Community

View file

@ -0,0 +1,209 @@
// You can run this example from the root of the mio repo:
// cargo run --example tcp_listenfd_server --features="os-poll net"
// or with wasi:
// cargo +nightly build --target wasm32-wasi --example tcp_listenfd_server --features="os-poll net"
// wasmtime run --tcplisten 127.0.0.1:9000 --env 'LISTEN_FDS=1' target/wasm32-wasi/debug/examples/tcp_listenfd_server.wasm
use mio::event::Event;
use mio::net::{TcpListener, TcpStream};
use mio::{Events, Interest, Poll, Registry, Token};
use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::str::from_utf8;
// Setup some tokens to allow us to identify which event is for which socket.
const SERVER: Token = Token(0);
// Some data we'll send over the connection.
const DATA: &[u8] = b"Hello world!\n";
#[cfg(not(windows))]
fn get_first_listen_fd_listener() -> Option<std::net::TcpListener> {
#[cfg(unix)]
use std::os::unix::io::FromRawFd;
#[cfg(target_os = "wasi")]
use std::os::wasi::io::FromRawFd;
let stdlistener = unsafe { std::net::TcpListener::from_raw_fd(3) };
stdlistener.set_nonblocking(true).unwrap();
Some(stdlistener)
}
#[cfg(windows)]
fn get_first_listen_fd_listener() -> Option<std::net::TcpListener> {
// Windows does not support `LISTEN_FDS`
None
}
fn main() -> io::Result<()> {
env_logger::init();
std::env::var("LISTEN_FDS").expect("LISTEN_FDS environment variable unset");
// Create a poll instance.
let mut poll = Poll::new()?;
// Create storage for events.
let mut events = Events::with_capacity(128);
// Setup the TCP server socket.
let mut server = {
let stdlistener = get_first_listen_fd_listener().unwrap();
println!("Using preopened socket FD 3");
println!("You can connect to the server using `nc`:");
match stdlistener.local_addr() {
Ok(a) => println!(" $ nc {} {}", a.ip(), a.port()),
Err(_) => println!(" $ nc <IP> <PORT>"),
}
println!("You'll see our welcome message and anything you type will be printed here.");
TcpListener::from_std(stdlistener)
};
// Register the server with poll we can receive events for it.
poll.registry()
.register(&mut server, SERVER, Interest::READABLE)?;
// Map of `Token` -> `TcpStream`.
let mut connections = HashMap::new();
// Unique token for each incoming connection.
let mut unique_token = Token(SERVER.0 + 1);
loop {
poll.poll(&mut events, None)?;
for event in events.iter() {
match event.token() {
SERVER => loop {
// Received an event for the TCP server socket, which
// indicates we can accept an connection.
let (mut connection, address) = match server.accept() {
Ok((connection, address)) => (connection, address),
Err(ref e) if would_block(e) => {
// If we get a `WouldBlock` error we know our
// listener has no more incoming connections queued,
// so we can return to polling and wait for some
// more.
break;
}
Err(e) => {
// If it was any other kind of error, something went
// wrong and we terminate with an error.
return Err(e);
}
};
println!("Accepted connection from: {}", address);
let token = next(&mut unique_token);
poll.registry()
.register(&mut connection, token, Interest::WRITABLE)?;
connections.insert(token, connection);
},
token => {
// Maybe received an event for a TCP connection.
let done = if let Some(connection) = connections.get_mut(&token) {
handle_connection_event(poll.registry(), connection, event)?
} else {
// Sporadic events happen, we can safely ignore them.
false
};
if done {
if let Some(mut connection) = connections.remove(&token) {
poll.registry().deregister(&mut connection)?;
}
}
}
}
}
}
}
fn next(current: &mut Token) -> Token {
let next = current.0;
current.0 += 1;
Token(next)
}
/// Returns `true` if the connection is done.
fn handle_connection_event(
registry: &Registry,
connection: &mut TcpStream,
event: &Event,
) -> io::Result<bool> {
if event.is_writable() {
// We can (maybe) write to the connection.
match connection.write(DATA) {
// We want to write the entire `DATA` buffer in a single go. If we
// write less we'll return a short write error (same as
// `io::Write::write_all` does).
Ok(n) if n < DATA.len() => return Err(io::ErrorKind::WriteZero.into()),
Ok(_) => {
// After we've written something we'll reregister the connection
// to only respond to readable events.
registry.reregister(connection, event.token(), Interest::READABLE)?
}
// Would block "errors" are the OS's way of saying that the
// connection is not actually ready to perform this I/O operation.
Err(ref err) if would_block(err) => {}
// Got interrupted (how rude!), we'll try again.
Err(ref err) if interrupted(err) => {
return handle_connection_event(registry, connection, event)
}
// Other errors we'll consider fatal.
Err(err) => return Err(err),
}
}
if event.is_readable() {
let mut connection_closed = false;
let mut received_data = vec![0; 4096];
let mut bytes_read = 0;
// We can (maybe) read from the connection.
loop {
match connection.read(&mut received_data[bytes_read..]) {
Ok(0) => {
// Reading 0 bytes means the other side has closed the
// connection or is done writing, then so are we.
connection_closed = true;
break;
}
Ok(n) => {
bytes_read += n;
if bytes_read == received_data.len() {
received_data.resize(received_data.len() + 1024, 0);
}
}
// Would block "errors" are the OS's way of saying that the
// connection is not actually ready to perform this I/O operation.
Err(ref err) if would_block(err) => break,
Err(ref err) if interrupted(err) => continue,
// Other errors we'll consider fatal.
Err(err) => return Err(err),
}
}
if bytes_read != 0 {
let received_data = &received_data[..bytes_read];
if let Ok(str_buf) = from_utf8(received_data) {
println!("Received data: {}", str_buf.trim_end());
} else {
println!("Received (none UTF-8) data: {:?}", received_data);
}
}
if connection_closed {
println!("Connection closed");
return Ok(true);
}
}
Ok(false)
}
fn would_block(err: &io::Error) -> bool {
err.kind() == io::ErrorKind::WouldBlock
}
fn interrupted(err: &io::Error) -> bool {
err.kind() == io::ErrorKind::Interrupted
}

View file

@ -13,6 +13,7 @@ const SERVER: Token = Token(0);
// Some data we'll send over the connection.
const DATA: &[u8] = b"Hello world!\n";
#[cfg(not(target_os = "wasi"))]
fn main() -> io::Result<()> {
env_logger::init();
@ -181,3 +182,8 @@ fn would_block(err: &io::Error) -> bool {
fn interrupted(err: &io::Error) -> bool {
err.kind() == io::ErrorKind::Interrupted
}
#[cfg(target_os = "wasi")]
fn main() {
panic!("can't bind to an address with wasi")
}

View file

@ -1,14 +1,16 @@
// You can run this example from the root of the mio repo:
// cargo run --example udp_server --features="os-poll net"
use log::warn;
use mio::net::UdpSocket;
use mio::{Events, Interest, Poll, Token};
use std::io;
// A token to allow us to identify which event is for the `UdpSocket`.
const UDP_SOCKET: Token = Token(0);
#[cfg(not(target_os = "wasi"))]
fn main() -> io::Result<()> {
use mio::net::UdpSocket;
env_logger::init();
// Create a poll instance.
@ -19,6 +21,7 @@ fn main() -> io::Result<()> {
// Setup the UDP socket.
let addr = "127.0.0.1:9000".parse().unwrap();
let mut socket = UdpSocket::bind(addr)?;
// Register our socket with the token defined above and an interest in being
@ -75,3 +78,8 @@ fn main() -> io::Result<()> {
}
}
}
#[cfg(target_os = "wasi")]
fn main() {
panic!("can't bind to an address with wasi")
}

View file

@ -62,7 +62,7 @@ impl Event {
/// | [kqueue] | `EV_ERROR` and `EV_EOF` with `fflags` set to `0`. |
///
/// [OS selector]: ../struct.Poll.html#implementation-notes
/// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
/// [epoll]: https://man7.org/linux/man-pages/man7/epoll.7.html
/// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
pub fn is_error(&self) -> bool {
sys::event::is_error(&self.inner)
@ -93,7 +93,7 @@ impl Event {
/// | [kqueue] | `EV_EOF` |
///
/// [OS selector]: ../struct.Poll.html#implementation-notes
/// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
/// [epoll]: https://man7.org/linux/man-pages/man7/epoll.7.html
/// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
pub fn is_read_closed(&self) -> bool {
sys::event::is_read_closed(&self.inner)
@ -123,7 +123,7 @@ impl Event {
/// | [kqueue] | `EV_EOF` |
///
/// [OS selector]: ../struct.Poll.html#implementation-notes
/// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
/// [epoll]: https://man7.org/linux/man-pages/man7/epoll.7.html
/// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
pub fn is_write_closed(&self) -> bool {
sys::event::is_write_closed(&self.inner)
@ -144,7 +144,7 @@ impl Event {
/// | [kqueue] | *Not supported* |
///
/// [OS selector]: ../struct.Poll.html#implementation-notes
/// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
/// [epoll]: https://man7.org/linux/man-pages/man7/epoll.7.html
/// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
#[inline]
pub fn is_priority(&self) -> bool {
@ -167,7 +167,7 @@ impl Event {
/// 1: Only supported on DragonFly BSD, FreeBSD, iOS and macOS.
///
/// [OS selector]: ../struct.Poll.html#implementation-notes
/// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
/// [epoll]: https://man7.org/linux/man-pages/man7/epoll.7.html
/// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
pub fn is_aio(&self) -> bool {
sys::event::is_aio(&self.inner)

View file

@ -121,7 +121,7 @@ where
token: Token,
interests: Interest,
) -> io::Result<()> {
(&mut **self).register(registry, token, interests)
(**self).register(registry, token, interests)
}
fn reregister(
@ -130,10 +130,10 @@ where
token: Token,
interests: Interest,
) -> io::Result<()> {
(&mut **self).reregister(registry, token, interests)
(**self).reregister(registry, token, interests)
}
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
(&mut **self).deregister(registry)
(**self).deregister(registry)
}
}

View file

@ -20,18 +20,9 @@ pub struct Interest(NonZeroU8);
const READABLE: u8 = 0b0001;
const WRITABLE: u8 = 0b0010;
// The following are not available on all platforms.
#[cfg_attr(
not(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
)),
allow(dead_code)
)]
const AIO: u8 = 0b0100;
#[cfg_attr(not(target_os = "freebsd"), allow(dead_code))]
const LIO: u8 = 0b1000;
const PRIORITY: u8 = 0b10000;
impl Interest {
/// Returns a `Interest` set representing readable interests.
@ -45,7 +36,9 @@ impl Interest {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
pub const AIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(AIO) });
@ -53,6 +46,10 @@ impl Interest {
#[cfg(target_os = "freebsd")]
pub const LIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(LIO) });
/// Returns a `Interest` set representing priority completion interests.
#[cfg(any(target_os = "linux", target_os = "android"))]
pub const PRIORITY: Interest = Interest(unsafe { NonZeroU8::new_unchecked(PRIORITY) });
/// Add together two `Interest`.
///
/// This does the same thing as the `BitOr` implementation, but is a
@ -104,15 +101,20 @@ impl Interest {
(self.0.get() & WRITABLE) != 0
}
/// Returns true if `Interest` contains AIO readiness
/// Returns true if `Interest` contains AIO readiness.
pub const fn is_aio(self) -> bool {
(self.0.get() & AIO) != 0
}
/// Returns true if `Interest` contains LIO readiness
/// Returns true if `Interest` contains LIO readiness.
pub const fn is_lio(self) -> bool {
(self.0.get() & LIO) != 0
}
/// Returns true if `Interest` contains priority readiness.
pub const fn is_priority(self) -> bool {
(self.0.get() & PRIORITY) != 0
}
}
impl ops::BitOr for Interest {
@ -152,7 +154,9 @@ impl fmt::Debug for Interest {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
{
if self.is_aio() {
@ -173,6 +177,16 @@ impl fmt::Debug for Interest {
one = true
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
{
if self.is_priority() {
if one {
write!(fmt, " | ")?
}
write!(fmt, "PRIORITY")?;
one = true
}
}
debug_assert!(one, "printing empty interests");
Ok(())
}

View file

@ -1,6 +1,8 @@
use std::ops::{Deref, DerefMut};
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
#[cfg(target_os = "wasi")]
use std::os::wasi::io::AsRawFd;
#[cfg(windows)]
use std::os::windows::io::AsRawSocket;
#[cfg(debug_assertions)]
@ -200,6 +202,44 @@ where
}
}
#[cfg(target_os = "wasi")]
impl<T> event::Source for IoSource<T>
where
T: AsRawFd,
{
fn register(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
#[cfg(debug_assertions)]
self.selector_id.associate(registry)?;
registry
.selector()
.register(self.inner.as_raw_fd() as _, token, interests)
}
fn reregister(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
#[cfg(debug_assertions)]
self.selector_id.check_association(registry)?;
registry
.selector()
.reregister(self.inner.as_raw_fd() as _, token, interests)
}
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
#[cfg(debug_assertions)]
self.selector_id.remove_association(registry)?;
registry.selector().deregister(self.inner.as_raw_fd() as _)
}
}
impl<T> fmt::Debug for IoSource<T>
where
T: fmt::Debug,

View file

@ -48,6 +48,7 @@ mod interest;
mod poll;
mod sys;
mod token;
#[cfg(not(target_os = "wasi"))]
mod waker;
pub mod event;
@ -65,6 +66,7 @@ pub use event::Events;
pub use interest::Interest;
pub use poll::{Poll, Registry};
pub use token::Token;
#[cfg(not(target_os = "wasi"))]
pub use waker::Waker;
#[cfg(all(unix, feature = "os-ext"))]
@ -99,7 +101,7 @@ pub mod features {
#![cfg_attr(feature = "os-poll", doc = "## `os-poll` (enabled)")]
#![cfg_attr(not(feature = "os-poll"), doc = "## `os-poll` (disabled)")]
//!
//! Mio by default provides only a shell implementation, that `panic!`s the
//! Mio by default provides only a shell implementation that `panic!`s the
//! moment it is actually run. To run it requires OS support, this is
//! enabled by activating the `os-poll` feature.
//!

View file

@ -68,3 +68,31 @@ macro_rules! cfg_any_os_ext {
)*
}
}
macro_rules! trace {
($($t:tt)*) => {
log!(trace, $($t)*)
}
}
macro_rules! warn {
($($t:tt)*) => {
log!(warn, $($t)*)
}
}
macro_rules! error {
($($t:tt)*) => {
log!(error, $($t)*)
}
}
macro_rules! log {
($level: ident, $($t:tt)*) => {
#[cfg(feature = "log")]
{ log::$level!($($t)*) }
// Silence unused variables warnings.
#[cfg(not(feature = "log"))]
{ if false { let _ = ( $($t)* ); } }
}
}

View file

@ -28,7 +28,9 @@
mod tcp;
pub use self::tcp::{TcpListener, TcpStream};
#[cfg(not(target_os = "wasi"))]
mod udp;
#[cfg(not(target_os = "wasi"))]
pub use self::udp::UdpSocket;
#[cfg(unix)]

View file

@ -1,6 +1,8 @@
use std::net::{self, SocketAddr};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(target_os = "wasi")]
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::{fmt, io};
@ -9,6 +11,7 @@ use crate::io_source::IoSource;
use crate::net::TcpStream;
#[cfg(unix)]
use crate::sys::tcp::set_reuseaddr;
#[cfg(not(target_os = "wasi"))]
use crate::sys::tcp::{bind, listen, new_for_addr};
use crate::{event, sys, Interest, Registry, Token};
@ -52,6 +55,7 @@ impl TcpListener {
/// 2. Set the `SO_REUSEADDR` option on the socket on Unix.
/// 3. Bind the socket to the specified address.
/// 4. Calls `listen` on the socket to prepare it to receive new connections.
#[cfg(not(target_os = "wasi"))]
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
@ -215,3 +219,30 @@ impl FromRawSocket for TcpListener {
TcpListener::from_std(FromRawSocket::from_raw_socket(socket))
}
}
#[cfg(target_os = "wasi")]
impl IntoRawFd for TcpListener {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}
#[cfg(target_os = "wasi")]
impl AsRawFd for TcpListener {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
#[cfg(target_os = "wasi")]
impl FromRawFd for TcpListener {
/// Converts a `RawFd` to a `TcpListener`.
///
/// # Notes
///
/// The caller is responsible for ensuring that the socket is in
/// non-blocking mode.
unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
TcpListener::from_std(FromRawFd::from_raw_fd(fd))
}
}

View file

@ -3,10 +3,13 @@ use std::io::{self, IoSlice, IoSliceMut, Read, Write};
use std::net::{self, Shutdown, SocketAddr};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(target_os = "wasi")]
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use crate::io_source::IoSource;
#[cfg(not(target_os = "wasi"))]
use crate::sys::tcp::{connect, new_for_addr};
use crate::{event, Interest, Registry, Token};
@ -63,16 +66,21 @@ impl TcpStream {
/// [here](https://github.com/Thomasdezeeuw/heph/blob/0c4f1ab3eaf08bea1d65776528bfd6114c9f8374/src/net/tcp/stream.rs#L560-L622).
///
/// 1. Call `TcpStream::connect`
/// 2. Register the returned stream with at least [read interest].
/// 3. Wait for a (readable) event.
/// 2. Register the returned stream with at least [write interest].
/// 3. Wait for a (writable) event.
/// 4. Check `TcpStream::peer_addr`. If it returns `libc::EINPROGRESS` or
/// `ErrorKind::NotConnected` it means the stream is not yet connected,
/// go back to step 3. If it returns an address it means the stream is
/// connected, go to step 5. If another error is returned something
/// whent wrong.
/// went wrong.
/// 5. Now the stream can be used.
///
/// [read interest]: Interest::READABLE
/// This may return a `WouldBlock` in which case the socket connection
/// cannot be completed immediately, it usually means there are insufficient
/// entries in the routing cache.
///
/// [write interest]: Interest::WRITABLE
#[cfg(not(target_os = "wasi"))]
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
@ -199,53 +207,111 @@ impl TcpStream {
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.peek(buf)
}
/// Execute an I/O operation ensuring that the socket receives more events
/// if it hits a [`WouldBlock`] error.
///
/// # Notes
///
/// This method is required to be called for **all** I/O operations to
/// ensure the user will receive events once the socket is ready again after
/// returning a [`WouldBlock`] error.
///
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
///
/// # Examples
///
#[cfg_attr(unix, doc = "```no_run")]
#[cfg_attr(windows, doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use std::io;
/// #[cfg(unix)]
/// use std::os::unix::io::AsRawFd;
/// #[cfg(windows)]
/// use std::os::windows::io::AsRawSocket;
/// use mio::net::TcpStream;
///
/// let address = "127.0.0.1:8080".parse().unwrap();
/// let stream = TcpStream::connect(address)?;
///
/// // Wait until the stream is readable...
///
/// // Read from the stream using a direct libc call, of course the
/// // `io::Read` implementation would be easier to use.
/// let mut buf = [0; 512];
/// let n = stream.try_io(|| {
/// let buf_ptr = &mut buf as *mut _ as *mut _;
/// #[cfg(unix)]
/// let res = unsafe { libc::recv(stream.as_raw_fd(), buf_ptr, buf.len(), 0) };
/// #[cfg(windows)]
/// let res = unsafe { libc::recvfrom(stream.as_raw_socket() as usize, buf_ptr, buf.len() as i32, 0, std::ptr::null_mut(), std::ptr::null_mut()) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("read {} bytes", n);
/// # Ok(())
/// # }
/// ```
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
where
F: FnOnce() -> io::Result<T>,
{
self.inner.do_io(|_| f())
}
}
impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).read(buf))
self.inner.do_io(|mut inner| inner.read(buf))
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
}
}
impl<'a> Read for &'a TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).read(buf))
self.inner.do_io(|mut inner| inner.read(buf))
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
}
}
impl Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).write(buf))
self.inner.do_io(|mut inner| inner.write(buf))
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
}
fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|inner| (&*inner).flush())
self.inner.do_io(|mut inner| inner.flush())
}
}
impl<'a> Write for &'a TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).write(buf))
self.inner.do_io(|mut inner| inner.write(buf))
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
}
fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|inner| (&*inner).flush())
self.inner.do_io(|mut inner| inner.flush())
}
}
@ -332,3 +398,30 @@ impl FromRawSocket for TcpStream {
TcpStream::from_std(FromRawSocket::from_raw_socket(socket))
}
}
#[cfg(target_os = "wasi")]
impl IntoRawFd for TcpStream {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}
#[cfg(target_os = "wasi")]
impl AsRawFd for TcpStream {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
#[cfg(target_os = "wasi")]
impl FromRawFd for TcpStream {
/// Converts a `RawFd` to a `TcpStream`.
///
/// # Notes
///
/// The caller is responsible for ensuring that the socket is in
/// non-blocking mode.
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
}
}

View file

@ -79,7 +79,7 @@ use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}
/// let num_recv = echoer_socket.recv(&mut buffer)?;
/// println!("echo {:?} -> {:?}", buffer, num_recv);
/// buffer = [0; 9];
/// # drop(buffer); // Silence unused assignment warning.
/// # _ = buffer; // Silence unused assignment warning.
/// # return Ok(());
/// }
/// _ => unreachable!()
@ -320,6 +320,10 @@ impl UdpSocket {
/// Connects the UDP socket setting the default destination for `send()`
/// and limiting packets that are read via `recv` from the address specified
/// in `addr`.
///
/// This may return a `WouldBlock` in which case the socket connection
/// cannot be completed immediately, it usually means there are insufficient
/// entries in the routing cache.
pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
self.inner.connect(addr)
}
@ -548,6 +552,64 @@ impl UdpSocket {
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.inner.take_error()
}
/// Execute an I/O operation ensuring that the socket receives more events
/// if it hits a [`WouldBlock`] error.
///
/// # Notes
///
/// This method is required to be called for **all** I/O operations to
/// ensure the user will receive events once the socket is ready again after
/// returning a [`WouldBlock`] error.
///
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
///
/// # Examples
///
#[cfg_attr(unix, doc = "```no_run")]
#[cfg_attr(windows, doc = "```ignore")]
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use std::io;
/// #[cfg(unix)]
/// use std::os::unix::io::AsRawFd;
/// #[cfg(windows)]
/// use std::os::windows::io::AsRawSocket;
/// use mio::net::UdpSocket;
///
/// let address = "127.0.0.1:8080".parse().unwrap();
/// let dgram = UdpSocket::bind(address)?;
///
/// // Wait until the dgram is readable...
///
/// // Read from the dgram using a direct libc call, of course the
/// // `io::Read` implementation would be easier to use.
/// let mut buf = [0; 512];
/// let n = dgram.try_io(|| {
/// let buf_ptr = &mut buf as *mut _ as *mut _;
/// #[cfg(unix)]
/// let res = unsafe { libc::recv(dgram.as_raw_fd(), buf_ptr, buf.len(), 0) };
/// #[cfg(windows)]
/// let res = unsafe { libc::recvfrom(dgram.as_raw_socket() as usize, buf_ptr, buf.len() as i32, 0, std::ptr::null_mut(), std::ptr::null_mut()) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("read {} bytes", n);
/// # Ok(())
/// # }
/// ```
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
where
F: FnOnce() -> io::Result<T>,
{
self.inner.do_io(|_| f())
}
}
impl event::Source for UdpSocket {

View file

@ -22,8 +22,8 @@ impl UnixDatagram {
///
/// This function is intended to be used to wrap a Unix datagram from the
/// standard library in the Mio equivalent. The conversion assumes nothing
/// about the underlying datagram; ; it is left up to the user to set it
/// in non-blocking mode.
/// about the underlying datagram; it is left up to the user to set it in
/// non-blocking mode.
pub fn from_std(socket: net::UnixDatagram) -> UnixDatagram {
UnixDatagram {
inner: IoSource::new(socket),
@ -31,6 +31,9 @@ impl UnixDatagram {
}
/// Connects the socket to the specified address.
///
/// This may return a `WouldBlock` in which case the socket connection
/// cannot be completed immediately.
pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
self.inner.connect(path)
}
@ -108,6 +111,74 @@ impl UnixDatagram {
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.inner.shutdown(how)
}
/// Execute an I/O operation ensuring that the socket receives more events
/// if it hits a [`WouldBlock`] error.
///
/// # Notes
///
/// This method is required to be called for **all** I/O operations to
/// ensure the user will receive events once the socket is ready again after
/// returning a [`WouldBlock`] error.
///
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use std::io;
/// use std::os::unix::io::AsRawFd;
/// use mio::net::UnixDatagram;
///
/// let (dgram1, dgram2) = UnixDatagram::pair()?;
///
/// // Wait until the dgram is writable...
///
/// // Write to the dgram using a direct libc call, of course the
/// // `io::Write` implementation would be easier to use.
/// let buf = b"hello";
/// let n = dgram1.try_io(|| {
/// let buf_ptr = &buf as *const _ as *const _;
/// let res = unsafe { libc::send(dgram1.as_raw_fd(), buf_ptr, buf.len(), 0) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::send, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("write {} bytes", n);
///
/// // Wait until the dgram is readable...
///
/// // Read from the dgram using a direct libc call, of course the
/// // `io::Read` implementation would be easier to use.
/// let mut buf = [0; 512];
/// let n = dgram2.try_io(|| {
/// let buf_ptr = &mut buf as *mut _ as *mut _;
/// let res = unsafe { libc::recv(dgram2.as_raw_fd(), buf_ptr, buf.len(), 0) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("read {} bytes", n);
/// # Ok(())
/// # }
/// ```
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
where
F: FnOnce() -> io::Result<T>,
{
self.inner.do_io(|_| f())
}
}
impl event::Source for UnixDatagram {

View file

@ -15,6 +15,9 @@ pub struct UnixStream {
impl UnixStream {
/// Connects to the socket named by `path`.
///
/// This may return a `WouldBlock` in which case the socket connection
/// cannot be completed immediately. Usually it means the backlog is full.
pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
sys::uds::stream::connect(path.as_ref()).map(UnixStream::from_std)
}
@ -69,53 +72,121 @@ impl UnixStream {
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.inner.shutdown(how)
}
/// Execute an I/O operation ensuring that the socket receives more events
/// if it hits a [`WouldBlock`] error.
///
/// # Notes
///
/// This method is required to be called for **all** I/O operations to
/// ensure the user will receive events once the socket is ready again after
/// returning a [`WouldBlock`] error.
///
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use std::io;
/// use std::os::unix::io::AsRawFd;
/// use mio::net::UnixStream;
///
/// let (stream1, stream2) = UnixStream::pair()?;
///
/// // Wait until the stream is writable...
///
/// // Write to the stream using a direct libc call, of course the
/// // `io::Write` implementation would be easier to use.
/// let buf = b"hello";
/// let n = stream1.try_io(|| {
/// let buf_ptr = &buf as *const _ as *const _;
/// let res = unsafe { libc::send(stream1.as_raw_fd(), buf_ptr, buf.len(), 0) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::send, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("write {} bytes", n);
///
/// // Wait until the stream is readable...
///
/// // Read from the stream using a direct libc call, of course the
/// // `io::Read` implementation would be easier to use.
/// let mut buf = [0; 512];
/// let n = stream2.try_io(|| {
/// let buf_ptr = &mut buf as *mut _ as *mut _;
/// let res = unsafe { libc::recv(stream2.as_raw_fd(), buf_ptr, buf.len(), 0) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("read {} bytes", n);
/// # Ok(())
/// # }
/// ```
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
where
F: FnOnce() -> io::Result<T>,
{
self.inner.do_io(|_| f())
}
}
impl Read for UnixStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).read(buf))
self.inner.do_io(|mut inner| inner.read(buf))
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
}
}
impl<'a> Read for &'a UnixStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).read(buf))
self.inner.do_io(|mut inner| inner.read(buf))
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).read_vectored(bufs))
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
}
}
impl Write for UnixStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).write(buf))
self.inner.do_io(|mut inner| inner.write(buf))
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
}
fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|inner| (&*inner).flush())
self.inner.do_io(|mut inner| inner.flush())
}
}
impl<'a> Write for &'a UnixStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).write(buf))
self.inner.do_io(|mut inner| inner.write(buf))
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|inner| (&*inner).write_vectored(bufs))
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
}
fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|inner| (&*inner).flush())
self.inner.do_io(|mut inner| inner.flush())
}
}

View file

@ -1,5 +1,4 @@
use crate::{event, sys, Events, Interest, Token};
use log::trace;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
use std::time::Duration;
@ -187,6 +186,28 @@ use std::{fmt, io};
/// operations to go through Mio otherwise it is not able to update it's
/// internal state properly and won't generate events.
///
/// ### Polling without registering event sources
///
///
/// *The following is **not** guaranteed, just a description of the current
/// situation!* Mio is allowed to change the following without it being
/// considered a breaking change, don't depend on this, it's just here to inform
/// the user. On platforms that use epoll, kqueue or IOCP (see implementation
/// notes below) polling without previously registering [event sources] will
/// result in sleeping forever, only a process signal will be able to wake up
/// the thread.
///
/// On WASM/WASI this is different as it doesn't support process signals,
/// furthermore the WASI specification doesn't specify a behaviour in this
/// situation, thus it's up to the implementation what to do here. As an
/// example, the wasmtime runtime will return `EINVAL` in this situation, but
/// different runtimes may return different results. If you have further
/// insights or thoughts about this situation (and/or how Mio should handle it)
/// please add you comment to [pull request#1580].
///
/// [event sources]: crate::event::Source
/// [pull request#1580]: https://github.com/tokio-rs/mio/pull/1580
///
/// # Implementation notes
///
/// `Poll` is backed by the selector provided by the operating system.
@ -218,10 +239,10 @@ use std::{fmt, io};
/// data to be copied into an intermediate buffer before it is passed to the
/// kernel.
///
/// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
/// [epoll]: https://man7.org/linux/man-pages/man7/epoll.7.html
/// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
/// [IOCP]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx
/// [`signalfd`]: http://man7.org/linux/man-pages/man2/signalfd.2.html
/// [IOCP]: https://docs.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports
/// [`signalfd`]: https://man7.org/linux/man-pages/man2/signalfd.2.html
/// [`SourceFd`]: unix/struct.SourceFd.html
/// [`Poll::poll`]: struct.Poll.html#method.poll
pub struct Poll {
@ -234,6 +255,54 @@ pub struct Registry {
}
impl Poll {
cfg_os_poll! {
/// Return a new `Poll` handle.
///
/// This function will make a syscall to the operating system to create
/// the system selector. If this syscall fails, `Poll::new` will return
/// with the error.
///
/// close-on-exec flag is set on the file descriptors used by the selector to prevent
/// leaking it to executed processes. However, on some systems such as
/// old Linux systems that don't support `epoll_create1` syscall it is done
/// non-atomically, so a separate thread executing in parallel to this
/// function may accidentally leak the file descriptor if it executes a
/// new process before this function returns.
///
/// See [struct] level docs for more details.
///
/// [struct]: struct.Poll.html
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Poll, Events};
/// use std::time::Duration;
///
/// let mut poll = match Poll::new() {
/// Ok(poll) => poll,
/// Err(e) => panic!("failed to create Poll instance; err={:?}", e),
/// };
///
/// // Create a structure to receive polled events
/// let mut events = Events::with_capacity(1024);
///
/// // Wait for events, but none will be received because no
/// // `event::Source`s have been registered with this `Poll` instance.
/// poll.poll(&mut events, Some(Duration::from_millis(500)))?;
/// assert!(events.is_empty());
/// # Ok(())
/// # }
/// ```
pub fn new() -> io::Result<Poll> {
sys::Selector::new().map(|selector| Poll {
registry: Registry { selector },
})
}
}
/// Create a separate `Registry` which can be used to register
/// `event::Source`s.
pub fn registry(&self) -> &Registry {
@ -279,6 +348,10 @@ impl Poll {
/// of Mio would automatically retry the poll call if it was interrupted
/// (if `EINTR` was returned).
///
/// Currently if the `timeout` elapses without any readiness events
/// triggering this will return `Ok(())`. However we're not guaranteeing
/// this behaviour as this depends on the OS.
///
/// # Examples
///
/// A basic example -- establishing a `TcpStream` connection.
@ -338,49 +411,6 @@ impl Poll {
}
}
cfg_os_poll! {
impl Poll {
/// Return a new `Poll` handle.
///
/// This function will make a syscall to the operating system to create
/// the system selector. If this syscall fails, `Poll::new` will return
/// with the error.
///
/// See [struct] level docs for more details.
///
/// [struct]: struct.Poll.html
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Poll, Events};
/// use std::time::Duration;
///
/// let mut poll = match Poll::new() {
/// Ok(poll) => poll,
/// Err(e) => panic!("failed to create Poll instance; err={:?}", e),
/// };
///
/// // Create a structure to receive polled events
/// let mut events = Events::with_capacity(1024);
///
/// // Wait for events, but none will be received because no
/// // `event::Source`s have been registered with this `Poll` instance.
/// poll.poll(&mut events, Some(Duration::from_millis(500)))?;
/// assert!(events.is_empty());
/// # Ok(())
/// # }
/// ```
pub fn new() -> io::Result<Poll> {
sys::Selector::new().map(|selector| Poll {
registry: Registry { selector },
})
}
}
}
#[cfg(unix)]
impl AsRawFd for Poll {
fn as_raw_fd(&self) -> RawFd {
@ -645,7 +675,7 @@ impl Registry {
/// Internal check to ensure only a single `Waker` is active per [`Poll`]
/// instance.
#[cfg(debug_assertions)]
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
pub(crate) fn register_waker(&self) {
assert!(
!self.selector.register_waker(),
@ -654,6 +684,7 @@ impl Registry {
}
/// Get access to the `sys::Selector`.
#[cfg(any(not(target_os = "wasi"), feature = "net"))]
pub(crate) fn selector(&self) -> &sys::Selector {
&self.selector
}

View file

@ -63,6 +63,12 @@ cfg_os_poll! {
pub use self::windows::*;
}
#[cfg(target_os = "wasi")]
cfg_os_poll! {
mod wasi;
pub(crate) use self::wasi::*;
}
cfg_not_os_poll! {
mod shell;
pub(crate) use self::shell::*;

View file

@ -7,7 +7,9 @@ macro_rules! os_required {
mod selector;
pub(crate) use self::selector::{event, Event, Events, Selector};
#[cfg(not(target_os = "wasi"))]
mod waker;
#[cfg(not(target_os = "wasi"))]
pub(crate) use self::waker::Waker;
cfg_net! {

View file

@ -19,7 +19,7 @@ impl Selector {
os_required!();
}
#[cfg(debug_assertions)]
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
pub fn register_waker(&self) -> bool {
os_required!();
}
@ -44,6 +44,25 @@ cfg_any_os_ext! {
}
}
#[cfg(target_os = "wasi")]
cfg_any_os_ext! {
use crate::{Interest, Token};
impl Selector {
pub fn register(&self, _: wasi::Fd, _: Token, _: Interest) -> io::Result<()> {
os_required!();
}
pub fn reregister(&self, _: wasi::Fd, _: Token, _: Interest) -> io::Result<()> {
os_required!();
}
pub fn deregister(&self, _: wasi::Fd) -> io::Result<()> {
os_required!();
}
}
}
cfg_io_source! {
#[cfg(debug_assertions)]
impl Selector {

View file

@ -1,18 +1,22 @@
use std::io;
use std::net::{self, SocketAddr};
#[cfg(not(target_os = "wasi"))]
pub(crate) fn new_for_addr(_: SocketAddr) -> io::Result<i32> {
os_required!();
}
#[cfg(not(target_os = "wasi"))]
pub(crate) fn bind(_: &net::TcpListener, _: SocketAddr) -> io::Result<()> {
os_required!();
}
#[cfg(not(target_os = "wasi"))]
pub(crate) fn connect(_: &net::TcpStream, _: SocketAddr) -> io::Result<()> {
os_required!();
}
#[cfg(not(target_os = "wasi"))]
pub(crate) fn listen(_: &net::TcpListener, _: u32) -> io::Result<()> {
os_required!();
}

View file

@ -1,3 +1,4 @@
#![cfg(not(target_os = "wasi"))]
use std::io;
use std::net::{self, SocketAddr};

View file

@ -20,43 +20,49 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
))]
let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
// Gives a warning for platforms without SOCK_NONBLOCK.
#[allow(clippy::let_and_return)]
let socket = syscall!(socket(domain, socket_type, 0));
let socket = syscall!(socket(domain, socket_type, 0))?;
// Mimick `libstd` and set `SO_NOSIGPIPE` on apple systems.
#[cfg(target_vendor = "apple")]
let socket = socket.and_then(|socket| {
syscall!(setsockopt(
socket,
libc::SOL_SOCKET,
libc::SO_NOSIGPIPE,
&1 as *const libc::c_int as *const libc::c_void,
size_of::<libc::c_int>() as libc::socklen_t
))
.map(|_| socket)
});
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
if let Err(err) = syscall!(setsockopt(
socket,
libc::SOL_SOCKET,
libc::SO_NOSIGPIPE,
&1 as *const libc::c_int as *const libc::c_void,
size_of::<libc::c_int>() as libc::socklen_t
)) {
let _ = syscall!(close(socket));
return Err(err);
}
// Darwin doesn't have SOCK_NONBLOCK or SOCK_CLOEXEC.
#[cfg(any(target_os = "ios", target_os = "macos"))]
let socket = socket.and_then(|socket| {
// For platforms that don't support flags in socket, we need to
// set the flags ourselves.
syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))
.and_then(|_| syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)).map(|_| socket))
.map_err(|e| {
// If either of the `fcntl` calls failed, ensure the socket is
// closed and return the error.
let _ = syscall!(close(socket));
e
})
});
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
{
if let Err(err) = syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK)) {
let _ = syscall!(close(socket));
return Err(err);
}
if let Err(err) = syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)) {
let _ = syscall!(close(socket));
return Err(err);
}
}
socket
Ok(socket)
}
/// A type with the same memory layout as `libc::sockaddr`. Used in converting Rust level
@ -96,7 +102,9 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
target_os = "tvos",
target_os = "watchos",
))]
sin_len: 0,
};
@ -120,7 +128,9 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
target_os = "tvos",
target_os = "watchos",
))]
sin6_len: 0,
#[cfg(target_os = "illumos")]

View file

@ -155,6 +155,7 @@ pub fn new() -> io::Result<(Sender, Receiver)> {
target_os = "netbsd",
target_os = "openbsd",
target_os = "illumos",
target_os = "redox",
))]
unsafe {
if libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC | libc::O_NONBLOCK) != 0 {
@ -162,7 +163,12 @@ pub fn new() -> io::Result<(Sender, Receiver)> {
}
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
unsafe {
// For platforms that don't have `pipe2(2)` we need to manually set the
// correct flags on the file descriptor.
@ -175,7 +181,7 @@ pub fn new() -> io::Result<(Sender, Receiver)> {
|| libc::fcntl(*fd, libc::F_SETFD, libc::FD_CLOEXEC) != 0
{
let err = io::Error::last_os_error();
// Don't leak file descriptors. Can't handle error though.
// Don't leak file descriptors. Can't handle closing error though.
let _ = libc::close(fds[0]);
let _ = libc::close(fds[1]);
return Err(err);
@ -187,18 +193,22 @@ pub fn new() -> io::Result<(Sender, Receiver)> {
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "illumos",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "ios",
target_os = "macos",
target_os = "illumos",
target_os = "redox",
target_os = "tvos",
target_os = "watchos",
)))]
compile_error!("unsupported target for `mio::unix::pipe`");
// Safety: we just initialised the `fds` above.
// SAFETY: we just initialised the `fds` above.
let r = unsafe { Receiver::from_raw_fd(fds[0]) };
let w = unsafe { Sender::from_raw_fd(fds[1]) };
Ok((w, r))
}
@ -215,6 +225,74 @@ impl Sender {
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
set_nonblocking(self.inner.as_raw_fd(), nonblocking)
}
/// Execute an I/O operation ensuring that the socket receives more events
/// if it hits a [`WouldBlock`] error.
///
/// # Notes
///
/// This method is required to be called for **all** I/O operations to
/// ensure the user will receive events once the socket is ready again after
/// returning a [`WouldBlock`] error.
///
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use std::io;
/// use std::os::unix::io::AsRawFd;
/// use mio::unix::pipe;
///
/// let (sender, receiver) = pipe::new()?;
///
/// // Wait until the sender is writable...
///
/// // Write to the sender using a direct libc call, of course the
/// // `io::Write` implementation would be easier to use.
/// let buf = b"hello";
/// let n = sender.try_io(|| {
/// let buf_ptr = &buf as *const _ as *const _;
/// let res = unsafe { libc::write(sender.as_raw_fd(), buf_ptr, buf.len()) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::write, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("write {} bytes", n);
///
/// // Wait until the receiver is readable...
///
/// // Read from the receiver using a direct libc call, of course the
/// // `io::Read` implementation would be easier to use.
/// let mut buf = [0; 512];
/// let n = receiver.try_io(|| {
/// let buf_ptr = &mut buf as *mut _ as *mut _;
/// let res = unsafe { libc::read(receiver.as_raw_fd(), buf_ptr, buf.len()) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::read, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("read {} bytes", n);
/// # Ok(())
/// # }
/// ```
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
where
F: FnOnce() -> io::Result<T>,
{
self.inner.do_io(|_| f())
}
}
impl event::Source for Sender {
@ -243,29 +321,29 @@ impl event::Source for Sender {
impl Write for Sender {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|sender| (&*sender).write(buf))
self.inner.do_io(|mut sender| sender.write(buf))
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|sender| (&*sender).write_vectored(bufs))
self.inner.do_io(|mut sender| sender.write_vectored(bufs))
}
fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|sender| (&*sender).flush())
self.inner.do_io(|mut sender| sender.flush())
}
}
impl Write for &Sender {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|sender| (&*sender).write(buf))
self.inner.do_io(|mut sender| sender.write(buf))
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|sender| (&*sender).write_vectored(bufs))
self.inner.do_io(|mut sender| sender.write_vectored(bufs))
}
fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|sender| (&*sender).flush())
self.inner.do_io(|mut sender| sender.flush())
}
}
@ -312,6 +390,74 @@ impl Receiver {
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
set_nonblocking(self.inner.as_raw_fd(), nonblocking)
}
/// Execute an I/O operation ensuring that the socket receives more events
/// if it hits a [`WouldBlock`] error.
///
/// # Notes
///
/// This method is required to be called for **all** I/O operations to
/// ensure the user will receive events once the socket is ready again after
/// returning a [`WouldBlock`] error.
///
/// [`WouldBlock`]: io::ErrorKind::WouldBlock
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use std::io;
/// use std::os::unix::io::AsRawFd;
/// use mio::unix::pipe;
///
/// let (sender, receiver) = pipe::new()?;
///
/// // Wait until the sender is writable...
///
/// // Write to the sender using a direct libc call, of course the
/// // `io::Write` implementation would be easier to use.
/// let buf = b"hello";
/// let n = sender.try_io(|| {
/// let buf_ptr = &buf as *const _ as *const _;
/// let res = unsafe { libc::write(sender.as_raw_fd(), buf_ptr, buf.len()) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::write, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("write {} bytes", n);
///
/// // Wait until the receiver is readable...
///
/// // Read from the receiver using a direct libc call, of course the
/// // `io::Read` implementation would be easier to use.
/// let mut buf = [0; 512];
/// let n = receiver.try_io(|| {
/// let buf_ptr = &mut buf as *mut _ as *mut _;
/// let res = unsafe { libc::read(receiver.as_raw_fd(), buf_ptr, buf.len()) };
/// if res != -1 {
/// Ok(res as usize)
/// } else {
/// // If EAGAIN or EWOULDBLOCK is set by libc::read, the closure
/// // should return `WouldBlock` error.
/// Err(io::Error::last_os_error())
/// }
/// })?;
/// eprintln!("read {} bytes", n);
/// # Ok(())
/// # }
/// ```
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
where
F: FnOnce() -> io::Result<T>,
{
self.inner.do_io(|_| f())
}
}
impl event::Source for Receiver {
@ -340,21 +486,21 @@ impl event::Source for Receiver {
impl Read for Receiver {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|sender| (&*sender).read(buf))
self.inner.do_io(|mut sender| sender.read(buf))
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|sender| (&*sender).read_vectored(bufs))
self.inner.do_io(|mut sender| sender.read_vectored(bufs))
}
}
impl Read for &Receiver {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|sender| (&*sender).read(buf))
self.inner.do_io(|mut sender| sender.read(buf))
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|sender| (&*sender).read_vectored(bufs))
self.inner.do_io(|mut sender| sender.read_vectored(bufs))
}
}

View file

@ -1,7 +1,6 @@
use crate::{Interest, Token};
use libc::{EPOLLET, EPOLLIN, EPOLLOUT, EPOLLRDHUP};
use log::error;
use libc::{EPOLLET, EPOLLIN, EPOLLOUT, EPOLLPRI, EPOLLRDHUP};
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(debug_assertions)]
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
@ -23,15 +22,41 @@ pub struct Selector {
impl Selector {
pub fn new() -> io::Result<Selector> {
#[cfg(not(target_os = "android"))]
let res = syscall!(epoll_create1(libc::EPOLL_CLOEXEC));
// On Android < API level 16 `epoll_create1` is not defined, so use a
// raw system call.
// According to libuv, `EPOLL_CLOEXEC` is not defined on Android API <
// 21. But `EPOLL_CLOEXEC` is an alias for `O_CLOEXEC` on that platform,
// so we use it instead.
#[cfg(target_os = "android")]
let flag = libc::O_CLOEXEC;
#[cfg(not(target_os = "android"))]
let flag = libc::EPOLL_CLOEXEC;
let res = syscall!(syscall(libc::SYS_epoll_create1, libc::O_CLOEXEC));
syscall!(epoll_create1(flag)).map(|ep| Selector {
let ep = match res {
Ok(ep) => ep as RawFd,
Err(err) => {
// When `epoll_create1` is not available fall back to use
// `epoll_create` followed by `fcntl`.
if let Some(libc::ENOSYS) = err.raw_os_error() {
match syscall!(epoll_create(1024)) {
Ok(ep) => match syscall!(fcntl(ep, libc::F_SETFD, libc::FD_CLOEXEC)) {
Ok(ep) => ep as RawFd,
Err(err) => {
// `fcntl` failed, cleanup `ep`.
let _ = unsafe { libc::close(ep) };
return Err(err);
}
},
Err(err) => return Err(err),
}
} else {
return Err(err);
}
}
};
Ok(Selector {
#[cfg(debug_assertions)]
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
ep,
@ -61,7 +86,17 @@ impl Selector {
const MAX_SAFE_TIMEOUT: u128 = libc::c_int::max_value() as u128;
let timeout = timeout
.map(|to| cmp::min(to.as_millis(), MAX_SAFE_TIMEOUT) as libc::c_int)
.map(|to| {
// `Duration::as_millis` truncates, so round up. This avoids
// turning sub-millisecond timeouts into a zero timeout, unless
// the caller explicitly requests that by specifying a zero
// timeout.
let to_ms = to
.checked_add(Duration::from_nanos(999_999))
.unwrap_or(to)
.as_millis();
cmp::min(MAX_SAFE_TIMEOUT, to_ms) as libc::c_int
})
.unwrap_or(-1);
events.clear();
@ -82,6 +117,8 @@ impl Selector {
let mut event = libc::epoll_event {
events: interests_to_epoll(interests),
u64: usize::from(token) as u64,
#[cfg(target_os = "redox")]
_pad: 0,
};
syscall!(epoll_ctl(self.ep, libc::EPOLL_CTL_ADD, fd, &mut event)).map(|_| ())
@ -91,6 +128,8 @@ impl Selector {
let mut event = libc::epoll_event {
events: interests_to_epoll(interests),
u64: usize::from(token) as u64,
#[cfg(target_os = "redox")]
_pad: 0,
};
syscall!(epoll_ctl(self.ep, libc::EPOLL_CTL_MOD, fd, &mut event)).map(|_| ())
@ -140,6 +179,10 @@ fn interests_to_epoll(interests: Interest) -> u32 {
kind |= EPOLLOUT;
}
if interests.is_priority() {
kind |= EPOLLPRI;
}
kind as u32
}

View file

@ -1,6 +1,5 @@
use crate::{Interest, Token};
use log::error;
use std::mem::MaybeUninit;
use std::mem::{self, MaybeUninit};
use std::ops::{Deref, DerefMut};
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(debug_assertions)]
@ -21,7 +20,12 @@ type Count = libc::size_t;
// Type of the `filter` field in the `kevent` structure.
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
type Filter = libc::c_short;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
type Filter = i16;
#[cfg(target_os = "netbsd")]
type Filter = u32;
@ -29,22 +33,16 @@ type Filter = u32;
// Type of the `flags` field in the `kevent` structure.
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
type Flags = libc::c_ushort;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
type Flags = u16;
#[cfg(target_os = "netbsd")]
type Flags = u32;
// Type of the `data` field in the `kevent` structure.
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
))]
type Data = libc::intptr_t;
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
type Data = i64;
// Type of the `udata` field in the `kevent` structure.
#[cfg(not(target_os = "netbsd"))]
type UData = *mut libc::c_void;
@ -57,9 +55,8 @@ macro_rules! kevent {
ident: $id as libc::uintptr_t,
filter: $filter as Filter,
flags: $flags,
fflags: 0,
data: 0,
udata: $data as UData,
..unsafe { mem::zeroed() }
}
};
}
@ -75,15 +72,17 @@ pub struct Selector {
impl Selector {
pub fn new() -> io::Result<Selector> {
syscall!(kqueue())
.and_then(|kq| syscall!(fcntl(kq, libc::F_SETFD, libc::FD_CLOEXEC)).map(|_| kq))
.map(|kq| Selector {
#[cfg(debug_assertions)]
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
kq,
#[cfg(debug_assertions)]
has_waker: AtomicBool::new(false),
})
let kq = syscall!(kqueue())?;
let selector = Selector {
#[cfg(debug_assertions)]
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
kq,
#[cfg(debug_assertions)]
has_waker: AtomicBool::new(false),
};
syscall!(fcntl(kq, libc::F_SETFD, libc::FD_CLOEXEC))?;
Ok(selector)
}
pub fn try_clone(&self) -> io::Result<Selector> {
@ -163,7 +162,7 @@ impl Selector {
// the array.
slice::from_raw_parts_mut(changes[0].as_mut_ptr(), n_changes)
};
kevent_register(self.kq, changes, &[libc::EPIPE as Data])
kevent_register(self.kq, changes, &[libc::EPIPE as i64])
}
pub fn reregister(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
@ -195,7 +194,7 @@ impl Selector {
kevent_register(
self.kq,
&mut changes,
&[libc::ENOENT as Data, libc::EPIPE as Data],
&[libc::ENOENT as i64, libc::EPIPE as i64],
)
}
@ -211,7 +210,7 @@ impl Selector {
// the ENOENT error when it comes up. The ENOENT error informs us that
// the filter wasn't there in first place, but we don't really care
// about that since our goal is to remove it.
kevent_register(self.kq, &mut changes, &[libc::ENOENT as Data])
kevent_register(self.kq, &mut changes, &[libc::ENOENT as i64])
}
#[cfg(debug_assertions)]
@ -220,7 +219,13 @@ impl Selector {
}
// Used by `Waker`.
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
pub fn setup_waker(&self, token: Token) -> io::Result<()> {
// First attempt to accept user space notifications.
let mut kevent = kevent!(
@ -240,7 +245,13 @@ impl Selector {
}
// Used by `Waker`.
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
pub fn wake(&self, token: Token) -> io::Result<()> {
let mut kevent = kevent!(
0,
@ -264,7 +275,7 @@ impl Selector {
fn kevent_register(
kq: RawFd,
changes: &mut [libc::kevent],
ignored_errors: &[Data],
ignored_errors: &[i64],
) -> io::Result<()> {
syscall!(kevent(
kq,
@ -289,11 +300,11 @@ fn kevent_register(
}
/// Check all events for possible errors, it returns the first error found.
fn check_errors(events: &[libc::kevent], ignored_errors: &[Data]) -> io::Result<()> {
fn check_errors(events: &[libc::kevent], ignored_errors: &[i64]) -> io::Result<()> {
for event in events {
// We can't use references to packed structures (in checking the ignored
// errors), so we need copy the data out before use.
let data = event.data;
let data = event.data as _;
// Check for the error flag, the actual error will be in the `data`
// field.
if (event.flags & libc::EV_ERROR != 0) && data != 0 && !ignored_errors.contains(&data) {
@ -371,14 +382,26 @@ pub mod event {
pub fn is_readable(event: &Event) -> bool {
event.filter == libc::EVFILT_READ || {
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
// Used by the `Awakener`. On platforms that use `eventfd` or a unix
// pipe it will emit a readable event so we'll fake that here as
// well.
{
event.filter == libc::EVFILT_USER
}
#[cfg(not(any(target_os = "freebsd", target_os = "ios", target_os = "macos")))]
#[cfg(not(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
)))]
{
false
}
@ -415,7 +438,9 @@ pub mod event {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
{
event.filter == libc::EVFILT_AIO
@ -424,7 +449,9 @@ pub mod event {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)))]
{
false
@ -460,7 +487,9 @@ pub mod event {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::EVFILT_FS,
#[cfg(target_os = "freebsd")]
@ -469,7 +498,9 @@ pub mod event {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::EVFILT_USER,
#[cfg(target_os = "freebsd")]
@ -478,9 +509,19 @@ pub mod event {
libc::EVFILT_EMPTY,
#[cfg(target_os = "dragonfly")]
libc::EVFILT_EXCEPT,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::EVFILT_MACHPORT,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::EVFILT_VM,
);
@ -505,11 +546,26 @@ pub mod event {
libc::EV_ERROR,
libc::EV_EOF,
libc::EV_SYSFLAGS,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::EV_FLAG0,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::EV_POLL,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::EV_OOBAND,
#[cfg(target_os = "dragonfly")]
libc::EV_NODATA,
@ -526,49 +582,63 @@ pub mod event {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::NOTE_TRIGGER,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::NOTE_FFNOP,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::NOTE_FFAND,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::NOTE_FFOR,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::NOTE_FFCOPY,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::NOTE_FFCTRLMASK,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
libc::NOTE_FFLAGSMASK,
libc::NOTE_LOWAT,
@ -578,24 +648,49 @@ pub mod event {
libc::NOTE_OOB,
#[cfg(target_os = "openbsd")]
libc::NOTE_EOF,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_EXTEND,
libc::NOTE_ATTRIB,
libc::NOTE_LINK,
libc::NOTE_RENAME,
libc::NOTE_REVOKE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_NONE,
#[cfg(any(target_os = "openbsd"))]
libc::NOTE_TRUNCATE,
libc::NOTE_EXIT,
libc::NOTE_FORK,
libc::NOTE_EXEC,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_SIGNAL,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_EXITSTATUS,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_EXIT_DETAIL,
libc::NOTE_PDATAMASK,
libc::NOTE_PCTRLMASK,
@ -603,55 +698,132 @@ pub mod event {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
))]
libc::NOTE_TRACK,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
))]
libc::NOTE_TRACKERR,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
))]
libc::NOTE_CHILD,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_EXIT_DETAIL_MASK,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_EXIT_DECRYPTFAIL,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_EXIT_MEMORY,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_EXIT_CSERROR,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_VM_PRESSURE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_VM_PRESSURE_TERMINATE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_VM_ERROR,
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_SECONDS,
#[cfg(any(target_os = "freebsd"))]
libc::NOTE_MSECONDS,
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_USECONDS,
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_NSECONDS,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_ABSOLUTE,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_LEEWAY,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_CRITICAL,
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos"
))]
libc::NOTE_BACKGROUND,
);

View file

@ -1,7 +1,17 @@
#[cfg(any(target_os = "android", target_os = "illumos", target_os = "linux"))]
#[cfg(any(
target_os = "android",
target_os = "illumos",
target_os = "linux",
target_os = "redox",
))]
mod epoll;
#[cfg(any(target_os = "android", target_os = "illumos", target_os = "linux"))]
#[cfg(any(
target_os = "android",
target_os = "illumos",
target_os = "linux",
target_os = "redox",
))]
pub(crate) use self::epoll::{event, Event, Events, Selector};
#[cfg(any(
@ -10,7 +20,9 @@ pub(crate) use self::epoll::{event, Event, Events, Selector};
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
target_os = "tvos",
target_os = "watchos",
))]
mod kqueue;
@ -20,7 +32,9 @@ mod kqueue;
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
target_os = "tvos",
target_os = "watchos",
))]
pub(crate) use self::kqueue::{event, Event, Events, Selector};

View file

@ -40,7 +40,7 @@ pub(crate) fn listen(socket: &net::TcpListener, backlog: u32) -> io::Result<()>
}
pub(crate) fn set_reuseaddr(socket: &net::TcpListener, reuseaddr: bool) -> io::Result<()> {
let val: libc::c_int = if reuseaddr { 1 } else { 0 };
let val: libc::c_int = i32::from(reuseaddr);
syscall!(setsockopt(
socket.as_raw_fd(),
libc::SOL_SOCKET,
@ -60,16 +60,13 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream,
#[cfg(any(
// Android x86's seccomp profile forbids calls to `accept4(2)`
// See https://github.com/tokio-rs/mio/issues/1445 for details
all(
not(target_arch="x86"),
target_os = "android"
),
all(not(target_arch="x86"), target_os = "android"),
target_os = "dragonfly",
target_os = "freebsd",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
))]
let stream = {
syscall!(accept4(
@ -85,9 +82,12 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream,
// OSes inherit the non-blocking flag from the listener, so we just have to
// set `CLOEXEC`.
#[cfg(any(
all(target_arch = "x86", target_os = "android"),
target_os = "ios",
target_os = "macos",
target_os = "redox",
target_os = "tvos",
target_os = "watchos",
all(target_arch = "x86", target_os = "android"),
))]
let stream = {
syscall!(accept(

View file

@ -6,21 +6,13 @@ use std::net::{self, SocketAddr};
use std::os::unix::io::{AsRawFd, FromRawFd};
pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
// Gives a warning for non Apple platforms.
#[allow(clippy::let_and_return)]
let socket = new_ip_socket(addr, libc::SOCK_DGRAM);
let fd = new_ip_socket(addr, libc::SOCK_DGRAM)?;
let socket = unsafe { net::UdpSocket::from_raw_fd(fd) };
socket.and_then(|socket| {
let (raw_addr, raw_addr_length) = socket_addr(&addr);
syscall!(bind(socket, raw_addr.as_ptr(), raw_addr_length))
.map_err(|err| {
// Close the socket if we hit an error, ignoring the error
// from closing since we can't pass back two errors.
let _ = unsafe { libc::close(socket) };
err
})
.map(|_| unsafe { net::UdpSocket::from_raw_fd(socket) })
})
let (raw_addr, raw_addr_length) = socket_addr(&addr);
syscall!(bind(fd, raw_addr.as_ptr(), raw_addr_length))?;
Ok(socket)
}
pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> {

View file

@ -7,18 +7,18 @@ use std::os::unix::net;
use std::path::Path;
pub(crate) fn bind(path: &Path) -> io::Result<net::UnixDatagram> {
let fd = new_socket(libc::AF_UNIX, libc::SOCK_DGRAM)?;
// Ensure the fd is closed.
let socket = unsafe { net::UnixDatagram::from_raw_fd(fd) };
let (sockaddr, socklen) = socket_addr(path)?;
let sockaddr = &sockaddr as *const libc::sockaddr_un as *const _;
syscall!(bind(fd, sockaddr, socklen))?;
let socket = unbound()?;
syscall!(bind(socket.as_raw_fd(), sockaddr, socklen))?;
Ok(socket)
}
pub(crate) fn unbound() -> io::Result<net::UnixDatagram> {
new_socket(libc::AF_UNIX, libc::SOCK_DGRAM)
.map(|socket| unsafe { net::UnixDatagram::from_raw_fd(socket) })
let fd = new_socket(libc::AF_UNIX, libc::SOCK_DGRAM)?;
Ok(unsafe { net::UnixDatagram::from_raw_fd(fd) })
}
pub(crate) fn pair() -> io::Result<(net::UnixDatagram, net::UnixDatagram)> {

View file

@ -7,19 +7,15 @@ use std::path::Path;
use std::{io, mem};
pub(crate) fn bind(path: &Path) -> io::Result<net::UnixListener> {
let socket = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
let (sockaddr, socklen) = socket_addr(path)?;
let sockaddr = &sockaddr as *const libc::sockaddr_un as *const libc::sockaddr;
syscall!(bind(socket, sockaddr, socklen))
.and_then(|_| syscall!(listen(socket, 1024)))
.map_err(|err| {
// Close the socket if we hit an error, ignoring the error from
// closing since we can't pass back two errors.
let _ = unsafe { libc::close(socket) };
err
})
.map(|_| unsafe { net::UnixListener::from_raw_fd(socket) })
let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
let socket = unsafe { net::UnixListener::from_raw_fd(fd) };
syscall!(bind(fd, sockaddr, socklen))?;
syscall!(listen(fd, 1024))?;
Ok(socket)
}
pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
@ -42,12 +38,12 @@ pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, So
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "redox",
target_os = "tvos",
target_os = "watchos",
// Android x86's seccomp profile forbids calls to `accept4(2)`
// See https://github.com/tokio-rs/mio/issues/1445 for details
all(
target_arch = "x86",
target_os = "android"
)
all(target_arch = "x86", target_os = "android"),
)))]
let socket = {
let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
@ -64,6 +60,9 @@ pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, So
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "redox",
target_os = "tvos",
target_os = "watchos",
all(target_arch = "x86", target_os = "android")
))]
let socket = syscall!(accept(

View file

@ -3,7 +3,7 @@ pub use self::socketaddr::SocketAddr;
/// Get the `sun_path` field offset of `sockaddr_un` for the target OS.
///
/// On Linux, this funtion equates to the same value as
/// On Linux, this function equates to the same value as
/// `size_of::<sa_family_t>()`, but some other implementations include
/// other fields before `sun_path`, so the expression more portably
/// describes the size of the address structure.
@ -40,7 +40,7 @@ cfg_os_poll! {
sockaddr.sun_family = libc::AF_UNIX as libc::sa_family_t;
let bytes = path.as_os_str().as_bytes();
match (bytes.get(0), bytes.len().cmp(&sockaddr.sun_path.len())) {
match (bytes.first(), bytes.len().cmp(&sockaddr.sun_path.len())) {
// Abstract paths don't need a null terminator
(Some(&0), Ordering::Greater) => {
return Err(io::Error::new(
@ -64,7 +64,7 @@ cfg_os_poll! {
let offset = path_offset(&sockaddr);
let mut socklen = offset + bytes.len();
match bytes.get(0) {
match bytes.first() {
// The struct has already been zeroes so the null byte for pathname
// addresses is already there.
Some(&0) | None => {}
@ -77,7 +77,12 @@ cfg_os_poll! {
fn pair<T>(flags: libc::c_int) -> io::Result<(T, T)>
where T: FromRawFd,
{
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
#[cfg(not(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)))]
let flags = flags | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
let mut fds = [-1; 2];
@ -90,7 +95,12 @@ cfg_os_poll! {
// performed. If a `fnctl` fails after the sockets have been created,
// the file descriptors will leak. Creating `pair` above ensures that if
// there is an error, the file descriptors are closed.
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
{
syscall!(fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK))?;
syscall!(fcntl(fds[0], libc::F_SETFD, libc::FD_CLOEXEC))?;

View file

@ -7,23 +7,18 @@ use std::os::unix::net;
use std::path::Path;
pub(crate) fn connect(path: &Path) -> io::Result<net::UnixStream> {
let socket = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
let (sockaddr, socklen) = socket_addr(path)?;
let sockaddr = &sockaddr as *const libc::sockaddr_un as *const libc::sockaddr;
match syscall!(connect(socket, sockaddr, socklen)) {
let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
let socket = unsafe { net::UnixStream::from_raw_fd(fd) };
match syscall!(connect(fd, sockaddr, socklen)) {
Ok(_) => {}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
Err(e) => {
// Close the socket if we hit an error, ignoring the error
// from closing since we can't pass back two errors.
let _ = unsafe { libc::close(socket) };
return Err(e);
}
Err(ref err) if err.raw_os_error() == Some(libc::EINPROGRESS) => {}
Err(e) => return Err(e),
}
Ok(unsafe { net::UnixStream::from_raw_fd(socket) })
Ok(socket)
}
pub(crate) fn pair() -> io::Result<(net::UnixStream, net::UnixStream)> {

View file

@ -20,14 +20,11 @@ mod eventfd {
impl Waker {
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
syscall!(eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK)).and_then(|fd| {
// Turn the file descriptor into a file first so we're ensured
// it's closed when dropped, e.g. when register below fails.
let file = unsafe { File::from_raw_fd(fd) };
selector
.register(fd, token, Interest::READABLE)
.map(|()| Waker { fd: file })
})
let fd = syscall!(eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK))?;
let file = unsafe { File::from_raw_fd(fd) };
selector.register(fd, token, Interest::READABLE)?;
Ok(Waker { fd: file })
}
pub fn wake(&self) -> io::Result<()> {
@ -61,7 +58,13 @@ mod eventfd {
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::eventfd::Waker;
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
mod kqueue {
use crate::sys::Selector;
use crate::Token;
@ -82,11 +85,9 @@ mod kqueue {
impl Waker {
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
selector.try_clone().and_then(|selector| {
selector
.setup_waker(token)
.map(|()| Waker { selector, token })
})
let selector = selector.try_clone()?;
selector.setup_waker(token)?;
Ok(Waker { selector, token })
}
pub fn wake(&self) -> io::Result<()> {
@ -95,7 +96,13 @@ mod kqueue {
}
}
#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
))]
pub use self::kqueue::Waker;
#[cfg(any(
@ -103,6 +110,7 @@ pub use self::kqueue::Waker;
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
))]
mod pipe {
use crate::sys::unix::Selector;
@ -126,13 +134,11 @@ mod pipe {
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
let mut fds = [-1; 2];
syscall!(pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK | libc::O_CLOEXEC))?;
// Turn the file descriptors into files first so we're ensured
// they're closed when dropped, e.g. when register below fails.
let sender = unsafe { File::from_raw_fd(fds[1]) };
let receiver = unsafe { File::from_raw_fd(fds[0]) };
selector
.register(fds[0], token, Interest::READABLE)
.map(|()| Waker { sender, receiver })
selector.register(fds[0], token, Interest::READABLE)?;
Ok(Waker { sender, receiver })
}
pub fn wake(&self) -> io::Result<()> {
@ -174,5 +180,6 @@ mod pipe {
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
))]
pub use self::pipe::Waker;

370
third_party/rust/mio/src/sys/wasi/mod.rs vendored Normal file
View file

@ -0,0 +1,370 @@
//! # Notes
//!
//! The current implementation is somewhat limited. The `Waker` is not
//! implemented, as at the time of writing there is no way to support to wake-up
//! a thread from calling `poll_oneoff`.
//!
//! Furthermore the (re/de)register functions also don't work while concurrently
//! polling as both registering and polling requires a lock on the
//! `subscriptions`.
//!
//! Finally `Selector::try_clone`, required by `Registry::try_clone`, doesn't
//! work. However this could be implemented by use of an `Arc`.
//!
//! In summary, this only (barely) works using a single thread.
use std::cmp::min;
use std::io;
#[cfg(all(feature = "net", debug_assertions))]
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;
#[cfg(feature = "net")]
use crate::{Interest, Token};
cfg_net! {
pub(crate) mod tcp {
use std::io;
use std::net::{self, SocketAddr};
pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream, SocketAddr)> {
let (stream, addr) = listener.accept()?;
stream.set_nonblocking(true)?;
Ok((stream, addr))
}
}
}
/// Unique id for use as `SelectorId`.
#[cfg(all(debug_assertions, feature = "net"))]
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
pub(crate) struct Selector {
#[cfg(all(debug_assertions, feature = "net"))]
id: usize,
/// Subscriptions (reads events) we're interested in.
subscriptions: Arc<Mutex<Vec<wasi::Subscription>>>,
}
impl Selector {
pub(crate) fn new() -> io::Result<Selector> {
Ok(Selector {
#[cfg(all(debug_assertions, feature = "net"))]
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
subscriptions: Arc::new(Mutex::new(Vec::new())),
})
}
#[cfg(all(debug_assertions, feature = "net"))]
pub(crate) fn id(&self) -> usize {
self.id
}
pub(crate) fn select(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()> {
events.clear();
let mut subscriptions = self.subscriptions.lock().unwrap();
// If we want to a use a timeout in the `wasi_poll_oneoff()` function
// we need another subscription to the list.
if let Some(timeout) = timeout {
subscriptions.push(timeout_subscription(timeout));
}
// `poll_oneoff` needs the same number of events as subscriptions.
let length = subscriptions.len();
events.reserve(length);
debug_assert!(events.capacity() >= length);
#[cfg(debug_assertions)]
if length == 0 {
warn!(
"calling mio::Poll::poll with empty subscriptions, this likely not what you want"
);
}
let res = unsafe { wasi::poll_oneoff(subscriptions.as_ptr(), events.as_mut_ptr(), length) };
// Remove the timeout subscription we possibly added above.
if timeout.is_some() {
let timeout_sub = subscriptions.pop();
debug_assert_eq!(
timeout_sub.unwrap().u.tag,
wasi::EVENTTYPE_CLOCK.raw(),
"failed to remove timeout subscription"
);
}
drop(subscriptions); // Unlock.
match res {
Ok(n_events) => {
// Safety: `poll_oneoff` initialises the `events` for us.
unsafe { events.set_len(n_events) };
// Remove the timeout event.
if timeout.is_some() {
if let Some(index) = events.iter().position(is_timeout_event) {
events.swap_remove(index);
}
}
check_errors(&events)
}
Err(err) => Err(io_err(err)),
}
}
pub(crate) fn try_clone(&self) -> io::Result<Selector> {
Ok(Selector {
#[cfg(all(debug_assertions, feature = "net"))]
id: self.id,
subscriptions: self.subscriptions.clone(),
})
}
#[cfg(feature = "net")]
pub(crate) fn register(
&self,
fd: wasi::Fd,
token: Token,
interests: Interest,
) -> io::Result<()> {
let mut subscriptions = self.subscriptions.lock().unwrap();
if interests.is_writable() {
let subscription = wasi::Subscription {
userdata: token.0 as wasi::Userdata,
u: wasi::SubscriptionU {
tag: wasi::EVENTTYPE_FD_WRITE.raw(),
u: wasi::SubscriptionUU {
fd_write: wasi::SubscriptionFdReadwrite {
file_descriptor: fd,
},
},
},
};
subscriptions.push(subscription);
}
if interests.is_readable() {
let subscription = wasi::Subscription {
userdata: token.0 as wasi::Userdata,
u: wasi::SubscriptionU {
tag: wasi::EVENTTYPE_FD_READ.raw(),
u: wasi::SubscriptionUU {
fd_read: wasi::SubscriptionFdReadwrite {
file_descriptor: fd,
},
},
},
};
subscriptions.push(subscription);
}
Ok(())
}
#[cfg(feature = "net")]
pub(crate) fn reregister(
&self,
fd: wasi::Fd,
token: Token,
interests: Interest,
) -> io::Result<()> {
self.deregister(fd)
.and_then(|()| self.register(fd, token, interests))
}
#[cfg(feature = "net")]
pub(crate) fn deregister(&self, fd: wasi::Fd) -> io::Result<()> {
let mut subscriptions = self.subscriptions.lock().unwrap();
let predicate = |subscription: &wasi::Subscription| {
// Safety: `subscription.u.tag` defines the type of the union in
// `subscription.u.u`.
match subscription.u.tag {
t if t == wasi::EVENTTYPE_FD_WRITE.raw() => unsafe {
subscription.u.u.fd_write.file_descriptor == fd
},
t if t == wasi::EVENTTYPE_FD_READ.raw() => unsafe {
subscription.u.u.fd_read.file_descriptor == fd
},
_ => false,
}
};
let mut ret = Err(io::ErrorKind::NotFound.into());
while let Some(index) = subscriptions.iter().position(predicate) {
subscriptions.swap_remove(index);
ret = Ok(())
}
ret
}
}
/// Token used to a add a timeout subscription, also used in removing it again.
const TIMEOUT_TOKEN: wasi::Userdata = wasi::Userdata::max_value();
/// Returns a `wasi::Subscription` for `timeout`.
fn timeout_subscription(timeout: Duration) -> wasi::Subscription {
wasi::Subscription {
userdata: TIMEOUT_TOKEN,
u: wasi::SubscriptionU {
tag: wasi::EVENTTYPE_CLOCK.raw(),
u: wasi::SubscriptionUU {
clock: wasi::SubscriptionClock {
id: wasi::CLOCKID_MONOTONIC,
// Timestamp is in nanoseconds.
timeout: min(wasi::Timestamp::MAX as u128, timeout.as_nanos())
as wasi::Timestamp,
// Give the implementation another millisecond to coalesce
// events.
precision: Duration::from_millis(1).as_nanos() as wasi::Timestamp,
// Zero means the `timeout` is considered relative to the
// current time.
flags: 0,
},
},
},
}
}
fn is_timeout_event(event: &wasi::Event) -> bool {
event.type_ == wasi::EVENTTYPE_CLOCK && event.userdata == TIMEOUT_TOKEN
}
/// Check all events for possible errors, it returns the first error found.
fn check_errors(events: &[Event]) -> io::Result<()> {
for event in events {
if event.error != wasi::ERRNO_SUCCESS {
return Err(io_err(event.error));
}
}
Ok(())
}
/// Convert `wasi::Errno` into an `io::Error`.
fn io_err(errno: wasi::Errno) -> io::Error {
// TODO: check if this is valid.
io::Error::from_raw_os_error(errno.raw() as i32)
}
pub(crate) type Events = Vec<Event>;
pub(crate) type Event = wasi::Event;
pub(crate) mod event {
use std::fmt;
use crate::sys::Event;
use crate::Token;
pub(crate) fn token(event: &Event) -> Token {
Token(event.userdata as usize)
}
pub(crate) fn is_readable(event: &Event) -> bool {
event.type_ == wasi::EVENTTYPE_FD_READ
}
pub(crate) fn is_writable(event: &Event) -> bool {
event.type_ == wasi::EVENTTYPE_FD_WRITE
}
pub(crate) fn is_error(_: &Event) -> bool {
// Not supported? It could be that `wasi::Event.error` could be used for
// this, but the docs say `error that occurred while processing the
// subscription request`, so it's checked in `Select::select` already.
false
}
pub(crate) fn is_read_closed(event: &Event) -> bool {
event.type_ == wasi::EVENTTYPE_FD_READ
// Safety: checked the type of the union above.
&& (event.fd_readwrite.flags & wasi::EVENTRWFLAGS_FD_READWRITE_HANGUP) != 0
}
pub(crate) fn is_write_closed(event: &Event) -> bool {
event.type_ == wasi::EVENTTYPE_FD_WRITE
// Safety: checked the type of the union above.
&& (event.fd_readwrite.flags & wasi::EVENTRWFLAGS_FD_READWRITE_HANGUP) != 0
}
pub(crate) fn is_priority(_: &Event) -> bool {
// Not supported.
false
}
pub(crate) fn is_aio(_: &Event) -> bool {
// Not supported.
false
}
pub(crate) fn is_lio(_: &Event) -> bool {
// Not supported.
false
}
pub(crate) fn debug_details(f: &mut fmt::Formatter<'_>, event: &Event) -> fmt::Result {
debug_detail!(
TypeDetails(wasi::Eventtype),
PartialEq::eq,
wasi::EVENTTYPE_CLOCK,
wasi::EVENTTYPE_FD_READ,
wasi::EVENTTYPE_FD_WRITE,
);
#[allow(clippy::trivially_copy_pass_by_ref)]
fn check_flag(got: &wasi::Eventrwflags, want: &wasi::Eventrwflags) -> bool {
(got & want) != 0
}
debug_detail!(
EventrwflagsDetails(wasi::Eventrwflags),
check_flag,
wasi::EVENTRWFLAGS_FD_READWRITE_HANGUP,
);
struct EventFdReadwriteDetails(wasi::EventFdReadwrite);
impl fmt::Debug for EventFdReadwriteDetails {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EventFdReadwrite")
.field("nbytes", &self.0.nbytes)
.field("flags", &self.0.flags)
.finish()
}
}
f.debug_struct("Event")
.field("userdata", &event.userdata)
.field("error", &event.error)
.field("type", &TypeDetails(event.type_))
.field("fd_readwrite", &EventFdReadwriteDetails(event.fd_readwrite))
.finish()
}
}
cfg_os_poll! {
cfg_io_source! {
pub(crate) struct IoSourceState;
impl IoSourceState {
pub(crate) fn new() -> IoSourceState {
IoSourceState
}
pub(crate) fn do_io<T, F, R>(&self, f: F, io: &T) -> io::Result<R>
where
F: FnOnce(&T) -> io::Result<R>,
{
// We don't hold state, so we can just call the function and
// return.
f(io)
}
}
}
}

View file

@ -1,17 +1,32 @@
use ntapi::ntioapi::{IO_STATUS_BLOCK_u, IO_STATUS_BLOCK};
use ntapi::ntioapi::{NtCancelIoFileEx, NtDeviceIoControlFile};
use ntapi::ntrtl::RtlNtStatusToDosError;
use std::ffi::c_void;
use std::fmt;
use std::fs::File;
use std::io;
use std::mem::size_of;
use std::os::windows::io::AsRawHandle;
use std::ptr::null_mut;
use winapi::shared::ntdef::{HANDLE, LARGE_INTEGER, NTSTATUS, PVOID, ULONG};
use winapi::shared::ntstatus::{STATUS_NOT_FOUND, STATUS_PENDING, STATUS_SUCCESS};
const IOCTL_AFD_POLL: ULONG = 0x00012024;
use windows_sys::Win32::Foundation::{
RtlNtStatusToDosError, HANDLE, NTSTATUS, STATUS_NOT_FOUND, STATUS_PENDING, STATUS_SUCCESS,
};
use windows_sys::Win32::System::WindowsProgramming::{
NtDeviceIoControlFile, IO_STATUS_BLOCK, IO_STATUS_BLOCK_0,
};
const IOCTL_AFD_POLL: u32 = 0x00012024;
#[link(name = "ntdll")]
extern "system" {
/// See <https://processhacker.sourceforge.io/doc/ntioapi_8h.html#a0d4d550cad4d62d75b76961e25f6550c>
///
/// This is an undocumented API and as such not part of <https://github.com/microsoft/win32metadata>
/// from which `windows-sys` is generated, and also unlikely to be added, so
/// we manually declare it here
fn NtCancelIoFileEx(
FileHandle: HANDLE,
IoRequestToCancel: *mut IO_STATUS_BLOCK,
IoStatusBlock: *mut IO_STATUS_BLOCK,
) -> NTSTATUS;
}
/// Winsock2 AFD driver instance.
///
/// All operations are unsafe due to IO_STATUS_BLOCK parameter are being used by Afd driver during STATUS_PENDING before I/O Completion Port returns its result.
@ -24,7 +39,7 @@ pub struct Afd {
#[derive(Debug)]
pub struct AfdPollHandleInfo {
pub handle: HANDLE,
pub events: ULONG,
pub events: u32,
pub status: NTSTATUS,
}
@ -32,10 +47,10 @@ unsafe impl Send for AfdPollHandleInfo {}
#[repr(C)]
pub struct AfdPollInfo {
pub timeout: LARGE_INTEGER,
pub timeout: i64,
// Can have only value 1.
pub number_of_handles: ULONG,
pub exclusive: ULONG,
pub number_of_handles: u32,
pub exclusive: u32,
pub handles: [AfdPollHandleInfo; 1],
}
@ -58,13 +73,13 @@ impl Afd {
&self,
info: &mut AfdPollInfo,
iosb: *mut IO_STATUS_BLOCK,
overlapped: PVOID,
overlapped: *mut c_void,
) -> io::Result<bool> {
let info_ptr: PVOID = info as *mut _ as PVOID;
(*iosb).u.Status = STATUS_PENDING;
let info_ptr = info as *mut _ as *mut c_void;
(*iosb).Anonymous.Status = STATUS_PENDING;
let status = NtDeviceIoControlFile(
self.fd.as_raw_handle(),
null_mut(),
self.fd.as_raw_handle() as HANDLE,
0,
None,
overlapped,
iosb,
@ -93,15 +108,15 @@ impl Afd {
/// Use it only with request is still being polled so that you have valid `IO_STATUS_BLOCK` to use.
/// User should NOT deallocate there overlapped value after the `cancel` to prevent double free.
pub unsafe fn cancel(&self, iosb: *mut IO_STATUS_BLOCK) -> io::Result<()> {
if (*iosb).u.Status != STATUS_PENDING {
if (*iosb).Anonymous.Status != STATUS_PENDING {
return Ok(());
}
let mut cancel_iosb = IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_u { Status: 0 },
Anonymous: IO_STATUS_BLOCK_0 { Status: 0 },
Information: 0,
};
let status = NtCancelIoFileEx(self.fd.as_raw_handle(), iosb, &mut cancel_iosb);
let status = NtCancelIoFileEx(self.fd.as_raw_handle() as HANDLE, iosb, &mut cancel_iosb);
if status == STATUS_SUCCESS || status == STATUS_NOT_FOUND {
return Ok(());
}
@ -114,18 +129,21 @@ impl Afd {
cfg_io_source! {
use std::mem::zeroed;
use std::os::windows::io::{FromRawHandle, RawHandle};
use std::ptr::null_mut;
use std::sync::atomic::{AtomicUsize, Ordering};
use miow::iocp::CompletionPort;
use ntapi::ntioapi::{NtCreateFile, FILE_OPEN};
use winapi::shared::ntdef::{OBJECT_ATTRIBUTES, UNICODE_STRING, USHORT, WCHAR};
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::winbase::{SetFileCompletionNotificationModes, FILE_SKIP_SET_EVENT_ON_HANDLE};
use winapi::um::winnt::{SYNCHRONIZE, FILE_SHARE_READ, FILE_SHARE_WRITE};
use super::iocp::CompletionPort;
use windows_sys::Win32::{
Foundation::{UNICODE_STRING, INVALID_HANDLE_VALUE},
System::WindowsProgramming::{
OBJECT_ATTRIBUTES, FILE_SKIP_SET_EVENT_ON_HANDLE,
},
Storage::FileSystem::{FILE_OPEN, NtCreateFile, SetFileCompletionNotificationModes, SYNCHRONIZE, FILE_SHARE_READ, FILE_SHARE_WRITE},
};
const AFD_HELPER_ATTRIBUTES: OBJECT_ATTRIBUTES = OBJECT_ATTRIBUTES {
Length: size_of::<OBJECT_ATTRIBUTES>() as ULONG,
RootDirectory: null_mut(),
Length: size_of::<OBJECT_ATTRIBUTES>() as u32,
RootDirectory: 0,
ObjectName: &AFD_OBJ_NAME as *const _ as *mut _,
Attributes: 0,
SecurityDescriptor: null_mut(),
@ -133,12 +151,12 @@ cfg_io_source! {
};
const AFD_OBJ_NAME: UNICODE_STRING = UNICODE_STRING {
Length: (AFD_HELPER_NAME.len() * size_of::<WCHAR>()) as USHORT,
MaximumLength: (AFD_HELPER_NAME.len() * size_of::<WCHAR>()) as USHORT,
Length: (AFD_HELPER_NAME.len() * size_of::<u16>()) as u16,
MaximumLength: (AFD_HELPER_NAME.len() * size_of::<u16>()) as u16,
Buffer: AFD_HELPER_NAME.as_ptr() as *mut _,
};
const AFD_HELPER_NAME: &[WCHAR] = &[
const AFD_HELPER_NAME: &[u16] = &[
'\\' as _,
'D' as _,
'e' as _,
@ -166,10 +184,10 @@ cfg_io_source! {
impl Afd {
/// Create new Afd instance.
pub fn new(cp: &CompletionPort) -> io::Result<Afd> {
pub(crate) fn new(cp: &CompletionPort) -> io::Result<Afd> {
let mut afd_helper_handle: HANDLE = INVALID_HANDLE_VALUE;
let mut iosb = IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_u { Status: 0 },
Anonymous: IO_STATUS_BLOCK_0 { Status: 0 },
Information: 0,
};
@ -197,14 +215,14 @@ cfg_io_source! {
let fd = File::from_raw_handle(afd_helper_handle as RawHandle);
// Increment by 2 to reserve space for other types of handles.
// Non-AFD types (currently only NamedPipe), use odd numbered
// tokens. This allows the selector to differentate between them
// tokens. This allows the selector to differentiate between them
// and dispatch events accordingly.
let token = NEXT_TOKEN.fetch_add(2, Ordering::Relaxed) + 2;
let afd = Afd { fd };
cp.add_handle(token, &afd.fd)?;
match SetFileCompletionNotificationModes(
afd_helper_handle,
FILE_SKIP_SET_EVENT_ON_HANDLE,
FILE_SKIP_SET_EVENT_ON_HANDLE as u8 // This is just 2, so fits in u8
) {
0 => Err(io::Error::last_os_error()),
_ => Ok(afd),

View file

@ -1,8 +1,7 @@
use std::fmt;
use miow::iocp::CompletionStatus;
use super::afd;
use super::iocp::CompletionStatus;
use crate::Token;
#[derive(Clone)]

View file

@ -0,0 +1,30 @@
use std::os::windows::io::RawHandle;
use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
/// Wrapper around a Windows HANDLE so that we close it upon drop in all scenarios
#[derive(Debug)]
pub struct Handle(HANDLE);
impl Handle {
#[inline]
pub fn new(handle: HANDLE) -> Self {
Self(handle)
}
pub fn raw(&self) -> HANDLE {
self.0
}
pub fn into_raw(self) -> RawHandle {
let ret = self.0;
// This is super important so that drop is not called!
std::mem::forget(self);
ret as RawHandle
}
}
impl Drop for Handle {
fn drop(&mut self) {
unsafe { CloseHandle(self.0) };
}
}

View file

@ -1,17 +1,17 @@
use std::fmt;
use std::ops::{Deref, DerefMut};
use ntapi::ntioapi::IO_STATUS_BLOCK;
use windows_sys::Win32::System::WindowsProgramming::IO_STATUS_BLOCK;
pub struct IoStatusBlock(IO_STATUS_BLOCK);
cfg_io_source! {
use ntapi::ntioapi::IO_STATUS_BLOCK_u;
use windows_sys::Win32::System::WindowsProgramming::{IO_STATUS_BLOCK_0};
impl IoStatusBlock {
pub fn zeroed() -> Self {
Self(IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_u { Status: 0 },
Anonymous: IO_STATUS_BLOCK_0 { Status: 0 },
Information: 0,
})
}

View file

@ -0,0 +1,273 @@
//! Bindings to IOCP, I/O Completion Ports
use super::{Handle, Overlapped};
use std::cmp;
use std::fmt;
use std::io;
use std::mem;
use std::os::windows::io::*;
use std::time::Duration;
use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE};
use windows_sys::Win32::System::IO::{
CreateIoCompletionPort, GetQueuedCompletionStatusEx, PostQueuedCompletionStatus, OVERLAPPED,
OVERLAPPED_ENTRY,
};
/// A handle to an Windows I/O Completion Port.
#[derive(Debug)]
pub(crate) struct CompletionPort {
handle: Handle,
}
/// A status message received from an I/O completion port.
///
/// These statuses can be created via the `new` or `empty` constructors and then
/// provided to a completion port, or they are read out of a completion port.
/// The fields of each status are read through its accessor methods.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct CompletionStatus(OVERLAPPED_ENTRY);
impl fmt::Debug for CompletionStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CompletionStatus(OVERLAPPED_ENTRY)")
}
}
unsafe impl Send for CompletionStatus {}
unsafe impl Sync for CompletionStatus {}
impl CompletionPort {
/// Creates a new I/O completion port with the specified concurrency value.
///
/// The number of threads given corresponds to the level of concurrency
/// allowed for threads associated with this port. Consult the Windows
/// documentation for more information about this value.
pub fn new(threads: u32) -> io::Result<CompletionPort> {
let ret = unsafe { CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, threads) };
if ret == 0 {
Err(io::Error::last_os_error())
} else {
Ok(CompletionPort {
handle: Handle::new(ret),
})
}
}
/// Associates a new `HANDLE` to this I/O completion port.
///
/// This function will associate the given handle to this port with the
/// given `token` to be returned in status messages whenever it receives a
/// notification.
///
/// Any object which is convertible to a `HANDLE` via the `AsRawHandle`
/// trait can be provided to this function, such as `std::fs::File` and
/// friends.
#[cfg(any(feature = "net", feature = "os-ext"))]
pub fn add_handle<T: AsRawHandle + ?Sized>(&self, token: usize, t: &T) -> io::Result<()> {
let ret = unsafe {
CreateIoCompletionPort(t.as_raw_handle() as HANDLE, self.handle.raw(), token, 0)
};
if ret == 0 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
}
/// Dequeues a number of completion statuses from this I/O completion port.
///
/// This function is the same as `get` except that it may return more than
/// one status. A buffer of "zero" statuses is provided (the contents are
/// not read) and then on success this function will return a sub-slice of
/// statuses which represent those which were dequeued from this port. This
/// function does not wait to fill up the entire list of statuses provided.
///
/// Like with `get`, a timeout may be specified for this operation.
pub fn get_many<'a>(
&self,
list: &'a mut [CompletionStatus],
timeout: Option<Duration>,
) -> io::Result<&'a mut [CompletionStatus]> {
debug_assert_eq!(
mem::size_of::<CompletionStatus>(),
mem::size_of::<OVERLAPPED_ENTRY>()
);
let mut removed = 0;
let timeout = duration_millis(timeout);
let len = cmp::min(list.len(), <u32>::max_value() as usize) as u32;
let ret = unsafe {
GetQueuedCompletionStatusEx(
self.handle.raw(),
list.as_ptr() as *mut _,
len,
&mut removed,
timeout,
0,
)
};
if ret == 0 {
Err(io::Error::last_os_error())
} else {
Ok(&mut list[..removed as usize])
}
}
/// Posts a new completion status onto this I/O completion port.
///
/// This function will post the given status, with custom parameters, to the
/// port. Threads blocked in `get` or `get_many` will eventually receive
/// this status.
pub fn post(&self, status: CompletionStatus) -> io::Result<()> {
let ret = unsafe {
PostQueuedCompletionStatus(
self.handle.raw(),
status.0.dwNumberOfBytesTransferred,
status.0.lpCompletionKey,
status.0.lpOverlapped,
)
};
if ret == 0 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
}
}
impl AsRawHandle for CompletionPort {
fn as_raw_handle(&self) -> RawHandle {
self.handle.raw() as RawHandle
}
}
impl FromRawHandle for CompletionPort {
unsafe fn from_raw_handle(handle: RawHandle) -> CompletionPort {
CompletionPort {
handle: Handle::new(handle as HANDLE),
}
}
}
impl IntoRawHandle for CompletionPort {
fn into_raw_handle(self) -> RawHandle {
self.handle.into_raw()
}
}
impl CompletionStatus {
/// Creates a new completion status with the provided parameters.
///
/// This function is useful when creating a status to send to a port with
/// the `post` method. The parameters are opaquely passed through and not
/// interpreted by the system at all.
pub(crate) fn new(bytes: u32, token: usize, overlapped: *mut Overlapped) -> Self {
CompletionStatus(OVERLAPPED_ENTRY {
dwNumberOfBytesTransferred: bytes,
lpCompletionKey: token,
lpOverlapped: overlapped as *mut _,
Internal: 0,
})
}
/// Creates a new borrowed completion status from the borrowed
/// `OVERLAPPED_ENTRY` argument provided.
///
/// This method will wrap the `OVERLAPPED_ENTRY` in a `CompletionStatus`,
/// returning the wrapped structure.
#[cfg(feature = "os-ext")]
pub fn from_entry(entry: &OVERLAPPED_ENTRY) -> &Self {
// Safety: CompletionStatus is repr(transparent) w/ OVERLAPPED_ENTRY, so
// a reference to one is guaranteed to be layout compatible with the
// reference to another.
unsafe { &*(entry as *const _ as *const _) }
}
/// Creates a new "zero" completion status.
///
/// This function is useful when creating a stack buffer or vector of
/// completion statuses to be passed to the `get_many` function.
pub fn zero() -> Self {
Self::new(0, 0, std::ptr::null_mut())
}
/// Returns the number of bytes that were transferred for the I/O operation
/// associated with this completion status.
pub fn bytes_transferred(&self) -> u32 {
self.0.dwNumberOfBytesTransferred
}
/// Returns the completion key value associated with the file handle whose
/// I/O operation has completed.
///
/// A completion key is a per-handle key that is specified when it is added
/// to an I/O completion port via `add_handle` or `add_socket`.
pub fn token(&self) -> usize {
self.0.lpCompletionKey as usize
}
/// Returns a pointer to the `Overlapped` structure that was specified when
/// the I/O operation was started.
pub fn overlapped(&self) -> *mut OVERLAPPED {
self.0.lpOverlapped
}
/// Returns a pointer to the internal `OVERLAPPED_ENTRY` object.
pub fn entry(&self) -> &OVERLAPPED_ENTRY {
&self.0
}
}
#[inline]
fn duration_millis(dur: Option<Duration>) -> u32 {
if let Some(dur) = dur {
// `Duration::as_millis` truncates, so round up. This avoids
// turning sub-millisecond timeouts into a zero timeout, unless
// the caller explicitly requests that by specifying a zero
// timeout.
let dur_ms = dur
.checked_add(Duration::from_nanos(999_999))
.unwrap_or(dur)
.as_millis();
cmp::min(dur_ms, u32::MAX as u128) as u32
} else {
u32::MAX
}
}
#[cfg(test)]
mod tests {
use super::{CompletionPort, CompletionStatus};
#[test]
fn is_send_sync() {
fn is_send_sync<T: Send + Sync>() {}
is_send_sync::<CompletionPort>();
}
#[test]
fn get_many() {
let c = CompletionPort::new(1).unwrap();
c.post(CompletionStatus::new(1, 2, 3 as *mut _)).unwrap();
c.post(CompletionStatus::new(4, 5, 6 as *mut _)).unwrap();
let mut s = vec![CompletionStatus::zero(); 4];
{
let s = c.get_many(&mut s, None).unwrap();
assert_eq!(s.len(), 2);
assert_eq!(s[0].bytes_transferred(), 1);
assert_eq!(s[0].token(), 2);
assert_eq!(s[0].overlapped(), 3 as *mut _);
assert_eq!(s[1].bytes_transferred(), 4);
assert_eq!(s[1].token(), 5);
assert_eq!(s[1].overlapped(), 6 as *mut _);
}
assert_eq!(s[2].bytes_transferred(), 0);
assert_eq!(s[2].token(), 0);
assert_eq!(s[2].overlapped(), 0 as *mut _);
}
}

View file

@ -1,15 +1,20 @@
mod afd;
mod io_status_block;
pub mod event;
pub use event::{Event, Events};
mod selector;
pub use selector::{Selector, SelectorInner, SockState};
mod handle;
use handle::Handle;
mod io_status_block;
mod iocp;
mod overlapped;
use overlapped::Overlapped;
mod selector;
pub use selector::{Selector, SelectorInner, SockState};
// Macros must be defined before the modules that use them
cfg_net! {
/// Helper macro to execute a system call that returns an `io::Result`.

View file

@ -1,19 +1,29 @@
use std::ffi::OsStr;
use std::io::{self, Read, Write};
use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
use std::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle};
use std::sync::atomic::Ordering::{Relaxed, SeqCst};
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::{Arc, Mutex};
use std::{fmt, mem, slice};
use miow::iocp::{CompletionPort, CompletionStatus};
use miow::pipe;
use winapi::shared::winerror::{ERROR_BROKEN_PIPE, ERROR_PIPE_LISTENING};
use winapi::um::ioapiset::CancelIoEx;
use winapi::um::minwinbase::{OVERLAPPED, OVERLAPPED_ENTRY};
use windows_sys::Win32::Foundation::{
ERROR_BROKEN_PIPE, ERROR_IO_INCOMPLETE, ERROR_IO_PENDING, ERROR_NO_DATA, ERROR_PIPE_CONNECTED,
ERROR_PIPE_LISTENING, HANDLE, INVALID_HANDLE_VALUE,
};
use windows_sys::Win32::Storage::FileSystem::{
ReadFile, WriteFile, FILE_FLAG_FIRST_PIPE_INSTANCE, FILE_FLAG_OVERLAPPED, PIPE_ACCESS_DUPLEX,
};
use windows_sys::Win32::System::Pipes::{
ConnectNamedPipe, CreateNamedPipeW, DisconnectNamedPipe, PIPE_TYPE_BYTE,
PIPE_UNLIMITED_INSTANCES,
};
use windows_sys::Win32::System::IO::{
CancelIoEx, GetOverlappedResult, OVERLAPPED, OVERLAPPED_ENTRY,
};
use crate::event::Source;
use crate::sys::windows::{Event, Overlapped};
use crate::sys::windows::iocp::{CompletionPort, CompletionStatus};
use crate::sys::windows::{Event, Handle, Overlapped};
use crate::Registry;
use crate::{Interest, Token};
@ -75,7 +85,7 @@ struct Inner {
read: Overlapped,
write: Overlapped,
// END NOTE.
handle: pipe::NamedPipe,
handle: Handle,
connecting: AtomicBool,
io: Mutex<Io>,
pool: Mutex<BufferPool>,
@ -103,6 +113,193 @@ impl Inner {
// `read` is after `connect: Overlapped` and `read: Overlapped`.
(ptr as *mut Overlapped).wrapping_sub(2) as *const Inner
}
/// Issue a connection request with the specified overlapped operation.
///
/// This function will issue a request to connect a client to this server,
/// returning immediately after starting the overlapped operation.
///
/// If this function immediately succeeds then `Ok(true)` is returned. If
/// the overlapped operation is enqueued and pending, then `Ok(false)` is
/// returned. Otherwise an error is returned indicating what went wrong.
///
/// # Unsafety
///
/// This function is unsafe because the kernel requires that the
/// `overlapped` pointer is valid until the end of the I/O operation. The
/// kernel also requires that `overlapped` is unique for this I/O operation
/// and is not in use for any other I/O.
///
/// To safely use this function callers must ensure that this pointer is
/// valid until the I/O operation is completed, typically via completion
/// ports and waiting to receive the completion notification on the port.
pub unsafe fn connect_overlapped(&self, overlapped: *mut OVERLAPPED) -> io::Result<bool> {
if ConnectNamedPipe(self.handle.raw(), overlapped) != 0 {
return Ok(true);
}
let err = io::Error::last_os_error();
match err.raw_os_error().map(|e| e as u32) {
Some(ERROR_PIPE_CONNECTED) => Ok(true),
Some(ERROR_NO_DATA) => Ok(true),
Some(ERROR_IO_PENDING) => Ok(false),
_ => Err(err),
}
}
/// Disconnects this named pipe from any connected client.
pub fn disconnect(&self) -> io::Result<()> {
if unsafe { DisconnectNamedPipe(self.handle.raw()) } == 0 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
}
/// Issues an overlapped read operation to occur on this pipe.
///
/// This function will issue an asynchronous read to occur in an overlapped
/// fashion, returning immediately. The `buf` provided will be filled in
/// with data and the request is tracked by the `overlapped` function
/// provided.
///
/// If the operation succeeds immediately, `Ok(Some(n))` is returned where
/// `n` is the number of bytes read. If an asynchronous operation is
/// enqueued, then `Ok(None)` is returned. Otherwise if an error occurred
/// it is returned.
///
/// When this operation completes (or if it completes immediately), another
/// mechanism must be used to learn how many bytes were transferred (such as
/// looking at the filed in the IOCP status message).
///
/// # Unsafety
///
/// This function is unsafe because the kernel requires that the `buf` and
/// `overlapped` pointers to be valid until the end of the I/O operation.
/// The kernel also requires that `overlapped` is unique for this I/O
/// operation and is not in use for any other I/O.
///
/// To safely use this function callers must ensure that the pointers are
/// valid until the I/O operation is completed, typically via completion
/// ports and waiting to receive the completion notification on the port.
pub unsafe fn read_overlapped(
&self,
buf: &mut [u8],
overlapped: *mut OVERLAPPED,
) -> io::Result<Option<usize>> {
let len = std::cmp::min(buf.len(), u32::MAX as usize) as u32;
let res = ReadFile(
self.handle.raw(),
buf.as_mut_ptr() as *mut _,
len,
std::ptr::null_mut(),
overlapped,
);
if res == 0 {
let err = io::Error::last_os_error();
if err.raw_os_error() != Some(ERROR_IO_PENDING as i32) {
return Err(err);
}
}
let mut bytes = 0;
let res = GetOverlappedResult(self.handle.raw(), overlapped, &mut bytes, 0);
if res == 0 {
let err = io::Error::last_os_error();
if err.raw_os_error() == Some(ERROR_IO_INCOMPLETE as i32) {
Ok(None)
} else {
Err(err)
}
} else {
Ok(Some(bytes as usize))
}
}
/// Issues an overlapped write operation to occur on this pipe.
///
/// This function will issue an asynchronous write to occur in an overlapped
/// fashion, returning immediately. The `buf` provided will be filled in
/// with data and the request is tracked by the `overlapped` function
/// provided.
///
/// If the operation succeeds immediately, `Ok(Some(n))` is returned where
/// `n` is the number of bytes written. If an asynchronous operation is
/// enqueued, then `Ok(None)` is returned. Otherwise if an error occurred
/// it is returned.
///
/// When this operation completes (or if it completes immediately), another
/// mechanism must be used to learn how many bytes were transferred (such as
/// looking at the filed in the IOCP status message).
///
/// # Unsafety
///
/// This function is unsafe because the kernel requires that the `buf` and
/// `overlapped` pointers to be valid until the end of the I/O operation.
/// The kernel also requires that `overlapped` is unique for this I/O
/// operation and is not in use for any other I/O.
///
/// To safely use this function callers must ensure that the pointers are
/// valid until the I/O operation is completed, typically via completion
/// ports and waiting to receive the completion notification on the port.
pub unsafe fn write_overlapped(
&self,
buf: &[u8],
overlapped: *mut OVERLAPPED,
) -> io::Result<Option<usize>> {
let len = std::cmp::min(buf.len(), u32::MAX as usize) as u32;
let res = WriteFile(
self.handle.raw(),
buf.as_ptr() as *const _,
len,
std::ptr::null_mut(),
overlapped,
);
if res == 0 {
let err = io::Error::last_os_error();
if err.raw_os_error() != Some(ERROR_IO_PENDING as i32) {
return Err(err);
}
}
let mut bytes = 0;
let res = GetOverlappedResult(self.handle.raw(), overlapped, &mut bytes, 0);
if res == 0 {
let err = io::Error::last_os_error();
if err.raw_os_error() == Some(ERROR_IO_INCOMPLETE as i32) {
Ok(None)
} else {
Err(err)
}
} else {
Ok(Some(bytes as usize))
}
}
/// Calls the `GetOverlappedResult` function to get the result of an
/// overlapped operation for this handle.
///
/// This function takes the `OVERLAPPED` argument which must have been used
/// to initiate an overlapped I/O operation, and returns either the
/// successful number of bytes transferred during the operation or an error
/// if one occurred.
///
/// # Unsafety
///
/// This function is unsafe as `overlapped` must have previously been used
/// to execute an operation for this handle, and it must also be a valid
/// pointer to an `Overlapped` instance.
#[inline]
unsafe fn result(&self, overlapped: *mut OVERLAPPED) -> io::Result<usize> {
let mut transferred = 0;
let r = GetOverlappedResult(self.handle.raw(), overlapped, &mut transferred, 0);
if r == 0 {
Err(io::Error::last_os_error())
} else {
Ok(transferred as usize)
}
}
}
#[test]
@ -158,10 +355,30 @@ impl NamedPipe {
/// Creates a new named pipe at the specified `addr` given a "reasonable
/// set" of initial configuration options.
pub fn new<A: AsRef<OsStr>>(addr: A) -> io::Result<NamedPipe> {
let pipe = pipe::NamedPipe::new(addr)?;
// Safety: nothing actually unsafe about this. The trait fn includes
// `unsafe`.
Ok(unsafe { NamedPipe::from_raw_handle(pipe.into_raw_handle()) })
use std::os::windows::ffi::OsStrExt;
let name: Vec<_> = addr.as_ref().encode_wide().chain(Some(0)).collect();
// Safety: syscall
let h = unsafe {
CreateNamedPipeW(
name.as_ptr(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE,
PIPE_UNLIMITED_INSTANCES,
65536,
65536,
0,
std::ptr::null_mut(),
)
};
if h == INVALID_HANDLE_VALUE {
Err(io::Error::last_os_error())
} else {
// Safety: nothing actually unsafe about this. The trait fn includes
// `unsafe`.
Ok(unsafe { Self::from_raw_handle(h as RawHandle) })
}
}
/// Attempts to call `ConnectNamedPipe`, if possible.
@ -196,7 +413,7 @@ impl NamedPipe {
// internal state accordingly.
let res = unsafe {
let overlapped = self.inner.connect.as_ptr() as *mut _;
self.inner.handle.connect_overlapped(overlapped)
self.inner.connect_overlapped(overlapped)
};
match res {
@ -248,7 +465,7 @@ impl NamedPipe {
/// After a `disconnect` is issued, then a `connect` may be called again to
/// connect to another client.
pub fn disconnect(&self) -> io::Result<()> {
self.inner.handle.disconnect()
self.inner.disconnect()
}
}
@ -256,10 +473,7 @@ impl FromRawHandle for NamedPipe {
unsafe fn from_raw_handle(handle: RawHandle) -> NamedPipe {
NamedPipe {
inner: Arc::new(Inner {
// Safety: not really unsafe
handle: pipe::NamedPipe::from_raw_handle(handle),
// transmutes to straddle winapi versions (mio 0.6 is on an
// older winapi)
handle: Handle::new(handle as HANDLE),
connect: Overlapped::new(connect_done),
connecting: AtomicBool::new(false),
read: Overlapped::new(read_done),
@ -401,10 +615,7 @@ impl Source for NamedPipe {
io.cp = Some(selector.clone_port());
let inner_token = NEXT_TOKEN.fetch_add(2, Relaxed) + 2;
selector
.inner
.cp
.add_handle(inner_token, &self.inner.handle)?;
selector.inner.cp.add_handle(inner_token, self)?;
}
io.token = Some(token);
@ -447,7 +658,7 @@ impl Source for NamedPipe {
impl AsRawHandle for NamedPipe {
fn as_raw_handle(&self) -> RawHandle {
self.inner.handle.as_raw_handle()
self.inner.handle.raw() as RawHandle
}
}
@ -494,7 +705,7 @@ impl Inner {
let e = unsafe {
let overlapped = me.read.as_ptr() as *mut _;
let slice = slice::from_raw_parts_mut(buf.as_mut_ptr(), buf.capacity());
me.handle.read_overlapped(slice, overlapped)
me.read_overlapped(slice, overlapped)
};
match e {
@ -533,7 +744,7 @@ impl Inner {
// Very similar to `schedule_read` above, just done for the write half.
let e = unsafe {
let overlapped = me.write.as_ptr() as *mut _;
me.handle.write_overlapped(&buf[pos..], overlapped)
me.write_overlapped(&buf[pos..], overlapped)
};
// See `connect` above for the rationale behind `forget`
@ -600,8 +811,8 @@ impl Inner {
}
}
unsafe fn cancel<T: AsRawHandle>(handle: &T, overlapped: &Overlapped) -> io::Result<()> {
let ret = CancelIoEx(handle.as_raw_handle(), overlapped.as_ptr() as *mut _);
unsafe fn cancel(handle: &Handle, overlapped: &Overlapped) -> io::Result<()> {
let ret = CancelIoEx(handle.raw(), overlapped.as_ptr());
// `CancelIoEx` returns 0 on error:
// https://docs.microsoft.com/en-us/windows/win32/fileio/cancelioex-func
if ret == 0 {
@ -626,7 +837,7 @@ fn connect_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
// Stash away our connect error if one happened
debug_assert_eq!(status.bytes_transferred(), 0);
unsafe {
match me.handle.result(status.overlapped()) {
match me.result(status.overlapped()) {
Ok(n) => debug_assert_eq!(n, 0),
Err(e) => me.io.lock().unwrap().connect_error = Some(e),
}
@ -652,7 +863,7 @@ fn read_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
_ => unreachable!(),
};
unsafe {
match me.handle.result(status.overlapped()) {
match me.result(status.overlapped()) {
Ok(n) => {
debug_assert_eq!(status.bytes_transferred() as usize, n);
buf.set_len(status.bytes_transferred() as usize);
@ -692,7 +903,7 @@ fn write_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
};
unsafe {
match me.handle.result(status.overlapped()) {
match me.result(status.overlapped()) {
Ok(n) => {
debug_assert_eq!(status.bytes_transferred() as usize, n);
let new_pos = pos + (status.bytes_transferred() as usize);

View file

@ -3,15 +3,14 @@ use std::mem;
use std::net::SocketAddr;
use std::sync::Once;
use winapi::ctypes::c_int;
use winapi::shared::in6addr::{in6_addr_u, IN6_ADDR};
use winapi::shared::inaddr::{in_addr_S_un, IN_ADDR};
use winapi::shared::ws2def::{ADDRESS_FAMILY, AF_INET, AF_INET6, SOCKADDR, SOCKADDR_IN};
use winapi::shared::ws2ipdef::{SOCKADDR_IN6_LH_u, SOCKADDR_IN6_LH};
use winapi::um::winsock2::{ioctlsocket, socket, FIONBIO, INVALID_SOCKET, SOCKET};
use windows_sys::Win32::Networking::WinSock::{
closesocket, ioctlsocket, socket, AF_INET, AF_INET6, FIONBIO, IN6_ADDR, IN6_ADDR_0,
INVALID_SOCKET, IN_ADDR, IN_ADDR_0, SOCKADDR, SOCKADDR_IN, SOCKADDR_IN6, SOCKADDR_IN6_0,
SOCKET,
};
/// Initialise the network stack for Windows.
pub(crate) fn init() {
fn init() {
static INIT: Once = Once::new();
INIT.call_once(|| {
// Let standard library call `WSAStartup` for us, we can't do it
@ -22,26 +21,30 @@ pub(crate) fn init() {
}
/// Create a new non-blocking socket.
pub(crate) fn new_ip_socket(addr: SocketAddr, socket_type: c_int) -> io::Result<SOCKET> {
use winapi::um::winsock2::{PF_INET, PF_INET6};
pub(crate) fn new_ip_socket(addr: SocketAddr, socket_type: i32) -> io::Result<SOCKET> {
let domain = match addr {
SocketAddr::V4(..) => PF_INET,
SocketAddr::V6(..) => PF_INET6,
SocketAddr::V4(..) => AF_INET,
SocketAddr::V6(..) => AF_INET6,
};
new_socket(domain, socket_type)
new_socket(domain.into(), socket_type)
}
pub(crate) fn new_socket(domain: c_int, socket_type: c_int) -> io::Result<SOCKET> {
syscall!(
socket(domain, socket_type, 0),
pub(crate) fn new_socket(domain: u32, socket_type: i32) -> io::Result<SOCKET> {
init();
let socket = syscall!(
socket(domain as i32, socket_type, 0),
PartialEq::eq,
INVALID_SOCKET
)
.and_then(|socket| {
syscall!(ioctlsocket(socket, FIONBIO, &mut 1), PartialEq::ne, 0).map(|_| socket as SOCKET)
})
)?;
if let Err(err) = syscall!(ioctlsocket(socket, FIONBIO, &mut 1), PartialEq::ne, 0) {
let _ = unsafe { closesocket(socket) };
return Err(err);
}
Ok(socket as SOCKET)
}
/// A type with the same memory layout as `SOCKADDR`. Used in converting Rust level
@ -51,7 +54,7 @@ pub(crate) fn new_socket(domain: c_int, socket_type: c_int) -> io::Result<SOCKET
#[repr(C)]
pub(crate) union SocketAddrCRepr {
v4: SOCKADDR_IN,
v6: SOCKADDR_IN6_LH,
v6: SOCKADDR_IN6,
}
impl SocketAddrCRepr {
@ -60,49 +63,49 @@ impl SocketAddrCRepr {
}
}
pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, c_int) {
pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, i32) {
match addr {
SocketAddr::V4(ref addr) => {
// `s_addr` is stored as BE on all machine and the array is in BE order.
// So the native endian conversion method is used so that it's never swapped.
let sin_addr = unsafe {
let mut s_un = mem::zeroed::<in_addr_S_un>();
*s_un.S_addr_mut() = u32::from_ne_bytes(addr.ip().octets());
let mut s_un = mem::zeroed::<IN_ADDR_0>();
s_un.S_addr = u32::from_ne_bytes(addr.ip().octets());
IN_ADDR { S_un: s_un }
};
let sockaddr_in = SOCKADDR_IN {
sin_family: AF_INET as ADDRESS_FAMILY,
sin_family: AF_INET as u16, // 1
sin_port: addr.port().to_be(),
sin_addr,
sin_zero: [0; 8],
};
let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
(sockaddr, mem::size_of::<SOCKADDR_IN>() as c_int)
(sockaddr, mem::size_of::<SOCKADDR_IN>() as i32)
}
SocketAddr::V6(ref addr) => {
let sin6_addr = unsafe {
let mut u = mem::zeroed::<in6_addr_u>();
*u.Byte_mut() = addr.ip().octets();
let mut u = mem::zeroed::<IN6_ADDR_0>();
u.Byte = addr.ip().octets();
IN6_ADDR { u }
};
let u = unsafe {
let mut u = mem::zeroed::<SOCKADDR_IN6_LH_u>();
*u.sin6_scope_id_mut() = addr.scope_id();
let mut u = mem::zeroed::<SOCKADDR_IN6_0>();
u.sin6_scope_id = addr.scope_id();
u
};
let sockaddr_in6 = SOCKADDR_IN6_LH {
sin6_family: AF_INET6 as ADDRESS_FAMILY,
let sockaddr_in6 = SOCKADDR_IN6 {
sin6_family: AF_INET6 as u16, // 23
sin6_port: addr.port().to_be(),
sin6_addr,
sin6_flowinfo: addr.flowinfo(),
u,
Anonymous: u,
};
let sockaddr = SocketAddrCRepr { v6: sockaddr_in6 };
(sockaddr, mem::size_of::<SOCKADDR_IN6_LH>() as c_int)
(sockaddr, mem::size_of::<SOCKADDR_IN6>() as i32)
}
}
}

View file

@ -3,13 +3,11 @@ use crate::sys::windows::Event;
use std::cell::UnsafeCell;
use std::fmt;
#[cfg(feature = "os-ext")]
use winapi::um::minwinbase::OVERLAPPED;
use winapi::um::minwinbase::OVERLAPPED_ENTRY;
use windows_sys::Win32::System::IO::{OVERLAPPED, OVERLAPPED_ENTRY};
#[repr(C)]
pub(crate) struct Overlapped {
inner: UnsafeCell<miow::Overlapped>,
inner: UnsafeCell<OVERLAPPED>,
pub(crate) callback: fn(&OVERLAPPED_ENTRY, Option<&mut Vec<Event>>),
}
@ -17,13 +15,13 @@ pub(crate) struct Overlapped {
impl Overlapped {
pub(crate) fn new(cb: fn(&OVERLAPPED_ENTRY, Option<&mut Vec<Event>>)) -> Overlapped {
Overlapped {
inner: UnsafeCell::new(miow::Overlapped::zero()),
inner: UnsafeCell::new(unsafe { std::mem::zeroed() }),
callback: cb,
}
}
pub(crate) fn as_ptr(&self) -> *const OVERLAPPED {
unsafe { (*self.inner.get()).raw() }
self.inner.get()
}
}

View file

@ -10,8 +10,9 @@ cfg_net! {
use crate::Interest;
}
use miow::iocp::{CompletionPort, CompletionStatus};
use super::iocp::{CompletionPort, CompletionStatus};
use std::collections::VecDeque;
use std::ffi::c_void;
use std::io;
use std::marker::PhantomPinned;
use std::os::windows::io::RawSocket;
@ -21,11 +22,11 @@ use std::sync::atomic::AtomicUsize;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use winapi::shared::ntdef::NT_SUCCESS;
use winapi::shared::ntdef::{HANDLE, PVOID};
use winapi::shared::ntstatus::STATUS_CANCELLED;
use winapi::shared::winerror::{ERROR_INVALID_HANDLE, ERROR_IO_PENDING, WAIT_TIMEOUT};
use winapi::um::minwinbase::OVERLAPPED;
use windows_sys::Win32::Foundation::{
ERROR_INVALID_HANDLE, ERROR_IO_PENDING, HANDLE, STATUS_CANCELLED, WAIT_TIMEOUT,
};
use windows_sys::Win32::System::IO::OVERLAPPED;
#[derive(Debug)]
struct AfdGroup {
@ -141,7 +142,7 @@ impl SockState {
/* No poll operation is pending; start one. */
self.poll_info.exclusive = 0;
self.poll_info.number_of_handles = 1;
*unsafe { self.poll_info.timeout.QuadPart_mut() } = std::i64::MAX;
self.poll_info.timeout = i64::MAX;
self.poll_info.handles[0].handle = self.base_socket as HANDLE;
self.poll_info.handles[0].status = 0;
self.poll_info.handles[0].events = self.user_evts | afd::POLL_LOCAL_CLOSE;
@ -204,9 +205,9 @@ impl SockState {
unsafe {
if self.delete_pending {
return None;
} else if self.iosb.u.Status == STATUS_CANCELLED {
} else if self.iosb.Anonymous.Status == STATUS_CANCELLED {
/* The poll request was cancelled by CancelIoEx. */
} else if !NT_SUCCESS(self.iosb.u.Status) {
} else if self.iosb.Anonymous.Status < 0 {
/* The overlapped request itself failed in an unexpected way. */
afd_events = afd::POLL_CONNECT_FAIL;
} else if self.poll_info.number_of_handles < 1 {
@ -295,7 +296,7 @@ impl Drop for SockState {
/// Converts the pointer to a `SockState` into a raw pointer.
/// To revert see `from_overlapped`.
fn into_overlapped(sock_state: Pin<Arc<Mutex<SockState>>>) -> PVOID {
fn into_overlapped(sock_state: Pin<Arc<Mutex<SockState>>>) -> *mut c_void {
let overlapped_ptr: *const Mutex<SockState> =
unsafe { Arc::into_raw(Pin::into_inner_unchecked(sock_state)) };
overlapped_ptr as *mut _
@ -316,7 +317,7 @@ fn from_overlapped(ptr: *mut OVERLAPPED) -> Pin<Arc<Mutex<SockState>>> {
#[cfg(debug_assertions)]
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
/// Windows implementaion of `sys::Selector`
/// Windows implementation of `sys::Selector`
///
/// Edge-triggered event notification is simulated by resetting internal event flag of each socket state `SockState`
/// and setting all events back by intercepting all requests that could cause `io::ErrorKind::WouldBlock` happening.
@ -534,9 +535,12 @@ impl SelectorInner {
cfg_io_source! {
use std::mem::size_of;
use std::ptr::null_mut;
use winapi::um::mswsock;
use winapi::um::winsock2::WSAGetLastError;
use winapi::um::winsock2::{WSAIoctl, SOCKET_ERROR};
use windows_sys::Win32::Networking::WinSock::{
WSAGetLastError, WSAIoctl, SIO_BASE_HANDLE, SIO_BSP_HANDLE,
SIO_BSP_HANDLE_POLL, SIO_BSP_HANDLE_SELECT, SOCKET_ERROR,
};
impl SelectorInner {
fn register(
@ -640,7 +644,7 @@ cfg_io_source! {
ioctl,
null_mut(),
0,
&mut base_socket as *mut _ as PVOID,
&mut base_socket as *mut _ as *mut c_void,
size_of::<RawSocket>() as u32,
&mut bytes,
null_mut(),
@ -655,7 +659,7 @@ cfg_io_source! {
}
fn get_base_socket(raw_socket: RawSocket) -> io::Result<RawSocket> {
let res = try_get_base_socket(raw_socket, mswsock::SIO_BASE_HANDLE);
let res = try_get_base_socket(raw_socket, SIO_BASE_HANDLE);
if let Ok(base_socket) = res {
return Ok(base_socket);
}
@ -666,9 +670,9 @@ cfg_io_source! {
// However, at least one known LSP deliberately breaks it, so we try
// some alternative IOCTLs, starting with the most appropriate one.
for &ioctl in &[
mswsock::SIO_BSP_HANDLE_SELECT,
mswsock::SIO_BSP_HANDLE_POLL,
mswsock::SIO_BSP_HANDLE,
SIO_BSP_HANDLE_SELECT,
SIO_BSP_HANDLE_POLL,
SIO_BSP_HANDLE,
] {
if let Ok(base_socket) = try_get_base_socket(raw_socket, ioctl) {
// Since we know now that we're dealing with an LSP (otherwise

View file

@ -2,21 +2,16 @@ use std::io;
use std::net::{self, SocketAddr};
use std::os::windows::io::AsRawSocket;
use winapi::um::winsock2::{self, PF_INET, PF_INET6, SOCKET, SOCKET_ERROR, SOCK_STREAM};
use windows_sys::Win32::Networking::WinSock::{self, SOCKET, SOCKET_ERROR, SOCK_STREAM};
use crate::sys::windows::net::{init, new_socket, socket_addr};
use crate::sys::windows::net::{new_ip_socket, socket_addr};
pub(crate) fn new_for_addr(address: SocketAddr) -> io::Result<SOCKET> {
init();
let domain = match address {
SocketAddr::V4(_) => PF_INET,
SocketAddr::V6(_) => PF_INET6,
};
new_socket(domain, SOCK_STREAM)
new_ip_socket(address, SOCK_STREAM)
}
pub(crate) fn bind(socket: &net::TcpListener, addr: SocketAddr) -> io::Result<()> {
use winsock2::bind;
use WinSock::bind;
let (raw_addr, raw_addr_length) = socket_addr(&addr);
syscall!(
@ -32,7 +27,7 @@ pub(crate) fn bind(socket: &net::TcpListener, addr: SocketAddr) -> io::Result<()
}
pub(crate) fn connect(socket: &net::TcpStream, addr: SocketAddr) -> io::Result<()> {
use winsock2::connect;
use WinSock::connect;
let (raw_addr, raw_addr_length) = socket_addr(&addr);
let res = syscall!(
@ -53,7 +48,7 @@ pub(crate) fn connect(socket: &net::TcpStream, addr: SocketAddr) -> io::Result<(
pub(crate) fn listen(socket: &net::TcpListener, backlog: u32) -> io::Result<()> {
use std::convert::TryInto;
use winsock2::listen;
use WinSock::listen;
let backlog = backlog.try_into().unwrap_or(i32::max_value());
syscall!(

View file

@ -2,43 +2,36 @@ use std::io;
use std::mem::{self, MaybeUninit};
use std::net::{self, SocketAddr};
use std::os::windows::io::{AsRawSocket, FromRawSocket};
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.
use std::os::windows::raw::SOCKET as StdSocket; // windows-sys uses usize, stdlib uses u32/u64.
use winapi::ctypes::c_int;
use winapi::shared::ws2def::IPPROTO_IPV6;
use winapi::shared::ws2ipdef::IPV6_V6ONLY;
use winapi::um::winsock2::{bind as win_bind, closesocket, getsockopt, SOCKET_ERROR, SOCK_DGRAM};
use crate::sys::windows::net::{init, new_ip_socket, socket_addr};
use crate::sys::windows::net::{new_ip_socket, socket_addr};
use windows_sys::Win32::Networking::WinSock::{
bind as win_bind, getsockopt, IPPROTO_IPV6, IPV6_V6ONLY, SOCKET_ERROR, SOCK_DGRAM,
};
pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
init();
new_ip_socket(addr, SOCK_DGRAM).and_then(|socket| {
let (raw_addr, raw_addr_length) = socket_addr(&addr);
syscall!(
win_bind(socket, raw_addr.as_ptr(), raw_addr_length,),
PartialEq::eq,
SOCKET_ERROR
)
.map_err(|err| {
// Close the socket if we hit an error, ignoring the error
// from closing since we can't pass back two errors.
let _ = unsafe { closesocket(socket) };
err
})
.map(|_| unsafe { net::UdpSocket::from_raw_socket(socket as StdSocket) })
})
let raw_socket = new_ip_socket(addr, SOCK_DGRAM)?;
let socket = unsafe { net::UdpSocket::from_raw_socket(raw_socket as StdSocket) };
let (raw_addr, raw_addr_length) = socket_addr(&addr);
syscall!(
win_bind(raw_socket, raw_addr.as_ptr(), raw_addr_length),
PartialEq::eq,
SOCKET_ERROR
)?;
Ok(socket)
}
pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> {
let mut optval: MaybeUninit<c_int> = MaybeUninit::uninit();
let mut optlen = mem::size_of::<c_int>() as c_int;
let mut optval: MaybeUninit<i32> = MaybeUninit::uninit();
let mut optlen = mem::size_of::<i32>() as i32;
syscall!(
getsockopt(
socket.as_raw_socket() as usize,
IPPROTO_IPV6 as c_int,
IPV6_V6ONLY as c_int,
IPPROTO_IPV6 as i32,
IPV6_V6ONLY as i32,
optval.as_mut_ptr().cast(),
&mut optlen,
),
@ -46,7 +39,7 @@ pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> {
SOCKET_ERROR
)?;
debug_assert_eq!(optlen as usize, mem::size_of::<c_int>());
debug_assert_eq!(optlen as usize, mem::size_of::<i32>());
// Safety: `getsockopt` initialised `optval` for us.
let optval = unsafe { optval.assume_init() };
Ok(optval != 0)

View file

@ -2,7 +2,7 @@ use crate::sys::windows::Event;
use crate::sys::windows::Selector;
use crate::Token;
use miow::iocp::CompletionPort;
use super::iocp::CompletionPort;
use std::io;
use std::sync::Arc;

View file

@ -28,7 +28,7 @@ use std::io;
/// kqueue. On Linux it uses [eventfd].
///
/// [implementation notes of `Poll`]: struct.Poll.html#implementation-notes
/// [eventfd]: http://man7.org/linux/man-pages/man2/eventfd.2.html
/// [eventfd]: https://man7.org/linux/man-pages/man2/eventfd.2.html
///
/// # Examples
///

View file

@ -1 +0,0 @@
{"files":{"Cargo.toml":"c590838810b459f0055af8724e1ac392570a0dcf223bf403b87f728a14c6a500","LICENSE-APACHE":"cf90d659de5c1e6418267ab8043b756e65508ee5d8d50b29eb2d2fe444c2c3eb","LICENSE-MIT":"11a7964ccc0dd115d16720ab1d826c5d03e52838748ffaba3d21bae8bcacd82a","README.md":"748712a61ff52ec28ed1695b01975a379125f9c3e8a4ad5b2e9b64096c2a3df1","build.rs":"13a274ea4cb1886872626b8a98269e9bf2e1f93cb1068fc8c797e421746cac7e","src/lib.rs":"261643e01f42e3b04cc0760811da090348923d40761c863eebb4735af6294207","src/macros.rs":"b0a852ebea2e1aed3e7d70eeadc8356778b064d2eca6e796598e9ab37ac54175","src/ntapi_base.rs":"b2edefaf68709c32f7fb4377ea21457afd3c7546ba59596f9f25bbaeb220f4d4","src/ntdbg.rs":"f891d4b26ef9d6c68ca098ab70bb4b1dd4d7e1d05e0f65c32bc6cb1151528f91","src/ntexapi.rs":"9be1b1d061055b6f5276093db8346ecf148d0ad6e438d185a16b126acb514c22","src/ntgdi.rs":"9fa6610566d77e95294432957f8cb8564cef3bb09d2d8d0adcf23047fa3a5221","src/ntioapi.rs":"577f3c3d83a95a965fff62efbdaa01769e9b3cf713f0d296a948f34cdfddcedc","src/ntkeapi.rs":"1ede6613c94303e6087e30e64ee1f1623eada9d088ce50992904e1812b263923","src/ntldr.rs":"e70ac420828f47d35dade883efee4231b6455d53ff4d317ecf6d809d7bc5a2bc","src/ntlpcapi.rs":"da5070b1c1adad34091aedd01d2b888daa4dc9446fdcd69668565e6eeb2db11f","src/ntmisc.rs":"4904e383065828b86013ebd3b85d45b384b522899954ac89c561963061acc962","src/ntmmapi.rs":"3a371e9edb7df91d1242f9dae92bf6d295c9b6c3ca65846c8d1ebbba55bdf7ee","src/ntnls.rs":"ef90b985da124d2f4c4b8cb0addab766a0928843b4afa4bce40b3a9fcddaf163","src/ntobapi.rs":"3071d8bc73e40d92d769e4093744820c0a5e116ecf4a94676ca3cdc008adfd8e","src/ntpebteb.rs":"94a9fbc1b3c48fa368f1b602fa205d41d3201e4d8c638c0898402eb3ebb5b72a","src/ntpfapi.rs":"37270db61f2562cd5481302c2a5a64be186b8c7126eacfe12b6c66e9bec4bf61","src/ntpnpapi.rs":"cfcaa3dd6110f25a48c51c011bb8369e83e3817e142afb412e40d6e4b868a036","src/ntpoapi.rs":"a535206a89cd42f81e3b931e5802f8b3343fd35387e9f3fedd9b042a78853f34","src/ntpsapi.rs":"2ed2af3e90054aaf260952adcc4e46d6935db1efd57f843124f942388ecfc6ce","src/ntregapi.rs":"a6f5a830b48e88fd0a4824036fffda2d2d80d1cad07baf37607121142f2c4777","src/ntrtl.rs":"d970ae6cba47f346eef103d6bcac7260bb7fc70ebb7ec226b09acb6c5bc1f6c6","src/ntsam.rs":"dc59cfa944c27cf02b782fdbf110de4757ca6ae77806820a64a17742670242b4","src/ntseapi.rs":"c87688e028aa05513e361bb72288ef3af2f3dfe8e923745a84409d8fdeee57fd","src/ntsmss.rs":"6ac1f029b56a2a8856569c3acbedd7c560d2ccfac030aa2f2178f52d9312cdc5","src/nttmapi.rs":"7092c8b35aae642572c333b0fef1fe4a32f5a9c563249b585766317051670db5","src/nttp.rs":"47be534d36af7d6a715c87ef646824162bd3eb47f86a85ed8357c987c1a4fcdd","src/ntwow64.rs":"725baf7b32d24c0800abf730b58335e682332b821636ca699c40e80ba7148f94","src/ntxcapi.rs":"54fcadd43a0e146ade8ebdd750b09872d0e8f7a1295a9646910529048d5f6dca","src/ntzwapi.rs":"012932586fdbcac8eff57d90ce640e10d20e150dc7702100d1ea46f6f261f868","src/string.rs":"ac0e73f37384e03f14d9dc47fcfb3620a4157e122481f30c82b16fb21ab86a40","src/subprocesstag.rs":"4c85e44c91521cb20e5c6624b0cf4b27ca6ac7c3e560854ad34e0e66fb809971","src/winapi_local.rs":"2003099deec5e7039e5d2dd0aa6a43120816f67e94f4d9909c7f6689b62747e4","src/winapi_local/um.rs":"48859dfb53520bdd569c052ac26d06de2d16c57403ffbe4febbc1e1f25847f45","src/winapi_local/um/winioctl.rs":"00020fcda499ce558edfa4d684f5b4e198cbcfa5b3b8e9b62a122c0aca46514f","src/winapi_local/um/winnt.rs":"2640f7d4027632d45708fc085baaf90f55f792e9b9802625f2b7d4e7655f9da4","src/winsta.rs":"c5a28c5c55f08745b2b100a5a374af821cf173b053eb8ee54ae19a85455d3fac"},"package":"bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"}

View file

@ -1,69 +0,0 @@
# 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 are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "ntapi"
version = "0.4.0"
authors = ["MSxDOS <melcodos@gmail.com>"]
include = [
"src/**/*",
"Cargo.toml",
"build.rs",
"README.md",
"LICENSE-APACHE",
"LICENSE-MIT",
]
description = "FFI bindings for Native API"
documentation = "https://docs.rs/ntapi/*/x86_64-pc-windows-msvc/ntapi/"
readme = "README.md"
keywords = [
"windows",
"ffi",
"ntapi",
"native",
"win32",
]
categories = [
"external-ffi-bindings",
"no-std",
"os::windows-apis",
]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/MSxDOS/ntapi"
[package.metadata.docs.rs]
default-target = "x86_64-pc-windows-msvc"
targets = [
"aarch64-pc-windows-msvc",
"i686-pc-windows-msvc",
"x86_64-pc-windows-msvc",
]
[dependencies.winapi]
version = "0.3.9"
features = [
"cfg",
"evntrace",
"in6addr",
"inaddr",
"minwinbase",
"ntsecapi",
"windef",
"winioctl",
]
[features]
default = ["user"]
func-types = []
impl-default = ["winapi/impl-default"]
kernel = []
user = []

View file

@ -1,202 +0,0 @@
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.

View file

@ -1,17 +0,0 @@
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.

View file

@ -1,17 +0,0 @@
# ntapi [![AppVeyor][appveyor_badge]][appveyor_link] [![Crates.io][crates_badge]][crates_link] [![Documentation][docs_badge]][docs_link] [![Lines of Code][loc_badge]][loc_link] [![Unsafe][unsafe_badge]][unsafe_link]
Rust FFI bindings for Native API. Mostly based on Process Hacker [phnt](https://github.com/processhacker/processhacker/tree/master/phnt) headers as the most complete source of bindings to be found. The comments there also contain useful information on how to use specific things.
### Minimum supported Rust
1.64
[appveyor_link]: https://ci.appveyor.com/project/MSxDOS/ntapi
[appveyor_badge]: https://ci.appveyor.com/api/projects/status/i1fcmm0c5b7c6b6u/branch/master?svg=true
[crates_link]: https://crates.io/crates/ntapi
[crates_badge]: https://img.shields.io/crates/v/ntapi.svg
[docs_link]: https://docs.rs/ntapi/*/x86_64-pc-windows-msvc/ntapi/
[docs_badge]: https://docs.rs/ntapi/badge.svg
[loc_link]: https://github.com/Aaronepower/tokei
[loc_badge]: https://tokei.rs/b1/github/MSxDOS/ntapi
[unsafe_link]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html
[unsafe_badge]: https://img.shields.io/badge/unsafe-%E2%9C%94-C901DD.svg

View file

@ -1,15 +0,0 @@
use std::env::var;
fn main() {
#[cfg(feature = "user")] {
if var("TARGET").map(
|t| t == "x86_64-pc-windows-gnu" || t == "i686-pc-windows-gnu"
).unwrap_or(false) {
if var("WINAPI_NO_BUNDLED_LIBRARIES").is_ok() {
println!("cargo:rustc-link-lib=ntdll");
} else {
println!("cargo:rustc-link-lib=winapi_ntdll");
}
}
}
}

View file

@ -1,51 +0,0 @@
//! # Features
//! **`func-types`** -- Generate [types][fn_ptr] for external functions.<br/>
//! **`impl-default`** -- Implement [`Default`] for structs and unions.<br/>
//! **`user`** *(default)* -- Link to `ntdll`.<br/>
//! **`kernel`** -- Link to `ntoskrnl` on MSVC targets.<br/>
//!
//! [fn_ptr]: https://doc.rust-lang.org/reference/types.html#function-pointer-types
//! [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html#tymethod.default
#![cfg(all(windows, any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))]
#![no_std]
#![deny(unused, unused_qualifications)]
#![warn(unused_attributes)]
#![allow(bad_style, deprecated, overflowing_literals, unused_macros, clippy::cast_lossless, clippy::cast_ptr_alignment, clippy::len_without_is_empty, clippy::trivially_copy_pass_by_ref, clippy::unreadable_literal)]
#[doc(hidden)]
pub extern crate core as _core;
#[macro_use]
#[doc(hidden)]
pub extern crate winapi;
#[macro_use]
mod macros;
pub mod ntapi_base;
pub mod ntdbg;
pub mod ntexapi;
pub mod ntgdi;
pub mod ntioapi;
pub mod ntkeapi;
pub mod ntldr;
pub mod ntlpcapi;
pub mod ntmisc;
pub mod ntmmapi;
pub mod ntnls;
pub mod ntobapi;
pub mod ntpebteb;
pub mod ntpfapi;
pub mod ntpnpapi;
pub mod ntpoapi;
pub mod ntpsapi;
pub mod ntregapi;
pub mod ntrtl;
pub mod ntsam;
pub mod ntseapi;
pub mod ntsmss;
pub mod nttmapi;
pub mod nttp;
pub mod ntwow64;
pub mod ntxcapi;
pub mod ntzwapi;
pub mod string;
pub mod subprocesstag;
pub mod winapi_local;
pub mod winsta;

View file

@ -1,112 +0,0 @@
#[macro_export]
macro_rules! EXTERN {
(extern $c:tt {$(
fn $n:ident ($( $p:tt $(: $t:ty)?),* $(,)?) $(-> $r:ty)?;
)+}) => {
#[cfg_attr(all(target_env = "msvc", feature = "user"), link(name = "ntdll"))]
#[cfg_attr(all(target_env = "msvc", feature = "kernel"), link(name = "ntoskrnl"))]
extern $c {$(
pub fn $n(
$($p $(: $t)?),*
) $(-> $r)?;
)+}
$(
#[cfg(feature = "func-types")]
pub type $n = unsafe extern $c fn($($p $(: $t)?),*) $(-> $r)?;
)+
};
(extern $c:tt {$(
static mut $n:ident : $t:ty;
)+}) => {
#[cfg_attr(all(target_env = "msvc", feature = "user"), link(name = "ntdll"))]
extern $c {$(
pub static mut $n: $t;
)+}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! FIELD_OFFSET {
($_type:ty, $field:ident$(.$cfields:ident)*) => {
unsafe {
union Transmuter<T: 'static> {
p: *const T,
r: &'static T,
i: usize,
}
#[allow(unaligned_references)]
Transmuter {
r: &(&Transmuter {
p: $crate::_core::ptr::null::<$_type>()
}.r).$field$(.$cfields)*
}.i
}
};
}
macro_rules! BITFIELD {
($base:ident $field:ident: $fieldtype:ty [
$($thing:ident $set_thing:ident[$r:expr],)+
]) => {
impl $base {$(
#[inline]
pub const fn $thing(&self) -> $fieldtype {
const SIZE: usize = $crate::_core::mem::size_of::<$fieldtype>() * 8;
self.$field << (SIZE - $r.end) >> (SIZE - $r.end + $r.start)
}
#[inline]
pub fn $set_thing(&mut self, val: $fieldtype) {
const MASK: $fieldtype = ((1 << ($r.end - $r.start)) - 1) << $r.start;
self.$field &= !MASK;
self.$field |= (val << $r.start) & MASK;
}
)+}
};
(unsafe $base:ident $field:ident: $fieldtype:ty [
$($thing:ident $set_thing:ident[$r:expr],)+
]) => {
impl $base {$(
#[inline]
pub unsafe fn $thing(&self) -> $fieldtype {
const SIZE: usize = $crate::_core::mem::size_of::<$fieldtype>() * 8;
self.$field << (SIZE - $r.end) >> (SIZE - $r.end + $r.start)
}
#[inline]
pub unsafe fn $set_thing(&mut self, val: $fieldtype) {
const MASK: $fieldtype = ((1 << ($r.end - $r.start)) - 1) << $r.start;
self.$field &= !MASK;
self.$field |= (val << $r.start) & MASK;
}
)+}
};
}
macro_rules! UNION {
($(#[$attrs:meta])* union $name:ident {
$($variant:ident: $ftype:ty,)+
}) => (
#[repr(C)] $(#[$attrs])*
pub union $name {
$(pub $variant: $ftype,)+
}
impl Copy for $name {}
impl Clone for $name {
#[inline]
fn clone(&self) -> $name { *self }
}
#[cfg(feature = "impl-default")]
impl Default for $name {
#[inline]
fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } }
}
);
}
macro_rules! FN {
(stdcall $func:ident($($p:ident: $t:ty,)*) -> $ret:ty) => (
pub type $func = Option<unsafe extern "system" fn($($p: $t,)*) -> $ret>;
);
(cdecl $func:ident($($p:ident: $t:ty,)*) -> $ret:ty) => (
pub type $func = Option<unsafe extern "C" fn($($p: $t,)*) -> $ret>;
);
}
macro_rules! IFDEF {
($($thing:item)*) => ($($thing)*)
}

View file

@ -1,40 +0,0 @@
use winapi::shared::ntdef::{HANDLE, LONG, NTSTATUS, ULONG, ULONGLONG, USHORT};
use winapi::shared::ntstatus::FACILITY_NTWIN32;
pub type KPRIORITY = LONG;
pub type RTL_ATOM = USHORT;
pub type PRTL_ATOM = *mut RTL_ATOM;
pub const NT_FACILITY_MASK: ULONG = 0xfff;
pub const NT_FACILITY_SHIFT: ULONG = 16;
#[inline]
pub const fn NT_FACILITY(Status: NTSTATUS) -> ULONG {
(Status as u32) >> NT_FACILITY_SHIFT & NT_FACILITY_MASK
}
#[inline]
pub const fn NT_NTWIN32(Status: NTSTATUS) -> bool {
NT_FACILITY(Status) == FACILITY_NTWIN32 as u32
}
#[inline]
pub const fn WIN32_FROM_NTSTATUS(Status: NTSTATUS) -> ULONG {
(Status as u32) & 0xffff
}
STRUCT!{struct CLIENT_ID {
UniqueProcess: HANDLE,
UniqueThread: HANDLE,
}}
pub type PCLIENT_ID = *mut CLIENT_ID;
STRUCT!{struct CLIENT_ID32 {
UniqueProcess: ULONG,
UniqueThread: ULONG,
}}
pub type PCLIENT_ID32 = *mut CLIENT_ID32;
STRUCT!{struct CLIENT_ID64 {
UniqueProcess: ULONGLONG,
UniqueThread: ULONGLONG,
}}
pub type PCLIENT_ID64 = *mut CLIENT_ID64;
STRUCT!{struct KSYSTEM_TIME {
LowPart: ULONG,
High1Time: LONG,
High2Time: LONG,
}}
pub type PKSYSTEM_TIME = *mut KSYSTEM_TIME;

View file

@ -1,239 +0,0 @@
use crate::ntapi_base::{CLIENT_ID, PCLIENT_ID};
use winapi::shared::evntprov::EVENT_FILTER_DESCRIPTOR;
use winapi::shared::guiddef::LPCGUID;
use winapi::shared::ntdef::{
BOOLEAN, HANDLE, NTSTATUS, PCCH, PCH, PCSTR, PHANDLE, PLARGE_INTEGER, POBJECT_ATTRIBUTES,
PULONG, PVOID, UCHAR, ULONG, ULONGLONG,
};
use winapi::um::minwinbase::LPDEBUG_EVENT;
use winapi::um::winnt::{ACCESS_MASK, EXCEPTION_RECORD, STANDARD_RIGHTS_REQUIRED, SYNCHRONIZE};
use winapi::vc::vadefs::va_list;
EXTERN!{extern "system" {
fn DbgUserBreakPoint();
fn DbgBreakPoint();
fn DbgBreakPointWithStatus(
Status: ULONG,
);
}}
pub const DBG_STATUS_CONTROL_C: u32 = 1;
pub const DBG_STATUS_SYSRQ: u32 = 2;
pub const DBG_STATUS_BUGCHECK_FIRST: u32 = 3;
pub const DBG_STATUS_BUGCHECK_SECOND: u32 = 4;
pub const DBG_STATUS_FATAL: u32 = 5;
pub const DBG_STATUS_DEBUG_CONTROL: u32 = 6;
pub const DBG_STATUS_WORKER: u32 = 7;
EXTERN!{extern "C" {
fn DbgPrint(
Format: PCSTR,
...
) -> ULONG;
fn DbgPrintEx(
ComponentId: ULONG,
Level: ULONG,
Format: PCSTR,
...
) -> ULONG;
}}
EXTERN!{extern "system" {
fn vDbgPrintEx(
ComponentId: ULONG,
Level: ULONG,
Format: PCCH,
arglist: va_list,
) -> ULONG;
fn vDbgPrintExWithPrefix(
Prefix: PCH,
ComponentId: ULONG,
Level: ULONG,
Format: PCCH,
arglist: va_list,
) -> ULONG;
fn DbgQueryDebugFilterState(
ComponentId: ULONG,
Level: ULONG,
) -> NTSTATUS;
fn DbgSetDebugFilterState(
ComponentId: ULONG,
Level: ULONG,
State: BOOLEAN,
) -> NTSTATUS;
fn DbgPrompt(
Prompt: PCCH,
Response: PCH,
Length: ULONG,
) -> ULONG;
}}
STRUCT!{struct DBGKM_EXCEPTION {
ExceptionRecord: EXCEPTION_RECORD,
FirstChance: ULONG,
}}
pub type PDBGKM_EXCEPTION = *mut DBGKM_EXCEPTION;
STRUCT!{struct DBGKM_CREATE_THREAD {
SubSystemKey: ULONG,
StartAddress: PVOID,
}}
pub type PDBGKM_CREATE_THREAD = *mut DBGKM_CREATE_THREAD;
STRUCT!{struct DBGKM_CREATE_PROCESS {
SubSystemKey: ULONG,
FileHandle: HANDLE,
BaseOfImage: PVOID,
DebugInfoFileOffset: ULONG,
DebugInfoSize: ULONG,
InitialThread: DBGKM_CREATE_THREAD,
}}
pub type PDBGKM_CREATE_PROCESS = *mut DBGKM_CREATE_PROCESS;
STRUCT!{struct DBGKM_EXIT_THREAD {
ExitStatus: NTSTATUS,
}}
pub type PDBGKM_EXIT_THREAD = *mut DBGKM_EXIT_THREAD;
STRUCT!{struct DBGKM_EXIT_PROCESS {
ExitStatus: NTSTATUS,
}}
pub type PDBGKM_EXIT_PROCESS = *mut DBGKM_EXIT_PROCESS;
STRUCT!{struct DBGKM_LOAD_DLL {
FileHandle: HANDLE,
BaseOfDll: PVOID,
DebugInfoFileOffset: ULONG,
DebugInfoSize: ULONG,
NamePointer: PVOID,
}}
pub type PDBGKM_LOAD_DLL = *mut DBGKM_LOAD_DLL;
STRUCT!{struct DBGKM_UNLOAD_DLL {
BaseAddress: PVOID,
}}
pub type PDBGKM_UNLOAD_DLL = *mut DBGKM_UNLOAD_DLL;
ENUM!{enum DBG_STATE {
DbgIdle = 0,
DbgReplyPending = 1,
DbgCreateThreadStateChange = 2,
DbgCreateProcessStateChange = 3,
DbgExitThreadStateChange = 4,
DbgExitProcessStateChange = 5,
DbgExceptionStateChange = 6,
DbgBreakpointStateChange = 7,
DbgSingleStepStateChange = 8,
DbgLoadDllStateChange = 9,
DbgUnloadDllStateChange = 10,
}}
pub type PDBG_STATE = *mut DBG_STATE;
STRUCT!{struct DBGUI_CREATE_THREAD {
HandleToThread: HANDLE,
NewThread: DBGKM_CREATE_THREAD,
}}
pub type PDBGUI_CREATE_THREAD = *mut DBGUI_CREATE_THREAD;
STRUCT!{struct DBGUI_CREATE_PROCESS {
HandleToProcess: HANDLE,
HandleToThread: HANDLE,
NewProcess: DBGKM_CREATE_PROCESS,
}}
UNION!{union DBGUI_WAIT_STATE_CHANGE_StateInfo {
Exception: DBGKM_EXCEPTION,
CreateThread: DBGUI_CREATE_THREAD,
CreateProcessInfo: DBGUI_CREATE_PROCESS,
ExitThread: DBGKM_EXIT_THREAD,
ExitProcess: DBGKM_EXIT_PROCESS,
LoadDll: DBGKM_LOAD_DLL,
UnloadDll: DBGKM_UNLOAD_DLL,
}}
pub type PDBGUI_CREATE_PROCESS = *mut DBGUI_CREATE_PROCESS;
STRUCT!{struct DBGUI_WAIT_STATE_CHANGE {
NewState: DBG_STATE,
AppClientId: CLIENT_ID,
StateInfo: DBGUI_WAIT_STATE_CHANGE_StateInfo,
}}
pub type PDBGUI_WAIT_STATE_CHANGE = *mut DBGUI_WAIT_STATE_CHANGE;
pub const DEBUG_READ_EVENT: ULONG = 0x0001;
pub const DEBUG_PROCESS_ASSIGN: ULONG = 0x0002;
pub const DEBUG_SET_INFORMATION: ULONG = 0x0004;
pub const DEBUG_QUERY_INFORMATION: ULONG = 0x0008;
pub const DEBUG_ALL_ACCESS: ACCESS_MASK = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | DEBUG_READ_EVENT
| DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | DEBUG_QUERY_INFORMATION;
pub const DEBUG_KILL_ON_CLOSE: u32 = 0x1;
ENUM!{enum DEBUGOBJECTINFOCLASS {
DebugObjectUnusedInformation = 0,
DebugObjectKillProcessOnExitInformation = 1,
MaxDebugObjectInfoClass = 2,
}}
pub type PDEBUGOBJECTINFOCLASS = *mut DEBUGOBJECTINFOCLASS;
EXTERN!{extern "system" {
fn NtCreateDebugObject(
DebugObjectHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
Flags: ULONG,
) -> NTSTATUS;
fn NtDebugActiveProcess(
ProcessHandle: HANDLE,
DebugObjectHandle: HANDLE,
) -> NTSTATUS;
fn NtDebugContinue(
DebugObjectHandle: HANDLE,
ClientId: PCLIENT_ID,
ContinueStatus: NTSTATUS,
) -> NTSTATUS;
fn NtRemoveProcessDebug(
ProcessHandle: HANDLE,
DebugObjectHandle: HANDLE,
) -> NTSTATUS;
fn NtSetInformationDebugObject(
DebugObjectHandle: HANDLE,
DebugObjectInformationClass: DEBUGOBJECTINFOCLASS,
DebugInformation: PVOID,
DebugInformationLength: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtWaitForDebugEvent(
DebugObjectHandle: HANDLE,
Alertable: BOOLEAN,
Timeout: PLARGE_INTEGER,
WaitStateChange: PVOID,
) -> NTSTATUS;
fn DbgUiConnectToDbg() -> NTSTATUS;
fn DbgUiGetThreadDebugObject() -> HANDLE;
fn DbgUiSetThreadDebugObject(
DebugObject: HANDLE,
);
fn DbgUiWaitStateChange(
StateChange: PDBGUI_WAIT_STATE_CHANGE,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn DbgUiContinue(
AppClientId: PCLIENT_ID,
ContinueStatus: NTSTATUS,
) -> NTSTATUS;
fn DbgUiStopDebugging(
Process: HANDLE,
) -> NTSTATUS;
fn DbgUiDebugActiveProcess(
Process: HANDLE,
) -> NTSTATUS;
fn DbgUiRemoteBreakin(
Context: PVOID,
);
fn DbgUiIssueRemoteBreakin(
Process: HANDLE,
) -> NTSTATUS;
fn DbgUiConvertStateChangeStructure(
StateChange: PDBGUI_WAIT_STATE_CHANGE,
DebugEvent: LPDEBUG_EVENT,
) -> NTSTATUS;
}}
FN!{stdcall PENABLECALLBACK(
SourceId: LPCGUID,
IsEnabled: ULONG,
Level: UCHAR,
MatchAnyKeyword: ULONGLONG,
MatchAllKeyword: ULONGLONG,
FilterData: *mut EVENT_FILTER_DESCRIPTOR,
CallbackContext: PVOID,
) -> ()}
pub type REGHANDLE = ULONGLONG;
pub type PREGHANDLE = *mut ULONGLONG;
EXTERN!{extern "system" {
fn EtwEventRegister(
ProviderId: LPCGUID,
EnableCallback: PENABLECALLBACK,
CallbackContext: PVOID,
RegHandle: PREGHANDLE,
) -> NTSTATUS;
}}

File diff suppressed because it is too large Load diff

View file

@ -1,123 +0,0 @@
use winapi::shared::ntdef::{PVOID, UCHAR, ULONG, USHORT};
pub const GDI_MAX_HANDLE_COUNT: usize = 0x4000;
pub const GDI_HANDLE_INDEX_SHIFT: ULONG = 0;
pub const GDI_HANDLE_INDEX_BITS: ULONG = 16;
pub const GDI_HANDLE_INDEX_MASK: ULONG = 0xffff;
pub const GDI_HANDLE_TYPE_SHIFT: ULONG = 16;
pub const GDI_HANDLE_TYPE_BITS: ULONG = 5;
pub const GDI_HANDLE_TYPE_MASK: ULONG = 0x1f;
pub const GDI_HANDLE_ALTTYPE_SHIFT: ULONG = 21;
pub const GDI_HANDLE_ALTTYPE_BITS: ULONG = 2;
pub const GDI_HANDLE_ALTTYPE_MASK: ULONG = 0x3;
pub const GDI_HANDLE_STOCK_SHIFT: ULONG = 23;
pub const GDI_HANDLE_STOCK_BITS: ULONG = 1;
pub const GDI_HANDLE_STOCK_MASK: ULONG = 0x1;
pub const GDI_HANDLE_UNIQUE_SHIFT: ULONG = 24;
pub const GDI_HANDLE_UNIQUE_BITS: ULONG = 8;
pub const GDI_HANDLE_UNIQUE_MASK: ULONG = 0xff;
#[inline]
pub const fn GDI_HANDLE_INDEX(Handle: ULONG) -> ULONG {
Handle & GDI_HANDLE_INDEX_MASK
}
#[inline]
pub const fn GDI_HANDLE_TYPE(Handle: ULONG) -> ULONG {
Handle >> GDI_HANDLE_TYPE_SHIFT & GDI_HANDLE_TYPE_MASK
}
#[inline]
pub const fn GDI_HANDLE_ALTTYPE(Handle: ULONG) -> ULONG {
Handle >> GDI_HANDLE_ALTTYPE_SHIFT & GDI_HANDLE_ALTTYPE_MASK
}
#[inline]
pub const fn GDI_HANDLE_STOCK(Handle: ULONG) -> ULONG {
Handle >> GDI_HANDLE_STOCK_SHIFT & GDI_HANDLE_STOCK_MASK
}
#[inline]
pub const fn GDI_MAKE_HANDLE(Index: ULONG, Unique: ULONG) -> ULONG {
Unique << GDI_HANDLE_INDEX_BITS | Index
}
pub const GDI_DEF_TYPE: ULONG = 0;
pub const GDI_DC_TYPE: ULONG = 1;
pub const GDI_DD_DIRECTDRAW_TYPE: ULONG = 2;
pub const GDI_DD_SURFACE_TYPE: ULONG = 3;
pub const GDI_RGN_TYPE: ULONG = 4;
pub const GDI_SURF_TYPE: ULONG = 5;
pub const GDI_CLIENTOBJ_TYPE: ULONG = 6;
pub const GDI_PATH_TYPE: ULONG = 7;
pub const GDI_PAL_TYPE: ULONG = 8;
pub const GDI_ICMLCS_TYPE: ULONG = 9;
pub const GDI_LFONT_TYPE: ULONG = 10;
pub const GDI_RFONT_TYPE: ULONG = 11;
pub const GDI_PFE_TYPE: ULONG = 12;
pub const GDI_PFT_TYPE: ULONG = 13;
pub const GDI_ICMCXF_TYPE: ULONG = 14;
pub const GDI_ICMDLL_TYPE: ULONG = 15;
pub const GDI_BRUSH_TYPE: ULONG = 16;
pub const GDI_PFF_TYPE: ULONG = 17;
pub const GDI_CACHE_TYPE: ULONG = 18;
pub const GDI_SPACE_TYPE: ULONG = 19;
pub const GDI_DBRUSH_TYPE: ULONG = 20;
pub const GDI_META_TYPE: ULONG = 21;
pub const GDI_EFSTATE_TYPE: ULONG = 22;
pub const GDI_BMFD_TYPE: ULONG = 23;
pub const GDI_VTFD_TYPE: ULONG = 24;
pub const GDI_TTFD_TYPE: ULONG = 25;
pub const GDI_RC_TYPE: ULONG = 26;
pub const GDI_TEMP_TYPE: ULONG = 27;
pub const GDI_DRVOBJ_TYPE: ULONG = 28;
pub const GDI_DCIOBJ_TYPE: ULONG = 29;
pub const GDI_SPOOL_TYPE: ULONG = 30;
#[inline]
pub const fn GDI_CLIENT_TYPE_FROM_HANDLE(Handle: ULONG) -> ULONG {
Handle & (GDI_HANDLE_ALTTYPE_MASK << GDI_HANDLE_ALTTYPE_SHIFT | GDI_HANDLE_TYPE_MASK
<< GDI_HANDLE_TYPE_SHIFT)
}
#[inline]
pub const fn GDI_CLIENT_TYPE_FROM_UNIQUE(Unique: ULONG) -> ULONG {
GDI_CLIENT_TYPE_FROM_HANDLE(Unique << 16)
}
pub const GDI_ALTTYPE_1: ULONG = 1 << GDI_HANDLE_ALTTYPE_SHIFT;
pub const GDI_ALTTYPE_2: ULONG = 2 << GDI_HANDLE_ALTTYPE_SHIFT;
pub const GDI_ALTTYPE_3: ULONG = 3 << GDI_HANDLE_ALTTYPE_SHIFT;
pub const GDI_CLIENT_BITMAP_TYPE: ULONG = GDI_SURF_TYPE << GDI_HANDLE_TYPE_SHIFT;
pub const GDI_CLIENT_BRUSH_TYPE: ULONG = GDI_BRUSH_TYPE << GDI_HANDLE_TYPE_SHIFT;
pub const GDI_CLIENT_CLIENTOBJ_TYPE: ULONG = GDI_CLIENTOBJ_TYPE << GDI_HANDLE_TYPE_SHIFT;
pub const GDI_CLIENT_DC_TYPE: ULONG = GDI_DC_TYPE << GDI_HANDLE_TYPE_SHIFT;
pub const GDI_CLIENT_FONT_TYPE: ULONG = GDI_LFONT_TYPE << GDI_HANDLE_TYPE_SHIFT;
pub const GDI_CLIENT_PALETTE_TYPE: ULONG = GDI_PAL_TYPE << GDI_HANDLE_TYPE_SHIFT;
pub const GDI_CLIENT_REGION_TYPE: ULONG = GDI_RGN_TYPE << GDI_HANDLE_TYPE_SHIFT;
pub const GDI_CLIENT_ALTDC_TYPE: ULONG = GDI_CLIENT_DC_TYPE | GDI_ALTTYPE_1;
pub const GDI_CLIENT_DIBSECTION_TYPE: ULONG = GDI_CLIENT_BITMAP_TYPE | GDI_ALTTYPE_1;
pub const GDI_CLIENT_EXTPEN_TYPE: ULONG = GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_2;
pub const GDI_CLIENT_METADC16_TYPE: ULONG = GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_3;
pub const GDI_CLIENT_METAFILE_TYPE: ULONG = GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_2;
pub const GDI_CLIENT_METAFILE16_TYPE: ULONG = GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_1;
pub const GDI_CLIENT_PEN_TYPE: ULONG = GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_1;
UNION!{union GDI_HANDLE_ENTRY_u {
Object: PVOID,
NextFree: PVOID,
}}
STRUCT!{struct GDI_HANDLE_ENTRY_Owner_s {
ProcessId: USHORT,
Bitfields: USHORT,
}}
BITFIELD!{GDI_HANDLE_ENTRY_Owner_s Bitfields: USHORT [
Lock set_Lock[0..1],
Count set_Count[1..16],
]}
UNION!{union GDI_HANDLE_ENTRY_Owner {
s: GDI_HANDLE_ENTRY_Owner_s,
Value: ULONG,
}}
STRUCT!{struct GDI_HANDLE_ENTRY {
u: GDI_HANDLE_ENTRY_u,
Owner: GDI_HANDLE_ENTRY_Owner,
Unique: USHORT,
Type: UCHAR,
Flags: UCHAR,
UserPointer: PVOID,
}}
pub type PGDI_HANDLE_ENTRY = *mut GDI_HANDLE_ENTRY;
STRUCT!{struct GDI_SHARED_MEMORY {
Handles: [GDI_HANDLE_ENTRY; GDI_MAX_HANDLE_COUNT],
}}
pub type PGDI_SHARED_MEMORY = *mut GDI_SHARED_MEMORY;

File diff suppressed because it is too large Load diff

View file

@ -1,121 +0,0 @@
use winapi::shared::ntdef::{BOOLEAN, NTSTATUS, PVOID, ULONG};
pub const LOW_PRIORITY: u32 = 0;
pub const LOW_REALTIME_PRIORITY: u32 = 16;
pub const HIGH_PRIORITY: u32 = 31;
pub const MAXIMUM_PRIORITY: u32 = 32;
ENUM!{enum KTHREAD_STATE {
Initialized = 0,
Ready = 1,
Running = 2,
Standby = 3,
Terminated = 4,
Waiting = 5,
Transition = 6,
DeferredReady = 7,
GateWaitObsolete = 8,
WaitingForProcessInSwap = 9,
MaximumThreadState = 10,
}}
pub type PKTHREAD_STATE = *mut KTHREAD_STATE;
ENUM!{enum KHETERO_CPU_POLICY {
KHeteroCpuPolicyAll = 0,
KHeteroCpuPolicyLarge = 1,
KHeteroCpuPolicyLargeOrIdle = 2,
KHeteroCpuPolicySmall = 3,
KHeteroCpuPolicySmallOrIdle = 4,
KHeteroCpuPolicyDynamic = 5,
KHeteroCpuPolicyStaticMax = 6,
KHeteroCpuPolicyBiasedSmall = 7,
KHeteroCpuPolicyBiasedLarge = 8,
KHeteroCpuPolicyDefault = 9,
KHeteroCpuPolicyMax = 10,
}}
pub type PKHETERO_CPU_POLICY = *mut KHETERO_CPU_POLICY;
ENUM!{enum KWAIT_REASON {
Executive = 0,
FreePage = 1,
PageIn = 2,
PoolAllocation = 3,
DelayExecution = 4,
Suspended = 5,
UserRequest = 6,
WrExecutive = 7,
WrFreePage = 8,
WrPageIn = 9,
WrPoolAllocation = 10,
WrDelayExecution = 11,
WrSuspended = 12,
WrUserRequest = 13,
WrEventPair = 14,
WrQueue = 15,
WrLpcReceive = 16,
WrLpcReply = 17,
WrVirtualMemory = 18,
WrPageOut = 19,
WrRendezvous = 20,
WrKeyedEvent = 21,
WrTerminated = 22,
WrProcessInSwap = 23,
WrCpuRateControl = 24,
WrCalloutStack = 25,
WrKernel = 26,
WrResource = 27,
WrPushLock = 28,
WrMutex = 29,
WrQuantumEnd = 30,
WrDispatchInt = 31,
WrPreempted = 32,
WrYieldExecution = 33,
WrFastMutex = 34,
WrGuardedMutex = 35,
WrRundown = 36,
WrAlertByThreadId = 37,
WrDeferredPreempt = 38,
MaximumWaitReason = 39,
}}
pub type PKWAIT_REASON = *mut KWAIT_REASON;
ENUM!{enum KPROFILE_SOURCE {
ProfileTime = 0,
ProfileAlignmentFixup = 1,
ProfileTotalIssues = 2,
ProfilePipelineDry = 3,
ProfileLoadInstructions = 4,
ProfilePipelineFrozen = 5,
ProfileBranchInstructions = 6,
ProfileTotalNonissues = 7,
ProfileDcacheMisses = 8,
ProfileIcacheMisses = 9,
ProfileCacheMisses = 10,
ProfileBranchMispredictions = 11,
ProfileStoreInstructions = 12,
ProfileFpInstructions = 13,
ProfileIntegerInstructions = 14,
Profile2Issue = 15,
Profile3Issue = 16,
Profile4Issue = 17,
ProfileSpecialInstructions = 18,
ProfileTotalCycles = 19,
ProfileIcacheIssues = 20,
ProfileDcacheAccesses = 21,
ProfileMemoryBarrierCycles = 22,
ProfileLoadLinkedIssues = 23,
ProfileMaximum = 24,
}}
EXTERN!{extern "system" {
fn NtCallbackReturn(
OutputBuffer: PVOID,
OutputLength: ULONG,
Status: NTSTATUS,
) -> NTSTATUS;
fn NtFlushProcessWriteBuffers();
fn NtQueryDebugFilterState(
ComponentId: ULONG,
Level: ULONG,
) -> NTSTATUS;
fn NtSetDebugFilterState(
ComponentId: ULONG,
Level: ULONG,
State: BOOLEAN,
) -> NTSTATUS;
fn NtYieldExecution() -> NTSTATUS;
}}

View file

@ -1,661 +0,0 @@
use winapi::shared::basetsd::{LONG_PTR, PSIZE_T, SIZE_T, ULONG_PTR};
use winapi::shared::ntdef::{
BOOLEAN, HANDLE, LARGE_INTEGER, LIST_ENTRY, LONG, LONGLONG, NTSTATUS, PANSI_STRING, PCSTR,
PCUNICODE_STRING, PCWSTR, PHANDLE, POBJECT_ATTRIBUTES, PSINGLE_LIST_ENTRY, PSTR, PULONG,
PUNICODE_STRING, PUSHORT, PVOID, PWSTR, RTL_BALANCED_NODE, SINGLE_LIST_ENTRY, UCHAR, ULONG,
UNICODE_STRING, USHORT,
};
use winapi::um::winnt::{
ACCESS_MASK, ACTIVATION_CONTEXT, IMAGE_RESOURCE_DIRECTORY_ENTRY, PCIMAGE_DELAYLOAD_DESCRIPTOR,
PIMAGE_BASE_RELOCATION, PIMAGE_IMPORT_DESCRIPTOR, PIMAGE_RESOURCE_DATA_ENTRY,
PIMAGE_RESOURCE_DIRECTORY, PIMAGE_RESOURCE_DIRECTORY_STRING, PIMAGE_THUNK_DATA,
};
FN!{stdcall PLDR_INIT_ROUTINE(
DllHandle: PVOID,
Reason: ULONG,
Context: PVOID,
) -> BOOLEAN}
STRUCT!{struct LDR_SERVICE_TAG_RECORD {
Next: *mut LDR_SERVICE_TAG_RECORD,
ServiceTag: ULONG,
}}
pub type PLDR_SERVICE_TAG_RECORD = *mut LDR_SERVICE_TAG_RECORD;
STRUCT!{struct LDRP_CSLIST {
Tail: PSINGLE_LIST_ENTRY,
}}
pub type PLDRP_CSLIST = *mut LDRP_CSLIST;
ENUM!{enum LDR_DDAG_STATE {
LdrModulesMerged = -5i32 as u32,
LdrModulesInitError = -4i32 as u32,
LdrModulesSnapError = -3i32 as u32,
LdrModulesUnloaded = -2i32 as u32,
LdrModulesUnloading = -1i32 as u32,
LdrModulesPlaceHolder = 0,
LdrModulesMapping = 1,
LdrModulesMapped = 2,
LdrModulesWaitingForDependencies = 3,
LdrModulesSnapping = 4,
LdrModulesSnapped = 5,
LdrModulesCondensed = 6,
LdrModulesReadyToInit = 7,
LdrModulesInitializing = 8,
LdrModulesReadyToRun = 9,
}}
UNION!{union LDR_DDAG_NODE_u {
Dependencies: LDRP_CSLIST,
RemovalLink: SINGLE_LIST_ENTRY,
}}
STRUCT!{struct LDR_DDAG_NODE {
Modules: LIST_ENTRY,
ServiceTagList: PLDR_SERVICE_TAG_RECORD,
LoadCount: ULONG,
LoadWhileUnloadingCount: ULONG,
LowestLink: ULONG,
u: LDR_DDAG_NODE_u,
IncomingDependencies: LDRP_CSLIST,
State: LDR_DDAG_STATE,
CondenseLink: SINGLE_LIST_ENTRY,
PreorderNumber: ULONG,
}}
pub type PLDR_DDAG_NODE = *mut LDR_DDAG_NODE;
STRUCT!{struct LDR_DEPENDENCY_RECORD {
DependencyLink: SINGLE_LIST_ENTRY,
DependencyNode: PLDR_DDAG_NODE,
IncomingDependencyLink: SINGLE_LIST_ENTRY,
IncomingDependencyNode: PLDR_DDAG_NODE,
}}
pub type PLDR_DEPENDENCY_RECORD = *mut LDR_DEPENDENCY_RECORD;
ENUM!{enum LDR_DLL_LOAD_REASON {
LoadReasonStaticDependency = 0,
LoadReasonStaticForwarderDependency = 1,
LoadReasonDynamicForwarderDependency = 2,
LoadReasonDelayloadDependency = 3,
LoadReasonDynamicLoad = 4,
LoadReasonAsImageLoad = 5,
LoadReasonAsDataLoad = 6,
LoadReasonEnclavePrimary = 7,
LoadReasonEnclaveDependency = 8,
LoadReasonUnknown = -1i32 as u32,
}}
pub type PLDR_DLL_LOAD_REASON = *mut LDR_DLL_LOAD_REASON;
pub const LDRP_PACKAGED_BINARY: ULONG = 0x00000001;
pub const LDRP_STATIC_LINK: ULONG = 0x00000002;
pub const LDRP_IMAGE_DLL: ULONG = 0x00000004;
pub const LDRP_LOAD_IN_PROGRESS: ULONG = 0x00001000;
pub const LDRP_UNLOAD_IN_PROGRESS: ULONG = 0x00002000;
pub const LDRP_ENTRY_PROCESSED: ULONG = 0x00004000;
pub const LDRP_ENTRY_INSERTED: ULONG = 0x00008000;
pub const LDRP_CURRENT_LOAD: ULONG = 0x00010000;
pub const LDRP_FAILED_BUILTIN_LOAD: ULONG = 0x00020000;
pub const LDRP_DONT_CALL_FOR_THREADS: ULONG = 0x00040000;
pub const LDRP_PROCESS_ATTACH_CALLED: ULONG = 0x00080000;
pub const LDRP_DEBUG_SYMBOLS_LOADED: ULONG = 0x00100000;
pub const LDRP_IMAGE_NOT_AT_BASE: ULONG = 0x00200000;
pub const LDRP_COR_IMAGE: ULONG = 0x00400000;
pub const LDRP_DONT_RELOCATE: ULONG = 0x00800000;
pub const LDRP_SYSTEM_MAPPED: ULONG = 0x01000000;
pub const LDRP_IMAGE_VERIFYING: ULONG = 0x02000000;
pub const LDRP_DRIVER_DEPENDENT_DLL: ULONG = 0x04000000;
pub const LDRP_ENTRY_NATIVE: ULONG = 0x08000000;
pub const LDRP_REDIRECTED: ULONG = 0x10000000;
pub const LDRP_NON_PAGED_DEBUG_INFO: ULONG = 0x20000000;
pub const LDRP_MM_LOADED: ULONG = 0x40000000;
pub const LDRP_COMPAT_DATABASE_PROCESSED: ULONG = 0x80000000;
STRUCT!{struct LDRP_LOAD_CONTEXT {
BaseDllName: UNICODE_STRING,
somestruct: PVOID,
Flags: ULONG,
pstatus: *mut NTSTATUS,
ParentEntry: *mut LDR_DATA_TABLE_ENTRY,
Entry: *mut LDR_DATA_TABLE_ENTRY,
WorkQueueListEntry: LIST_ENTRY,
ReplacedEntry: *mut LDR_DATA_TABLE_ENTRY,
pvImports: *mut *mut LDR_DATA_TABLE_ENTRY,
ImportDllCount: ULONG,
TaskCount: LONG,
pvIAT: PVOID,
SizeOfIAT: ULONG,
CurrentDll: ULONG,
piid: PIMAGE_IMPORT_DESCRIPTOR,
OriginalIATProtect: ULONG,
GuardCFCheckFunctionPointer: PVOID,
pGuardCFCheckFunctionPointer: *mut PVOID,
}}
UNION!{union LDR_DATA_TABLE_ENTRY_u1 {
InInitializationOrderLinks: LIST_ENTRY,
InProgressLinks: LIST_ENTRY,
}}
UNION!{union LDR_DATA_TABLE_ENTRY_u2 {
FlagGroup: [UCHAR; 4],
Flags: ULONG,
}}
STRUCT!{struct LDR_DATA_TABLE_ENTRY {
InLoadOrderLinks: LIST_ENTRY,
InMemoryOrderLinks: LIST_ENTRY,
u1: LDR_DATA_TABLE_ENTRY_u1,
DllBase: PVOID,
EntryPoint: PLDR_INIT_ROUTINE,
SizeOfImage: ULONG,
FullDllName: UNICODE_STRING,
BaseDllName: UNICODE_STRING,
u2: LDR_DATA_TABLE_ENTRY_u2,
ObsoleteLoadCount: USHORT,
TlsIndex: USHORT,
HashLinks: LIST_ENTRY,
TimeDateStamp: ULONG,
EntryPointActivationContext: *mut ACTIVATION_CONTEXT,
Lock: PVOID,
DdagNode: PLDR_DDAG_NODE,
NodeModuleLink: LIST_ENTRY,
LoadContext: *mut LDRP_LOAD_CONTEXT,
ParentDllBase: PVOID,
SwitchBackContext: PVOID,
BaseAddressIndexNode: RTL_BALANCED_NODE,
MappingInfoIndexNode: RTL_BALANCED_NODE,
OriginalBase: ULONG_PTR,
LoadTime: LARGE_INTEGER,
BaseNameHashValue: ULONG,
LoadReason: LDR_DLL_LOAD_REASON,
ImplicitPathOptions: ULONG,
ReferenceCount: ULONG,
DependentLoadFlags: ULONG,
SigningLevel: UCHAR,
}}
BITFIELD!{unsafe LDR_DATA_TABLE_ENTRY_u2 Flags: ULONG [
PackagedBinary set_PackagedBinary[0..1],
MarkedForRemoval set_MarkedForRemoval[1..2],
ImageDll set_ImageDll[2..3],
LoadNotificationsSent set_LoadNotificationsSent[3..4],
TelemetryEntryProcessed set_TelemetryEntryProcessed[4..5],
ProcessStaticImport set_ProcessStaticImport[5..6],
InLegacyLists set_InLegacyLists[6..7],
InIndexes set_InIndexes[7..8],
ShimDll set_ShimDll[8..9],
InExceptionTable set_InExceptionTable[9..10],
ReservedFlags1 set_ReservedFlags1[10..12],
LoadInProgress set_LoadInProgress[12..13],
LoadConfigProcessed set_LoadConfigProcessed[13..14],
EntryProcessed set_EntryProcessed[14..15],
ProtectDelayLoad set_ProtectDelayLoad[15..16],
ReservedFlags3 set_ReservedFlags3[16..18],
DontCallForThreads set_DontCallForThreads[18..19],
ProcessAttachCalled set_ProcessAttachCalled[19..20],
ProcessAttachFailed set_ProcessAttachFailed[20..21],
CorDeferredValidate set_CorDeferredValidate[21..22],
CorImage set_CorImage[22..23],
DontRelocate set_DontRelocate[23..24],
CorILOnly set_CorILOnly[24..25],
ReservedFlags5 set_ReservedFlags5[25..28],
Redirected set_Redirected[28..29],
ReservedFlags6 set_ReservedFlags6[29..31],
CompatDatabaseProcessed set_CompatDatabaseProcessed[31..32],
]}
pub type PLDR_DATA_TABLE_ENTRY = *mut LDR_DATA_TABLE_ENTRY;
#[inline]
pub const fn LDR_IS_DATAFILE(DllHandle: ULONG_PTR) -> bool {
DllHandle & 1 != 0
}
#[inline]
pub const fn LDR_IS_IMAGEMAPPING(DllHandle: ULONG_PTR) -> bool {
DllHandle & 2 != 0
}
#[inline]
pub const fn LDR_IS_RESOURCE(DllHandle: ULONG_PTR) -> bool {
LDR_IS_IMAGEMAPPING(DllHandle) || LDR_IS_DATAFILE(DllHandle)
}
EXTERN!{extern "system" {
fn LdrLoadDll(
DllPath: PWSTR,
DllCharacteristics: PULONG,
DllName: PUNICODE_STRING,
DllHandle: *mut PVOID,
) -> NTSTATUS;
fn LdrUnloadDll(
DllHandle: PVOID,
) -> NTSTATUS;
fn LdrGetDllHandle(
DllPath: PWSTR,
DllCharacteristics: PULONG,
DllName: PUNICODE_STRING,
DllHandle: *mut PVOID,
) -> NTSTATUS;
}}
pub const LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT: ULONG = 0x00000001;
pub const LDR_GET_DLL_HANDLE_EX_PIN: ULONG = 0x00000002;
EXTERN!{extern "system" {
fn LdrGetDllHandleEx(
Flags: ULONG,
DllPath: PWSTR,
DllCharacteristics: PULONG,
DllName: PUNICODE_STRING,
DllHandle: *mut PVOID,
) -> NTSTATUS;
fn LdrGetDllHandleByMapping(
BaseAddress: PVOID,
DllHandle: *mut PVOID,
) -> NTSTATUS;
fn LdrGetDllHandleByName(
BaseDllName: PUNICODE_STRING,
FullDllName: PUNICODE_STRING,
DllHandle: *mut PVOID,
) -> NTSTATUS;
fn LdrGetDllFullName(
DllHandle: PVOID,
FullDllName: PUNICODE_STRING,
) -> NTSTATUS;
fn LdrGetDllDirectory(
DllDirectory: PUNICODE_STRING,
) -> NTSTATUS;
fn LdrSetDllDirectory(
DllDirectory: PUNICODE_STRING,
) -> NTSTATUS;
}}
pub const LDR_ADDREF_DLL_PIN: ULONG = 0x00000001;
EXTERN!{extern "system" {
fn LdrAddRefDll(
Flags: ULONG,
DllHandle: PVOID,
) -> NTSTATUS;
fn LdrGetProcedureAddress(
DllHandle: PVOID,
ProcedureName: PANSI_STRING,
ProcedureNumber: ULONG,
ProcedureAddress: *mut PVOID,
) -> NTSTATUS;
}}
pub const LDR_GET_PROCEDURE_ADDRESS_DONT_RECORD_FORWARDER: ULONG = 0x00000001;
EXTERN!{extern "system" {
fn LdrGetProcedureAddressEx(
DllHandle: PVOID,
ProcedureName: PANSI_STRING,
ProcedureNumber: ULONG,
ProcedureAddress: *mut PVOID,
Flags: ULONG,
) -> NTSTATUS;
fn LdrGetKnownDllSectionHandle(
DllName: PCWSTR,
KnownDlls32: BOOLEAN,
Section: PHANDLE,
) -> NTSTATUS;
fn LdrGetProcedureAddressForCaller(
DllHandle: PVOID,
ProcedureName: PANSI_STRING,
ProcedureNumber: ULONG,
ProcedureAddress: *mut PVOID,
Flags: ULONG,
Callback: *mut PVOID,
) -> NTSTATUS;
}}
pub const LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS: ULONG = 0x00000001;
pub const LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY: ULONG = 0x00000002;
pub const LDR_LOCK_LOADER_LOCK_DISPOSITION_INVALID: ULONG = 0;
pub const LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED: ULONG = 1;
pub const LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED: ULONG = 2;
EXTERN!{extern "system" {
fn LdrLockLoaderLock(
Flags: ULONG,
Disposition: *mut ULONG,
Cookie: *mut PVOID,
) -> NTSTATUS;
}}
pub const LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS: ULONG = 0x00000001;
EXTERN!{extern "system" {
fn LdrUnlockLoaderLock(
Flags: ULONG,
Cookie: PVOID,
) -> NTSTATUS;
fn LdrRelocateImage(
NewBase: PVOID,
LoaderName: PSTR,
Success: NTSTATUS,
Conflict: NTSTATUS,
Invalid: NTSTATUS,
) -> NTSTATUS;
fn LdrRelocateImageWithBias(
NewBase: PVOID,
Bias: LONGLONG,
LoaderName: PSTR,
Success: NTSTATUS,
Conflict: NTSTATUS,
Invalid: NTSTATUS,
) -> NTSTATUS;
fn LdrProcessRelocationBlock(
VA: ULONG_PTR,
SizeOfBlock: ULONG,
NextOffset: PUSHORT,
Diff: LONG_PTR,
) -> PIMAGE_BASE_RELOCATION;
fn LdrVerifyMappedImageMatchesChecksum(
BaseAddress: PVOID,
NumberOfBytes: SIZE_T,
FileLength: ULONG,
) -> BOOLEAN;
}}
FN!{stdcall PLDR_IMPORT_MODULE_CALLBACK(
Parameter: PVOID,
ModuleName: PSTR,
) -> ()}
EXTERN!{extern "system" {
fn LdrVerifyImageMatchesChecksum(
ImageFileHandle: HANDLE,
ImportCallbackRoutine: PLDR_IMPORT_MODULE_CALLBACK,
ImportCallbackParameter: PVOID,
ImageCharacteristics: PUSHORT,
) -> NTSTATUS;
}}
STRUCT!{struct LDR_IMPORT_CALLBACK_INFO {
ImportCallbackRoutine: PLDR_IMPORT_MODULE_CALLBACK,
ImportCallbackParameter: PVOID,
}}
pub type PLDR_IMPORT_CALLBACK_INFO = *mut LDR_IMPORT_CALLBACK_INFO;
STRUCT!{struct LDR_SECTION_INFO {
SectionHandle: HANDLE,
DesiredAccess: ACCESS_MASK,
ObjA: POBJECT_ATTRIBUTES,
SectionPageProtection: ULONG,
AllocationAttributes: ULONG,
}}
pub type PLDR_SECTION_INFO = *mut LDR_SECTION_INFO;
STRUCT!{struct LDR_VERIFY_IMAGE_INFO {
Size: ULONG,
Flags: ULONG,
CallbackInfo: LDR_IMPORT_CALLBACK_INFO,
SectionInfo: LDR_SECTION_INFO,
ImageCharacteristics: USHORT,
}}
pub type PLDR_VERIFY_IMAGE_INFO = *mut LDR_VERIFY_IMAGE_INFO;
EXTERN!{extern "system" {
fn LdrVerifyImageMatchesChecksumEx(
ImageFileHandle: HANDLE,
VerifyInfo: PLDR_VERIFY_IMAGE_INFO,
) -> NTSTATUS;
fn LdrQueryModuleServiceTags(
DllHandle: PVOID,
ServiceTagBuffer: PULONG,
BufferSize: PULONG,
) -> NTSTATUS;
}}
pub const LDR_DLL_NOTIFICATION_REASON_LOADED: ULONG = 1;
pub const LDR_DLL_NOTIFICATION_REASON_UNLOADED: ULONG = 2;
STRUCT!{struct LDR_DLL_LOADED_NOTIFICATION_DATA {
Flags: ULONG,
FullDllName: PUNICODE_STRING,
BaseDllName: PUNICODE_STRING,
DllBase: PVOID,
SizeOfImage: ULONG,
}}
pub type PLDR_DLL_LOADED_NOTIFICATION_DATA = *mut LDR_DLL_LOADED_NOTIFICATION_DATA;
STRUCT!{struct LDR_DLL_UNLOADED_NOTIFICATION_DATA {
Flags: ULONG,
FullDllName: PCUNICODE_STRING,
BaseDllName: PCUNICODE_STRING,
DllBase: PVOID,
SizeOfImage: ULONG,
}}
pub type PLDR_DLL_UNLOADED_NOTIFICATION_DATA = *mut LDR_DLL_UNLOADED_NOTIFICATION_DATA;
UNION!{union LDR_DLL_NOTIFICATION_DATA {
Loaded: LDR_DLL_LOADED_NOTIFICATION_DATA,
Unloaded: LDR_DLL_UNLOADED_NOTIFICATION_DATA,
}}
pub type PLDR_DLL_NOTIFICATION_DATA = *mut LDR_DLL_NOTIFICATION_DATA;
FN!{stdcall PLDR_DLL_NOTIFICATION_FUNCTION(
NotificationReason: ULONG,
NotificationData: PLDR_DLL_NOTIFICATION_DATA,
Context: PVOID,
) -> ()}
EXTERN!{extern "system" {
fn LdrRegisterDllNotification(
Flags: ULONG,
NotificationFunction: PLDR_DLL_NOTIFICATION_FUNCTION,
Context: PVOID,
Cookie: *mut PVOID,
) -> NTSTATUS;
fn LdrUnregisterDllNotification(
Cookie: PVOID,
) -> NTSTATUS;
}}
STRUCT!{struct PS_MITIGATION_OPTIONS_MAP {
Map: [ULONG_PTR; 2],
}}
pub type PPS_MITIGATION_OPTIONS_MAP = *mut PS_MITIGATION_OPTIONS_MAP;
STRUCT!{struct PS_MITIGATION_AUDIT_OPTIONS_MAP {
Map: [ULONG_PTR; 2],
}}
pub type PPS_MITIGATION_AUDIT_OPTIONS_MAP = *mut PS_MITIGATION_AUDIT_OPTIONS_MAP;
STRUCT!{struct PS_SYSTEM_DLL_INIT_BLOCK {
Size: ULONG,
SystemDllWowRelocation: ULONG_PTR,
SystemDllNativeRelocation: ULONG_PTR,
Wow64SharedInformation: [ULONG_PTR; 16],
RngData: ULONG,
Flags: ULONG,
MitigationOptionsMap: PS_MITIGATION_OPTIONS_MAP,
CfgBitMap: ULONG_PTR,
CfgBitMapSize: ULONG_PTR,
Wow64CfgBitMap: ULONG_PTR,
Wow64CfgBitMapSize: ULONG_PTR,
MitigationAuditOptionsMap: PS_MITIGATION_AUDIT_OPTIONS_MAP,
}}
BITFIELD!{PS_SYSTEM_DLL_INIT_BLOCK Flags: ULONG [
CfgOverride set_CfgOverride[0..1],
Reserved set_Reserved[1..32],
]}
pub type PPS_SYSTEM_DLL_INIT_BLOCK = *mut PS_SYSTEM_DLL_INIT_BLOCK;
EXTERN!{extern "system" {
fn LdrSystemDllInitBlock() -> PPS_SYSTEM_DLL_INIT_BLOCK;
fn LdrAddLoadAsDataTable(
Module: PVOID,
FilePath: PWSTR,
Size: SIZE_T,
Handle: HANDLE,
) -> NTSTATUS;
fn LdrRemoveLoadAsDataTable(
InitModule: PVOID,
BaseModule: *mut PVOID,
Size: PSIZE_T,
Flags: ULONG,
) -> NTSTATUS;
fn LdrGetFileNameFromLoadAsDataTable(
Module: PVOID,
pFileNamePrt: *mut PVOID,
) -> NTSTATUS;
fn LdrDisableThreadCalloutsForDll(
DllImageBase: PVOID,
) -> NTSTATUS;
fn LdrAccessResource(
DllHandle: PVOID,
ResourceDataEntry: PIMAGE_RESOURCE_DATA_ENTRY,
ResourceBuffer: *mut PVOID,
ResourceLength: *mut ULONG,
) -> NTSTATUS;
}}
STRUCT!{struct LDR_RESOURCE_INFO {
Type: ULONG_PTR,
Name: ULONG_PTR,
Language: ULONG_PTR,
}}
pub type PLDR_RESOURCE_INFO = *mut LDR_RESOURCE_INFO;
pub const RESOURCE_TYPE_LEVEL: ULONG = 0;
pub const RESOURCE_NAME_LEVEL: ULONG = 1;
pub const RESOURCE_LANGUAGE_LEVEL: ULONG = 2;
pub const RESOURCE_DATA_LEVEL: ULONG = 3;
EXTERN!{extern "system" {
fn LdrFindResource_U(
DllHandle: PVOID,
ResourceInfo: PLDR_RESOURCE_INFO,
Level: ULONG,
ResourceDataEntry: *mut PIMAGE_RESOURCE_DATA_ENTRY,
) -> NTSTATUS;
fn LdrFindResourceDirectory_U(
DllHandle: PVOID,
ResourceInfo: PLDR_RESOURCE_INFO,
Level: ULONG,
ResourceDirectory: *mut PIMAGE_RESOURCE_DIRECTORY,
) -> NTSTATUS;
}}
STRUCT!{struct LDR_ENUM_RESOURCE_ENTRY_Path_s {
Id: USHORT,
NameIsPresent: USHORT,
}}
UNION!{union LDR_ENUM_RESOURCE_ENTRY_Path {
NameOrId: ULONG_PTR,
Name: PIMAGE_RESOURCE_DIRECTORY_STRING,
s: LDR_ENUM_RESOURCE_ENTRY_Path_s,
}}
STRUCT!{struct LDR_ENUM_RESOURCE_ENTRY {
Path: [LDR_ENUM_RESOURCE_ENTRY_Path; 3],
Data: PVOID,
Size: ULONG,
Reserved: ULONG,
}}
pub type PLDR_ENUM_RESOURCE_ENTRY = *mut LDR_ENUM_RESOURCE_ENTRY;
#[inline]
pub unsafe fn NAME_FROM_RESOURCE_ENTRY(
RootDirectory: PIMAGE_RESOURCE_DIRECTORY,
Entry: &IMAGE_RESOURCE_DIRECTORY_ENTRY,
) -> usize {
if Entry.u.s().NameIsString() != 0 {
return RootDirectory as usize + Entry.u.s().NameOffset() as usize;
}
*Entry.u.Id() as usize
}
EXTERN!{extern "system" {
fn LdrEnumResources(
DllHandle: PVOID,
ResourceInfo: PLDR_RESOURCE_INFO,
Level: ULONG,
ResourceCount: *mut ULONG,
Resources: PLDR_ENUM_RESOURCE_ENTRY,
) -> NTSTATUS;
fn LdrFindEntryForAddress(
DllHandle: PVOID,
Entry: *mut PLDR_DATA_TABLE_ENTRY,
) -> NTSTATUS;
}}
STRUCT!{struct RTL_PROCESS_MODULE_INFORMATION {
Section: HANDLE,
MappedBase: PVOID,
ImageBase: PVOID,
ImageSize: ULONG,
Flags: ULONG,
LoadOrderIndex: USHORT,
InitOrderIndex: USHORT,
LoadCount: USHORT,
OffsetToFileName: USHORT,
FullPathName: [UCHAR; 256],
}}
pub type PRTL_PROCESS_MODULE_INFORMATION = *mut RTL_PROCESS_MODULE_INFORMATION;
STRUCT!{struct RTL_PROCESS_MODULES {
NumberOfModules: ULONG,
Modules: [RTL_PROCESS_MODULE_INFORMATION; 1],
}}
pub type PRTL_PROCESS_MODULES = *mut RTL_PROCESS_MODULES;
STRUCT!{struct RTL_PROCESS_MODULE_INFORMATION_EX {
NextOffset: USHORT,
BaseInfo: RTL_PROCESS_MODULE_INFORMATION,
ImageChecksum: ULONG,
TimeDateStamp: ULONG,
DefaultBase: PVOID,
}}
pub type PRTL_PROCESS_MODULE_INFORMATION_EX = *mut RTL_PROCESS_MODULE_INFORMATION_EX;
EXTERN!{extern "system" {
fn LdrQueryProcessModuleInformation(
ModuleInformation: PRTL_PROCESS_MODULES,
Size: ULONG,
ReturnedSize: PULONG,
) -> NTSTATUS;
}}
FN!{stdcall PLDR_ENUM_CALLBACK(
ModuleInformation: PLDR_DATA_TABLE_ENTRY,
Parameter: PVOID,
Stop: *mut BOOLEAN,
) -> ()}
EXTERN!{extern "system" {
fn LdrEnumerateLoadedModules(
ReservedFlag: BOOLEAN,
EnumProc: PLDR_ENUM_CALLBACK,
Context: PVOID,
) -> NTSTATUS;
fn LdrOpenImageFileOptionsKey(
SubKey: PUNICODE_STRING,
Wow64: BOOLEAN,
NewKeyHandle: PHANDLE,
) -> NTSTATUS;
fn LdrQueryImageFileKeyOption(
KeyHandle: HANDLE,
ValueName: PCWSTR,
Type: ULONG,
Buffer: PVOID,
BufferSize: ULONG,
ReturnedLength: PULONG,
) -> NTSTATUS;
fn LdrQueryImageFileExecutionOptions(
SubKey: PUNICODE_STRING,
ValueName: PCWSTR,
ValueSize: ULONG,
Buffer: PVOID,
BufferSize: ULONG,
ReturnedLength: PULONG,
) -> NTSTATUS;
fn LdrQueryImageFileExecutionOptionsEx(
SubKey: PUNICODE_STRING,
ValueName: PCWSTR,
Type: ULONG,
Buffer: PVOID,
BufferSize: ULONG,
ReturnedLength: PULONG,
Wow64: BOOLEAN,
) -> NTSTATUS;
}}
UNION!{union DELAYLOAD_PROC_DESCRIPTOR_Description {
Name: PCSTR,
Ordinal: ULONG,
}}
STRUCT!{struct DELAYLOAD_PROC_DESCRIPTOR {
ImportDescribedByName: ULONG,
Description: DELAYLOAD_PROC_DESCRIPTOR_Description,
}}
pub type PDELAYLOAD_PROC_DESCRIPTOR = *mut DELAYLOAD_PROC_DESCRIPTOR;
STRUCT!{struct DELAYLOAD_INFO {
Size: ULONG,
DelayloadDescriptor: PCIMAGE_DELAYLOAD_DESCRIPTOR,
ThunkAddress: PIMAGE_THUNK_DATA,
TargetDllName: PCSTR,
TargetApiDescriptor: DELAYLOAD_PROC_DESCRIPTOR,
TargetModuleBase: PVOID,
Unused: PVOID,
LastError: ULONG,
}}
pub type PDELAYLOAD_INFO = *mut DELAYLOAD_INFO;
FN!{stdcall PDELAYLOAD_FAILURE_DLL_CALLBACK(
NotificationReason: ULONG,
DelayloadInfo: PDELAYLOAD_INFO,
) -> PVOID}
FN!{stdcall PDELAYLOAD_FAILURE_SYSTEM_ROUTINE(
DllName: PCSTR,
ProcName: PCSTR,
) -> PVOID}
EXTERN!{extern "system" {
fn LdrResolveDelayLoadedAPI(
ParentModuleBase: PVOID,
DelayloadDescriptor: PCIMAGE_DELAYLOAD_DESCRIPTOR,
FailureDllHook: PDELAYLOAD_FAILURE_DLL_CALLBACK,
FailureSystemHook: PDELAYLOAD_FAILURE_SYSTEM_ROUTINE,
ThunkAddress: PIMAGE_THUNK_DATA,
Flags: ULONG,
) -> PVOID;
fn LdrResolveDelayLoadsFromDll(
ParentBase: PVOID,
TargetDllName: PCSTR,
Flags: ULONG,
) -> NTSTATUS;
fn LdrSetDefaultDllDirectories(
DirectoryFlags: ULONG,
) -> NTSTATUS;
fn LdrShutdownProcess() -> NTSTATUS;
fn LdrShutdownThread() -> NTSTATUS;
fn LdrSetImplicitPathOptions(
ImplicitPathOptions: ULONG,
) -> NTSTATUS;
fn LdrControlFlowGuardEnforced() -> BOOLEAN;
}}

View file

@ -1,692 +0,0 @@
use core::mem::size_of;
use crate::ntapi_base::{CLIENT_ID, CLIENT_ID64};
use winapi::ctypes::c_double;
use winapi::shared::basetsd::{PSIZE_T, SIZE_T, ULONG64, ULONG_PTR};
use winapi::shared::ntdef::{
BOOLEAN, CSHORT, HANDLE, LARGE_INTEGER, NTSTATUS, OBJ_CASE_INSENSITIVE, PHANDLE,
PLARGE_INTEGER, POBJECT_ATTRIBUTES, PULONG, PUNICODE_STRING, PVOID, ULONG, ULONGLONG,
UNICODE_STRING,
};
use winapi::um::winnt::{
ACCESS_MASK, PSECURITY_DESCRIPTOR, PSECURITY_QUALITY_OF_SERVICE, PSID, RTL_SRWLOCK,
SECURITY_QUALITY_OF_SERVICE, STANDARD_RIGHTS_REQUIRED, SYNCHRONIZE,
};
pub const PORT_CONNECT: u32 = 0x0001;
pub const PORT_ALL_ACCESS: u32 = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1;
STRUCT!{struct PORT_MESSAGE_u1_s {
DataLength: CSHORT,
TotalLength: CSHORT,
}}
STRUCT!{struct PORT_MESSAGE_u2_s {
Type: CSHORT,
DataInfoOffset: CSHORT,
}}
UNION!{union PORT_MESSAGE_u1 {
s: PORT_MESSAGE_u1_s,
Length: ULONG,
}}
UNION!{union PORT_MESSAGE_u2 {
s: PORT_MESSAGE_u2_s,
ZeroInit: ULONG,
}}
UNION!{union PORT_MESSAGE_u3 {
ClientId: CLIENT_ID,
DoNotUseThisField: c_double,
}}
UNION!{union PORT_MESSAGE_u4 {
ClientViewSize: SIZE_T,
CallbackId: ULONG,
}}
STRUCT!{struct PORT_MESSAGE {
u1: PORT_MESSAGE_u1,
u2: PORT_MESSAGE_u2,
u3: PORT_MESSAGE_u3,
MessageId: ULONG,
u4: PORT_MESSAGE_u4,
}}
pub type PPORT_MESSAGE = *mut PORT_MESSAGE;
STRUCT!{struct PORT_DATA_ENTRY {
Base: PVOID,
Size: ULONG,
}}
pub type PPORT_DATA_ENTRY = *mut PORT_DATA_ENTRY;
STRUCT!{struct PORT_DATA_INFORMATION {
CountDataEntries: ULONG,
DataEntries: [PORT_DATA_ENTRY; 1],
}}
pub type PPORT_DATA_INFORMATION = *mut PORT_DATA_INFORMATION;
pub const LPC_REQUEST: ULONG = 1;
pub const LPC_REPLY: ULONG = 2;
pub const LPC_DATAGRAM: ULONG = 3;
pub const LPC_LOST_REPLY: ULONG = 4;
pub const LPC_PORT_CLOSED: ULONG = 5;
pub const LPC_CLIENT_DIED: ULONG = 6;
pub const LPC_EXCEPTION: ULONG = 7;
pub const LPC_DEBUG_EVENT: ULONG = 8;
pub const LPC_ERROR_EVENT: ULONG = 9;
pub const LPC_CONNECTION_REQUEST: ULONG = 10;
pub const LPC_KERNELMODE_MESSAGE: CSHORT = 0x8000;
pub const LPC_NO_IMPERSONATE: CSHORT = 0x4000;
pub const PORT_VALID_OBJECT_ATTRIBUTES: u32 = OBJ_CASE_INSENSITIVE;
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub const PORT_MAXIMUM_MESSAGE_LENGTH: u32 = 512;
#[cfg(target_arch = "x86")]
pub const PORT_MAXIMUM_MESSAGE_LENGTH: u32 = 256;
pub const LPC_MAX_CONNECTION_INFO_SIZE: u32 = 16 * size_of::<ULONG_PTR>() as u32;
pub const PORT_TOTAL_MAXIMUM_MESSAGE_LENGTH: u32 = (PORT_MAXIMUM_MESSAGE_LENGTH
+ size_of::<PORT_MESSAGE>() as u32
+ LPC_MAX_CONNECTION_INFO_SIZE
+ 0xf) & !0xf;
STRUCT!{struct LPC_CLIENT_DIED_MSG {
PortMsg: PORT_MESSAGE,
CreateTime: LARGE_INTEGER,
}}
pub type PLPC_CLIENT_DIED_MSG = *mut LPC_CLIENT_DIED_MSG;
STRUCT!{struct PORT_VIEW {
Length: ULONG,
SectionHandle: HANDLE,
SectionOffset: ULONG,
ViewSize: SIZE_T,
ViewBase: PVOID,
ViewRemoteBase: PVOID,
}}
pub type PPORT_VIEW = *mut PORT_VIEW;
STRUCT!{struct REMOTE_PORT_VIEW {
Length: ULONG,
ViewSize: SIZE_T,
ViewBase: PVOID,
}}
pub type PREMOTE_PORT_VIEW = *mut REMOTE_PORT_VIEW;
STRUCT!{struct PORT_MESSAGE64_u1_s {
DataLength: CSHORT,
TotalLength: CSHORT,
}}
STRUCT!{struct PORT_MESSAGE64_u2_s {
Type: CSHORT,
DataInfoOffset: CSHORT,
}}
UNION!{union PORT_MESSAGE64_u1 {
s: PORT_MESSAGE64_u1_s,
Length: ULONG,
}}
UNION!{union PORT_MESSAGE64_u2 {
s: PORT_MESSAGE64_u2_s,
ZeroInit: ULONG,
}}
UNION!{union PORT_MESSAGE64_u3 {
ClientId: CLIENT_ID64,
DoNotUseThisField: c_double,
}}
UNION!{union PORT_MESSAGE64_u4 {
ClientViewSize: ULONGLONG,
CallbackId: ULONG,
}}
STRUCT!{struct PORT_MESSAGE64 {
u1: PORT_MESSAGE64_u1,
u2: PORT_MESSAGE64_u2,
u3: PORT_MESSAGE64_u3,
MessageId: ULONG,
u4: PORT_MESSAGE64_u4,
}}
pub type PPORT_MESSAGE64 = *mut PORT_MESSAGE64;
STRUCT!{struct LPC_CLIENT_DIED_MSG64 {
PortMsg: PORT_MESSAGE64,
CreateTime: LARGE_INTEGER,
}}
pub type PLPC_CLIENT_DIED_MSG64 = *mut LPC_CLIENT_DIED_MSG64;
STRUCT!{struct PORT_VIEW64 {
Length: ULONG,
SectionHandle: ULONGLONG,
SectionOffset: ULONG,
ViewSize: ULONGLONG,
ViewBase: ULONGLONG,
ViewRemoteBase: ULONGLONG,
}}
pub type PPORT_VIEW64 = *mut PORT_VIEW64;
STRUCT!{struct REMOTE_PORT_VIEW64 {
Length: ULONG,
ViewSize: ULONGLONG,
ViewBase: ULONGLONG,
}}
pub type PREMOTE_PORT_VIEW64 = *mut REMOTE_PORT_VIEW64;
EXTERN!{extern "system" {
fn NtCreatePort(
PortHandle: PHANDLE,
ObjectAttributes: POBJECT_ATTRIBUTES,
MaxConnectionInfoLength: ULONG,
MaxMessageLength: ULONG,
MaxPoolUsage: ULONG,
) -> NTSTATUS;
fn NtCreateWaitablePort(
PortHandle: PHANDLE,
ObjectAttributes: POBJECT_ATTRIBUTES,
MaxConnectionInfoLength: ULONG,
MaxMessageLength: ULONG,
MaxPoolUsage: ULONG,
) -> NTSTATUS;
fn NtConnectPort(
PortHandle: PHANDLE,
PortName: PUNICODE_STRING,
SecurityQos: PSECURITY_QUALITY_OF_SERVICE,
ClientView: PPORT_VIEW,
ServerView: PREMOTE_PORT_VIEW,
MaxMessageLength: PULONG,
ConnectionInformation: PVOID,
ConnectionInformationLength: PULONG,
) -> NTSTATUS;
fn NtSecureConnectPort(
PortHandle: PHANDLE,
PortName: PUNICODE_STRING,
SecurityQos: PSECURITY_QUALITY_OF_SERVICE,
ClientView: PPORT_VIEW,
RequiredServerSid: PSID,
ServerView: PREMOTE_PORT_VIEW,
MaxMessageLength: PULONG,
ConnectionInformation: PVOID,
ConnectionInformationLength: PULONG,
) -> NTSTATUS;
fn NtListenPort(
PortHandle: HANDLE,
ConnectionRequest: PPORT_MESSAGE,
) -> NTSTATUS;
fn NtAcceptConnectPort(
PortHandle: PHANDLE,
PortContext: PVOID,
ConnectionRequest: PPORT_MESSAGE,
AcceptConnection: BOOLEAN,
ServerView: PPORT_VIEW,
ClientView: PREMOTE_PORT_VIEW,
) -> NTSTATUS;
fn NtCompleteConnectPort(
PortHandle: HANDLE,
) -> NTSTATUS;
fn NtRequestPort(
PortHandle: HANDLE,
RequestMessage: PPORT_MESSAGE,
) -> NTSTATUS;
fn NtRequestWaitReplyPort(
PortHandle: HANDLE,
RequestMessage: PPORT_MESSAGE,
ReplyMessage: PPORT_MESSAGE,
) -> NTSTATUS;
fn NtReplyPort(
PortHandle: HANDLE,
ReplyMessage: PPORT_MESSAGE,
) -> NTSTATUS;
fn NtReplyWaitReplyPort(
PortHandle: HANDLE,
ReplyMessage: PPORT_MESSAGE,
) -> NTSTATUS;
fn NtReplyWaitReceivePort(
PortHandle: HANDLE,
PortContext: *mut PVOID,
ReplyMessage: PPORT_MESSAGE,
ReceiveMessage: PPORT_MESSAGE,
) -> NTSTATUS;
fn NtReplyWaitReceivePortEx(
PortHandle: HANDLE,
PortContext: *mut PVOID,
ReplyMessage: PPORT_MESSAGE,
ReceiveMessage: PPORT_MESSAGE,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtImpersonateClientOfPort(
PortHandle: HANDLE,
Message: PPORT_MESSAGE,
) -> NTSTATUS;
fn NtReadRequestData(
PortHandle: HANDLE,
Message: PPORT_MESSAGE,
DataEntryIndex: ULONG,
Buffer: PVOID,
BufferSize: SIZE_T,
NumberOfBytesRead: PSIZE_T,
) -> NTSTATUS;
fn NtWriteRequestData(
PortHandle: HANDLE,
Message: PPORT_MESSAGE,
DataEntryIndex: ULONG,
Buffer: PVOID,
BufferSize: SIZE_T,
NumberOfBytesWritten: PSIZE_T,
) -> NTSTATUS;
}}
ENUM!{enum PORT_INFORMATION_CLASS {
PortBasicInformation = 0,
PortDumpInformation = 1,
}}
EXTERN!{extern "system" {
fn NtQueryInformationPort(
PortHandle: HANDLE,
PortInformationClass: PORT_INFORMATION_CLASS,
PortInformation: PVOID,
Length: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
}}
pub type PALPC_HANDLE = *mut HANDLE;
pub type ALPC_HANDLE = HANDLE;
pub const ALPC_PORFLG_ALLOW_LPC_REQUESTS: ULONG = 0x20000;
pub const ALPC_PORFLG_WAITABLE_PORT: ULONG = 0x40000;
pub const ALPC_PORFLG_SYSTEM_PROCESS: ULONG = 0x100000;
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
STRUCT!{struct ALPC_PORT_ATTRIBUTES {
Flags: ULONG,
SecurityQos: SECURITY_QUALITY_OF_SERVICE,
MaxMessageLength: SIZE_T,
MemoryBandwidth: SIZE_T,
MaxPoolUsage: SIZE_T,
MaxSectionSize: SIZE_T,
MaxViewSize: SIZE_T,
MaxTotalSectionSize: SIZE_T,
DupObjectTypes: ULONG,
Reserved: ULONG,
}}
#[cfg(target_arch = "x86")]
STRUCT!{struct ALPC_PORT_ATTRIBUTES {
Flags: ULONG,
SecurityQos: SECURITY_QUALITY_OF_SERVICE,
MaxMessageLength: SIZE_T,
MemoryBandwidth: SIZE_T,
MaxPoolUsage: SIZE_T,
MaxSectionSize: SIZE_T,
MaxViewSize: SIZE_T,
MaxTotalSectionSize: SIZE_T,
DupObjectTypes: ULONG,
}}
pub type PALPC_PORT_ATTRIBUTES = *mut ALPC_PORT_ATTRIBUTES;
pub const ALPC_MESSAGE_SECURITY_ATTRIBUTE: ULONG = 0x80000000;
pub const ALPC_MESSAGE_VIEW_ATTRIBUTE: ULONG = 0x40000000;
pub const ALPC_MESSAGE_CONTEXT_ATTRIBUTE: ULONG = 0x20000000;
pub const ALPC_MESSAGE_HANDLE_ATTRIBUTE: ULONG = 0x10000000;
STRUCT!{struct ALPC_MESSAGE_ATTRIBUTES {
AllocatedAttributes: ULONG,
ValidAttributes: ULONG,
}}
pub type PALPC_MESSAGE_ATTRIBUTES = *mut ALPC_MESSAGE_ATTRIBUTES;
STRUCT!{struct ALPC_COMPLETION_LIST_STATE {
Value: ULONG64,
}}
BITFIELD!{ALPC_COMPLETION_LIST_STATE Value: ULONG64 [
Head set_Head[0..24],
Tail set_Tail[24..48],
ActiveThreadCount set_ActiveThreadCount[48..64],
]}
pub type PALPC_COMPLETION_LIST_STATE = *mut ALPC_COMPLETION_LIST_STATE;
pub const ALPC_COMPLETION_LIST_BUFFER_GRANULARITY_MASK: ULONG = 0x3f;
STRUCT!{#[repr(align(128))] struct ALPC_COMPLETION_LIST_HEADER {
StartMagic: ULONG64,
TotalSize: ULONG,
ListOffset: ULONG,
ListSize: ULONG,
BitmapOffset: ULONG,
BitmapSize: ULONG,
DataOffset: ULONG,
DataSize: ULONG,
AttributeFlags: ULONG,
AttributeSize: ULONG,
__padding0: [u64; 10],
State: ALPC_COMPLETION_LIST_STATE,
LastMessageId: ULONG,
LastCallbackId: ULONG,
__padding1: [u32; 28],
PostCount: ULONG,
__padding2: [u32; 31],
ReturnCount: ULONG,
__padding3: [u32; 31],
LogSequenceNumber: ULONG,
__padding4: [u64; 15],
UserLock: RTL_SRWLOCK,
EndMagic: ULONG64,
__padding5: [u64; 14],
}}
pub type PALPC_COMPLETION_LIST_HEADER = *mut ALPC_COMPLETION_LIST_HEADER;
STRUCT!{struct ALPC_CONTEXT_ATTR {
PortContext: PVOID,
MessageContext: PVOID,
Sequence: ULONG,
MessageId: ULONG,
CallbackId: ULONG,
}}
pub type PALPC_CONTEXT_ATTR = *mut ALPC_CONTEXT_ATTR;
pub const ALPC_HANDLEFLG_DUPLICATE_SAME_ACCESS: ULONG = 0x10000;
pub const ALPC_HANDLEFLG_DUPLICATE_SAME_ATTRIBUTES: ULONG = 0x20000;
pub const ALPC_HANDLEFLG_DUPLICATE_INHERIT: ULONG = 0x80000;
STRUCT!{struct ALPC_HANDLE_ATTR32 {
Flags: ULONG,
Reserved0: ULONG,
SameAccess: ULONG,
SameAttributes: ULONG,
Indirect: ULONG,
Inherit: ULONG,
Reserved1: ULONG,
Handle: ULONG,
ObjectType: ULONG,
DesiredAccess: ULONG,
GrantedAccess: ULONG,
}}
pub type PALPC_HANDLE_ATTR32 = *mut ALPC_HANDLE_ATTR32;
STRUCT!{struct ALPC_HANDLE_ATTR {
Flags: ULONG,
Reserved0: ULONG,
SameAccess: ULONG,
SameAttributes: ULONG,
Indirect: ULONG,
Inherit: ULONG,
Reserved1: ULONG,
Handle: HANDLE,
HandleAttrArray: PALPC_HANDLE_ATTR32,
ObjectType: ULONG,
HandleCount: ULONG,
DesiredAccess: ACCESS_MASK,
GrantedAccess: ACCESS_MASK,
}}
pub type PALPC_HANDLE_ATTR = *mut ALPC_HANDLE_ATTR;
pub const ALPC_SECFLG_CREATE_HANDLE: ULONG = 0x20000;
STRUCT!{struct ALPC_SECURITY_ATTR {
Flags: ULONG,
QoS: PSECURITY_QUALITY_OF_SERVICE,
ContextHandle: ALPC_HANDLE,
}}
pub type PALPC_SECURITY_ATTR = *mut ALPC_SECURITY_ATTR;
pub const ALPC_VIEWFLG_NOT_SECURE: ULONG = 0x40000;
STRUCT!{struct ALPC_DATA_VIEW_ATTR {
Flags: ULONG,
SectionHandle: ALPC_HANDLE,
ViewBase: PVOID,
ViewSize: SIZE_T,
}}
pub type PALPC_DATA_VIEW_ATTR = *mut ALPC_DATA_VIEW_ATTR;
ENUM!{enum ALPC_PORT_INFORMATION_CLASS {
AlpcBasicInformation = 0,
AlpcPortInformation = 1,
AlpcAssociateCompletionPortInformation = 2,
AlpcConnectedSIDInformation = 3,
AlpcServerInformation = 4,
AlpcMessageZoneInformation = 5,
AlpcRegisterCompletionListInformation = 6,
AlpcUnregisterCompletionListInformation = 7,
AlpcAdjustCompletionListConcurrencyCountInformation = 8,
AlpcRegisterCallbackInformation = 9,
AlpcCompletionListRundownInformation = 10,
AlpcWaitForPortReferences = 11,
}}
STRUCT!{struct ALPC_BASIC_INFORMATION {
Flags: ULONG,
SequenceNo: ULONG,
PortContext: PVOID,
}}
pub type PALPC_BASIC_INFORMATION = *mut ALPC_BASIC_INFORMATION;
STRUCT!{struct ALPC_PORT_ASSOCIATE_COMPLETION_PORT {
CompletionKey: PVOID,
CompletionPort: HANDLE,
}}
pub type PALPC_PORT_ASSOCIATE_COMPLETION_PORT = *mut ALPC_PORT_ASSOCIATE_COMPLETION_PORT;
STRUCT!{struct ALPC_SERVER_INFORMATION_Out {
ThreadBlocked: BOOLEAN,
ConnectedProcessId: HANDLE,
ConnectionPortName: UNICODE_STRING,
}}
UNION!{union ALPC_SERVER_INFORMATION {
ThreadHandle: HANDLE,
Out: ALPC_SERVER_INFORMATION_Out,
}}
pub type PALPC_SERVER_INFORMATION = *mut ALPC_SERVER_INFORMATION;
STRUCT!{struct ALPC_PORT_MESSAGE_ZONE_INFORMATION {
Buffer: PVOID,
Size: ULONG,
}}
pub type PALPC_PORT_MESSAGE_ZONE_INFORMATION = *mut ALPC_PORT_MESSAGE_ZONE_INFORMATION;
STRUCT!{struct ALPC_PORT_COMPLETION_LIST_INFORMATION {
Buffer: PVOID,
Size: ULONG,
ConcurrencyCount: ULONG,
AttributeFlags: ULONG,
}}
pub type PALPC_PORT_COMPLETION_LIST_INFORMATION = *mut ALPC_PORT_COMPLETION_LIST_INFORMATION;
ENUM!{enum ALPC_MESSAGE_INFORMATION_CLASS {
AlpcMessageSidInformation = 0,
AlpcMessageTokenModifiedIdInformation = 1,
AlpcMessageDirectStatusInformation = 2,
AlpcMessageHandleInformation = 3,
MaxAlpcMessageInfoClass = 4,
}}
pub type PALPC_MESSAGE_INFORMATION_CLASS = *mut ALPC_MESSAGE_INFORMATION_CLASS;
STRUCT!{struct ALPC_MESSAGE_HANDLE_INFORMATION {
Index: ULONG,
Flags: ULONG,
Handle: ULONG,
ObjectType: ULONG,
GrantedAccess: ACCESS_MASK,
}}
pub type PALPC_MESSAGE_HANDLE_INFORMATION = *mut ALPC_MESSAGE_HANDLE_INFORMATION;
EXTERN!{extern "system" {
fn NtAlpcCreatePort(
PortHandle: PHANDLE,
ObjectAttributes: POBJECT_ATTRIBUTES,
PortAttributes: PALPC_PORT_ATTRIBUTES,
) -> NTSTATUS;
fn NtAlpcDisconnectPort(
PortHandle: HANDLE,
Flags: ULONG,
) -> NTSTATUS;
fn NtAlpcQueryInformation(
PortHandle: HANDLE,
PortInformationClass: ALPC_PORT_INFORMATION_CLASS,
PortInformation: PVOID,
Length: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtAlpcSetInformation(
PortHandle: HANDLE,
PortInformationClass: ALPC_PORT_INFORMATION_CLASS,
PortInformation: PVOID,
Length: ULONG,
) -> NTSTATUS;
fn NtAlpcCreatePortSection(
PortHandle: HANDLE,
Flags: ULONG,
SectionHandle: HANDLE,
SectionSize: SIZE_T,
AlpcSectionHandle: PALPC_HANDLE,
ActualSectionSize: PSIZE_T,
) -> NTSTATUS;
fn NtAlpcDeletePortSection(
PortHandle: HANDLE,
Flags: ULONG,
SectionHandle: ALPC_HANDLE,
) -> NTSTATUS;
fn NtAlpcCreateResourceReserve(
PortHandle: HANDLE,
Flags: ULONG,
MessageSize: SIZE_T,
ResourceId: PALPC_HANDLE,
) -> NTSTATUS;
fn NtAlpcDeleteResourceReserve(
PortHandle: HANDLE,
Flags: ULONG,
ResourceId: ALPC_HANDLE,
) -> NTSTATUS;
fn NtAlpcCreateSectionView(
PortHandle: HANDLE,
Flags: ULONG,
ViewAttributes: PALPC_DATA_VIEW_ATTR,
) -> NTSTATUS;
fn NtAlpcDeleteSectionView(
PortHandle: HANDLE,
Flags: ULONG,
ViewBase: PVOID,
) -> NTSTATUS;
fn NtAlpcCreateSecurityContext(
PortHandle: HANDLE,
Flags: ULONG,
SecurityAttribute: PALPC_SECURITY_ATTR,
) -> NTSTATUS;
fn NtAlpcDeleteSecurityContext(
PortHandle: HANDLE,
Flags: ULONG,
ContextHandle: ALPC_HANDLE,
) -> NTSTATUS;
fn NtAlpcRevokeSecurityContext(
PortHandle: HANDLE,
Flags: ULONG,
ContextHandle: ALPC_HANDLE,
) -> NTSTATUS;
fn NtAlpcQueryInformationMessage(
PortHandle: HANDLE,
PortMessage: PPORT_MESSAGE,
MessageInformationClass: ALPC_MESSAGE_INFORMATION_CLASS,
MessageInformation: PVOID,
Length: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
}}
pub const ALPC_MSGFLG_REPLY_MESSAGE: ULONG = 0x1;
pub const ALPC_MSGFLG_LPC_MODE: ULONG = 0x2;
pub const ALPC_MSGFLG_RELEASE_MESSAGE: ULONG = 0x10000;
pub const ALPC_MSGFLG_SYNC_REQUEST: ULONG = 0x20000;
pub const ALPC_MSGFLG_WAIT_USER_MODE: ULONG = 0x100000;
pub const ALPC_MSGFLG_WAIT_ALERTABLE: ULONG = 0x200000;
pub const ALPC_MSGFLG_WOW64_CALL: ULONG = 0x80000000;
EXTERN!{extern "system" {
fn NtAlpcConnectPort(
PortHandle: PHANDLE,
PortName: PUNICODE_STRING,
ObjectAttributes: POBJECT_ATTRIBUTES,
PortAttributes: PALPC_PORT_ATTRIBUTES,
Flags: ULONG,
RequiredServerSid: PSID,
ConnectionMessage: PPORT_MESSAGE,
BufferLength: PULONG,
OutMessageAttributes: PALPC_MESSAGE_ATTRIBUTES,
InMessageAttributes: PALPC_MESSAGE_ATTRIBUTES,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtAlpcConnectPortEx(
PortHandle: PHANDLE,
ConnectionPortObjectAttributes: POBJECT_ATTRIBUTES,
ClientPortObjectAttributes: POBJECT_ATTRIBUTES,
PortAttributes: PALPC_PORT_ATTRIBUTES,
Flags: ULONG,
ServerSecurityRequirements: PSECURITY_DESCRIPTOR,
ConnectionMessage: PPORT_MESSAGE,
BufferLength: PSIZE_T,
OutMessageAttributes: PALPC_MESSAGE_ATTRIBUTES,
InMessageAttributes: PALPC_MESSAGE_ATTRIBUTES,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtAlpcAcceptConnectPort(
PortHandle: PHANDLE,
ConnectionPortHandle: HANDLE,
Flags: ULONG,
ObjectAttributes: POBJECT_ATTRIBUTES,
PortAttributes: PALPC_PORT_ATTRIBUTES,
PortContext: PVOID,
ConnectionRequest: PPORT_MESSAGE,
ConnectionMessageAttributes: PALPC_MESSAGE_ATTRIBUTES,
AcceptConnection: BOOLEAN,
) -> NTSTATUS;
fn NtAlpcSendWaitReceivePort(
PortHandle: HANDLE,
Flags: ULONG,
SendMessageA: PPORT_MESSAGE,
SendMessageAttributes: PALPC_MESSAGE_ATTRIBUTES,
ReceiveMessage: PPORT_MESSAGE,
BufferLength: PSIZE_T,
ReceiveMessageAttributes: PALPC_MESSAGE_ATTRIBUTES,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
}}
pub const ALPC_CANCELFLG_TRY_CANCEL: ULONG = 0x1;
pub const ALPC_CANCELFLG_NO_CONTEXT_CHECK: ULONG = 0x8;
pub const ALPC_CANCELFLGP_FLUSH: ULONG = 0x10000;
EXTERN!{extern "system" {
fn NtAlpcCancelMessage(
PortHandle: HANDLE,
Flags: ULONG,
MessageContext: PALPC_CONTEXT_ATTR,
) -> NTSTATUS;
fn NtAlpcImpersonateClientOfPort(
PortHandle: HANDLE,
Message: PPORT_MESSAGE,
Flags: PVOID,
) -> NTSTATUS;
fn NtAlpcImpersonateClientContainerOfPort(
PortHandle: HANDLE,
Message: PPORT_MESSAGE,
Flags: ULONG,
) -> NTSTATUS;
fn NtAlpcOpenSenderProcess(
ProcessHandle: PHANDLE,
PortHandle: HANDLE,
PortMessage: PPORT_MESSAGE,
Flags: ULONG,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtAlpcOpenSenderThread(
ThreadHandle: PHANDLE,
PortHandle: HANDLE,
PortMessage: PPORT_MESSAGE,
Flags: ULONG,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn AlpcMaxAllowedMessageLength() -> ULONG;
fn AlpcGetHeaderSize(
Flags: ULONG,
) -> ULONG;
fn AlpcInitializeMessageAttribute(
AttributeFlags: ULONG,
Buffer: PALPC_MESSAGE_ATTRIBUTES,
BufferSize: ULONG,
RequiredBufferSize: PULONG,
) -> NTSTATUS;
fn AlpcGetMessageAttribute(
Buffer: PALPC_MESSAGE_ATTRIBUTES,
AttributeFlag: ULONG,
) -> PVOID;
fn AlpcRegisterCompletionList(
PortHandle: HANDLE,
Buffer: PALPC_COMPLETION_LIST_HEADER,
Size: ULONG,
ConcurrencyCount: ULONG,
AttributeFlags: ULONG,
) -> NTSTATUS;
fn AlpcUnregisterCompletionList(
PortHandle: HANDLE,
) -> NTSTATUS;
fn AlpcRundownCompletionList(
PortHandle: HANDLE,
) -> NTSTATUS;
fn AlpcAdjustCompletionListConcurrencyCount(
PortHandle: HANDLE,
ConcurrencyCount: ULONG,
) -> NTSTATUS;
fn AlpcRegisterCompletionListWorkerThread(
CompletionList: PVOID,
) -> BOOLEAN;
fn AlpcUnregisterCompletionListWorkerThread(
CompletionList: PVOID,
) -> BOOLEAN;
fn AlpcGetCompletionListLastMessageInformation(
CompletionList: PVOID,
LastMessageId: PULONG,
LastCallbackId: PULONG,
);
fn AlpcGetOutstandingCompletionListMessageCount(
CompletionList: PVOID,
) -> ULONG;
fn AlpcGetMessageFromCompletionList(
CompletionList: PVOID,
MessageAttributes: *mut PALPC_MESSAGE_ATTRIBUTES,
) -> PPORT_MESSAGE;
fn AlpcFreeCompletionListMessage(
CompletionList: PVOID,
Message: PPORT_MESSAGE,
);
fn AlpcGetCompletionListMessageAttributes(
CompletionList: PVOID,
Message: PPORT_MESSAGE,
) -> PALPC_MESSAGE_ATTRIBUTES;
}}

View file

@ -1,42 +0,0 @@
use winapi::shared::ntdef::{HANDLE, NTSTATUS, PULONG, PVOID, ULONG};
use winapi::um::winnt::STANDARD_RIGHTS_ALL;
pub const FLT_PORT_CONNECT: u32 = 0x0001;
pub const FLT_PORT_ALL_ACCESS: u32 = FLT_PORT_CONNECT | STANDARD_RIGHTS_ALL;
ENUM!{enum VDMSERVICECLASS {
VdmStartExecution = 0,
VdmQueueInterrupt = 1,
VdmDelayInterrupt = 2,
VdmInitialize = 3,
VdmFeatures = 4,
VdmSetInt21Handler = 5,
VdmQueryDir = 6,
VdmPrinterDirectIoOpen = 7,
VdmPrinterDirectIoClose = 8,
VdmPrinterInitialize = 9,
VdmSetLdtEntries = 10,
VdmSetProcessLdtInfo = 11,
VdmAdlibEmulation = 12,
VdmPMCliControl = 13,
VdmQueryVdmProcess = 14,
}}
pub type PVDMSERVICECLASS = *mut VDMSERVICECLASS;
EXTERN!{extern "system" {
fn NtVdmControl(
Service: VDMSERVICECLASS,
ServiceData: PVOID,
) -> NTSTATUS;
fn NtTraceEvent(
TraceHandle: HANDLE,
Flags: ULONG,
FieldSize: ULONG,
Fields: PVOID,
) -> NTSTATUS;
fn NtTraceControl(
FunctionCode: ULONG,
InBuffer: PVOID,
InBufferLen: ULONG,
OutBuffer: PVOID,
OutBufferLen: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
}}

View file

@ -1,630 +0,0 @@
use crate::winapi_local::um::winnt::PMEM_EXTENDED_PARAMETER;
use winapi::shared::basetsd::{PSIZE_T, PULONG_PTR, SIZE_T, ULONG_PTR};
use winapi::shared::ntdef::{
BOOLEAN, HANDLE, LARGE_INTEGER, NTSTATUS, PHANDLE, PLARGE_INTEGER, POBJECT_ATTRIBUTES, PULONG,
PUNICODE_STRING, PVOID, UCHAR, ULONG, ULONGLONG, UNICODE_STRING, USHORT,
};
use winapi::um::winnt::{
ACCESS_MASK, PCFG_CALL_TARGET_INFO, STANDARD_RIGHTS_REQUIRED, SYNCHRONIZE,
};
ENUM!{enum MEMORY_INFORMATION_CLASS {
MemoryBasicInformation = 0,
MemoryWorkingSetInformation = 1,
MemoryMappedFilenameInformation = 2,
MemoryRegionInformation = 3,
MemoryWorkingSetExInformation = 4,
MemorySharedCommitInformation = 5,
MemoryImageInformation = 6,
MemoryRegionInformationEx = 7,
MemoryPrivilegedBasicInformation = 8,
MemoryEnclaveImageInformation = 9,
MemoryBasicInformationCapped = 10,
}}
STRUCT!{struct MEMORY_WORKING_SET_BLOCK {
Bitfields: ULONG_PTR,
}}
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
BITFIELD!{MEMORY_WORKING_SET_BLOCK Bitfields: ULONG_PTR [
Protection set_Protection[0..5],
ShareCount set_ShareCount[5..8],
Shared set_Shared[8..9],
Node set_Node[9..12],
VirtualPage set_VirtualPage[12..64],
]}
#[cfg(target_arch = "x86")]
BITFIELD!{MEMORY_WORKING_SET_BLOCK Bitfields: ULONG_PTR [
Protection set_Protection[0..5],
ShareCount set_ShareCount[5..8],
Shared set_Shared[8..9],
Node set_Node[9..12],
VirtualPage set_VirtualPage[12..32],
]}
pub type PMEMORY_WORKING_SET_BLOCK = *mut MEMORY_WORKING_SET_BLOCK;
STRUCT!{struct MEMORY_WORKING_SET_INFORMATION {
NumberOfEntries: ULONG_PTR,
WorkingSetInfo: [MEMORY_WORKING_SET_BLOCK; 1],
}}
pub type PMEMORY_WORKING_SET_INFORMATION = *mut MEMORY_WORKING_SET_INFORMATION;
STRUCT!{struct MEMORY_REGION_INFORMATION {
AllocationBase: PVOID,
AllocationProtect: ULONG,
RegionType: ULONG,
RegionSize: SIZE_T,
CommitSize: SIZE_T,
}}
BITFIELD!{MEMORY_REGION_INFORMATION RegionType: ULONG [
Private set_Private[0..1],
MappedDataFile set_MappedDataFile[1..2],
MappedImage set_MappedImage[2..3],
MappedPageFile set_MappedPageFile[3..4],
MappedPhysical set_MappedPhysical[4..5],
DirectMapped set_DirectMapped[5..6],
SoftwareEnclave set_SoftwareEnclave[6..7],
PageSize64K set_PageSize64K[7..8],
PlaceholderReservation set_PlaceholderReservation[8..9],
Reserved set_Reserved[9..32],
]}
pub type PMEMORY_REGION_INFORMATION = *mut MEMORY_REGION_INFORMATION;
ENUM!{enum MEMORY_WORKING_SET_EX_LOCATION {
MemoryLocationInvalid = 0,
MemoryLocationResident = 1,
MemoryLocationPagefile = 2,
MemoryLocationReserved = 3,
}}
UNION!{union MEMORY_WORKING_SET_EX_BLOCK_u {
Bitfields: ULONG_PTR,
Invalid: ULONG_PTR,
}}
STRUCT!{struct MEMORY_WORKING_SET_EX_BLOCK {
u: MEMORY_WORKING_SET_EX_BLOCK_u,
}}
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
BITFIELD!{unsafe MEMORY_WORKING_SET_EX_BLOCK_u Bitfields: ULONG_PTR [
Valid set_Valid[0..1],
ShareCount set_ShareCount[1..4],
Win32Protection set_Win32Protection[4..15],
Shared set_Shared[15..16],
Node set_Node[16..22],
Locked set_Locked[22..23],
LargePage set_LargePage[23..24],
Priority set_Priority[24..27],
Reserved set_Reserved[27..30],
SharedOriginal set_SharedOriginal[30..31],
Bad set_Bad[31..32],
ReservedUlong set_ReservedUlong[32..64],
]}
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
BITFIELD!{unsafe MEMORY_WORKING_SET_EX_BLOCK_u Invalid: ULONG_PTR [
Invalid_Valid set_Invalid_Valid[0..1],
Invalid_Reserved0 set_Invalid_Reserved0[1..15],
Invalid_Shared set_Invalid_Shared[15..16],
Invalid_Reserved1 set_Invalid_Reserved1[16..21],
Invalid_PageTable set_Invalid_PageTable[21..22],
Invalid_Location set_Invalid_Location[22..24],
Invalid_Priority set_Invalid_Priority[24..27],
Invalid_ModifiedList set_Invalid_ModifiedList[27..28],
Invalid_Reserved2 set_Invalid_Reserved2[28..30],
Invalid_SharedOriginal set_Invalid_SharedOriginal[30..31],
Invalid_Bad set_Invalid_Bad[31..32],
Invalid_ReservedUlong set_Invalid_ReservedUlong[32..64],
]}
#[cfg(target_arch = "x86")]
BITFIELD!{unsafe MEMORY_WORKING_SET_EX_BLOCK_u Bitfields: ULONG_PTR [
Valid set_Valid[0..1],
ShareCount set_ShareCount[1..4],
Win32Protection set_Win32Protection[4..15],
Shared set_Shared[15..16],
Node set_Node[16..22],
Locked set_Locked[22..23],
LargePage set_LargePage[23..24],
Priority set_Priority[24..27],
Reserved set_Reserved[27..30],
SharedOriginal set_SharedOriginal[30..31],
Bad set_Bad[31..32],
]}
#[cfg(target_arch = "x86")]
BITFIELD!{unsafe MEMORY_WORKING_SET_EX_BLOCK_u Invalid: ULONG_PTR [
Invalid_Valid set_Invalid_Valid[0..1],
Invalid_Reserved0 set_Invalid_Reserved0[1..15],
Invalid_Shared set_Invalid_Shared[15..16],
Invalid_Reserved1 set_Invalid_Reserved1[16..21],
Invalid_PageTable set_Invalid_PageTable[21..22],
Invalid_Location set_Invalid_Location[22..24],
Invalid_Priority set_Invalid_Priority[24..27],
Invalid_ModifiedList set_Invalid_ModifiedList[27..28],
Invalid_Reserved2 set_Invalid_Reserved2[28..30],
Invalid_SharedOriginal set_Invalid_SharedOriginal[30..31],
Invalid_Bad set_Invalid_Bad[31..32],
]}
pub type PMEMORY_WORKING_SET_EX_BLOCK = *mut MEMORY_WORKING_SET_EX_BLOCK;
STRUCT!{struct MEMORY_WORKING_SET_EX_INFORMATION {
VirtualAddress: PVOID,
VirtualAttributes: MEMORY_WORKING_SET_EX_BLOCK,
}}
pub type PMEMORY_WORKING_SET_EX_INFORMATION = *mut MEMORY_WORKING_SET_EX_INFORMATION;
STRUCT!{struct MEMORY_SHARED_COMMIT_INFORMATION {
CommitSize: SIZE_T,
}}
pub type PMEMORY_SHARED_COMMIT_INFORMATION = *mut MEMORY_SHARED_COMMIT_INFORMATION;
STRUCT!{struct MEMORY_IMAGE_INFORMATION {
ImageBase: PVOID,
SizeOfImage: SIZE_T,
ImageFlags: ULONG,
}}
BITFIELD!{MEMORY_IMAGE_INFORMATION ImageFlags: ULONG [
ImagePartialMap set_ImagePartialMap[0..1],
ImageNotExecutable set_ImageNotExecutable[1..2],
ImageSigningLevel set_ImageSigningLevel[2..6],
Reserved set_Reserved[6..32],
]}
pub type PMEMORY_IMAGE_INFORMATION = *mut MEMORY_IMAGE_INFORMATION;
STRUCT!{struct MEMORY_ENCLAVE_IMAGE_INFORMATION {
ImageInfo: MEMORY_IMAGE_INFORMATION,
UniqueID: [UCHAR; 32],
AuthorID: [UCHAR; 32],
}}
pub type PMEMORY_ENCLAVE_IMAGE_INFORMATION = *mut MEMORY_ENCLAVE_IMAGE_INFORMATION;
pub const MMPFNLIST_ZERO: u32 = 0;
pub const MMPFNLIST_FREE: u32 = 1;
pub const MMPFNLIST_STANDBY: u32 = 2;
pub const MMPFNLIST_MODIFIED: u32 = 3;
pub const MMPFNLIST_MODIFIEDNOWRITE: u32 = 4;
pub const MMPFNLIST_BAD: u32 = 5;
pub const MMPFNLIST_ACTIVE: u32 = 6;
pub const MMPFNLIST_TRANSITION: u32 = 7;
pub const MMPFNUSE_PROCESSPRIVATE: u32 = 0;
pub const MMPFNUSE_FILE: u32 = 1;
pub const MMPFNUSE_PAGEFILEMAPPED: u32 = 2;
pub const MMPFNUSE_PAGETABLE: u32 = 3;
pub const MMPFNUSE_PAGEDPOOL: u32 = 4;
pub const MMPFNUSE_NONPAGEDPOOL: u32 = 5;
pub const MMPFNUSE_SYSTEMPTE: u32 = 6;
pub const MMPFNUSE_SESSIONPRIVATE: u32 = 7;
pub const MMPFNUSE_METAFILE: u32 = 8;
pub const MMPFNUSE_AWEPAGE: u32 = 9;
pub const MMPFNUSE_DRIVERLOCKPAGE: u32 = 10;
pub const MMPFNUSE_KERNELSTACK: u32 = 11;
STRUCT!{struct MEMORY_FRAME_INFORMATION {
Bitfields: ULONGLONG,
}}
BITFIELD!{MEMORY_FRAME_INFORMATION Bitfields: ULONGLONG [
UseDescription set_UseDescription[0..4],
ListDescription set_ListDescription[4..7],
Reserved0 set_Reserved0[7..8],
Pinned set_Pinned[8..9],
DontUse set_DontUse[9..57],
Priority set_Priority[57..60],
Reserved set_Reserved[60..64],
]}
STRUCT!{struct FILEOFFSET_INFORMATION {
Bitfields: ULONGLONG,
}}
BITFIELD!{FILEOFFSET_INFORMATION Bitfields: ULONGLONG [
DontUse set_DontUse[0..9],
Offset set_Offset[9..57],
Reserved set_Reserved[57..64],
]}
STRUCT!{struct PAGEDIR_INFORMATION {
Bitfields: ULONGLONG,
}}
BITFIELD!{PAGEDIR_INFORMATION Bitfields: ULONGLONG [
DontUse set_DontUse[0..9],
PageDirectoryBase set_PageDirectoryBase[9..57],
Reserved set_Reserved[57..64],
]}
STRUCT!{struct UNIQUE_PROCESS_INFORMATION {
Bitfields: ULONGLONG,
}}
BITFIELD!{UNIQUE_PROCESS_INFORMATION Bitfields: ULONGLONG [
DontUse set_DontUse[0..9],
UniqueProcessKey set_UniqueProcessKey[9..57],
Reserved set_Reserved[57..64],
]}
pub type PUNIQUE_PROCESS_INFORMATION = *mut UNIQUE_PROCESS_INFORMATION;
UNION!{union MMPFN_IDENTITY_u1 {
e1: MEMORY_FRAME_INFORMATION,
e2: FILEOFFSET_INFORMATION,
e3: PAGEDIR_INFORMATION,
e4: UNIQUE_PROCESS_INFORMATION,
}}
UNION!{union MMPFN_IDENTITY_u2 {
e1: ULONG_PTR,
e2_CombinedPage: ULONG_PTR,
FileObject: ULONG_PTR,
UniqueFileObjectKey: ULONG_PTR,
ProtoPteAddress: ULONG_PTR,
VirtualAddress: ULONG_PTR,
}}
STRUCT!{struct MMPFN_IDENTITY {
u1: MMPFN_IDENTITY_u1,
PageFrameIndex: ULONG_PTR,
u2: MMPFN_IDENTITY_u2,
}}
BITFIELD!{unsafe MMPFN_IDENTITY_u2 e1: ULONG_PTR [
Image set_Image[0..1],
Mismatch set_Mismatch[1..2],
]}
pub type PMMPFN_IDENTITY = *mut MMPFN_IDENTITY;
STRUCT!{struct MMPFN_MEMSNAP_INFORMATION {
InitialPageFrameIndex: ULONG_PTR,
Count: ULONG_PTR,
}}
pub type PMMPFN_MEMSNAP_INFORMATION = *mut MMPFN_MEMSNAP_INFORMATION;
ENUM!{enum SECTION_INFORMATION_CLASS {
SectionBasicInformation = 0,
SectionImageInformation = 1,
SectionRelocationInformation = 2,
SectionOriginalBaseInformation = 3,
SectionInternalImageInformation = 4,
MaxSectionInfoClass = 5,
}}
STRUCT!{struct SECTION_BASIC_INFORMATION {
BaseAddress: PVOID,
AllocationAttributes: ULONG,
MaximumSize: LARGE_INTEGER,
}}
pub type PSECTION_BASIC_INFORMATION = *mut SECTION_BASIC_INFORMATION;
STRUCT!{struct SECTION_IMAGE_INFORMATION_u1_s {
SubSystemMinorVersion: USHORT,
SubSystemMajorVersion: USHORT,
}}
UNION!{union SECTION_IMAGE_INFORMATION_u1 {
s: SECTION_IMAGE_INFORMATION_u1_s,
SubSystemVersion: ULONG,
}}
STRUCT!{struct SECTION_IMAGE_INFORMATION_u2_s {
MajorOperatingSystemVersion: USHORT,
MinorOperatingSystemVersion: USHORT,
}}
UNION!{union SECTION_IMAGE_INFORMATION_u2 {
s: SECTION_IMAGE_INFORMATION_u2_s,
OperatingSystemVersion: ULONG,
}}
STRUCT!{struct SECTION_IMAGE_INFORMATION {
TransferAddress: PVOID,
ZeroBits: ULONG,
MaximumStackSize: SIZE_T,
CommittedStackSize: SIZE_T,
SubSystemType: ULONG,
u1: SECTION_IMAGE_INFORMATION_u1,
u2: SECTION_IMAGE_INFORMATION_u2,
ImageCharacteristics: USHORT,
DllCharacteristics: USHORT,
Machine: USHORT,
ImageContainsCode: BOOLEAN,
ImageFlags: UCHAR,
LoaderFlags: ULONG,
ImageFileSize: ULONG,
CheckSum: ULONG,
}}
BITFIELD!{SECTION_IMAGE_INFORMATION ImageFlags: UCHAR [
ComPlusNativeReady set_ComPlusNativeReady[0..1],
ComPlusILOnly set_ComPlusILOnly[1..2],
ImageDynamicallyRelocated set_ImageDynamicallyRelocated[2..3],
ImageMappedFlat set_ImageMappedFlat[3..4],
BaseBelow4gb set_BaseBelow4gb[4..5],
ComPlusPrefer32bit set_ComPlusPrefer32bit[5..6],
Reserved set_Reserved[6..8],
]}
pub type PSECTION_IMAGE_INFORMATION = *mut SECTION_IMAGE_INFORMATION;
STRUCT!{struct SECTION_INTERNAL_IMAGE_INFORMATION {
SectionInformation: SECTION_IMAGE_INFORMATION,
ExtendedFlags: ULONG,
}}
BITFIELD!{SECTION_INTERNAL_IMAGE_INFORMATION ExtendedFlags: ULONG [
ImageExportSuppressionEnabled set_ImageExportSuppressionEnabled[0..1],
Reserved set_Reserved[1..32],
]}
pub type PSECTION_INTERNAL_IMAGE_INFORMATION = *mut SECTION_INTERNAL_IMAGE_INFORMATION;
ENUM!{enum SECTION_INHERIT {
ViewShare = 1,
ViewUnmap = 2,
}}
pub const SEC_BASED: u32 = 0x200000;
pub const SEC_NO_CHANGE: u32 = 0x400000;
pub const SEC_GLOBAL: u32 = 0x20000000;
pub const MEM_EXECUTE_OPTION_DISABLE: u32 = 0x1;
pub const MEM_EXECUTE_OPTION_ENABLE: u32 = 0x2;
pub const MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION: u32 = 0x4;
pub const MEM_EXECUTE_OPTION_PERMANENT: u32 = 0x8;
pub const MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE: u32 = 0x10;
pub const MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE: u32 = 0x20;
pub const MEM_EXECUTE_OPTION_VALID_FLAGS: u32 = 0x3f;
EXTERN!{extern "system" {
fn NtAllocateVirtualMemory(
ProcessHandle: HANDLE,
BaseAddress: *mut PVOID,
ZeroBits: ULONG_PTR,
RegionSize: PSIZE_T,
AllocationType: ULONG,
Protect: ULONG,
) -> NTSTATUS;
fn NtFreeVirtualMemory(
ProcessHandle: HANDLE,
BaseAddress: *mut PVOID,
RegionSize: PSIZE_T,
FreeType: ULONG,
) -> NTSTATUS;
fn NtReadVirtualMemory(
ProcessHandle: HANDLE,
BaseAddress: PVOID,
Buffer: PVOID,
BufferSize: SIZE_T,
NumberOfBytesRead: PSIZE_T,
) -> NTSTATUS;
fn NtWriteVirtualMemory(
ProcessHandle: HANDLE,
BaseAddress: PVOID,
Buffer: PVOID,
BufferSize: SIZE_T,
NumberOfBytesWritten: PSIZE_T,
) -> NTSTATUS;
fn NtProtectVirtualMemory(
ProcessHandle: HANDLE,
BaseAddress: *mut PVOID,
RegionSize: PSIZE_T,
NewProtect: ULONG,
OldProtect: PULONG,
) -> NTSTATUS;
fn NtQueryVirtualMemory(
ProcessHandle: HANDLE,
BaseAddress: PVOID,
MemoryInformationClass: MEMORY_INFORMATION_CLASS,
MemoryInformation: PVOID,
MemoryInformationLength: SIZE_T,
ReturnLength: PSIZE_T,
) -> NTSTATUS;
}}
ENUM!{enum VIRTUAL_MEMORY_INFORMATION_CLASS {
VmPrefetchInformation = 0,
VmPagePriorityInformation = 1,
VmCfgCallTargetInformation = 2,
VmPageDirtyStateInformation = 3,
}}
STRUCT!{struct MEMORY_RANGE_ENTRY {
VirtualAddress: PVOID,
NumberOfBytes: SIZE_T,
}}
pub type PMEMORY_RANGE_ENTRY = *mut MEMORY_RANGE_ENTRY;
STRUCT!{struct CFG_CALL_TARGET_LIST_INFORMATION {
NumberOfEntries: ULONG,
Reserved: ULONG,
NumberOfEntriesProcessed: PULONG,
CallTargetInfo: PCFG_CALL_TARGET_INFO,
Section: PVOID,
FileOffset: ULONGLONG,
}}
pub type PCFG_CALL_TARGET_LIST_INFORMATION = *mut CFG_CALL_TARGET_LIST_INFORMATION;
EXTERN!{extern "system" {
fn NtSetInformationVirtualMemory(
ProcessHandle: HANDLE,
VmInformationClass: VIRTUAL_MEMORY_INFORMATION_CLASS,
NumberOfEntries: ULONG_PTR,
VirtualAddresses: PMEMORY_RANGE_ENTRY,
VmInformation: PVOID,
VmInformationLength: ULONG,
) -> NTSTATUS;
fn NtLockVirtualMemory(
ProcessHandle: HANDLE,
BaseAddress: *mut PVOID,
RegionSize: PSIZE_T,
MapType: ULONG,
) -> NTSTATUS;
fn NtUnlockVirtualMemory(
ProcessHandle: HANDLE,
BaseAddress: *mut PVOID,
RegionSize: PSIZE_T,
MapType: ULONG,
) -> NTSTATUS;
fn NtCreateSection(
SectionHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
MaximumSize: PLARGE_INTEGER,
SectionPageProtection: ULONG,
AllocationAttributes: ULONG,
FileHandle: HANDLE,
) -> NTSTATUS;
fn NtCreateSectionEx(
SectionHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
MaximumSize: PLARGE_INTEGER,
SectionPageProtection: ULONG,
AllocationAttributes: ULONG,
FileHandle: HANDLE,
ExtendedParameters: PMEM_EXTENDED_PARAMETER,
ExtendedParameterCount: ULONG,
) -> NTSTATUS;
fn NtOpenSection(
SectionHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtMapViewOfSection(
SectionHandle: HANDLE,
ProcessHandle: HANDLE,
BaseAddress: *mut PVOID,
ZeroBits: ULONG_PTR,
CommitSize: SIZE_T,
SectionOffset: PLARGE_INTEGER,
ViewSize: PSIZE_T,
InheritDisposition: SECTION_INHERIT,
AllocationType: ULONG,
Win32Protect: ULONG,
) -> NTSTATUS;
fn NtUnmapViewOfSection(
ProcessHandle: HANDLE,
BaseAddress: PVOID,
) -> NTSTATUS;
fn NtUnmapViewOfSectionEx(
ProcessHandle: HANDLE,
BaseAddress: PVOID,
Flags: ULONG,
) -> NTSTATUS;
fn NtExtendSection(
SectionHandle: HANDLE,
NewSectionSize: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtQuerySection(
SectionHandle: HANDLE,
SectionInformationClass: SECTION_INFORMATION_CLASS,
SectionInformation: PVOID,
SectionInformationLength: SIZE_T,
ReturnLength: PSIZE_T,
) -> NTSTATUS;
fn NtAreMappedFilesTheSame(
File1MappedAsAnImage: PVOID,
File2MappedAsFile: PVOID,
) -> NTSTATUS;
}}
pub const MEMORY_PARTITION_QUERY_ACCESS: u32 = 0x0001;
pub const MEMORY_PARTITION_MODIFY_ACCESS: u32 = 0x0002;
pub const MEMORY_PARTITION_ALL_ACCESS: u32 = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE
| MEMORY_PARTITION_QUERY_ACCESS | MEMORY_PARTITION_MODIFY_ACCESS;
ENUM!{enum MEMORY_PARTITION_INFORMATION_CLASS {
SystemMemoryPartitionInformation = 0,
SystemMemoryPartitionMoveMemory = 1,
SystemMemoryPartitionAddPagefile = 2,
SystemMemoryPartitionCombineMemory = 3,
SystemMemoryPartitionInitialAddMemory = 4,
SystemMemoryPartitionGetMemoryEvents = 5,
SystemMemoryPartitionMax = 6,
}}
STRUCT!{struct MEMORY_PARTITION_CONFIGURATION_INFORMATION {
Flags: ULONG,
NumaNode: ULONG,
Channel: ULONG,
NumberOfNumaNodes: ULONG,
ResidentAvailablePages: ULONG_PTR,
CommittedPages: ULONG_PTR,
CommitLimit: ULONG_PTR,
PeakCommitment: ULONG_PTR,
TotalNumberOfPages: ULONG_PTR,
AvailablePages: ULONG_PTR,
ZeroPages: ULONG_PTR,
FreePages: ULONG_PTR,
StandbyPages: ULONG_PTR,
StandbyPageCountByPriority: [ULONG_PTR; 8],
RepurposedPagesByPriority: [ULONG_PTR; 8],
MaximumCommitLimit: ULONG_PTR,
DonatedPagesToPartitions: ULONG_PTR,
PartitionId: ULONG,
}}
pub type PMEMORY_PARTITION_CONFIGURATION_INFORMATION =
*mut MEMORY_PARTITION_CONFIGURATION_INFORMATION;
STRUCT!{struct MEMORY_PARTITION_TRANSFER_INFORMATION {
NumberOfPages: ULONG_PTR,
NumaNode: ULONG,
Flags: ULONG,
}}
pub type PMEMORY_PARTITION_TRANSFER_INFORMATION = *mut MEMORY_PARTITION_TRANSFER_INFORMATION;
STRUCT!{struct MEMORY_PARTITION_PAGEFILE_INFORMATION {
PageFileName: UNICODE_STRING,
MinimumSize: LARGE_INTEGER,
MaximumSize: LARGE_INTEGER,
Flags: ULONG,
}}
pub type PMEMORY_PARTITION_PAGEFILE_INFORMATION = *mut MEMORY_PARTITION_PAGEFILE_INFORMATION;
STRUCT!{struct MEMORY_PARTITION_PAGE_COMBINE_INFORMATION {
StopHandle: HANDLE,
Flags: ULONG,
TotalNumberOfPages: ULONG_PTR,
}}
pub type PMEMORY_PARTITION_PAGE_COMBINE_INFORMATION =
*mut MEMORY_PARTITION_PAGE_COMBINE_INFORMATION;
STRUCT!{struct MEMORY_PARTITION_PAGE_RANGE {
StartPage: ULONG_PTR,
NumberOfPages: ULONG_PTR,
}}
pub type PMEMORY_PARTITION_PAGE_RANGE = *mut MEMORY_PARTITION_PAGE_RANGE;
STRUCT!{struct MEMORY_PARTITION_INITIAL_ADD_INFORMATION {
Flags: ULONG,
NumberOfRanges: ULONG,
NumberOfPagesAdded: ULONG_PTR,
PartitionRanges: [MEMORY_PARTITION_PAGE_RANGE; 1],
}}
pub type PMEMORY_PARTITION_INITIAL_ADD_INFORMATION = *mut MEMORY_PARTITION_INITIAL_ADD_INFORMATION;
STRUCT!{struct MEMORY_PARTITION_MEMORY_EVENTS_INFORMATION {
Flags: ULONG,
HandleAttributes: ULONG,
DesiredAccess: ULONG,
LowCommitCondition: HANDLE,
HighCommitCondition: HANDLE,
MaximumCommitCondition: HANDLE,
}}
BITFIELD!{MEMORY_PARTITION_MEMORY_EVENTS_INFORMATION Flags: ULONG [
CommitEvents set_CommitEvents[0..1],
Spare set_Spare[1..32],
]}
pub type PMEMORY_PARTITION_MEMORY_EVENTS_INFORMATION =
*mut MEMORY_PARTITION_MEMORY_EVENTS_INFORMATION;
EXTERN!{extern "system" {
fn NtCreatePartition(
PartitionHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
PreferredNode: ULONG,
) -> NTSTATUS;
fn NtOpenPartition(
PartitionHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtManagePartition(
PartitionInformationClass: MEMORY_PARTITION_INFORMATION_CLASS,
PartitionInformation: PVOID,
PartitionInformationLength: ULONG,
) -> NTSTATUS;
fn NtMapUserPhysicalPages(
VirtualAddress: PVOID,
NumberOfPages: ULONG_PTR,
UserPfnArray: PULONG_PTR,
) -> NTSTATUS;
fn NtMapUserPhysicalPagesScatter(
VirtualAddresses: *mut PVOID,
NumberOfPages: ULONG_PTR,
UserPfnArray: PULONG_PTR,
) -> NTSTATUS;
fn NtAllocateUserPhysicalPages(
ProcessHandle: HANDLE,
NumberOfPages: PULONG_PTR,
UserPfnArray: PULONG_PTR,
) -> NTSTATUS;
fn NtFreeUserPhysicalPages(
ProcessHandle: HANDLE,
NumberOfPages: PULONG_PTR,
UserPfnArray: PULONG_PTR,
) -> NTSTATUS;
fn NtOpenSession(
SessionHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtGetWriteWatch(
ProcessHandle: HANDLE,
Flags: ULONG,
BaseAddress: PVOID,
RegionSize: SIZE_T,
UserAddressArray: *mut PVOID,
EntriesInUserAddressArray: PULONG_PTR,
Granularity: PULONG,
) -> NTSTATUS;
fn NtResetWriteWatch(
ProcessHandle: HANDLE,
BaseAddress: PVOID,
RegionSize: SIZE_T,
) -> NTSTATUS;
fn NtCreatePagingFile(
PageFileName: PUNICODE_STRING,
MinimumSize: PLARGE_INTEGER,
MaximumSize: PLARGE_INTEGER,
Priority: ULONG,
) -> NTSTATUS;
fn NtFlushInstructionCache(
ProcessHandle: HANDLE,
BaseAddress: PVOID,
Length: SIZE_T,
) -> NTSTATUS;
fn NtFlushWriteBuffer() -> NTSTATUS;
}}

View file

@ -1,29 +0,0 @@
use winapi::shared::ntdef::{BOOLEAN, PUSHORT, PVOID, UCHAR, USHORT};
pub const MAXIMUM_LEADBYTES: usize = 12;
STRUCT!{struct CPTABLEINFO {
CodePage: USHORT,
MaximumCharacterSize: USHORT,
DefaultChar: USHORT,
UniDefaultChar: USHORT,
TransDefaultChar: USHORT,
TransUniDefaultChar: USHORT,
DBCSCodePage: USHORT,
LeadByte: [UCHAR; MAXIMUM_LEADBYTES],
MultiByteTable: PUSHORT,
WideCharTable: PVOID,
DBCSRanges: PUSHORT,
DBCSOffsets: PUSHORT,
}}
pub type PCPTABLEINFO = *mut CPTABLEINFO;
STRUCT!{struct NLSTABLEINFO {
OemTableInfo: CPTABLEINFO,
AnsiTableInfo: CPTABLEINFO,
UpperCaseTable: PUSHORT,
LowerCaseTable: PUSHORT,
}}
pub type PNLSTABLEINFO = *mut NLSTABLEINFO;
EXTERN!{extern "C" {
static mut NlsAnsiCodePage: USHORT;
static mut NlsMbCodePageTag: BOOLEAN;
static mut NlsMbOemCodePageTag: BOOLEAN;
}}

View file

@ -1,226 +0,0 @@
use winapi::shared::ntdef::{
BOOLEAN, CHAR, HANDLE, LARGE_INTEGER, LONG, NTSTATUS, PHANDLE, PLARGE_INTEGER,
POBJECT_ATTRIBUTES, PULONG, PUNICODE_STRING, PVOID, UCHAR, ULONG, UNICODE_STRING, WAIT_TYPE,
};
use winapi::um::winnt::{
ACCESS_MASK, GENERIC_MAPPING, PSECURITY_DESCRIPTOR, SECURITY_INFORMATION,
STANDARD_RIGHTS_REQUIRED,
};
pub const OBJECT_TYPE_CREATE: u32 = 0x0001;
pub const OBJECT_TYPE_ALL_ACCESS: ACCESS_MASK = STANDARD_RIGHTS_REQUIRED | 0x1;
pub const DIRECTORY_QUERY: u32 = 0x0001;
pub const DIRECTORY_TRAVERSE: u32 = 0x0002;
pub const DIRECTORY_CREATE_OBJECT: u32 = 0x0004;
pub const DIRECTORY_CREATE_SUBDIRECTORY: u32 = 0x0008;
pub const DIRECTORY_ALL_ACCESS: ACCESS_MASK = STANDARD_RIGHTS_REQUIRED | 0xf;
pub const SYMBOLIC_LINK_QUERY: u32 = 0x0001;
pub const SYMBOLIC_LINK_ALL_ACCESS: ACCESS_MASK = STANDARD_RIGHTS_REQUIRED | 0x1;
pub const OBJ_PROTECT_CLOSE: u32 = 0x00000001;
pub const OBJ_INHERIT: u32 = 0x00000002;
pub const OBJ_AUDIT_OBJECT_CLOSE: u32 = 0x00000004;
ENUM!{enum OBJECT_INFORMATION_CLASS {
ObjectBasicInformation = 0,
ObjectNameInformation = 1,
ObjectTypeInformation = 2,
ObjectTypesInformation = 3,
ObjectHandleFlagInformation = 4,
ObjectSessionInformation = 5,
ObjectSessionObjectInformation = 6,
MaxObjectInfoClass = 7,
}}
STRUCT!{struct OBJECT_BASIC_INFORMATION {
Attributes: ULONG,
GrantedAccess: ACCESS_MASK,
HandleCount: ULONG,
PointerCount: ULONG,
PagedPoolCharge: ULONG,
NonPagedPoolCharge: ULONG,
Reserved: [ULONG; 3],
NameInfoSize: ULONG,
TypeInfoSize: ULONG,
SecurityDescriptorSize: ULONG,
CreationTime: LARGE_INTEGER,
}}
pub type POBJECT_BASIC_INFORMATION = *mut OBJECT_BASIC_INFORMATION;
STRUCT!{struct OBJECT_NAME_INFORMATION {
Name: UNICODE_STRING,
}}
pub type POBJECT_NAME_INFORMATION = *mut OBJECT_NAME_INFORMATION;
STRUCT!{struct OBJECT_TYPE_INFORMATION {
TypeName: UNICODE_STRING,
TotalNumberOfObjects: ULONG,
TotalNumberOfHandles: ULONG,
TotalPagedPoolUsage: ULONG,
TotalNonPagedPoolUsage: ULONG,
TotalNamePoolUsage: ULONG,
TotalHandleTableUsage: ULONG,
HighWaterNumberOfObjects: ULONG,
HighWaterNumberOfHandles: ULONG,
HighWaterPagedPoolUsage: ULONG,
HighWaterNonPagedPoolUsage: ULONG,
HighWaterNamePoolUsage: ULONG,
HighWaterHandleTableUsage: ULONG,
InvalidAttributes: ULONG,
GenericMapping: GENERIC_MAPPING,
ValidAccessMask: ULONG,
SecurityRequired: BOOLEAN,
MaintainHandleCount: BOOLEAN,
TypeIndex: UCHAR,
ReservedByte: CHAR,
PoolType: ULONG,
DefaultPagedPoolCharge: ULONG,
DefaultNonPagedPoolCharge: ULONG,
}}
pub type POBJECT_TYPE_INFORMATION = *mut OBJECT_TYPE_INFORMATION;
STRUCT!{struct OBJECT_TYPES_INFORMATION {
NumberOfTypes: ULONG,
}}
pub type POBJECT_TYPES_INFORMATION = *mut OBJECT_TYPES_INFORMATION;
STRUCT!{struct OBJECT_HANDLE_FLAG_INFORMATION {
Inherit: BOOLEAN,
ProtectFromClose: BOOLEAN,
}}
pub type POBJECT_HANDLE_FLAG_INFORMATION = *mut OBJECT_HANDLE_FLAG_INFORMATION;
EXTERN!{extern "system" {
fn NtQueryObject(
Handle: HANDLE,
ObjectInformationClass: OBJECT_INFORMATION_CLASS,
ObjectInformation: PVOID,
ObjectInformationLength: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtSetInformationObject(
Handle: HANDLE,
ObjectInformationClass: OBJECT_INFORMATION_CLASS,
ObjectInformation: PVOID,
ObjectInformationLength: ULONG,
) -> NTSTATUS;
}}
pub const DUPLICATE_CLOSE_SOURCE: u32 = 0x00000001;
pub const DUPLICATE_SAME_ACCESS: u32 = 0x00000002;
pub const DUPLICATE_SAME_ATTRIBUTES: u32 = 0x00000004;
EXTERN!{extern "system" {
fn NtDuplicateObject(
SourceProcessHandle: HANDLE,
SourceHandle: HANDLE,
TargetProcessHandle: HANDLE,
TargetHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
HandleAttributes: ULONG,
Options: ULONG,
) -> NTSTATUS;
fn NtMakeTemporaryObject(
Handle: HANDLE,
) -> NTSTATUS;
fn NtMakePermanentObject(
Handle: HANDLE,
) -> NTSTATUS;
fn NtSignalAndWaitForSingleObject(
SignalHandle: HANDLE,
WaitHandle: HANDLE,
Alertable: BOOLEAN,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtWaitForSingleObject(
Handle: HANDLE,
Alertable: BOOLEAN,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtWaitForMultipleObjects(
Count: ULONG,
Handles: *mut HANDLE,
WaitType: WAIT_TYPE,
Alertable: BOOLEAN,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtWaitForMultipleObjects32(
Count: ULONG,
Handles: *mut LONG,
WaitType: WAIT_TYPE,
Alertable: BOOLEAN,
Timeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtSetSecurityObject(
Handle: HANDLE,
SecurityInformation: SECURITY_INFORMATION,
SecurityDescriptor: PSECURITY_DESCRIPTOR,
) -> NTSTATUS;
fn NtQuerySecurityObject(
Handle: HANDLE,
SecurityInformation: SECURITY_INFORMATION,
SecurityDescriptor: PSECURITY_DESCRIPTOR,
Length: ULONG,
LengthNeeded: PULONG,
) -> NTSTATUS;
fn NtClose(
Handle: HANDLE,
) -> NTSTATUS;
fn NtCompareObjects(
FirstObjectHandle: HANDLE,
SecondObjectHandle: HANDLE,
) -> NTSTATUS;
fn NtCreateDirectoryObject(
DirectoryHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtCreateDirectoryObjectEx(
DirectoryHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
ShadowDirectoryHandle: HANDLE,
Flags: ULONG,
) -> NTSTATUS;
fn NtOpenDirectoryObject(
DirectoryHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
}}
STRUCT!{struct OBJECT_DIRECTORY_INFORMATION {
Name: UNICODE_STRING,
TypeName: UNICODE_STRING,
}}
pub type POBJECT_DIRECTORY_INFORMATION = *mut OBJECT_DIRECTORY_INFORMATION;
EXTERN!{extern "system" {
fn NtQueryDirectoryObject(
DirectoryHandle: HANDLE,
Buffer: PVOID,
Length: ULONG,
ReturnSingleEntry: BOOLEAN,
RestartScan: BOOLEAN,
Context: PULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtCreatePrivateNamespace(
NamespaceHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
BoundaryDescriptor: PVOID,
) -> NTSTATUS;
fn NtOpenPrivateNamespace(
NamespaceHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
BoundaryDescriptor: PVOID,
) -> NTSTATUS;
fn NtDeletePrivateNamespace(
NamespaceHandle: HANDLE,
) -> NTSTATUS;
fn NtCreateSymbolicLinkObject(
LinkHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
LinkTarget: PUNICODE_STRING,
) -> NTSTATUS;
fn NtOpenSymbolicLinkObject(
LinkHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtQuerySymbolicLinkObject(
LinkHandle: HANDLE,
LinkTarget: PUNICODE_STRING,
ReturnedLength: PULONG,
) -> NTSTATUS;
}}

View file

@ -1,431 +0,0 @@
use core::mem::size_of;
use crate::ntapi_base::CLIENT_ID;
use crate::ntpsapi::{GDI_HANDLE_BUFFER, PPEB_LDR_DATA};
use crate::ntrtl::PRTL_USER_PROCESS_PARAMETERS;
use winapi::shared::basetsd::{SIZE_T, ULONG_PTR};
use winapi::shared::guiddef::GUID;
use winapi::shared::ntdef::{
BOOLEAN, CHAR, HANDLE, LCID, LIST_ENTRY, LONG, NTSTATUS, PROCESSOR_NUMBER, PSTR, PVOID, UCHAR,
ULARGE_INTEGER, ULONG, ULONGLONG, UNICODE_STRING, USHORT, WCHAR,
};
use winapi::um::winnt::{
ACTIVATION_CONTEXT, FLS_MAXIMUM_AVAILABLE, NT_TIB, PRTL_CRITICAL_SECTION, PSLIST_HEADER,
};
STRUCT!{struct RTL_ACTIVATION_CONTEXT_STACK_FRAME {
Previous: PRTL_ACTIVATION_CONTEXT_STACK_FRAME,
ActivationContext: *mut ACTIVATION_CONTEXT,
Flags: ULONG,
}}
pub type PRTL_ACTIVATION_CONTEXT_STACK_FRAME = *mut RTL_ACTIVATION_CONTEXT_STACK_FRAME;
STRUCT!{struct ACTIVATION_CONTEXT_STACK {
ActiveFrame: *mut RTL_ACTIVATION_CONTEXT_STACK_FRAME,
FrameListCache: LIST_ENTRY,
Flags: ULONG,
NextCookieSequenceNumber: ULONG,
StackId: ULONG,
}}
pub type PACTIVATION_CONTEXT_STACK = *mut ACTIVATION_CONTEXT_STACK;
STRUCT!{struct API_SET_NAMESPACE {
Version: ULONG,
Size: ULONG,
Flags: ULONG,
Count: ULONG,
EntryOffset: ULONG,
HashOffset: ULONG,
HashFactor: ULONG,
}}
pub type PAPI_SET_NAMESPACE = *mut API_SET_NAMESPACE;
STRUCT!{struct API_SET_HASH_ENTRY {
Hash: ULONG,
Index: ULONG,
}}
pub type PAPI_SET_HASH_ENTRY = *mut API_SET_HASH_ENTRY;
STRUCT!{struct API_SET_NAMESPACE_ENTRY {
Flags: ULONG,
NameOffset: ULONG,
NameLength: ULONG,
HashedLength: ULONG,
ValueOffset: ULONG,
ValueCount: ULONG,
}}
pub type PAPI_SET_NAMESPACE_ENTRY = *mut API_SET_NAMESPACE_ENTRY;
STRUCT!{struct API_SET_VALUE_ENTRY {
Flags: ULONG,
NameOffset: ULONG,
NameLength: ULONG,
ValueOffset: ULONG,
ValueLength: ULONG,
}}
pub type PAPI_SET_VALUE_ENTRY = *mut API_SET_VALUE_ENTRY;
UNION!{union PEB_u {
KernelCallbackTable: PVOID,
UserSharedInfoPtr: PVOID,
}}
#[repr(C)]
pub struct LEAP_SECOND_DATA([u8; 0]); //fixme
STRUCT!{struct PEB {
InheritedAddressSpace: BOOLEAN,
ReadImageFileExecOptions: BOOLEAN,
BeingDebugged: BOOLEAN,
BitField: BOOLEAN,
Mutant: HANDLE,
ImageBaseAddress: PVOID,
Ldr: PPEB_LDR_DATA,
ProcessParameters: PRTL_USER_PROCESS_PARAMETERS,
SubSystemData: PVOID,
ProcessHeap: PVOID,
FastPebLock: PRTL_CRITICAL_SECTION,
IFEOKey: PVOID,
AtlThunkSListPtr: PSLIST_HEADER,
CrossProcessFlags: ULONG,
u: PEB_u,
SystemReserved: [ULONG; 1],
AtlThunkSListPtr32: ULONG,
ApiSetMap: PAPI_SET_NAMESPACE,
TlsExpansionCounter: ULONG,
TlsBitmap: PVOID,
TlsBitmapBits: [ULONG; 2],
ReadOnlySharedMemoryBase: PVOID,
SharedData: PVOID,
ReadOnlyStaticServerData: *mut PVOID,
AnsiCodePageData: PVOID,
OemCodePageData: PVOID,
UnicodeCaseTableData: PVOID,
NumberOfProcessors: ULONG,
NtGlobalFlag: ULONG,
CriticalSectionTimeout: ULARGE_INTEGER,
HeapSegmentReserve: SIZE_T,
HeapSegmentCommit: SIZE_T,
HeapDeCommitTotalFreeThreshold: SIZE_T,
HeapDeCommitFreeBlockThreshold: SIZE_T,
NumberOfHeaps: ULONG,
MaximumNumberOfHeaps: ULONG,
ProcessHeaps: *mut PVOID,
GdiSharedHandleTable: PVOID,
ProcessStarterHelper: PVOID,
GdiDCAttributeList: ULONG,
LoaderLock: PRTL_CRITICAL_SECTION,
OSMajorVersion: ULONG,
OSMinorVersion: ULONG,
OSBuildNumber: USHORT,
OSCSDVersion: USHORT,
OSPlatformId: ULONG,
ImageSubsystem: ULONG,
ImageSubsystemMajorVersion: ULONG,
ImageSubsystemMinorVersion: ULONG,
ActiveProcessAffinityMask: ULONG_PTR,
GdiHandleBuffer: GDI_HANDLE_BUFFER,
PostProcessInitRoutine: PVOID,
TlsExpansionBitmap: PVOID,
TlsExpansionBitmapBits: [ULONG; 32],
SessionId: ULONG,
AppCompatFlags: ULARGE_INTEGER,
AppCompatFlagsUser: ULARGE_INTEGER,
pShimData: PVOID,
AppCompatInfo: PVOID,
CSDVersion: UNICODE_STRING,
ActivationContextData: PVOID,
ProcessAssemblyStorageMap: PVOID,
SystemDefaultActivationContextData: PVOID,
SystemAssemblyStorageMap: PVOID,
MinimumStackCommit: SIZE_T,
FlsCallback: *mut PVOID,
FlsListHead: LIST_ENTRY,
FlsBitmap: PVOID,
FlsBitmapBits: [ULONG; FLS_MAXIMUM_AVAILABLE as usize / (size_of::<ULONG>() * 8)],
FlsHighIndex: ULONG,
WerRegistrationData: PVOID,
WerShipAssertPtr: PVOID,
pUnused: PVOID,
pImageHeaderHash: PVOID,
TracingFlags: ULONG,
CsrServerReadOnlySharedMemoryBase: ULONGLONG,
TppWorkerpListLock: PRTL_CRITICAL_SECTION,
TppWorkerpList: LIST_ENTRY,
WaitOnAddressHashTable: [PVOID; 128],
TelemetryCoverageHeader: PVOID,
CloudFileFlags: ULONG,
CloudFileDiagFlags: ULONG,
PlaceholderCompatibilityMode: CHAR,
PlaceholderCompatibilityModeReserved: [CHAR; 7],
LeapSecondData: *mut LEAP_SECOND_DATA,
LeapSecondFlags: ULONG,
NtGlobalFlag2: ULONG,
}}
BITFIELD!{PEB BitField: BOOLEAN [
ImageUsesLargePages set_ImageUsesLargePages[0..1],
IsProtectedProcess set_IsProtectedProcess[1..2],
IsImageDynamicallyRelocated set_IsImageDynamicallyRelocated[2..3],
SkipPatchingUser32Forwarders set_SkipPatchingUser32Forwarders[3..4],
IsPackagedProcess set_IsPackagedProcess[4..5],
IsAppContainer set_IsAppContainer[5..6],
IsProtectedProcessLight set_IsProtectedProcessLight[6..7],
IsLongPathAwareProcess set_IsLongPathAwareProcess[7..8],
]}
BITFIELD!{PEB CrossProcessFlags: ULONG [
ProcessInJob set_ProcessInJob[0..1],
ProcessInitializing set_ProcessInitializing[1..2],
ProcessUsingVEH set_ProcessUsingVEH[2..3],
ProcessUsingVCH set_ProcessUsingVCH[3..4],
ProcessUsingFTH set_ProcessUsingFTH[4..5],
ProcessPreviouslyThrottled set_ProcessPreviouslyThrottled[5..6],
ProcessCurrentlyThrottled set_ProcessCurrentlyThrottled[6..7],
ProcessImagesHotPatched set_ProcessImagesHotPatched[7..8],
ReservedBits0 set_ReservedBits0[8..32],
]}
BITFIELD!{PEB TracingFlags: ULONG [
HeapTracingEnabled set_HeapTracingEnabled[0..1],
CritSecTracingEnabled set_CritSecTracingEnabled[1..2],
LibLoaderTracingEnabled set_LibLoaderTracingEnabled[2..3],
SpareTracingBits set_SpareTracingBits[3..32],
]}
BITFIELD!{PEB LeapSecondFlags: ULONG [
SixtySecondEnabled set_SixtySecondEnabled[0..1],
Reserved set_Reserved[1..32],
]}
pub type PPEB = *mut PEB;
pub const GDI_BATCH_BUFFER_SIZE: usize = 310;
STRUCT!{struct GDI_TEB_BATCH {
Offset: ULONG,
HDC: ULONG_PTR,
Buffer: [ULONG; GDI_BATCH_BUFFER_SIZE],
}}
pub type PGDI_TEB_BATCH = *mut GDI_TEB_BATCH;
STRUCT!{struct TEB_ACTIVE_FRAME_CONTEXT {
Flags: ULONG,
FrameName: PSTR,
}}
pub type PTEB_ACTIVE_FRAME_CONTEXT = *mut TEB_ACTIVE_FRAME_CONTEXT;
STRUCT!{struct TEB_ACTIVE_FRAME {
Flags: ULONG,
Previous: *mut TEB_ACTIVE_FRAME,
Context: PTEB_ACTIVE_FRAME_CONTEXT,
}}
pub type PTEB_ACTIVE_FRAME = *mut TEB_ACTIVE_FRAME;
STRUCT!{struct TEB_u_s {
ReservedPad0: UCHAR,
ReservedPad1: UCHAR,
ReservedPad2: UCHAR,
IdealProcessor: UCHAR,
}}
UNION!{union TEB_u {
CurrentIdealProcessor: PROCESSOR_NUMBER,
IdealProcessorValue: ULONG,
s: TEB_u_s,
}}
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
STRUCT!{struct TEB {
NtTib: NT_TIB,
EnvironmentPointer: PVOID,
ClientId: CLIENT_ID,
ActiveRpcHandle: PVOID,
ThreadLocalStoragePointer: PVOID,
ProcessEnvironmentBlock: PPEB,
LastErrorValue: ULONG,
CountOfOwnedCriticalSections: ULONG,
CsrClientThread: PVOID,
Win32ThreadInfo: PVOID,
User32Reserved: [ULONG; 26],
UserReserved: [ULONG; 5],
WOW32Reserved: PVOID,
CurrentLocale: LCID,
FpSoftwareStatusRegister: ULONG,
ReservedForDebuggerInstrumentation: [PVOID; 16],
SystemReserved1: [PVOID; 30],
PlaceholderCompatibilityMode: CHAR,
PlaceholderReserved: [CHAR; 11],
ProxiedProcessId: ULONG,
ActivationStack: ACTIVATION_CONTEXT_STACK,
WorkingOnBehalfTicket: [UCHAR; 8],
ExceptionCode: NTSTATUS,
ActivationContextStackPointer: PACTIVATION_CONTEXT_STACK,
InstrumentationCallbackSp: ULONG_PTR,
InstrumentationCallbackPreviousPc: ULONG_PTR,
InstrumentationCallbackPreviousSp: ULONG_PTR,
TxFsContext: ULONG,
InstrumentationCallbackDisabled: BOOLEAN,
GdiTebBatch: GDI_TEB_BATCH,
RealClientId: CLIENT_ID,
GdiCachedProcessHandle: HANDLE,
GdiClientPID: ULONG,
GdiClientTID: ULONG,
GdiThreadLocalInfo: PVOID,
Win32ClientInfo: [ULONG_PTR; 62],
glDispatchTable: [PVOID; 233],
glReserved1: [ULONG_PTR; 29],
glReserved2: PVOID,
glSectionInfo: PVOID,
glSection: PVOID,
glTable: PVOID,
glCurrentRC: PVOID,
glContext: PVOID,
LastStatusValue: NTSTATUS,
StaticUnicodeString: UNICODE_STRING,
StaticUnicodeBuffer: [WCHAR; 261],
DeallocationStack: PVOID,
TlsSlots: [PVOID; 64],
TlsLinks: LIST_ENTRY,
Vdm: PVOID,
ReservedForNtRpc: PVOID,
DbgSsReserved: [PVOID; 2],
HardErrorMode: ULONG,
Instrumentation: [PVOID; 11],
ActivityId: GUID,
SubProcessTag: PVOID,
PerflibData: PVOID,
EtwTraceData: PVOID,
WinSockData: PVOID,
GdiBatchCount: ULONG,
u: TEB_u,
GuaranteedStackBytes: ULONG,
ReservedForPerf: PVOID,
ReservedForOle: PVOID,
WaitingOnLoaderLock: ULONG,
SavedPriorityState: PVOID,
ReservedForCodeCoverage: ULONG_PTR,
ThreadPoolData: PVOID,
TlsExpansionSlots: *mut PVOID,
DeallocationBStore: PVOID,
BStoreLimit: PVOID,
MuiGeneration: ULONG,
IsImpersonating: ULONG,
NlsCache: PVOID,
pShimData: PVOID,
HeapVirtualAffinity: USHORT,
LowFragHeapDataSlot: USHORT,
CurrentTransactionHandle: HANDLE,
ActiveFrame: PTEB_ACTIVE_FRAME,
FlsData: PVOID,
PreferredLanguages: PVOID,
UserPrefLanguages: PVOID,
MergedPrefLanguages: PVOID,
MuiImpersonation: ULONG,
CrossTebFlags: USHORT,
SameTebFlags: USHORT,
TxnScopeEnterCallback: PVOID,
TxnScopeExitCallback: PVOID,
TxnScopeContext: PVOID,
LockCount: ULONG,
WowTebOffset: LONG,
ResourceRetValue: PVOID,
ReservedForWdf: PVOID,
ReservedForCrt: ULONGLONG,
EffectiveContainerId: GUID,
}}
#[cfg(target_arch = "x86")]
STRUCT!{struct TEB {
NtTib: NT_TIB,
EnvironmentPointer: PVOID,
ClientId: CLIENT_ID,
ActiveRpcHandle: PVOID,
ThreadLocalStoragePointer: PVOID,
ProcessEnvironmentBlock: PPEB,
LastErrorValue: ULONG,
CountOfOwnedCriticalSections: ULONG,
CsrClientThread: PVOID,
Win32ThreadInfo: PVOID,
User32Reserved: [ULONG; 26],
UserReserved: [ULONG; 5],
WOW32Reserved: PVOID,
CurrentLocale: LCID,
FpSoftwareStatusRegister: ULONG,
ReservedForDebuggerInstrumentation: [PVOID; 16],
SystemReserved1: [PVOID; 26],
PlaceholderCompatibilityMode: CHAR,
PlaceholderReserved: [CHAR; 11],
ProxiedProcessId: ULONG,
ActivationStack: ACTIVATION_CONTEXT_STACK,
WorkingOnBehalfTicket: [UCHAR; 8],
ExceptionCode: NTSTATUS,
ActivationContextStackPointer: PACTIVATION_CONTEXT_STACK,
InstrumentationCallbackSp: ULONG_PTR,
InstrumentationCallbackPreviousPc: ULONG_PTR,
InstrumentationCallbackPreviousSp: ULONG_PTR,
InstrumentationCallbackDisabled: BOOLEAN,
SpareBytes: [UCHAR; 23],
TxFsContext: ULONG,
GdiTebBatch: GDI_TEB_BATCH,
RealClientId: CLIENT_ID,
GdiCachedProcessHandle: HANDLE,
GdiClientPID: ULONG,
GdiClientTID: ULONG,
GdiThreadLocalInfo: PVOID,
Win32ClientInfo: [ULONG_PTR; 62],
glDispatchTable: [PVOID; 233],
glReserved1: [ULONG_PTR; 29],
glReserved2: PVOID,
glSectionInfo: PVOID,
glSection: PVOID,
glTable: PVOID,
glCurrentRC: PVOID,
glContext: PVOID,
LastStatusValue: NTSTATUS,
StaticUnicodeString: UNICODE_STRING,
StaticUnicodeBuffer: [WCHAR; 261],
DeallocationStack: PVOID,
TlsSlots: [PVOID; 64],
TlsLinks: LIST_ENTRY,
Vdm: PVOID,
ReservedForNtRpc: PVOID,
DbgSsReserved: [PVOID; 2],
HardErrorMode: ULONG,
Instrumentation: [PVOID; 9],
ActivityId: GUID,
SubProcessTag: PVOID,
PerflibData: PVOID,
EtwTraceData: PVOID,
WinSockData: PVOID,
GdiBatchCount: ULONG,
u: TEB_u,
GuaranteedStackBytes: ULONG,
ReservedForPerf: PVOID,
ReservedForOle: PVOID,
WaitingOnLoaderLock: ULONG,
SavedPriorityState: PVOID,
ReservedForCodeCoverage: ULONG_PTR,
ThreadPoolData: PVOID,
TlsExpansionSlots: *mut PVOID,
MuiGeneration: ULONG,
IsImpersonating: ULONG,
NlsCache: PVOID,
pShimData: PVOID,
HeapVirtualAffinity: USHORT,
LowFragHeapDataSlot: USHORT,
CurrentTransactionHandle: HANDLE,
ActiveFrame: PTEB_ACTIVE_FRAME,
FlsData: PVOID,
PreferredLanguages: PVOID,
UserPrefLanguages: PVOID,
MergedPrefLanguages: PVOID,
MuiImpersonation: ULONG,
CrossTebFlags: USHORT,
SameTebFlags: USHORT,
TxnScopeEnterCallback: PVOID,
TxnScopeExitCallback: PVOID,
TxnScopeContext: PVOID,
LockCount: ULONG,
WowTebOffset: LONG,
ResourceRetValue: PVOID,
ReservedForWdf: PVOID,
ReservedForCrt: ULONGLONG,
EffectiveContainerId: GUID,
}}
BITFIELD!{TEB SameTebFlags: USHORT [
SafeThunkCall set_SafeThunkCall[0..1],
InDebugPrint set_InDebugPrint[1..2],
HasFiberData set_HasFiberData[2..3],
SkipThreadAttach set_SkipThreadAttach[3..4],
WerInShipAssertCode set_WerInShipAssertCode[4..5],
RanProcessInit set_RanProcessInit[5..6],
ClonedThread set_ClonedThread[6..7],
SuppressDebugMsg set_SuppressDebugMsg[7..8],
DisableUserStackWalk set_DisableUserStackWalk[8..9],
RtlExceptionAttached set_RtlExceptionAttached[9..10],
InitialThread set_InitialThread[10..11],
SessionAware set_SessionAware[11..12],
LoadOwner set_LoadOwner[12..13],
LoaderWorker set_LoaderWorker[13..14],
SkipLoaderInit set_SkipLoaderInit[14..15],
SpareSameTebBits set_SpareSameTebBits[15..16],
]}
pub type PTEB = *mut TEB;

View file

@ -1,219 +0,0 @@
use crate::ntexapi::SYSTEM_MEMORY_LIST_INFORMATION;
use crate::ntmmapi::MMPFN_IDENTITY;
use winapi::shared::basetsd::{SIZE_T, ULONG_PTR};
use winapi::shared::ntdef::{CHAR, LONGLONG, PVOID, ULONG, ULONGLONG, WCHAR};
ENUM!{enum PF_BOOT_PHASE_ID {
PfKernelInitPhase = 0,
PfBootDriverInitPhase = 90,
PfSystemDriverInitPhase = 120,
PfSessionManagerInitPhase = 150,
PfSMRegistryInitPhase = 180,
PfVideoInitPhase = 210,
PfPostVideoInitPhase = 240,
PfBootAcceptedRegistryInitPhase = 270,
PfUserShellReadyPhase = 300,
PfMaxBootPhaseId = 900,
}}
ENUM!{enum PF_ENABLE_STATUS {
PfSvNotSpecified = 0,
PfSvEnabled = 1,
PfSvDisabled = 2,
PfSvMaxEnableStatus = 3,
}}
STRUCT!{struct PF_TRACE_LIMITS {
MaxNumPages: ULONG,
MaxNumSections: ULONG,
TimerPeriod: LONGLONG,
}}
pub type PPF_TRACE_LIMITS = *mut PF_TRACE_LIMITS;
STRUCT!{struct PF_SYSTEM_PREFETCH_PARAMETERS {
EnableStatus: [PF_ENABLE_STATUS; 2],
TraceLimits: [PF_TRACE_LIMITS; 2],
MaxNumActiveTraces: ULONG,
MaxNumSavedTraces: ULONG,
RootDirPath: [WCHAR; 32],
HostingApplicationList: [WCHAR; 128],
}}
pub type PPF_SYSTEM_PREFETCH_PARAMETERS = *mut PF_SYSTEM_PREFETCH_PARAMETERS;
pub const PF_BOOT_CONTROL_VERSION: u32 = 1;
STRUCT!{struct PF_BOOT_CONTROL {
Version: ULONG,
DisableBootPrefetching: ULONG,
}}
pub type PPF_BOOT_CONTROL = *mut PF_BOOT_CONTROL;
ENUM!{enum PREFETCHER_INFORMATION_CLASS {
PrefetcherRetrieveTrace = 1,
PrefetcherSystemParameters = 2,
PrefetcherBootPhase = 3,
PrefetcherRetrieveBootLoaderTrace = 4,
PrefetcherBootControl = 5,
}}
pub const PREFETCHER_INFORMATION_VERSION: ULONG = 23;
pub const PREFETCHER_INFORMATION_MAGIC: ULONG = 0x6b756843;
STRUCT!{struct PREFETCHER_INFORMATION {
Version: ULONG,
Magic: ULONG,
PrefetcherInformationClass: PREFETCHER_INFORMATION_CLASS,
PrefetcherInformation: PVOID,
PrefetcherInformationLength: ULONG,
}}
pub type PPREFETCHER_INFORMATION = *mut PREFETCHER_INFORMATION;
STRUCT!{struct PF_SYSTEM_SUPERFETCH_PARAMETERS {
EnabledComponents: ULONG,
BootID: ULONG,
SavedSectInfoTracesMax: ULONG,
SavedPageAccessTracesMax: ULONG,
ScenarioPrefetchTimeoutStandby: ULONG,
ScenarioPrefetchTimeoutHibernate: ULONG,
}}
pub type PPF_SYSTEM_SUPERFETCH_PARAMETERS = *mut PF_SYSTEM_SUPERFETCH_PARAMETERS;
pub const PF_PFN_PRIO_REQUEST_VERSION: u32 = 1;
pub const PF_PFN_PRIO_REQUEST_QUERY_MEMORY_LIST: u32 = 0x1;
pub const PF_PFN_PRIO_REQUEST_VALID_FLAGS: u32 = 0x1;
STRUCT!{struct PF_PFN_PRIO_REQUEST {
Version: ULONG,
RequestFlags: ULONG,
PfnCount: ULONG_PTR,
MemInfo: SYSTEM_MEMORY_LIST_INFORMATION,
PageData: [MMPFN_IDENTITY; 256],
}}
pub type PPF_PFN_PRIO_REQUEST = *mut PF_PFN_PRIO_REQUEST;
ENUM!{enum PFS_PRIVATE_PAGE_SOURCE_TYPE {
PfsPrivateSourceKernel = 0,
PfsPrivateSourceSession = 1,
PfsPrivateSourceProcess = 2,
PfsPrivateSourceMax = 3,
}}
UNION!{union PFS_PRIVATE_PAGE_SOURCE_u {
SessionId: ULONG,
ProcessId: ULONG,
}}
STRUCT!{struct PFS_PRIVATE_PAGE_SOURCE {
Type: PFS_PRIVATE_PAGE_SOURCE_TYPE,
u: PFS_PRIVATE_PAGE_SOURCE_u,
ImagePathHash: ULONG,
UniqueProcessHash: ULONG_PTR,
}}
UNION!{union PF_PRIVSOURCE_INFO_u {
WsSwapPages: ULONG_PTR,
SessionPagedPoolPages: ULONG_PTR,
StoreSizePages: ULONG_PTR,
}}
pub type PPFS_PRIVATE_PAGE_SOURCE = *mut PFS_PRIVATE_PAGE_SOURCE;
STRUCT!{struct PF_PRIVSOURCE_INFO {
DbInfo: PFS_PRIVATE_PAGE_SOURCE,
EProcess: PVOID,
WsPrivatePages: SIZE_T,
TotalPrivatePages: SIZE_T,
SessionID: ULONG,
ImageName: [CHAR; 16],
u: PF_PRIVSOURCE_INFO_u,
WsTotalPages: ULONG_PTR,
DeepFreezeTimeMs: ULONG,
BitFields: ULONG,
}}
BITFIELD!{PF_PRIVSOURCE_INFO BitFields: ULONG [
ModernApp set_ModernApp[0..1],
DeepFrozen set_DeepFrozen[1..2],
Foreground set_Foreground[2..3],
PerProcessStore set_PerProcessStore[3..4],
Spare set_Spare[4..32],
]}
pub type PPF_PRIVSOURCE_INFO = *mut PF_PRIVSOURCE_INFO;
pub const PF_PRIVSOURCE_QUERY_REQUEST_VERSION: u32 = 3;
STRUCT!{struct PF_PRIVSOURCE_QUERY_REQUEST {
Version: ULONG,
Flags: ULONG,
InfoCount: ULONG,
InfoArray: [PF_PRIVSOURCE_INFO; 1],
}}
pub type PPF_PRIVSOURCE_QUERY_REQUEST = *mut PF_PRIVSOURCE_QUERY_REQUEST;
ENUM!{enum PF_PHASED_SCENARIO_TYPE {
PfScenarioTypeNone = 0,
PfScenarioTypeStandby = 1,
PfScenarioTypeHibernate = 2,
PfScenarioTypeFUS = 3,
PfScenarioTypeMax = 4,
}}
pub const PF_SCENARIO_PHASE_INFO_VERSION: u32 = 4;
STRUCT!{struct PF_SCENARIO_PHASE_INFO {
Version: ULONG,
ScenType: PF_PHASED_SCENARIO_TYPE,
PhaseId: ULONG,
SequenceNumber: ULONG,
Flags: ULONG,
FUSUserId: ULONG,
}}
pub type PPF_SCENARIO_PHASE_INFO = *mut PF_SCENARIO_PHASE_INFO;
STRUCT!{struct PF_MEMORY_LIST_NODE {
Bitfields: ULONGLONG,
StandbyLowPageCount: ULONGLONG,
StandbyMediumPageCount: ULONGLONG,
StandbyHighPageCount: ULONGLONG,
FreePageCount: ULONGLONG,
ModifiedPageCount: ULONGLONG,
}}
BITFIELD!{PF_MEMORY_LIST_NODE Bitfields: ULONGLONG [
Node set_Node[0..8],
Spare set_Spare[8..64],
]}
pub type PPF_MEMORY_LIST_NODE = *mut PF_MEMORY_LIST_NODE;
pub const PF_MEMORY_LIST_INFO_VERSION: u32 = 1;
STRUCT!{struct PF_MEMORY_LIST_INFO {
Version: ULONG,
Size: ULONG,
NodeCount: ULONG,
Nodes: [PF_MEMORY_LIST_NODE; 1],
}}
pub type PPF_MEMORY_LIST_INFO = *mut PF_MEMORY_LIST_INFO;
STRUCT!{struct PF_PHYSICAL_MEMORY_RANGE {
BasePfn: ULONG_PTR,
PageCount: ULONG_PTR,
}}
pub type PPF_PHYSICAL_MEMORY_RANGE = *mut PF_PHYSICAL_MEMORY_RANGE;
pub const PF_PHYSICAL_MEMORY_RANGE_INFO_VERSION: u32 = 1;
STRUCT!{struct PF_PHYSICAL_MEMORY_RANGE_INFO {
Version: ULONG,
RangeCount: ULONG,
Ranges: [PF_PHYSICAL_MEMORY_RANGE; 1],
}}
pub type PPF_PHYSICAL_MEMORY_RANGE_INFO = *mut PF_PHYSICAL_MEMORY_RANGE_INFO;
pub const PF_REPURPOSED_BY_PREFETCH_INFO_VERSION: u32 = 1;
STRUCT!{struct PF_REPURPOSED_BY_PREFETCH_INFO {
Version: ULONG,
RepurposedByPrefetch: ULONG,
}}
pub type PPF_REPURPOSED_BY_PREFETCH_INFO = *mut PF_REPURPOSED_BY_PREFETCH_INFO;
ENUM!{enum SUPERFETCH_INFORMATION_CLASS {
SuperfetchRetrieveTrace = 1,
SuperfetchSystemParameters = 2,
SuperfetchLogEvent = 3,
SuperfetchGenerateTrace = 4,
SuperfetchPrefetch = 5,
SuperfetchPfnQuery = 6,
SuperfetchPfnSetPriority = 7,
SuperfetchPrivSourceQuery = 8,
SuperfetchSequenceNumberQuery = 9,
SuperfetchScenarioPhase = 10,
SuperfetchWorkerPriority = 11,
SuperfetchScenarioQuery = 12,
SuperfetchScenarioPrefetch = 13,
SuperfetchRobustnessControl = 14,
SuperfetchTimeControl = 15,
SuperfetchMemoryListQuery = 16,
SuperfetchMemoryRangesQuery = 17,
SuperfetchTracingControl = 18,
SuperfetchTrimWhileAgingControl = 19,
SuperfetchRepurposedByPrefetch = 20,
SuperfetchInformationMax = 21,
}}
pub const SUPERFETCH_INFORMATION_VERSION: ULONG = 45;
pub const SUPERFETCH_INFORMATION_MAGIC: ULONG = 0x6b756843;
STRUCT!{struct SUPERFETCH_INFORMATION {
Version: ULONG,
Magic: ULONG,
InfoClass: SUPERFETCH_INFORMATION_CLASS,
Data: PVOID,
Length: ULONG,
}}
pub type PSUPERFETCH_INFORMATION = *mut SUPERFETCH_INFORMATION;

View file

@ -1,118 +0,0 @@
use winapi::shared::cfg::PNP_VETO_TYPE;
use winapi::shared::guiddef::GUID;
use winapi::shared::ntdef::{HANDLE, NTSTATUS, PULONG, PUNICODE_STRING, PVOID, ULONG, WCHAR};
ENUM!{enum PLUGPLAY_EVENT_CATEGORY {
HardwareProfileChangeEvent = 0,
TargetDeviceChangeEvent = 1,
DeviceClassChangeEvent = 2,
CustomDeviceEvent = 3,
DeviceInstallEvent = 4,
DeviceArrivalEvent = 5,
PowerEvent = 6,
VetoEvent = 7,
BlockedDriverEvent = 8,
InvalidIDEvent = 9,
MaxPlugEventCategory = 10,
}}
pub type PPLUGPLAY_EVENT_CATEGORY = *mut PLUGPLAY_EVENT_CATEGORY;
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_DeviceClass {
ClassGuid: GUID,
SymbolicLinkName: [WCHAR; 1],
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_TargetDevice {
DeviceIds: [WCHAR; 1],
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_InstallDevice {
DeviceId: [WCHAR; 1],
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_CustomNotification {
NotificationStructure: PVOID,
DeviceIds: [WCHAR; 1],
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_ProfileNotification {
Notification: PVOID,
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_PowerNotification {
NotificationCode: ULONG,
NotificationData: ULONG,
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_VetoNotification {
VetoType: PNP_VETO_TYPE,
DeviceIdVetoNameBuffer: [WCHAR; 1],
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_BlockedDriverNotification {
BlockedDriverGuid: GUID,
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK_u_InvalidIDNotification {
ParentId: [WCHAR; 1],
}}
UNION!{union PLUGPLAY_EVENT_BLOCK_u {
DeviceClass: PLUGPLAY_EVENT_BLOCK_u_DeviceClass,
TargetDevice: PLUGPLAY_EVENT_BLOCK_u_TargetDevice,
InstallDevice: PLUGPLAY_EVENT_BLOCK_u_InstallDevice,
CustomNotification: PLUGPLAY_EVENT_BLOCK_u_CustomNotification,
ProfileNotification: PLUGPLAY_EVENT_BLOCK_u_ProfileNotification,
PowerNotification: PLUGPLAY_EVENT_BLOCK_u_PowerNotification,
VetoNotification: PLUGPLAY_EVENT_BLOCK_u_VetoNotification,
BlockedDriverNotification: PLUGPLAY_EVENT_BLOCK_u_BlockedDriverNotification,
InvalidIDNotification: PLUGPLAY_EVENT_BLOCK_u_InvalidIDNotification,
}}
STRUCT!{struct PLUGPLAY_EVENT_BLOCK {
EventGuid: GUID,
EventCategory: PLUGPLAY_EVENT_CATEGORY,
Result: PULONG,
Flags: ULONG,
TotalSize: ULONG,
DeviceObject: PVOID,
u: PLUGPLAY_EVENT_BLOCK_u,
}}
pub type PPLUGPLAY_EVENT_BLOCK = *mut PLUGPLAY_EVENT_BLOCK;
ENUM!{enum PLUGPLAY_CONTROL_CLASS {
PlugPlayControlEnumerateDevice = 0,
PlugPlayControlRegisterNewDevice = 1,
PlugPlayControlDeregisterDevice = 2,
PlugPlayControlInitializeDevice = 3,
PlugPlayControlStartDevice = 4,
PlugPlayControlUnlockDevice = 5,
PlugPlayControlQueryAndRemoveDevice = 6,
PlugPlayControlUserResponse = 7,
PlugPlayControlGenerateLegacyDevice = 8,
PlugPlayControlGetInterfaceDeviceList = 9,
PlugPlayControlProperty = 10,
PlugPlayControlDeviceClassAssociation = 11,
PlugPlayControlGetRelatedDevice = 12,
PlugPlayControlGetInterfaceDeviceAlias = 13,
PlugPlayControlDeviceStatus = 14,
PlugPlayControlGetDeviceDepth = 15,
PlugPlayControlQueryDeviceRelations = 16,
PlugPlayControlTargetDeviceRelation = 17,
PlugPlayControlQueryConflictList = 18,
PlugPlayControlRetrieveDock = 19,
PlugPlayControlResetDevice = 20,
PlugPlayControlHaltDevice = 21,
PlugPlayControlGetBlockedDriverList = 22,
PlugPlayControlGetDeviceInterfaceEnabled = 23,
MaxPlugPlayControl = 24,
}}
pub type PPLUGPLAY_CONTROL_CLASS = *mut PLUGPLAY_CONTROL_CLASS;
EXTERN!{extern "system" {
fn NtGetPlugPlayEvent(
EventHandle: HANDLE,
Context: PVOID,
EventBlock: PPLUGPLAY_EVENT_BLOCK,
EventBufferSize: ULONG,
) -> NTSTATUS;
fn NtPlugPlayControl(
PnPControlClass: PLUGPLAY_CONTROL_CLASS,
PnPControlData: PVOID,
PnPControlDataLength: ULONG,
) -> NTSTATUS;
fn NtSerializeBoot() -> NTSTATUS;
fn NtEnableLastKnownGood() -> NTSTATUS;
fn NtDisableLastKnownGood() -> NTSTATUS;
fn NtReplacePartitionUnit(
TargetInstancePath: PUNICODE_STRING,
SpareInstancePath: PUNICODE_STRING,
Flags: ULONG,
) -> NTSTATUS;
}}

View file

@ -1,134 +0,0 @@
use winapi::shared::ntdef::{
BOOLEAN, HANDLE, LONG, NTSTATUS, PLONG, PUNICODE_STRING, PVOID, UCHAR, ULONG, UNICODE_STRING,
USHORT,
};
use winapi::um::winnt::{
DEVICE_POWER_STATE, EXECUTION_STATE, LATENCY_TIME, PDEVICE_POWER_STATE, PEXECUTION_STATE,
POWER_ACTION, POWER_INFORMATION_LEVEL, SYSTEM_POWER_STATE,
};
UNION!{union POWER_STATE {
SystemState: SYSTEM_POWER_STATE,
DeviceState: DEVICE_POWER_STATE,
}}
pub type PPOWER_STATE = *mut POWER_STATE;
ENUM!{enum POWER_STATE_TYPE {
SystemPowerState = 0,
DevicePowerState = 1,
}}
pub type PPOWER_STATE_TYPE = *mut POWER_STATE_TYPE;
STRUCT!{struct SYSTEM_POWER_STATE_CONTEXT {
ContextAsUlong: ULONG,
}}
BITFIELD!{SYSTEM_POWER_STATE_CONTEXT ContextAsUlong: ULONG [
Reserved1 set_Reserved1[0..8],
TargetSystemState set_TargetSystemState[8..12],
EffectiveSystemState set_EffectiveSystemState[12..16],
CurrentSystemState set_CurrentSystemState[16..20],
IgnoreHibernationPath set_IgnoreHibernationPath[20..21],
PseudoTransition set_PseudoTransition[21..22],
Reserved2 set_Reserved2[22..32],
]}
pub type PSYSTEM_POWER_STATE_CONTEXT = *mut SYSTEM_POWER_STATE_CONTEXT;
STRUCT!{struct COUNTED_REASON_CONTEXT_u_s {
ResourceFileName: UNICODE_STRING,
ResourceReasonId: USHORT,
StringCount: ULONG,
ReasonStrings: PUNICODE_STRING,
}}
UNION!{union COUNTED_REASON_CONTEXT_u {
s: COUNTED_REASON_CONTEXT_u_s,
SimpleString: UNICODE_STRING,
}}
STRUCT!{struct COUNTED_REASON_CONTEXT {
Version: ULONG,
Flags: ULONG,
u: COUNTED_REASON_CONTEXT_u,
}}
pub type PCOUNTED_REASON_CONTEXT = *mut COUNTED_REASON_CONTEXT;
ENUM!{enum POWER_STATE_HANDLER_TYPE {
PowerStateSleeping1 = 0,
PowerStateSleeping2 = 1,
PowerStateSleeping3 = 2,
PowerStateSleeping4 = 3,
PowerStateShutdownOff = 4,
PowerStateShutdownReset = 5,
PowerStateSleeping4Firmware = 6,
PowerStateMaximum = 7,
}}
pub type PPOWER_STATE_HANDLER_TYPE = *mut POWER_STATE_HANDLER_TYPE;
FN!{stdcall PENTER_STATE_SYSTEM_HANDLER(
SystemContext: PVOID,
) -> NTSTATUS}
FN!{stdcall PENTER_STATE_HANDLER(
Context: PVOID,
SystemHandler: PENTER_STATE_SYSTEM_HANDLER,
SystemContext: PVOID,
NumberProcessors: LONG,
Number: PLONG,
) -> NTSTATUS}
STRUCT!{struct POWER_STATE_HANDLER {
Type: POWER_STATE_HANDLER_TYPE,
RtcWake: BOOLEAN,
Spare: [UCHAR; 3],
Handler: PENTER_STATE_HANDLER,
Context: PVOID,
}}
pub type PPOWER_STATE_HANDLER = *mut POWER_STATE_HANDLER;
FN!{stdcall PENTER_STATE_NOTIFY_HANDLER(
State: POWER_STATE_HANDLER_TYPE,
Context: PVOID,
Entering: BOOLEAN,
) -> NTSTATUS}
STRUCT!{struct POWER_STATE_NOTIFY_HANDLER {
Handler: PENTER_STATE_NOTIFY_HANDLER,
Context: PVOID,
}}
pub type PPOWER_STATE_NOTIFY_HANDLER = *mut POWER_STATE_NOTIFY_HANDLER;
STRUCT!{struct PROCESSOR_POWER_INFORMATION {
Number: ULONG,
MaxMhz: ULONG,
CurrentMhz: ULONG,
MhzLimit: ULONG,
MaxIdleState: ULONG,
CurrentIdleState: ULONG,
}}
pub type PPROCESSOR_POWER_INFORMATION = *mut PROCESSOR_POWER_INFORMATION;
STRUCT!{struct SYSTEM_POWER_INFORMATION {
MaxIdlenessAllowed: ULONG,
Idleness: ULONG,
TimeRemaining: ULONG,
CoolingMode: UCHAR,
}}
pub type PSYSTEM_POWER_INFORMATION = *mut SYSTEM_POWER_INFORMATION;
EXTERN!{extern "system" {
fn NtPowerInformation(
InformationLevel: POWER_INFORMATION_LEVEL,
InputBuffer: PVOID,
InputBufferLength: ULONG,
OutputBuffer: PVOID,
OutputBufferLength: ULONG,
) -> NTSTATUS;
fn NtSetThreadExecutionState(
NewFlags: EXECUTION_STATE,
PreviousFlags: PEXECUTION_STATE,
) -> NTSTATUS;
fn NtRequestWakeupLatency(
latency: LATENCY_TIME,
) -> NTSTATUS;
fn NtInitiatePowerAction(
SystemAction: POWER_ACTION,
LightestSystemState: SYSTEM_POWER_STATE,
Flags: ULONG,
Asynchronous: BOOLEAN,
) -> NTSTATUS;
fn NtSetSystemPowerState(
SystemAction: POWER_ACTION,
LightestSystemState: SYSTEM_POWER_STATE,
Flags: ULONG,
) -> NTSTATUS;
fn NtGetDevicePowerState(
Device: HANDLE,
State: PDEVICE_POWER_STATE,
) -> NTSTATUS;
fn NtIsSystemResumeAutomatic() -> BOOLEAN;
}}

File diff suppressed because it is too large Load diff

View file

@ -1,450 +0,0 @@
use crate::ntioapi::{PIO_APC_ROUTINE, PIO_STATUS_BLOCK};
use winapi::shared::ntdef::{
BOOLEAN, HANDLE, LARGE_INTEGER, NTSTATUS, OBJECT_ATTRIBUTES, PHANDLE, POBJECT_ATTRIBUTES,
PULONG, PUNICODE_STRING, PVOID, UCHAR, ULONG, UNICODE_STRING, USHORT, WCHAR,
};
use winapi::um::winnt::ACCESS_MASK;
pub const REG_INIT_BOOT_SM: USHORT = 0x0000;
pub const REG_INIT_BOOT_SETUP: USHORT = 0x0001;
pub const REG_INIT_BOOT_ACCEPTED_BASE: USHORT = 0x0002;
pub const REG_INIT_BOOT_ACCEPTED_MAX: USHORT = REG_INIT_BOOT_ACCEPTED_BASE;
pub const REG_MAX_KEY_VALUE_NAME_LENGTH: u32 = 32767;
pub const REG_MAX_KEY_NAME_LENGTH: u32 = 512;
ENUM!{enum KEY_INFORMATION_CLASS {
KeyBasicInformation = 0,
KeyNodeInformation = 1,
KeyFullInformation = 2,
KeyNameInformation = 3,
KeyCachedInformation = 4,
KeyFlagsInformation = 5,
KeyVirtualizationInformation = 6,
KeyHandleTagsInformation = 7,
KeyTrustInformation = 8,
KeyLayerInformation = 9,
MaxKeyInfoClass = 10,
}}
STRUCT!{struct KEY_BASIC_INFORMATION {
LastWriteTime: LARGE_INTEGER,
TitleIndex: ULONG,
NameLength: ULONG,
Name: [WCHAR; 1],
}}
pub type PKEY_BASIC_INFORMATION = *mut KEY_BASIC_INFORMATION;
STRUCT!{struct KEY_NODE_INFORMATION {
LastWriteTime: LARGE_INTEGER,
TitleIndex: ULONG,
ClassOffset: ULONG,
ClassLength: ULONG,
NameLength: ULONG,
Name: [WCHAR; 1],
}}
pub type PKEY_NODE_INFORMATION = *mut KEY_NODE_INFORMATION;
STRUCT!{struct KEY_FULL_INFORMATION {
LastWriteTime: LARGE_INTEGER,
TitleIndex: ULONG,
ClassOffset: ULONG,
ClassLength: ULONG,
SubKeys: ULONG,
MaxNameLen: ULONG,
MaxClassLen: ULONG,
Values: ULONG,
MaxValueNameLen: ULONG,
MaxValueDataLen: ULONG,
Class: [WCHAR; 1],
}}
pub type PKEY_FULL_INFORMATION = *mut KEY_FULL_INFORMATION;
STRUCT!{struct KEY_NAME_INFORMATION {
NameLength: ULONG,
Name: [WCHAR; 1],
}}
pub type PKEY_NAME_INFORMATION = *mut KEY_NAME_INFORMATION;
STRUCT!{struct KEY_CACHED_INFORMATION {
LastWriteTime: LARGE_INTEGER,
TitleIndex: ULONG,
SubKeys: ULONG,
MaxNameLen: ULONG,
Values: ULONG,
MaxValueNameLen: ULONG,
MaxValueDataLen: ULONG,
NameLength: ULONG,
Name: [WCHAR; 1],
}}
pub type PKEY_CACHED_INFORMATION = *mut KEY_CACHED_INFORMATION;
STRUCT!{struct KEY_FLAGS_INFORMATION {
UserFlags: ULONG,
}}
pub type PKEY_FLAGS_INFORMATION = *mut KEY_FLAGS_INFORMATION;
STRUCT!{struct KEY_VIRTUALIZATION_INFORMATION {
Bitfields: ULONG,
}}
BITFIELD!{KEY_VIRTUALIZATION_INFORMATION Bitfields: ULONG [
VirtualizationCandidate set_VirtualizationCandidate[0..1],
VirtualizationEnabled set_VirtualizationEnabled[1..2],
VirtualTarget set_VirtualTarget[2..3],
VirtualStore set_VirtualStore[3..4],
VirtualSource set_VirtualSource[4..5],
Reserved set_Reserved[5..32],
]}
pub type PKEY_VIRTUALIZATION_INFORMATION = *mut KEY_VIRTUALIZATION_INFORMATION;
STRUCT!{struct KEY_TRUST_INFORMATION {
Bitfields: ULONG,
}}
BITFIELD!{KEY_TRUST_INFORMATION Bitfields: ULONG [
TrustedKey set_TrustedKey[0..1],
Reserved set_Reserved[1..32],
]}
pub type PKEY_TRUST_INFORMATION = *mut KEY_TRUST_INFORMATION;
STRUCT!{struct KEY_LAYER_INFORMATION {
IsTombstone: ULONG,
IsSupersedeLocal: ULONG,
IsSupersedeTree: ULONG,
ClassIsInherited: ULONG,
Reserved: ULONG,
}}
pub type PKEY_LAYER_INFORMATION = *mut KEY_LAYER_INFORMATION;
ENUM!{enum KEY_SET_INFORMATION_CLASS {
KeyWriteTimeInformation = 0,
KeyWow64FlagsInformation = 1,
KeyControlFlagsInformation = 2,
KeySetVirtualizationInformation = 3,
KeySetDebugInformation = 4,
KeySetHandleTagsInformation = 5,
KeySetLayerInformation = 6,
MaxKeySetInfoClass = 7,
}}
STRUCT!{struct KEY_WRITE_TIME_INFORMATION {
LastWriteTime: LARGE_INTEGER,
}}
pub type PKEY_WRITE_TIME_INFORMATION = *mut KEY_WRITE_TIME_INFORMATION;
STRUCT!{struct KEY_WOW64_FLAGS_INFORMATION {
UserFlags: ULONG,
}}
pub type PKEY_WOW64_FLAGS_INFORMATION = *mut KEY_WOW64_FLAGS_INFORMATION;
STRUCT!{struct KEY_HANDLE_TAGS_INFORMATION {
HandleTags: ULONG,
}}
pub type PKEY_HANDLE_TAGS_INFORMATION = *mut KEY_HANDLE_TAGS_INFORMATION;
STRUCT!{struct KEY_SET_LAYER_INFORMATION {
Bitfields: ULONG,
}}
BITFIELD!{KEY_SET_LAYER_INFORMATION Bitfields: ULONG [
IsTombstone set_IsTombstone[0..1],
IsSupersedeLocal set_IsSupersedeLocal[1..2],
IsSupersedeTree set_IsSupersedeTree[2..3],
ClassIsInherited set_ClassIsInherited[3..4],
Reserved set_Reserved[4..32],
]}
pub type PKEY_SET_LAYER_INFORMATION = *mut KEY_SET_LAYER_INFORMATION;
STRUCT!{struct KEY_CONTROL_FLAGS_INFORMATION {
ControlFlags: ULONG,
}}
pub type PKEY_CONTROL_FLAGS_INFORMATION = *mut KEY_CONTROL_FLAGS_INFORMATION;
STRUCT!{struct KEY_SET_VIRTUALIZATION_INFORMATION {
HandleTags: ULONG,
}}
BITFIELD!{KEY_SET_VIRTUALIZATION_INFORMATION HandleTags: ULONG [
VirtualTarget set_VirtualTarget[0..1],
VirtualStore set_VirtualStore[1..2],
VirtualSource set_VirtualSource[2..3],
Reserved set_Reserved[3..32],
]}
pub type PKEY_SET_VIRTUALIZATION_INFORMATION = *mut KEY_SET_VIRTUALIZATION_INFORMATION;
ENUM!{enum KEY_VALUE_INFORMATION_CLASS {
KeyValueBasicInformation = 0,
KeyValueFullInformation = 1,
KeyValuePartialInformation = 2,
KeyValueFullInformationAlign64 = 3,
KeyValuePartialInformationAlign64 = 4,
KeyValueLayerInformation = 5,
MaxKeyValueInfoClass = 6,
}}
STRUCT!{struct KEY_VALUE_BASIC_INFORMATION {
TitleIndex: ULONG,
Type: ULONG,
NameLength: ULONG,
Name: [WCHAR; 1],
}}
pub type PKEY_VALUE_BASIC_INFORMATION = *mut KEY_VALUE_BASIC_INFORMATION;
STRUCT!{struct KEY_VALUE_FULL_INFORMATION {
TitleIndex: ULONG,
Type: ULONG,
DataOffset: ULONG,
DataLength: ULONG,
NameLength: ULONG,
Name: [WCHAR; 1],
}}
pub type PKEY_VALUE_FULL_INFORMATION = *mut KEY_VALUE_FULL_INFORMATION;
STRUCT!{struct KEY_VALUE_PARTIAL_INFORMATION {
TitleIndex: ULONG,
Type: ULONG,
DataLength: ULONG,
Data: [UCHAR; 1],
}}
pub type PKEY_VALUE_PARTIAL_INFORMATION = *mut KEY_VALUE_PARTIAL_INFORMATION;
STRUCT!{struct KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 {
Type: ULONG,
DataLength: ULONG,
Data: [UCHAR; 1],
}}
pub type PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 = *mut KEY_VALUE_PARTIAL_INFORMATION_ALIGN64;
STRUCT!{struct KEY_VALUE_LAYER_INFORMATION {
IsTombstone: ULONG,
Reserved: ULONG,
}}
pub type PKEY_VALUE_LAYER_INFORMATION = *mut KEY_VALUE_LAYER_INFORMATION;
STRUCT!{struct KEY_VALUE_ENTRY {
ValueName: PUNICODE_STRING,
DataLength: ULONG,
DataOffset: ULONG,
Type: ULONG,
}}
pub type PKEY_VALUE_ENTRY = *mut KEY_VALUE_ENTRY;
ENUM!{enum REG_ACTION {
KeyAdded = 0,
KeyRemoved = 1,
KeyModified = 2,
}}
STRUCT!{struct REG_NOTIFY_INFORMATION {
NextEntryOffset: ULONG,
Action: REG_ACTION,
KeyLength: ULONG,
Key: [WCHAR; 1],
}}
pub type PREG_NOTIFY_INFORMATION = *mut REG_NOTIFY_INFORMATION;
STRUCT!{struct KEY_PID_ARRAY {
PID: HANDLE,
KeyName: UNICODE_STRING,
}}
pub type PKEY_PID_ARRAY = *mut KEY_PID_ARRAY;
STRUCT!{struct KEY_OPEN_SUBKEYS_INFORMATION {
Count: ULONG,
KeyArray: [KEY_PID_ARRAY; 1],
}}
pub type PKEY_OPEN_SUBKEYS_INFORMATION = *mut KEY_OPEN_SUBKEYS_INFORMATION;
EXTERN!{extern "system" {
fn NtCreateKey(
KeyHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
TitleIndex: ULONG,
Class: PUNICODE_STRING,
CreateOptions: ULONG,
Disposition: PULONG,
) -> NTSTATUS;
fn NtCreateKeyTransacted(
KeyHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
TitleIndex: ULONG,
Class: PUNICODE_STRING,
CreateOptions: ULONG,
TransactionHandle: HANDLE,
Disposition: PULONG,
) -> NTSTATUS;
fn NtOpenKey(
KeyHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtOpenKeyTransacted(
KeyHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
TransactionHandle: HANDLE,
) -> NTSTATUS;
fn NtOpenKeyEx(
KeyHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
OpenOptions: ULONG,
) -> NTSTATUS;
fn NtOpenKeyTransactedEx(
KeyHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
OpenOptions: ULONG,
TransactionHandle: HANDLE,
) -> NTSTATUS;
fn NtDeleteKey(
KeyHandle: HANDLE,
) -> NTSTATUS;
fn NtRenameKey(
KeyHandle: HANDLE,
NewName: PUNICODE_STRING,
) -> NTSTATUS;
fn NtDeleteValueKey(
KeyHandle: HANDLE,
ValueName: PUNICODE_STRING,
) -> NTSTATUS;
fn NtQueryKey(
KeyHandle: HANDLE,
KeyInformationClass: KEY_INFORMATION_CLASS,
KeyInformation: PVOID,
Length: ULONG,
ResultLength: PULONG,
) -> NTSTATUS;
fn NtSetInformationKey(
KeyHandle: HANDLE,
KeySetInformationClass: KEY_SET_INFORMATION_CLASS,
KeySetInformation: PVOID,
KeySetInformationLength: ULONG,
) -> NTSTATUS;
fn NtQueryValueKey(
KeyHandle: HANDLE,
ValueName: PUNICODE_STRING,
KeyValueInformationClass: KEY_VALUE_INFORMATION_CLASS,
KeyValueInformation: PVOID,
Length: ULONG,
ResultLength: PULONG,
) -> NTSTATUS;
fn NtSetValueKey(
KeyHandle: HANDLE,
ValueName: PUNICODE_STRING,
TitleIndex: ULONG,
Type: ULONG,
Data: PVOID,
DataSize: ULONG,
) -> NTSTATUS;
fn NtQueryMultipleValueKey(
KeyHandle: HANDLE,
ValueEntries: PKEY_VALUE_ENTRY,
EntryCount: ULONG,
ValueBuffer: PVOID,
BufferLength: PULONG,
RequiredBufferLength: PULONG,
) -> NTSTATUS;
fn NtEnumerateKey(
KeyHandle: HANDLE,
Index: ULONG,
KeyInformationClass: KEY_INFORMATION_CLASS,
KeyInformation: PVOID,
Length: ULONG,
ResultLength: PULONG,
) -> NTSTATUS;
fn NtEnumerateValueKey(
KeyHandle: HANDLE,
Index: ULONG,
KeyValueInformationClass: KEY_VALUE_INFORMATION_CLASS,
KeyValueInformation: PVOID,
Length: ULONG,
ResultLength: PULONG,
) -> NTSTATUS;
fn NtFlushKey(
KeyHandle: HANDLE,
) -> NTSTATUS;
fn NtCompactKeys(
Count: ULONG,
KeyArray: *mut HANDLE,
) -> NTSTATUS;
fn NtCompressKey(
Key: HANDLE,
) -> NTSTATUS;
fn NtLoadKey(
TargetKey: POBJECT_ATTRIBUTES,
SourceFile: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtLoadKey2(
TargetKey: POBJECT_ATTRIBUTES,
SourceFile: POBJECT_ATTRIBUTES,
Flags: ULONG,
) -> NTSTATUS;
fn NtLoadKeyEx(
TargetKey: POBJECT_ATTRIBUTES,
SourceFile: POBJECT_ATTRIBUTES,
Flags: ULONG,
TrustClassKey: HANDLE,
Event: HANDLE,
DesiredAccess: ACCESS_MASK,
RootHandle: PHANDLE,
IoStatus: PIO_STATUS_BLOCK,
) -> NTSTATUS;
fn NtReplaceKey(
NewFile: POBJECT_ATTRIBUTES,
TargetHandle: HANDLE,
OldFile: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtSaveKey(
KeyHandle: HANDLE,
FileHandle: HANDLE,
) -> NTSTATUS;
fn NtSaveKeyEx(
KeyHandle: HANDLE,
FileHandle: HANDLE,
Format: ULONG,
) -> NTSTATUS;
fn NtSaveMergedKeys(
HighPrecedenceKeyHandle: HANDLE,
LowPrecedenceKeyHandle: HANDLE,
FileHandle: HANDLE,
) -> NTSTATUS;
fn NtRestoreKey(
KeyHandle: HANDLE,
FileHandle: HANDLE,
Flags: ULONG,
) -> NTSTATUS;
fn NtUnloadKey(
TargetKey: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
}}
pub const REG_FORCE_UNLOAD: ULONG = 1;
pub const REG_UNLOAD_LEGAL_FLAGS: ULONG = REG_FORCE_UNLOAD;
EXTERN!{extern "system" {
fn NtUnloadKey2(
TargetKey: POBJECT_ATTRIBUTES,
Flags: ULONG,
) -> NTSTATUS;
fn NtUnloadKeyEx(
TargetKey: POBJECT_ATTRIBUTES,
Event: HANDLE,
) -> NTSTATUS;
fn NtNotifyChangeKey(
KeyHandle: HANDLE,
Event: HANDLE,
ApcRoutine: PIO_APC_ROUTINE,
ApcContext: PVOID,
IoStatusBlock: PIO_STATUS_BLOCK,
CompletionFilter: ULONG,
WatchTree: BOOLEAN,
Buffer: PVOID,
BufferSize: ULONG,
Asynchronous: BOOLEAN,
) -> NTSTATUS;
fn NtNotifyChangeMultipleKeys(
MasterKeyHandle: HANDLE,
Count: ULONG,
SubordinateObjects: *mut OBJECT_ATTRIBUTES,
Event: HANDLE,
ApcRoutine: PIO_APC_ROUTINE,
ApcContext: PVOID,
IoStatusBlock: PIO_STATUS_BLOCK,
CompletionFilter: ULONG,
WatchTree: BOOLEAN,
Buffer: PVOID,
BufferSize: ULONG,
Asynchronous: BOOLEAN,
) -> NTSTATUS;
fn NtQueryOpenSubKeys(
TargetKey: POBJECT_ATTRIBUTES,
HandleCount: PULONG,
) -> NTSTATUS;
fn NtQueryOpenSubKeysEx(
TargetKey: POBJECT_ATTRIBUTES,
BufferLength: ULONG,
Buffer: PVOID,
RequiredSize: PULONG,
) -> NTSTATUS;
fn NtInitializeRegistry(
BootCondition: USHORT,
) -> NTSTATUS;
fn NtLockRegistryKey(
KeyHandle: HANDLE,
) -> NTSTATUS;
fn NtLockProductActivationKeys(
pPrivateVer: *mut ULONG,
pSafeMode: *mut ULONG,
) -> NTSTATUS;
fn NtFreezeRegistry(
TimeOutInSeconds: ULONG,
) -> NTSTATUS;
fn NtThawRegistry() -> NTSTATUS;
}}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,439 +0,0 @@
use winapi::shared::basetsd::{PLONG64, PULONG64, ULONG64};
use winapi::shared::ntdef::{
BOOLEAN, HANDLE, LONG, NTSTATUS, PBOOLEAN, PHANDLE, PLARGE_INTEGER, PLUID, PNTSTATUS,
POBJECT_ATTRIBUTES, PUCHAR, PULONG, PUNICODE_STRING, PVOID, ULONG, UNICODE_STRING, USHORT,
};
use winapi::um::winnt::{
ACCESS_MASK, AUDIT_EVENT_TYPE, PACCESS_MASK, PGENERIC_MAPPING, POBJECT_TYPE_LIST,
PPRIVILEGE_SET, PSECURITY_DESCRIPTOR, PSE_SIGNING_LEVEL, PSID, PSID_AND_ATTRIBUTES,
PTOKEN_DEFAULT_DACL, PTOKEN_GROUPS, PTOKEN_MANDATORY_POLICY, PTOKEN_OWNER,
PTOKEN_PRIMARY_GROUP, PTOKEN_PRIVILEGES, PTOKEN_SOURCE, PTOKEN_USER, SE_SIGNING_LEVEL,
TOKEN_INFORMATION_CLASS, TOKEN_TYPE,
};
pub const SE_MIN_WELL_KNOWN_PRIVILEGE: LONG = 2;
pub const SE_CREATE_TOKEN_PRIVILEGE: LONG = 2;
pub const SE_ASSIGNPRIMARYTOKEN_PRIVILEGE: LONG = 3;
pub const SE_LOCK_MEMORY_PRIVILEGE: LONG = 4;
pub const SE_INCREASE_QUOTA_PRIVILEGE: LONG = 5;
pub const SE_MACHINE_ACCOUNT_PRIVILEGE: LONG = 6;
pub const SE_TCB_PRIVILEGE: LONG = 7;
pub const SE_SECURITY_PRIVILEGE: LONG = 8;
pub const SE_TAKE_OWNERSHIP_PRIVILEGE: LONG = 9;
pub const SE_LOAD_DRIVER_PRIVILEGE: LONG = 10;
pub const SE_SYSTEM_PROFILE_PRIVILEGE: LONG = 11;
pub const SE_SYSTEMTIME_PRIVILEGE: LONG = 12;
pub const SE_PROF_SINGLE_PROCESS_PRIVILEGE: LONG = 13;
pub const SE_INC_BASE_PRIORITY_PRIVILEGE: LONG = 14;
pub const SE_CREATE_PAGEFILE_PRIVILEGE: LONG = 15;
pub const SE_CREATE_PERMANENT_PRIVILEGE: LONG = 16;
pub const SE_BACKUP_PRIVILEGE: LONG = 17;
pub const SE_RESTORE_PRIVILEGE: LONG = 18;
pub const SE_SHUTDOWN_PRIVILEGE: LONG = 19;
pub const SE_DEBUG_PRIVILEGE: LONG = 20;
pub const SE_AUDIT_PRIVILEGE: LONG = 21;
pub const SE_SYSTEM_ENVIRONMENT_PRIVILEGE: LONG = 22;
pub const SE_CHANGE_NOTIFY_PRIVILEGE: LONG = 23;
pub const SE_REMOTE_SHUTDOWN_PRIVILEGE: LONG = 24;
pub const SE_UNDOCK_PRIVILEGE: LONG = 25;
pub const SE_SYNC_AGENT_PRIVILEGE: LONG = 26;
pub const SE_ENABLE_DELEGATION_PRIVILEGE: LONG = 27;
pub const SE_MANAGE_VOLUME_PRIVILEGE: LONG = 28;
pub const SE_IMPERSONATE_PRIVILEGE: LONG = 29;
pub const SE_CREATE_GLOBAL_PRIVILEGE: LONG = 30;
pub const SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE: LONG = 31;
pub const SE_RELABEL_PRIVILEGE: LONG = 32;
pub const SE_INC_WORKING_SET_PRIVILEGE: LONG = 33;
pub const SE_TIME_ZONE_PRIVILEGE: LONG = 34;
pub const SE_CREATE_SYMBOLIC_LINK_PRIVILEGE: LONG = 35;
pub const SE_DELEGATE_SESSION_USER_IMPERSONATE_PRIVILEGE: LONG = 36;
pub const SE_MAX_WELL_KNOWN_PRIVILEGE: LONG = SE_DELEGATE_SESSION_USER_IMPERSONATE_PRIVILEGE;
pub const TOKEN_SECURITY_ATTRIBUTE_TYPE_INVALID: USHORT = 0x00;
pub const TOKEN_SECURITY_ATTRIBUTE_TYPE_INT64: USHORT = 0x01;
pub const TOKEN_SECURITY_ATTRIBUTE_TYPE_UINT64: USHORT = 0x02;
pub const TOKEN_SECURITY_ATTRIBUTE_TYPE_STRING: USHORT = 0x03;
pub const TOKEN_SECURITY_ATTRIBUTE_TYPE_FQBN: USHORT = 0x04;
pub const TOKEN_SECURITY_ATTRIBUTE_TYPE_SID: USHORT = 0x05;
pub const TOKEN_SECURITY_ATTRIBUTE_TYPE_BOOLEAN: USHORT = 0x06;
pub const TOKEN_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING: USHORT = 0x10;
pub const TOKEN_SECURITY_ATTRIBUTE_NON_INHERITABLE: USHORT = 0x0001;
pub const TOKEN_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE: USHORT = 0x0002;
pub const TOKEN_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY: USHORT = 0x0004;
pub const TOKEN_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT: USHORT = 0x0008;
pub const TOKEN_SECURITY_ATTRIBUTE_DISABLED: USHORT = 0x0010;
pub const TOKEN_SECURITY_ATTRIBUTE_MANDATORY: USHORT = 0x0020;
pub const TOKEN_SECURITY_ATTRIBUTE_COMPARE_IGNORE: USHORT = 0x0040;
pub const TOKEN_SECURITY_ATTRIBUTE_VALID_FLAGS: USHORT = TOKEN_SECURITY_ATTRIBUTE_NON_INHERITABLE
| TOKEN_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE | TOKEN_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY
| TOKEN_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT | TOKEN_SECURITY_ATTRIBUTE_DISABLED
| TOKEN_SECURITY_ATTRIBUTE_MANDATORY;
pub const TOKEN_SECURITY_ATTRIBUTE_CUSTOM_FLAGS: u32 = 0xffff0000;
STRUCT!{struct TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE {
Version: ULONG64,
Name: UNICODE_STRING,
}}
pub type PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE = *mut TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE;
STRUCT!{struct TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE {
pValue: PVOID,
ValueLength: ULONG,
}}
pub type PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE =
*mut TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE;
UNION!{union TOKEN_SECURITY_ATTRIBUTE_V1_Values {
pInt64: PLONG64,
pUint64: PULONG64,
pString: PUNICODE_STRING,
pFqbn: PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE,
pOctetString: PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE,
}}
STRUCT!{struct TOKEN_SECURITY_ATTRIBUTE_V1 {
Name: UNICODE_STRING,
ValueType: USHORT,
Reserved: USHORT,
Flags: ULONG,
ValueCount: ULONG,
Values: TOKEN_SECURITY_ATTRIBUTE_V1_Values,
}}
pub type PTOKEN_SECURITY_ATTRIBUTE_V1 = *mut TOKEN_SECURITY_ATTRIBUTE_V1;
pub const TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION_V1: USHORT = 1;
pub const TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION: USHORT =
TOKEN_SECURITY_ATTRIBUTES_INFORMATION_VERSION_V1;
STRUCT!{struct TOKEN_SECURITY_ATTRIBUTES_INFORMATION {
Version: USHORT,
Reserved: USHORT,
AttributeCount: ULONG,
pAttributeV1: PTOKEN_SECURITY_ATTRIBUTE_V1,
}}
pub type PTOKEN_SECURITY_ATTRIBUTES_INFORMATION = *mut TOKEN_SECURITY_ATTRIBUTES_INFORMATION;
STRUCT!{struct TOKEN_PROCESS_TRUST_LEVEL {
TrustLevelSid: PSID,
}}
pub type PTOKEN_PROCESS_TRUST_LEVEL = *mut TOKEN_PROCESS_TRUST_LEVEL;
EXTERN!{extern "system" {
fn NtCreateToken(
TokenHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
TokenType: TOKEN_TYPE,
AuthenticationId: PLUID,
ExpirationTime: PLARGE_INTEGER,
User: PTOKEN_USER,
Groups: PTOKEN_GROUPS,
Privileges: PTOKEN_PRIVILEGES,
Owner: PTOKEN_OWNER,
PrimaryGroup: PTOKEN_PRIMARY_GROUP,
DefaultDacl: PTOKEN_DEFAULT_DACL,
TokenSource: PTOKEN_SOURCE,
) -> NTSTATUS;
fn NtCreateLowBoxToken(
TokenHandle: PHANDLE,
ExistingTokenHandle: HANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
PackageSid: PSID,
CapabilityCount: ULONG,
Capabilities: PSID_AND_ATTRIBUTES,
HandleCount: ULONG,
Handles: *mut HANDLE,
) -> NTSTATUS;
fn NtCreateTokenEx(
TokenHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
TokenType: TOKEN_TYPE,
AuthenticationId: PLUID,
ExpirationTime: PLARGE_INTEGER,
User: PTOKEN_USER,
Groups: PTOKEN_GROUPS,
Privileges: PTOKEN_PRIVILEGES,
UserAttributes: PTOKEN_SECURITY_ATTRIBUTES_INFORMATION,
DeviceAttributes: PTOKEN_SECURITY_ATTRIBUTES_INFORMATION,
DeviceGroups: PTOKEN_GROUPS,
TokenMandatoryPolicy: PTOKEN_MANDATORY_POLICY,
Owner: PTOKEN_OWNER,
PrimaryGroup: PTOKEN_PRIMARY_GROUP,
DefaultDacl: PTOKEN_DEFAULT_DACL,
TokenSource: PTOKEN_SOURCE,
) -> NTSTATUS;
fn NtOpenProcessToken(
ProcessHandle: HANDLE,
DesiredAccess: ACCESS_MASK,
TokenHandle: PHANDLE,
) -> NTSTATUS;
fn NtOpenProcessTokenEx(
ProcessHandle: HANDLE,
DesiredAccess: ACCESS_MASK,
HandleAttributes: ULONG,
TokenHandle: PHANDLE,
) -> NTSTATUS;
fn NtOpenThreadToken(
ThreadHandle: HANDLE,
DesiredAccess: ACCESS_MASK,
OpenAsSelf: BOOLEAN,
TokenHandle: PHANDLE,
) -> NTSTATUS;
fn NtOpenThreadTokenEx(
ThreadHandle: HANDLE,
DesiredAccess: ACCESS_MASK,
OpenAsSelf: BOOLEAN,
HandleAttributes: ULONG,
TokenHandle: PHANDLE,
) -> NTSTATUS;
fn NtDuplicateToken(
ExistingTokenHandle: HANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
EffectiveOnly: BOOLEAN,
TokenType: TOKEN_TYPE,
NewTokenHandle: PHANDLE,
) -> NTSTATUS;
fn NtQueryInformationToken(
TokenHandle: HANDLE,
TokenInformationClass: TOKEN_INFORMATION_CLASS,
TokenInformation: PVOID,
TokenInformationLength: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtSetInformationToken(
TokenHandle: HANDLE,
TokenInformationClass: TOKEN_INFORMATION_CLASS,
TokenInformation: PVOID,
TokenInformationLength: ULONG,
) -> NTSTATUS;
fn NtAdjustPrivilegesToken(
TokenHandle: HANDLE,
DisableAllPrivileges: BOOLEAN,
NewState: PTOKEN_PRIVILEGES,
BufferLength: ULONG,
PreviousState: PTOKEN_PRIVILEGES,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtAdjustGroupsToken(
TokenHandle: HANDLE,
ResetToDefault: BOOLEAN,
NewState: PTOKEN_GROUPS,
BufferLength: ULONG,
PreviousState: PTOKEN_GROUPS,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtAdjustTokenClaimsAndDeviceGroups(
TokenHandle: HANDLE,
UserResetToDefault: BOOLEAN,
DeviceResetToDefault: BOOLEAN,
DeviceGroupsResetToDefault: BOOLEAN,
NewUserState: PTOKEN_SECURITY_ATTRIBUTES_INFORMATION,
NewDeviceState: PTOKEN_SECURITY_ATTRIBUTES_INFORMATION,
NewDeviceGroupsState: PTOKEN_GROUPS,
UserBufferLength: ULONG,
PreviousUserState: PTOKEN_SECURITY_ATTRIBUTES_INFORMATION,
DeviceBufferLength: ULONG,
PreviousDeviceState: PTOKEN_SECURITY_ATTRIBUTES_INFORMATION,
DeviceGroupsBufferLength: ULONG,
PreviousDeviceGroups: PTOKEN_GROUPS,
UserReturnLength: PULONG,
DeviceReturnLength: PULONG,
DeviceGroupsReturnBufferLength: PULONG,
) -> NTSTATUS;
fn NtFilterToken(
ExistingTokenHandle: HANDLE,
Flags: ULONG,
SidsToDisable: PTOKEN_GROUPS,
PrivilegesToDelete: PTOKEN_PRIVILEGES,
RestrictedSids: PTOKEN_GROUPS,
NewTokenHandle: PHANDLE,
) -> NTSTATUS;
fn NtFilterTokenEx(
ExistingTokenHandle: HANDLE,
Flags: ULONG,
SidsToDisable: PTOKEN_GROUPS,
PrivilegesToDelete: PTOKEN_PRIVILEGES,
RestrictedSids: PTOKEN_GROUPS,
DisableUserClaimsCount: ULONG,
UserClaimsToDisable: PUNICODE_STRING,
DisableDeviceClaimsCount: ULONG,
DeviceClaimsToDisable: PUNICODE_STRING,
DeviceGroupsToDisable: PTOKEN_GROUPS,
RestrictedUserAttributes: PTOKEN_SECURITY_ATTRIBUTES_INFORMATION,
RestrictedDeviceAttributes: PTOKEN_SECURITY_ATTRIBUTES_INFORMATION,
RestrictedDeviceGroups: PTOKEN_GROUPS,
NewTokenHandle: PHANDLE,
) -> NTSTATUS;
fn NtCompareTokens(
FirstTokenHandle: HANDLE,
SecondTokenHandle: HANDLE,
Equal: PBOOLEAN,
) -> NTSTATUS;
fn NtPrivilegeCheck(
ClientToken: HANDLE,
RequiredPrivileges: PPRIVILEGE_SET,
Result: PBOOLEAN,
) -> NTSTATUS;
fn NtImpersonateAnonymousToken(
ThreadHandle: HANDLE,
) -> NTSTATUS;
fn NtQuerySecurityAttributesToken(
TokenHandle: HANDLE,
Attributes: PUNICODE_STRING,
NumberOfAttributes: ULONG,
Buffer: PVOID,
Length: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtAccessCheck(
SecurityDescriptor: PSECURITY_DESCRIPTOR,
ClientToken: HANDLE,
DesiredAccess: ACCESS_MASK,
GenericMapping: PGENERIC_MAPPING,
PrivilegeSet: PPRIVILEGE_SET,
PrivilegeSetLength: PULONG,
GrantedAccess: PACCESS_MASK,
AccessStatus: PNTSTATUS,
) -> NTSTATUS;
fn NtAccessCheckByType(
SecurityDescriptor: PSECURITY_DESCRIPTOR,
PrincipalSelfSid: PSID,
ClientToken: HANDLE,
DesiredAccess: ACCESS_MASK,
ObjectTypeList: POBJECT_TYPE_LIST,
ObjectTypeListLength: ULONG,
GenericMapping: PGENERIC_MAPPING,
PrivilegeSet: PPRIVILEGE_SET,
PrivilegeSetLength: PULONG,
GrantedAccess: PACCESS_MASK,
AccessStatus: PNTSTATUS,
) -> NTSTATUS;
fn NtAccessCheckByTypeResultList(
SecurityDescriptor: PSECURITY_DESCRIPTOR,
PrincipalSelfSid: PSID,
ClientToken: HANDLE,
DesiredAccess: ACCESS_MASK,
ObjectTypeList: POBJECT_TYPE_LIST,
ObjectTypeListLength: ULONG,
GenericMapping: PGENERIC_MAPPING,
PrivilegeSet: PPRIVILEGE_SET,
PrivilegeSetLength: PULONG,
GrantedAccess: PACCESS_MASK,
AccessStatus: PNTSTATUS,
) -> NTSTATUS;
fn NtSetCachedSigningLevel(
Flags: ULONG,
InputSigningLevel: SE_SIGNING_LEVEL,
SourceFiles: PHANDLE,
SourceFileCount: ULONG,
TargetFile: HANDLE,
) -> NTSTATUS;
fn NtGetCachedSigningLevel(
File: HANDLE,
Flags: PULONG,
SigningLevel: PSE_SIGNING_LEVEL,
Thumbprint: PUCHAR,
ThumbprintSize: PULONG,
ThumbprintAlgorithm: PULONG,
) -> NTSTATUS;
fn NtAccessCheckAndAuditAlarm(
SubsystemName: PUNICODE_STRING,
HandleId: PVOID,
ObjectTypeName: PUNICODE_STRING,
ObjectName: PUNICODE_STRING,
SecurityDescriptor: PSECURITY_DESCRIPTOR,
DesiredAccess: ACCESS_MASK,
GenericMapping: PGENERIC_MAPPING,
ObjectCreation: BOOLEAN,
GrantedAccess: PACCESS_MASK,
AccessStatus: PNTSTATUS,
GenerateOnClose: PBOOLEAN,
) -> NTSTATUS;
fn NtAccessCheckByTypeAndAuditAlarm(
SubsystemName: PUNICODE_STRING,
HandleId: PVOID,
ObjectTypeName: PUNICODE_STRING,
ObjectName: PUNICODE_STRING,
SecurityDescriptor: PSECURITY_DESCRIPTOR,
PrincipalSelfSid: PSID,
DesiredAccess: ACCESS_MASK,
AuditType: AUDIT_EVENT_TYPE,
Flags: ULONG,
ObjectTypeList: POBJECT_TYPE_LIST,
ObjectTypeListLength: ULONG,
GenericMapping: PGENERIC_MAPPING,
ObjectCreation: BOOLEAN,
GrantedAccess: PACCESS_MASK,
AccessStatus: PNTSTATUS,
GenerateOnClose: PBOOLEAN,
) -> NTSTATUS;
fn NtAccessCheckByTypeResultListAndAuditAlarm(
SubsystemName: PUNICODE_STRING,
HandleId: PVOID,
ObjectTypeName: PUNICODE_STRING,
ObjectName: PUNICODE_STRING,
SecurityDescriptor: PSECURITY_DESCRIPTOR,
PrincipalSelfSid: PSID,
DesiredAccess: ACCESS_MASK,
AuditType: AUDIT_EVENT_TYPE,
Flags: ULONG,
ObjectTypeList: POBJECT_TYPE_LIST,
ObjectTypeListLength: ULONG,
GenericMapping: PGENERIC_MAPPING,
ObjectCreation: BOOLEAN,
GrantedAccess: PACCESS_MASK,
AccessStatus: PNTSTATUS,
GenerateOnClose: PBOOLEAN,
) -> NTSTATUS;
fn NtAccessCheckByTypeResultListAndAuditAlarmByHandle(
SubsystemName: PUNICODE_STRING,
HandleId: PVOID,
ClientToken: HANDLE,
ObjectTypeName: PUNICODE_STRING,
ObjectName: PUNICODE_STRING,
SecurityDescriptor: PSECURITY_DESCRIPTOR,
PrincipalSelfSid: PSID,
DesiredAccess: ACCESS_MASK,
AuditType: AUDIT_EVENT_TYPE,
Flags: ULONG,
ObjectTypeList: POBJECT_TYPE_LIST,
ObjectTypeListLength: ULONG,
GenericMapping: PGENERIC_MAPPING,
ObjectCreation: BOOLEAN,
GrantedAccess: PACCESS_MASK,
AccessStatus: PNTSTATUS,
GenerateOnClose: PBOOLEAN,
) -> NTSTATUS;
fn NtOpenObjectAuditAlarm(
SubsystemName: PUNICODE_STRING,
HandleId: PVOID,
ObjectTypeName: PUNICODE_STRING,
ObjectName: PUNICODE_STRING,
SecurityDescriptor: PSECURITY_DESCRIPTOR,
ClientToken: HANDLE,
DesiredAccess: ACCESS_MASK,
GrantedAccess: ACCESS_MASK,
Privileges: PPRIVILEGE_SET,
ObjectCreation: BOOLEAN,
AccessGranted: BOOLEAN,
GenerateOnClose: PBOOLEAN,
) -> NTSTATUS;
fn NtPrivilegeObjectAuditAlarm(
SubsystemName: PUNICODE_STRING,
HandleId: PVOID,
ClientToken: HANDLE,
DesiredAccess: ACCESS_MASK,
Privileges: PPRIVILEGE_SET,
AccessGranted: BOOLEAN,
) -> NTSTATUS;
fn NtCloseObjectAuditAlarm(
SubsystemName: PUNICODE_STRING,
HandleId: PVOID,
GenerateOnClose: BOOLEAN,
) -> NTSTATUS;
fn NtDeleteObjectAuditAlarm(
SubsystemName: PUNICODE_STRING,
HandleId: PVOID,
GenerateOnClose: BOOLEAN,
) -> NTSTATUS;
fn NtPrivilegedServiceAuditAlarm(
SubsystemName: PUNICODE_STRING,
ServiceName: PUNICODE_STRING,
ClientToken: HANDLE,
Privileges: PPRIVILEGE_SET,
AccessGranted: BOOLEAN,
) -> NTSTATUS;
}}

View file

@ -1,15 +0,0 @@
use crate::ntlpcapi::PPORT_MESSAGE;
use winapi::shared::minwindef::DWORD;
use winapi::shared::ntdef::{HANDLE, NTSTATUS, PHANDLE, PUNICODE_STRING};
EXTERN!{extern "system" {
fn RtlConnectToSm(
ApiPortName: PUNICODE_STRING,
ApiPortHandle: HANDLE,
ProcessImageType: DWORD,
SmssConnection: PHANDLE,
) -> NTSTATUS;
fn RtlSendMsgToSm(
ApiPortHandle: HANDLE,
MessageData: PPORT_MESSAGE,
) -> NTSTATUS;
}}

View file

@ -1,239 +0,0 @@
use winapi::shared::basetsd::ULONG_PTR;
use winapi::shared::guiddef::LPGUID;
use winapi::shared::ktmtypes::{NOTIFICATION_MASK, PCRM_PROTOCOL_ID, PTRANSACTION_NOTIFICATION};
use winapi::shared::ntdef::{
BOOLEAN, HANDLE, NTSTATUS, PHANDLE, PLARGE_INTEGER, POBJECT_ATTRIBUTES, PULONG,
PUNICODE_STRING, PVOID, ULONG,
};
use winapi::um::winnt::{
ACCESS_MASK, ENLISTMENT_INFORMATION_CLASS, KTMOBJECT_TYPE, PKTMOBJECT_CURSOR,
RESOURCEMANAGER_INFORMATION_CLASS, TRANSACTIONMANAGER_INFORMATION_CLASS,
TRANSACTION_INFORMATION_CLASS,
};
EXTERN!{extern "system" {
fn NtCreateTransactionManager(
TmHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
LogFileName: PUNICODE_STRING,
CreateOptions: ULONG,
CommitStrength: ULONG,
) -> NTSTATUS;
fn NtOpenTransactionManager(
TmHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
LogFileName: PUNICODE_STRING,
TmIdentity: LPGUID,
OpenOptions: ULONG,
) -> NTSTATUS;
fn NtRenameTransactionManager(
LogFileName: PUNICODE_STRING,
ExistingTransactionManagerGuid: LPGUID,
) -> NTSTATUS;
fn NtRollforwardTransactionManager(
TransactionManagerHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtRecoverTransactionManager(
TransactionManagerHandle: HANDLE,
) -> NTSTATUS;
fn NtQueryInformationTransactionManager(
TransactionManagerHandle: HANDLE,
TransactionManagerInformationClass: TRANSACTIONMANAGER_INFORMATION_CLASS,
TransactionManagerInformation: PVOID,
TransactionManagerInformationLength: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtSetInformationTransactionManager(
TmHandle: HANDLE,
TransactionManagerInformationClass: TRANSACTIONMANAGER_INFORMATION_CLASS,
TransactionManagerInformation: PVOID,
TransactionManagerInformationLength: ULONG,
) -> NTSTATUS;
fn NtEnumerateTransactionObject(
RootObjectHandle: HANDLE,
QueryType: KTMOBJECT_TYPE,
ObjectCursor: PKTMOBJECT_CURSOR,
ObjectCursorLength: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtCreateTransaction(
TransactionHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
Uow: LPGUID,
TmHandle: HANDLE,
CreateOptions: ULONG,
IsolationLevel: ULONG,
IsolationFlags: ULONG,
Timeout: PLARGE_INTEGER,
Description: PUNICODE_STRING,
) -> NTSTATUS;
fn NtOpenTransaction(
TransactionHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ObjectAttributes: POBJECT_ATTRIBUTES,
Uow: LPGUID,
TmHandle: HANDLE,
) -> NTSTATUS;
fn NtQueryInformationTransaction(
TransactionHandle: HANDLE,
TransactionInformationClass: TRANSACTION_INFORMATION_CLASS,
TransactionInformation: PVOID,
TransactionInformationLength: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtSetInformationTransaction(
TransactionHandle: HANDLE,
TransactionInformationClass: TRANSACTION_INFORMATION_CLASS,
TransactionInformation: PVOID,
TransactionInformationLength: ULONG,
) -> NTSTATUS;
fn NtCommitTransaction(
TransactionHandle: HANDLE,
Wait: BOOLEAN,
) -> NTSTATUS;
fn NtRollbackTransaction(
TransactionHandle: HANDLE,
Wait: BOOLEAN,
) -> NTSTATUS;
fn NtCreateEnlistment(
EnlistmentHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ResourceManagerHandle: HANDLE,
TransactionHandle: HANDLE,
ObjectAttributes: POBJECT_ATTRIBUTES,
CreateOptions: ULONG,
NotificationMask: NOTIFICATION_MASK,
EnlistmentKey: PVOID,
) -> NTSTATUS;
fn NtOpenEnlistment(
EnlistmentHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
ResourceManagerHandle: HANDLE,
EnlistmentGuid: LPGUID,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtQueryInformationEnlistment(
EnlistmentHandle: HANDLE,
EnlistmentInformationClass: ENLISTMENT_INFORMATION_CLASS,
EnlistmentInformation: PVOID,
EnlistmentInformationLength: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtSetInformationEnlistment(
EnlistmentHandle: HANDLE,
EnlistmentInformationClass: ENLISTMENT_INFORMATION_CLASS,
EnlistmentInformation: PVOID,
EnlistmentInformationLength: ULONG,
) -> NTSTATUS;
fn NtRecoverEnlistment(
EnlistmentHandle: HANDLE,
EnlistmentKey: PVOID,
) -> NTSTATUS;
fn NtPrePrepareEnlistment(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtPrepareEnlistment(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtCommitEnlistment(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtRollbackEnlistment(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtPrePrepareComplete(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtPrepareComplete(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtCommitComplete(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtReadOnlyEnlistment(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtRollbackComplete(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtSinglePhaseReject(
EnlistmentHandle: HANDLE,
TmVirtualClock: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtCreateResourceManager(
ResourceManagerHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
TmHandle: HANDLE,
RmGuid: LPGUID,
ObjectAttributes: POBJECT_ATTRIBUTES,
CreateOptions: ULONG,
Description: PUNICODE_STRING,
) -> NTSTATUS;
fn NtOpenResourceManager(
ResourceManagerHandle: PHANDLE,
DesiredAccess: ACCESS_MASK,
TmHandle: HANDLE,
ResourceManagerGuid: LPGUID,
ObjectAttributes: POBJECT_ATTRIBUTES,
) -> NTSTATUS;
fn NtRecoverResourceManager(
ResourceManagerHandle: HANDLE,
) -> NTSTATUS;
fn NtGetNotificationResourceManager(
ResourceManagerHandle: HANDLE,
TransactionNotification: PTRANSACTION_NOTIFICATION,
NotificationLength: ULONG,
Timeout: PLARGE_INTEGER,
ReturnLength: PULONG,
Asynchronous: ULONG,
AsynchronousContext: ULONG_PTR,
) -> NTSTATUS;
fn NtQueryInformationResourceManager(
ResourceManagerHandle: HANDLE,
ResourceManagerInformationClass: RESOURCEMANAGER_INFORMATION_CLASS,
ResourceManagerInformation: PVOID,
ResourceManagerInformationLength: ULONG,
ReturnLength: PULONG,
) -> NTSTATUS;
fn NtSetInformationResourceManager(
ResourceManagerHandle: HANDLE,
ResourceManagerInformationClass: RESOURCEMANAGER_INFORMATION_CLASS,
ResourceManagerInformation: PVOID,
ResourceManagerInformationLength: ULONG,
) -> NTSTATUS;
fn NtRegisterProtocolAddressInformation(
ResourceManager: HANDLE,
ProtocolId: PCRM_PROTOCOL_ID,
ProtocolInformationSize: ULONG,
ProtocolInformation: PVOID,
CreateOptions: ULONG,
) -> NTSTATUS;
fn NtPropagationComplete(
ResourceManagerHandle: HANDLE,
RequestCookie: ULONG,
BufferLength: ULONG,
Buffer: PVOID,
) -> NTSTATUS;
fn NtPropagationFailed(
ResourceManagerHandle: HANDLE,
RequestCookie: ULONG,
PropStatus: NTSTATUS,
) -> NTSTATUS;
fn NtFreezeTransactions(
FreezeTimeout: PLARGE_INTEGER,
ThawTimeout: PLARGE_INTEGER,
) -> NTSTATUS;
fn NtThawTransactions() -> NTSTATUS;
}}

View file

@ -1,207 +0,0 @@
use crate::ntioapi::PIO_STATUS_BLOCK;
use winapi::shared::ntdef::{HANDLE, LOGICAL, LONG, NTSTATUS, PLARGE_INTEGER, PVOID};
use winapi::um::winnt::{
PRTL_CRITICAL_SECTION, PTP_CALLBACK_ENVIRON, PTP_CALLBACK_INSTANCE, PTP_CLEANUP_GROUP, PTP_IO,
PTP_POOL, PTP_POOL_STACK_INFORMATION, PTP_SIMPLE_CALLBACK, PTP_TIMER, PTP_TIMER_CALLBACK,
PTP_WAIT, PTP_WAIT_CALLBACK, PTP_WORK, PTP_WORK_CALLBACK,
};
#[repr(C)]
pub struct TP_ALPC([u8; 0]);
pub type PTP_ALPC = *mut TP_ALPC;
FN!{stdcall PTP_ALPC_CALLBACK(
Instance: PTP_CALLBACK_INSTANCE,
Context: PVOID,
Alpc: PTP_ALPC,
) -> ()}
FN!{stdcall PTP_ALPC_CALLBACK_EX(
Instanc: PTP_CALLBACK_INSTANCE,
Contex: PVOID,
Alp: PTP_ALPC,
ApcContext: PVOID,
) -> ()}
EXTERN!{extern "system" {
fn TpAllocPool(
PoolReturn: *mut PTP_POOL,
Reserved: PVOID,
) -> NTSTATUS;
fn TpReleasePool(
Pool: PTP_POOL,
);
fn TpSetPoolMaxThreads(
Pool: PTP_POOL,
MaxThreads: LONG,
);
fn TpSetPoolMinThreads(
Pool: PTP_POOL,
MinThreads: LONG,
) -> NTSTATUS;
fn TpQueryPoolStackInformation(
Pool: PTP_POOL,
PoolStackInformation: PTP_POOL_STACK_INFORMATION,
) -> NTSTATUS;
fn TpSetPoolStackInformation(
Pool: PTP_POOL,
PoolStackInformation: PTP_POOL_STACK_INFORMATION,
) -> NTSTATUS;
fn TpAllocCleanupGroup(
CleanupGroupReturn: *mut PTP_CLEANUP_GROUP,
) -> NTSTATUS;
fn TpReleaseCleanupGroup(
CleanupGroup: PTP_CLEANUP_GROUP,
);
fn TpReleaseCleanupGroupMembers(
CleanupGroup: PTP_CLEANUP_GROUP,
CancelPendingCallbacks: LOGICAL,
CleanupParameter: PVOID,
);
fn TpCallbackSetEventOnCompletion(
Instance: PTP_CALLBACK_INSTANCE,
Event: HANDLE,
);
fn TpCallbackReleaseSemaphoreOnCompletion(
Instance: PTP_CALLBACK_INSTANCE,
Semaphore: HANDLE,
ReleaseCount: LONG,
);
fn TpCallbackReleaseMutexOnCompletion(
Instance: PTP_CALLBACK_INSTANCE,
Mutex: HANDLE,
);
fn TpCallbackLeaveCriticalSectionOnCompletion(
Instance: PTP_CALLBACK_INSTANCE,
CriticalSection: PRTL_CRITICAL_SECTION,
);
fn TpCallbackUnloadDllOnCompletion(
Instance: PTP_CALLBACK_INSTANCE,
DllHandle: PVOID,
);
fn TpCallbackMayRunLong(
Instance: PTP_CALLBACK_INSTANCE,
) -> NTSTATUS;
fn TpDisassociateCallback(
Instance: PTP_CALLBACK_INSTANCE,
);
fn TpSimpleTryPost(
Callback: PTP_SIMPLE_CALLBACK,
Context: PVOID,
CallbackEnviron: PTP_CALLBACK_ENVIRON,
) -> NTSTATUS;
fn TpAllocWork(
WorkReturn: *mut PTP_WORK,
Callback: PTP_WORK_CALLBACK,
Context: PVOID,
CallbackEnviron: PTP_CALLBACK_ENVIRON,
) -> NTSTATUS;
fn TpReleaseWork(
Work: PTP_WORK,
);
fn TpPostWork(
Work: PTP_WORK,
);
fn TpWaitForWork(
Work: PTP_WORK,
CancelPendingCallbacks: LOGICAL,
);
fn TpAllocTimer(
Timer: *mut PTP_TIMER,
Callback: PTP_TIMER_CALLBACK,
Context: PVOID,
CallbackEnviron: PTP_CALLBACK_ENVIRON,
) -> NTSTATUS;
fn TpReleaseTimer(
Timer: PTP_TIMER,
);
fn TpSetTimer(
Timer: PTP_TIMER,
DueTime: PLARGE_INTEGER,
Period: LONG,
WindowLength: LONG,
);
fn TpIsTimerSet(
Timer: PTP_TIMER,
) -> LOGICAL;
fn TpWaitForTimer(
Timer: PTP_TIMER,
CancelPendingCallbacks: LOGICAL,
);
fn TpAllocWait(
WaitReturn: *mut PTP_WAIT,
Callback: PTP_WAIT_CALLBACK,
Context: PVOID,
CallbackEnviron: PTP_CALLBACK_ENVIRON,
) -> NTSTATUS;
fn TpReleaseWait(
Wait: PTP_WAIT,
);
fn TpSetWait(
Wait: PTP_WAIT,
Handle: HANDLE,
Timeout: PLARGE_INTEGER,
);
fn TpWaitForWait(
Wait: PTP_WAIT,
CancelPendingCallbacks: LOGICAL,
);
}}
FN!{stdcall PTP_IO_CALLBACK(
Instance: PTP_CALLBACK_INSTANCE,
Context: PVOID,
ApcContext: PVOID,
IoSB: PIO_STATUS_BLOCK,
Io: PTP_IO,
) -> ()}
EXTERN!{extern "system" {
fn TpAllocIoCompletion(
IoReturn: *mut PTP_IO,
File: HANDLE,
Callback: PTP_IO_CALLBACK,
Context: PVOID,
CallbackEnviron: PTP_CALLBACK_ENVIRON,
) -> NTSTATUS;
fn TpReleaseIoCompletion(
Io: PTP_IO,
);
fn TpStartAsyncIoOperation(
Io: PTP_IO,
);
fn TpCancelAsyncIoOperation(
Io: PTP_IO,
);
fn TpWaitForIoCompletion(
Io: PTP_IO,
CancelPendingCallbacks: LOGICAL,
);
fn TpAllocAlpcCompletion(
AlpcReturn: *mut PTP_ALPC,
AlpcPort: HANDLE,
Callback: PTP_ALPC_CALLBACK,
Context: PVOID,
CallbackEnviron: PTP_CALLBACK_ENVIRON,
) -> NTSTATUS;
fn TpAllocAlpcCompletionEx(
AlpcReturn: *mut PTP_ALPC,
AlpcPort: HANDLE,
Callback: PTP_ALPC_CALLBACK_EX,
Context: PVOID,
CallbackEnviron: PTP_CALLBACK_ENVIRON,
) -> NTSTATUS;
fn TpReleaseAlpcCompletion(
Alpc: PTP_ALPC,
);
fn TpWaitForAlpcCompletion(
Alpc: PTP_ALPC,
);
}}
ENUM!{enum TP_TRACE_TYPE {
TpTraceThreadPriority = 1,
TpTraceThreadAffinity = 2,
MaxTpTraceType = 3,
}}
EXTERN!{extern "system" {
fn TpCaptureCaller(
Type: TP_TRACE_TYPE,
);
fn TpCheckTerminateWorker(
Thread: HANDLE,
);
}}

View file

@ -1,476 +0,0 @@
use core::mem::size_of;
use crate::ntapi_base::CLIENT_ID32;
use crate::ntldr::{LDR_DDAG_STATE, LDR_DLL_LOAD_REASON};
use crate::ntpsapi::GDI_HANDLE_BUFFER32;
use crate::ntrtl::RTL_MAX_DRIVE_LETTERS;
use crate::string::{UTF16Const, UTF8Const};
use winapi::shared::guiddef::GUID;
use winapi::shared::ntdef::{
BOOLEAN, CHAR, LARGE_INTEGER, LCID, LIST_ENTRY32, LONG, NTSTATUS, PROCESSOR_NUMBER,
SINGLE_LIST_ENTRY32, STRING32, UCHAR, ULARGE_INTEGER, ULONG, ULONGLONG, UNICODE_STRING,
UNICODE_STRING32, USHORT, WCHAR,
};
use winapi::um::winnt::{FLS_MAXIMUM_AVAILABLE, NT_TIB32};
pub const WOW64_SYSTEM_DIRECTORY: UTF8Const = UTF8Const("SysWOW64\0");
/// "SysWOW64"
pub const WOW64_SYSTEM_DIRECTORY_U: UTF16Const = UTF16Const(&[
0x0053, 0x0079, 0x0073, 0x0057, 0x004F, 0x0057, 0x0036, 0x0034, 0u16,
]);
pub const WOW64_X86_TAG: UTF8Const = UTF8Const(" (x86)\0");
/// " (x86)"
pub const WOW64_X86_TAG_U: UTF16Const = UTF16Const(&[
0x0020, 0x0028, 0x0078, 0x0038, 0x0036, 0x0029, 0u16,
]);
ENUM!{enum WOW64_SHARED_INFORMATION {
SharedNtdll32LdrInitializeThunk = 0,
SharedNtdll32KiUserExceptionDispatcher = 1,
SharedNtdll32KiUserApcDispatcher = 2,
SharedNtdll32KiUserCallbackDispatcher = 3,
SharedNtdll32ExpInterlockedPopEntrySListFault = 4,
SharedNtdll32ExpInterlockedPopEntrySListResume = 5,
SharedNtdll32ExpInterlockedPopEntrySListEnd = 6,
SharedNtdll32RtlUserThreadStart = 7,
SharedNtdll32pQueryProcessDebugInformationRemote = 8,
SharedNtdll32BaseAddress = 9,
SharedNtdll32LdrSystemDllInitBlock = 10,
Wow64SharedPageEntriesCount = 11,
}}
STRUCT!{struct RTL_BALANCED_NODE32_u_s {
Left: ULONG, // WOW64_POINTER
Right: ULONG, // WOW64_POINTER
}}
UNION!{union RTL_BALANCED_NODE32_u {
Children: [ULONG; 2], // WOW64_POINTER
s: RTL_BALANCED_NODE32_u_s,
}}
STRUCT!{struct RTL_BALANCED_NODE32 {
u: RTL_BALANCED_NODE32_u,
ParentValue: ULONG,
}}
pub type PRTL_BALANCED_NODE32 = *mut RTL_BALANCED_NODE32;
STRUCT!{struct RTL_RB_TREE32 {
Root: ULONG, // WOW64_POINTER
Min: ULONG, // WOW64_POINTER
}}
pub type PRTL_RB_TREE32 = *mut RTL_RB_TREE32;
STRUCT!{struct PEB_LDR_DATA32 {
Length: ULONG,
Initialized: BOOLEAN,
SsHandle: ULONG,
InLoadOrderModuleList: LIST_ENTRY32,
InMemoryOrderModuleList: LIST_ENTRY32,
InInitializationOrderModuleList: LIST_ENTRY32,
EntryInProgress: ULONG,
ShutdownInProgress: BOOLEAN,
ShutdownThreadId: ULONG,
}}
pub type PPEB_LDR_DATA32 = *mut PEB_LDR_DATA32;
STRUCT!{struct LDR_SERVICE_TAG_RECORD32 {
Next: ULONG,
ServiceTag: ULONG,
}}
pub type PLDR_SERVICE_TAG_RECORD32 = *mut LDR_SERVICE_TAG_RECORD32;
STRUCT!{struct LDRP_CSLIST32 {
Tail: ULONG, // WOW64_POINTER
}}
pub type PLDRP_CSLIST32 = *mut LDRP_CSLIST32;
UNION!{union LDR_DDAG_NODE32_u {
Dependencies: LDRP_CSLIST32,
RemovalLink: SINGLE_LIST_ENTRY32,
}}
STRUCT!{struct LDR_DDAG_NODE32 {
Modules: LIST_ENTRY32,
ServiceTagList: ULONG, // WOW64_POINTER
LoadCount: ULONG,
LoadWhileUnloadingCount: ULONG,
LowestLink: ULONG,
u: LDR_DDAG_NODE32_u,
IncomingDependencies: LDRP_CSLIST32,
State: LDR_DDAG_STATE,
CondenseLink: SINGLE_LIST_ENTRY32,
PreorderNumber: ULONG,
}}
pub type PLDR_DDAG_NODE32 = *mut LDR_DDAG_NODE32;
pub const LDR_DATA_TABLE_ENTRY_SIZE_WINXP_32: usize = 80;
pub const LDR_DATA_TABLE_ENTRY_SIZE_WIN7_32: usize = 144;
pub const LDR_DATA_TABLE_ENTRY_SIZE_WIN8_32: usize = 152;
UNION!{union LDR_DATA_TABLE_ENTRY32_u1 {
InInitializationOrderLinks: LIST_ENTRY32,
InProgressLinks: LIST_ENTRY32,
}}
UNION!{union LDR_DATA_TABLE_ENTRY32_u2 {
FlagGroup: [UCHAR; 4],
Flags: ULONG,
}}
STRUCT!{struct LDR_DATA_TABLE_ENTRY32 {
InLoadOrderLinks: LIST_ENTRY32,
InMemoryOrderLinks: LIST_ENTRY32,
u1: LDR_DATA_TABLE_ENTRY32_u1,
DllBase: ULONG, // WOW64_POINTER
EntryPoint: ULONG, // WOW64_POINTER
SizeOfImage: ULONG,
FullDllName: UNICODE_STRING32,
BaseDllName: UNICODE_STRING32,
u2: LDR_DATA_TABLE_ENTRY32_u2,
ObsoleteLoadCount: USHORT,
TlsIndex: USHORT,
HashLinks: LIST_ENTRY32,
TimeDateStamp: ULONG,
EntryPointActivationContext: ULONG, // WOW64_POINTER
Lock: ULONG, // WOW64_POINTER
DdagNode: ULONG, // WOW64_POINTER
NodeModuleLink: LIST_ENTRY32,
LoadContext: ULONG, // WOW64_POINTER
ParentDllBase: ULONG, // WOW64_POINTER
SwitchBackContext: ULONG, // WOW64_POINTER
BaseAddressIndexNode: RTL_BALANCED_NODE32,
MappingInfoIndexNode: RTL_BALANCED_NODE32,
OriginalBase: ULONG,
LoadTime: LARGE_INTEGER,
BaseNameHashValue: ULONG,
LoadReason: LDR_DLL_LOAD_REASON,
ImplicitPathOptions: ULONG,
ReferenceCount: ULONG,
DependentLoadFlags: ULONG,
SigningLevel: UCHAR,
}}
BITFIELD!{unsafe LDR_DATA_TABLE_ENTRY32_u2 Flags: ULONG [
PackagedBinary set_PackagedBinary[0..1],
MarkedForRemoval set_MarkedForRemoval[1..2],
ImageDll set_ImageDll[2..3],
LoadNotificationsSent set_LoadNotificationsSent[3..4],
TelemetryEntryProcessed set_TelemetryEntryProcessed[4..5],
ProcessStaticImport set_ProcessStaticImport[5..6],
InLegacyLists set_InLegacyLists[6..7],
InIndexes set_InIndexes[7..8],
ShimDll set_ShimDll[8..9],
InExceptionTable set_InExceptionTable[9..10],
ReservedFlags1 set_ReservedFlags1[10..12],
LoadInProgress set_LoadInProgress[12..13],
LoadConfigProcessed set_LoadConfigProcessed[13..14],
EntryProcessed set_EntryProcessed[14..15],
ProtectDelayLoad set_ProtectDelayLoad[15..16],
ReservedFlags3 set_ReservedFlags3[16..18],
DontCallForThreads set_DontCallForThreads[18..19],
ProcessAttachCalled set_ProcessAttachCalled[19..20],
ProcessAttachFailed set_ProcessAttachFailed[20..21],
CorDeferredValidate set_CorDeferredValidate[21..22],
CorImage set_CorImage[22..23],
DontRelocate set_DontRelocate[23..24],
CorILOnly set_CorILOnly[24..25],
ReservedFlags5 set_ReservedFlags5[25..28],
Redirected set_Redirected[28..29],
ReservedFlags6 set_ReservedFlags6[29..31],
CompatDatabaseProcessed set_CompatDatabaseProcessed[31..32],
]}
pub type PLDR_DATA_TABLE_ENTRY32 = *mut LDR_DATA_TABLE_ENTRY32;
STRUCT!{struct CURDIR32 {
DosPath: UNICODE_STRING32,
Handle: ULONG, // WOW64_POINTER
}}
pub type PCURDIR32 = *mut CURDIR32;
STRUCT!{struct RTL_DRIVE_LETTER_CURDIR32 {
Flags: USHORT,
Length: USHORT,
TimeStamp: ULONG,
DosPath: STRING32,
}}
pub type PRTL_DRIVE_LETTER_CURDIR32 = *mut RTL_DRIVE_LETTER_CURDIR32;
STRUCT!{struct RTL_USER_PROCESS_PARAMETERS32 {
MaximumLength: ULONG,
Length: ULONG,
Flags: ULONG,
DebugFlags: ULONG,
ConsoleHandle: ULONG, // WOW64_POINTER
ConsoleFlags: ULONG,
StandardInput: ULONG, // WOW64_POINTER
StandardOutput: ULONG, // WOW64_POINTER
StandardError: ULONG, // WOW64_POINTER
CurrentDirectory: CURDIR32,
DllPath: UNICODE_STRING32,
ImagePathName: UNICODE_STRING32,
CommandLine: UNICODE_STRING32,
Environment: ULONG, // WOW64_POINTER
StartingX: ULONG,
StartingY: ULONG,
CountX: ULONG,
CountY: ULONG,
CountCharsX: ULONG,
CountCharsY: ULONG,
FillAttribute: ULONG,
WindowFlags: ULONG,
ShowWindowFlags: ULONG,
WindowTitle: UNICODE_STRING32,
DesktopInfo: UNICODE_STRING32,
ShellInfo: UNICODE_STRING32,
RuntimeData: UNICODE_STRING32,
CurrentDirectories: [RTL_DRIVE_LETTER_CURDIR32; RTL_MAX_DRIVE_LETTERS],
EnvironmentSize: ULONG,
EnvironmentVersion: ULONG,
PackageDependencyData: ULONG, // WOW64_POINTER
ProcessGroupId: ULONG,
LoaderThreads: ULONG,
}}
pub type PRTL_USER_PROCESS_PARAMETERS32 = *mut RTL_USER_PROCESS_PARAMETERS32;
UNION!{union PEB32_u {
KernelCallbackTable: ULONG, // WOW64_POINTER
UserSharedInfoPtr: ULONG, // WOW64_POINTER
}}
STRUCT!{struct PEB32 {
InheritedAddressSpace: BOOLEAN,
ReadImageFileExecOptions: BOOLEAN,
BeingDebugged: BOOLEAN,
BitField: BOOLEAN,
Mutant: ULONG, // WOW64_POINTER
ImageBaseAddress: ULONG, // WOW64_POINTER
Ldr: ULONG, // WOW64_POINTER
ProcessParameters: ULONG, // WOW64_POINTER
SubSystemData: ULONG, // WOW64_POINTER
ProcessHeap: ULONG, // WOW64_POINTER
FastPebLock: ULONG, // WOW64_POINTER
AtlThunkSListPtr: ULONG, // WOW64_POINTER
IFEOKey: ULONG, // WOW64_POINTER
CrossProcessFlags: ULONG,
u: PEB32_u,
SystemReserved: [ULONG; 1],
AtlThunkSListPtr32: ULONG,
ApiSetMap: ULONG, // WOW64_POINTER
TlsExpansionCounter: ULONG,
TlsBitmap: ULONG, // WOW64_POINTER
TlsBitmapBits: [ULONG; 2],
ReadOnlySharedMemoryBase: ULONG, // WOW64_POINTER
HotpatchInformation: ULONG, // WOW64_POINTER
ReadOnlyStaticServerData: ULONG, // WOW64_POINTER
AnsiCodePageData: ULONG, // WOW64_POINTER
OemCodePageData: ULONG, // WOW64_POINTER
UnicodeCaseTableData: ULONG, // WOW64_POINTER
NumberOfProcessors: ULONG,
NtGlobalFlag: ULONG,
CriticalSectionTimeout: LARGE_INTEGER,
HeapSegmentReserve: ULONG,
HeapSegmentCommit: ULONG,
HeapDeCommitTotalFreeThreshold: ULONG,
HeapDeCommitFreeBlockThreshold: ULONG,
NumberOfHeaps: ULONG,
MaximumNumberOfHeaps: ULONG,
ProcessHeaps: ULONG, // WOW64_POINTER
GdiSharedHandleTable: ULONG, // WOW64_POINTER
ProcessStarterHelper: ULONG, // WOW64_POINTER
GdiDCAttributeList: ULONG,
LoaderLock: ULONG, // WOW64_POINTER
OSMajorVersion: ULONG,
OSMinorVersion: ULONG,
OSBuildNumber: USHORT,
OSCSDVersion: USHORT,
OSPlatformId: ULONG,
ImageSubsystem: ULONG,
ImageSubsystemMajorVersion: ULONG,
ImageSubsystemMinorVersion: ULONG,
ActiveProcessAffinityMask: ULONG,
GdiHandleBuffer: GDI_HANDLE_BUFFER32,
PostProcessInitRoutine: ULONG, // WOW64_POINTER
TlsExpansionBitmap: ULONG, // WOW64_POINTER
TlsExpansionBitmapBits: [ULONG; 32],
SessionId: ULONG,
AppCompatFlags: ULARGE_INTEGER,
AppCompatFlagsUser: ULARGE_INTEGER,
pShimData: ULONG, // WOW64_POINTER
AppCompatInfo: ULONG, // WOW64_POINTER
CSDVersion: UNICODE_STRING32,
ActivationContextData: ULONG, // WOW64_POINTER
ProcessAssemblyStorageMap: ULONG, // WOW64_POINTER
SystemDefaultActivationContextData: ULONG, // WOW64_POINTER
SystemAssemblyStorageMap: ULONG, // WOW64_POINTER
MinimumStackCommit: ULONG,
FlsCallback: ULONG, // WOW64_POINTER
FlsListHead: LIST_ENTRY32,
FlsBitmap: ULONG, // WOW64_POINTER
FlsBitmapBits: [ULONG; FLS_MAXIMUM_AVAILABLE as usize / (size_of::<ULONG>() * 8)],
FlsHighIndex: ULONG,
WerRegistrationData: ULONG, // WOW64_POINTER
WerShipAssertPtr: ULONG, // WOW64_POINTER
pContextData: ULONG, // WOW64_POINTER
pImageHeaderHash: ULONG, // WOW64_POINTER
TracingFlags: ULONG,
CsrServerReadOnlySharedMemoryBase: ULONGLONG,
TppWorkerpListLock: ULONG, // WOW64_POINTER
TppWorkerpList: LIST_ENTRY32,
WaitOnAddressHashTable: [ULONG; 128], // WOW64_POINTER
TelemetryCoverageHeader: ULONG, // WOW64_POINTER
CloudFileFlags: ULONG,
CloudFileDiagFlags: ULONG,
PlaceholderCompatibilityMode: CHAR,
PlaceholderCompatibilityModeReserved: [CHAR; 7],
}}
BITFIELD!{PEB32 BitField: BOOLEAN [
ImageUsesLargePages set_ImageUsesLargePages[0..1],
IsProtectedProcess set_IsProtectedProcess[1..2],
IsImageDynamicallyRelocated set_IsImageDynamicallyRelocated[2..3],
SkipPatchingUser32Forwarders set_SkipPatchingUser32Forwarders[3..4],
IsPackagedProcess set_IsPackagedProcess[4..5],
IsAppContainer set_IsAppContainer[5..6],
IsProtectedProcessLight set_IsProtectedProcessLight[6..7],
IsLongPathAwareProcess set_IsLongPathAwareProcess[7..8],
]}
BITFIELD!{PEB32 CrossProcessFlags: ULONG [
ProcessInJob set_ProcessInJob[0..1],
ProcessInitializing set_ProcessInitializing[1..2],
ProcessUsingVEH set_ProcessUsingVEH[2..3],
ProcessUsingVCH set_ProcessUsingVCH[3..4],
ProcessUsingFTH set_ProcessUsingFTH[4..5],
ReservedBits0 set_ReservedBits0[5..32],
]}
BITFIELD!{PEB32 TracingFlags: ULONG [
HeapTracingEnabled set_HeapTracingEnabled[0..1],
CritSecTracingEnabled set_CritSecTracingEnabled[1..2],
LibLoaderTracingEnabled set_LibLoaderTracingEnabled[2..3],
SpareTracingBits set_SpareTracingBits[3..32],
]}
pub type PPEB32 = *mut PEB32;
pub const GDI_BATCH_BUFFER_SIZE: usize = 310;
STRUCT!{struct GDI_TEB_BATCH32 {
Offset: ULONG,
HDC: ULONG,
Buffer: [ULONG; GDI_BATCH_BUFFER_SIZE],
}}
pub type PGDI_TEB_BATCH32 = *mut GDI_TEB_BATCH32;
STRUCT!{struct TEB32_u_s {
ReservedPad0: UCHAR,
ReservedPad1: UCHAR,
ReservedPad2: UCHAR,
IdealProcessor: UCHAR,
}}
UNION!{union TEB32_u {
CurrentIdealProcessor: PROCESSOR_NUMBER,
IdealProcessorValue: ULONG,
s: TEB32_u_s,
}}
STRUCT!{struct TEB32 {
NtTib: NT_TIB32,
EnvironmentPointer: ULONG, // WOW64_POINTER
ClientId: CLIENT_ID32,
ActiveRpcHandle: ULONG, // WOW64_POINTER
ThreadLocalStoragePointer: ULONG, // WOW64_POINTER
ProcessEnvironmentBlock: ULONG, // WOW64_POINTER
LastErrorValue: ULONG,
CountOfOwnedCriticalSections: ULONG,
CsrClientThread: ULONG, // WOW64_POINTER
Win32ThreadInfo: ULONG, // WOW64_POINTER
User32Reserved: [ULONG; 26],
UserReserved: [ULONG; 5],
WOW32Reserved: ULONG, // WOW64_POINTER
CurrentLocale: LCID,
FpSoftwareStatusRegister: ULONG,
ReservedForDebuggerInstrumentation: [ULONG; 16], // WOW64_POINTER
SystemReserved1: [ULONG; 36], // WOW64_POINTER
WorkingOnBehalfTicket: [UCHAR; 8],
ExceptionCode: NTSTATUS,
ActivationContextStackPointer: ULONG, // WOW64_POINTER
InstrumentationCallbackSp: ULONG,
InstrumentationCallbackPreviousPc: ULONG,
InstrumentationCallbackPreviousSp: ULONG,
InstrumentationCallbackDisabled: BOOLEAN,
SpareBytes: [UCHAR; 23],
TxFsContext: ULONG,
GdiTebBatch: GDI_TEB_BATCH32,
RealClientId: CLIENT_ID32,
GdiCachedProcessHandle: ULONG, // WOW64_POINTER
GdiClientPID: ULONG,
GdiClientTID: ULONG,
GdiThreadLocalInfo: ULONG, // WOW64_POINTER
Win32ClientInfo: [ULONG; 62],
glDispatchTable: [ULONG; 233], // WOW64_POINTER
glReserved1: [ULONG; 29], // WOW64_POINTER
glReserved2: ULONG, // WOW64_POINTER
glSectionInfo: ULONG, // WOW64_POINTER
glSection: ULONG, // WOW64_POINTER
glTable: ULONG, // WOW64_POINTER
glCurrentRC: ULONG, // WOW64_POINTER
glContext: ULONG, // WOW64_POINTER
LastStatusValue: NTSTATUS,
StaticUnicodeString: UNICODE_STRING32,
StaticUnicodeBuffer: [WCHAR; 261],
DeallocationStack: ULONG, // WOW64_POINTER
TlsSlots: [ULONG; 64], // WOW64_POINTER
TlsLinks: LIST_ENTRY32,
Vdm: ULONG, // WOW64_POINTER
ReservedForNtRpc: ULONG, // WOW64_POINTER
DbgSsReserved: [ULONG; 2], // WOW64_POINTER
HardErrorMode: ULONG,
Instrumentation: [ULONG; 9], // WOW64_POINTER
ActivityId: GUID,
SubProcessTag: ULONG, // WOW64_POINTER
PerflibData: ULONG, // WOW64_POINTER
EtwTraceData: ULONG, // WOW64_POINTER
WinSockData: ULONG, // WOW64_POINTER
GdiBatchCount: ULONG,
u: TEB32_u,
GuaranteedStackBytes: ULONG,
ReservedForPerf: ULONG, // WOW64_POINTER
ReservedForOle: ULONG, // WOW64_POINTER
WaitingOnLoaderLock: ULONG,
SavedPriorityState: ULONG, // WOW64_POINTER
ReservedForCodeCoverage: ULONG,
ThreadPoolData: ULONG, // WOW64_POINTER
TlsExpansionSlots: ULONG, // WOW64_POINTER
MuiGeneration: ULONG,
IsImpersonating: ULONG,
NlsCache: ULONG, // WOW64_POINTER
pShimData: ULONG, // WOW64_POINTER
HeapVirtualAffinity: USHORT,
LowFragHeapDataSlot: USHORT,
CurrentTransactionHandle: ULONG, // WOW64_POINTER
ActiveFrame: ULONG, // WOW64_POINTER
FlsData: ULONG, // WOW64_POINTER
PreferredLanguages: ULONG, // WOW64_POINTER
UserPrefLanguages: ULONG, // WOW64_POINTER
MergedPrefLanguages: ULONG, // WOW64_POINTER
MuiImpersonation: ULONG,
CrossTebFlags: USHORT,
SameTebFlags: USHORT,
TxnScopeEnterCallback: ULONG, // WOW64_POINTER
TxnScopeExitCallback: ULONG, // WOW64_POINTER
TxnScopeContext: ULONG, // WOW64_POINTER
LockCount: ULONG,
WowTebOffset: LONG,
ResourceRetValue: ULONG, // WOW64_POINTER
ReservedForWdf: ULONG, // WOW64_POINTER
ReservedForCrt: ULONGLONG,
EffectiveContainerId: GUID,
}}
BITFIELD!{TEB32 SameTebFlags: USHORT [
SafeThunkCall set_SafeThunkCall[0..1],
InDebugPrint set_InDebugPrint[1..2],
HasFiberData set_HasFiberData[2..3],
SkipThreadAttach set_SkipThreadAttach[3..4],
WerInShipAssertCode set_WerInShipAssertCode[4..5],
RanProcessInit set_RanProcessInit[5..6],
ClonedThread set_ClonedThread[6..7],
SuppressDebugMsg set_SuppressDebugMsg[7..8],
DisableUserStackWalk set_DisableUserStackWalk[8..9],
RtlExceptionAttached set_RtlExceptionAttached[9..10],
InitialThread set_InitialThread[10..11],
SessionAware set_SessionAware[11..12],
LoadOwner set_LoadOwner[12..13],
LoaderWorker set_LoaderWorker[13..14],
SpareSameTebBits set_SpareSameTebBits[14..16],
]}
pub type PTEB32 = *mut TEB32;
#[inline]
pub fn UStr32ToUStr(
Destination: &mut UNICODE_STRING,
Source: &UNICODE_STRING32,
) {
Destination.Length = Source.Length;
Destination.MaximumLength = Source.MaximumLength;
Destination.Buffer = Source.Buffer as *mut u16;
}
#[inline]
pub fn UStrToUStr32(
Destination: &mut UNICODE_STRING32,
Source: &UNICODE_STRING,
) {
Destination.Length = Source.Length;
Destination.MaximumLength = Source.MaximumLength;
Destination.Buffer = Source.Buffer as u32;
}

View file

@ -1,29 +0,0 @@
use winapi::shared::ntdef::{BOOLEAN, NTSTATUS, PSTR, PVOID, ULONG};
use winapi::um::winnt::{PCONTEXT, PEXCEPTION_RECORD};
EXTERN!{extern "system" {
fn RtlDispatchException(
ExceptionRecord: PEXCEPTION_RECORD,
ContextRecord: PCONTEXT,
) -> BOOLEAN;
fn RtlRaiseStatus(
Status: NTSTATUS,
);
fn RtlRaiseException(
ExceptionRecord: PEXCEPTION_RECORD,
);
fn NtContinue(
ContextRecord: PCONTEXT,
TestAlert: BOOLEAN,
) -> NTSTATUS;
fn NtRaiseException(
ExceptionRecord: PEXCEPTION_RECORD,
ContextRecord: PCONTEXT,
FirstChance: BOOLEAN,
) -> NTSTATUS;
fn RtlAssert(
VoidFailedAssertion: PVOID,
VoidFileName: PVOID,
LineNumber: ULONG,
MutableMessage: PSTR,
);
}}

File diff suppressed because it is too large Load diff

View file

@ -1,58 +0,0 @@
/// A wrapper over UTF16 string constants.
pub struct UTF16Const(pub &'static [u16]);
impl UTF16Const {
#[inline]
pub fn as_ptr(&self) -> *const u16 {
self.0.as_ptr()
}
#[inline]
pub fn as_mut_ptr(&self) -> *mut u16 {
self.0.as_ptr() as *mut u16
}
#[inline]
pub fn len(&self) -> usize {
self.0.len() - 1
}
}
impl AsRef<[u16]> for UTF16Const {
#[inline]
fn as_ref(&self) -> &[u16] {
&self.0[..self.len()]
}
}
impl Copy for UTF16Const {}
impl Clone for UTF16Const {
#[inline]
fn clone(&self) -> UTF16Const { *self }
}
/// A wrapper over UTF8 string constants.
pub struct UTF8Const(pub &'static str);
impl UTF8Const {
#[inline]
pub fn as_ptr(&self) -> *const i8 {
self.0.as_ptr() as *const i8
}
#[inline]
pub fn as_mut_ptr(&self) -> *mut i8 {
self.0.as_ptr() as *mut i8
}
#[inline]
pub fn len(&self) -> usize {
self.0.len() - 1
}
#[inline]
pub fn as_str(&self) -> &str {
&self.0[..self.len()]
}
}
impl AsRef<str> for UTF8Const {
#[inline]
fn as_ref(&self) -> &str {
&self.0[..self.len()]
}
}
impl Copy for UTF8Const {}
impl Clone for UTF8Const {
#[inline]
fn clone(&self) -> UTF8Const { *self }
}

View file

@ -1,77 +0,0 @@
use winapi::shared::minwindef::DWORD;
use winapi::shared::ntdef::{LPCWSTR, LPWSTR, PVOID};
ENUM!{enum TAG_INFO_LEVEL {
eTagInfoLevelNameFromTag = 1,
eTagInfoLevelNamesReferencingModule = 2,
eTagInfoLevelNameTagMapping = 3,
eTagInfoLevelMax = 4,
}}
ENUM!{enum TAG_TYPE {
eTagTypeService = 1,
eTagTypeMax = 2,
}}
STRUCT!{struct TAG_INFO_NAME_FROM_TAG_IN_PARAMS {
dwPid: DWORD,
dwTag: DWORD,
}}
pub type PTAG_INFO_NAME_FROM_TAG_IN_PARAMS = *mut TAG_INFO_NAME_FROM_TAG_IN_PARAMS;
STRUCT!{struct TAG_INFO_NAME_FROM_TAG_OUT_PARAMS {
eTagType: DWORD,
pszName: LPWSTR,
}}
pub type PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS = *mut TAG_INFO_NAME_FROM_TAG_OUT_PARAMS;
STRUCT!{struct TAG_INFO_NAME_FROM_TAG {
InParams: TAG_INFO_NAME_FROM_TAG_IN_PARAMS,
OutParams: TAG_INFO_NAME_FROM_TAG_OUT_PARAMS,
}}
pub type PTAG_INFO_NAME_FROM_TAG = *mut TAG_INFO_NAME_FROM_TAG;
STRUCT!{struct TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS {
dwPid: DWORD,
pszModule: LPWSTR,
}}
pub type PTAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS =
*mut TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS;
STRUCT!{struct TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS {
eTagType: DWORD,
pmszNames: LPWSTR,
}}
pub type PTAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS =
*mut TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS;
STRUCT!{struct TAG_INFO_NAMES_REFERENCING_MODULE {
InParams: TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS,
OutParams: TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS,
}}
pub type PTAG_INFO_NAMES_REFERENCING_MODULE = *mut TAG_INFO_NAMES_REFERENCING_MODULE;
STRUCT!{struct TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS {
dwPid: DWORD,
}}
pub type PTAG_INFO_NAME_TAG_MAPPING_IN_PARAMS = *mut TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS;
STRUCT!{struct TAG_INFO_NAME_TAG_MAPPING_ELEMENT {
eTagType: DWORD,
dwTag: DWORD,
pszName: LPWSTR,
pszGroupName: LPWSTR,
}}
pub type PTAG_INFO_NAME_TAG_MAPPING_ELEMENT = *mut TAG_INFO_NAME_TAG_MAPPING_ELEMENT;
STRUCT!{struct TAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS {
cElements: DWORD,
pNameTagMappingElements: PTAG_INFO_NAME_TAG_MAPPING_ELEMENT,
}}
pub type PTAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS = *mut TAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS;
STRUCT!{struct TAG_INFO_NAME_TAG_MAPPING {
InParams: TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS,
pOutParams: PTAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS,
}}
pub type PTAG_INFO_NAME_TAG_MAPPING = *mut TAG_INFO_NAME_TAG_MAPPING;
EXTERN!{extern "system" {
fn I_QueryTagInformation(
pszMachineName: LPCWSTR,
eInfoLevel: TAG_INFO_LEVEL,
pTagInfo: PVOID,
) -> DWORD;
}}
FN!{stdcall PQUERY_TAG_INFORMATION(
pszMachineName: LPCWSTR,
eInfoLevel: TAG_INFO_LEVEL,
pTagInfo: PVOID,
) -> DWORD}

View file

@ -1 +0,0 @@
pub mod um;

View file

@ -1,2 +0,0 @@
pub(crate) mod winioctl;
pub mod winnt;

View file

@ -1,4 +0,0 @@
#[inline]
pub(crate) const fn CTL_CODE(DeviceType: u32, Function: u32, Method: u32, Access: u32) -> u32 {
(DeviceType << 16) | (Access << 14) | (Function << 2) | Method
}

View file

@ -1,71 +0,0 @@
use winapi::shared::basetsd::{DWORD64, SIZE_T, ULONG64};
use winapi::shared::minwindef::DWORD;
use winapi::um::winnt::{HANDLE, PVOID};
#[doc(hidden)]
#[inline]
pub const fn UInt32x32To64(a: u32, b: u32) -> u64 {
a as u64 * b as u64
}
#[cfg(not(target_arch = "aarch64"))]
IFDEF!{
use core::arch::asm;
use crate::ntpebteb::TEB;
#[inline]
pub unsafe fn __readfsdword(Offset: DWORD) -> DWORD {
let out: u32;
asm!(
"mov {:e}, fs:[{:e}]",
lateout(reg) out,
in(reg) Offset,
options(nostack, pure, readonly),
);
out
}
#[inline]
#[cfg(target_pointer_width = "64")]
pub unsafe fn __readgsqword(Offset: DWORD) -> DWORD64 {
let out: u64;
asm!(
"mov {}, gs:[{:e}]",
lateout(reg) out,
in(reg) Offset,
options(nostack, pure, readonly),
);
out
}
#[inline] #[allow(unused_unsafe)]
pub unsafe fn NtCurrentTeb() -> *mut TEB {
use winapi::um::winnt::NT_TIB;
let teb_offset = FIELD_OFFSET!(NT_TIB, _Self) as u32;
#[cfg(target_arch = "x86_64")] {
__readgsqword(teb_offset) as *mut TEB
}
#[cfg(target_arch = "x86")] {
__readfsdword(teb_offset) as *mut TEB
}
}
}
ENUM!{enum MEM_EXTENDED_PARAMETER_TYPE {
MemExtendedParameterInvalidType = 0,
MemExtendedParameterAddressRequirements = 1,
MemExtendedParameterNumaNode = 2,
MemExtendedParameterPartitionHandle = 3,
MemExtendedParameterMax = 4,
}}
pub type PMEM_EXTENDED_PARAMETER_TYPE = *mut MEM_EXTENDED_PARAMETER_TYPE;
UNION!{union MEM_EXTENDED_PARAMETER_u {
ULong64: DWORD64,
Pointer: PVOID,
Size: SIZE_T,
Handle: HANDLE,
ULong: DWORD,
}}
STRUCT!{struct MEM_EXTENDED_PARAMETER {
BitFields: ULONG64,
u: MEM_EXTENDED_PARAMETER_u,
}}
BITFIELD!{MEM_EXTENDED_PARAMETER BitFields: ULONG64 [
Type set_Type[0..8],
Reserved set_Reserved[8..64],
]}
pub type PMEM_EXTENDED_PARAMETER = *mut MEM_EXTENDED_PARAMETER;

Some files were not shown because too many files have changed in this diff Show more