windows_kernel_build/
lib.rs1use std::env::var;
2use std::path::Path;
3use std::path::PathBuf;
4use thiserror::Error;
5use winreg::RegKey;
6use winreg::enums::*;
7use failure::format_err;
8
9#[derive(Debug, Error)]
11pub enum Error {
12 #[error(transparent)]
13 IoError(#[from] std::io::Error),
14 #[error("cannot find the directory")]
15 DirectoryNotFound,
16}
17
18pub enum DirectoryType {
20 Include,
21 Library,
22}
23
24pub fn get_windows_kits_dir() -> Result<PathBuf, Error> {
27 let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
28 let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots";
29 let dir: String = hklm.open_subkey(key)?.get_value("KitsRoot10")?;
30
31 Ok(dir.into())
32}
33
34pub fn get_km_dir(dir_type: DirectoryType) -> Result<PathBuf, Error> {
38 let dir = get_windows_kits_dir()?
40 .join(match dir_type {
41 DirectoryType::Include => "Include",
42 DirectoryType::Library => "Lib",
43 })
44 .read_dir()?;
45
46 let dir = dir
49 .filter_map(|dir| dir.ok())
50 .map(|dir| dir.path())
51 .filter(|dir| {
52 dir.components()
53 .last()
54 .and_then(|c| c.as_os_str().to_str())
55 .map(|c| c.starts_with("10.") && dir.join("km").is_dir())
56 .unwrap_or(false)
57 })
58 .max()
59 .ok_or_else(|| Error::DirectoryNotFound)?;
60
61 Ok(dir.join("km"))
63}
64
65pub fn build() -> Result<(), Error> {
67 let dir = get_km_dir(DirectoryType::Library).unwrap();
69
70 let target = std::env::var("TARGET").unwrap();
72
73 let arch = if target.contains("x86_64") {
74 "x64"
75 } else if target.contains("i686") {
76 "x86"
77 } else {
78 panic!("The target {} is currently not supported.", target);
79 };
80
81 let dir = dir.join(arch);
82
83 println!("cargo:rustc-link-search=native={}", dir.to_str().unwrap());
85
86 println!("cargo:rustc-link-arg=/NODEFAULTLIB");
88 println!("cargo:rustc-link-arg=/SUBSYSTEM:NATIVE");
89 println!("cargo:rustc-link-arg=/DRIVER");
90 println!("cargo:rustc-link-arg=/DYNAMICBASE");
91 println!("cargo:rustc-link-arg=/MANIFEST:NO");
92 println!("cargo:rustc-link-arg=/ENTRY:driver_entry");
93 println!("cargo:rustc-link-arg=/MERGE:.edata=.rdata");
94 println!("cargo:rustc-link-arg=/MERGE:.rustc=.data");
95 println!("cargo:rustc-link-arg=/INTEGRITYCHECK");
96
97 Ok(())
98}
99
100
101pub fn get_km_dir_path(windows_kits_dir: &PathBuf) -> Result<PathBuf, failure::Error> {
105 let readdir = Path::new(windows_kits_dir).join("lib").read_dir()?;
106
107 let max_libdir = readdir
108 .filter_map(|dir| dir.ok())
109 .map(|dir| dir.path())
110 .filter(|dir| {
111 dir.components()
112 .last()
113 .and_then(|c| c.as_os_str().to_str())
114 .map(|c| c.starts_with("10.") && dir.join("km").is_dir())
115 .unwrap_or(false)
116 })
117 .max()
118 .ok_or_else(|| format_err!("Can not find a valid km dir in `{:?}`", windows_kits_dir))?;
119
120 Ok(max_libdir.join("km"))
121}
122
123
124pub fn internal_link_search() {
144 let windows_kits_dir = get_windows_kits_dir().unwrap();
145 let km_dir = get_km_dir_path(&windows_kits_dir).unwrap();
146 let target = var("TARGET").unwrap();
147
148 let arch = if target.contains("x86_64") {
149 "x64"
150 } else if target.contains("i686") {
151 "x86"
152 } else {
153 panic!("Only support x86_64 and i686!");
154 };
155
156 let lib_dir = km_dir.join(arch);
157 println!(
158 "cargo:rustc-link-search=native={}",
159 lib_dir.to_str().unwrap()
160 );
161 println!("cargo:rustc-link-lib=msvcrt");
162}
163
164
165pub fn extra_link_search() {}
167
168
169pub fn build_driver() {
180 if var(format!(
181 "CARGO_FEATURE_{}",
182 "extra_link_search".to_uppercase()
183 ))
184 .is_ok()
185 {
186 extra_link_search()
187 } else {
188 internal_link_search()
189 }
190}
191