simple_rc: win init simple resource pack

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou
2022-04-24 23:39:15 +08:00
parent e1bb25c70e
commit 2081113bed
13 changed files with 444 additions and 83 deletions

13
libs/simple_rc/Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "simple_rc"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde_derive = "1.0"
serde = "1.0"
walkdir = "2"
confy = { git = "https://github.com/open-trade/confy" }
hbb_common = { path = "../hbb_common" }

View File

@@ -0,0 +1,23 @@
extern crate simple_rc;
use simple_rc::*;
fn main() {
{
const CONF_FILE: &str = "simple_rc.toml";
generate(CONF_FILE).unwrap();
}
{
generate_with_conf(&Config {
outfile: "src/rc.rs".to_owned(),
confs: vec![ConfigItem {
inc: "D:/projects/windows/RustDeskTempTopMostWindow/x64/Release/xxx".to_owned(),
// exc: vec!["*.dll".to_owned(), "*.exe".to_owned()],
exc: vec![],
suppressed_front: "D:/projects/windows".to_owned(),
}],
})
.unwrap();
}
}

View File

@@ -0,0 +1,12 @@
# The output source file
outfile = "src/rc.rs"
# The resource config list.
[[confs]]
# The file or director to integrate.
inc = "D:/projects/windows/RustDeskTempTopMostWindow/x64/Release/xxx"
# The exclusions.
exc = ["*.dll", "*.exe"]
# The front path that will ignore for extracting.
# The following config will make base output path to be "RustDeskTempTopMostWindow/x64/Release/xxx".
suppressed_front = "D:/projects/windows"

208
libs/simple_rc/src/lib.rs Normal file
View File

@@ -0,0 +1,208 @@
use hbb_common::{bail, ResultType};
use serde_derive::{Deserialize, Serialize};
use std::{collections::HashMap, fs::File, io::prelude::*, path::Path};
use walkdir::WalkDir;
//mod rc;
#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
pub struct ConfigItem {
// include directory or file
pub inc: String,
// exclude files
pub exc: Vec<String>,
// out_path = origin_path - suppressed_front
pub suppressed_front: String,
}
#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
pub struct Config {
// output source file
pub outfile: String,
// config items
pub confs: Vec<ConfigItem>,
}
pub fn get_outin_files<'a>(item: &'a ConfigItem) -> ResultType<HashMap<String, String>> {
let mut outin_filemap = HashMap::new();
for entry in WalkDir::new(&item.inc).follow_links(true) {
let path = entry?.into_path();
if path.is_file() {
let mut exclude = false;
for excfile in item.exc.iter() {
if excfile.starts_with("*.") {
if let Some(ext) = path.extension().and_then(|x| x.to_str()) {
if excfile.ends_with(&format!(".{}", ext)) {
exclude = true;
break;
}
}
} else {
if path.ends_with(Path::new(excfile)) {
exclude = true;
break;
}
}
}
if exclude {
continue;
}
let mut suppressed_front = item.suppressed_front.clone();
if !suppressed_front.is_empty() && suppressed_front.ends_with('/') {
suppressed_front.push('/');
}
let outpath = path.strip_prefix(Path::new(&suppressed_front))?;
let outfile = if outpath.is_absolute() {
match outpath
.file_name()
.and_then(|f| f.to_str())
.map(|f| f.to_string())
{
None => {
bail!("Failed to get filename of {}", outpath.display());
}
Some(s) => s,
}
} else {
match outpath.to_str() {
None => {
bail!("Failed to convert {} to string", outpath.display());
}
// Simple replace \ to / here.
// A better way is to use lib [path-slash](https://github.com/rhysd/path-slash)
Some(s) => s.to_string().replace("\\", "/"),
}
};
let infile = match path.canonicalize()?.to_str() {
None => {
bail!("Failed to get file path of {}", path.display());
}
Some(s) => s.to_string(),
};
if let Some(_) = outin_filemap.insert(outfile.clone(), infile) {
bail!("outfile {} is set before", outfile);
}
}
}
Ok(outin_filemap)
}
pub fn generate(conf_file: &str) -> ResultType<()> {
let conf = confy::load_path(conf_file)?;
generate_with_conf(&conf)?;
Ok(())
}
pub fn generate_with_conf<'a>(conf: &'a Config) -> ResultType<()> {
let mut outfile = File::create(&conf.outfile)?;
outfile.write(
br##"use hbb_common::{bail, ResultType};
use std::{
fs::{self, File},
io::prelude::*,
path::Path,
};
"##,
)?;
outfile.write(b"#[allow(dead_code)]\n")?;
outfile.write(b"pub fn extract_resources(root_path: &str) -> ResultType<()> {\n")?;
outfile.write(b" let mut resources: Vec<(&str, &[u8])> = Vec::new();\n")?;
let mut outin_files = HashMap::new();
for item in conf.confs.iter() {
for (o, i) in get_outin_files(item)?.into_iter() {
if let Some(_) = outin_files.insert(o.clone(), i) {
bail!("outfile {} is set before", o);
}
}
}
let mut count = 1;
for (o, i) in outin_files.iter() {
let mut infile = File::open(&i)?;
let mut buffer = Vec::<u8>::new();
infile.read_to_end(&mut buffer)?;
let var_outfile = format!("outfile_{}", count);
let var_outdata = format!("outdata_{}", count);
write!(outfile, " let {} = \"{}\";\n", var_outfile, o)?;
write!(outfile, " let {}: &[u8] = &[\n ", var_outdata)?;
let mut line_num = 20;
for v in buffer {
if line_num == 0 {
write!(outfile, "\n ")?;
line_num = 20;
}
write!(outfile, "{:#04x}, ", v)?;
line_num -= 1;
}
write!(outfile, "\n ];\n")?;
write!(
outfile,
" resources.push(({}, &{}));\n",
var_outfile, var_outdata
)?;
count += 1;
}
outfile.write(b" do_extract(root_path, resources)?;\n")?;
outfile.write(b" Ok(())\n")?;
outfile.write(b"}\n")?;
outfile.write(
br##"
#[allow(dead_code)]
fn do_extract(root_path: &str, resources: Vec<(&str, &[u8])>) -> ResultType<()> {
let mut root_path = root_path.replace("\\", "/");
if !root_path.ends_with('/') {
root_path.push('/');
}
let root_path = Path::new(&root_path);
for (outfile, data) in resources {
let outfile_path = root_path.join(outfile);
match outfile_path.parent().and_then(|p| p.to_str()) {
None => {
bail!("Failed to get parent of {}", outfile_path.display());
}
Some(p) => {
fs::create_dir_all(p)?;
let mut of = File::create(outfile_path)?;
of.write_all(data)?;
of.flush()?;
}
}
}
Ok(())
}
"##,
)?;
outfile.flush()?;
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
// #[test]
// fn test_extract() {
// use super::*;
// rc::extract_resources("D:").unwrap();
// }
}

View File

@@ -1,12 +1,14 @@
#[cfg(windows)]
use virtual_display::win10::{idd, DRIVER_INSTALL_PATH};
#[cfg(windows)]
use std::{
ffi::CStr,
io::{self, Read},
path::Path,
};
#[cfg(windows)]
fn prompt_input() -> u8 {
println!("Press key execute:");
println!(" 1. 'x' 1. exit");
@@ -24,6 +26,7 @@ fn prompt_input() -> u8 {
.unwrap_or(0)
}
#[cfg(windows)]
unsafe fn plug_in(index: idd::UINT, edid: idd::UINT) {
println!("Plug in monitor begin");
if idd::FALSE == idd::MonitorPlugIn(index, edid, 25) {
@@ -48,6 +51,7 @@ unsafe fn plug_in(index: idd::UINT, edid: idd::UINT) {
}
}
#[cfg(windows)]
unsafe fn plug_out(index: idd::UINT) {
println!("Plug out monitor begin");
if idd::FALSE == idd::MonitorPlugOut(index) {
@@ -58,88 +62,91 @@ unsafe fn plug_out(index: idd::UINT) {
}
fn main() {
let abs_path = Path::new(DRIVER_INSTALL_PATH).canonicalize().unwrap();
#[cfg(windows)]
{
let abs_path = Path::new(DRIVER_INSTALL_PATH).canonicalize().unwrap();
unsafe {
let invalid_device = 0 as idd::HSWDEVICE;
let mut h_sw_device = invalid_device;
unsafe {
let invalid_device = 0 as idd::HSWDEVICE;
let mut h_sw_device = invalid_device;
let full_inf_path: Vec<u16> = abs_path
.to_string_lossy()
.as_ref()
.encode_utf16()
.chain(Some(0).into_iter())
.collect();
let full_inf_path: Vec<u16> = abs_path
.to_string_lossy()
.as_ref()
.encode_utf16()
.chain(Some(0).into_iter())
.collect();
loop {
match prompt_input() as char {
'x' => break,
'i' => {
println!("Install or update driver begin, {}", abs_path.display());
let mut reboot_required = idd::FALSE;
if idd::InstallUpdate(full_inf_path.as_ptr() as _, &mut reboot_required)
== idd::FALSE
{
println!("{}", CStr::from_ptr(idd::GetLastMsg()).to_str().unwrap());
} else {
println!(
"Install or update driver done, reboot is {} required",
if reboot_required == idd::FALSE {
"not"
} else {
""
}
);
loop {
match prompt_input() as char {
'x' => break,
'i' => {
println!("Install or update driver begin, {}", abs_path.display());
let mut reboot_required = idd::FALSE;
if idd::InstallUpdate(full_inf_path.as_ptr() as _, &mut reboot_required)
== idd::FALSE
{
println!("{}", CStr::from_ptr(idd::GetLastMsg()).to_str().unwrap());
} else {
println!(
"Install or update driver done, reboot is {} required",
if reboot_required == idd::FALSE {
"not"
} else {
""
}
);
}
}
}
'u' => {
println!("Uninstall driver begin {}", abs_path.display());
let mut reboot_required = idd::FALSE;
if idd::Uninstall(full_inf_path.as_ptr() as _, &mut reboot_required)
== idd::FALSE
{
println!("{}", CStr::from_ptr(idd::GetLastMsg()).to_str().unwrap());
} else {
println!(
"Uninstall driver done, reboot is {} required",
if reboot_required == idd::FALSE {
"not"
} else {
""
}
);
'u' => {
println!("Uninstall driver begin {}", abs_path.display());
let mut reboot_required = idd::FALSE;
if idd::Uninstall(full_inf_path.as_ptr() as _, &mut reboot_required)
== idd::FALSE
{
println!("{}", CStr::from_ptr(idd::GetLastMsg()).to_str().unwrap());
} else {
println!(
"Uninstall driver done, reboot is {} required",
if reboot_required == idd::FALSE {
"not"
} else {
""
}
);
}
}
}
'c' => {
println!("Create device begin");
if h_sw_device != invalid_device {
println!("Device created before");
continue;
'c' => {
println!("Create device begin");
if h_sw_device != invalid_device {
println!("Device created before");
continue;
}
if idd::FALSE == idd::DeviceCreate(&mut h_sw_device) {
println!("{}", CStr::from_ptr(idd::GetLastMsg()).to_str().unwrap());
idd::DeviceClose(h_sw_device);
h_sw_device = invalid_device;
} else {
println!("Create device done");
}
}
if idd::FALSE == idd::DeviceCreate(&mut h_sw_device) {
println!("{}", CStr::from_ptr(idd::GetLastMsg()).to_str().unwrap());
'd' => {
println!("Close device begin");
idd::DeviceClose(h_sw_device);
h_sw_device = invalid_device;
} else {
println!("Create device done");
println!("Close device done");
}
'1' => plug_in(0, 0),
'2' => plug_in(1, 0),
'3' => plug_in(2, 0),
'4' => plug_out(0),
'5' => plug_out(1),
'6' => plug_out(2),
_ => {}
}
'd' => {
println!("Close device begin");
idd::DeviceClose(h_sw_device);
h_sw_device = invalid_device;
println!("Close device done");
}
'1' => plug_in(0, 0),
'2' => plug_in(1, 0),
'3' => plug_in(2, 0),
'4' => plug_out(0),
'5' => plug_out(1),
'6' => plug_out(2),
_ => {}
}
}
idd::DeviceClose(h_sw_device);
idd::DeviceClose(h_sw_device);
}
}
}