windows_rpc/
lib.rs

1//! Windows RPC client and server library for Rust.
2//!
3//! This crate, together with [`windows_rpc_macros`](https://docs.rs/windows-rpc-macros), provides
4//! a way to define Windows RPC interfaces using Rust traits and automatically generate all the
5//! necessary client and server code. The generated code handles NDR (Network Data Representation)
6//! marshalling, format strings, and Windows RPC runtime integration.
7//!
8//! # Quick Start
9//!
10//! Define an RPC interface as a trait with the [`rpc_interface`] macro:
11//!
12//! ```rust
13//! use windows_rpc::rpc_interface;
14//! use windows_rpc::{ProtocolSequence, client_binding::ClientBinding};
15//!
16//! #[rpc_interface(guid(0x12345678_1234_1234_1234_123456789abc), version(1.0))]
17//! trait Calculator {
18//!     fn add(a: i32, b: i32) -> i32;
19//!     fn multiply(x: i32, y: i32) -> i32;
20//! }
21//! ```
22//!
23//! This generates three types:
24//! - `CalculatorClient` - for making RPC calls
25//! - `CalculatorServerImpl` - trait to implement for the server
26//! - `CalculatorServer` - wraps your implementation for RPC dispatch
27//!
28//! # Server Example
29//!
30//! ```rust,no_run
31//! use windows_rpc::rpc_interface;
32//!
33//! #[rpc_interface(guid(0x12345678_1234_1234_1234_123456789abc), version(1.0))]
34//! trait Calculator {
35//!     fn add(a: i32, b: i32) -> i32;
36//! }
37//!
38//! struct CalculatorImpl;
39//!
40//! impl CalculatorServerImpl for CalculatorImpl {
41//!     fn add(&self, a: i32, b: i32) -> i32 {
42//!         a + b
43//!     }
44//! }
45//!
46//! fn main() -> Result<(), Box<dyn std::error::Error>> {
47//!     let mut server = CalculatorServer::new(CalculatorImpl);
48//!     server.register("calculator_endpoint")?;
49//!
50//!     // Non-blocking: returns immediately, processes calls in background
51//!     server.listen_async()?;
52//!
53//!     // ... do other work or wait for shutdown signal ...
54//!
55//!     server.stop()?;
56//!     Ok(())
57//! }
58//! ```
59//!
60//! # Client Example
61//!
62//! ```rust,no_run
63//! use windows_rpc::rpc_interface;
64//! use windows_rpc::{ProtocolSequence, client_binding::ClientBinding};
65//!
66//! #[rpc_interface(guid(0x12345678_1234_1234_1234_123456789abc), version(1.0))]
67//! trait Calculator {
68//!     fn add(a: i32, b: i32) -> i32;
69//! }
70//!
71//! fn main() -> Result<(), Box<dyn std::error::Error>> {
72//!     let binding = ClientBinding::new(ProtocolSequence::Alpc, "calculator_endpoint")?;
73//!     let client = CalculatorClient::new(binding);
74//!
75//!     let result = client.add(10, 20);
76//!     println!("10 + 20 = {result}");  // Prints: 10 + 20 = 30
77//!
78//!     Ok(())
79//! }
80//! ```
81//!
82//! # Supported Types
83//!
84//! The following types can be used for parameters and return values:
85//!
86//! | Rust Type | Description |
87//! |-----------|-------------|
88//! | `i8`, `u8` | 8-bit integers |
89//! | `i16`, `u16` | 16-bit integers |
90//! | `i32`, `u32` | 32-bit integers |
91//! | `i64`, `u64` | 64-bit integers |
92//! | `&str` | String (input parameters only) |
93//!
94//! # Protocol Support
95//!
96//! Currently only ALPC (Advanced Local Procedure Call) is supported via the `ncalrpc`
97//! protocol sequence. This allows RPC communication between processes on the same machine.
98//!
99//! # What This Library Does
100//!
101//! - Generates all MIDL stub metadata (`MIDL_STUB_DESC`, `MIDL_SERVER_INFO`, etc.)
102//! - Handles NDR 2.0 and NDR64 format strings for type marshalling
103//! - Manages RPC binding handles and server lifecycle
104//! - Converts between Rust types and Windows ABI types
105//! - Provides clean async (non-blocking) and sync (blocking) server modes
106//!
107//! # Limitations
108//!
109//! This library is currently limited in scope:
110//!
111//! - **Protocol**: Only local RPC (ALPC/ncalrpc) is supported. TCP, UDP, and named pipes
112//!   are not yet implemented.
113//! - **Parameter direction**: Only input (`[in]`) parameters are supported. Output and
114//!   input-output parameters are not available.
115//! - **Types**: Only primitive integers and strings are supported. No pointers, structs,
116//!   arrays, unions, or other complex types.
117//! - **Strings**: The `&str` type is only supported for input parameters, not return values.
118//! - **Security**: No interface security (authentication, authorization, encryption) is
119//!   implemented.
120//! - **Exceptions**: SEH exceptions from the RPC runtime are not caught or handled.
121//! - **Callbacks**: RPC callbacks from server to client are not supported.
122//!
123//! # Interoperability
124//!
125//! The generated code produces standard Windows RPC interfaces that are compatible with
126//! MIDL-generated C/C++ clients and servers. You can use a Rust server with a C++ client
127//! (or vice versa) as long as the interface GUID, version, and method signatures match.
128//!
129//! # Safety
130//!
131//! This crate uses `unsafe` code extensively to interact with the Windows RPC runtime.
132//! The generated client and server code manages memory carefully to ensure:
133//!
134//! - RPC metadata structures remain valid for the lifetime of the client/server
135//! - String conversions between Rust and Windows types are handled correctly
136//! - Thread-local context is used safely for server dispatch
137//!
138//! However, bugs in this crate could lead to memory corruption or undefined behavior.
139#![cfg(windows)]
140
141#[doc(hidden)]
142pub mod alloc;
143pub mod client_binding;
144#[doc(hidden)]
145pub mod server;
146pub mod server_binding;
147
148pub use windows_rpc_macros::rpc_interface;
149
150/// Protocol sequence for RPC communication.
151///
152/// Specifies the transport protocol used for RPC calls.
153///
154/// # Example
155///
156/// ```rust,no_run
157/// use windows_rpc::{ProtocolSequence, client_binding::ClientBinding};
158///
159/// # fn main() -> windows::core::Result<()> {
160/// // Connect using local RPC (ALPC)
161/// let binding = ClientBinding::new(ProtocolSequence::Alpc, "my_endpoint")?;
162/// # Ok(())
163/// # }
164/// ```
165#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
166pub enum ProtocolSequence {
167    /// ALPC (Advanced Local Procedure Call) - local RPC on the same machine.
168    ///
169    /// Uses the `ncalrpc` protocol sequence. This is the fastest option for
170    /// communication between processes on the same Windows machine.
171    Alpc,
172    // TODO: test and add
173    //Tcp,
174    //Udp,
175    //NamedPipe
176}
177
178impl ProtocolSequence {
179    fn to_pcwstr(self) -> windows::core::PCWSTR {
180        match self {
181            ProtocolSequence::Alpc => windows::core::w!("ncalrpc"),
182        }
183    }
184}