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}