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