ndisapi/ndisapi.rs
1//! # Module: NDISAPI
2//!
3//! This module provides a high-level interface to the NDISAPI Rust library for communicating with the Windows Packet Filter driver.
4//! It includes the definition and implementation of the `Ndisapi` struct, which represents the main entry point to interact with the driver.
5//!
6//! The NDISAPI module also contains submodules for various aspects of the NDISAPI functionality, such as:
7//! - base_api: Basic API operations
8//! - defs: Definitions of constants, structures, and enumerations
9//! - fastio_api: Fast I/O operations
10//! - filters_api: Filter management and manipulation
11//! - io_api: Basic I/O operations
12//! - static_api: Static and Registry related methods for the NDISAPI
13//!
14//! For a detailed description of each submodule and the `Ndisapi` struct, refer to their respective documentation within the module.
15
16// Imports required dependencies
17use windows::{
18 core::{Result, PCWSTR},
19 Win32::Foundation::CloseHandle,
20 Win32::Foundation::HANDLE,
21 Win32::Storage::FileSystem::{
22 CreateFileW, FILE_FLAG_OVERLAPPED, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,
23 },
24};
25
26// Submodules
27mod base_api;
28mod defs;
29mod fastio_api;
30mod filters_api;
31mod io_api;
32mod static_api;
33
34// Re-exports the `driver` submodule
35pub use crate::driver::*;
36
37// Re-export already public members in `defs.rs`
38pub use crate::ndisapi::defs::{NetworkAdapterInfo, Version};
39
40// Re-export already public members in `fastio_api.rs`
41pub use crate::ndisapi::fastio_api::{IntermediateBufferArray, IntermediateBufferArrayMut};
42
43/// The `Ndisapi` struct represents an instance of the NDIS filter driver that provides access to network adapters and packets.
44///
45/// This struct is used to communicate with the NDIS filter driver and access its functionalities. It contains a single field, `driver_handle`,
46/// which represents a handle to the driver. This handle is used to perform operations such as reading and writing packets, setting filters, and
47/// getting information about network adapters.
48///
49/// To use `Ndisapi`, you should first create an instance of the struct by calling the `Ndisapi::new()` function. This will return a `Result`
50/// that contains an instance of `Ndisapi` if the operation was successful, or an error if it failed. Once you have an instance of `Ndisapi`,
51/// you can call its methods to perform various network-related operations.
52///
53/// For example, you can use the `Ndisapi::read_packets()` method to read packets from the network adapter, or the `Ndisapi::send_packets_to_adapter()`
54/// method to write packets to the network adapter. You can also use the `Ndisapi::set_packet_filter_table()` method to set a filter that specifies which
55/// packets should be captured or dropped.
56#[derive(Debug, Clone)]
57pub struct Ndisapi {
58 // Represents a handle to the NDIS filter driver.
59 driver_handle: HANDLE,
60 // Stores the driver registry key for parameters
61 registry_key: Vec<u16>,
62}
63
64// Implements the Drop trait for the `Ndisapi` struct
65impl Drop for Ndisapi {
66 // Provides a custom implementation for the `drop` method
67 fn drop(&mut self) {
68 // Closes the driver_handle when the `Ndisapi` instance goes out of scope
69 let _ = unsafe { CloseHandle(self.driver_handle) };
70 }
71}
72
73// Implements additional methods for the `Ndisapi` struct
74impl Ndisapi {
75 /// Initializes new Ndisapi instance opening the NDIS filter driver
76 ///
77 /// # Arguments
78 ///
79 /// * `driver_name` - The name of the file representing the NDIS filter driver.
80 ///
81 /// # Returns
82 ///
83 /// * `Result<Self>` - A Result containing the Ndisapi instance if successful, or an error if not.
84 ///
85 /// # Examples
86 ///
87 /// ```no_run
88 /// use ndisapi::Ndisapi;
89 /// let ndisapi = Ndisapi::new("NDISRD").unwrap();
90 /// ```
91 pub fn new(driver_name: &str) -> Result<Self> {
92 // Create the filename and driver parameters registry path
93 let filename = format!(r"\\.\{driver_name}");
94 let registry_key = format!(r"SYSTEM\CurrentControlSet\Services\{driver_name}\Parameters");
95 let mut filename: Vec<u16> = filename.encode_utf16().collect();
96 let mut registry_key: Vec<u16> = registry_key.encode_utf16().collect();
97 filename.push(0);
98 registry_key.push(0);
99
100 // Attempts to create a file handle for the NDIS filter driver
101 match unsafe {
102 CreateFileW(
103 PCWSTR::from_raw(filename.as_ptr()),
104 0u32,
105 FILE_SHARE_READ | FILE_SHARE_WRITE,
106 None,
107 OPEN_EXISTING,
108 FILE_FLAG_OVERLAPPED,
109 None,
110 )
111 } {
112 Ok(driver_handle) => Ok(Self {
113 driver_handle,
114 registry_key,
115 }),
116 Err(e) => Err(e),
117 }
118 }
119
120 pub fn get_driver_registry_key(&self) -> PCWSTR {
121 PCWSTR::from_raw(self.registry_key.as_ptr())
122 }
123}