5 Commits

Author SHA1 Message Date
amizing25 62a934011b feat: add gitea prebuilt actions
Prebuilt release / prebuilt (push) Successful in 1m42s
2026-07-16 22:59:49 +07:00
amizing25 b559c3b433 chore: remove mhypbase 2026-07-16 22:45:38 +07:00
amizing25 8ed8c7c443 feat: update pattern 2026-07-16 16:56:23 +07:00
amizing25 1ec60097a6 feat: add AccountPlatNative patch for CN SDK auth 2026-06-03 18:47:17 +07:00
amizing25 aec2a1e575 feat(launcher): build executable to require administrator by default
Add rustc-link-arg directives in build.rs to embed a UAC manifest:
- /MANIFEST:EMBED
- /MANIFESTUAC:level='requireAdministrator'
2025-08-22 06:39:39 +07:00
16 changed files with 436 additions and 84 deletions
+99
View File
@@ -0,0 +1,99 @@
name: Prebuilt release
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
releases: write
jobs:
prebuilt:
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install nightly Rust
uses: dtolnay/rust-toolchain@nightly
with:
targets: x86_64-pc-windows-gnu
- name: Install MinGW and packaging tools
run: |
sudo apt-get update
sudo apt-get install -y mingw-w64 zip unzip jq
- name: Build release binaries
env:
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: x86_64-w64-mingw32-gcc
run: cargo build --release --target x86_64-pc-windows-gnu -p ext -p launcher
- name: Package prebuilt release
run: |
set -euo pipefail
rm -rf dist
mkdir -p dist
cp target/x86_64-pc-windows-gnu/release/hkrpg.dll dist/
cp target/x86_64-pc-windows-gnu/release/launcher.exe dist/
test -f dist/hkrpg.dll
test -f dist/launcher.exe
(
cd dist
zip -9 -q ../hkrpg.zip hkrpg.dll launcher.exe
)
unzip -l hkrpg.zip
- name: Publish prebuilt release
env:
GITEA_API_URL: ${{ gitea.server_url }}/api/v1
GITEA_REPOSITORY: ${{ gitea.repository }}
GITEA_SHA: ${{ gitea.sha }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
set -euo pipefail
api="${GITEA_API_URL}"
repo="${GITEA_REPOSITORY}"
tag="prebuilt"
auth=(-H "Authorization: token ${GITEA_TOKEN}" -H "Accept: application/json")
release_status="$(curl -sS "${auth[@]}" -o release.json -w '%{http_code}' \
"${api}/repos/${repo}/releases/tags/${tag}" || true)"
case "${release_status}" in
200)
;;
404)
curl -fsS -X POST "${auth[@]}" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"${tag}\",\"target_commitish\":\"${GITEA_SHA}\",\"name\":\"${tag}\",\"body\":\"Automated prebuilt binaries for ${GITEA_SHA}\",\"draft\":false,\"prerelease\":false}" \
"${api}/repos/${repo}/releases" > release.json
;;
*)
cat release.json
exit 1
;;
esac
release_id="$(jq -er '.id' release.json)"
assets="$(curl -fsS "${auth[@]}" \
"${api}/repos/${repo}/releases/${release_id}/assets")"
while read -r asset_id; do
test -z "${asset_id}" || curl -fsS -X DELETE "${auth[@]}" \
"${api}/repos/${repo}/releases/${release_id}/assets/${asset_id}"
done < <(printf '%s' "${assets}" | jq -r '.[] | select(.name == "hkrpg.zip") | .id')
curl -fsS -X POST "${auth[@]}" \
-F "attachment=@hkrpg.zip;type=application/zip" \
"${api}/repos/${repo}/releases/${release_id}/assets?name=hkrpg.zip"
Generated
+84 -4
View File
@@ -17,6 +17,32 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "dashmap"
version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
dependencies = [
"cfg-if",
"crossbeam-utils",
"hashbrown",
"lock_api",
"once_cell",
"parking_lot_core",
]
[[package]] [[package]]
name = "ext" name = "ext"
version = "0.1.0" version = "0.1.0"
@@ -25,10 +51,17 @@ dependencies = [
"windows", "windows",
] ]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]] [[package]]
name = "hkrpg" name = "hkrpg"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dashmap",
"ilhook", "ilhook",
"patternscan", "patternscan",
"windows", "windows",
@@ -77,6 +110,15 @@ version = "0.2.171"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.4" version = "2.7.4"
@@ -84,11 +126,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]] [[package]]
name = "mhypbase" name = "once_cell"
version = "0.1.0" version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "parking_lot_core"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [ dependencies = [
"hkrpg", "cfg-if",
"windows", "libc",
"redox_syscall",
"smallvec",
"windows-link",
] ]
[[package]] [[package]]
@@ -115,6 +168,15 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "redox_syscall"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.1" version = "1.11.1"
@@ -144,6 +206,18 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.100" version = "2.0.100"
@@ -201,6 +275,12 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]] [[package]]
name = "windows-result" name = "windows-result"
version = "0.1.2" version = "0.1.2"
+8 -1
View File
@@ -1,11 +1,17 @@
[workspace] [workspace]
members = ["hkrpg", "launcher", "mhypbase", "ext"] members = ["hkrpg", "launcher", "ext"]
resolver = "2" resolver = "2"
[workspace.package] [workspace.package]
version = "0.1.0" version = "0.1.0"
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
strip = true
[workspace.dependencies] [workspace.dependencies]
windows = { version = "0.54.0", features = [ windows = { version = "0.54.0", features = [
"Win32_Foundation", "Win32_Foundation",
@@ -22,6 +28,7 @@ windows = { version = "0.54.0", features = [
] } ] }
ilhook = "2.1.1" ilhook = "2.1.1"
patternscan = "1.2.0" patternscan = "1.2.0"
dashmap = "6.1.0"
# Local crates # Local crates
hkrpg = { path = "hkrpg/" } hkrpg = { path = "hkrpg/" }
+2 -2
View File
@@ -3,9 +3,9 @@ features:
- remove censorship - remove censorship
- replace AccountRSAKey into custom public key (by default, compatible with [hoyo-sdk by xeondev](https://git.xeondev.com/reversedrooms/hoyo-sdk)) - replace AccountRSAKey into custom public key (by default, compatible with [hoyo-sdk by xeondev](https://git.xeondev.com/reversedrooms/hoyo-sdk))
currently, this has only been tested on CNBETAWin3.1.53 and may require an update for future versions. currently, this has only been tested on CNBETAWin4.4.51 and may require an update for future versions.
note: if you plan to use `mhypbase.dll`, please make a copy of the original first in case something breaks. Otherwise, simply copy `hkrpg.dll` and `launcher.exe` into the game folder and run `launcher.exe` as an administrator. note: simply copy `hkrpg.dll` and `launcher.exe` into the game folder and run `launcher.exe` as an administrator.
Sources: Sources:
+1
View File
@@ -7,3 +7,4 @@ version.workspace = true
windows.workspace = true windows.workspace = true
ilhook.workspace = true ilhook.workspace = true
patternscan.workspace = true patternscan.workspace = true
dashmap.workspace = true
+9
View File
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudOyZJDKXjYQdUS+wN7d
lKBP2XkhkDO/sx6pttn719o+rJ8y8XOO3rftSoRasvw1nzidDQqEnHl1Aw5+a90D
OQvlgBaIda3npqVmi4X2sEzswR7EH5BOJizx7LAxixcoby3jOQathdpl44wQ04XR
+SIkukvxcL1jTepfuc0Pp+DD+4MU5O4/38b9v+ryizU+1CdwzukV27rkMvOtA6ok
Is6Vkb5ubcAC/W3vCIP5gv+QRdYB6ihzLhs5WI/9Ex2PrLpdpxr7gClvEFxkHcLy
LCvSfp9pvt/tnsYsk1tct0HKEr8tlaJ6t1zEGEvFQZRpBsahl/lhpT15vyM8iyiD
DwIDAQAB
-----END PUBLIC KEY-----
+10 -21
View File
@@ -7,12 +7,10 @@ use crate::util::scan_il2cpp_section;
const IL2CPP_STRING_NEW_LEN: &str = const IL2CPP_STRING_NEW_LEN: &str =
"E8 ? ? ? ? EB ? 31 C0 48 89 06 48 8B 47 ? 48 89 46 ? F2 0F 10 47"; "E8 ? ? ? ? EB ? 31 C0 48 89 06 48 8B 47 ? 48 89 46 ? F2 0F 10 47";
const MAKE_INITIAL_URL: &str = const MAKE_INITIAL_URL: &str =
"E8 ? ? ? ? 48 89 D9 48 89 C2 E8 ? ? ? ? 48 89 D9 4C 89 FA E8 ? ? ? ? 49 89 5D"; // TODO "55 41 56 56 57 53 48 81 EC 90 00 00 00 48 8D AC 24 ? ? ? ? 48 C7 45 ? ? ? ? ? 48 85 C9 74";
const SET_DITHER: &str = "E8 ? ? ? ? 84 C0 75 ? C7 43"; const SET_DITHER: &str = "E8 ? ? ? ? 84 C0 75 ? C7 43";
const SDK_PUBLIC_KEY_LITERAL: &str = const SDK_PUBLIC_KEY_LITERAL: &str =
"48 8B 0D ? ? ? ? 4C 89 E2 E8 ? ? ? ? 48 89 C6 48 8B 0D ? ? ? ? E8 ? ? ? ? 48 89 C7 48 8B 0D"; "48 8B 0D ? ? ? ? 4C 89 E2 E8 ? ? ? ? 48 89 C6 48 8B 0D ? ? ? ? E8 ? ? ? ? 48 89 C7 48 8B 0D";
// const HK_CHECK1: &str = "55 41 56 56 57 53 48 81 EC 00 01 00 00 48 8D AC 24 80 00 00 00 C7 45 7C 00 00 00 00";
// const HK_CHECK2: &str = "55 41 57 41 56 41 55 41 54 56 57 53 48 81 EC B8 02 00 00";
#[derive(Default)] #[derive(Default)]
pub struct RVAConfig { pub struct RVAConfig {
@@ -38,7 +36,15 @@ pub static GAME_ASSEMBLY_BASE: LazyLock<usize> =
macro_rules! set_rva { macro_rules! set_rva {
($base:ident, $config:ident, $field:ident, $scan_fn:ident, $rva_pat:expr, $fallback:expr) => { ($base:ident, $config:ident, $field:ident, $scan_fn:ident, $rva_pat:expr, $fallback:expr) => {
if let Some(addr) = unsafe { $scan_fn($rva_pat) } { if $rva_pat == "" {
$config.$field = *$base + $fallback;
println!(
"[hkrpg::addr::set_rva] Using fallback relative address for {} [{}] -> 0x{:X}",
stringify!($field),
stringify!($base),
$config.$field - *$base
);
} else if let Some(addr) = unsafe { $scan_fn($rva_pat) } {
$config.$field = addr; $config.$field = addr;
println!( println!(
"[hkrpg::addr::set_rva] Found relative address for {} [{}] -> 0x{:X}", "[hkrpg::addr::set_rva] Found relative address for {} [{}] -> 0x{:X}",
@@ -101,21 +107,4 @@ pub unsafe fn init_rvas() {
SDK_PUBLIC_KEY_LITERAL, SDK_PUBLIC_KEY_LITERAL,
0x0 0x0
) )
// set_rva!(
// UNITY_PLAYER_BASE,
// config,
// hk_check1,
// scan_unity_player_section,
// HK_CHECK1,
// 0x0
// );
// set_rva!(
// UNITY_PLAYER_BASE,
// config,
// hk_check2,
// scan_unity_player_section,
// HK_CHECK2,
// 0x0
// );
} }
+4 -3
View File
@@ -1,10 +1,10 @@
#![feature(str_from_utf16_endian, once_cell_get_mut)] #![feature(once_cell_get_mut)]
use std::{thread, time::Duration}; use std::{thread, time::Duration};
use modules::{ use modules::{
HkrpgModuleManager, censorship_patch::CensorshipPatch, crypto::Crypto, hk_check::HkCheck, HkrpgModuleManager, apn::ApnPatch, censorship_patch::CensorshipPatch, crypto::Crypto,
misc::Misc, network::Network, hk_check::HkCheck, misc::Misc, network::Network,
}; };
use windows::{ use windows::{
Win32::System::{Console, LibraryLoader::GetModuleHandleA}, Win32::System::{Console, LibraryLoader::GetModuleHandleA},
@@ -35,6 +35,7 @@ pub fn main() {
addr::init_rvas(); addr::init_rvas();
let mut module_manager = HkrpgModuleManager::default(); let mut module_manager = HkrpgModuleManager::default();
module_manager.add::<ApnPatch>();
module_manager.add::<HkCheck>(); module_manager.add::<HkCheck>();
module_manager.add::<Network>(); module_manager.add::<Network>();
module_manager.add::<Crypto>(); module_manager.add::<Crypto>();
+160
View File
@@ -0,0 +1,160 @@
use dashmap::DashMap;
use ilhook::x64::Registers;
use patternscan::scan_first_match;
use std::{
borrow::Cow,
ffi::{CStr, CString},
path::Path,
sync::{LazyLock, OnceLock},
};
use windows::{
Win32::System::{
LibraryLoader::{GetModuleHandleW, LoadLibraryW},
ProcessStatus::{GetModuleInformation, MODULEINFO},
Threading::GetCurrentProcess,
},
core::{PCWSTR, w},
};
use crate::modules::{HkrpgModule, HkrpgModuleContext};
pub struct ApnPatch;
impl HkrpgModule for HkrpgModuleContext<ApnPatch> {
unsafe fn init(&mut self) -> Result<(), ilhook::HookError> {
if !load_apn_dll() {
return Ok(());
};
let base;
loop {
if let Ok(module) = unsafe { GetModuleHandleW(w!("AccountPlatNative.dll")) } {
base = module.0 as usize;
println!("AccountPlatNative.dll: 0x{base:X}");
break;
}
std::thread::sleep(std::time::Duration::from_millis(50));
}
let Some(string_alloc_rva) = scan_apn("E8 ? ? ? ? 41 89 BF") else {
println!("[AccountPlatNative] failed to scan string_alloc rva. patch disabled");
return Ok(());
};
self.interceptor
.attach(base + string_alloc_rva, on_string_alloc)
.expect("Failed to hook AccountPlatNative string alloc");
println!("[AccountPlatNative] patch enabled");
Ok(())
}
}
extern "win64" fn on_string_alloc(reg: *mut Registers, _: usize) {
const SDK_PUBLIC_KEY: &str = include_str!("../../sdk_public_key.pem");
static STRING_CACHE_MAP: LazyLock<DashMap<Cow<'static, str>, CString>> =
LazyLock::new(DashMap::new);
unsafe {
let content = CStr::from_ptr((*reg).rdx as *const i8).to_string_lossy();
let size = (*reg).r8;
if let Some(cstring) = STRING_CACHE_MAP.get(&content) {
(*reg).rdx = cstring.as_ptr() as u64;
(*reg).r8 = cstring.count_bytes() as u64;
return;
}
// URL string alloc
if content.starts_with("https://") && content.contains(".mihoyo.com") {
let mut new_url = String::from("http://127.0.0.1:21000");
content.split('/').skip(3).for_each(|s| {
new_url.push('/');
new_url.push_str(s);
});
let cstring = STRING_CACHE_MAP
.entry(content.clone())
.or_insert_with(|| CString::new(&*new_url).expect("Failed to create CString"));
(*reg).rdx = cstring.as_ptr() as u64;
(*reg).r8 = new_url.len() as u64;
println!("[AccountPlatNative] url {content} replaced to {new_url}");
}
// RSA public key string alloc
else if size == 268 && content.starts_with("-----BEGIN PUBLIC KEY-----") {
let cstring = STRING_CACHE_MAP
.entry(content.clone())
.or_insert_with(|| CString::new(SDK_PUBLIC_KEY).expect("Failed to create CString"));
(*reg).rdx = cstring.as_ptr() as u64;
(*reg).r8 = SDK_PUBLIC_KEY.len() as u64;
println!("[AccountPlatNative] sdk public key replaced! ");
}
}
}
fn load_apn_dll() -> bool {
let dll_path = "./StarRail_Data/Plugins/x86_64/AccountPlatNative.dll";
if !Path::new(dll_path).exists() {
return false;
}
let wide_dll_path: Vec<u16> = dll_path.encode_utf16().chain(std::iter::once(0)).collect();
let ptr = wide_dll_path.as_ptr();
if let Err(err) = unsafe { LoadLibraryW(PCWSTR::from_raw(ptr)) } {
println!("[AccountPlatNative] Failed to inject {dll_path}. Error: {err:#?}",);
};
true
}
pub fn scan_apn(pat: &str) -> Option<usize> {
let mut slice = apn_slice();
scan_first_match(&mut slice, pat).unwrap().map(|address| {
let slice = apn_slice();
match slice.get(address) {
// jmp sub_xxxxxxx
Some(&0xE8) => {
let offset =
i32::from_le_bytes(slice[address + 1..address + 5].try_into().unwrap());
address + 5 + offset as usize
}
// mov REGISTER, [rip + offset] (0x48 0x8B 0x0D XXXXXXXX)
Some(&0x48) if slice.get(address + 1) == Some(&0x8B) => {
let offset =
i32::from_le_bytes(slice[address + 3..address + 7].try_into().unwrap());
address + 7 + offset as usize
}
_ => address,
}
})
}
fn apn_slice() -> &'static [u8] {
static SLICE: OnceLock<&[u8]> = OnceLock::new();
unsafe {
SLICE.get_or_init(|| {
let module = GetModuleHandleW(w!("AccountPlatNative.dll")).unwrap();
let mut module_info = MODULEINFO {
lpBaseOfDll: std::ptr::null_mut(),
SizeOfImage: 0,
EntryPoint: std::ptr::null_mut(),
};
GetModuleInformation(
GetCurrentProcess(),
module,
&mut module_info,
std::mem::size_of::<MODULEINFO>() as u32,
)
.unwrap();
std::slice::from_raw_parts(
module.0 as *const u8,
module_info.SizeOfImage.try_into().unwrap(),
)
})
}
}
+2 -1
View File
@@ -2,11 +2,12 @@ use std::marker::PhantomData;
use crate::{addr, interceptor::Interceptor}; use crate::{addr, interceptor::Interceptor};
pub mod apn;
pub mod censorship_patch; pub mod censorship_patch;
pub mod crypto; pub mod crypto;
pub mod hk_check; pub mod hk_check;
pub mod network;
pub mod misc; pub mod misc;
pub mod network;
pub struct HkrpgModuleContext<T> { pub struct HkrpgModuleContext<T> {
_base: usize, _base: usize,
+2 -2
View File
@@ -22,7 +22,7 @@ impl HkrpgModule for HkrpgModuleContext<Network> {
impl Network { impl Network {
const SDK_URL: &str = "http://127.0.0.1:21000"; const SDK_URL: &str = "http://127.0.0.1:21000";
// const DISPATCH_URL: &str = "http://127.0.0.1:21000"; const DISPATCH_URL: &str = "http://127.0.0.1:21000";
const REDIRECT_SDK: bool = true; const REDIRECT_SDK: bool = true;
const REDIRECT_DISPATCH: bool = true; const REDIRECT_DISPATCH: bool = true;
@@ -38,7 +38,7 @@ impl Network {
s if (s.contains("bhsr.com") || s.contains("starrails.com")) s if (s.contains("bhsr.com") || s.contains("starrails.com"))
&& Self::REDIRECT_DISPATCH => && Self::REDIRECT_DISPATCH =>
{ {
Self::SDK_URL.to_string() Self::DISPATCH_URL.to_string()
} }
s => { s => {
println!("Leaving request as-is: {s}"); println!("Leaving request as-is: {s}");
+54
View File
@@ -0,0 +1,54 @@
use std::{env, fs, path::PathBuf, process::Command};
fn main() {
match env::var("CARGO_CFG_TARGET_ENV").as_deref() {
Ok("msvc") => {
println!("cargo:rustc-link-arg-bin=launcher=/MANIFEST:EMBED");
println!("cargo:rustc-link-arg-bin=launcher=/MANIFESTUAC:level='requireAdministrator'");
}
Ok("gnu") => {
let Some(out_dir) = env::var_os("OUT_DIR") else {
return;
};
let out_dir = PathBuf::from(out_dir);
let manifest = out_dir.join("launcher.manifest");
let resource = out_dir.join("launcher.rc");
let object = out_dir.join("launcher-manifest.o");
if fs::write(&manifest, MANIFEST).is_err() || fs::write(&resource, RESOURCE).is_err() {
return;
}
let Ok(status) = Command::new("x86_64-w64-mingw32-windres")
.current_dir(&out_dir)
.args(["launcher.rc", "-O", "coff", "-o"])
.arg(&object)
.status()
else {
return;
};
if !status.success() {
return;
}
println!("cargo:rustc-link-arg-bin=launcher={}", object.display());
}
_ => {}
}
}
const RESOURCE: &str = "1 24 \"launcher.manifest\"\n";
const MANIFEST: &str = r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"#;
-12
View File
@@ -1,12 +0,0 @@
[package]
name = "mhypbase"
edition = "2024"
version.workspace = true
[lib]
name = "mhypbase"
crate-type = ["cdylib"]
[dependencies]
windows.workspace = true
hkrpg.workspace = true
-7
View File
@@ -1,7 +0,0 @@
fn main() {
println!(
"cargo:rustc-link-search=native={}",
std::env::var("OUT_DIR").unwrap()
);
println!("cargo:rustc-link-arg=/DEF:mhypbase/mhypbase.def");
}
-3
View File
@@ -1,3 +0,0 @@
LIBRARY MHYPBASE
EXPORTS
Initialize @1
-27
View File
@@ -1,27 +0,0 @@
use windows::Win32::{
Foundation::HINSTANCE,
System::{
SystemServices::DLL_PROCESS_ATTACH,
Threading::{GetCurrentThread, TerminateThread},
},
};
#[unsafe(no_mangle)]
#[allow(non_snake_case, unused_variables)]
extern "cdecl" fn Initialize() -> bool {
std::thread::sleep(std::time::Duration::from_secs(2));
unsafe {
TerminateThread(GetCurrentThread(), 0).unwrap();
}
false
}
#[allow(non_snake_case)]
#[unsafe(no_mangle)]
unsafe extern "system" fn DllMain(_: HINSTANCE, call_reason: u32, _: *mut ()) {
if call_reason == DLL_PROCESS_ATTACH {
std::thread::spawn(hkrpg::main);
}
}