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}