[
  {
    "path": ".gitignore",
    "content": "**/target/\n*.lock\n*.dll\n*.pdb\n*.lib\n*.exe\n*.cer\n"
  },
  {
    "path": "02-hello-world/Cargo.toml",
    "content": "[package]\nname = \"02-hello-world\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n[lib]\ncrate-type = [\"cdylib\"]\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release]\npanic = \"abort\"\n\n[build-dependencies]\nwindows-kernel-build = { path = \"../windows-kernel-build\" }\n\n[dependencies.winapi]\ngit = \"https://github.com/Trantect/winapi-rs.git\"\nbranch = \"feature/km\"\nfeatures = [\n    \"wdm\",\n    \"ntstatus\",\n]\n"
  },
  {
    "path": "02-hello-world/Makefile.toml",
    "content": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.bat\"\n\n[env.development]\nTARGET_PATH = \"target/debug\"\n\n[env.production]\nTARGET_PATH = \"target/release\"\nBUILD_RELEASE = \"--release\"\n\n[tasks.clean-cert]\nscript = '''\n# Remove the self-signed certificate.\nif exist DriverCertificate.cer ( rm DriverCertificate.cer )\n'''\n\n[tasks.build-driver]\nscript = '''\ncargo b %BUILD_FLAGS%\n'''\n\n[tasks.rename]\nignore_errors = true\nscript = '''\ncd %TARGET_PATH%\nrename driver.dll driver.sys\n'''\n\n[tasks.sign]\ndependencies = [\"build-driver\", \"rename\"]\nscript = '''\ncall \"%VC_BUILD_DIR%\"\n\nif not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )\n\nsigntool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys\n'''\n"
  },
  {
    "path": "02-hello-world/build.rs",
    "content": "fn main() {\n    windows_kernel_build::build().unwrap();\n}\n"
  },
  {
    "path": "02-hello-world/rust-toolchain",
    "content": "nightly\n"
  },
  {
    "path": "02-hello-world/src/lib.rs",
    "content": "#![no_std]\n\nuse core::panic::PanicInfo;\nuse winapi::km::wdm::{DbgPrint, DRIVER_OBJECT};\nuse winapi::shared::ntdef::{NTSTATUS, UNICODE_STRING};\nuse winapi::shared::ntstatus::STATUS_SUCCESS;\n\n#[panic_handler]\nfn panic(_info: &PanicInfo) -> ! {\n    loop {}\n}\n\n#[no_mangle]\npub extern \"system\" fn driver_entry(driver: &mut DRIVER_OBJECT, _: &UNICODE_STRING) -> NTSTATUS {\n    unsafe {\n        DbgPrint(\"Hello, world!\\0\".as_ptr());\n    }\n\n    driver.DriverUnload = Some(driver_exit);\n\n    STATUS_SUCCESS\n}\n\npub extern \"system\" fn driver_exit(_driver: &mut DRIVER_OBJECT) {\n    unsafe {\n        DbgPrint(\"Bye bye!\\0\".as_ptr());\n    }\n}\n"
  },
  {
    "path": "03-generating-bindings/Cargo.toml",
    "content": "[package]\nname = \"03-generating-bindings\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n[lib]\ncrate-type = [\"cdylib\"]\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release]\npanic = \"abort\"\n\n[build-dependencies]\nwindows-kernel-build = { path = \"../windows-kernel-build\" }\n\n[dependencies]\nwindows-kernel-sys = { path = \"../windows-kernel-sys\" }\n"
  },
  {
    "path": "03-generating-bindings/Makefile.toml",
    "content": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.bat\"\n\n[env.development]\nTARGET_PATH = \"target/debug\"\n\n[env.production]\nTARGET_PATH = \"target/release\"\nBUILD_RELEASE = \"--release\"\n\n[tasks.clean-cert]\nscript = '''\n# Remove the self-signed certificate.\nif exist DriverCertificate.cer ( rm DriverCertificate.cer )\n'''\n\n[tasks.build-driver]\nscript = '''\ncargo b %BUILD_FLAGS%\n'''\n\n[tasks.rename]\nignore_errors = true\nscript = '''\ncd %TARGET_PATH%\nrename driver.dll driver.sys\n'''\n\n[tasks.sign]\ndependencies = [\"build-driver\", \"rename\"]\nscript = '''\ncall \"%VC_BUILD_DIR%\"\n\nif not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )\n\nsigntool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys\n'''\n"
  },
  {
    "path": "03-generating-bindings/build.rs",
    "content": "fn main() {\n    windows_kernel_build::build().unwrap();\n}\n"
  },
  {
    "path": "03-generating-bindings/rust-toolchain",
    "content": "nightly\n"
  },
  {
    "path": "03-generating-bindings/src/lib.rs",
    "content": "#![no_std]\n\nuse core::panic::PanicInfo;\nuse windows_kernel_sys::base::{DRIVER_OBJECT, NTSTATUS, STATUS_SUCCESS, UNICODE_STRING};\nuse windows_kernel_sys::ntoskrnl::DbgPrint;\n\n#[panic_handler]\nfn panic(_info: &PanicInfo) -> ! {\n    loop {}\n}\n\n#[no_mangle]\npub extern \"system\" fn driver_entry(driver: &mut DRIVER_OBJECT, _: &UNICODE_STRING) -> NTSTATUS {\n    unsafe {\n        DbgPrint(\"Hello, world!\\0\".as_ptr() as _);\n    }\n\n    driver.DriverUnload = Some(driver_exit);\n\n    STATUS_SUCCESS\n}\n\npub unsafe extern \"C\" fn driver_exit(_driver: *mut DRIVER_OBJECT) {\n    DbgPrint(\"Bye bye!\\0\".as_ptr() as _);\n}\n"
  },
  {
    "path": "04-safe-framework/Cargo.toml",
    "content": "[package]\nname = \"04-safe-framework\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n[lib]\ncrate-type = [\"cdylib\"]\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release]\npanic = \"abort\"\n\n[build-dependencies]\nwindows-kernel-build = { path = \"../windows-kernel-build\" }\n\n[dependencies]\nwindows-kernel-rs = { path = \"../windows-kernel-rs\" }\nwindows-kernel-sys = { path = \"../windows-kernel-sys\" }\n"
  },
  {
    "path": "04-safe-framework/Makefile.toml",
    "content": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.bat\"\n\n[env.development]\nTARGET_PATH = \"target/debug\"\n\n[env.production]\nTARGET_PATH = \"target/release\"\nBUILD_RELEASE = \"--release\"\n\n[tasks.clean-cert]\nscript = '''\n# Remove the self-signed certificate.\nif exist DriverCertificate.cer ( rm DriverCertificate.cer )\n'''\n\n[tasks.build-driver]\nscript = '''\ncargo b %BUILD_FLAGS%\n'''\n\n[tasks.rename]\nignore_errors = true\nscript = '''\ncd %TARGET_PATH%\nrename driver.dll driver.sys\n'''\n\n[tasks.sign]\ndependencies = [\"build-driver\", \"rename\"]\nscript = '''\ncall \"%VC_BUILD_DIR%\"\n\nif not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )\n\nsigntool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys\n'''\n"
  },
  {
    "path": "04-safe-framework/build.rs",
    "content": "fn main() {\n    windows_kernel_build::build().unwrap();\n}\n"
  },
  {
    "path": "04-safe-framework/rust-toolchain",
    "content": "nightly\n"
  },
  {
    "path": "04-safe-framework/src/lib.rs",
    "content": "#![no_std]\n\nuse windows_kernel_rs::{Driver, Error, kernel_module, KernelModule, println};\n\nstruct Module;\n\nimpl KernelModule for Module {\n    fn init(_: Driver, _: &str) -> Result<Self, Error> {\n        println!(\"Hello, world!\");\n\n        Ok(Module)\n    }\n\n    fn cleanup(&mut self, _: Driver) {\n        println!(\"Bye bye!\");\n    }\n}\n\nkernel_module!(Module);\n"
  },
  {
    "path": "05-creating-devices/Cargo.toml",
    "content": "[package]\nname = \"05-creating-devices\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n[lib]\ncrate-type = [\"cdylib\"]\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release]\npanic = \"abort\"\n\n[build-dependencies]\nwindows-kernel-build = { path = \"../windows-kernel-build\" }\n\n[dependencies]\nwidestring = { version = \"0.4\", default-features = false, features = [\"alloc\"]}\nwindows-kernel-rs = { path = \"../windows-kernel-rs\" }\nwindows-kernel-sys = { path = \"../windows-kernel-sys\" }\n"
  },
  {
    "path": "05-creating-devices/Makefile.toml",
    "content": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.bat\"\n\n[env.development]\nTARGET_PATH = \"target/debug\"\n\n[env.production]\nTARGET_PATH = \"target/release\"\nBUILD_RELEASE = \"--release\"\n\n[tasks.clean-cert]\nscript = '''\n# Remove the self-signed certificate.\nif exist DriverCertificate.cer ( rm DriverCertificate.cer )\n'''\n\n[tasks.build-driver]\nscript = '''\ncargo b %BUILD_FLAGS%\n'''\n\n[tasks.rename]\nignore_errors = true\nscript = '''\ncd %TARGET_PATH%\nrename driver.dll driver.sys\n'''\n\n[tasks.sign]\ndependencies = [\"build-driver\", \"rename\"]\nscript = '''\ncall \"%VC_BUILD_DIR%\"\n\nif not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )\n\nsigntool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys\n'''\n"
  },
  {
    "path": "05-creating-devices/build.rs",
    "content": "fn main() {\n    windows_kernel_build::build().unwrap();\n}\n"
  },
  {
    "path": "05-creating-devices/rust-toolchain",
    "content": "nightly\n"
  },
  {
    "path": "05-creating-devices/src/lib.rs",
    "content": "#![no_std]\n\nuse windows_kernel_rs::device::{\n    Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceType, RequestError};\nuse windows_kernel_rs::println;\nuse windows_kernel_rs::request::{IoRequest};\nuse windows_kernel_rs::{Access, Driver, Error, kernel_module, KernelModule, SymbolicLink};\n\nstruct MyDevice;\n\nimpl DeviceOperations for MyDevice {\n    fn create(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {\n        println!(\"userspace opened the device\");\n\n        Ok(Completion::Complete(0, request))\n    }\n\n    fn close(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {\n        println!(\"userspace closed the device\");\n\n        Ok(Completion::Complete(0, request))\n    }\n\n    fn cleanup(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {\n        println!(\"device is no longer in use by userspace\");\n\n        Ok(Completion::Complete(0, request))\n    }\n}\n\nstruct Module {\n    _device: Device,\n    _symbolic_link: SymbolicLink,\n}\n\nimpl KernelModule for Module {\n    fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {\n        let device = driver.create_device(\n            \"\\\\Device\\\\Example\",\n            DeviceType::Unknown,\n            DeviceFlags::SECURE_OPEN,\n            DeviceDoFlags::DO_BUFFERED_IO,\n            Access::NonExclusive,\n            MyDevice,\n        )?;\n        let symbolic_link = SymbolicLink::new(\"\\\\??\\\\Example\", \"\\\\Device\\\\Example\")?;\n\n        Ok(Module {\n            _device: device,\n            _symbolic_link: symbolic_link,\n        })\n    }\n\n    fn cleanup(&mut self, _driver: Driver) {\n    }\n}\n\nkernel_module!(Module);\n"
  },
  {
    "path": "06-reading-and-writing/Cargo.toml",
    "content": "[package]\nname = \"06-reading-and-writing\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n[lib]\ncrate-type = [\"cdylib\"]\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release]\npanic = \"abort\"\n\n[build-dependencies]\nwindows-kernel-build = { path = \"../windows-kernel-build\" }\n\n[dependencies]\nwidestring = { version = \"0.4\", default-features = false, features = [\"alloc\"]}\nwindows-kernel-rs = { path = \"../windows-kernel-rs\" }\nwindows-kernel-sys = { path = \"../windows-kernel-sys\" }\n"
  },
  {
    "path": "06-reading-and-writing/Makefile.toml",
    "content": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.bat\"\n\n[env.development]\nTARGET_PATH = \"target/debug\"\n\n[env.production]\nTARGET_PATH = \"target/release\"\nBUILD_RELEASE = \"--release\"\n\n[tasks.clean-cert]\nscript = '''\n# Remove the self-signed certificate.\nif exist DriverCertificate.cer ( rm DriverCertificate.cer )\n'''\n\n[tasks.build-driver]\nscript = '''\ncargo b %BUILD_FLAGS%\n'''\n\n[tasks.rename]\nignore_errors = true\nscript = '''\ncd %TARGET_PATH%\nrename driver.dll driver.sys\n'''\n\n[tasks.sign]\ndependencies = [\"build-driver\", \"rename\"]\nscript = '''\ncall \"%VC_BUILD_DIR%\"\n\nif not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )\n\nsigntool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys\n'''\n"
  },
  {
    "path": "06-reading-and-writing/build.rs",
    "content": "fn main() {\n    windows_kernel_build::build().unwrap();\n}\n"
  },
  {
    "path": "06-reading-and-writing/rust-toolchain",
    "content": "nightly\n"
  },
  {
    "path": "06-reading-and-writing/src/lib.rs",
    "content": "#![no_std]\n\nextern crate alloc;\n\nuse alloc::vec;\nuse alloc::vec::Vec;\nuse windows_kernel_rs::device::{\n    Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceType, RequestError};\nuse windows_kernel_rs::request::{ReadRequest, WriteRequest};\nuse windows_kernel_rs::{Access, Driver, Error, kernel_module, KernelModule, SymbolicLink};\n\nstruct MyDevice {\n    data: Vec<u8>,\n}\n\nimpl DeviceOperations for MyDevice {\n    fn read(&mut self, _device: &Device, request: ReadRequest) -> Result<Completion, RequestError> {\n        let mut user_ptr = request.user_ptr();\n        let slice = user_ptr.as_mut_slice();\n\n        let offset = (request.offset() as usize).min(self.data.len());\n        let size = slice.len().min(self.data.len() - offset);\n\n        slice[0..size].copy_from_slice(&self.data[offset..offset + size]);\n\n        Ok(Completion::Complete(size as u32, request.into()))\n    }\n\n    fn write(&mut self, _device: &Device, request: WriteRequest) -> Result<Completion, RequestError> {\n        let user_ptr = request.user_ptr();\n\n        if request.offset() > 0 {\n            return Err(RequestError(Error::END_OF_FILE, request.into()))?;\n        }\n\n        let slice = user_ptr.as_slice();\n        let size = slice.len().min(4096);\n\n        self.data = slice[0..size].to_vec();\n\n        Ok(Completion::Complete(size as u32, request.into()))\n    }\n}\n\nstruct Module {\n    _device: Device,\n    _symbolic_link: SymbolicLink,\n}\n\nimpl KernelModule for Module {\n    fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {\n        let device = driver.create_device(\n            \"\\\\Device\\\\Example\",\n            DeviceType::Unknown,\n            DeviceFlags::SECURE_OPEN,\n            DeviceDoFlags::DO_BUFFERED_IO,\n            Access::NonExclusive,\n            MyDevice {\n                data: vec![],\n            },\n        )?;\n        let symbolic_link = SymbolicLink::new(\"\\\\??\\\\Example\", \"\\\\Device\\\\Example\")?;\n\n        Ok(Module {\n            _device: device,\n            _symbolic_link: symbolic_link,\n        })\n    }\n}\n\nkernel_module!(Module);\n"
  },
  {
    "path": "07-io-controls/Cargo.toml",
    "content": "[package]\nname = \"07-io-controls\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n[lib]\ncrate-type = [\"cdylib\"]\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release]\npanic = \"abort\"\n\n[build-dependencies]\nwindows-kernel-build = { path = \"../windows-kernel-build\" }\n\n[dependencies]\nwidestring = { version = \"0.4\", default-features = false, features = [\"alloc\"]}\nwindows-kernel-rs = { path = \"../windows-kernel-rs\" }\nwindows-kernel-sys = { path = \"../windows-kernel-sys\" }\n"
  },
  {
    "path": "07-io-controls/Makefile.toml",
    "content": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.bat\"\n\n[env.development]\nTARGET_PATH = \"target/debug\"\n\n[env.production]\nTARGET_PATH = \"target/release\"\nBUILD_RELEASE = \"--release\"\n\n[tasks.clean-cert]\nscript = '''\n# Remove the self-signed certificate.\nif exist DriverCertificate.cer ( rm DriverCertificate.cer )\n'''\n\n[tasks.build-driver]\nscript = '''\ncargo b %BUILD_FLAGS%\n'''\n\n[tasks.rename]\nignore_errors = true\nscript = '''\ncd %TARGET_PATH%\nrename driver.dll driver.sys\n'''\n\n[tasks.sign]\ndependencies = [\"build-driver\", \"rename\"]\nscript = '''\ncall \"%VC_BUILD_DIR%\"\n\nif not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )\n\nsigntool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys\n'''\n"
  },
  {
    "path": "07-io-controls/build.rs",
    "content": "fn main() {\n    windows_kernel_build::build().unwrap();\n}\n"
  },
  {
    "path": "07-io-controls/rust-toolchain",
    "content": "nightly\n"
  },
  {
    "path": "07-io-controls/src/lib.rs",
    "content": "#![no_std]\n\nuse windows_kernel_rs::device::{\n    Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceType, RequestError};\nuse windows_kernel_rs::request::IoControlRequest;\nuse windows_kernel_rs::{kernel_module, println};\nuse windows_kernel_rs::{Access, Driver, Error, KernelModule, RequiredAccess, SymbolicLink};\n\nstruct MyDevice {\n    value: u32,\n}\n\nconst IOCTL_PRINT_VALUE: u32 = 0x800;\nconst IOCTL_READ_VALUE:  u32 = 0x801;\nconst IOCTL_WRITE_VALUE: u32 = 0x802;\n\nimpl MyDevice {\n    fn print_value(&mut self, _request: &IoControlRequest) -> Result<u32, Error> {\n        println!(\"value: {}\", self.value);\n\n        Ok(0)\n    }\n\n    fn read_value(&mut self, request: &IoControlRequest) -> Result<u32, Error> {\n        let mut user_ptr = request.user_ptr();\n\n        user_ptr.write(&self.value)?;\n\n        Ok(core::mem::size_of::<u32>() as u32)\n    }\n\n    fn write_value(&mut self, request: &IoControlRequest) -> Result<u32, Error> {\n        let user_ptr = request.user_ptr();\n\n        self.value = user_ptr.read()?;\n\n        Ok(0)\n    }\n}\n\nimpl DeviceOperations for MyDevice {\n    fn ioctl(&mut self, _device: &Device, request: IoControlRequest) -> Result<Completion, RequestError> {\n        let result = match request.function() {\n            (_, IOCTL_PRINT_VALUE) =>\n                self.print_value(&request),\n            (RequiredAccess::READ_DATA, IOCTL_READ_VALUE) =>\n                self.read_value(&request),\n            (RequiredAccess::WRITE_DATA, IOCTL_WRITE_VALUE) =>\n                self.write_value(&request),\n            _ => Err(Error::INVALID_PARAMETER),\n        };\n\n        match result {\n            Ok(size) => Ok(Completion::Complete(size, request.into())),\n            Err(e) => Err(RequestError(e, request.into())),\n        }\n    }\n}\n\nstruct Module {\n    _device: Device,\n    _symbolic_link: SymbolicLink,\n}\n\nimpl KernelModule for Module {\n    fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {\n        let device = driver.create_device(\n            \"\\\\Device\\\\Example\",\n            DeviceType::Unknown,\n            DeviceFlags::SECURE_OPEN,\n            DeviceDoFlags::DO_BUFFERED_IO,\n            Access::NonExclusive,\n            MyDevice {\n                value: 0,\n            },\n        )?;\n        let symbolic_link = SymbolicLink::new(\"\\\\??\\\\Example\", \"\\\\Device\\\\Example\")?;\n\n        Ok(Module {\n            _device: device,\n            _symbolic_link: symbolic_link,\n        })\n    }\n\n    fn cleanup(&mut self, _driver: Driver) {\n    }\n}\n\nkernel_module!(Module);\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 S.J.R. van Schaik\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# windows-kernel-rs\n\n**Note**: this is still work in progress!\n\nThis is a Windows kernel framework in Rust that consists of [windows-kernel-sys](windows-kernel-sys), a crate that provides low-level unsafe bindings generated using [bindgen](https://github.com/rust-lang/rust-bindgen), and [windows-kernel-rs](windows-kernel-rs), a crate that provides safe abstractions in Rust on top.\n\n## Features\n\nTo give you an idea of whether these crates are useful to you, here is a non-exhaustive overview of the features that are currently supported and that are more or less planned:\n\n* [x] `KernelModule` to provide safe entry and exit points to your driver.\n* [x] Batteries included: panic handler, global allocator, etc.\n* [x] Rust error handling using `Result`.\n* [x] Device API to quickly set up with devices with a trait to provide the various callbacks.\n* [x] Support for reading from and writing to devices.\n* [x] Support for handling device I/O controls.\n* [x] Basic safe abstraction on top of I/O Request Packets (IRPs) using Rust ownership to model their lifetimes.\n* [x] Basic support for Memory Descriptor Lists (MDLs).\n* [x] Version API to query the current version of Microsoft Windows.\n* [x] Affinity API to run closures on a specific CPU or all CPUs in the system.\n* [x] Device API\n* [x] `FastMutex` (similar to [`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html)) based on the `FAST_MUTEX` API.\n* [x] `PushLock` (similar to [`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html)) based on the `EX_PUSH_LOCK` API.\n* [x] Abstraction for processes and process attachments to execute code in the context of a process.\n* [x] Abstraction for sections.\n* [x] Basic x86-64 intrinsics.\n* [ ] More complete model of IRP handling.\n* [ ] Support for x86 and AArch64.\n\n## Articles\n\n**Note**: this framework may progress faster than I can keep my articles up-to-date. They may currently be due for a bit of a rewrite to reflect some of the changes that made it into this repository since I have written the articles.\n\nIn addition, there are articles that cover implementing Windows kernel drivers in Rust from the ground up, including corresponding examples provided as part of this repository:\n\n1. [Prerequisites](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-prerequisites)\n2. [Hello World](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-hello-world) - [02-hello-world](02-hello-world)\n3. [Generating Bindings](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-generating-bindings) - [03-generating-bindings](03-generating-bindings)\n4. [Safe Framework](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-safe-framework) - [04-safe-framework](04-safe-framework)\n5. [Creating Devices](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-creating-devices/) - [05-creating-devices](05-creating-devices) - [user/05-creating-devices](user/05-creating-devices)\n6. [Reading and Writing](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-reading-and-writing/) - [06-reading-and-writing](06-reading-and-writing) - [user/06-reading-and-writing](user/06-reading-and-writing)\n7. [I/O Controls](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-io-controls/) - [07-io-controls](07-io-controls) - [user/07-io-controls](user/07-io-controls)\n"
  },
  {
    "path": "user/05-creating-devices/Cargo.toml",
    "content": "[package]\nname = \"user-05-creating-devices\"\nversion = \"0.1.0\"\nedition = \"2018\"\n"
  },
  {
    "path": "user/05-creating-devices/src/main.rs",
    "content": "use std::fs::File;\n\nfn main() -> Result<(), std::io::Error> {\n    let _file = File::open(\"\\\\??\\\\Example\")?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "user/06-reading-and-writing/Cargo.toml",
    "content": "[package]\nname = \"user-06-reading-and-writing\"\nversion = \"0.1.0\"\nedition = \"2018\"\n"
  },
  {
    "path": "user/06-reading-and-writing/src/main.rs",
    "content": "use std::fs::OpenOptions;\nuse std::io::{Read, Write};\n\nfn main() -> Result<(), std::io::Error> {\n    let mut file = OpenOptions::new()\n        .read(true)\n        .write(true)\n        .create(false)\n        .open(\"\\\\??\\\\Example\")?;\n\n    file.write_all(\"Hello, world!\".as_bytes())?;\n\n    let mut data = vec![0u8; 4096];\n    let size = file.read(&mut data)?;\n    \n    match std::str::from_utf8(&data[..size]) {\n        Ok(s) => println!(\"read {} bytes: \\\"{}\\\"\", size, s),\n        _ => println!(\"read {} bytes: {:x?}\", size, &data[..size]),\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "user/07-io-controls/Cargo.toml",
    "content": "[package]\nname = \"user-07-io-controls\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[target.'cfg(windows)'.dependencies]\nwinioctl = { path = \"../../winioctl\" }\n"
  },
  {
    "path": "user/07-io-controls/src/main.rs",
    "content": "use std::fs::OpenOptions;\nuse std::os::windows::io::AsRawHandle;\nuse winioctl::{DeviceType, Error};\nuse winioctl::{ioctl_none, ioctl_read, ioctl_write};\n\nconst IOCTL_PRINT_VALUE: u32 = 0x800;\nconst IOCTL_READ_VALUE:  u32 = 0x801;\nconst IOCTL_WRITE_VALUE: u32 = 0x802;\n\nioctl_none!(ioctl_print_value, DeviceType::Unknown, IOCTL_PRINT_VALUE);\nioctl_read!(ioctl_read_value, DeviceType::Unknown, IOCTL_READ_VALUE, i32);\nioctl_write!(ioctl_write_value, DeviceType::Unknown, IOCTL_WRITE_VALUE, i32);\n\nfn main() -> Result<(), Error> {\n    let file = OpenOptions::new()\n        .read(true)\n        .write(true)\n        .create(false)\n        .open(\"\\\\??\\\\Example\")?;\n    let mut value = 0;\n\n    unsafe {\n        ioctl_read_value(file.as_raw_handle(), &mut value)?;\n    }\n\n    value += 1;\n\n    unsafe {\n        ioctl_write_value(file.as_raw_handle(), &value)?;\n    }\n\n    unsafe {\n        ioctl_print_value(file.as_raw_handle())?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "windows-kernel-build/Cargo.toml",
    "content": "[package]\nname = \"windows-kernel-build\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\nthiserror = \"1.0\"\nwinreg = \"0.51\"\n"
  },
  {
    "path": "windows-kernel-build/src/lib.rs",
    "content": "use std::path::PathBuf;\nuse thiserror::Error;\nuse winreg::RegKey;\nuse winreg::enums::HKEY_LOCAL_MACHINE;\n\n#[derive(Debug, Error)]\npub enum Error {\n    #[error(transparent)]\n    IoError(#[from] std::io::Error),\n    #[error(\"cannot find the directory\")]\n    DirectoryNotFound,\n}\n\npub enum DirectoryType {\n    Include,\n    Library,\n}\n\n/// Retrieves the path to the Windows Kits directory. The default should be\n/// `C:\\Program Files (x86)\\Windows Kits\\10`.\npub fn get_windows_kits_dir() -> Result<PathBuf, Error> {\n    let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);\n    let key = r\"SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots\";\n    let dir: String = hklm.open_subkey(key)?.get_value(\"KitsRoot10\")?;\n\n    Ok(dir.into())\n}\n\n/// Retrieves the path to the kernel mode libraries. The path may look something like:\n/// `C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.18362.0\\km`.\npub fn get_km_dir(dir_type: DirectoryType) -> Result<PathBuf, Error> {\n    // We first append lib to the path and read the directory..\n    let dir = get_windows_kits_dir()?\n        .join(match dir_type {\n            DirectoryType::Include => \"Include\",\n            DirectoryType::Library => \"Lib\",\n        })\n        .read_dir()?;\n\n    // In the lib directory we may have one or more directories named after the version of Windows,\n    // we will be looking for the highest version number.\n    let dir = dir\n        .filter_map(|dir| dir.ok())\n        .map(|dir| dir.path())\n        .filter(|dir| {\n            dir.components()\n                .last()\n                .and_then(|c| c.as_os_str().to_str())\n                .map(|c| c.starts_with(\"10.\") && dir.join(\"km\").is_dir())\n                .unwrap_or(false)\n        })\n        .max()\n        .ok_or_else(|| Error::DirectoryNotFound)?;\n\n    // Finally append km to the path to get the path to the kernel mode libraries.\n    Ok(dir.join(\"km\"))\n}\n\npub fn build() -> Result<(), Error> {\n    // Get the path to the kernel libraries.\n    let dir = get_km_dir(DirectoryType::Library).unwrap();\n\n    // Append the architecture based on our target.\n    let target = std::env::var(\"TARGET\").unwrap();\n\n    let arch = if target.contains(\"x86_64\") {\n        \"x64\"\n    } else if target.contains(\"i686\") {\n        \"x86\"\n    } else {\n        panic!(\"The target {} is currently not supported.\", target);\n    };\n\n    let dir = dir.join(arch);\n\n    // Specify the link path.\n    println!(\"cargo:rustc-link-search=native={}\", dir.to_str().unwrap());\n\n    // Ensure the right linker flags are passed for building a driver.\n    println!(\"cargo:rustc-link-arg=/NODEFAULTLIB\");\n    println!(\"cargo:rustc-link-arg=/SUBSYSTEM:NATIVE\");\n    println!(\"cargo:rustc-link-arg=/DRIVER\");\n    println!(\"cargo:rustc-link-arg=/DYNAMICBASE\");\n    println!(\"cargo:rustc-link-arg=/MANIFEST:NO\");\n    println!(\"cargo:rustc-link-arg=/ENTRY:driver_entry\");\n    println!(\"cargo:rustc-link-arg=/MERGE:.edata=.rdata\");\n    println!(\"cargo:rustc-link-arg=/MERGE:.rustc=.data\");\n    println!(\"cargo:rustc-link-arg=/INTEGRITYCHECK\");\n\n    Ok(())\n}\n"
  },
  {
    "path": "windows-kernel-rs/Cargo.toml",
    "content": "[package]\nname = \"windows-kernel-rs\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release]\npanic = \"abort\"\n\n[features]\ndefault = [\"alloc\"]\nalloc = []\nsystem = []\n\n[dependencies]\nbitflags = \"2.4.0\"\ncty = \"0.2\"\nlazy_static = { version = \"1.4\", features = [\"spin_no_std\"] }\nwidestring = { version = \"1\", default-features = false, features = [\"alloc\"] }\nwindows-kernel-sys = { path = \"../windows-kernel-sys\" }\n"
  },
  {
    "path": "windows-kernel-rs/rust-toolchain",
    "content": "nightly\n"
  },
  {
    "path": "windows-kernel-rs/src/affinity.rs",
    "content": "//! This module provides functions to get information about the logical CPUs in the system, and to\n//! run closures on specific or all CPUs.\n\nuse crate::error::{Error, IntoResult};\nuse windows_kernel_sys::base::{ALL_PROCESSOR_GROUPS, GROUP_AFFINITY, PROCESSOR_NUMBER, ULONG_PTR};\nuse windows_kernel_sys::ntoskrnl::{\n    KeIpiGenericCall, KeGetCurrentProcessorNumberEx, KeGetProcessorNumberFromIndex,\n    KeQueryActiveProcessorCountEx, KeRevertToUserGroupAffinityThread,\n    KeSetSystemGroupAffinityThread,\n};\n\n/// Uses [`KeGetCurrentProcessorNumberEx`] to get the logical number associated with the CPU that\n/// is currently running our code.\npub fn get_current_cpu_num() -> u32 {\n    unsafe {\n        KeGetCurrentProcessorNumberEx(core::ptr::null_mut())\n    }\n}\n\n/// Uses [`KeQueryActiveProcessorCountEx`] to get the number of CPUs in the system, that is all the\n/// CPUs from all the different CPU groups are counted, such that each of them has a logical\n/// number.\npub fn get_cpu_count() -> u32 {\n    unsafe {\n        KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS as _)\n    }\n}\n\n/// This is the callback used by [`run_on_each_cpu_parallel`] to run the closure on all CPUs.\nunsafe extern \"C\" fn broadcast_callback<F>(\n    context: ULONG_PTR,\n) -> ULONG_PTR\nwhere\n    F: FnMut(),\n{\n    let f = &mut *(context as *mut F);\n    f();\n\n    0\n}\n\n/// Runs the given closure on all CPUs in the system without interrupting all CPUs to force them to\n/// switch to kernel mode. Instead, this is a more graceful version that simply relies on\n/// [`run_on_cpu`] to switch to all the possible CPUs by configuring the affinity, and execute the\n/// closure on the selected CPU. Upon executing the closure on all CPUs, the affinity is restored.\n/// Also see [`run_on_each_cpu_parallel`] which is a more aggressive version that relies on an IPI\n/// to run a given closure on all CPUs in parallel.\npub fn run_on_each_cpu<F>(\n    f: &mut F,\n) -> Result<(), Error>\nwhere\n    F: FnMut() -> Result<(), Error>,\n{\n    for cpu_num in 0..get_cpu_count() {\n        run_on_cpu(cpu_num, f)?;\n    }\n\n    Ok(())\n}\n\n/// Runs the given closure on all CPUs in the system by broadcasting an Inter-Processor Interrupt\n/// (IPI) to interrupt all CPUs to force them to switch to kernel mode to run the given closure.\n/// Upon execution of the closure, these CPUs resume their work. Also see [`run_on_each_cpu`] which\n/// is a friendlier version that does not rely on an IPI but instead configures the affinity to run\n/// a given a closure on all CPUs.\npub fn run_on_each_cpu_parallel<F>(\n    f: &F,\n)\nwhere\n    F: Fn(),\n{\n    unsafe {\n        KeIpiGenericCall(Some(broadcast_callback::<F>), f as *const _ as ULONG_PTR);\n    }\n}\n\n/// Runs the given closure on the CPU with the given CPU number by temporarily configuring the CPU\n/// affinity to only contain the given CPU number. Upon switching to the selected CPU, the CPU\n/// executes the closure. Then the original affinity is restored.\npub fn run_on_cpu<F>(\n    cpu_num: u32,\n    f: &mut F,\n) -> Result<(), Error>\nwhere\n    F: FnMut() -> Result<(), Error>,\n{\n    let mut processor_num = PROCESSOR_NUMBER {\n        Group: 0,\n        Number: 0,\n        Reserved: 0,\n    };\n\n    unsafe {\n        KeGetProcessorNumberFromIndex(cpu_num, &mut processor_num)\n    }.into_result()?;\n\n    let mut previous = GROUP_AFFINITY {\n        Mask: 0,\n        Group: 0,\n        Reserved: [0; 3],\n    };\n\n    let mut affinity = GROUP_AFFINITY {\n        Mask: 1 << processor_num.Number,\n        Group: processor_num.Group,\n        Reserved: [0; 3],\n    };\n\n    unsafe {\n        KeSetSystemGroupAffinityThread(&mut affinity, &mut previous);\n    }\n\n    let result = f();\n\n    unsafe {\n        KeRevertToUserGroupAffinityThread(&mut previous);\n    }\n\n    result\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/allocator.rs",
    "content": "//! This module provides an allocator to use with the [`alloc`] crate. You can define your own\n//! global allocator with the `#[global_allocator]` attribute when not using the `alloc` feature,\n//! in case you want to specify your own tag to use with [`ExAllocatePool2`] and\n//! [`ExAllocatePoolWithTag`].\n\nuse core::alloc::{GlobalAlloc, Layout};\nuse crate::version::VersionInfo;\nuse lazy_static::lazy_static;\nuse windows_kernel_sys::base::_POOL_TYPE as POOL_TYPE;\nuse windows_kernel_sys::ntoskrnl::{ExAllocatePoolWithTag, ExAllocatePool2, ExFreePool};\n\n/// See issue #52191.\n#[alloc_error_handler]\nfn alloc_error(_: Layout) -> ! {\n    loop {}\n}\n\nlazy_static! {\n    /// The version of Microsoft Windows that is currently running. This is used by\n    /// [`KernelAllocator`] to determine whether to use [`ExAllocatePool2`] or\n    /// [`ExAllocatePoolWithTag`].\n    static ref VERSION_INFO: VersionInfo = {\n        VersionInfo::query().unwrap()\n    };\n}\n\n/// Represents a kernel allocator that relies on the `ExAllocatePool` family of functions to\n/// allocate and free memory for the `alloc` crate.\npub struct KernelAllocator {\n    /// The 32-bit tag to use for the pool, this is usually derived from a quadruplet of ASCII\n    /// bytes, e.g. by invoking `u32::from_ne_bytes(*b\"rust\")`.\n    tag: u32,\n}\n\nimpl KernelAllocator {\n    /// Sets up a new kernel allocator with the 32-bit tag specified. The tag is usually derived\n    /// from a quadruplet of ASCII bytes, e.g. by invoking `u32::from_ne_bytes(*b\"rust\")`.\n    pub const fn new(tag: u32) -> Self {\n        Self {\n            tag,\n        }\n    }\n}\n\nunsafe impl GlobalAlloc for KernelAllocator {\n    /// Uses [`ExAllocatePool2`] on Microsoft Windows 10.0.19041 and later, and\n    /// [`ExAllocatePoolWithTag`] on older versions of Microsoft Windows to allocate memory.\n    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {\n        let use_ex_allocate_pool2 =\n            VERSION_INFO.major() > 10 ||\n            (VERSION_INFO.major() == 10 && VERSION_INFO.build_number() == 19041);\n\n        let ptr = if use_ex_allocate_pool2 {\n            ExAllocatePool2(\n                POOL_TYPE::NonPagedPool as _,\n                layout.size() as u64,\n                self.tag,\n            )\n        } else {\n            ExAllocatePoolWithTag(\n                POOL_TYPE::NonPagedPool,\n                layout.size() as u64,\n                self.tag,\n            )\n        };\n\n        if ptr.is_null() {\n            panic!(\"[kernel-alloc] failed to allocate pool.\");\n        }\n\n        ptr as _\n    }\n\n    /// Uses [`ExFreePool`] to free allocated memory.\n    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {\n        ExFreePool(ptr as _)\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/device.rs",
    "content": "use crate::error::Error;\nuse crate::request::{IoControlRequest, IoRequest, ReadRequest, WriteRequest};\nuse alloc::boxed::Box;\nuse bitflags::bitflags;\nuse windows_kernel_sys::base::STATUS_SUCCESS;\nuse windows_kernel_sys::base::{DEVICE_OBJECT, IRP, NTSTATUS};\nuse windows_kernel_sys::base::{\n    IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_CREATE, IRP_MJ_DEVICE_CONTROL, IRP_MJ_READ, IRP_MJ_WRITE,\n};\nuse windows_kernel_sys::ntoskrnl::{IoDeleteDevice, IoGetCurrentIrpStackLocation};\n\n#[derive(Copy, Clone, Debug)]\npub enum Access {\n    NonExclusive,\n    Exclusive,\n}\n\nimpl Access {\n    pub fn is_exclusive(&self) -> bool {\n        match *self {\n            Access::Exclusive => true,\n            _ => false,\n        }\n    }\n}\n\nbitflags! {\n    pub struct DeviceFlags: u32 {\n        const SECURE_OPEN = windows_kernel_sys::base::FILE_DEVICE_SECURE_OPEN;\n    }\n}\n\nbitflags! {\n    pub struct DeviceDoFlags: u32 {\n        const DO_BUFFERED_IO = windows_kernel_sys::base::DO_BUFFERED_IO;\n        const DO_DIRECT_IO   = windows_kernel_sys::base::DO_DIRECT_IO;\n    }\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub enum DeviceType {\n    Port8042,\n    Acpi,\n    Battery,\n    Beep,\n    BusExtender,\n    Cdrom,\n    CdromFileSystem,\n    Changer,\n    Controller,\n    DataLink,\n    Dfs,\n    DfsFileSystem,\n    DfsVolume,\n    Disk,\n    DiskFileSystem,\n    Dvd,\n    FileSystem,\n    Fips,\n    FullscreenVideo,\n    InportPort,\n    Keyboard,\n    Ks,\n    Ksec,\n    Mailslot,\n    MassStorage,\n    MidiIn,\n    MidiOut,\n    Modem,\n    Mouse,\n    MultiUncProvider,\n    NamedPipe,\n    Network,\n    NetworkBrowser,\n    NetworkFileSystem,\n    NetworkRedirector,\n    Null,\n    ParallelPort,\n    PhysicalNetcard,\n    Printer,\n    Scanner,\n    Screen,\n    Serenum,\n    SerialPort,\n    SerialMousePort,\n    Smartcard,\n    Smb,\n    Sound,\n    Streams,\n    Tape,\n    TapeFileSystem,\n    Termsrv,\n    Transport,\n    Unknown,\n    Vdm,\n    Video,\n    VirtualDisk,\n    WaveIn,\n    WaveOut,\n}\n\nimpl Into<u32> for DeviceType {\n    fn into(self) -> u32 {\n        match self {\n            DeviceType::Port8042 => windows_kernel_sys::base::FILE_DEVICE_8042_PORT,\n            DeviceType::Acpi => windows_kernel_sys::base::FILE_DEVICE_ACPI,\n            DeviceType::Battery => windows_kernel_sys::base::FILE_DEVICE_BATTERY,\n            DeviceType::Beep => windows_kernel_sys::base::FILE_DEVICE_BEEP,\n            DeviceType::BusExtender => windows_kernel_sys::base::FILE_DEVICE_BUS_EXTENDER,\n            DeviceType::Cdrom => windows_kernel_sys::base::FILE_DEVICE_CD_ROM,\n            DeviceType::CdromFileSystem => windows_kernel_sys::base::FILE_DEVICE_CD_ROM_FILE_SYSTEM,\n            DeviceType::Changer => windows_kernel_sys::base::FILE_DEVICE_CHANGER,\n            DeviceType::Controller => windows_kernel_sys::base::FILE_DEVICE_CONTROLLER,\n            DeviceType::DataLink => windows_kernel_sys::base::FILE_DEVICE_DATALINK,\n            DeviceType::Dfs => windows_kernel_sys::base::FILE_DEVICE_DFS,\n            DeviceType::DfsFileSystem => windows_kernel_sys::base::FILE_DEVICE_DFS_FILE_SYSTEM,\n            DeviceType::DfsVolume => windows_kernel_sys::base::FILE_DEVICE_DFS_VOLUME,\n            DeviceType::Disk => windows_kernel_sys::base::FILE_DEVICE_DISK,\n            DeviceType::DiskFileSystem => windows_kernel_sys::base::FILE_DEVICE_DISK_FILE_SYSTEM,\n            DeviceType::Dvd => windows_kernel_sys::base::FILE_DEVICE_DVD,\n            DeviceType::FileSystem => windows_kernel_sys::base::FILE_DEVICE_FILE_SYSTEM,\n            DeviceType::Fips => windows_kernel_sys::base::FILE_DEVICE_FIPS,\n            DeviceType::FullscreenVideo => windows_kernel_sys::base::FILE_DEVICE_FULLSCREEN_VIDEO,\n            DeviceType::InportPort => windows_kernel_sys::base::FILE_DEVICE_INPORT_PORT,\n            DeviceType::Keyboard => windows_kernel_sys::base::FILE_DEVICE_KEYBOARD,\n            DeviceType::Ks => windows_kernel_sys::base::FILE_DEVICE_KS,\n            DeviceType::Ksec => windows_kernel_sys::base::FILE_DEVICE_KSEC,\n            DeviceType::Mailslot => windows_kernel_sys::base::FILE_DEVICE_MAILSLOT,\n            DeviceType::MassStorage => windows_kernel_sys::base::FILE_DEVICE_MASS_STORAGE,\n            DeviceType::MidiIn => windows_kernel_sys::base::FILE_DEVICE_MIDI_IN,\n            DeviceType::MidiOut => windows_kernel_sys::base::FILE_DEVICE_MIDI_OUT,\n            DeviceType::Modem => windows_kernel_sys::base::FILE_DEVICE_MODEM,\n            DeviceType::Mouse => windows_kernel_sys::base::FILE_DEVICE_MOUSE,\n            DeviceType::MultiUncProvider => {\n                windows_kernel_sys::base::FILE_DEVICE_MULTI_UNC_PROVIDER\n            }\n            DeviceType::NamedPipe => windows_kernel_sys::base::FILE_DEVICE_NAMED_PIPE,\n            DeviceType::Network => windows_kernel_sys::base::FILE_DEVICE_NETWORK,\n            DeviceType::NetworkBrowser => windows_kernel_sys::base::FILE_DEVICE_NETWORK_BROWSER,\n            DeviceType::NetworkFileSystem => {\n                windows_kernel_sys::base::FILE_DEVICE_NETWORK_FILE_SYSTEM\n            }\n            DeviceType::NetworkRedirector => {\n                windows_kernel_sys::base::FILE_DEVICE_NETWORK_REDIRECTOR\n            }\n            DeviceType::Null => windows_kernel_sys::base::FILE_DEVICE_NULL,\n            DeviceType::ParallelPort => windows_kernel_sys::base::FILE_DEVICE_PARALLEL_PORT,\n            DeviceType::PhysicalNetcard => windows_kernel_sys::base::FILE_DEVICE_PHYSICAL_NETCARD,\n            DeviceType::Printer => windows_kernel_sys::base::FILE_DEVICE_PRINTER,\n            DeviceType::Scanner => windows_kernel_sys::base::FILE_DEVICE_SCANNER,\n            DeviceType::Screen => windows_kernel_sys::base::FILE_DEVICE_SCREEN,\n            DeviceType::Serenum => windows_kernel_sys::base::FILE_DEVICE_SERENUM,\n            DeviceType::SerialMousePort => windows_kernel_sys::base::FILE_DEVICE_SERIAL_MOUSE_PORT,\n            DeviceType::SerialPort => windows_kernel_sys::base::FILE_DEVICE_SERIAL_PORT,\n            DeviceType::Smartcard => windows_kernel_sys::base::FILE_DEVICE_SMARTCARD,\n            DeviceType::Smb => windows_kernel_sys::base::FILE_DEVICE_SMB,\n            DeviceType::Sound => windows_kernel_sys::base::FILE_DEVICE_SOUND,\n            DeviceType::Streams => windows_kernel_sys::base::FILE_DEVICE_STREAMS,\n            DeviceType::Tape => windows_kernel_sys::base::FILE_DEVICE_TAPE,\n            DeviceType::TapeFileSystem => windows_kernel_sys::base::FILE_DEVICE_TAPE_FILE_SYSTEM,\n            DeviceType::Termsrv => windows_kernel_sys::base::FILE_DEVICE_TERMSRV,\n            DeviceType::Transport => windows_kernel_sys::base::FILE_DEVICE_TRANSPORT,\n            DeviceType::Unknown => windows_kernel_sys::base::FILE_DEVICE_UNKNOWN,\n            DeviceType::Vdm => windows_kernel_sys::base::FILE_DEVICE_VDM,\n            DeviceType::Video => windows_kernel_sys::base::FILE_DEVICE_VIDEO,\n            DeviceType::VirtualDisk => windows_kernel_sys::base::FILE_DEVICE_VIRTUAL_DISK,\n            DeviceType::WaveIn => windows_kernel_sys::base::FILE_DEVICE_WAVE_IN,\n            DeviceType::WaveOut => windows_kernel_sys::base::FILE_DEVICE_WAVE_OUT,\n        }\n    }\n}\n\nimpl From<u32> for DeviceType {\n    fn from(value: u32) -> Self {\n        match value {\n            windows_kernel_sys::base::FILE_DEVICE_8042_PORT => DeviceType::Port8042,\n            windows_kernel_sys::base::FILE_DEVICE_ACPI => DeviceType::Acpi,\n            windows_kernel_sys::base::FILE_DEVICE_BATTERY => DeviceType::Battery,\n            windows_kernel_sys::base::FILE_DEVICE_BEEP => DeviceType::Beep,\n            windows_kernel_sys::base::FILE_DEVICE_BUS_EXTENDER => DeviceType::BusExtender,\n            windows_kernel_sys::base::FILE_DEVICE_CD_ROM => DeviceType::Cdrom,\n            windows_kernel_sys::base::FILE_DEVICE_CD_ROM_FILE_SYSTEM => DeviceType::CdromFileSystem,\n            windows_kernel_sys::base::FILE_DEVICE_CHANGER => DeviceType::Changer,\n            windows_kernel_sys::base::FILE_DEVICE_CONTROLLER => DeviceType::Controller,\n            windows_kernel_sys::base::FILE_DEVICE_DATALINK => DeviceType::DataLink,\n            windows_kernel_sys::base::FILE_DEVICE_DFS => DeviceType::Dfs,\n            windows_kernel_sys::base::FILE_DEVICE_DFS_FILE_SYSTEM => DeviceType::DfsFileSystem,\n            windows_kernel_sys::base::FILE_DEVICE_DFS_VOLUME => DeviceType::DfsVolume,\n            windows_kernel_sys::base::FILE_DEVICE_DISK => DeviceType::Disk,\n            windows_kernel_sys::base::FILE_DEVICE_DISK_FILE_SYSTEM => DeviceType::DiskFileSystem,\n            windows_kernel_sys::base::FILE_DEVICE_DVD => DeviceType::Dvd,\n            windows_kernel_sys::base::FILE_DEVICE_FILE_SYSTEM => DeviceType::FileSystem,\n            windows_kernel_sys::base::FILE_DEVICE_FIPS => DeviceType::Fips,\n            windows_kernel_sys::base::FILE_DEVICE_FULLSCREEN_VIDEO => DeviceType::FullscreenVideo,\n            windows_kernel_sys::base::FILE_DEVICE_INPORT_PORT => DeviceType::InportPort,\n            windows_kernel_sys::base::FILE_DEVICE_KEYBOARD => DeviceType::Keyboard,\n            windows_kernel_sys::base::FILE_DEVICE_KS => DeviceType::Ks,\n            windows_kernel_sys::base::FILE_DEVICE_KSEC => DeviceType::Ksec,\n            windows_kernel_sys::base::FILE_DEVICE_MAILSLOT => DeviceType::Mailslot,\n            windows_kernel_sys::base::FILE_DEVICE_MASS_STORAGE => DeviceType::MassStorage,\n            windows_kernel_sys::base::FILE_DEVICE_MIDI_IN => DeviceType::MidiIn,\n            windows_kernel_sys::base::FILE_DEVICE_MIDI_OUT => DeviceType::MidiOut,\n            windows_kernel_sys::base::FILE_DEVICE_MODEM => DeviceType::Modem,\n            windows_kernel_sys::base::FILE_DEVICE_MOUSE => DeviceType::Mouse,\n            windows_kernel_sys::base::FILE_DEVICE_MULTI_UNC_PROVIDER => {\n                DeviceType::MultiUncProvider\n            }\n            windows_kernel_sys::base::FILE_DEVICE_NAMED_PIPE => DeviceType::NamedPipe,\n            windows_kernel_sys::base::FILE_DEVICE_NETWORK => DeviceType::Network,\n            windows_kernel_sys::base::FILE_DEVICE_NETWORK_BROWSER => DeviceType::NetworkBrowser,\n            windows_kernel_sys::base::FILE_DEVICE_NETWORK_FILE_SYSTEM => {\n                DeviceType::NetworkFileSystem\n            }\n            windows_kernel_sys::base::FILE_DEVICE_NETWORK_REDIRECTOR => {\n                DeviceType::NetworkRedirector\n            }\n            windows_kernel_sys::base::FILE_DEVICE_NULL => DeviceType::Null,\n            windows_kernel_sys::base::FILE_DEVICE_PARALLEL_PORT => DeviceType::ParallelPort,\n            windows_kernel_sys::base::FILE_DEVICE_PHYSICAL_NETCARD => DeviceType::PhysicalNetcard,\n            windows_kernel_sys::base::FILE_DEVICE_PRINTER => DeviceType::Printer,\n            windows_kernel_sys::base::FILE_DEVICE_SCANNER => DeviceType::Scanner,\n            windows_kernel_sys::base::FILE_DEVICE_SCREEN => DeviceType::Screen,\n            windows_kernel_sys::base::FILE_DEVICE_SERENUM => DeviceType::Serenum,\n            windows_kernel_sys::base::FILE_DEVICE_SERIAL_MOUSE_PORT => DeviceType::SerialMousePort,\n            windows_kernel_sys::base::FILE_DEVICE_SERIAL_PORT => DeviceType::SerialPort,\n            windows_kernel_sys::base::FILE_DEVICE_SMARTCARD => DeviceType::Smartcard,\n            windows_kernel_sys::base::FILE_DEVICE_SMB => DeviceType::Smb,\n            windows_kernel_sys::base::FILE_DEVICE_SOUND => DeviceType::Sound,\n            windows_kernel_sys::base::FILE_DEVICE_STREAMS => DeviceType::Streams,\n            windows_kernel_sys::base::FILE_DEVICE_TAPE => DeviceType::Tape,\n            windows_kernel_sys::base::FILE_DEVICE_TAPE_FILE_SYSTEM => DeviceType::TapeFileSystem,\n            windows_kernel_sys::base::FILE_DEVICE_TERMSRV => DeviceType::Termsrv,\n            windows_kernel_sys::base::FILE_DEVICE_TRANSPORT => DeviceType::Transport,\n            windows_kernel_sys::base::FILE_DEVICE_UNKNOWN => DeviceType::Unknown,\n            windows_kernel_sys::base::FILE_DEVICE_VDM => DeviceType::Vdm,\n            windows_kernel_sys::base::FILE_DEVICE_VIDEO => DeviceType::Video,\n            windows_kernel_sys::base::FILE_DEVICE_VIRTUAL_DISK => DeviceType::VirtualDisk,\n            windows_kernel_sys::base::FILE_DEVICE_WAVE_IN => DeviceType::WaveIn,\n            windows_kernel_sys::base::FILE_DEVICE_WAVE_OUT => DeviceType::WaveOut,\n            _ => DeviceType::Unknown,\n        }\n    }\n}\n\n#[repr(C)]\npub struct device_operations {\n    dispatch: Option<extern \"C\" fn(*mut DEVICE_OBJECT, *mut IRP, u8) -> NTSTATUS>,\n    release: Option<extern \"C\" fn(*mut DEVICE_OBJECT)>,\n}\n\npub struct Device {\n    raw: *mut DEVICE_OBJECT,\n}\n\nunsafe impl Send for Device {}\nunsafe impl Sync for Device {}\n\nimpl Device {\n    pub unsafe fn from_raw(raw: *mut DEVICE_OBJECT) -> Self {\n        Self { raw }\n    }\n\n    pub unsafe fn as_raw(&self) -> *const DEVICE_OBJECT {\n        self.raw as *const _\n    }\n\n    pub unsafe fn as_raw_mut(&self) -> *mut DEVICE_OBJECT {\n        self.raw\n    }\n\n    pub fn into_raw(mut self) -> *mut DEVICE_OBJECT {\n        core::mem::replace(&mut self.raw, core::ptr::null_mut())\n    }\n\n    pub(crate) fn extension(&self) -> &DeviceExtension {\n        unsafe { &*((*self.raw).DeviceExtension as *const DeviceExtension) }\n    }\n\n    pub(crate) fn extension_mut(&self) -> &mut DeviceExtension {\n        unsafe { &mut *((*self.raw).DeviceExtension as *mut DeviceExtension) }\n    }\n\n    pub(crate) fn device_type(&self) -> DeviceType {\n        self.extension().device_type\n    }\n\n    pub(crate) fn vtable(&self) -> &device_operations {\n        unsafe { &*(self.extension().vtable as *const _) }\n    }\n\n    pub fn data<T: DeviceOperations>(&self) -> &T {\n        unsafe { &*(self.extension().data as *const T) }\n    }\n\n    pub fn data_mut<T: DeviceOperations>(&self) -> &mut T {\n        unsafe { &mut *(self.extension().data as *mut T) }\n    }\n}\n\nimpl Drop for Device {\n    fn drop(&mut self) {\n        if self.raw.is_null() {\n            return;\n        }\n\n        unsafe {\n            if let Some(release) = self.vtable().release {\n                release(self.raw);\n            }\n\n            IoDeleteDevice(self.raw);\n        }\n    }\n}\n\npub struct RequestError(pub Error, pub IoRequest);\n\npub enum Completion {\n    Complete(u32, IoRequest),\n}\n\npub trait DeviceOperations: Sync + Sized {\n    fn create(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {\n        Ok(Completion::Complete(0, request))\n    }\n\n    fn close(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {\n        Ok(Completion::Complete(0, request))\n    }\n\n    fn cleanup(\n        &mut self,\n        _device: &Device,\n        request: IoRequest,\n    ) -> Result<Completion, RequestError> {\n        Ok(Completion::Complete(0, request))\n    }\n\n    fn read(&mut self, _device: &Device, request: ReadRequest) -> Result<Completion, RequestError> {\n        Ok(Completion::Complete(0, request.into()))\n    }\n\n    fn write(\n        &mut self,\n        _device: &Device,\n        request: WriteRequest,\n    ) -> Result<Completion, RequestError> {\n        Ok(Completion::Complete(0, request.into()))\n    }\n\n    fn ioctl(\n        &mut self,\n        _device: &Device,\n        request: IoControlRequest,\n    ) -> Result<Completion, RequestError> {\n        Ok(Completion::Complete(0, request.into()))\n    }\n}\n\nextern \"C\" fn dispatch_callback<T: DeviceOperations>(\n    device: *mut DEVICE_OBJECT,\n    irp: *mut IRP,\n    major: u8,\n) -> NTSTATUS {\n    let device = unsafe { Device::from_raw(device) };\n    let data: &mut T = device.data_mut();\n    let request = unsafe { IoRequest::from_raw(irp) };\n\n    let result = match major as _ {\n        IRP_MJ_CREATE => data.create(&device, request),\n        IRP_MJ_CLOSE => data.close(&device, request),\n        IRP_MJ_CLEANUP => data.cleanup(&device, request),\n        IRP_MJ_READ => {\n            let read_request = ReadRequest { inner: request };\n\n            data.read(&device, read_request)\n        }\n        IRP_MJ_WRITE => {\n            let write_request = WriteRequest { inner: request };\n\n            data.write(&device, write_request)\n        }\n        IRP_MJ_DEVICE_CONTROL => {\n            let control_request = IoControlRequest { inner: request };\n\n            if device.device_type() == control_request.control_code().device_type() {\n                data.ioctl(&device, control_request)\n            } else {\n                Err(RequestError(\n                    Error::INVALID_PARAMETER,\n                    control_request.into(),\n                ))\n            }\n        }\n        _ => Err(RequestError(Error::INVALID_PARAMETER, request)),\n    };\n\n    device.into_raw();\n\n    match result {\n        Ok(Completion::Complete(size, request)) => {\n            request.complete(Ok(size));\n            STATUS_SUCCESS\n        }\n        Err(RequestError(e, request)) => {\n            let status = e.to_ntstatus();\n            request.complete(Err(e));\n            status\n        }\n    }\n}\n\nextern \"C\" fn release_callback<T: DeviceOperations>(device: *mut DEVICE_OBJECT) {\n    unsafe {\n        let extension = (*device).DeviceExtension as *mut DeviceExtension;\n\n        let ptr = core::mem::replace(&mut (*extension).data, core::ptr::null_mut());\n        let _ = Box::from_raw(ptr as *mut T);\n    }\n}\n\npub(crate) struct DeviceOperationsVtable<T>(core::marker::PhantomData<T>);\n\nimpl<T: DeviceOperations> DeviceOperationsVtable<T> {\n    pub(crate) const VTABLE: device_operations = device_operations {\n        dispatch: Some(dispatch_callback::<T>),\n        release: Some(release_callback::<T>),\n    };\n}\n\n#[repr(C)]\npub struct DeviceExtension {\n    pub(crate) vtable: *const device_operations,\n    pub(crate) data: *mut cty::c_void,\n    pub(crate) device_type: DeviceType,\n}\n\npub extern \"C\" fn dispatch_device(device: *mut DEVICE_OBJECT, irp: *mut IRP) -> NTSTATUS {\n    let stack_location = unsafe { &*IoGetCurrentIrpStackLocation(irp) };\n    let device = unsafe { Device::from_raw(device) };\n    let vtable = device.vtable();\n\n    match vtable.dispatch {\n        Some(dispatch) => dispatch(device.into_raw(), irp, stack_location.MajorFunction),\n        _ => {\n            device.into_raw();\n            STATUS_SUCCESS\n        }\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/driver.rs",
    "content": "use alloc::boxed::Box;\nuse crate::device::{Access, Device, DeviceExtension, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceOperationsVtable, DeviceType};\nuse crate::error::{Error, IntoResult};\nuse crate::string::create_unicode_string;\nuse widestring::U16CString;\nuse windows_kernel_sys::base::DRIVER_OBJECT;\nuse windows_kernel_sys::ntoskrnl::{IoCreateDevice};\n\npub struct Driver {\n    pub(crate) raw: *mut DRIVER_OBJECT,\n}\n\nimpl Driver {\n    pub unsafe fn from_raw(raw: *mut DRIVER_OBJECT) -> Self {\n        Self {\n            raw,\n        }\n    }\n\n    pub unsafe fn as_raw(&self) -> *const DRIVER_OBJECT {\n        self.raw as _\n    }\n\n    pub unsafe fn as_raw_mut(&mut self) -> *mut DRIVER_OBJECT {\n        self.raw as _\n    }\n\n    pub fn create_device<T>(\n        &mut self,\n        name: &str,\n        device_type: DeviceType,\n        device_flags: DeviceFlags,\n        device_do_flags: DeviceDoFlags,\n        access: Access,\n        data: T,\n    ) -> Result<Device, Error>\n    where\n        T: DeviceOperations\n    {\n        // Box the data.\n        let data = Box::new(data);\n\n        // Convert the name to UTF-16 and then create a UNICODE_STRING.\n        let name = U16CString::from_str(name).unwrap();\n        let mut name = create_unicode_string(name.as_slice());\n\n        // Create the device.\n        let mut device = core::ptr::null_mut();\n\n        unsafe {\n            IoCreateDevice(\n                self.raw,\n                core::mem::size_of::<DeviceExtension>() as u32,\n                &mut name,\n                device_type.into(),\n                device_flags.bits(),\n                access.is_exclusive() as _,\n                &mut device,\n            )\n        }.into_result()?;\n\n        unsafe {\n            (*device).Flags |= device_do_flags.bits();\n        }\n\n        let device = unsafe { Device::from_raw(device) };\n\n        // Store the boxed data and vtable.\n        let extension = device.extension_mut();\n        extension.device_type = device_type;\n        extension.vtable = &DeviceOperationsVtable::<T>::VTABLE;\n        extension.data = Box::into_raw(data) as *mut cty::c_void;\n\n        Ok(device)\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/error.rs",
    "content": "use windows_kernel_sys::base::NTSTATUS;\nuse windows_kernel_sys::base::{\n    STATUS_SUCCESS,\n    STATUS_GUARD_PAGE_VIOLATION,\n    STATUS_DATATYPE_MISALIGNMENT,\n    STATUS_BREAKPOINT,\n    STATUS_SINGLE_STEP,\n    STATUS_UNWIND_CONSOLIDATE,\n    STATUS_UNSUCCESSFUL,\n    STATUS_NOT_IMPLEMENTED,\n    STATUS_ACCESS_VIOLATION,\n    STATUS_IN_PAGE_ERROR,\n    STATUS_INVALID_HANDLE,\n    STATUS_INVALID_PARAMETER,\n    STATUS_END_OF_FILE,\n    STATUS_NO_MEMORY,\n    STATUS_ILLEGAL_INSTRUCTION,\n    STATUS_NONCONTINUABLE_EXCEPTION,\n    STATUS_INVALID_DISPOSITION,\n    STATUS_ARRAY_BOUNDS_EXCEEDED,\n    STATUS_FLOAT_DENORMAL_OPERAND,\n    STATUS_FLOAT_DIVIDE_BY_ZERO,\n    STATUS_FLOAT_INEXACT_RESULT,\n    STATUS_FLOAT_INVALID_OPERATION,\n    STATUS_FLOAT_OVERFLOW,\n    STATUS_FLOAT_STACK_CHECK,\n    STATUS_FLOAT_UNDERFLOW,\n    STATUS_INTEGER_DIVIDE_BY_ZERO,\n    STATUS_INTEGER_OVERFLOW,\n    STATUS_PRIVILEGED_INSTRUCTION,\n    STATUS_INSUFFICIENT_RESOURCES,\n    STATUS_INVALID_USER_BUFFER,\n    STATUS_STACK_OVERFLOW,\n};\n\n#[derive(Clone, Copy, Debug)]\npub struct Error(NTSTATUS);\n\nimpl Error {\n    pub const GUARD_PAGE_VIOLATION:     Error = Error(STATUS_GUARD_PAGE_VIOLATION);\n    pub const DATATYPE_MISALIGNMENT:    Error = Error(STATUS_DATATYPE_MISALIGNMENT);\n    pub const BREAKPOINT:               Error = Error(STATUS_BREAKPOINT);\n    pub const SINGLE_STEP:              Error = Error(STATUS_SINGLE_STEP);\n    pub const UNWIND_CONSOLIDATE:       Error = Error(STATUS_UNWIND_CONSOLIDATE);\n    pub const UNSUCCESSFUL:             Error = Error(STATUS_UNSUCCESSFUL);\n    pub const NOT_IMPLEMENTED:          Error = Error(STATUS_NOT_IMPLEMENTED);\n    pub const ACCESS_VIOLATION:         Error = Error(STATUS_ACCESS_VIOLATION);\n    pub const IN_PAGE_ERROR:            Error = Error(STATUS_IN_PAGE_ERROR);\n    pub const INVALID_HANDLE:           Error = Error(STATUS_INVALID_HANDLE);\n    pub const INVALID_PARAMETER:        Error = Error(STATUS_INVALID_PARAMETER);\n    pub const END_OF_FILE:              Error = Error(STATUS_END_OF_FILE);\n    pub const NO_MEMORY:                Error = Error(STATUS_NO_MEMORY);\n    pub const ILLEGAL_INSTRUCTION:      Error = Error(STATUS_ILLEGAL_INSTRUCTION);\n    pub const NONCONTINUABLE_EXCEPTION: Error = Error(STATUS_NONCONTINUABLE_EXCEPTION);\n    pub const INVALID_DISPOSITION:      Error = Error(STATUS_INVALID_DISPOSITION);\n    pub const ARRAY_BOUNDS_EXCEEDED:    Error = Error(STATUS_ARRAY_BOUNDS_EXCEEDED);\n    pub const FLOAT_DENORMAL_OPERAND:   Error = Error(STATUS_FLOAT_DENORMAL_OPERAND);\n    pub const FLOAT_DIVIDE_BY_ZERO:     Error = Error(STATUS_FLOAT_DIVIDE_BY_ZERO);\n    pub const FLOAT_INEXACT_RESULT:     Error = Error(STATUS_FLOAT_INEXACT_RESULT);\n    pub const FLOAT_INVALID_OPERATION:  Error = Error(STATUS_FLOAT_INVALID_OPERATION);\n    pub const FLOAT_OVERFLOW:           Error = Error(STATUS_FLOAT_OVERFLOW);\n    pub const FLOAT_STACK_CHECK:        Error = Error(STATUS_FLOAT_STACK_CHECK);\n    pub const FLOAT_UNDERFLOW:          Error = Error(STATUS_FLOAT_UNDERFLOW);\n    pub const INTEGER_DIVIDE_BY_ZERO:   Error = Error(STATUS_INTEGER_DIVIDE_BY_ZERO);\n    pub const INTEGER_OVERFLOW:         Error = Error(STATUS_INTEGER_OVERFLOW);\n    pub const PRIVILEGED_INSTRUCTION:   Error = Error(STATUS_PRIVILEGED_INSTRUCTION);\n    pub const INSUFFICIENT_RESOURCES:   Error = Error(STATUS_INSUFFICIENT_RESOURCES);\n    pub const INVALID_USER_BUFFER:      Error = Error(STATUS_INVALID_USER_BUFFER);\n    pub const STACK_OVERFLOW:           Error = Error(STATUS_STACK_OVERFLOW);\n\n    pub fn from_ntstatus(status: NTSTATUS) -> Error {\n        Error(status)\n    }\n\n    pub fn to_ntstatus(&self) -> NTSTATUS {\n        self.0\n    }\n}\n\npub trait IntoResult {\n    fn into_result(self) -> Result<(), Error>;\n}\n\nimpl IntoResult for NTSTATUS {\n    fn into_result(self) -> Result<(), Error> {\n        match self {\n            STATUS_SUCCESS => Ok(()),\n            status => Err(Error::from_ntstatus(status)),\n        }\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/intrin.rs",
    "content": "use crate::error::{Error, IntoResult};\nuse windows_kernel_sys::intrin::{read_msr_safe, write_msr_safe};\n\n/// Attempts to read the given model-specific register. Accessing an invalid model-specific\n/// register would normally result in a CPU exception. This function uses Structured Exception\n/// Handling (SEH) to safely catch CPU exceptions and to turn them into an [`Error`]. This prevents\n/// a hang.\npub fn read_msr(register: u32) -> Result<u64, Error> {\n    let mut value = 0;\n\n    unsafe {\n        read_msr_safe(register, &mut value)\n    }.into_result()?;\n\n    Ok(value)\n}\n\n/// Attempts to write the given value to the given model-specific register. Accessing an invalid\n/// model-specific register would normally result in a CPU exception. This function uses Structured\n/// Handling (SEH) to safely catch CPU exceptions and to turn them into an [`Error`]. This prevents\n/// a hang.\npub fn write_msr(register: u32, value: u64) -> Result<(), Error> {\n    unsafe {\n        write_msr_safe(register, value)\n    }.into_result()?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/io.rs",
    "content": "use windows_kernel_sys::base::ANSI_STRING;\nuse windows_kernel_sys::ntoskrnl::DbgPrint;\n\n#[macro_export]\nmacro_rules! print {\n    ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));\n}\n\n#[macro_export]\nmacro_rules! println {\n    () => ($crate::print!(\"\\n\"));\n    ($($arg:tt)*) => ($crate::print!(\"{}\\n\", format_args!($($arg)*)));\n}\n\n#[doc(hidden)]\npub fn _print(args: core::fmt::Arguments) {\n    // Format the string using the `alloc::format!` as this is guaranteed to return a `String`\n    // instead of a `Result` that we would have to `unwrap`. This ensures that this code stays\n    // panic-free.\n    let s = alloc::format!(\"{}\", args);\n\n    // Print the string. We must make sure to not pass this user-supplied string as the format\n    // string, as `DbgPrint` may then format any format specifiers it contains. This could\n    // potentially be an attack vector.\n    let s = ANSI_STRING {\n        Length: s.len() as u16,\n        MaximumLength: s.len() as u16,\n        Buffer: s.as_ptr() as _,\n    };\n\n    unsafe { DbgPrint(\"%Z\\0\".as_ptr() as _, &s) };\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/ioctl.rs",
    "content": "use crate::device::DeviceType;\nuse bitflags::bitflags;\nuse windows_kernel_sys::base::{\n    FILE_ANY_ACCESS, FILE_READ_DATA, FILE_WRITE_DATA, METHOD_BUFFERED, METHOD_IN_DIRECT,\n    METHOD_NEITHER, METHOD_OUT_DIRECT,\n};\n\nbitflags! {\n    #[derive(Clone, Copy, Debug, PartialEq, Eq)]\n    pub struct RequiredAccess: u32 {\n        const ANY_ACCESS = FILE_ANY_ACCESS;\n        const READ_DATA = FILE_READ_DATA;\n        const WRITE_DATA = FILE_WRITE_DATA;\n        const READ_WRITE_DATA = FILE_READ_DATA | FILE_WRITE_DATA;\n    }\n}\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n#[repr(u32)]\npub enum TransferMethod {\n    Neither = METHOD_NEITHER,\n    InputDirect = METHOD_IN_DIRECT,\n    OutputDirect = METHOD_OUT_DIRECT,\n    Buffered = METHOD_BUFFERED,\n}\n\nimpl From<u32> for TransferMethod {\n    fn from(value: u32) -> Self {\n        match value & 0x3 {\n            METHOD_NEITHER => Self::Neither,\n            METHOD_IN_DIRECT => Self::InputDirect,\n            METHOD_OUT_DIRECT => Self::OutputDirect,\n            METHOD_BUFFERED => Self::Buffered,\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl Into<u32> for TransferMethod {\n    fn into(self) -> u32 {\n        match self {\n            Self::Neither => METHOD_NEITHER,\n            Self::InputDirect => METHOD_IN_DIRECT,\n            Self::OutputDirect => METHOD_OUT_DIRECT,\n            Self::Buffered => METHOD_BUFFERED,\n        }\n    }\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct ControlCode(\n    pub DeviceType,\n    pub RequiredAccess,\n    pub u32,\n    pub TransferMethod,\n);\n\nimpl ControlCode {\n    const METHOD_BITS: usize = 2;\n    const NUM_BITS: usize = 12;\n    const ACCESS_BITS: usize = 2;\n    const TYPE_BITS: usize = 16;\n\n    const METHOD_SHIFT: usize = 0;\n    const NUM_SHIFT: usize = Self::METHOD_SHIFT + Self::METHOD_BITS;\n    const ACCESS_SHIFT: usize = Self::NUM_SHIFT + Self::NUM_BITS;\n    const TYPE_SHIFT: usize = Self::ACCESS_SHIFT + Self::ACCESS_BITS;\n\n    const METHOD_MASK: u32 = (1 << Self::METHOD_BITS) - 1;\n    const NUM_MASK: u32 = (1 << Self::NUM_BITS) - 1;\n    const ACCESS_MASK: u32 = (1 << Self::ACCESS_BITS) - 1;\n    const TYPE_MASK: u32 = (1 << Self::TYPE_BITS) - 1;\n\n    pub fn device_type(&self) -> DeviceType {\n        self.0\n    }\n\n    pub fn required_access(&self) -> RequiredAccess {\n        self.1\n    }\n\n    pub fn number(&self) -> u32 {\n        self.2\n    }\n\n    pub fn transfer_method(&self) -> TransferMethod {\n        self.3\n    }\n}\n\nimpl From<u32> for ControlCode {\n    fn from(value: u32) -> Self {\n        let method = (value >> Self::METHOD_SHIFT) & Self::METHOD_MASK;\n        let num = (value >> Self::NUM_SHIFT) & Self::NUM_MASK;\n        let access = (value >> Self::ACCESS_SHIFT) & Self::ACCESS_MASK;\n        let ty = (value >> Self::TYPE_SHIFT) & Self::TYPE_MASK;\n\n        Self(\n            ty.into(),\n            RequiredAccess::from_bits(access).unwrap_or(RequiredAccess::READ_DATA),\n            num,\n            method.into(),\n        )\n    }\n}\n\nimpl Into<u32> for ControlCode {\n    fn into(self) -> u32 {\n        let method = Into::<u32>::into(self.3) << Self::METHOD_SHIFT;\n        let num = self.2 << Self::NUM_SHIFT;\n        let access = self.1.bits() << Self::ACCESS_SHIFT;\n        let ty = Into::<u32>::into(self.0) << Self::TYPE_SHIFT;\n\n        ty | access | num | method\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/lib.rs",
    "content": "#![no_std]\n\n#![feature(alloc_error_handler)]\n\nextern crate alloc;\n\npub mod affinity;\npub mod allocator;\npub mod device;\npub mod driver;\npub mod error;\npub mod intrin;\npub mod io;\npub mod ioctl;\npub mod mdl;\npub mod memory;\npub mod process;\npub mod request;\npub mod section;\npub mod string;\npub mod symbolic_link;\npub mod sync;\npub mod user_ptr;\npub mod version;\n\npub use crate::affinity::{get_cpu_count, get_current_cpu_num, run_on_cpu, run_on_each_cpu};\npub use crate::device::{Access, Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceType, dispatch_device, RequestError};\npub use crate::driver::Driver;\npub use crate::error::Error;\npub use crate::ioctl::{ControlCode, RequiredAccess, TransferMethod};\npub use crate::request::{IoRequest, IoControlRequest, ReadRequest, WriteRequest};\npub use crate::symbolic_link::SymbolicLink;\npub use crate::user_ptr::UserPtr;\n\npub use widestring::U16CString;\npub use windows_kernel_sys::base::{DRIVER_OBJECT, IRP_MJ_MAXIMUM_FUNCTION, NTSTATUS, STATUS_SUCCESS, UNICODE_STRING};\n\n#[cfg(feature = \"alloc\")]\n#[global_allocator]\nstatic ALLOCATOR: allocator::KernelAllocator = allocator::KernelAllocator::new(\n        u32::from_ne_bytes(*b\"rust\")\n    );\n\n#[panic_handler]\nfn panic(_info: &core::panic::PanicInfo) -> ! {\n    loop {}\n}\n\n#[used]\n#[no_mangle]\npub static _fltused: i32 = 0;\n\n#[no_mangle]\npub extern \"system\" fn __CxxFrameHandler3() -> i32 {\n    0\n}\n\n#[macro_export]\nmacro_rules! kernel_module {\n    ($module:ty) => {\n        static mut __MOD: Option<$module> = None;\n\n        #[no_mangle]\n        pub extern \"system\" fn driver_entry(\n            driver: &mut $crate::DRIVER_OBJECT,\n            registry_path: &$crate::UNICODE_STRING,\n        ) -> $crate::NTSTATUS {\n            unsafe {\n                driver.DriverUnload = Some(driver_exit);\n\n                for i in 0..$crate::IRP_MJ_MAXIMUM_FUNCTION {\n                    driver.MajorFunction[i as usize] = Some($crate::dispatch_device);\n                }\n            }\n\n            let driver = unsafe {\n                Driver::from_raw(driver)\n            };\n\n            let registry_path = unsafe {\n                $crate::U16CString::from_ptr_str(registry_path.Buffer)\n            };\n            let registry_path = registry_path.to_string_lossy();\n\n            match <$module as $crate::KernelModule>::init(driver, registry_path.as_str()) {\n                Ok(m) => {\n                    unsafe {\n                        __MOD = Some(m);\n                    }\n\n                    $crate::STATUS_SUCCESS\n                }\n                Err(e) => {\n                    e.to_ntstatus()\n                }\n            }\n        }\n\n        pub unsafe extern \"C\" fn driver_exit(\n            driver: *mut $crate::DRIVER_OBJECT,\n        ) {\n            let driver = unsafe {\n                Driver::from_raw(driver)\n            };\n\n            match __MOD.take() {\n                Some(mut m) => m.cleanup(driver),\n                _ => (),\n            }\n        }\n    };\n}\n\npub trait KernelModule: Sized + Sync {\n    fn init(driver: Driver, registry_path: &str) -> Result<Self, Error>;\n    fn cleanup(&mut self, _driver: Driver) {\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/mdl.rs",
    "content": "use crate::error::Error;\nuse crate::memory::MemoryCaching;\n\n#[repr(i32)]\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum AccessMode {\n    KernelMode = windows_kernel_sys::base::_MODE::KernelMode,\n    UserMode   = windows_kernel_sys::base::_MODE::UserMode,\n}\n\npub struct MemoryDescriptorList {\n    raw: *mut windows_kernel_sys::base::MDL,\n}\n\nunsafe impl Send for MemoryDescriptorList {}\nunsafe impl Sync for MemoryDescriptorList {}\n\nimpl MemoryDescriptorList {\n    pub fn new(\n        addr: *mut core::ffi::c_void,\n        size: usize,\n    ) -> Result<Self, Error> {\n        use windows_kernel_sys::ntoskrnl::IoAllocateMdl;\n\n        let raw = unsafe {\n            IoAllocateMdl(addr, size as _, false as _, false as _, core::ptr::null_mut())\n        };\n\n        if raw.is_null() {\n            return Err(Error::INSUFFICIENT_RESOURCES);\n        }\n\n        Ok(Self {\n            raw,\n        })\n    }\n\n    pub fn build_for_non_paged_pool(\n        &mut self,\n    ) {\n        use windows_kernel_sys::ntoskrnl::MmBuildMdlForNonPagedPool;\n\n        unsafe {\n            MmBuildMdlForNonPagedPool(self.raw);\n        }\n    }\n\n    pub fn map_locked_pages(\n        self,\n        access: AccessMode,\n        caching: MemoryCaching,\n        desired_addr: Option<*mut core::ffi::c_void>,\n    ) -> Result<LockedMapping, Error> {\n        use windows_kernel_sys::ntoskrnl::MmMapLockedPagesSpecifyCache;\n\n        let ptr = unsafe {\n            MmMapLockedPagesSpecifyCache(\n                self.raw,\n                access as _,\n                caching as _,\n                desired_addr.unwrap_or(core::ptr::null_mut()),\n                false as _,\n                0,\n            )\n        };\n\n        Ok(LockedMapping {\n            raw: self.raw,\n            ptr,\n        })\n    }\n}\n\nimpl Drop for MemoryDescriptorList {\n    fn drop(&mut self) {\n        use windows_kernel_sys::ntoskrnl::IoFreeMdl;\n\n        unsafe {\n            IoFreeMdl(self.raw);\n        }\n    }\n}\n\npub struct LockedMapping {\n    raw: *mut windows_kernel_sys::base::MDL,\n    ptr: *mut core::ffi::c_void,\n}\n\nunsafe impl Send for LockedMapping {}\nunsafe impl Sync for LockedMapping {}\n\nimpl LockedMapping {\n    pub fn ptr(&self) -> *mut core::ffi::c_void {\n        self.ptr\n    }\n\n    pub fn unlock(self) -> MemoryDescriptorList {\n        use windows_kernel_sys::ntoskrnl::MmUnmapLockedPages;\n\n        unsafe {\n            MmUnmapLockedPages(self.ptr, self.raw);\n        }\n\n        MemoryDescriptorList {\n            raw: self.raw,\n        }\n    }\n}\n\nimpl Drop for LockedMapping {\n    fn drop(&mut self) {\n        use windows_kernel_sys::ntoskrnl::{IoFreeMdl, MmUnmapLockedPages};\n\n        unsafe {\n            MmUnmapLockedPages(self.ptr, self.raw);\n            IoFreeMdl(self.raw);\n        }\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/memory.rs",
    "content": "use crate::error::{Error, IntoResult};\nuse windows_kernel_sys::base::{MM_COPY_ADDRESS, MM_COPY_MEMORY_PHYSICAL, MM_COPY_MEMORY_VIRTUAL, PHYSICAL_ADDRESS};\nuse windows_kernel_sys::base::_MEMORY_CACHING_TYPE as MEMORY_CACHING_TYPE;\n\n#[repr(i32)]\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum MemoryCaching {\n    NonCached              = MEMORY_CACHING_TYPE::MmNonCached,\n    Cached                 = MEMORY_CACHING_TYPE::MmCached,\n    WriteCombined          = MEMORY_CACHING_TYPE::MmWriteCombined,\n    #[cfg(feature = \"system\")]\n    HardwareCoherentCached = MEMORY_CACHING_TYPE::MmHardwareCoherentCached,\n    #[cfg(feature = \"system\")]\n    NonCachedUnordered     = MEMORY_CACHING_TYPE::MmNonCachedUnordered,\n    #[cfg(feature = \"system\")]\n    USWCCached             = MEMORY_CACHING_TYPE::MmUSWCCached,\n    NotMapped              = MEMORY_CACHING_TYPE::MmNotMapped,\n}\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]\npub struct PhysicalAddress(u64);\n\nimpl From<u64> for PhysicalAddress {\n    fn from(value: u64) -> Self {\n        Self(value)\n    }\n}\n\nimpl Into<u64> for PhysicalAddress {\n    fn into(self) -> u64 {\n        self.0\n    }\n}\n\nimpl From<PHYSICAL_ADDRESS> for PhysicalAddress {\n    fn from(value: PHYSICAL_ADDRESS) -> Self {\n        Self(unsafe { value.QuadPart } as _)\n    }\n}\n\nimpl Into<PHYSICAL_ADDRESS> for PhysicalAddress {\n    fn into(self) -> PHYSICAL_ADDRESS {\n        let mut addr: PHYSICAL_ADDRESS = unsafe { core::mem::zeroed() };\n\n        addr.QuadPart = self.0 as _;\n\n        addr\n    }\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub enum CopyAddress {\n    Virtual(*mut core::ffi::c_void),\n    Physical(PhysicalAddress),\n}\n\nunsafe impl Send for CopyAddress {}\nunsafe impl Sync for CopyAddress {}\n\nimpl Into<(u32, MM_COPY_ADDRESS)> for CopyAddress {\n    fn into(self) -> (u32, MM_COPY_ADDRESS) {\n        let mut copy_addr: MM_COPY_ADDRESS = unsafe {\n            core::mem::zeroed()\n        };\n\n        let flags = match self {\n            CopyAddress::Virtual(addr) => {\n                copy_addr.__bindgen_anon_1.VirtualAddress = addr as _;\n                MM_COPY_MEMORY_VIRTUAL\n            }\n            CopyAddress::Physical(addr) => {\n                copy_addr.__bindgen_anon_1.PhysicalAddress = addr.into();\n                MM_COPY_MEMORY_PHYSICAL\n            }\n        };\n\n        (flags, copy_addr)\n    }\n}\n\npub struct IoMapping {\n    ptr: *mut core::ffi::c_void,\n    size: usize,\n}\n\nunsafe impl Send for IoMapping {}\nunsafe impl Sync for IoMapping {}\n\nimpl IoMapping {\n    pub fn new(addr: PhysicalAddress, size: usize, caching: MemoryCaching) -> Result<Self, Error> {\n        use windows_kernel_sys::ntoskrnl::MmMapIoSpace;\n\n        let ptr = unsafe {\n            MmMapIoSpace(addr.into(), size as _, caching as _)\n        };\n\n        if ptr.is_null() {\n            return Err(Error::INVALID_PARAMETER);\n        }\n\n        Ok(Self {\n            ptr,\n            size,\n        })\n    }\n\n    pub fn ptr(&self) -> *mut core::ffi::c_void {\n        self.ptr\n    }\n\n    pub fn size(&self) -> usize {\n        self.size\n    }\n}\n\nimpl Drop for IoMapping {\n    fn drop(&mut self) {\n        use windows_kernel_sys::ntoskrnl::MmUnmapIoSpace;\n\n        unsafe {\n            MmUnmapIoSpace(self.ptr, self.size as _);\n        }\n    }\n}\n\n#[cfg(feature = \"system\")]\npub fn get_virtual_for_physical(addr: PhysicalAddress) -> *mut core::ffi::c_void {\n    use windows_kernel_sys::ntoskrnl::MmGetVirtualForPhysical;\n\n    let virt_addr = unsafe { MmGetVirtualForPhysical(addr.into()) };\n\n    virt_addr as _\n}\n\npub fn read_memory(\n    buffer: &mut [u8],\n    source: CopyAddress,\n) -> Result<usize, Error> {\n    use windows_kernel_sys::ntoskrnl::MmCopyMemory;\n\n    let (flags, copy_addr) = source.into();\n    let mut bytes = 0;\n\n    unsafe {\n        MmCopyMemory(\n            buffer.as_mut_ptr() as _,\n            copy_addr,\n            buffer.len() as _,\n            flags,\n            &mut bytes,\n        )\n    }.into_result()?;\n\n    Ok(bytes as _)\n}\n\n#[cfg(feature = \"system\")]\npub fn write_memory(\n    target: CopyAddress,\n    buffer: &[u8],\n) -> Result<usize, Error> {\n    use windows_kernel_sys::ntoskrnl::MmCopyMemory;\n\n    let mut copy_addr: MM_COPY_ADDRESS = unsafe { core::mem::zeroed() };\n    let mut bytes = 0;\n\n    let target = match target {\n        CopyAddress::Virtual(addr) => addr,\n        CopyAddress::Physical(addr) => get_virtual_for_physical(addr),\n    };\n\n    copy_addr.__bindgen_anon_1.VirtualAddress = buffer.as_ptr() as _;\n\n    unsafe {\n        MmCopyMemory(\n            target as _,\n            copy_addr,\n            buffer.len() as _,\n            MM_COPY_MEMORY_VIRTUAL,\n            &mut bytes,\n        )\n    }.into_result()?;\n\n    Ok(bytes as _)\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/process.rs",
    "content": "use bitflags::bitflags;\nuse crate::error::{Error, IntoResult};\nuse windows_kernel_sys::base::{CLIENT_ID, HANDLE, KAPC_STATE, OBJECT_ATTRIBUTES, PEPROCESS};\nuse windows_kernel_sys::ntoskrnl::{KeStackAttachProcess, KeUnstackDetachProcess};\nuse windows_kernel_sys::ntoskrnl::{ObDereferenceObject, ObReferenceObject};\nuse windows_kernel_sys::ntoskrnl::{PsGetCurrentProcess, PsLookupProcessByProcessId};\nuse windows_kernel_sys::ntoskrnl::{ZwClose, ZwOpenProcess};\n\npub type ProcessId = usize;\n\n#[derive(Clone, Debug)]\npub struct Process {\n    pub process: PEPROCESS,\n}\n\nimpl Process {\n    pub fn as_ptr(&self) -> PEPROCESS {\n        self.process\n    }\n\n    pub fn current() -> Self {\n        let process = unsafe {\n            PsGetCurrentProcess()\n        };\n\n        unsafe {\n            ObReferenceObject(process as _);\n        }\n\n        Self {\n            process,\n        }\n    }\n\n    pub fn by_id(process_id: ProcessId) -> Result<Self, Error> {\n        let mut process = core::ptr::null_mut();\n\n        unsafe {\n            PsLookupProcessByProcessId(process_id as _, &mut process)\n        }.into_result()?;\n\n        Ok(Self {\n            process,\n        })\n    }\n\n    pub fn id(&self) -> ProcessId {\n        let handle = unsafe {\n            windows_kernel_sys::ntoskrnl::PsGetProcessId(self.process)\n        };\n\n        handle as _\n    }\n\n    pub fn attach(&self) -> ProcessAttachment {\n        unsafe {\n            ProcessAttachment::attach(self.process)\n        }\n    }\n}\n\nimpl Drop for Process {\n    fn drop(&mut self) {\n        unsafe {\n            ObDereferenceObject(self.process as _);\n        }\n    }\n}\n\npub struct ProcessAttachment {\n    process: PEPROCESS,\n    state: KAPC_STATE,\n}\n\nimpl ProcessAttachment {\n    pub unsafe fn attach(process: PEPROCESS) -> Self {\n        let mut state: KAPC_STATE = core::mem::zeroed();\n    \n        ObReferenceObject(process as _);\n        KeStackAttachProcess(process, &mut state);\n\n        Self {\n            process,\n            state,\n        }\n    }\n}\n\nimpl Drop for ProcessAttachment {\n    fn drop(&mut self) {\n        unsafe {\n            KeUnstackDetachProcess(&mut self.state);\n            ObDereferenceObject(self.process as _);\n        }\n    }\n}\n\nbitflags! {\n    pub struct ProcessAccess: u32 {\n        const ALL_ACCESS = windows_kernel_sys::base::PROCESS_ALL_ACCESS;\n    }\n}\n\npub struct ZwProcess {\n    pub(crate) handle: HANDLE,\n}\n\nimpl ZwProcess {\n    pub fn open(id: ProcessId, access: ProcessAccess) -> Result<Self, Error> {\n        let mut attrs: OBJECT_ATTRIBUTES = unsafe { core::mem::zeroed() };\n        attrs.Length = core::mem::size_of::<OBJECT_ATTRIBUTES>() as u32;\n\n        let mut client_id = CLIENT_ID {\n            UniqueProcess: id as _,\n            UniqueThread: core::ptr::null_mut(),\n        };\n\n        let mut handle = core::ptr::null_mut();\n\n        unsafe {\n            ZwOpenProcess(&mut handle, access.bits(), &mut attrs, &mut client_id)\n        }.into_result()?;\n\n        Ok(Self {\n            handle,\n        })\n    }\n}\n\nimpl Drop for ZwProcess {\n    fn drop(&mut self) {\n        unsafe {\n            ZwClose(self.handle);\n        }\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/request.rs",
    "content": "use bitflags::bitflags;\nuse core::ops::Deref;\nuse crate::error::Error;\nuse crate::ioctl::{ControlCode, RequiredAccess, TransferMethod};\nuse crate::user_ptr::UserPtr;\nuse windows_kernel_sys::base::{IO_NO_INCREMENT, IO_STACK_LOCATION, IRP, STATUS_SUCCESS};\nuse windows_kernel_sys::base::_MM_PAGE_PRIORITY as MM_PAGE_PRIORITY;\nuse windows_kernel_sys::ntoskrnl::{IoCompleteRequest, IoGetCurrentIrpStackLocation};\nuse windows_kernel_sys::ntoskrnl::{MmGetMdlByteCount, MmGetMdlByteOffset, MmGetSystemAddressForMdlSafe};\n\nbitflags! {\n    pub struct IrpFlags: u32 {\n        const NOCACHE = windows_kernel_sys::base::IRP_NOCACHE;\n        const PAGING_IO = windows_kernel_sys::base::IRP_PAGING_IO;\n        const MOUNT_COMPLETION =  windows_kernel_sys::base::IRP_MOUNT_COMPLETION;\n        const SYNCHRONOUS_API = windows_kernel_sys::base::IRP_SYNCHRONOUS_API;\n        const ASSOCIATED_IRP = windows_kernel_sys::base::IRP_ASSOCIATED_IRP;\n        const BUFFERED_IO = windows_kernel_sys::base::IRP_BUFFERED_IO;\n        const DEALLOCATE_BUFFER = windows_kernel_sys::base::IRP_DEALLOCATE_BUFFER;\n        const INPUT_OPERATION = windows_kernel_sys::base::IRP_INPUT_OPERATION;\n        const SYNCHRONOUS_PAGING_IO = windows_kernel_sys::base::IRP_SYNCHRONOUS_PAGING_IO;\n        const CREATE_OPERATION = windows_kernel_sys::base::IRP_CREATE_OPERATION;\n        const READ_OPERATION = windows_kernel_sys::base::IRP_READ_OPERATION;\n        const WRITE_OPERATION = windows_kernel_sys::base::IRP_WRITE_OPERATION;\n        const CLOSE_OPERATION = windows_kernel_sys::base::IRP_CLOSE_OPERATION;\n        const DEFER_IO_COMPLETION = windows_kernel_sys::base::IRP_DEFER_IO_COMPLETION;\n        const OB_QUERY_NAME = windows_kernel_sys::base::IRP_OB_QUERY_NAME;\n        const HOLD_DEVICE_QUEUE = windows_kernel_sys::base::IRP_HOLD_DEVICE_QUEUE;\n        const UM_DRIVER_INITIATED_IO = windows_kernel_sys::base::IRP_UM_DRIVER_INITIATED_IO;\n    }\n}\n\npub struct IoRequest {\n    irp: *mut IRP,    \n}\n\nimpl IoRequest {\n    pub unsafe fn from_raw(irp: *mut IRP) -> Self {\n        Self { irp }\n    }\n\n    pub fn irp(&self) -> &IRP {\n        unsafe { &*self.irp }\n    }\n\n    pub fn irp_mut(&self) -> &mut IRP {\n        unsafe { &mut *self.irp }\n    }\n\n    pub fn flags(&self) -> IrpFlags {\n        IrpFlags::from_bits(self.irp().Flags)\n            .unwrap_or(IrpFlags::empty())\n    }\n\n    pub fn stack_location(&self) -> &IO_STACK_LOCATION {\n        unsafe { &*IoGetCurrentIrpStackLocation(self.irp_mut()) }\n    }\n\n    pub fn major(&self) -> u8 {\n        self.stack_location().MajorFunction\n    }\n\n    pub(crate) fn complete(&self, value: Result<u32, Error>) {\n        let irp = self.irp_mut();\n        \n        match value {\n            Ok(value) => {\n                irp.IoStatus.Information = value as _;\n                irp.IoStatus.__bindgen_anon_1.Status = STATUS_SUCCESS;\n            }\n            Err(error) => {\n                irp.IoStatus.Information = 0;\n                irp.IoStatus.__bindgen_anon_1.Status = error.to_ntstatus();\n            }\n        }\n\n        unsafe {\n            IoCompleteRequest(irp, IO_NO_INCREMENT as _);\n        }\n    }\n}\n\npub struct ReadRequest {\n    pub(crate) inner: IoRequest,\n}\n\nimpl Deref for ReadRequest {\n    type Target = IoRequest;\n\n    fn deref(&self) -> &Self::Target {\n        &self.inner\n    }\n}\n\nimpl ReadRequest {\n    pub fn user_ptr(&self) -> UserPtr {\n        let stack_location = self.stack_location();\n        let irp = self.irp();\n\n        let (ptr, size) = if !irp.MdlAddress.is_null() {\n            let ptr = unsafe {\n                MmGetSystemAddressForMdlSafe(irp.MdlAddress, MM_PAGE_PRIORITY::HighPagePriority as _)\n            };\n\n            let size = unsafe { MmGetMdlByteCount(irp.MdlAddress) } as usize;\n\n            (ptr, size)\n        } else if !unsafe { irp.AssociatedIrp.SystemBuffer }.is_null() { \n            let ptr = unsafe { irp.AssociatedIrp.SystemBuffer };\n            let size = unsafe { stack_location.Parameters.Read }.Length as usize;\n\n            (ptr, size)\n        } else {\n            (core::ptr::null_mut(), 0)\n        };\n\n        unsafe { UserPtr::new_buffered(ptr, 0, size) }\n    }\n\n    pub fn offset(&self) -> i64 {\n        let stack_location = self.stack_location();\n        let irp = self.irp();\n\n        if !irp.MdlAddress.is_null() {\n            (unsafe { MmGetMdlByteOffset(irp.MdlAddress) }) as i64\n        } else if !unsafe { irp.AssociatedIrp.SystemBuffer }.is_null() {\n            unsafe { stack_location.Parameters.Read.ByteOffset.QuadPart } \n        } else {\n            0\n        }\n    }\n}\n\nimpl Into<IoRequest> for ReadRequest {\n    fn into(self) -> IoRequest {\n        self.inner\n    }\n}\n\npub struct WriteRequest {\n    pub(crate) inner: IoRequest,\n}\n\nimpl Deref for WriteRequest {\n    type Target = IoRequest;\n\n    fn deref(&self) -> &Self::Target {\n        &self.inner\n    }\n}\n\nimpl WriteRequest {\n    pub fn user_ptr(&self) -> UserPtr {\n        let stack_location = self.stack_location();\n        let irp = self.irp();\n\n        let (ptr, size) = if !irp.MdlAddress.is_null() {\n            let ptr = unsafe {\n                MmGetSystemAddressForMdlSafe(irp.MdlAddress, MM_PAGE_PRIORITY::HighPagePriority as _)\n            };\n\n            let size = unsafe { MmGetMdlByteCount(irp.MdlAddress) } as usize;\n\n            (ptr, size)\n        } else if !unsafe {irp.AssociatedIrp.SystemBuffer }.is_null() {             \n            let ptr = unsafe { irp.AssociatedIrp.SystemBuffer };\n            let size = unsafe { stack_location.Parameters.Write }.Length as usize;\n\n            (ptr, size)\n        } else {\n            (core::ptr::null_mut(), 0)\n        };\n\n        unsafe { UserPtr::new_buffered(ptr, size, 0) }\n    }\n\n    pub fn offset(&self) -> i64 {\n        let stack_location = self.stack_location();\n        let irp = self.irp();\n\n        if !irp.MdlAddress.is_null() {\n            (unsafe { MmGetMdlByteOffset(irp.MdlAddress) }) as i64\n        } else if !unsafe { irp.AssociatedIrp.SystemBuffer }.is_null() {\n            unsafe { stack_location.Parameters.Write.ByteOffset.QuadPart }\n        } else {\n            0\n        }\n    }\n}\n\nimpl Into<IoRequest> for WriteRequest {\n    fn into(self) -> IoRequest {\n        self.inner\n    }\n}\n\npub struct IoControlRequest {\n    pub(crate) inner: IoRequest,\n}\n\nimpl Deref for IoControlRequest {\n    type Target = IoRequest;\n\n    fn deref(&self) -> &Self::Target {\n        &self.inner\n    }\n}\n\nimpl IoControlRequest {\n    pub fn control_code(&self) -> ControlCode {\n        let stack_location = self.stack_location();\n\n        unsafe {\n            stack_location.Parameters.DeviceIoControl.IoControlCode.into()\n        }\n    }\n\n    pub fn function(&self) -> (RequiredAccess, u32) {\n        let code = self.control_code();\n\n        (code.required_access(), code.number())\n    }\n\n    pub fn user_ptr(&self) -> UserPtr {\n        let stack_location = self.stack_location();\n        let irp = self.irp();\n\n        let system_buffer = unsafe { irp.AssociatedIrp.SystemBuffer };\n\n        let mdl_address = if !irp.MdlAddress.is_null() {\n            unsafe { MmGetSystemAddressForMdlSafe(irp.MdlAddress, MM_PAGE_PRIORITY::HighPagePriority as _) }\n        } else {\n            core::ptr::null_mut()\n        };\n\n        let input_size = unsafe {\n            stack_location.Parameters.DeviceIoControl.InputBufferLength\n        } as usize;\n        let output_size = unsafe {\n            stack_location.Parameters.DeviceIoControl.OutputBufferLength\n        } as usize;\n\n        match self.control_code().transfer_method() {\n            TransferMethod::Buffered =>\n                unsafe { UserPtr::new_buffered(system_buffer, input_size, output_size) },\n            TransferMethod::InputDirect =>\n                unsafe { UserPtr::new_direct(mdl_address, system_buffer, output_size, input_size) },\n            TransferMethod::OutputDirect =>\n                unsafe { UserPtr::new_direct(system_buffer, mdl_address, input_size, output_size) },\n            TransferMethod::Neither =>\n                unsafe { UserPtr::new_neither() },\n        }\n    }\n}\n\nimpl Into<IoRequest> for IoControlRequest {\n    fn into(self) -> IoRequest {\n        self.inner\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/section.rs",
    "content": "use bitflags::bitflags;\nuse crate::error::{Error, IntoResult};\nuse crate::process::ZwProcess;\nuse crate::string::create_unicode_string;\nuse widestring::U16CString;\nuse windows_kernel_sys::base::{HANDLE, LARGE_INTEGER, OBJECT_ATTRIBUTES};\nuse windows_kernel_sys::ntoskrnl::{ZwClose, ZwMapViewOfSection, ZwOpenSection, ZwUnmapViewOfSection};\n\nbitflags! {\n    pub struct AllocationFlags: u32 {\n        const RESERVE     = windows_kernel_sys::base::MEM_RESERVE;\n        const LARGE_PAGES = windows_kernel_sys::base::MEM_LARGE_PAGES;\n        const TOP_DOWN    = windows_kernel_sys::base::MEM_TOP_DOWN;\n    }\n}\n\nbitflags! {\n    pub struct ProtectFlags: u32 {\n        const READ_WRITE = windows_kernel_sys::base::PAGE_READWRITE;\n    }\n}\n\nbitflags! {\n    pub struct SectionAccess: u32 {\n        const EXTEND_SIZE = windows_kernel_sys::base::SECTION_EXTEND_SIZE;\n        const MAP_EXECUTE = windows_kernel_sys::base::SECTION_MAP_EXECUTE;\n        const MAP_READ    = windows_kernel_sys::base::SECTION_MAP_READ;\n        const MAP_WRITE   = windows_kernel_sys::base::SECTION_MAP_WRITE;\n        const QUERY       = windows_kernel_sys::base::SECTION_QUERY;\n        const ALL_ACCESS  = windows_kernel_sys::base::SECTION_ALL_ACCESS;\n    }\n}\n\nbitflags! {\n    pub struct ObjectFlags: u32 {\n        const CASE_INSENSITIVE = windows_kernel_sys::base::OBJ_CASE_INSENSITIVE;\n        const KERNEL_HANDLE    = windows_kernel_sys::base::OBJ_KERNEL_HANDLE;\n    }\n}\n\n#[repr(i32)]\npub enum SectionInherit {\n    ViewShare = windows_kernel_sys::base::_SECTION_INHERIT::ViewShare,\n    ViewUnmap = windows_kernel_sys::base::_SECTION_INHERIT::ViewUnmap,\n}\n\npub enum BaseAddress {\n    Desired(*mut core::ffi::c_void),\n    ZeroBits(usize),\n}\n\npub struct Section {\n    handle: HANDLE,\n}\n\nunsafe impl Send for Section {}\nunsafe impl Sync for Section {}\n\nimpl Section {\n    pub fn open(path: &str, obj_flags: ObjectFlags, access: SectionAccess) -> Result<Self, Error> {\n        let name = U16CString::from_str(path).unwrap();\n        let mut name = create_unicode_string(name.as_slice());\n\n        let mut attrs = OBJECT_ATTRIBUTES {\n            Length: core::mem::size_of::<OBJECT_ATTRIBUTES>() as u32,\n            RootDirectory: core::ptr::null_mut(),\n            ObjectName: &mut name,\n            Attributes: obj_flags.bits(),\n            SecurityDescriptor: core::ptr::null_mut(),\n            SecurityQualityOfService: core::ptr::null_mut(),\n        };\n\n        let mut handle: HANDLE = core::ptr::null_mut();\n\n        unsafe {\n            ZwOpenSection(&mut handle, access.bits(), &mut attrs)\n        }.into_result()?;\n\n        Ok(Self {\n            handle\n        })\n    }\n\n    pub fn map_view(\n        &mut self,\n        process: ZwProcess,\n        base_address: BaseAddress,\n        commit_size: usize,\n        offset: Option<u64>,\n        view_size: usize,\n        inherit: SectionInherit,\n        allocation: AllocationFlags,\n        protection: ProtectFlags,\n    ) -> Result<SectionView, Error> {\n        let (mut base_address, zero_bits) = match base_address {\n            BaseAddress::Desired(ptr) => (ptr, 0),\n            BaseAddress::ZeroBits(bits) => (core::ptr::null_mut(), bits),\n        };\n\n        let mut offset = offset.map(|value| {\n            let mut offset: LARGE_INTEGER = unsafe { core::mem::zeroed() };\n            offset.QuadPart = value as _;\n            offset\n        });\n\n        let mut size: u64 = view_size as _;\n\n        unsafe {\n            ZwMapViewOfSection(\n                self.handle,\n                process.handle,\n                &mut base_address,\n                zero_bits as _,\n                commit_size as _,\n                match offset {\n                    Some(ref mut offset) => offset as _,\n                    _ => core::ptr::null_mut(),\n                },\n                &mut size,\n                inherit as _,\n                allocation.bits(),\n                protection.bits(),\n            )\n        }.into_result()?;\n\n        Ok(SectionView {\n            process,\n            address: base_address,\n        })\n    }\n}\n\nimpl Drop for Section {\n    fn drop(&mut self) {\n        unsafe {\n            ZwClose(self.handle);\n        }\n    }\n}\n\npub struct SectionView {\n    process: ZwProcess,\n    address: *mut core::ffi::c_void,\n}\n\nunsafe impl Send for SectionView {}\nunsafe impl Sync for SectionView {}\n\nimpl SectionView {\n    pub fn address(&self) -> *mut core::ffi::c_void {\n        self.address\n    }\n}\n\nimpl Drop for SectionView {\n    fn drop(&mut self) {\n        unsafe {\n            ZwUnmapViewOfSection(\n                self.process.handle,\n                self.address,\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/string.rs",
    "content": "use windows_kernel_sys::base::UNICODE_STRING;\n\npub fn create_unicode_string(s: &[u16]) -> UNICODE_STRING {\n    let len = s.len();\n\n    let n = if len > 0 && s[len - 1] == 0 { len - 1 } else { len };\n\n    UNICODE_STRING {\n        Length: (n * 2) as u16,\n        MaximumLength: (len * 2) as u16,\n        Buffer: s.as_ptr() as _,\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/symbolic_link.rs",
    "content": "use crate::error::{Error, IntoResult};\nuse crate::string::create_unicode_string;\nuse widestring::U16CString;\nuse windows_kernel_sys::ntoskrnl::{IoCreateSymbolicLink, IoDeleteSymbolicLink};\n\npub struct SymbolicLink {\n    name: U16CString,\n}\n\nimpl SymbolicLink {\n    pub fn new(name: &str, target: &str) -> Result<Self, Error> {\n        // Convert the name to UTF-16 and then create a UNICODE_STRING.\n        let name = U16CString::from_str(name).unwrap();\n        let mut name_ptr = create_unicode_string(name.as_slice());\n\n        // Convert the target to UTF-16 and then create a UNICODE_STRING.\n        let target = U16CString::from_str(target).unwrap();\n        let mut target_ptr = create_unicode_string(target.as_slice());\n\n        unsafe {\n            IoCreateSymbolicLink(&mut name_ptr, &mut target_ptr)\n        }.into_result()?;\n\n        Ok(Self {\n            name,\n        })\n    }\n}\n\nimpl Drop for SymbolicLink {\n    fn drop(&mut self) {\n        let mut name_ptr = create_unicode_string(self.name.as_slice());\n\n        unsafe {\n            IoDeleteSymbolicLink(&mut name_ptr);\n        }\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/sync/fast_mutex.rs",
    "content": "use alloc::boxed::Box;\nuse core::cell::UnsafeCell;\nuse core::ops::{Deref, DerefMut};\nuse windows_kernel_sys::base::FAST_MUTEX;\nuse windows_kernel_sys::ntoskrnl::{\n    ExInitializeFastMutex, ExAcquireFastMutex, ExReleaseFastMutex, ExTryToAcquireFastMutex,\n};\n\n/// A mutual exclusion primitive useful for protecting shared data.\n///\n/// This mutex will block threads waiting for the lock to become available. The mutex can also be\n/// statically initialized or created via a [`new`] constructor. Each mutex has a type parameter\n/// which represents the data that it is protecting. The data can only be accessed through the RAII\n/// guards returned from [`lock`] and [`try_lock`], which guarantees that the data is only ever\n/// accessed when the mutex is locked.\n///\n/// [`new`]: FastMutex::new\n/// [`lock`]: FastMutex::lock\n/// [`try_lock`]: FastMutex::try_lock\npub struct FastMutex<T: ?Sized> {\n    pub(crate) lock: Box<FAST_MUTEX>,\n    pub(crate) data: UnsafeCell<T>,\n}\n\nunsafe impl<T> Send for FastMutex<T> {}\nunsafe impl<T> Sync for FastMutex<T> {}\n\nimpl<T> FastMutex<T> {\n    /// Creates a new mutex in an unlocked state ready for use.\n    pub fn new(data: T) -> Self {\n        let mut lock: Box<FAST_MUTEX> = Box::new(unsafe {\n            core::mem::zeroed()\n        });\n\n        unsafe {\n            ExInitializeFastMutex(\n                &mut *lock,\n            )\n        };\n\n        Self {\n            lock,\n            data: UnsafeCell::new(data),\n        }\n    }\n\n    /// Consumes this `FastMutex`, returning the underlying data.\n    #[inline]\n    pub fn into_inner(self) -> T {\n        let Self { data, .. } = self;\n        data.into_inner()\n    }\n\n    /// Attempts to acquire this lock.\n    ///\n    /// If the lock could not be acquired at this time, then `None` is returned. Otherwise, an RAII\n    /// guard is returned. The lock will be unlocked when the guard is dropped.\n    ///\n    /// This function does not block.\n    #[inline]\n    pub fn try_lock(&mut self) -> Option<FastMutexGuard<T>> {\n        let status = unsafe {\n            ExTryToAcquireFastMutex(\n                &mut *self.lock,\n            )\n        } != 0;\n\n        match status {\n            true => Some(FastMutexGuard {\n                lock: &mut self.lock,\n                data: unsafe { &mut *self.data.get() },\n            }),\n            _ => None,\n        }\n    }\n\n    /// Acquires a mutex, blocking the current thread until it is able to do so.\n    ///\n    /// This function will block the local thread until it is available to acquire the mutex. Upon\n    /// returning, the thread is the only thread with the lock held. An RAII guard is returned to\n    /// allow scoped unlock of the lock. When the guard goes out of scope, the mutex will be\n    /// unlocked.\n    ///\n    /// The underlying function does not allow for recursion. If the thread already holds the lock\n    /// and tries to lock the mutex again, this function will return `None` instead.\n    #[inline]\n    pub fn lock(&mut self) -> Option<FastMutexGuard<T>> {\n        unsafe {\n            ExAcquireFastMutex(\n                &mut *self.lock,\n            )\n        };\n\n        Some(FastMutexGuard {\n            lock: &mut self.lock,\n            data: unsafe { &mut *self.data.get() },\n        })\n    }\n}\n\nimpl<T: ?Sized + Default> Default for FastMutex<T> {\n    fn default() -> Self {\n        Self::new(T::default())\n    }\n}\n\nimpl<T> From<T> for FastMutex<T> {\n    fn from(data: T) -> Self {\n        Self::new(data)\n    }\n}\n\n/// An RAII implementation of a \"scoped lock\" of a mutex. When this structure is dropped (falls out\n/// of scope), the lock will be unlocked.\n///\n/// The data protected by the mutex can be accessed through this guard via its [`Deref`] and\n/// [`DerefMut`] implementations.\n///\n/// This structure is created by the [`lock`] and [`try_lock`] methods on [`FastMutex`].\n///\n/// [`lock`]: FastMutex::lock\n/// [`try_lock`]: FastMutex::try_lock\npub struct FastMutexGuard<'a, T: 'a + ?Sized> {\n    pub(crate) lock: &'a mut FAST_MUTEX,\n    pub(crate) data: &'a mut T,\n}\n\nimpl<'a, T: ?Sized> Drop for FastMutexGuard<'a, T> {\n    fn drop(&mut self) {\n        unsafe {\n            ExReleaseFastMutex(\n                &mut *self.lock,\n            )\n        };\n    }\n}\n\nimpl<'a, T: ?Sized> Deref for FastMutexGuard<'a, T> {\n    type Target = T;\n\n    fn deref(&self) -> &T {\n        self.data\n    }\n}\n\nimpl<'a, T: ?Sized> DerefMut for FastMutexGuard<'a, T> {\n    fn deref_mut(&mut self) -> &mut T {\n        self.data\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/sync/mod.rs",
    "content": "pub mod fast_mutex;\npub mod push_lock;\n\npub use self::fast_mutex::FastMutex as Mutex;\npub use self::push_lock::PushLock as RwLock;\n"
  },
  {
    "path": "windows-kernel-rs/src/sync/push_lock.rs",
    "content": "use alloc::boxed::Box;\nuse core::cell::UnsafeCell;\nuse core::ops::{Deref, DerefMut};\nuse windows_kernel_sys::base::EX_PUSH_LOCK;\nuse windows_kernel_sys::ntoskrnl::{\n    ExInitializePushLock,\n    ExAcquirePushLockShared,\n    ExReleasePushLockShared,\n    ExAcquirePushLockExclusive,\n    ExReleasePushLockExclusive,\n    KeEnterCriticalRegion,\n    KeLeaveCriticalRegion,\n};\n\n/// A [`PushLock`] is an efficient implementation of a reader-writer lock that can be stored both\n/// in paged and non-paged memory.\n///\n/// This type of lock allows a number of readers or at most one writer at any point in time. The\n/// write portion of this lock typically allows modifications of the underlying data (exclusive\n/// access) and the read portion of this lock typically allows for read-only access (shared\n/// access).\n///\n/// In comparison, a [`FastMutex`] does not distinguish between readers or writers that acquire the\n/// lock, therefore blocking any threads waiting for the lock to become available. A [`PushLock`]\n/// will allow any number of readers to acquire the lock as long as a writer is not holding the\n/// lock.\n///\n/// The priority policy is such that a thread trying to acquire the [`PushLock`] for exclusive\n/// access will be prioritized over threads trying to acquire the [`PushLock`] for shared access.\n/// More specifically, if a thread cannot lock the [`PushLock`] for exclusive access immediately,\n/// it will wait for the thread(s) that currently holds the lock to release the lock. If another\n/// thread tries to acquire the [`PushLock`] for shared access while a thread is waiting to acquire\n/// the lock for exclusive access, it will yield to the thread(s) trying to acquire the\n/// [`PushLock`] for exclusive access, even in the event that the [`PushLock`] is acquired for\n/// shared access.\n///\n/// [`FastMutex`]: crate::fast_mutex::FastMutex\npub struct PushLock<T: ?Sized> {\n    pub(crate) lock: Box<EX_PUSH_LOCK>,\n    pub(crate) data: UnsafeCell<T>,\n}\n\nunsafe impl<T> Send for PushLock<T> {}\nunsafe impl<T> Sync for PushLock<T> {}\n\nimpl<T> PushLock<T> {\n    /// Creates new instance of [`PushLock<T>`] that is unlocked.\n    pub fn new(data: T) -> Self {\n        let mut lock: Box<EX_PUSH_LOCK> = Box::new(0);\n\n        unsafe {\n            ExInitializePushLock(\n                &mut *lock,\n            )\n        };\n\n        Self {\n            lock,\n            data: UnsafeCell::new(data),\n        }\n    }\n\n    /// Consumes this [`PushLock`], returning the underlying data.\n    #[inline]\n    pub fn into_inner(self) -> T {\n        let Self { data, .. } = self;\n        data.into_inner()\n    }\n\n    /// Locks this [`PushLock`] with shared read access, blocking the current thread until it can\n    /// be acquired.\n    ///\n    /// The calling thread will be blocked until there are no more writers which hold the lock.\n    /// There may be other readers currently inside the lock when this method returns.\n    ///\n    /// This function will yield to threads waiting to acquire the [`PushLock`] for exclusive\n    /// access, even in the event that the [`PushLock`] is currently held by one or more threads\n    /// for shared access.\n    ///\n    /// While the underlying function does allow for recursion, this atomically increments a shared\n    /// reader counter. Since dropping the RAII guard releases the lock by atomically decrementing\n    /// this shared counter, it will eventually reach zero once all RAII guards have been dropped. \n    #[inline]\n    pub fn read(&mut self) -> Option<PushLockReadGuard<T>> {\n        unsafe {\n            KeEnterCriticalRegion()\n        };\n\n        unsafe {\n            ExAcquirePushLockShared(\n                &mut *self.lock,\n            )\n        };\n\n        Some(PushLockReadGuard {\n            lock: &mut self.lock,\n            data: unsafe { &mut *self.data.get() },\n        })\n    }\n\n    /// Locks this [`PushLock`] with exclusive write access, blocking the current thread until it can\n    /// be acquired.\n    ///\n    /// This function will not return while other writers or other readers currently have access to\n    /// the lock.\n    ///\n    /// Returns an RAII guard which will drop the write access of this [`PushLock`] when dropped.\n    ///\n    /// This thread will take priority over any threads that are trying to acquire the lock for\n    /// shared access but that do not currently hold the lock for shared access.\n    ///\n    /// The underlying function does not allow for recursion, which ensures correct behavior. \n    #[inline]\n    pub fn write(&mut self) -> Option<PushLockWriteGuard<T>> {\n        unsafe {\n            KeEnterCriticalRegion()\n        };\n\n        unsafe {\n            ExAcquirePushLockExclusive(\n                &mut *self.lock,\n            )\n        };\n\n        Some(PushLockWriteGuard {\n            lock: &mut self.lock,\n            data: unsafe { &mut *self.data.get() },\n        })\n    }\n}\n\n/// RAII structure used to release the shared read access of a lock when dropped.\n///\n/// This structure is created by the [`read`] and [`try_read`] methods on [`PushLock`]\n///\n/// [`read`]: PushLock::read\n/// [`try_read`]: PushLock::try_read\npub struct PushLockReadGuard<'a, T: 'a + ?Sized> {\n    pub(crate) lock: &'a mut EX_PUSH_LOCK,\n    pub(crate) data: &'a T,\n}\n\nimpl<'a, T: ?Sized> Drop for PushLockReadGuard<'a, T> {\n    fn drop(&mut self) {\n        unsafe {\n            ExReleasePushLockShared(\n                &mut *self.lock,\n            )\n        };\n\n        unsafe {\n            KeLeaveCriticalRegion()\n        };\n    }\n}\n\nimpl<'a, T: ?Sized> Deref for PushLockReadGuard<'a, T> {\n    type Target = T;\n\n    fn deref(&self) -> &T {\n        self.data\n    }\n}\n\n/// RAII structure used to release the exclusive write access of a lock when dropped.\n///\n/// This structure is created by the [`write`] and [`try_write`] methods on [`PushLock`]\n///\n/// [`write`]: PushLock::write\n/// [`try_write`]: PushLock::try_write\npub struct PushLockWriteGuard<'a, T: 'a + ?Sized> {\n    pub(crate) lock: &'a mut EX_PUSH_LOCK,\n    pub(crate) data: &'a mut T,\n}\n\nimpl<'a, T: ?Sized> Drop for PushLockWriteGuard<'a, T> {\n    fn drop(&mut self) {\n        unsafe {\n            ExReleasePushLockExclusive(\n                &mut *self.lock,\n            )\n        };\n\n        unsafe {\n            KeLeaveCriticalRegion()\n        };\n    }\n}\n\nimpl<'a, T: ?Sized> Deref for PushLockWriteGuard<'a, T> {\n    type Target = T;\n\n    fn deref(&self) -> &T {\n        self.data\n    }\n}\n\nimpl<'a, T: ?Sized> DerefMut for PushLockWriteGuard<'a, T> {\n    fn deref_mut(&mut self) -> &mut T {\n        self.data\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/user_ptr.rs",
    "content": "use crate::error::Error;\n\npub enum UserPtr {\n    Buffered {\n        ptr: *mut cty::c_void,\n        read_size: usize,\n        write_size: usize,\n    },\n    Direct {\n        read_ptr: *const cty::c_void,\n        write_ptr: *mut cty::c_void,\n        read_size: usize,\n        write_size: usize,\n    },\n    Neither,\n}\n\nimpl UserPtr {\n    pub unsafe fn new_buffered(\n        ptr: *mut cty::c_void,\n        read_size: usize,\n        write_size: usize,\n    ) -> Self {\n        Self::Buffered{\n            ptr,\n            read_size,\n            write_size,\n        }\n    }\n\n    pub unsafe fn new_direct(\n        read_ptr: *const cty::c_void,\n        write_ptr: *mut cty::c_void,\n        read_size: usize,\n        write_size: usize,\n    ) -> Self {\n        Self::Direct {\n            read_ptr,\n            write_ptr,\n            read_size,\n            write_size,\n        }\n    }\n\n    pub unsafe fn new_neither() -> Self {\n        Self::Neither\n    }\n\n    pub fn read_size(&self) -> usize {\n        match self {\n            Self::Buffered { read_size, .. } => *read_size,\n            Self::Direct { read_size, .. } => *read_size,\n            Self::Neither => 0,\n        }\n    }\n\n    pub fn write_size(&self) -> usize {\n        match self {\n            Self::Buffered { write_size, .. } => *write_size,\n            Self::Direct { write_size, .. } => *write_size,\n            Self::Neither => 0,\n        }\n    }\n\n    pub fn as_slice(&self) -> &[u8] {\n        let (ptr, size) = match self {\n            Self::Buffered { ptr, read_size, .. } => (*ptr as _, *read_size),\n            Self::Direct { read_ptr, read_size, .. } => (*read_ptr, *read_size),\n            Self::Neither => (core::ptr::null(), 0),\n        };\n\n        if ptr.is_null() || size == 0 {\n            &[]\n        } else {\n            unsafe {\n                core::slice::from_raw_parts(ptr as *const u8, size)\n            }\n        }\n    }\n\n    pub fn as_mut_slice(&mut self) -> &mut [u8] {\n        let (ptr, size) = match self {\n            Self::Buffered { ptr, write_size, .. } => (*ptr, *write_size),\n            Self::Direct { write_ptr, write_size, .. } => (*write_ptr, *write_size),\n            Self::Neither => (core::ptr::null_mut(), 0),\n        };\n\n        if ptr.is_null() || size == 0 {\n            &mut []\n        } else {\n            unsafe {\n                core::slice::from_raw_parts_mut(ptr as *mut u8, size)\n            }\n        }\n    }\n\n    pub fn read<T: Copy + Default>(&self) -> Result<T, Error> {\n        let (ptr, size) = match self {\n            Self::Buffered { ptr, read_size, .. } => (*ptr as _, *read_size),\n            Self::Direct { read_ptr, read_size, .. } => (*read_ptr, *read_size),\n            Self::Neither => (core::ptr::null(), 0),\n        };\n\n        if ptr.is_null() || size == 0 {\n            return Err(Error::INVALID_PARAMETER);\n        }\n\n        if core::mem::size_of::<T>() > size {\n            return Err(Error::INVALID_USER_BUFFER);\n        }\n\n        let mut obj = T::default();\n\n        unsafe {\n            core::ptr::copy_nonoverlapping(\n                ptr as _,\n                &mut obj,\n                1,\n            );\n        }\n\n        Ok(obj)\n    }\n\n    pub fn write<T: Copy>(&mut self, obj: &T) -> Result<(), Error> {\n        let (ptr, size) = match self {\n            Self::Buffered { ptr, write_size, .. } => (*ptr, *write_size),\n            Self::Direct { write_ptr, write_size, .. } => (*write_ptr, *write_size),\n            Self::Neither => (core::ptr::null_mut(), 0),\n        };\n\n        if ptr.is_null() || size == 0 {\n            return Err(Error::INVALID_PARAMETER);\n        }\n\n        if core::mem::size_of::<T>() > size {\n            return Err(Error::INVALID_USER_BUFFER);\n        }\n\n        unsafe {\n            core::ptr::copy_nonoverlapping(\n                obj,\n                ptr as _,\n                1,\n            );\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "windows-kernel-rs/src/version.rs",
    "content": "//! This module provides utilities to query information about the version of Microsoft Windows.\n\nuse crate::error::{Error, IntoResult};\nuse windows_kernel_sys::base::RTL_OSVERSIONINFOW;\nuse windows_kernel_sys::ntoskrnl::RtlGetVersion;\n\n/// Represents version information for Microsoft Windows.\npub struct VersionInfo {\n    version_info: RTL_OSVERSIONINFOW,\n}\n\nimpl VersionInfo {\n    /// Uses [`RtlGetVersion`] to query the version info for Microsoft Windows.\n    pub fn query() -> Result<Self, Error> {\n        let mut version_info: RTL_OSVERSIONINFOW = unsafe { core::mem::zeroed() };\n\n        version_info.dwOSVersionInfoSize = core::mem::size_of::<RTL_OSVERSIONINFOW>() as u32;\n\n        unsafe {\n            RtlGetVersion(&mut version_info)\n        }.into_result()?;\n\n        Ok(Self {\n            version_info,\n        })\n    }\n\n    /// Retrieves the major version of Microsoft Windows.\n    pub fn major(&self) -> u32 {\n        self.version_info.dwMajorVersion\n    }\n\n    /// Retrieves the minor version of Microsoft Windows.\n    pub fn minor(&self) -> u32 {\n        self.version_info.dwMinorVersion\n    }\n\n    /// Retrieves the build number of Microsoft Windows.\n    pub fn build_number(&self) -> u32 {\n        self.version_info.dwBuildNumber\n    }\n}\n"
  },
  {
    "path": "windows-kernel-sys/Cargo.toml",
    "content": "[package]\nname = \"windows-kernel-sys\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[features]\ndefault = [\"intrin\", \"ntoskrnl\"]\nintrin = []\nntoskrnl = []\nnetio = []\n\n[dependencies]\ncty = \"0.2\"\n\n[build-dependencies]\nbindgen = \"0.68\"\ncc = \"1.0\"\nwindows-kernel-build = { path = \"../windows-kernel-build\" }\n"
  },
  {
    "path": "windows-kernel-sys/build.rs",
    "content": "use std::path::PathBuf;\nuse windows_kernel_build::DirectoryType;\n\nuse bindgen::callbacks::*;\n\n#[derive(Debug)]\nstruct Callbacks;\n\nimpl ParseCallbacks for Callbacks {\n    fn int_macro(&self, name: &str, _value: i64) -> Option<IntKind> {\n        Some(match name {\n            \"TRUE\" | \"FALSE\" => IntKind::UChar,\n            _ => return None,\n        })\n    }\n}\n\nfn generate_base() {\n    println!(\"cargo:rerun-if-changed=src/wrapper.h\");\n\n    let include_dir = windows_kernel_build::get_km_dir(DirectoryType::Include).unwrap();\n    let out_path = PathBuf::from(\n        std::env::var_os(\"OUT_DIR\")\n            .expect(\"the environment variable OUT_DIR is undefined\")\n    );\n\n    bindgen::Builder::default()\n        .header(\"src/wrapper.h\")\n        .use_core()\n        .derive_debug(false)\n        .layout_tests(false)\n        .ctypes_prefix(\"cty\")\n        .default_enum_style(bindgen::EnumVariation::ModuleConsts)\n        .clang_arg(format!(\"-I{}\", include_dir.to_str().unwrap()))\n        .parse_callbacks(Box::new(bindgen::CargoCallbacks))\n        .parse_callbacks(Box::new(Callbacks))\n        .ignore_functions()\n        .generate()\n        .unwrap()\n        .write_to_file(out_path.join(\"base.rs\"))\n        .unwrap();\n}\n\n#[cfg(feature = \"intrin\")]\nfn generate_intrin() {\n    println!(\"cargo:rerun-if-changed=src/wrapper_intrin.c\");\n\n    let include_dir = windows_kernel_build::get_km_dir(DirectoryType::Include).unwrap();\n\n    cc::Build::new()\n        .flag(\"/kernel\")\n        .include(include_dir)\n        .file(\"src/wrapper_intrin.c\")\n        .compile(\"wrapper_intrin\");\n}\n\n#[cfg(not(feature = \"intrin\"))]\nfn generate_intrin() {\n}\n\n#[cfg(feature = \"ntoskrnl\")]\nfn generate_ntoskrnl() {\n    println!(\"cargo:rerun-if-changed=src/wrapper.h\");\n    println!(\"cargo:rerun-if-changed=src/wrapper.c\");\n    println!(\"cargo:rustc-link-lib=ntoskrnl\");\n\n    let include_dir = windows_kernel_build::get_km_dir(DirectoryType::Include).unwrap();\n    let out_path = PathBuf::from(\n        std::env::var_os(\"OUT_DIR\")\n            .expect(\"the environment variable OUT_DIR is undefined\")\n    );\n\n    bindgen::Builder::default()\n        .header(\"src/wrapper.h\")\n        .use_core()\n        .derive_debug(false)\n        .layout_tests(false)\n        .ctypes_prefix(\"cty\")\n        .default_enum_style(bindgen::EnumVariation::ModuleConsts)\n        .clang_arg(format!(\"-I{}\", include_dir.to_str().unwrap()))\n        .parse_callbacks(Box::new(bindgen::CargoCallbacks))\n        .blocklist_type(\".*\")\n        .allowlist_function(\".*\")\n        .allowlist_recursively(false)\n        .generate()\n        .unwrap()\n        .write_to_file(out_path.join(\"ntoskrnl.rs\"))\n        .unwrap();\n\n    cc::Build::new()\n        .flag(\"/kernel\")\n        .include(include_dir)\n        .file(\"src/wrapper.c\")\n        .compile(\"wrapper_ntoskrnl\");\n}\n\n#[cfg(not(feature = \"ntoskrnl\"))]\nfn generate_ntoskrnl() {\n}\n\n#[cfg(feature = \"netio\")]\nfn generate_netio() {\n    println!(\"cargo:rerun-if-changed=src/wrapper_netio.h\");\n    println!(\"cargo:rustc-link-lib=netio\");\n\n    let include_dir = windows_kernel_build::get_km_dir(DirectoryType::Include).unwrap();\n    let out_path = PathBuf::from(\n        std::env::var_os(\"OUT_DIR\")\n            .expect(\"the environment variable OUT_DIR is undefined\")\n    );\n\n    bindgen::Builder::default()\n        .header(\"src/wrapper.h\")\n        .use_core()\n        .derive_debug(false)\n        .layout_tests(false)\n        .ctypes_prefix(\"cty\")\n        .default_enum_style(bindgen::EnumVariation::ModuleConsts)\n        .clang_arg(format!(\"-I{}\", include_dir.to_str().unwrap()))\n        .parse_callbacks(Box::new(bindgen::CargoCallbacks))\n        .blocklist_type(\".*\")\n        .allowlist_function(\".*\")\n        .allowlist_recursively(false)\n        .generate()\n        .unwrap()\n        .write_to_file(out_path.join(\"netio.rs\"))\n        .unwrap();\n}\n\n#[cfg(not(feature = \"netio\"))]\nfn generate_netio() {\n}\n\nfn main() {\n    println!(\"cargo:rerun-if-changed=build.rs\");\n\n    generate_base();\n    generate_intrin();\n    generate_ntoskrnl();\n    generate_netio();\n}\n"
  },
  {
    "path": "windows-kernel-sys/rust-toolchain",
    "content": "nightly\n"
  },
  {
    "path": "windows-kernel-sys/src/base.rs",
    "content": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\npub use cty::*;\n\ninclude!(concat!(env!(\"OUT_DIR\"), \"/base.rs\"));\n\npub const STATUS_SUCCESS:                  NTSTATUS = 0x00000000;\npub const STATUS_GUARD_PAGE_VIOLATION:     NTSTATUS = 0x80000001 as u32 as i32;\npub const STATUS_DATATYPE_MISALIGNMENT:    NTSTATUS = 0x80000002 as u32 as i32;\npub const STATUS_BREAKPOINT:               NTSTATUS = 0x80000003 as u32 as i32;\npub const STATUS_SINGLE_STEP:              NTSTATUS = 0x80000004 as u32 as i32;\npub const STATUS_UNWIND_CONSOLIDATE:       NTSTATUS = 0x80000029 as u32 as i32;\npub const STATUS_UNSUCCESSFUL:             NTSTATUS = 0xC0000001 as u32 as i32;\npub const STATUS_NOT_IMPLEMENTED:          NTSTATUS = 0xC0000002 as u32 as i32;\npub const STATUS_ACCESS_VIOLATION:         NTSTATUS = 0xC0000005 as u32 as i32;\npub const STATUS_IN_PAGE_ERROR:            NTSTATUS = 0xC0000006 as u32 as i32;\npub const STATUS_INVALID_HANDLE:           NTSTATUS = 0xC0000008 as u32 as i32;\npub const STATUS_INVALID_PARAMETER:        NTSTATUS = 0xC000000D as u32 as i32;\npub const STATUS_END_OF_FILE:              NTSTATUS = 0xC0000011 as u32 as i32;\npub const STATUS_NO_MEMORY:                NTSTATUS = 0xC0000017 as u32 as i32;\npub const STATUS_ILLEGAL_INSTRUCTION:      NTSTATUS = 0xC000001D as u32 as i32;\npub const STATUS_NONCONTINUABLE_EXCEPTION: NTSTATUS = 0xC0000025 as u32 as i32;\npub const STATUS_INVALID_DISPOSITION:      NTSTATUS = 0xC0000026 as u32 as i32;\npub const STATUS_ARRAY_BOUNDS_EXCEEDED:    NTSTATUS = 0xC000008C as u32 as i32;\npub const STATUS_FLOAT_DENORMAL_OPERAND:   NTSTATUS = 0xC000008D as u32 as i32;\npub const STATUS_FLOAT_DIVIDE_BY_ZERO:     NTSTATUS = 0xC000008E as u32 as i32;\npub const STATUS_FLOAT_INEXACT_RESULT:     NTSTATUS = 0xC000008F as u32 as i32;\npub const STATUS_FLOAT_INVALID_OPERATION:  NTSTATUS = 0xC0000090 as u32 as i32;\npub const STATUS_FLOAT_OVERFLOW:           NTSTATUS = 0xC0000091 as u32 as i32;\npub const STATUS_FLOAT_STACK_CHECK:        NTSTATUS = 0xC0000092 as u32 as i32;\npub const STATUS_FLOAT_UNDERFLOW:          NTSTATUS = 0xC0000093 as u32 as i32;\npub const STATUS_INTEGER_DIVIDE_BY_ZERO:   NTSTATUS = 0xC0000094 as u32 as i32;\npub const STATUS_INTEGER_OVERFLOW:         NTSTATUS = 0xC0000095 as u32 as i32;\npub const STATUS_PRIVILEGED_INSTRUCTION:   NTSTATUS = 0xC0000096 as u32 as i32;\npub const STATUS_INSUFFICIENT_RESOURCES:   NTSTATUS = 0xC000009A as u32 as i32;\npub const STATUS_INVALID_USER_BUFFER:      NTSTATUS = 0xC00000E8 as u32 as i32;\npub const STATUS_STACK_OVERFLOW:           NTSTATUS = 0xC00000FD as u32 as i32;\n"
  },
  {
    "path": "windows-kernel-sys/src/intrin.rs",
    "content": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\nuse crate::base::*;\n\n#[link(name = \"wrapper_intrin\")]\nextern \"C\" {\n    pub fn read_cr3() -> u64;\n    pub fn write_cr3(value: u64);\n    pub fn read_msr(register: u32) -> u64;\n    pub fn read_msr_safe(register: u32, value: &mut u64) -> NTSTATUS;\n    pub fn write_msr(register: u32, value: u64);\n    pub fn write_msr_safe(register: u32, value: u64) -> NTSTATUS;\n    pub fn invlpg(value: usize);\n}\n"
  },
  {
    "path": "windows-kernel-sys/src/lib.rs",
    "content": "#![no_std]\n\npub mod base;\n\n#[cfg(feature = \"intrin\")]\npub mod intrin;\n#[cfg(feature = \"netio\")]\npub mod netio;\n#[cfg(feature = \"ntoskrnl\")]\npub mod ntoskrnl;\n\npub use cty::*;\n"
  },
  {
    "path": "windows-kernel-sys/src/netio.rs",
    "content": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\nuse crate::base::*;\n\ninclude!(concat!(env!(\"OUT_DIR\"), \"/netio.rs\"));\n"
  },
  {
    "path": "windows-kernel-sys/src/ntoskrnl.rs",
    "content": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\nuse crate::base::*;\n\n#[link(name = \"wrapper_ntoskrnl\")]\nextern \"C\" {\n    pub fn _ExInitializeFastMutex(mutex: PFAST_MUTEX);\n    pub fn _ExAcquirePushLockExclusive(push_lock: PEX_PUSH_LOCK);\n    pub fn _ExReleasePushLockExclusive(push_lock: PEX_PUSH_LOCK);\n    pub fn _ExAcquirePushLockShared(push_lock: PEX_PUSH_LOCK);\n    pub fn _ExReleasePushLockShared(push_lock: PEX_PUSH_LOCK);\n    pub fn _IoGetCurrentIrpStackLocation(irp: PIRP) -> PIO_STACK_LOCATION;\n    pub fn _IoGetNextIrpStackLocation(irp: PIRP) -> PIO_STACK_LOCATION;\n    pub fn _IoSetCompletionRoutine(\n        irp: PIRP,\n        completion_routine: PIO_COMPLETION_ROUTINE,\n        context: PVOID,\n        invoke_on_success: BOOLEAN,\n        invoke_on_error: BOOLEAN,\n        invoke_on_cancel: BOOLEAN,\n    );\n    pub fn _IoCompleteRequest(irp: PIRP, priority_boost: CCHAR);\n    pub fn _MmGetMdlByteCount(mdl: PMDL) -> ULONG;\n    pub fn _MmGetMdlByteOffset(mdl: PMDL) -> ULONG;\n    pub fn _MmGetSystemAddressForMdlSafe(mdl: PMDL, priority: ULONG) -> PVOID;\n    pub fn _ObDereferenceObject(p: *mut cty::c_void);\n    pub fn _ObReferenceObject(p: *mut cty::c_void);\n}\n\npub use self::_ExInitializeFastMutex as ExInitializeFastMutex;\npub use self::_ExAcquirePushLockExclusive as ExAcquirePushLockExclusive;\npub use self::_ExReleasePushLockExclusive as ExReleasePushLockExclusive;\npub use self::_ExAcquirePushLockShared as ExAcquirePushLockShared;\npub use self::_ExReleasePushLockShared as ExReleasePushLockShared;\npub use self::_IoGetCurrentIrpStackLocation as IoGetCurrentIrpStackLocation;\npub use self::_IoGetNextIrpStackLocation as IoGetNextIrpStackLocation;\npub use self::_IoSetCompletionRoutine as IoSetCompletionRoutine;\npub use self::_IoCompleteRequest as IoCompleteRequest;\npub use self::_MmGetMdlByteCount as MmGetMdlByteCount;\npub use self::_MmGetMdlByteOffset as MmGetMdlByteOffset;\npub use self::_MmGetSystemAddressForMdlSafe as MmGetSystemAddressForMdlSafe;\npub use self::_ObDereferenceObject as ObDereferenceObject;\npub use self::_ObReferenceObject as ObReferenceObject;\n\npub use self::IoGetCurrentProcess as PsGetCurrentProcess;\n\ninclude!(concat!(env!(\"OUT_DIR\"), \"/ntoskrnl.rs\"));\n"
  },
  {
    "path": "windows-kernel-sys/src/wrapper.c",
    "content": "#include \"wrapper.h\"\n\nvoid _ExInitializeFastMutex(\n\tPFAST_MUTEX fast_mutex\n) {\n\tExInitializeFastMutex(fast_mutex);\n}\n\nvoid _ExAcquirePushLockExclusive(\n\tPEX_PUSH_LOCK push_lock\n) {\n\tExAcquirePushLockExclusive(push_lock);\n}\n\nvoid _ExReleasePushLockExclusive(\n\tPEX_PUSH_LOCK push_lock\n) {\n\tExReleasePushLockExclusive(push_lock);\n}\n\nvoid _ExAcquirePushLockShared(\n\tPEX_PUSH_LOCK push_lock\n) {\n\tExAcquirePushLockShared(push_lock);\n}\n\nvoid _ExReleasePushLockShared(\n\tPEX_PUSH_LOCK push_lock\n) {\n\tExReleasePushLockShared(push_lock);\n}\n\nPIO_STACK_LOCATION _IoGetCurrentIrpStackLocation(PIRP irp) {\n\treturn IoGetCurrentIrpStackLocation(irp);\n}\n\nPIO_STACK_LOCATION _IoGetNextIrpStackLocation(PIRP irp) {\n\treturn IoGetNextIrpStackLocation(irp);\n}\n\nvoid _IoSetCompletionRoutine(\n\tPIRP irp,\n\tPIO_COMPLETION_ROUTINE completion_routine, \n\tPVOID context,\n\tBOOLEAN invoke_on_success,\n\tBOOLEAN invoke_on_error,\n\tBOOLEAN invoke_on_cancel\n) {\n\tIoSetCompletionRoutine(irp, completion_routine, context, invoke_on_success, invoke_on_error, invoke_on_cancel);\n}\n\nvoid _IoCompleteRequest(\n\tPIRP irp,\n\tCCHAR priority_boost\n) {\n\tIoCompleteRequest(irp, priority_boost);\n}\n\nULONG _MmGetMdlByteCount(PMDL mdl) {\n\treturn MmGetMdlByteCount(mdl);\n}\n\nULONG _MmGetMdlByteOffset(PMDL mdl) {\n\treturn MmGetMdlByteOffset(mdl);\n}\n\nPVOID _MmGetSystemAddressForMdlSafe(PMDL mdl, ULONG priority) {\n\treturn MmGetSystemAddressForMdlSafe(mdl, priority);\n}\n\nvoid _ObDereferenceObject(PVOID p) {\n\tObDereferenceObject(p);\n}\n\nvoid _ObReferenceObject(PVOID p) {\n\tObReferenceObject(p);\n}\n"
  },
  {
    "path": "windows-kernel-sys/src/wrapper.h",
    "content": "#define _AMD64_\n\n#include \"ntdef.h\"\n#include \"ntstatus.h\"\n\ntypedef ULONG_PTR _EX_PUSH_LOCK;\ntypedef ULONG_PTR EX_PUSH_LOCK;\ntypedef ULONG_PTR *PEX_PUSH_LOCK;\n\ntypedef union _KGDTENTRY64\n{\n\tstruct\n\t{\n\t\tunsigned short LimitLow;\n\t\tunsigned short BaseLow;\n\t\tunion\n\t\t{\n\t\t\tstruct\n\t\t\t{\n\t\t\t\tunsigned char BaseMiddle;\n\t\t\t\tunsigned char Flags1;\n\t\t\t\tunsigned char Flags2;\n\t\t\t\tunsigned char BaseHigh;\n\t\t\t} Bytes;\n\t\t\tstruct\n\t\t\t{\n\t\t\t\tunsigned long BaseMiddle : 8;\n\t\t\t\tunsigned long Type : 5;\n\t\t\t\tunsigned long Dpl : 2;\n\t\t\t\tunsigned long Present : 1;\n\t\t\t\tunsigned long LimitHigh : 4;\n\t\t\t\tunsigned long System : 1;\n\t\t\t\tunsigned long LongMode : 1;\n\t\t\t\tunsigned long DefaultBig : 1;\n\t\t\t\tunsigned long Granularity : 1;\n\t\t\t\tunsigned long BaseHigh : 8;\n\t\t\t} Bits;\n\t\t};\n\t\tunsigned long BaseUpper;\n\t\tunsigned long MustBeZero;\n\t};\n\tunsigned __int64 Alignment;\n} KGDTENTRY64, *PKGDTENTRY64;\n\ntypedef union _KIDTENTRY64\n{\n\tstruct\n\t{\n\t\tunsigned short OffsetLow;\n\t\tunsigned short Selector;\n\t\tunsigned short IstIndex : 3;\n\t\tunsigned short Reserved0 : 5;\n\t\tunsigned short Type : 5;\n\t\tunsigned short Dpl : 2;\n\t\tunsigned short Present : 1;\n\t\tunsigned short OffsetMiddle;\n\t\tunsigned long OffsetHigh;\n\t\tunsigned long Reserved1;\n\t};\n\tunsigned __int64 Alignment;\n} KIDTENTRY64, *PKIDTENTRY64;\n\n#include \"ntifs.h\"\n"
  },
  {
    "path": "windows-kernel-sys/src/wrapper_intrin.c",
    "content": "#define _AMD64_\n\n#include \"wdm.h\"\n#include \"intrin.h\"\n\nunsigned __int64 read_cr3(void) {\n\treturn __readcr3();\n}\n\nvoid write_cr3(unsigned __int64 Value) {\n\t__writecr3(Value);\n}\n\nunsigned __int64 read_msr(\n\tunsigned long Register\n) {\n\treturn __readmsr(Register);\n}\n\nNTSTATUS read_msr_safe(\n\tunsigned long Register,\n\tunsigned __int64 *Value\n) {\n\tif (!Value) {\n\t\treturn STATUS_INVALID_PARAMETER;\n\t}\n\n\t__try {\n\t\t*Value = __readmsr(Register);\n\t} __except(EXCEPTION_EXECUTE_HANDLER) {\n\t\treturn GetExceptionCode();\n\t}\n\n\treturn STATUS_SUCCESS;\n}\n\nvoid write_msr(\n\tunsigned long Register,\n\tunsigned __int64 Value\n) {\n\t__writemsr(Register, Value);\n}\n\nNTSTATUS write_msr_safe(\n\tunsigned long Register,\n\tunsigned __int64 Value\n) {\n\t__try {\n\t\t__writemsr(Register, Value);\n\t} __except(EXCEPTION_EXECUTE_HANDLER) {\n\t\treturn GetExceptionCode();\n\t}\n\n\treturn STATUS_SUCCESS;\n}\n\nvoid invlpg(\n\tvoid *Address\n) {\n\t__invlpg(Address);\n}\n"
  },
  {
    "path": "windows-kernel-sys/src/wrapper_netio.h",
    "content": "#define _AMD64_\n\n#include \"ntdef.h\"\n#include \"wdm.h\"\n#include \"wsk.h\"\n"
  },
  {
    "path": "winioctl/Cargo.toml",
    "content": "[package]\nname = \"winioctl\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nbitflags = \"1.3\"\nthiserror = \"1.0\"\n\n[target.'cfg(windows)'.dependencies]\nwinapi = { version = \"0.3\", features = [\"ioapiset\", \"winioctl\"] }\n"
  },
  {
    "path": "winioctl/src/error.rs",
    "content": "use thiserror::Error;\n\n#[derive(Debug, Error)]\npub enum Error {\n    #[error(transparent)]\n    IoError(#[from] std::io::Error),\n}\n"
  },
  {
    "path": "winioctl/src/ioctl.rs",
    "content": "use bitflags::bitflags;\nuse winapi::um::winioctl::{\n    FILE_ANY_ACCESS,\n    METHOD_NEITHER, METHOD_IN_DIRECT, METHOD_OUT_DIRECT, METHOD_BUFFERED\n};\nuse winapi::um::winnt::{\n    FILE_READ_DATA, FILE_WRITE_DATA,\n};\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub enum DeviceType {\n    Port8042,\n    Acpi,\n    Battery,\n    Beep,\n    BusExtender,\n    Cdrom,\n    CdromFileSystem,\n    Changer,\n    Controller,\n    DataLink,\n    Dfs,\n    DfsFileSystem,\n    DfsVolume,\n    Disk,\n    DiskFileSystem,\n    Dvd,\n    FileSystem,\n    Fips,\n    FullscreenVideo,\n    InportPort,\n    Keyboard,\n    Ks,\n    Ksec,\n    Mailslot,\n    MassStorage,\n    MidiIn,\n    MidiOut,\n    Modem,\n    Mouse,\n    MultiUncProvider,\n    NamedPipe,\n    Network,\n    NetworkBrowser,\n    NetworkFileSystem,\n    NetworkRedirector,\n    Null,\n    ParallelPort,\n    PhysicalNetcard,\n    Printer,\n    Scanner,\n    Screen,\n    Serenum,\n    SerialPort,\n    SerialMousePort,\n    Smartcard,\n    Smb,\n    Sound,\n    Streams,\n    Tape,\n    TapeFileSystem,\n    Termsrv,\n    Transport,\n    Unknown,\n    Vdm,\n    Video,\n    VirtualDisk,\n    WaveIn,\n    WaveOut,\n}\n\nimpl Into<u32> for DeviceType {\n    fn into(self) -> u32 {\n        match self {\n            DeviceType::Port8042 => winapi::um::winioctl::FILE_DEVICE_8042_PORT,\n            DeviceType::Acpi => winapi::um::winioctl::FILE_DEVICE_ACPI,\n            DeviceType::Battery => winapi::um::winioctl::FILE_DEVICE_BATTERY,\n            DeviceType::Beep => winapi::um::winioctl::FILE_DEVICE_BEEP,\n            DeviceType::BusExtender => winapi::um::winioctl::FILE_DEVICE_BUS_EXTENDER,\n            DeviceType::Cdrom => winapi::um::winioctl::FILE_DEVICE_CD_ROM,\n            DeviceType::CdromFileSystem => winapi::um::winioctl::FILE_DEVICE_CD_ROM_FILE_SYSTEM,\n            DeviceType::Changer => winapi::um::winioctl::FILE_DEVICE_CHANGER,\n            DeviceType::Controller => winapi::um::winioctl::FILE_DEVICE_CONTROLLER,\n            DeviceType::DataLink => winapi::um::winioctl::FILE_DEVICE_DATALINK,\n            DeviceType::Dfs => winapi::um::winioctl::FILE_DEVICE_DFS,\n            DeviceType::DfsFileSystem => winapi::um::winioctl::FILE_DEVICE_DFS_FILE_SYSTEM,\n            DeviceType::DfsVolume => winapi::um::winioctl::FILE_DEVICE_DFS_VOLUME,\n            DeviceType::Disk => winapi::um::winioctl::FILE_DEVICE_DISK,\n            DeviceType::DiskFileSystem => winapi::um::winioctl::FILE_DEVICE_DISK_FILE_SYSTEM,\n            DeviceType::Dvd => winapi::um::winioctl::FILE_DEVICE_DVD,\n            DeviceType::FileSystem => winapi::um::winioctl::FILE_DEVICE_FILE_SYSTEM,\n            DeviceType::Fips => winapi::um::winioctl::FILE_DEVICE_FIPS,\n            DeviceType::FullscreenVideo => winapi::um::winioctl::FILE_DEVICE_FULLSCREEN_VIDEO,\n            DeviceType::InportPort => winapi::um::winioctl::FILE_DEVICE_INPORT_PORT,\n            DeviceType::Keyboard => winapi::um::winioctl::FILE_DEVICE_KEYBOARD,\n            DeviceType::Ks => winapi::um::winioctl::FILE_DEVICE_KS,\n            DeviceType::Ksec => winapi::um::winioctl::FILE_DEVICE_KSEC,\n            DeviceType::Mailslot => winapi::um::winioctl::FILE_DEVICE_MAILSLOT,\n            DeviceType::MassStorage => winapi::um::winioctl::FILE_DEVICE_MASS_STORAGE,\n            DeviceType::MidiIn => winapi::um::winioctl::FILE_DEVICE_MIDI_IN,\n            DeviceType::MidiOut => winapi::um::winioctl::FILE_DEVICE_MIDI_OUT,\n            DeviceType::Modem => winapi::um::winioctl::FILE_DEVICE_MODEM,\n            DeviceType::Mouse => winapi::um::winioctl::FILE_DEVICE_MOUSE,\n            DeviceType::MultiUncProvider => winapi::um::winioctl::FILE_DEVICE_MULTI_UNC_PROVIDER,\n            DeviceType::NamedPipe => winapi::um::winioctl::FILE_DEVICE_NAMED_PIPE,\n            DeviceType::Network => winapi::um::winioctl::FILE_DEVICE_NETWORK,\n            DeviceType::NetworkBrowser => winapi::um::winioctl::FILE_DEVICE_NETWORK_BROWSER,\n            DeviceType::NetworkFileSystem => winapi::um::winioctl::FILE_DEVICE_NETWORK_FILE_SYSTEM,\n            DeviceType::NetworkRedirector => winapi::um::winioctl::FILE_DEVICE_NETWORK_REDIRECTOR,\n            DeviceType::Null => winapi::um::winioctl::FILE_DEVICE_NULL,\n            DeviceType::ParallelPort => winapi::um::winioctl::FILE_DEVICE_PARALLEL_PORT,\n            DeviceType::PhysicalNetcard => winapi::um::winioctl::FILE_DEVICE_PHYSICAL_NETCARD,\n            DeviceType::Printer => winapi::um::winioctl::FILE_DEVICE_PRINTER,\n            DeviceType::Scanner => winapi::um::winioctl::FILE_DEVICE_SCANNER,\n            DeviceType::Screen => winapi::um::winioctl::FILE_DEVICE_SCREEN,\n            DeviceType::Serenum => winapi::um::winioctl::FILE_DEVICE_SERENUM,\n            DeviceType::SerialMousePort => winapi::um::winioctl::FILE_DEVICE_SERIAL_MOUSE_PORT,\n            DeviceType::SerialPort => winapi::um::winioctl::FILE_DEVICE_SERIAL_PORT,\n            DeviceType::Smartcard => winapi::um::winioctl::FILE_DEVICE_SMARTCARD,\n            DeviceType::Smb => winapi::um::winioctl::FILE_DEVICE_SMB,\n            DeviceType::Sound => winapi::um::winioctl::FILE_DEVICE_SOUND,\n            DeviceType::Streams => winapi::um::winioctl::FILE_DEVICE_STREAMS,\n            DeviceType::Tape => winapi::um::winioctl::FILE_DEVICE_TAPE,\n            DeviceType::TapeFileSystem => winapi::um::winioctl::FILE_DEVICE_TAPE_FILE_SYSTEM,\n            DeviceType::Termsrv => winapi::um::winioctl::FILE_DEVICE_TERMSRV,\n            DeviceType::Transport => winapi::um::winioctl::FILE_DEVICE_TRANSPORT,\n            DeviceType::Unknown => winapi::um::winioctl::FILE_DEVICE_UNKNOWN,\n            DeviceType::Vdm => winapi::um::winioctl::FILE_DEVICE_VDM,\n            DeviceType::Video => winapi::um::winioctl::FILE_DEVICE_VIDEO,\n            DeviceType::VirtualDisk => winapi::um::winioctl::FILE_DEVICE_VIRTUAL_DISK,\n            DeviceType::WaveIn => winapi::um::winioctl::FILE_DEVICE_WAVE_IN,\n            DeviceType::WaveOut => winapi::um::winioctl::FILE_DEVICE_WAVE_OUT,\n        }\n    }\n}\n\nimpl From<u32> for DeviceType {\n    fn from(value: u32) -> Self {\n        match value {\n            winapi::um::winioctl::FILE_DEVICE_8042_PORT => DeviceType::Port8042,\n            winapi::um::winioctl::FILE_DEVICE_ACPI => DeviceType::Acpi,\n            winapi::um::winioctl::FILE_DEVICE_BATTERY => DeviceType::Battery,\n            winapi::um::winioctl::FILE_DEVICE_BEEP => DeviceType::Beep,\n            winapi::um::winioctl::FILE_DEVICE_BUS_EXTENDER => DeviceType::BusExtender,\n            winapi::um::winioctl::FILE_DEVICE_CD_ROM => DeviceType::Cdrom,\n            winapi::um::winioctl::FILE_DEVICE_CD_ROM_FILE_SYSTEM => DeviceType::CdromFileSystem,\n            winapi::um::winioctl::FILE_DEVICE_CHANGER => DeviceType::Changer,\n            winapi::um::winioctl::FILE_DEVICE_CONTROLLER => DeviceType::Controller,\n            winapi::um::winioctl::FILE_DEVICE_DATALINK => DeviceType::DataLink,\n            winapi::um::winioctl::FILE_DEVICE_DFS => DeviceType::Dfs,\n            winapi::um::winioctl::FILE_DEVICE_DFS_FILE_SYSTEM => DeviceType::DfsFileSystem,\n            winapi::um::winioctl::FILE_DEVICE_DFS_VOLUME => DeviceType::DfsVolume,\n            winapi::um::winioctl::FILE_DEVICE_DISK => DeviceType::Disk,\n            winapi::um::winioctl::FILE_DEVICE_DISK_FILE_SYSTEM => DeviceType::DiskFileSystem,\n            winapi::um::winioctl::FILE_DEVICE_DVD => DeviceType::Dvd,\n            winapi::um::winioctl::FILE_DEVICE_FILE_SYSTEM => DeviceType::FileSystem,\n            winapi::um::winioctl::FILE_DEVICE_FIPS => DeviceType::Fips,\n            winapi::um::winioctl::FILE_DEVICE_FULLSCREEN_VIDEO => DeviceType::FullscreenVideo,\n            winapi::um::winioctl::FILE_DEVICE_INPORT_PORT => DeviceType::InportPort,\n            winapi::um::winioctl::FILE_DEVICE_KEYBOARD => DeviceType::Keyboard,\n            winapi::um::winioctl::FILE_DEVICE_KS => DeviceType::Ks,\n            winapi::um::winioctl::FILE_DEVICE_KSEC => DeviceType::Ksec,\n            winapi::um::winioctl::FILE_DEVICE_MAILSLOT => DeviceType::Mailslot,\n            winapi::um::winioctl::FILE_DEVICE_MASS_STORAGE => DeviceType::MassStorage,\n            winapi::um::winioctl::FILE_DEVICE_MIDI_IN => DeviceType::MidiIn,\n            winapi::um::winioctl::FILE_DEVICE_MIDI_OUT => DeviceType::MidiOut,\n            winapi::um::winioctl::FILE_DEVICE_MODEM => DeviceType::Modem,\n            winapi::um::winioctl::FILE_DEVICE_MOUSE => DeviceType::Mouse,\n            winapi::um::winioctl::FILE_DEVICE_MULTI_UNC_PROVIDER => DeviceType::MultiUncProvider,\n            winapi::um::winioctl::FILE_DEVICE_NAMED_PIPE => DeviceType::NamedPipe,\n            winapi::um::winioctl::FILE_DEVICE_NETWORK => DeviceType::Network,\n            winapi::um::winioctl::FILE_DEVICE_NETWORK_BROWSER => DeviceType::NetworkBrowser,\n            winapi::um::winioctl::FILE_DEVICE_NETWORK_FILE_SYSTEM => DeviceType::NetworkFileSystem,\n            winapi::um::winioctl::FILE_DEVICE_NETWORK_REDIRECTOR => DeviceType::NetworkRedirector,\n            winapi::um::winioctl::FILE_DEVICE_NULL => DeviceType::Null,\n            winapi::um::winioctl::FILE_DEVICE_PARALLEL_PORT => DeviceType::ParallelPort,\n            winapi::um::winioctl::FILE_DEVICE_PHYSICAL_NETCARD => DeviceType::PhysicalNetcard,\n            winapi::um::winioctl::FILE_DEVICE_PRINTER => DeviceType::Printer,\n            winapi::um::winioctl::FILE_DEVICE_SCANNER => DeviceType::Scanner,\n            winapi::um::winioctl::FILE_DEVICE_SCREEN => DeviceType::Screen,\n            winapi::um::winioctl::FILE_DEVICE_SERENUM => DeviceType::Serenum,\n            winapi::um::winioctl::FILE_DEVICE_SERIAL_MOUSE_PORT => DeviceType::SerialMousePort,\n            winapi::um::winioctl::FILE_DEVICE_SERIAL_PORT => DeviceType::SerialPort,\n            winapi::um::winioctl::FILE_DEVICE_SMARTCARD => DeviceType::Smartcard,\n            winapi::um::winioctl::FILE_DEVICE_SMB => DeviceType::Smb,\n            winapi::um::winioctl::FILE_DEVICE_SOUND => DeviceType::Sound,\n            winapi::um::winioctl::FILE_DEVICE_STREAMS => DeviceType::Streams,\n            winapi::um::winioctl::FILE_DEVICE_TAPE => DeviceType::Tape,\n            winapi::um::winioctl::FILE_DEVICE_TAPE_FILE_SYSTEM => DeviceType::TapeFileSystem,\n            winapi::um::winioctl::FILE_DEVICE_TERMSRV => DeviceType::Termsrv,\n            winapi::um::winioctl::FILE_DEVICE_TRANSPORT => DeviceType::Transport,\n            winapi::um::winioctl::FILE_DEVICE_UNKNOWN => DeviceType::Unknown,\n            winapi::um::winioctl::FILE_DEVICE_VDM => DeviceType::Vdm,\n            winapi::um::winioctl::FILE_DEVICE_VIDEO => DeviceType::Video,\n            winapi::um::winioctl::FILE_DEVICE_VIRTUAL_DISK => DeviceType::VirtualDisk,\n            winapi::um::winioctl::FILE_DEVICE_WAVE_IN => DeviceType::WaveIn,\n            winapi::um::winioctl::FILE_DEVICE_WAVE_OUT => DeviceType::WaveOut,\n            _ => DeviceType::Unknown,\n        }\n    }\n}\n\nbitflags! {\n    pub struct RequiredAccess: u32 {\n        const ANY_ACCESS = FILE_ANY_ACCESS;\n        const READ_DATA = FILE_READ_DATA;\n        const WRITE_DATA = FILE_WRITE_DATA;\n        const READ_WRITE_DATA = FILE_READ_DATA | FILE_WRITE_DATA;\n    }\n}\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n#[repr(u32)]\npub enum TransferMethod {\n    Neither = METHOD_NEITHER,\n    InputDirect = METHOD_IN_DIRECT,\n    OutputDirect = METHOD_OUT_DIRECT,\n    Buffered = METHOD_BUFFERED,\n}\n\nimpl From<u32> for TransferMethod {\n    fn from(value: u32) -> Self {\n        match value & 0x3 {\n            METHOD_NEITHER => Self::Neither,\n            METHOD_IN_DIRECT => Self::InputDirect,\n            METHOD_OUT_DIRECT => Self::OutputDirect,\n            METHOD_BUFFERED => Self::Buffered,\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl Into<u32> for TransferMethod {\n    fn into(self) -> u32 {\n        match self {\n            Self::Neither => METHOD_NEITHER,\n            Self::InputDirect => METHOD_IN_DIRECT,\n            Self::OutputDirect => METHOD_OUT_DIRECT,\n            Self::Buffered => METHOD_BUFFERED,\n        }\n    }\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct ControlCode(pub DeviceType, pub RequiredAccess, pub u32, pub TransferMethod);\n\nimpl ControlCode {\n    const METHOD_BITS: usize = 2;\n    const NUM_BITS:    usize = 12;\n    const ACCESS_BITS: usize = 2;\n    const TYPE_BITS:   usize = 16;\n\n    const METHOD_SHIFT: usize = 0;\n    const NUM_SHIFT:    usize = Self::METHOD_SHIFT + Self::METHOD_BITS;\n    const ACCESS_SHIFT: usize = Self::NUM_SHIFT + Self::NUM_BITS;\n    const TYPE_SHIFT:   usize = Self::ACCESS_SHIFT + Self::ACCESS_BITS;\n\n    const METHOD_MASK: u32 = (1 << Self::METHOD_BITS) - 1;\n    const NUM_MASK:    u32 = (1 << Self::NUM_BITS) - 1;\n    const ACCESS_MASK: u32 = (1 << Self::ACCESS_BITS) - 1;\n    const TYPE_MASK:   u32 = (1 << Self::TYPE_BITS) - 1;\n}\n\nimpl From<u32> for ControlCode {\n    fn from(value: u32) -> Self {\n        let method = (value >> Self::METHOD_SHIFT) & Self::METHOD_MASK;\n        let num    = (value >> Self::NUM_SHIFT)    & Self::NUM_MASK;\n        let access = (value >> Self::ACCESS_SHIFT) & Self::ACCESS_MASK;\n        let ty     = (value >> Self::TYPE_SHIFT)   & Self::TYPE_MASK;\n\n        Self(\n            ty.into(),\n            RequiredAccess::from_bits(access).unwrap_or(RequiredAccess::READ_DATA),\n            num,\n            method.into()\n        )\n    }\n}\n\nimpl Into<u32> for ControlCode {\n    fn into(self) -> u32 {\n        let method = Into::<u32>::into(self.3) << Self::METHOD_SHIFT;\n        let num    = self.2 << Self::NUM_SHIFT;\n        let access = self.1.bits() << Self::ACCESS_SHIFT;\n        let ty     = Into::<u32>::into(self.0) << Self::TYPE_SHIFT;\n\n        ty | access | num | method\n    }\n}\n\n#[macro_export]\nmacro_rules! ioctl_none {\n    ($(#[$attr:meta])* $name:ident, $dev_ty:expr, $nr:expr) => {\n        $(#[$attr])*\n        pub unsafe fn $name(handle: *mut std::ffi::c_void) -> Result<u32, $crate::Error> {\n            let code = $crate::ControlCode(\n                $dev_ty,\n                $crate::RequiredAccess::ANY_ACCESS,\n                $nr,\n                $crate::TransferMethod::Neither,\n            ).into();\n            let mut return_value = 0;\n\n            let status = $crate::DeviceIoControl(\n                handle as _,\n                code,\n                std::ptr::null_mut(),\n                0,\n                std::ptr::null_mut(),\n                0,\n                &mut return_value,\n                std::ptr::null_mut(),\n            ) != 0;\n\n            match status {\n                true => Ok(return_value),\n                _ => Err(std::io::Error::last_os_error())?,\n            }\n        }\n    }\n}\n\n#[macro_export]\nmacro_rules! ioctl_read {\n    ($(#[$attr:meta])* $name:ident, $dev_ty:expr, $nr:expr, $ty:ty) => {\n        $(#[$attr])*\n        pub unsafe fn $name(handle: *mut std::ffi::c_void, data: *mut $ty) -> Result<u32, $crate::Error> {\n            let code = $crate::ControlCode(\n                $dev_ty,\n                $crate::RequiredAccess::READ_DATA,\n                $nr,\n                $crate::TransferMethod::Buffered,\n            ).into();\n            let mut return_value = 0;\n\n            let status = $crate::DeviceIoControl(\n                handle as _,\n                code,\n                data as _,\n                std::mem::size_of::<$ty>() as _,\n                data as _,\n                std::mem::size_of::<$ty>() as _,\n                &mut return_value,\n                std::ptr::null_mut(),\n            ) != 0;\n\n            match status {\n                true => Ok(return_value),\n                _ => Err(std::io::Error::last_os_error())?,\n            }\n        }\n    }\n}\n\n#[macro_export]\nmacro_rules! ioctl_write {\n    ($(#[$attr:meta])* $name:ident, $dev_ty:expr, $nr:expr, $ty:ty) => {\n        $(#[$attr])*\n        pub unsafe fn $name(handle: *mut std::ffi::c_void, data: *const $ty) -> Result<u32, $crate::Error> {\n            let code = $crate::ControlCode(\n                $dev_ty,\n                $crate::RequiredAccess::WRITE_DATA,\n                $nr,\n                $crate::TransferMethod::Buffered,\n            ).into();\n            let mut return_value = 0;\n\n            let status = $crate::DeviceIoControl(\n                handle as _,\n                code,\n                data as _,\n                std::mem::size_of::<$ty>() as _,\n                std::ptr::null_mut(),\n                0,\n                &mut return_value,\n                std::ptr::null_mut(),\n            ) != 0;\n\n            match status {\n                true => Ok(return_value),\n                _ => Err(std::io::Error::last_os_error())?,\n            }\n        }\n    }\n}\n\n#[macro_export]\nmacro_rules! ioctl_readwrite {\n    ($(#[$attr:meta])* $name:ident, $dev_ty:expr, $nr:expr, $ty:ty) => {\n        $(#[$attr])*\n        pub unsafe fn $name(handle: *mut std::ffi::c_void, data: *mut $ty) -> Result<u32, $crate::Error> {\n            let code = $crate::ControlCode(\n                $dev_ty,\n                $crate::RequiredAccess::READ_WRITE_DATA,\n                $nr,\n                $crate::TransferMethod::Buffered,\n            ).into();\n            let mut return_value = 0;\n\n            let status = $crate::DeviceIoControl(\n                handle as _,\n                code,\n                data as _,\n                std::mem::size_of::<$ty>() as _,\n                data as _,\n                std::mem::size_of::<$ty>() as _,\n                &mut return_value,\n                std::ptr::null_mut(),\n            ) != 0;\n\n            match status {\n                true => Ok(return_value),\n                _ => Err(std::io::Error::last_os_error())?,\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "winioctl/src/lib.rs",
    "content": "mod error;\nmod ioctl;\n\npub use crate::error::Error;\npub use crate::ioctl::{ControlCode, DeviceType, RequiredAccess, TransferMethod};\n\npub use winapi::um::ioapiset::DeviceIoControl;\n"
  }
]