🌱 尝试检测管理员&以管理员模式重启

This commit is contained in:
BTMuli
2025-12-01 23:09:06 +08:00
committed by 目棃
parent 93be279cbb
commit 14c47369e7
8 changed files with 223 additions and 32 deletions

View File

@@ -36,14 +36,14 @@ walkdir = "2.5.0"
[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.61.2"
features = [
"Win32_System_Diagnostics_ToolHelp",
"Win32_System_WindowsProgramming",
"Win32_System_Pipes",
"Win32_System_Memory",
"Win32_System_Diagnostics",
"Win32_System_Diagnostics_Debug",
"Win32_System_Diagnostics_ToolHelp",
"Win32_System_LibraryLoader",
"Win32_System_Memory",
"Win32_System_Pipes",
"Win32_System_Threading",
"Win32_System_WindowsProgramming",
]
# deep link 插件

View File

@@ -70,3 +70,81 @@ pub async fn get_dir_size(path: String) -> u64 {
}
size
}
// 判断是否是管理员权限
#[cfg(target_os = "windows")]
#[tauri::command]
pub fn is_in_admin() -> bool {
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Security::{
AllocateAndInitializeSid, CheckTokenMembership, FreeSid, SID_IDENTIFIER_AUTHORITY, TOKEN_QUERY,
};
use windows_sys::Win32::System::SystemServices::{
DOMAIN_ALIAS_RID_ADMINS, SECURITY_BUILTIN_DOMAIN_RID,
};
use windows_sys::Win32::System::Threading::{GetCurrentProcess, OpenProcessToken};
unsafe {
let mut token_handle: HANDLE = std::ptr::null_mut();
if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut token_handle) != 0 {
let nt_authority = SID_IDENTIFIER_AUTHORITY { Value: [0, 0, 0, 0, 0, 5] };
let mut admin_group = std::ptr::null_mut();
if AllocateAndInitializeSid(
&nt_authority,
2,
SECURITY_BUILTIN_DOMAIN_RID.try_into().unwrap(),
DOMAIN_ALIAS_RID_ADMINS.try_into().unwrap(),
0,
0,
0,
0,
0,
0,
&mut admin_group,
) != 0
{
let mut is_admin = 0i32;
CheckTokenMembership(std::ptr::null_mut(), admin_group, &mut is_admin);
FreeSid(admin_group);
return is_admin != 0;
}
}
false
}
}
// 在 Windows 上以管理员权限重启应用
#[cfg(target_os = "windows")]
#[tauri::command]
pub fn run_with_admin() -> Result<(), String> {
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
use std::process::exit;
use windows_sys::Win32::UI::Shell::ShellExecuteW;
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
let exe_path = std::env::current_exe().map_err(|e| e.to_string())?;
let exe_str: Vec<u16> = OsStr::new(exe_path.to_string_lossy().as_ref())
.encode_wide()
.chain(std::iter::once(0))
.collect();
let verb: Vec<u16> = OsStr::new("runas").encode_wide().chain(once(0)).collect();
let result = unsafe {
ShellExecuteW(
std::ptr::null_mut(),
verb.as_ptr(),
exe_str.as_ptr(),
std::ptr::null(),
std::ptr::null(),
SW_SHOWNORMAL,
)
};
if result as usize > 32 {
exit(0);
} else {
Err("Failed to restart as administrator.".into())
}
}

View File

@@ -8,7 +8,9 @@ mod utils;
mod yae;
use crate::client::create_mhy_client;
use crate::commands::{create_window, execute_js, get_dir_size, init_app};
use crate::commands::{
create_window, execute_js, get_dir_size, init_app, is_in_admin, run_with_admin,
};
use crate::plugins::{build_log_plugin, build_si_plugin};
use crate::yae::call_yae_dll;
use tauri::{generate_context, generate_handler, Builder, Manager, Window, WindowEvent};
@@ -63,7 +65,9 @@ pub fn run() {
execute_js,
get_dir_size,
create_mhy_client,
call_yae_dll
call_yae_dll,
is_in_admin,
run_with_admin
])
.run(generate_context!())
.expect("error while running tauri application");

View File

@@ -6,17 +6,15 @@ pub mod proto;
use inject::{call_yaemain, create_named_pipe, find_module_base, inject_dll, spawn_process};
use prost::encoding::{decode_key, WireType};
use prost::Message;
use proto::{parse_achi_list, AchievementInfo};
use proto::parse_achi_list;
use serde_json::Value;
use std::collections::HashMap;
use std::fs::File;
use std::io;
use std::io::{Read, Write};
use std::os::windows::io::{FromRawHandle, OwnedHandle, RawHandle};
use std::os::windows::io::{FromRawHandle, RawHandle};
use std::sync::Arc;
use tauri::{AppHandle, Emitter, Manager};
use windows_sys::Win32::Storage::FileSystem::ReadFile;
use windows_sys::Win32::System::Pipes::ConnectNamedPipe;
// 读取配置值
@@ -79,8 +77,6 @@ pub fn parse_achievement_data(bytes: &[u8]) -> Vec<HashMap<u32, u32>> {
data
}
use windows_sys::Win32::Foundation::{GetLastError, ERROR_MORE_DATA};
fn read_u32_le<R: Read>(r: &mut R) -> io::Result<u32> {
let mut buf = [0u8; 4];
match r.read_exact(&mut buf) {

View File

@@ -106,15 +106,15 @@ pub struct AchievementInfo {
}
#[derive(Debug, Default, Serialize)]
pub struct AchievementEntry {
pub struct AchiItemRes {
pub id: u32,
pub total_progress: u32,
pub current_progress: u32,
pub finish_timestamp: u32,
pub status: u32, // 数值类型
pub total: u32,
pub cur: u32,
pub ts: u32,
pub stat: u32,
}
pub fn parse_achi_list(bytes: &[u8]) -> Result<Vec<AchievementEntry>, DecodeError> {
pub fn parse_achi_list(bytes: &[u8]) -> Result<Vec<AchiItemRes>, DecodeError> {
let mut cursor = Cursor::new(bytes);
let mut dicts: Vec<HashMap<u32, u32>> = Vec::new();
@@ -146,12 +146,12 @@ pub fn parse_achi_list(bytes: &[u8]) -> Result<Vec<AchievementEntry>, DecodeErro
let achievements = dicts
.into_iter()
.map(|d| AchievementEntry {
.map(|d| AchiItemRes {
id: d.get(&15).copied().unwrap_or(0),
status: d.get(&11).copied().unwrap_or(0),
total_progress: d.get(&8).copied().unwrap_or(0),
current_progress: d.get(&13).copied().unwrap_or(0),
finish_timestamp: d.get(&7).copied().unwrap_or(0),
stat: d.get(&11).copied().unwrap_or(0),
total: d.get(&8).copied().unwrap_or(0),
cur: d.get(&13).copied().unwrap_or(0),
ts: d.get(&7).copied().unwrap_or(0),
})
.collect();