diff options
| -rw-r--r-- | Cargo.lock | 132 | ||||
| -rw-r--r-- | Cargo.toml | 7 | ||||
| -rw-r--r-- | src/bot.rs | 5 | ||||
| -rw-r--r-- | src/lib.rs | 4 | ||||
| -rw-r--r-- | src/windows_util.rs | 129 |
5 files changed, 243 insertions, 34 deletions
@@ -229,9 +229,9 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" [[package]] name = "byteorder" @@ -300,7 +300,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -941,7 +941,7 @@ dependencies = [ "libc", "log", "rustversion", - "windows", + "windows 0.48.0", ] [[package]] @@ -1133,7 +1133,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -1615,7 +1615,7 @@ dependencies = [ "libc", "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3011,6 +3011,7 @@ name = "thulani" version = "0.3.1" dependencies = [ "anyhow", + "bytemuck", "chrono", "clap", "deadpool-postgres", @@ -3043,6 +3044,7 @@ dependencies = [ "tokio", "tokio-postgres", "url", + "windows 0.58.0", ] [[package]] @@ -3810,12 +3812,76 @@ dependencies = [ ] [[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -3833,7 +3899,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3853,18 +3919,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -3875,9 +3941,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -3887,9 +3953,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -3899,15 +3965,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -3917,9 +3983,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -3929,9 +3995,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -3941,9 +4007,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -3953,9 +4019,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winreg" @@ -19,9 +19,10 @@ name = "batch_delmeme" required-features = ["db"] [features] -default = ["db", "games"] +default = ["db", "games", "windows_autostart_postgres"] db = ["dep:diesel", "dep:diesel-async", "dep:diesel_async_migrations", "dep:tokio-postgres", "dep:deadpool-postgres"] games = [] +windows_autostart_postgres = [] [workspace.dependencies] lazy_static = "1.4" @@ -76,6 +77,10 @@ version = "0.12" default-features = false features = ["builder", "cache", "client", "framework", "gateway", "http", "model", "utils", "voice", "standard_framework", "rustls_backend"] +[target.'cfg(target_os = "windows")'.dependencies] +windows = { version = "0.58", features = ["Win32_System_Services"] } +bytemuck = { version = "1.16", features = ["min_const_generics"] } + [profile.release] codegen-units = 1 lto = "fat" @@ -364,6 +364,11 @@ fn after_handle(ctx: PoiseContext) -> BoxFuture<()> { } pub async fn run() -> anyhow::Result<()> { + #[cfg(all(windows, feature = "windows_autostart_postgres"))] + unsafe { + crate::windows_util::ensure_postgres_started()?; + }; + let token = &CONFIG.discord.auth.token; let sb_config = songbird::Config::default(); @@ -1,5 +1,6 @@ #![feature(try_blocks)] #![feature(let_chains)] +#![feature(maybe_uninit_slice)] #[cfg(feature = "db")] pub mod db; @@ -20,6 +21,9 @@ pub mod config; pub mod log_setup; pub mod util; +#[cfg(windows)] +pub mod windows_util; + pub use crate::{ config::*, util::*, diff --git a/src/windows_util.rs b/src/windows_util.rs new file mode 100644 index 0000000..348ea91 --- /dev/null +++ b/src/windows_util.rs @@ -0,0 +1,129 @@ +use windows::{ + core::HSTRING, + Win32::{ + Foundation, + System::Services, + }, +}; + +lazy_static::lazy_static! { + static ref PSQL_REGEX: regex::Regex = regex::Regex::new(r#"^(?:postgresql|psql|postgres)-.*([\d\.]*)"#).unwrap(); +} + +pub unsafe fn ensure_postgres_started() -> windows::core::Result<()> { + let sc_manager = Services::OpenSCManagerW( + None, + None, + (Foundation::GENERIC_READ | Foundation::GENERIC_WRITE).0, + )?; + + let services = list_services(sc_manager)?; + + let mut psql_services = + services.into_iter().filter(|status| PSQL_REGEX.is_match(&status.name)).collect::<Vec<_>>(); + + match psql_services.len() { + 1 => {}, + + 0 => { + log::warn!("unable to identify an installed postgres service"); + }, + + other => { + log::warn!("unable to identify postgres service: {other} potential matches found"); + return Ok(()); + }, + } + + let svc = psql_services.remove(0); + log::debug!("identified postgres service: {}", svc.name); + + match svc.status.dwCurrentState { + Services::SERVICE_RUNNING => { + log::info!("postgres was already running, done"); + return Ok(()); + }, + + Services::SERVICE_START_PENDING => { + log::info!("postgres was already in startup, done"); + return Ok(()); + }, + + _ => { + log::info!("postgres is not running: starting it") + }, + } + + let service = + Services::OpenServiceW(sc_manager, &HSTRING::from(&svc.name), Services::SERVICE_START)?; + + Services::StartServiceW(service, None)?; + + log::info!("started postgres service"); + + Services::CloseServiceHandle(service)?; + Services::CloseServiceHandle(sc_manager)?; + + Ok(()) +} + +const RESULT_SIZE: usize = size_of::<Services::ENUM_SERVICE_STATUS_PROCESSW>(); + +pub struct ServiceStatus { + pub display_name: String, + pub name: String, + pub status: Services::SERVICE_STATUS_PROCESS, +} + +pub unsafe fn list_services( + sc_manager: Services::SC_HANDLE, +) -> windows::core::Result<Vec<ServiceStatus>> { + let mut bytes_needed: u32 = 0; + let mut services_returned: u32 = 0; + let mut resume = 0; + + let mut svcs = vec![]; + + loop { + let mut data = [0u8; 256 * 1024]; + + let result = Services::EnumServicesStatusExW( + sc_manager, + Services::SC_ENUM_PROCESS_INFO, + Services::SERVICE_WIN32, + Services::SERVICE_STATE_ALL, + Some(&mut data), + &mut bytes_needed as *mut _, + &mut services_returned as *mut _, + Some(&mut resume), + None, + ); + + if let Err(ref e) = result + && e.code() != Foundation::ERROR_MORE_DATA.to_hresult() + { + return result.map(|_| unreachable!()); + } + + let data = bytemuck::cast_slice::<u8, [u8; RESULT_SIZE]>( + &data[..services_returned as usize * RESULT_SIZE], + ); + + let elems = data + .into_iter() + .map(|x| core::mem::transmute::<_, Services::ENUM_SERVICE_STATUS_PROCESSW>(*x)) + .map(|x| ServiceStatus { + display_name: x.lpDisplayName.to_string().unwrap(), + name: x.lpServiceName.to_string().unwrap(), + status: x.ServiceStatusProcess, + }); + + svcs.extend(elems); + + if result.is_ok() { + break; + } + } + + Ok(svcs) +} |
