use std::{
fs,
io::{Read, Write as _},
path::{Path, PathBuf},
};
use e_utils::{
parse::{AutoPath, MyParseFormat},
system::cmd,
};
use regex::Regex;
use crate::share::{default_cmd_res, CmdRes, SYSTEM_WIN32};
#[derive(Debug, Clone)]
pub enum ActiveLocalType {
Temp(String),
}
#[derive(PartialEq, Clone, Debug)]
pub enum OfficeVersion {
V2003,
V2006,
V2010,
V2013,
V2016,
V2019,
V365,
None,
}
impl OfficeVersion {
pub fn find_version(version: OfficeVersion, l: &Vec<(Self, PathBuf)>) -> (Self, PathBuf) {
for x in l {
if x.0 == version {
return x.clone();
}
}
(Self::None, PathBuf::new())
}
pub fn license_path(&self) -> Option<PathBuf> {
Some(
Path::new(match self {
OfficeVersion::V2003 => "C:\\Program Files\\Microsoft Office\\root\\Licenses3",
OfficeVersion::V2006 => "C:\\Program Files\\Microsoft Office\\root\\Licenses6",
OfficeVersion::V2010 => "C:\\Program Files\\Microsoft Office\\root\\Licenses10",
OfficeVersion::V2013 => "C:\\Program Files\\Microsoft Office\\root\\Licenses13",
OfficeVersion::V2016 => "C:\\Program Files\\Microsoft Office\\root\\Licenses16",
OfficeVersion::V2019 => "C:\\Program Files\\Microsoft Office\\root\\Licenses19",
OfficeVersion::V365 => "C:\\Program Files\\Microsoft Office\\root\\Licenses365",
OfficeVersion::None => return None,
})
.to_path_buf(),
)
}
}
pub fn clean_cache(save_type: ActiveLocalType) -> CmdRes {
let mut outres = default_cmd_res();
match save_type {
ActiveLocalType::Temp(fname) => {
if let Ok(tmp) = "%TEMP%".parse_env() {
let path = Path::new(&tmp).join(&format!("os-key-{fname}"));
if (path.exists() && path.auto_remove_file().is_ok()) || !path.exists() {
outres.content = format!("清除本地激活码");
outres.status = true;
}
}
}
}
outres
}
pub fn query_cache(save_type: ActiveLocalType) -> CmdRes {
let mut outres = default_cmd_res();
match save_type {
ActiveLocalType::Temp(fname) => {
if let Ok(tmp) = "%temp%".parse_env() {
let path = Path::new(&tmp).join(&format!("os-key-{fname}"));
if path.exists() {
if let Ok(mut f) = fs::OpenOptions::new().read(true).open(path) {
let mut sbuf = String::new();
if f.read_to_string(&mut sbuf).is_ok() && sbuf.len() > 3 {
outres.status = true;
}
outres.content = sbuf;
}
}
}
}
}
outres
}
pub fn check_os_active() -> CmdRes {
let mut outres = default_cmd_res();
match cmd(
"cscript",
["/nologo", "slmgr.vbs", "-xpr"],
Some(Path::new(SYSTEM_WIN32).to_path_buf()),
false,
false,
) {
Ok(output) => {
let output = output.stdout;
if output.contains("激活") || output.contains("activated") {
outres.status = true;
}
outres.content = output
}
Err(e) => outres.content = e.to_string(),
}
outres
}
pub fn active_os(product_key: &str, save_type: ActiveLocalType) -> CmdRes {
let mut outres = default_cmd_res();
if let Ok(re) = Regex::new(r"^[0-9A-Z]{5}-(?:[0-9A-Z]{5}-){3}[0-9A-Z]{5}$") {
if !re.is_match(product_key) {
outres.content = format!("Error: Active Code of Rule,Please check;{product_key}");
return outres;
}
}
match cmd(
"cscript",
["/nologo", "slmgr.vbs", "/ipk", product_key],
Some(Path::new(SYSTEM_WIN32).to_path_buf()),
false,
false,
) {
Ok(output) => {
match cmd(
"cscript",
["/nologo", "slmgr.vbs", "/ato"],
Some(Path::new(SYSTEM_WIN32).to_path_buf()),
false,
false,
) {
Ok(o2) => {
if o2.stdout.contains("激活") || o2.stdout.contains("activated") {
outres.status = true;
match save_type {
ActiveLocalType::Temp(fname) => {
if let Ok(tmp) = "%TEMP%".parse_env() {
let path = Path::new(&tmp).join(&format!("os-key-{fname}"));
if let Ok(mut f) = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)
{
let _ = f.write(product_key.as_bytes());
}
}
}
}
}
outres.content = format!("{};{}", output.stdout, o2.stdout)
}
Err(e) => outres.content = format!("Error: Active Code: {product_key};{e}"),
}
}
Err(e) => outres.content = format!("Error: Install Product Active Code: {product_key};{e}"),
}
outres
}
pub fn deactivate_os() -> CmdRes {
let mut outres = default_cmd_res();
match cmd(
"cscript",
["/nologo", "slmgr.vbs", "/upk"],
Some(Path::new(SYSTEM_WIN32).to_path_buf()),
false,
false,
) {
Ok(x1) => {
match cmd(
"cscript",
["/nologo", "slmgr.vbs", "/cpky"],
Some(Path::new(SYSTEM_WIN32).to_path_buf()),
false,
false,
) {
Ok(x2) => {
match cmd(
"cscript",
["/nologo", "slmgr.vbs", "/rearm"],
Some(Path::new(SYSTEM_WIN32).to_path_buf()),
false,
false,
) {
Ok(x3) => {
outres.content = format!("{};{};{}", x1.stdout, x2.stdout, x3.stdout);
outres.status = true;
}
Err(e) => {
outres.content =
format!("Error: Optionally, remove the product key from the registry;{e}")
}
}
}
Err(e) => {
outres.content =
format!("Error: Optionally, remove the product key from the registry;{e}")
}
}
}
Err(e) => outres.content = format!("Error: Uninstall the product key;{e}"),
}
outres
}
pub fn register_kms(server: &str) -> CmdRes {
let mut outres = default_cmd_res();
match cmd(
"cscript",
["/nologo", "slmgr.vbs", "/skms", server],
Some(Path::new(SYSTEM_WIN32).to_path_buf()),
false,
false,
) {
Ok(x) => {
outres.content = format!("{}", x.stdout);
outres.status = true;
}
Err(e) => outres.content = format!("Error: registry KMS {server};{e}"),
}
outres
}
pub fn clear_kms() -> CmdRes {
let mut outres = default_cmd_res();
let cwd = Path::new(SYSTEM_WIN32).to_path_buf();
match cmd(
"cscript",
["/nologo", "slmgr.vbs", "/ckms"],
Some(cwd),
false,
false,
) {
Ok(x) => {
outres.content = format!("{}", x.stdout);
outres.status = true;
}
Err(e) => outres.content = format!("Error: Clear KMS;{e}"),
}
outres
}
pub fn check_office(v: OfficeVersion) -> CmdRes {
let mut outres = default_cmd_res();
let olist = check_office_dir().unwrap_or_default();
let office = OfficeVersion::find_version(v, &olist);
match office.0 {
OfficeVersion::None => {
outres.content = format!("Error: Check Office Not Found {}", office.1.display())
}
_ => {
let exe = "ospp.vbs";
let exe_path = office.1.join(exe);
if exe_path.exists() {
match cmd(
"cscript",
["/nologo", exe, "/dstatus"],
Some(office.1),
false,
false,
) {
Ok(x) => {
if x.stdout.contains("LICENSE STATUS: ---LICENSED---") {
outres.status = true;
}
outres.content = format!("{}", x.stdout);
}
Err(e) => outres.content = format!("Error: Office check;{e}"),
}
} else {
outres.content = format!("Error: Check Office Not Found {}", exe_path.display());
}
}
}
outres
}
pub fn register_office_kms(v: OfficeVersion, server: &str) -> CmdRes {
let mut outres = default_cmd_res();
let olist = check_office_dir().unwrap_or_default();
let office = OfficeVersion::find_version(v, &olist);
match office.0 {
OfficeVersion::None => outres.content = format!("Error: Check Office Not Found"),
_ => {
let exe = "ospp.vbs";
let exe_path = office.1.join(exe);
if exe_path.exists() {
match cmd(
"cscript",
["/nologo", exe, &format!("/sethst:{server}")],
Some(office.1),
false,
false,
) {
Ok(x) => {
outres.status = true;
outres.content = format!("{}", x.stdout);
}
Err(e) => outres.content = format!("Error: Office set KMS: {server};{e}"),
}
} else {
outres.content = format!("Error: Check Office Not Found {}", exe_path.display());
}
}
}
outres
}
pub fn active_office(v: OfficeVersion) -> CmdRes {
let mut outres = default_cmd_res();
let olist = check_office_dir().unwrap_or_default();
let office = OfficeVersion::find_version(v, &olist);
match office.0 {
OfficeVersion::None => outres.content = format!("Error: Check Office Not Found"),
_ => {
let exe = "ospp.vbs";
let exe_path = office.1.join(exe);
if exe_path.exists() {
match cmd(
"cscript",
["/nologo", exe, &format!("/act")],
Some(office.1),
false,
false,
) {
Ok(x2) => {
if let Ok(re) = Regex::new("(successful|成功)") {
if re.is_match(&x2.stdout) {
outres.status = true;
}
}
outres.content = format!("{}", x2.stdout);
}
Err(e) => outres.content = format!("Error: Active Office;{e}"),
}
} else {
outres.content = format!("Error: Check Office Not Found {}", exe_path.display());
}
}
}
outres
}
fn check_office_dir() -> Option<Vec<(OfficeVersion, PathBuf)>> {
let p = Path::new("C:\\Program Files\\Microsoft Office");
let mut l = vec![];
if p.exists() {
for x in p.read_dir().ok()? {
if let Ok(dir) = x {
let s = &*dir.file_name().to_string_lossy().to_string();
let x = match s {
"Office2003" => OfficeVersion::V2003,
"Office2006" => OfficeVersion::V2006,
"Office2010" => OfficeVersion::V2010,
"Office2013" => OfficeVersion::V2013,
"Office2016" => OfficeVersion::V2016,
"Office2019" => OfficeVersion::V2019,
"Office365" => OfficeVersion::V365,
_ => OfficeVersion::None,
};
if x != OfficeVersion::None {
l.push((x, dir.path()));
}
}
}
}
Some(l)
}