From 2076b8dba967d49c10b784e499c209622ae88631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=84=9C=EC=9E=AC=EC=99=84?= Date: Fri, 23 May 2025 16:51:38 +0900 Subject: [PATCH 1/2] Add `Service.set_launch_protected, get_launch_protected` --- src/service.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/service.rs b/src/service.rs index 3fe426d..41a57f6 100644 --- a/src/service.rs +++ b/src/service.rs @@ -359,6 +359,42 @@ impl ServiceFailureActions { } } +/// Enum describing the service launch protection options. +/// +/// See +/// for more information. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(u32)] +pub enum ServiceLaunchProtected { + None = Services::SERVICE_LAUNCH_PROTECTED_NONE, + Windows = Services::SERVICE_LAUNCH_PROTECTED_WINDOWS, + WindowsLight = Services::SERVICE_LAUNCH_PROTECTED_WINDOWS_LIGHT, + AntimalwareLight = Services::SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT, +} +impl ServiceLaunchProtected { + pub fn to_raw(&self) -> u32 { + *self as u32 + } + + pub fn from_raw(raw: u32) -> crate::Result { + match raw { + x if x == ServiceLaunchProtected::None.to_raw() => Ok(ServiceLaunchProtected::None), + x if x == ServiceLaunchProtected::Windows.to_raw() => { + Ok(ServiceLaunchProtected::Windows) + } + x if x == ServiceLaunchProtected::WindowsLight.to_raw() => { + Ok(ServiceLaunchProtected::WindowsLight) + } + x if x == ServiceLaunchProtected::AntimalwareLight.to_raw() => { + Ok(ServiceLaunchProtected::AntimalwareLight) + } + _ => Err(Error::ParseValue( + "Invalid launch protection value", + ParseRawError::InvalidInteger(raw), + )), + } + } +} /// A struct that describes the service. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ServiceInfo { @@ -1802,6 +1838,35 @@ impl Service { } } + /// Set service launch protection. + /// This is a security feature that allows the service to run in a more secure environment. + /// there is no example because you need EV Certification and ELAM Driver to test it. + /// Please refer to the official documentation for more information: + /// + pub fn set_launch_protected(&self, protection: ServiceLaunchProtected) -> crate::Result<()> { + let mut launch_protected = + unsafe { mem::zeroed::() }; + launch_protected.dwLaunchProtected = protection.to_raw(); + unsafe { + self.change_config2( + Services::SERVICE_CONFIG_LAUNCH_PROTECTED, + &mut launch_protected, + ) + .map_err(Error::Winapi) + } + } + /// Get service launch protection. + /// This is a security feature that allows the service to run in a more secure environment. + pub fn get_launch_protected(&self) -> crate::Result { + let mut data = vec![0u8; std::mem::size_of::()]; + unsafe { + let raw_data: Services::SERVICE_LAUNCH_PROTECTED_INFO = self + .query_config2(Services::SERVICE_CONFIG_LAUNCH_PROTECTED, &mut data) + .map_err(Error::Winapi)?; + ServiceLaunchProtected::from_raw(raw_data.dwLaunchProtected) + } + } + /// Set service description. /// /// Required permission: [`ServiceAccess::CHANGE_CONFIG`]. From 799b8c74c702ff41b8583cd87bf7ff6d450ae5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=84=9C=EC=9E=AC=EC=99=84?= Date: Mon, 28 Jul 2025 09:47:39 +0900 Subject: [PATCH 2/2] chore: fix reviewed codes --- src/service.rs | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/service.rs b/src/service.rs index 41a57f6..36d7c9f 100644 --- a/src/service.rs +++ b/src/service.rs @@ -366,31 +366,34 @@ impl ServiceFailureActions { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(u32)] pub enum ServiceLaunchProtected { + /// No launch protection. The service can be modified or replaced without restriction. None = Services::SERVICE_LAUNCH_PROTECTED_NONE, + + /// Launch protection for Windows components. Windows = Services::SERVICE_LAUNCH_PROTECTED_WINDOWS, + + /// A lighter version of Windows launch protection. WindowsLight = Services::SERVICE_LAUNCH_PROTECTED_WINDOWS_LIGHT, + + /// Launch protection used by antimalware (ELAM) services. AntimalwareLight = Services::SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT, } -impl ServiceLaunchProtected { - pub fn to_raw(&self) -> u32 { - *self as u32 - } +impl TryFrom for ServiceLaunchProtected { + type Error = Error; - pub fn from_raw(raw: u32) -> crate::Result { - match raw { - x if x == ServiceLaunchProtected::None.to_raw() => Ok(ServiceLaunchProtected::None), - x if x == ServiceLaunchProtected::Windows.to_raw() => { - Ok(ServiceLaunchProtected::Windows) - } - x if x == ServiceLaunchProtected::WindowsLight.to_raw() => { + fn try_from(value: u32) -> Result { + match value { + Services::SERVICE_LAUNCH_PROTECTED_NONE => Ok(ServiceLaunchProtected::None), + Services::SERVICE_LAUNCH_PROTECTED_WINDOWS => Ok(ServiceLaunchProtected::Windows), + Services::SERVICE_LAUNCH_PROTECTED_WINDOWS_LIGHT => { Ok(ServiceLaunchProtected::WindowsLight) } - x if x == ServiceLaunchProtected::AntimalwareLight.to_raw() => { + Services::SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT => { Ok(ServiceLaunchProtected::AntimalwareLight) } _ => Err(Error::ParseValue( "Invalid launch protection value", - ParseRawError::InvalidInteger(raw), + ParseRawError::InvalidInteger(value), )), } } @@ -1846,7 +1849,7 @@ impl Service { pub fn set_launch_protected(&self, protection: ServiceLaunchProtected) -> crate::Result<()> { let mut launch_protected = unsafe { mem::zeroed::() }; - launch_protected.dwLaunchProtected = protection.to_raw(); + launch_protected.dwLaunchProtected = protection as u32; unsafe { self.change_config2( Services::SERVICE_CONFIG_LAUNCH_PROTECTED, @@ -1855,15 +1858,16 @@ impl Service { .map_err(Error::Winapi) } } + /// Get service launch protection. /// This is a security feature that allows the service to run in a more secure environment. pub fn get_launch_protected(&self) -> crate::Result { - let mut data = vec![0u8; std::mem::size_of::()]; + let mut data = [0u8; std::mem::size_of::()]; unsafe { let raw_data: Services::SERVICE_LAUNCH_PROTECTED_INFO = self .query_config2(Services::SERVICE_CONFIG_LAUNCH_PROTECTED, &mut data) .map_err(Error::Winapi)?; - ServiceLaunchProtected::from_raw(raw_data.dwLaunchProtected) + raw_data.dwLaunchProtected.try_into() } }