windows_rpc/client_binding.rs
1//! RPC client binding management.
2//!
3//! This module provides types for creating and managing RPC client bindings,
4//! which are used to connect to RPC servers.
5
6use std::{ffi::c_void, ptr};
7
8use windows::{
9 Win32::System::Rpc::{RpcBindingFromStringBindingW, RpcStringBindingComposeW},
10 core::HSTRING,
11};
12
13use crate::ProtocolSequence;
14
15/// An RPC client binding handle.
16///
17/// Represents a connection endpoint for making RPC calls to a server. The binding
18/// encapsulates the protocol, endpoint, and other connection parameters.
19///
20/// # Example
21///
22/// ```rust,no_run
23/// # use windows_rpc::rpc_interface;
24/// #
25/// # #[rpc_interface(guid(0x12345678_1234_1234_1234_123456789abc), version(1.0))]
26/// # trait MyInterface {
27/// # }
28/// use windows_rpc::{ProtocolSequence, client_binding::ClientBinding};
29///
30/// # fn main() -> windows::core::Result<()> {
31/// let binding = ClientBinding::new(ProtocolSequence::Alpc, "my_endpoint")?;
32/// let client = MyInterfaceClient::new(binding);
33/// # Ok(())
34/// # }
35/// ```
36///
37/// # Lifetime
38///
39/// The binding handle must remain valid for the lifetime of any client using it.
40/// The generated client structs take ownership of the binding.
41pub struct ClientBinding {
42 handle: *mut c_void,
43}
44
45impl ClientBinding {
46 /// Creates a new client binding to the specified endpoint.
47 ///
48 /// # Arguments
49 ///
50 /// * `protocol` - The protocol sequence to use for communication
51 /// * `endpoint` - The server endpoint name (e.g., "my_rpc_endpoint")
52 ///
53 /// # Errors
54 ///
55 /// Returns an error if:
56 /// - The binding string cannot be composed
57 /// - The binding handle cannot be created from the string
58 ///
59 /// # Example
60 ///
61 /// ```rust
62 /// use windows_rpc::{ProtocolSequence, client_binding::ClientBinding};
63 ///
64 /// # fn main() -> windows::core::Result<()> {
65 /// let binding = ClientBinding::new(ProtocolSequence::Alpc, "calculator_endpoint")?;
66 /// # Ok(())
67 /// # }
68 /// ```
69 pub fn new(protocol: ProtocolSequence, endpoint: &str) -> windows::core::Result<Self> {
70 let mut string_binding = windows::core::PWSTR::null();
71 unsafe {
72 RpcStringBindingComposeW(
73 // TODO: pass obj uuid, could replace the endpoint/network addr
74 None,
75 protocol.to_pcwstr(),
76 None,
77 &HSTRING::from(endpoint),
78 None,
79 Some(&raw mut string_binding),
80 )
81 }
82 .ok()?;
83
84 let mut handle: *mut core::ffi::c_void = ptr::null_mut();
85 unsafe { RpcBindingFromStringBindingW(string_binding, &raw mut handle) }.ok()?;
86
87 Ok(Self { handle })
88 }
89
90 /// Returns the raw RPC binding handle.
91 ///
92 /// This is used internally by the generated client code to make RPC calls.
93 #[doc(hidden)]
94 pub fn handle(&self) -> *mut c_void {
95 self.handle
96 }
97}