pacenotes_installer/
main.rs1#![windows_subsystem = "windows"]
4#![cfg(windows)]
5#![cfg_attr(
7 not(test),
8 deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)
9)]
10
11mod api;
12mod crash;
13mod elevation;
14mod game_process;
15mod http;
16mod i18n;
17mod package_download;
18mod run_header;
19mod selftest;
20mod single_instance;
21mod ui;
22mod wizard;
23mod worker;
24
25const DEFAULT_SERVER: &str = env!("PACENOTES_DEFAULT_SERVER");
28
29fn main() {
30 crash::install_panic_hook();
31
32 if let Some(selftest) = selftest::HttpSelfTest::from_args() {
33 std::process::exit(selftest.run());
34 }
35 if let Some(selftest) = selftest::DownloadSelfTest::from_args() {
36 std::process::exit(selftest.run());
37 }
38 if let Some(selftest) = selftest::ConflictReportSelfTest::from_args() {
39 std::process::exit(selftest.run());
40 }
41 selftest::panic_if_requested();
42
43 init_common_controls();
44
45 let restart = elevation::Restart::from_args();
48 if let Some(language) = restart.as_ref().map(|restart| restart.language) {
49 i18n::set_language(language);
50 } else if let Some(os_language) = i18n::os_language() {
51 i18n::set_language(os_language);
52 }
53
54 let already_running = match restart {
55 Some(_) => single_instance::another_instance_outlasts_restart(),
56 None => single_instance::another_instance_running(),
57 };
58 if already_running {
59 ui::message_box_warning(
60 core::ptr::null_mut(),
61 &i18n::load_string(i18n::IDS_ALREADY_RUNNING),
62 );
63 return;
64 }
65
66 wizard::run(&server_url(), cache_override(), restart);
67}
68
69fn init_common_controls() {
70 let classes = windows_sys::Win32::UI::Controls::INITCOMMONCONTROLSEX {
71 dwSize: core::mem::size_of::<windows_sys::Win32::UI::Controls::INITCOMMONCONTROLSEX>()
72 as u32,
73 dwICC: windows_sys::Win32::UI::Controls::ICC_STANDARD_CLASSES
74 | windows_sys::Win32::UI::Controls::ICC_PROGRESS_CLASS
75 | windows_sys::Win32::UI::Controls::ICC_LISTVIEW_CLASSES
76 | windows_sys::Win32::UI::Controls::ICC_TAB_CLASSES
77 | windows_sys::Win32::UI::Controls::ICC_TREEVIEW_CLASSES,
78 };
79 unsafe { windows_sys::Win32::UI::Controls::InitCommonControlsEx(&classes) };
80}
81
82fn server_url() -> String {
83 argument_after("--server")
84 .map(|url| url.trim_end_matches('/').to_string())
85 .unwrap_or_else(|| DEFAULT_SERVER.to_string())
86}
87
88fn cache_override() -> Option<std::path::PathBuf> {
91 argument_after("--cache").map(std::path::PathBuf::from)
92}
93
94fn argument_after(flag: &str) -> Option<String> {
95 let mut arguments = std::env::args().skip(1);
96 while let Some(argument) = arguments.next() {
97 if argument == flag {
98 return arguments.next();
99 }
100 }
101 None
102}