Add initial network scan code

This commit is contained in:
2Shirt 2025-11-28 19:25:53 -08:00
parent cf3d71567e
commit a760773269
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
8 changed files with 144 additions and 15 deletions

16
Cargo.lock generated
View file

@ -3145,6 +3145,7 @@ dependencies = [
"tracing-error",
"tracing-subscriber",
"vergen-gix",
"windows-sys 0.61.2",
"xml",
]
@ -3198,6 +3199,12 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.52.0"
@ -3216,6 +3223,15 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.48.5"

View file

@ -213,4 +213,8 @@
"<Ctrl-z>": "Suspend"
},
},
"network_server": "SERVER",
"network_share": "SHARE",
"network_user": "USER",
"network_pass": "PASS"
}

View file

@ -54,6 +54,14 @@ pub struct Config {
pub keybindings: KeyBindings,
#[serde(default)]
pub styles: Styles,
#[serde(default)]
pub network_server: String,
#[serde(default)]
pub network_share: String,
#[serde(default)]
pub network_user: String,
#[serde(default)]
pub network_pass: String,
}
pub static PROJECT_NAME: &str = "DEJA-VU";
@ -76,16 +84,14 @@ impl Config {
let config_dir = get_config_dir();
let mut builder = config::Config::builder()
.set_default("app_title", default_config.app_title.as_str())?
.set_default(
"clone_app_path",
String::from("C:\\Program Files\\Some Clone Tool\\app.exe"),
)?
.set_default(
"conemu_path",
String::from("C:\\Program Files\\ConEmu\\ConEmu64.exe"),
)?
.set_default("clone_app_path", default_config.app_title.as_str())?
.set_default("conemu_path", default_config.app_title.as_str())?
.set_default("config_dir", config_dir.to_str().unwrap())?
.set_default("data_dir", data_dir.to_str().unwrap())?;
.set_default("data_dir", data_dir.to_str().unwrap())?
.set_default("network_server", default_config.app_title.as_str())?
.set_default("network_share", default_config.app_title.as_str())?
.set_default("network_user", default_config.app_title.as_str())?
.set_default("network_pass", default_config.app_title.as_str())?;
let config_files = [
("config.json5", config::FileFormat::Json5),

View file

@ -41,6 +41,7 @@ tracing = "0.1.41"
tracing-error = "0.2.0"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "serde"] }
tempfile = "3.23.0"
windows-sys = { version = "0.61.1", features = ["Win32_NetworkManagement_WNet"] }
xml = "1.1.0"
[build-dependencies]

View file

@ -67,9 +67,10 @@ pub struct App {
impl App {
pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> {
let (action_tx, action_rx) = mpsc::unbounded_channel();
let config = Config::new()?;
let disk_list_arc = Arc::new(Mutex::new(Vec::new()));
let tasks = Tasks::new(action_tx.clone(), disk_list_arc.clone());
let state = State::new(disk_list_arc);
let state = State::new(config.clone(), disk_list_arc);
let wim_sources = Arc::clone(&state.wim_sources);
Ok(Self {
// TUI
@ -83,7 +84,7 @@ impl App {
Box::new(Footer::new()),
Box::new(popup::Popup::new()),
],
config: Config::new()?,
config,
frame_rate,
last_tick_key_events: Vec::new(),
should_quit: false,
@ -284,7 +285,7 @@ impl App {
}
Action::FindWimNetwork => {
self.state.reset_network();
// TODO: Actually scan network!
self.state.scan_wim_network();
}
Action::NextScreen => {
let next_mode = self.next_mode();

View file

@ -20,6 +20,7 @@ use crate::app::App;
mod app;
mod components;
mod net;
mod state;
mod wim;

68
win_installer/src/net.rs Normal file
View file

@ -0,0 +1,68 @@
// This file is part of Deja-Vu.
//
// Deja-Vu is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Deja-Vu is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Deja-Vu. If not, see <https://www.gnu.org/licenses/>.
//
//#![windows_subsystem = "windows"]
use std::ffi::CString;
use windows_sys::Win32::Foundation::NO_ERROR;
use windows_sys::Win32::NetworkManagement::WNet;
fn to_cstr(s: &str) -> CString {
CString::new(s).unwrap()
}
pub fn connect_network_share(
server: &str,
share: &str,
username: &str,
password: &str,
) -> Result<(), u32> {
let remote_name = to_cstr(&format!("\\\\{server}\\{share}"));
// init resources
let mut resources = WNet::NETRESOURCEA {
dwDisplayType: WNet::RESOURCEDISPLAYTYPE_SHAREADMIN,
dwScope: WNet::RESOURCE_GLOBALNET,
dwType: WNet::RESOURCETYPE_DISK,
dwUsage: WNet::RESOURCEUSAGE_ALL,
lpComment: std::ptr::null_mut(),
lpLocalName: std::ptr::null_mut(), // PUT a volume here if you want to mount as a windows volume
lpProvider: std::ptr::null_mut(),
lpRemoteName: remote_name.as_c_str().as_ptr() as *mut u8,
};
let username = to_cstr(username);
let password = to_cstr(password);
// mount
let result = unsafe {
let username_ptr = username.as_ptr();
let password_ptr = password.as_ptr();
WNet::WNetAddConnection2A(
&mut resources as *mut WNet::NETRESOURCEA,
password_ptr as *const u8,
username_ptr as *const u8,
//WNet::CONNECT_INTERACTIVE, // Interactive will show a system dialog in case credentials are wrong to retry with the password. Put 0 if you don't want it
0,
)
};
if result == NO_ERROR {
Ok(())
} else {
Err(result)
}
}

View file

@ -38,6 +38,7 @@ use crate::{
#[derive(Debug, Default)]
pub struct State {
pub config: Config,
pub disk_index_dest: Option<usize>,
pub disk_list: Arc<Mutex<Vec<Disk>>>,
pub driver: Option<drivers::Driver>,
@ -49,11 +50,12 @@ pub struct State {
}
impl State {
pub fn new(disk_list: Arc<Mutex<Vec<Disk>>>) -> Self {
let wim_sources = WimSources::new();
pub fn new(config: Config, disk_list: Arc<Mutex<Vec<Disk>>>) -> Self {
let wim_sources = Arc::new(Mutex::new(WimSources::new()));
State {
config,
disk_list,
wim_sources: Arc::new(Mutex::new(wim_sources)),
wim_sources,
..Default::default()
}
}
@ -85,6 +87,16 @@ impl State {
});
}
pub fn scan_wim_network(&mut self) {
let config = self.config.clone();
let disk_list_arc = self.disk_list.clone();
let wim_sources_arc = self.wim_sources.clone();
tokio::task::spawn(async move {
scan_network_share(config, disk_list_arc, wim_sources_arc);
});
}
}
pub fn scan_local_drives(
disk_list_arc: Arc<Mutex<Vec<Disk>>>,
wim_sources_arc: Arc<Mutex<WimSources>>,
@ -119,4 +131,24 @@ pub fn scan_local_drives(
}
});
}
pub fn scan_network_share(
config: Config,
disk_list_arc: Arc<Mutex<Vec<Disk>>>,
wim_sources_arc: Arc<Mutex<WimSources>>,
) {
let result = connect_network_share(
&config.network_server,
&config.network_share,
&config.network_user,
&config.network_pass,
);
// Connect to share
if result.is_err() {
return;
}
// Scan share
let _ = 14;
}