@@ -11,7 +11,7 @@ use winapi::shared::winerror::{ERROR_SERVICE_SPECIFIC_ERROR, NO_ERROR};
11
11
use winapi:: um:: { winnt, winsvc} ;
12
12
13
13
use crate :: sc_handle:: ScHandle ;
14
- use crate :: { double_nul_terminated, Error , Result } ;
14
+ use crate :: { double_nul_terminated, Error } ;
15
15
16
16
bitflags:: bitflags! {
17
17
/// Enum describing the types of Windows services.
@@ -82,12 +82,12 @@ impl ServiceStartType {
82
82
* self as u32
83
83
}
84
84
85
- pub fn from_raw ( raw : u32 ) -> Result < ServiceStartType > {
85
+ pub fn from_raw ( raw : u32 ) -> Result < ServiceStartType , ParseRawError > {
86
86
match raw {
87
87
x if x == ServiceStartType :: AutoStart . to_raw ( ) => Ok ( ServiceStartType :: AutoStart ) ,
88
88
x if x == ServiceStartType :: OnDemand . to_raw ( ) => Ok ( ServiceStartType :: OnDemand ) ,
89
89
x if x == ServiceStartType :: Disabled . to_raw ( ) => Ok ( ServiceStartType :: Disabled ) ,
90
- _ => Err ( Error :: InvalidServiceStartType ( raw) ) ,
90
+ _ => Err ( ParseRawError ( raw) ) ,
91
91
}
92
92
}
93
93
}
@@ -109,13 +109,13 @@ impl ServiceErrorControl {
109
109
* self as u32
110
110
}
111
111
112
- pub fn from_raw ( raw : u32 ) -> Result < ServiceErrorControl > {
112
+ pub fn from_raw ( raw : u32 ) -> Result < ServiceErrorControl , ParseRawError > {
113
113
match raw {
114
114
x if x == ServiceErrorControl :: Critical . to_raw ( ) => Ok ( ServiceErrorControl :: Critical ) ,
115
115
x if x == ServiceErrorControl :: Ignore . to_raw ( ) => Ok ( ServiceErrorControl :: Ignore ) ,
116
116
x if x == ServiceErrorControl :: Normal . to_raw ( ) => Ok ( ServiceErrorControl :: Normal ) ,
117
117
x if x == ServiceErrorControl :: Severe . to_raw ( ) => Ok ( ServiceErrorControl :: Severe ) ,
118
- _ => Err ( Error :: InvalidServiceErrorControl ( raw) ) ,
118
+ _ => Err ( ParseRawError ( raw) ) ,
119
119
}
120
120
}
121
121
}
@@ -233,7 +233,12 @@ pub struct ServiceConfig {
233
233
}
234
234
235
235
impl ServiceConfig {
236
- pub unsafe fn from_raw ( raw : winsvc:: QUERY_SERVICE_CONFIGW ) -> Result < ServiceConfig > {
236
+ /// Tries to parse a `QUERY_SERVICE_CONFIGW` into Rust [`ServiceConfig`].
237
+ ///
238
+ /// # Errors
239
+ ///
240
+ /// Returns an error if a field inside the `QUERY_SERVICE_CONFIGW` does not have a valid value.
241
+ pub unsafe fn from_raw ( raw : winsvc:: QUERY_SERVICE_CONFIGW ) -> crate :: Result < ServiceConfig > {
237
242
let dependencies = double_nul_terminated:: parse_str_ptr ( raw. lpDependencies )
238
243
. iter ( )
239
244
. map ( ServiceDependency :: from_system_identifier)
@@ -255,8 +260,10 @@ impl ServiceConfig {
255
260
256
261
Ok ( ServiceConfig {
257
262
service_type : ServiceType :: from_bits_truncate ( raw. dwServiceType ) ,
258
- start_type : ServiceStartType :: from_raw ( raw. dwStartType ) ?,
259
- error_control : ServiceErrorControl :: from_raw ( raw. dwErrorControl ) ?,
263
+ start_type : ServiceStartType :: from_raw ( raw. dwStartType )
264
+ . map_err ( Error :: InvalidServiceStartType ) ?,
265
+ error_control : ServiceErrorControl :: from_raw ( raw. dwErrorControl )
266
+ . map_err ( Error :: InvalidServiceErrorControl ) ?,
260
267
executable_path : PathBuf :: from (
261
268
WideCStr :: from_ptr_str ( raw. lpBinaryPathName ) . to_os_string ( ) ,
262
269
) ,
@@ -287,8 +294,8 @@ pub enum ServiceControl {
287
294
}
288
295
289
296
impl ServiceControl {
290
- pub fn from_raw ( raw_value : u32 ) -> Result < Self > {
291
- match raw_value {
297
+ pub fn from_raw ( raw : u32 ) -> Result < Self , ParseRawError > {
298
+ match raw {
292
299
x if x == ServiceControl :: Continue . to_raw ( ) => Ok ( ServiceControl :: Continue ) ,
293
300
x if x == ServiceControl :: Interrogate . to_raw ( ) => Ok ( ServiceControl :: Interrogate ) ,
294
301
x if x == ServiceControl :: NetBindAdd . to_raw ( ) => Ok ( ServiceControl :: NetBindAdd ) ,
@@ -300,7 +307,7 @@ impl ServiceControl {
300
307
x if x == ServiceControl :: Preshutdown . to_raw ( ) => Ok ( ServiceControl :: Preshutdown ) ,
301
308
x if x == ServiceControl :: Shutdown . to_raw ( ) => Ok ( ServiceControl :: Shutdown ) ,
302
309
x if x == ServiceControl :: Stop . to_raw ( ) => Ok ( ServiceControl :: Stop ) ,
303
- other => Err ( Error :: InvalidServiceControl ( other ) ) ,
310
+ _ => Err ( ParseRawError ( raw ) ) ,
304
311
}
305
312
}
306
313
@@ -323,16 +330,16 @@ pub enum ServiceState {
323
330
}
324
331
325
332
impl ServiceState {
326
- fn from_raw ( raw_state : u32 ) -> Result < Self > {
327
- match raw_state {
333
+ fn from_raw ( raw : u32 ) -> Result < Self , ParseRawError > {
334
+ match raw {
328
335
x if x == ServiceState :: Stopped . to_raw ( ) => Ok ( ServiceState :: Stopped ) ,
329
336
x if x == ServiceState :: StartPending . to_raw ( ) => Ok ( ServiceState :: StartPending ) ,
330
337
x if x == ServiceState :: StopPending . to_raw ( ) => Ok ( ServiceState :: StopPending ) ,
331
338
x if x == ServiceState :: Running . to_raw ( ) => Ok ( ServiceState :: Running ) ,
332
339
x if x == ServiceState :: ContinuePending . to_raw ( ) => Ok ( ServiceState :: ContinuePending ) ,
333
340
x if x == ServiceState :: PausePending . to_raw ( ) => Ok ( ServiceState :: PausePending ) ,
334
341
x if x == ServiceState :: Paused . to_raw ( ) => Ok ( ServiceState :: Paused ) ,
335
- other => Err ( Error :: InvalidServiceState ( other ) ) ,
342
+ _ => Err ( ParseRawError ( raw ) ) ,
336
343
}
337
344
}
338
345
@@ -477,16 +484,19 @@ impl ServiceStatus {
477
484
raw_status
478
485
}
479
486
480
- fn from_raw ( raw_status : winsvc:: SERVICE_STATUS ) -> Result < Self > {
487
+ /// Tries to parse a `SERVICE_STATUS` into a Rust [`ServiceStatus`].
488
+ ///
489
+ /// # Errors
490
+ ///
491
+ /// Returns an error if the `dwCurrentState` field does not represent a valid [`ServiceState`].
492
+ fn from_raw ( raw : winsvc:: SERVICE_STATUS ) -> Result < Self , ParseRawError > {
481
493
Ok ( ServiceStatus {
482
- service_type : ServiceType :: from_bits_truncate ( raw_status. dwServiceType ) ,
483
- current_state : ServiceState :: from_raw ( raw_status. dwCurrentState ) ?,
484
- controls_accepted : ServiceControlAccept :: from_bits_truncate (
485
- raw_status. dwControlsAccepted ,
486
- ) ,
487
- exit_code : ServiceExitCode :: from ( & raw_status) ,
488
- checkpoint : raw_status. dwCheckPoint ,
489
- wait_hint : Duration :: from_millis ( raw_status. dwWaitHint as u64 ) ,
494
+ service_type : ServiceType :: from_bits_truncate ( raw. dwServiceType ) ,
495
+ current_state : ServiceState :: from_raw ( raw. dwCurrentState ) ?,
496
+ controls_accepted : ServiceControlAccept :: from_bits_truncate ( raw. dwControlsAccepted ) ,
497
+ exit_code : ServiceExitCode :: from ( & raw ) ,
498
+ checkpoint : raw. dwCheckPoint ,
499
+ wait_hint : Duration :: from_millis ( raw. dwWaitHint as u64 ) ,
490
500
} )
491
501
}
492
502
}
@@ -521,11 +531,11 @@ impl Service {
521
531
/// # Ok(())
522
532
/// # }
523
533
/// ```
524
- pub fn start < S : AsRef < OsStr > > ( & self , service_arguments : & [ S ] ) -> Result < ( ) > {
534
+ pub fn start < S : AsRef < OsStr > > ( & self , service_arguments : & [ S ] ) -> crate :: Result < ( ) > {
525
535
let wide_service_arguments = service_arguments
526
536
. iter ( )
527
537
. map ( |s| WideCString :: from_str ( s) . map_err ( Error :: InvalidStartArgument ) )
528
- . collect :: < Result < Vec < WideCString > > > ( ) ?;
538
+ . collect :: < crate :: Result < Vec < WideCString > > > ( ) ?;
529
539
530
540
let mut raw_service_arguments: Vec < * const u16 > =
531
541
wide_service_arguments. iter ( ) . map ( |s| s. as_ptr ( ) ) . collect ( ) ;
@@ -539,42 +549,42 @@ impl Service {
539
549
} ;
540
550
541
551
if success == 0 {
542
- Err ( Error :: ServiceStartFailed ( io:: Error :: last_os_error ( ) ) )
552
+ Err ( Error :: Winapi ( io:: Error :: last_os_error ( ) ) )
543
553
} else {
544
554
Ok ( ( ) )
545
555
}
546
556
}
547
557
548
558
/// Stop the service.
549
- pub fn stop ( & self ) -> Result < ServiceStatus > {
559
+ pub fn stop ( & self ) -> crate :: Result < ServiceStatus > {
550
560
self . send_control_command ( ServiceControl :: Stop )
551
561
}
552
562
553
563
/// Get the service status from the system.
554
- pub fn query_status ( & self ) -> Result < ServiceStatus > {
564
+ pub fn query_status ( & self ) -> crate :: Result < ServiceStatus > {
555
565
let mut raw_status = unsafe { mem:: zeroed :: < winsvc:: SERVICE_STATUS > ( ) } ;
556
566
let success = unsafe {
557
567
winsvc:: QueryServiceStatus ( self . service_handle . raw_handle ( ) , & mut raw_status)
558
568
} ;
559
569
if success == 0 {
560
- Err ( Error :: ServiceQueryFailed ( io:: Error :: last_os_error ( ) ) )
570
+ Err ( Error :: Winapi ( io:: Error :: last_os_error ( ) ) )
561
571
} else {
562
- ServiceStatus :: from_raw ( raw_status)
572
+ ServiceStatus :: from_raw ( raw_status) . map_err ( Error :: InvalidServiceState )
563
573
}
564
574
}
565
575
566
576
/// Delete the service from system registry.
567
- pub fn delete ( self ) -> Result < ( ) > {
577
+ pub fn delete ( self ) -> crate :: Result < ( ) > {
568
578
let success = unsafe { winsvc:: DeleteService ( self . service_handle . raw_handle ( ) ) } ;
569
579
if success == 0 {
570
- Err ( Error :: ServiceDeleteFailed ( io:: Error :: last_os_error ( ) ) )
580
+ Err ( Error :: Winapi ( io:: Error :: last_os_error ( ) ) )
571
581
} else {
572
582
Ok ( ( ) )
573
583
}
574
584
}
575
585
576
586
/// Get the service config from the system.
577
- pub fn query_config ( & self ) -> Result < ServiceConfig > {
587
+ pub fn query_config ( & self ) -> crate :: Result < ServiceConfig > {
578
588
// As per docs, the maximum size of data buffer used by QueryServiceConfigW is 8K
579
589
let mut data = [ 0u8 ; 8096 ] ;
580
590
let mut bytes_written: u32 = 0 ;
@@ -589,7 +599,7 @@ impl Service {
589
599
} ;
590
600
591
601
if success == 0 {
592
- Err ( Error :: ServiceQueryFailed ( io:: Error :: last_os_error ( ) ) )
602
+ Err ( Error :: Winapi ( io:: Error :: last_os_error ( ) ) )
593
603
} else {
594
604
unsafe {
595
605
let raw_config = data. as_ptr ( ) as * const winsvc:: QUERY_SERVICE_CONFIGW ;
@@ -599,7 +609,7 @@ impl Service {
599
609
}
600
610
601
611
/// Private helper to send the control commands to the system.
602
- fn send_control_command ( & self , command : ServiceControl ) -> Result < ServiceStatus > {
612
+ fn send_control_command ( & self , command : ServiceControl ) -> crate :: Result < ServiceStatus > {
603
613
let mut raw_status = unsafe { mem:: zeroed :: < winsvc:: SERVICE_STATUS > ( ) } ;
604
614
let success = unsafe {
605
615
winsvc:: ControlService (
@@ -610,13 +620,17 @@ impl Service {
610
620
} ;
611
621
612
622
if success == 0 {
613
- Err ( Error :: ServiceControlFailed ( io:: Error :: last_os_error ( ) ) )
623
+ Err ( Error :: Winapi ( io:: Error :: last_os_error ( ) ) )
614
624
} else {
615
- ServiceStatus :: from_raw ( raw_status)
625
+ ServiceStatus :: from_raw ( raw_status) . map_err ( Error :: InvalidServiceState )
616
626
}
617
627
}
618
628
}
619
629
630
+ #[ derive( err_derive:: Error , Debug ) ]
631
+ #[ error( display = "Invalid integer value for the target type: {}" , _0) ]
632
+ pub struct ParseRawError ( u32 ) ;
633
+
620
634
#[ cfg( test) ]
621
635
mod tests {
622
636
use super :: * ;
0 commit comments