restart_manager/lib.rs
1//! Safe blocking bindings to the Windows Restart Manager (`rstrtmgr.dll`).
2//!
3//! A primary [`RestartSession`] owns shutdown, restart, filter, and
4//! cancellation capabilities. A secondary [`JoinedSession`] can only register
5//! and inspect resources, making a role violation impossible to express.
6//!
7//! # Example
8//!
9//! ```rust,no_run
10//! # #[cfg(windows)]
11//! # fn main() -> Result<(), restart_manager::Error> {
12//! use restart_manager::{RestartSession, ShutdownOptions};
13//!
14//! let mut session = RestartSession::new()?;
15//! session.register_files([r"C:\some\locked\file.dll"])?;
16//! let report = session.affected_applications()?;
17//! for application in &report {
18//! println!("locked by: {:?}", application.display_name());
19//! }
20//! let pending = session.shutdown_with_options(ShutdownOptions::default());
21//! let can_update = pending.shutdown_outcome().is_success();
22//! if can_update {
23//! // Replace or update the registered files here.
24//! }
25//! let completion = pending.restart();
26//! let outcome = completion.outcome().clone();
27//! completion.end()?;
28//! outcome.shutdown_outcome().clone().into_result()?;
29//! outcome
30//! .restart_outcome()
31//! .expect("restart was attempted")
32//! .clone()
33//! .into_result()?;
34//! # Ok(())
35//! # }
36//! # #[cfg(not(windows))]
37//! # fn main() {}
38//! ```
39//!
40//! Relative file and executable paths are made absolute, but this crate never
41//! checks existence or canonicalizes them. Restart Manager does not support
42//! registering directories. Forced shutdown is opt-in and can lose target
43//! application data. Restart is only possible for services and applications
44//! that registered for restart.
45//!
46//! Progress callbacks use a process-global native callback slot because the
47//! Windows API supplies no context pointer. Concurrent callback-bearing calls
48//! fail immediately with [`ErrorKind::CallbackInUse`]. A callback panic is
49//! contained at the FFI boundary and resumed after Windows returns.
50//!
51//! # Platform support
52//!
53//! All domain and session types are available on every target. Pure input
54//! validation behaves identically everywhere; operations that require Windows
55//! return [`ErrorKind::UnsupportedPlatform`].
56//!
57//! # Typestate guarantees
58//!
59//! A joined installer cannot query or control the primary workflow:
60//!
61//! ```compile_fail
62//! fn invalid(joined: &mut restart_manager::JoinedSession) {
63//! let _ = joined.affected_applications();
64//! }
65//! ```
66//!
67//! Restart is not available before a shutdown attempt:
68//!
69//! ```compile_fail
70//! fn invalid(session: restart_manager::RestartSession) {
71//! let _ = session.restart();
72//! }
73//! ```
74//!
75//! A pending recovery state cannot register resources, manipulate filters, or
76//! end the native session:
77//!
78//! ```compile_fail
79//! fn invalid(mut pending: restart_manager::RestartPending) {
80//! let batch = restart_manager::ResourceBatch::new();
81//! let _ = pending.register_resources(&batch);
82//! let _ = pending.end();
83//! }
84//! ```
85//!
86//! Consuming a state prevents a second operation on the same value:
87//!
88//! ```compile_fail
89//! fn invalid(session: restart_manager::RestartSession) {
90//! let _pending = session.shutdown();
91//! let _ = session.end();
92//! }
93//! ```
94#![deny(unsafe_code)]
95
96mod application;
97mod application_restart;
98mod error;
99mod filter;
100mod input;
101mod resource;
102mod session;
103mod shutdown;
104mod sys;
105#[cfg(feature = "tokio")]
106pub mod tokio;
107
108pub use crate::{
109 application::{
110 AffectedApplication, AffectedApplications, ApplicationStatus, ApplicationType,
111 ProcessIdentity, RebootReasons,
112 },
113 application_restart::{ApplicationRestartOptions, ApplicationRestartRegistration},
114 error::{Error, ErrorKind, ParseSessionKeyError, Result},
115 filter::{Filter, FilterAction, FilterTarget},
116 resource::ResourceBatch,
117 session::{
118 CancellationHandle, JoinedSession, OperationNotStarted, RecoveryCompletion, RestartPending,
119 RestartSession, SessionKey,
120 },
121 shutdown::{OperationOutcome, Progress, RecoveryOutcome, ShutdownOptions},
122};