Initial commit

This commit is contained in:
flux
2024-12-26 13:36:15 +00:00
commit 530fe7253a
15 changed files with 1806 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
[build]
rustflags = [
"-C",
"target-feature=+crt-static",
]
+1
View File
@@ -0,0 +1 @@
/target
+19
View File
@@ -0,0 +1,19 @@
{
"cSpell.words": [
"alertable",
"cdylib",
"Irql",
"kmtx",
"kmutex",
"KMUTEXGUARD",
"KWAIT",
"ntddk",
"NTSTATUS",
"PCUNICODE",
"PDEVICE",
"PKMUTEX",
"println",
"PRKMUTEX",
"RAII"
]
}
Generated
+958
View File
@@ -0,0 +1,958 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]]
name = "bindgen"
version = "0.69.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"itertools 0.12.1",
"lazy_static",
"lazycell",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
"which",
]
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "camino"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
dependencies = [
"serde",
]
[[package]]
name = "cargo-platform"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea"
dependencies = [
"serde",
]
[[package]]
name = "cargo_metadata"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037"
dependencies = [
"camino",
"cargo-platform",
"semver",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "cc"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e"
dependencies = [
"shlex",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap-cargo"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b2ea69cefa96b848b73ad516ad1d59a195cdf9263087d977f648a818c8b43e"
dependencies = [
"anstyle",
"clap",
]
[[package]]
name = "clap_builder"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "errno"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "home"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
dependencies = [
"windows-sys",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [
"spin",
]
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libloading"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
"windows-targets",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pin-project-lite"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
[[package]]
name = "prettyplease"
version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.4.9",
"regex-syntax 0.8.5",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.8.5",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "rustversion"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "semver"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
dependencies = [
"serde",
]
[[package]]
name = "serde"
version = "1.0.216"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.216"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
name = "tracing"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "wdk"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c80cc00b5c587d3a43f489350a797a258eefca5ab0bb5d0d5b56d4ce09ab42f2"
dependencies = [
"tracing",
"tracing-subscriber",
"wdk-build",
"wdk-sys",
]
[[package]]
name = "wdk-alloc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd1c139c6b9c05475bc7e8b356d4fbc252954d685691d70cfaec8b42c41b72d"
dependencies = [
"tracing",
"tracing-subscriber",
"wdk-build",
"wdk-sys",
]
[[package]]
name = "wdk-build"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b276786d848e5ab00e021968e89cfdc591938b69741a3733e7e3d91b23f547f"
dependencies = [
"anyhow",
"bindgen",
"camino",
"cargo_metadata",
"cfg-if",
"clap",
"clap-cargo",
"lazy_static",
"paste",
"rustversion",
"serde",
"serde_json",
"thiserror",
"tracing",
"windows",
]
[[package]]
name = "wdk-macros"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f069b2e89e5a3327e84bc2f672f7f35d94059da590666d7d605f33f2ae2fa3"
dependencies = [
"itertools 0.13.0",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "wdk-mutex"
version = "0.0.1"
dependencies = [
"wdk",
"wdk-alloc",
"wdk-build",
"wdk-panic",
"wdk-sys",
]
[[package]]
name = "wdk-panic"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba15dc2294f5c87df4b30218d93fb459ac8484a45683d4ad06fc0243e58736c"
[[package]]
name = "wdk-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f974829a3b0b362723d55f0d05d8f1715bb7a88297558c4127f69d85bbff7e"
dependencies = [
"anyhow",
"bindgen",
"cargo_metadata",
"cc",
"lazy_static",
"rustversion",
"serde_json",
"thiserror",
"tracing",
"tracing-subscriber",
"wdk-build",
"wdk-macros",
]
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
dependencies = [
"windows-core",
"windows-targets",
]
[[package]]
name = "windows-core"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-strings",
"windows-targets",
]
[[package]]
name = "windows-implement"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-result"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-strings"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
dependencies = [
"windows-result",
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+38
View File
@@ -0,0 +1,38 @@
[package]
name = "wdk-mutex"
version = "0.0.1"
edition = "2021"
authors = ["Flux Sec <fluxsec@proton.me>"]
license = "MIT"
repository = "https://github.com/0xflux/wdk_mutex"
documentation = "https://docs.rs/wdk-mutex"
readme = "Readme.md"
keywords = ["windows", "driver", "mutex", "kernel", "wdk"]
[package.metadata.wdk.driver-model]
driver-type = "WDM"
[lib]
crate-type = ["lib"]
[features]
default = []
nightly = ["wdk/nightly", "wdk-sys/nightly"]
debug = []
[dependencies]
wdk = "^0.3.0"
wdk-alloc = "^0.3.0"
wdk-sys = "^0.3.0"
wdk-panic = "^0.3.0"
[profile.dev]
panic = "abort"
lto = true
[profile.release]
panic = "abort"
lto = true
[build-dependencies]
wdk-build = "^0.3.0"
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 0xflux
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.
+139
View File
@@ -0,0 +1,139 @@
# wdk-mutex
An idiomatic Rust mutex type for Windows kernel driver development.
To use this crate, simply:
```
cargo add wdk-mutex
```
**See the sections below for examples**. This crate assumes you already have a Rust Windows Driver Kit project
using the Microsoft [windows-drivers-rs](https://github.com/microsoft/windows-drivers-rs) crate. You will
not be able to use this crate unless you are in a wdk development environment, setup steps outlined on
their repository.
This crate checks IRQL when acquiring and releasing the mutex, returning an error if IRQL is too high. See the crate documentation for details.
`wdk-mutex` is a work in progress to implement additional mutex types and functionality as required. Contributions, issues, and discussions are welcome. This crate is **NOT** affiliated with the WDK crates provided by Microsoft, but is designed to work with them and their ecosystem for Windows Rust
Kernel Driver development.
As this crate integrates into the wdk ecosystem, Microsoft stipulate: This project is still in early stages of development and is not yet recommended for production use.
Tests have been conducted on public modules, but are not included in the crate due to the complexity of
deploying kernel level tests. A new repo will be created specifically for testing this crate which
can be built as a driver.
This is licenced with an MIT Licence, conditions can be found in LICENCE in the crate GitHub repository.
## Stability
This crate has been built and tested with **nightly-2024-12-21**. Stability outside of nightly versions
stipulated here are considered undefined.
The crate has been tested on a Windows 11 image as a driver. No testing of other Windows versions have
been conducted.
## Features:
**KMUTEX:**
The `wdk-mutex` crate supports acquiring a KMUTEX. The type `Kmutex<T>` provides mutually exclusive access
to the inner type T allocated through this crate in the non-paged pool. All data required to initialise the
KMutex is allocated in the non-paged pool and as such is safe to pass stack data into the type as it will not go out of scope.
Access to the `T` within the `KMutex` can be done through calling `lock`, similar to the Rust std Mutex.
As the `KMutex` is designed to be used in the Windows Kernel, with the Windows `wdk` crate, the lifetimes of
the `KMutex` must be considered by the caller. See **examples** below for usage.
# Examples
## Locally scoped mutex:
```rust
{
let mtx = KMutex::new(0u32).unwrap();
let lock = mtx.lock().unwrap();
// If T implements display, you do not need to dereference the lock to print.
println!("The value is: {}", lock);
} // Mutex will become unlocked as it is managed via RAII
```
## Global scope via static pointer:
A future release is planned to make this process more ergonomic.
```rust
pub static HEAP_MTX_PTR: AtomicPtr<KMutex<u32>> = AtomicPtr::new(null_mut());
fn my_fn() {
let heap_mtx = Box::new(KMutex::new(0u32).unwrap());
let heap_mtx_ptr = Box::into_raw(heap_mtx);
HEAP_MTX_PTR.store(heap_mtx_ptr, Ordering::SeqCst);
// spawn some system threads
r _ in 0..3 {
let mut thread_handle: HANDLE = null_mut();
let status = unsafe {
PsCreateSystemThread(
&mut thread_handle,
0,
null_mut::<OBJECT_ATTRIBUTES>(),
null_mut(),
null_mut::<CLIENT_ID>(),
Some(callback_fn),
null_mut(),
)
};
println!("[i] Thread status: {status}");
}
}
unsafe extern "C" fn callback_fn(_: *mut c_void) {
for _ in 0..50 {
let p = HEAP_MTX_PTR.load(Ordering::SeqCst);
if !p.is_null() {
let p = unsafe { &*p };
let mut lock = p.lock().unwrap();
println!("Got the lock before change! {}", *lock);
*lock += 1;
println!("After the change: {}", *lock);
}
}
}
// IMPORTANT ensure the KMutex in the static is properly dropped to clean memory
extern "C" fn driver_exit(driver: *mut DRIVER_OBJECT) {
let ptr: *mut KMutex<u32> = HEAP_MTX_PTR.load(Ordering::SeqCst);
if !ptr.is_null() {
unsafe {
// RAII will kick in here to deallocate our memory
let _ = Box::from_raw(ptr);
}
}
}
```
# Planned updates
## Global interface:
A future addition is planned which will make the API more flexible for dynamically managing globally
available mutexes to somewhat reduce the overhead required to use this crate.
## Critical Sections:
An idiomatic implementation for entering and leaving a mutex critical section where no underlying
T is protected.
## FAST_MUTEX
An idiomatic implementation for FAST_MUTEX.
The next planned release will add Critical Section behaviour, where you do not want to wrap a generic T in a mutex (similar to std::mutex), but you want a section to be a critical section nonetheless.
Please note that each planned feature will be introduced gradually, and might undergo changes based on community feedback.
I welcome any contributions or suggestions to improve functionality, documentation, and compatibility.
+4
View File
@@ -0,0 +1,4 @@
fn main() -> Result<(), wdk_build::ConfigError> {
println!("Starting build process...");
wdk_build::configure_wdk_binary_build()
}
+13
View File
@@ -0,0 +1,13 @@
extend = "target/rust-driver-makefile.toml"
[config]
load_script = '''
#!@rust
//! ```cargo
//! [dependencies]
//! wdk-build = "0.3.0"
//! ```
#![allow(unused_doc_comments)]
wdk_build::cargo_make::load_rust_driver_makefile()?
'''
+2
View File
@@ -0,0 +1,2 @@
[toolchain]
channel = "nightly-2024-12-21"
+119
View File
@@ -0,0 +1,119 @@
//! Deprecated but leaving for reference as some of this logic may be useful in a
//! future planned addition.
use core::{ops::Deref, ptr::{drop_in_place, write}, sync::atomic::AtomicUsize};
use wdk::println;
use wdk_sys::{ntddk::{ExAllocatePool2, ExFreePool}, POOL_FLAG_NON_PAGED};
use crate::errors::DriverMutexError;
/// An atomically reference counted Arc in the non-paged pool
#[derive(Debug)]
pub struct ArcNP<T> {
/// A pointer to the actual allocation, which holds the reference count and T
ptr: *mut ArcInner<T>,
}
#[repr(C, align(8))]
#[derive(Debug)]
struct ArcInner<T> {
/// The atomic reference count
refcount: AtomicUsize,
data: T,
}
impl<T> ArcNP<T> {
/// Allocates a new atomically reference counted smart pointer in the
/// NonPagedPool with a given tag.
pub fn new(data: T, tag: u32) -> Result<Self, DriverMutexError> {
//
// Calculate the size required for the non-paged pool allocation and
// then allocate.
//
let inner_size = size_of::<ArcInner<T>>();
let mem = unsafe {
ExAllocatePool2(POOL_FLAG_NON_PAGED, inner_size as u64, tag)
};
if mem.is_null() {
return Err(DriverMutexError::PagedPoolAllocFailed);
}
// Cast the memory allocation to our type
let ptr = mem as *mut ArcInner<T>;
//
// write the ArcInner<T> into the newly allocated memory
//
// SAFETY: A null pointer check above ensures this operation is writing to properly
// initialised memory.
unsafe {
write(
ptr,
ArcInner {
refcount: AtomicUsize::new(1),
data,
}
);
}
Ok(Self { ptr })
}
}
impl<T> Deref for ArcNP<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
// SAFETY: This is safe as the type keeps track of the validity of the reference
// via
unsafe {
&(*self.ptr).data
}
}
}
impl<T> Clone for ArcNP<T> {
fn clone(&self) -> Self {
// increment the reference count
// SAFETY this operation is safe as Self's memory is tracked by the implementation of our smart pointer
unsafe {
let _ = &(*self.ptr).refcount.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
};
// Return the underlying ArcNP
Self { ptr: self.ptr }
}
}
impl<T> Drop for ArcNP<T> {
fn drop(&mut self) {
// dec the ref count
let count_prior_to_dec = unsafe {
&(*self.ptr).refcount
}.fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
println!("[wdk-mutex] Dec val: {}...", count_prior_to_dec);
// if the new count == 0, then we need to clean up the memory, else, there are still
// valid references living.
if count_prior_to_dec == 1 {
// SAFETY: At this point we are operating on the final Arc lifetime, so the data is still
// valid (as the count was 1, now 0 as it leaves its scope or is otherwise dropped).
println!("[wdk-mutex] Dropping underlying memory...");
unsafe {
// drop the underlying data
drop_in_place(&mut (*self.ptr).data);
ExFreePool(self.ptr as *mut _);
}
}
}
}
+8
View File
@@ -0,0 +1,8 @@
//! Error types used by wdk-mutex
#[derive(Debug, PartialEq, Eq)]
pub enum DriverMutexError {
IrqlTooHigh,
IrqlNotAPCLevel,
PagedPoolAllocFailed,
}
+93
View File
@@ -0,0 +1,93 @@
//! This module is out of commission pending a future release, and is a work in progress.
//!
//! Public interfaces disabled during development so it cannot be used by somebody using this crate.
//!
//! Use the `KMutex` module of this crate in the meantime.
#[cfg(not(test))]
extern crate wdk_panic;
use core::{cell::UnsafeCell, ops::{Deref, DerefMut}};
use wdk::println;
use wdk_sys::{ntddk::{ExAcquireFastMutex, ExReleaseFastMutex, KeGetCurrentIrql, KeInitializeEvent}, DISPATCH_LEVEL, FALSE, FAST_MUTEX, FM_LOCK_BIT, _EVENT_TYPE::SynchronizationEvent, APC_LEVEL};
use crate::errors::DriverMutexError;
#[allow(non_snake_case)]
unsafe fn ExInitializeFastMutex(kmutex: *mut FAST_MUTEX) {
// check IRQL
let irql = unsafe { KeGetCurrentIrql() };
assert!(irql as u32 <= DISPATCH_LEVEL);
core::ptr::write_volatile(&mut (*kmutex).Count, FM_LOCK_BIT as i32);
(*kmutex).Owner = core::ptr::null_mut();
(*kmutex).Contention = 0;
KeInitializeEvent(&mut (*kmutex).Event, SynchronizationEvent, FALSE as _)
}
#[derive(Debug)]
struct FastMutex<T> {
mutex: UnsafeCell<FAST_MUTEX>,
inner: UnsafeCell<T>,
}
unsafe impl<T: Sync> Sync for FastMutex<T>{}
impl<T> FastMutex<T> {
pub fn new(data: T) -> Result<Self, DriverMutexError> {
if unsafe { KeGetCurrentIrql() } > DISPATCH_LEVEL as u8 {
return Err(DriverMutexError::IrqlTooHigh)
}
let mut mutex = FAST_MUTEX::default();
unsafe { ExInitializeFastMutex(&mut mutex) };
let c = UnsafeCell::new(mutex);
Ok(FastMutex {
mutex: c,
inner: UnsafeCell::new(data),
})
}
pub fn lock(&self) -> Result<FastMutexGuard<'_, T>, DriverMutexError> {
if unsafe { KeGetCurrentIrql() } > APC_LEVEL as u8 {
return Err(DriverMutexError::IrqlTooHigh);
}
unsafe { ExAcquireFastMutex(self.mutex.get()) };
Ok(FastMutexGuard {
fast_mutex: self
})
}
}
#[derive(Debug)]
struct FastMutexGuard<'a, T> {
fast_mutex: &'a FastMutex<T>,
}
impl<'a, T> Deref for FastMutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.fast_mutex.inner.get() }
}
}
impl<'a, T> DerefMut for FastMutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.fast_mutex.inner.get() }
}
}
impl<'a, T> Drop for FastMutexGuard<'a, T> {
fn drop(&mut self) {
unsafe { ExReleaseFastMutex(self.fast_mutex.mutex.get()) };
}
}
+332
View File
@@ -0,0 +1,332 @@
//! A Rust idiomatic Windows Kernel Driver KMUTEX type which protects the inner type T
#[cfg(not(test))]
extern crate wdk_panic;
use core::{ffi::c_void, fmt::Display, ops::{Deref, DerefMut}, ptr::{self, drop_in_place, null_mut}};
use wdk::println;
use wdk_sys::{ntddk::{ExAllocatePool2, ExFreePool, KeGetCurrentIrql, KeInitializeMutex, KeReleaseMutex, KeWaitForSingleObject}, APC_LEVEL, DISPATCH_LEVEL, FALSE, KMUTEX, POOL_FLAG_NON_PAGED, _KWAIT_REASON::Executive, _MODE::KernelMode};
use crate::errors::DriverMutexError;
/// A thread safe mutex implemented through acquiring a KMUTEX in the Windows kernel.
///
/// The type `Kmutex<T>` provides mutually exclusive access to the inner type T allocated through
/// this crate in the non-paged pool. All data required to initialise the KMutex is allocated in the
/// non-paged pool and as such is safe to pass stack data into the type as it will not go out of scope.
///
/// `KMutex` holds an inner value which is a pointer to a `KMutexInner` type which is the actual type
/// allocated in the non-paged pool, and this holds information relating to the mutex.
///
/// Access to the `T` within the `KMutex` can be done through calling [`Self::lock`].
///
/// To receive debug messages when the IRQL is too high for an operation, enable the feature flag `debug`.
///
/// # Lifetimes
///
/// As the `KMutex` is designed to be used in the Windows Kernel, with the Windows `wdk` crate, the lifetimes of
/// the `KMutex` must be considered by the caller. See examples below for usage.
///
/// The KMutex can exist in a locally scoped function with little additional configuration. To use the mutex across
/// thread boundaries, or to use it in callback functions, the recommended course of action is to utilise either a
/// globally accessible `static AtomicPtr<KMutex<T>>`; or to utilise a
/// [Device Extension](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/device-extensions)
/// provided in the wdk.
///
/// <section class="warning">
/// If you use a `static AtomicPtr<KMutex<T>>` you MUST ensure that the memory is cleaned up when you exit the driver
/// otherwise you cause a memory leak.
///
/// A future addition is planned which will make the API more flexible for dynamically managing globally available
/// mutexes to somewhat reduce the overhead required to use this crate.
/// </section>
///
/// # Deallocation
///
/// KMutex handles the deallocation of resources at the point the KMutex is dropped.
///
/// # Examples
///
/// ## Locally scoped mutex:
///
/// ```
/// {
/// let mtx = KMutex::new(0u32).unwrap();
/// let lock = mtx.lock().unwrap();
///
/// // If T implements display, you do not need to dereference the lock to print.
/// println!("The value is: {}", lock);
/// } // Mutex will become unlocked as it is managed via RAII
/// ```
///
/// ## Global scope via static pointer:
///
/// A future release is planned to make this process more ergonomic.
///
/// ```
/// pub static HEAP_MTX_PTR: AtomicPtr<KMutex<u32>> = AtomicPtr::new(null_mut());
///
/// fn my_fn() {
/// let heap_mtx = Box::new(KMutex::new(0u32).unwrap());
/// let heap_mtx_ptr = Box::into_raw(heap_mtx);
/// HEAP_MTX_PTR.store(heap_mtx_ptr, Ordering::SeqCst);
///
/// // spawn some system threads
/// r _ in 0..3 {
/// let mut thread_handle: HANDLE = null_mut();
/// let status = unsafe {
/// PsCreateSystemThread(
/// &mut thread_handle,
/// 0,
/// null_mut::<OBJECT_ATTRIBUTES>(),
/// null_mut(),
/// null_mut::<CLIENT_ID>(),
/// Some(callback_fn),
/// null_mut(),
/// )
/// };
/// println!("[i] Thread status: {status}");
/// }
/// }
///
/// unsafe extern "C" fn callback_fn(_: *mut c_void) {
/// for _ in 0..50 {
/// let p = HEAP_MTX_PTR.load(Ordering::SeqCst);
/// if !p.is_null() {
/// let p = unsafe { &*p };
/// let mut lock = p.lock().unwrap();
/// println!("Got the lock before change! {}", *lock);
/// *lock += 1;
/// println!("After the change: {}", *lock);
/// }
/// }
/// }
///
/// // IMPORTANT ensure the KMutex in the static is properly dropped to clean memory
/// extern "C" fn driver_exit(driver: *mut DRIVER_OBJECT) {
/// let ptr: *mut KMutex<u32> = HEAP_MTX_PTR.load(Ordering::SeqCst);
/// if !ptr.is_null() {
/// unsafe {
/// // RAII will kick in here to deallocate our memory
/// let _ = Box::from_raw(ptr);
/// }
/// }
/// }
/// ```
pub struct KMutex<T> {
inner: *mut KMutexInner<T>
}
/// The underlying data which is non-page pool allocated which is pointed to by the `KMutex`.
struct KMutexInner<T> {
/// A KMUTEX structure allocated into KMutexInner
mutex: KMUTEX,
/// The data for which the mutex is protecting
data: T,
}
unsafe impl<T: Sync> Sync for KMutex<T>{}
impl<T> KMutex<T> {
/// Creates a new KMUTEX Windows Kernel Driver Mutex in a signaled (free) state.
///
/// # IRQL
///
/// This can be called at any IRQL.
///
/// # Examples
///
/// ```
/// use wdk_mutex::Mutex;
///
/// let my_mutex = wdk_mutex::KMutex::new(0u32);
/// ```
pub fn new(data: T) -> Result<Self, DriverMutexError> {
//
// Non-Paged heap alloc for all struct data required for KMutexInner
//
let total_sz_required = size_of::<KMutexInner<T>>();
let inner_heap_ptr: *mut c_void = unsafe {
ExAllocatePool2(POOL_FLAG_NON_PAGED, total_sz_required as u64, u32::from_be_bytes(*b"kmtx"))
};
if inner_heap_ptr.is_null() {
return Err(DriverMutexError::PagedPoolAllocFailed);
}
// Cast the memory allocation to a pointer to the inner
let kmutex_inner_ptr = inner_heap_ptr as *mut KMutexInner<T>;
// SAFETY: This raw write is safe as the pointer validity is checked above.
unsafe {
ptr::write(
kmutex_inner_ptr,
KMutexInner {
mutex: KMUTEX::default(),
data
}
);
// Initialise the KMUTEX object via the kernel
KeInitializeMutex(&(*kmutex_inner_ptr).mutex as *const _ as *mut _, 0);
}
Ok(Self { inner: kmutex_inner_ptr })
}
/// Acquires a mutex in a non-alertable manner.
///
/// A future release is planned to include an alternate implementation
/// which will lock the mutex and become alertable if it has to wait for the mutex to become free.
/// This function will block the local thread until it is available to acquire the mutex.
///
/// Once the thread has acquired the mutex, it will return a `KMutexGuard` which is a RAII scoped
/// guard allowing exclusive access to the inner T.
///
/// # Errors
///
/// todo
///
/// # IRQL
///
/// This function must be called at IRQL `<= APC_LEVEL`, if the IRQL is higher than this,
/// the function will return an error.
///
/// It is the callers responsibility to ensure the IRQL is sufficient to call this function and it
/// will not alter the IRQL for the caller, as this may introduce undefined behaviour elsewhere in the
/// driver / kernel.
pub fn lock(&self) -> Result<KMutexGuard<'_, T>, DriverMutexError> {
// Check the IRQL is <= APC_LEVEL as per remarks at
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-kewaitforsingleobject
let irql = unsafe {KeGetCurrentIrql()};
if irql > APC_LEVEL as u8 {
if cfg!(feature = "debug") {
println!("[wdk-mutex] [-] IRQL is too high to call .lock(). Current IRQL: {}", irql);
return Err(DriverMutexError::IrqlTooHigh);
}
}
// Discard the return value; the status code does not represent an error or contain information
// relevant to the context of no timeout.
let _ = unsafe {
// SAFETY: The IRQL is sufficient for the operation as checked above, and we know our pointer
// is valid as RAII manages the lifetime of the heap allocation, ensuring it will only be deallocated
// once Self gets dropped.
KeWaitForSingleObject(
&mut (*self.inner).mutex as *mut _ as *mut _,
Executive,
KernelMode as i8,
FALSE as u8,
null_mut(),
)
};
Ok(KMutexGuard {
kmutex: self
})
}
}
impl<T> Drop for KMutex<T> {
fn drop(&mut self) {
unsafe {
// Drop the underlying data and run destructors for the data, this would be relevant in the
// case where Self contains other heap allocated types which have their own deallocation
// methods.
drop_in_place(&mut (*self.inner).data);
// Free the memory we allocated
ExFreePool(self.inner as *mut _);
}
}
}
/// A RAII scoped guard for the inner data protected by the mutex. Once this guard is given out, the protected data
/// may be safely mutated by the caller as we guarantee exclusive access via Windows Kernel Mutex primitives.
///
/// When this structure is dropped (falls out of scope), the lock will be unlocked.
///
/// # IRQL
///
/// Access to the data within this guard must be done at <= APC_LEVEL if a non-alertable lock was acquired, or <=
/// DISPATCH_LEVEL if an alertable lock was acquired. It is the callers responsible to manage APC levels whilst
/// using the KMutex.
///
/// If you wish to manually drop the lock with a safety check, call the function [`drop_safe`].
///
/// # Kernel panic
///
/// Raising the IRQL above safe limits whilst using the mutex will cause a Kernel Panic if not appropriately handled.
/// When RAII drops this type, the mutex is released, if the mutex goes out of scope whilst you hold an IRQL that
/// is too high, you will receive a kernel panic.
///
pub struct KMutexGuard<'a, T> {
kmutex: &'a KMutex<T>,
}
impl<'a, T> Display for KMutexGuard<'a, T>
where T: Display
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
// SAFETY: Dereferencing the inner data is safe as RAII controls the memory allocations.
write!(f, "{}", unsafe { &(*self.kmutex.inner).data })
}
}
impl<'a, T> Deref for KMutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
// SAFETY: Dereferencing the inner data is safe as RAII controls the memory allocations.
unsafe { &(*self.kmutex.inner).data }
}
}
impl<'a, T> DerefMut for KMutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
// SAFETY: Dereferencing the inner data is safe as RAII controls the memory allocations.
// Mutable access is safe due to Self only being given out whilst a mutex is held from the
// kernel.
unsafe { &mut (*self.kmutex.inner).data }
}
}
impl<'a, T> Drop for KMutexGuard<'a, T> {
fn drop(&mut self) {
// NOT SAFE AT A IRQL TOO HIGH
unsafe { KeReleaseMutex(&mut (*self.kmutex.inner).mutex, FALSE as u8) };
}
}
impl<'a, T> KMutexGuard<'a, T> {
/// Safely drop the KMutexGuard, an alternative to RAII.
///
/// This function checks the IRQL before attempting to drop the guard.
///
/// # Errors
///
/// If the IRQL > DISPATCH_LEVEL, no unlock will occur and a DriverMutexError will be returned to the
/// caller.
///
/// # IRQL
///
/// This function is safe to call at any IRQL, but it will not release the mutex if IRQL > DISPATCH_LEVEL
fn drop_safe(&mut self) -> Result<(), DriverMutexError> {
let irql = unsafe {KeGetCurrentIrql()};
if irql > DISPATCH_LEVEL as u8 {
if cfg!(feature = "debug") {
println!("[wdk-mutex] [-] Unable to safely drop the KMUTEX. Calling IRQL is too high: {}", irql);
return Err(DriverMutexError::IrqlTooHigh);
}
}
unsafe { KeReleaseMutex(&mut (*self.kmutex.inner).mutex, FALSE as u8) };
Ok(())
}
}
+54
View File
@@ -0,0 +1,54 @@
//! An idiomatic Rust mutex type for Windows kernel driver development.
//!
//! The crate will safely check IRQL before doing operations which would cause a STOP CODE of
//! IRQL NOT LESS OR EQUAL (except for RAII dropping of scoped Mutex Guards).
//! In those cases, the API will return an error of the internal type `DriverMutexError`.
//!
//! This crate is a work in progress to implement additional mutex types and functionality as required. Contributions, issues,
//! and discussions are welcome.
//!
//! This crate is **NOT** affiliated with the WDK crates provided by Microsoft, but is designed to work with them for Windows Rust Kernel Driver
//! development.
//!
//! # Additional features:
//!
//! - `debug`: Enabling this feature will print debug messages to an attached debugger or kernel message viewer when an IRQL error occurs.
//!
//! # Planned updates
//!
//! ## Global interface:
//!
//! A future addition is planned which will make the API more flexible for dynamically managing globally available
//! mutexes to somewhat reduce the overhead required to use this crate.
//!
//! ## Critical Sections:
//!
//! An idiomatic implementation for entering and leaving a mutex critical section where no underlying T is protected.
//!
//! ## FAST_MUTEX
//!
//! An idiomatic implementation for FAST_MUTEX.
//!
//! # Tests
//!
//! Tests have been conducted on public modules.
//!
//! No tests are included in the crate. Tests have been conducted on another project https://github.com/0xflux/Sanctum; but a new repo
//! will be created specifically for testing this crate which can be built as a driver.
//!
//! <section class="warning">
//! As this crate integrates into the wdk ecosystem, Microsoft stipulate: This project is still in early stages of development and
//! is not yet recommended for production use.
//!
//! This is licenced with an MIT Licence, conditions can be found in LICENCE in the crate GitHub repository.
//! </section>
#![no_std]
#[cfg(not(test))]
extern crate wdk_panic;
pub mod kmutex;
// mod fast_mutex;
pub mod errors;