windows_rpc/
server_binding.rs

1//! RPC server binding management.
2//!
3//! This module provides types for creating and managing RPC server bindings,
4//! which control the server lifecycle: registration, listening, and shutdown.
5
6use std::ffi::c_void;
7use windows::Win32::System::Rpc::{
8    RPC_C_LISTEN_MAX_CALLS_DEFAULT, RpcMgmtStopServerListening, RpcServerListen,
9    RpcServerRegisterIf3, RpcServerUnregisterIf, RpcServerUseProtseqEpW,
10};
11use windows::core::{Error, HSTRING, PCWSTR};
12
13use crate::ProtocolSequence;
14
15/// Manages the lifecycle of an RPC server.
16///
17/// This struct handles the low-level details of registering an RPC interface
18/// with the Windows RPC runtime and managing the listen/stop lifecycle.
19///
20/// # Note
21///
22/// You typically don't create `ServerBinding` directly. Instead, use the
23/// generated `{Interface}Server` struct which manages this for you.
24///
25/// # Example
26///
27/// ```rust,no_run
28/// use windows_rpc::rpc_interface;
29///
30/// #[rpc_interface(guid(0x12345678_1234_1234_1234_123456789abc), version(1.0))]
31/// trait MyInterface {
32///     fn hello() -> i32;
33/// }
34///
35/// struct MyImpl;
36/// impl MyInterfaceServerImpl for MyImpl {
37///     fn hello() -> i32 { 42 }
38/// }
39///
40/// # fn main() -> windows::core::Result<()> {
41/// let mut server = MyInterfaceServer::<MyImpl>::new();
42/// server.register("my_endpoint")?;
43/// server.listen_async()?;
44/// // ... server is now accepting calls ...
45/// server.stop()?;
46/// # Ok(())
47/// # }
48/// ```
49pub struct ServerBinding {
50    protocol: ProtocolSequence,
51    endpoint: String,
52    interface_handle: *const c_void,
53    registered: bool,
54}
55
56impl ServerBinding {
57    /// Creates a new server binding for the specified endpoint.
58    ///
59    /// This registers the protocol sequence and endpoint with the RPC runtime,
60    /// but does not yet register the interface. Call [`register()`](Self::register)
61    /// to complete the registration.
62    ///
63    /// # Arguments
64    ///
65    /// * `protocol` - The protocol sequence to use
66    /// * `endpoint` - The endpoint name clients will connect to
67    /// * `interface_handle` - Pointer to the RPC interface specification
68    ///
69    /// # Errors
70    ///
71    /// Returns an error if the protocol sequence and endpoint cannot be registered.
72    pub fn new(
73        protocol: ProtocolSequence,
74        endpoint: impl Into<String>,
75        interface_handle: *const c_void,
76    ) -> Result<Self, Error> {
77        let endpoint = endpoint.into();
78        let endpoint_hstring = HSTRING::from(&endpoint);
79
80        // Register the protocol sequence and endpoint
81        unsafe {
82            RpcServerUseProtseqEpW(
83                protocol.to_pcwstr(),
84                RPC_C_LISTEN_MAX_CALLS_DEFAULT,
85                PCWSTR::from_raw(endpoint_hstring.as_ptr()),
86                None, // No security descriptor
87            )
88            .ok()?;
89        }
90
91        Ok(ServerBinding {
92            protocol,
93            endpoint,
94            interface_handle,
95            registered: false,
96        })
97    }
98
99    /// Registers the RPC interface with the runtime.
100    ///
101    /// After registration, the server can begin accepting calls. This method
102    /// is idempotent - calling it multiple times has no effect.
103    ///
104    /// # Errors
105    ///
106    /// Returns an error if the interface cannot be registered.
107    pub fn register(&mut self) -> Result<(), Error> {
108        if self.registered {
109            return Ok(());
110        }
111
112        unsafe {
113            RpcServerRegisterIf3(
114                self.interface_handle,
115                None, // Interface UUID (use from handle)
116                None, // Manager EPV
117                0,    // Flags
118                RPC_C_LISTEN_MAX_CALLS_DEFAULT,
119                u32::MAX, // Max RPC size
120                None,     // Security callback
121                None,     // Security descriptor
122            )
123            .ok()?;
124        }
125
126        self.registered = true;
127        Ok(())
128    }
129
130    /// Starts listening for RPC calls (blocking).
131    ///
132    /// This method blocks the current thread until [`stop()`](Self::stop) is called
133    /// from another thread. Use [`listen_async()`](Self::listen_async) for non-blocking
134    /// operation.
135    ///
136    /// # Errors
137    ///
138    /// Returns an error if:
139    /// - The interface has not been registered
140    /// - The RPC runtime fails to start listening
141    pub fn listen(&self) -> Result<(), Error> {
142        if !self.registered {
143            return Err(Error::from_hresult(windows::core::HRESULT(-1)));
144        }
145
146        unsafe {
147            RpcServerListen(
148                1, // MinimumCallThreads
149                RPC_C_LISTEN_MAX_CALLS_DEFAULT,
150                0, // DontWait = false (blocking)
151            )
152            .ok()?;
153        }
154
155        Ok(())
156    }
157
158    /// Starts listening for RPC calls (non-blocking).
159    ///
160    /// Returns immediately while RPC calls are processed in background threads
161    /// managed by the Windows RPC runtime. Call [`stop()`](Self::stop) to shut
162    /// down the server.
163    ///
164    /// This is the recommended mode for most applications as it allows the main
165    /// thread to continue other work or wait for a shutdown signal.
166    ///
167    /// # Errors
168    ///
169    /// Returns an error if:
170    /// - The interface has not been registered
171    /// - The RPC runtime fails to start listening
172    pub fn listen_async(&self) -> Result<(), Error> {
173        if !self.registered {
174            return Err(Error::from_hresult(windows::core::HRESULT(-1)));
175        }
176
177        unsafe {
178            RpcServerListen(
179                1, // MinimumCallThreads
180                RPC_C_LISTEN_MAX_CALLS_DEFAULT,
181                1, // DontWait = true (non-blocking)
182            )
183            .ok()?;
184        }
185
186        Ok(())
187    }
188
189    /// Stops the server from accepting new RPC calls.
190    ///
191    /// Outstanding calls may still complete. For a blocking server, this will
192    /// cause [`listen()`](Self::listen) to return.
193    ///
194    /// # Errors
195    ///
196    /// Returns an error if the RPC runtime fails to stop.
197    pub fn stop(&self) -> Result<(), Error> {
198        unsafe {
199            RpcMgmtStopServerListening(None).ok()?;
200        }
201        Ok(())
202    }
203
204    /// Unregisters the RPC interface.
205    ///
206    /// This is called automatically when the `ServerBinding` is dropped.
207    ///
208    /// # Errors
209    ///
210    /// Returns an error if the interface cannot be unregistered.
211    pub fn unregister(&mut self) -> Result<(), Error> {
212        if !self.registered {
213            return Ok(());
214        }
215
216        unsafe {
217            RpcServerUnregisterIf(Some(self.interface_handle), None, 1).ok()?;
218        }
219
220        self.registered = false;
221        Ok(())
222    }
223
224    /// Returns the endpoint name.
225    pub fn endpoint(&self) -> &str {
226        &self.endpoint
227    }
228
229    /// Returns the protocol sequence.
230    pub fn protocol(&self) -> ProtocolSequence {
231        self.protocol
232    }
233}
234
235impl Drop for ServerBinding {
236    fn drop(&mut self) {
237        // Best effort cleanup
238        let _ = self.unregister();
239    }
240}