#nt #list-entry #single-list-entry

no-std nt-list

兼容的、类型安全的、符合Rust语法的Windows NT链接列表实现

4个版本 (2个破坏性更新)

0.3.0 2023年10月19日
0.2.1 2023年10月19日
0.2.0 2022年10月27日
0.1.0 2022年7月28日

#301Windows APIs

MIT/Apache

84KB
1K SLoC

nt-list

crates.io docs.rs license: MIT OR Apache-2.0

由 Colin Finck <[email protected]>

提供兼容的、类型安全的、符合Rust语法的Windows NT链接列表实现,称为LIST_ENTRYSINGLE_LIST_ENTRY

行动中的示例


在WinDbg中调试Rust应用程序并使用!list扩展遍历双链表。这是nt-listLIST_ENTRY之间兼容性的证明。

详细信息

这种格式的单链表和双链表是Windows自身以及为Windows编写的驱动程序中广泛使用的根本性数据结构。在双链表的情况下,Windows定义了一个包含指向其他LIST_ENTRY结构的正向和反向指针的LIST_ENTRY结构。然后LIST_ENTRY被嵌入到您的自己的元素结构中。有关Windows中链接列表的更多详细信息,请参阅相关Microsoft文档

此设计具有与教科书中的链接列表实现不同的几个特性

  • 单个元素可以属于多个列表(通过具有多个LIST_ENTRY字段)。
  • 您负责只将同一类型的元素推送到列表中。没有类型安全性,C/C++编译器无法阻止您将不同类型的元素添加到同一列表中。
  • 链接指向元素中的 LIST_ENTRY 字段,而不是指向元素本身。您需要使用 CONTAINING_RECORD 来检索相应的元素结构,并且您负责传递给该宏的所有参数。

nt-list crate 为这些列表引入了类型安全,将一些责任从用户转移到编译器。此外,它提供了一个类似于 LinkedListVec 的 Rust 接口。

示例

使用 nt-list 创建链表归结为以下三个步骤

  1. 您定义一个空的枚举来标识您的列表(在推送元素时保证类型安全),并派生 NtList(双向链表)或 NtSingleList(单向链表)。
  2. 您定义您的元素结构,声明一个条目作为 #[boxed](如果需要),并派生 NtListElement
  3. 您使用元素结构和空枚举作为类型参数,调用相应列表实现的 new

所有这些加在一起看起来像

#[derive(NtSingleList)]
enum MyList {}

#[derive(Default, NtListElement)]
#[repr(C)]
struct MyElement {
    #[boxed]
    entry: NtSingleListEntry<Self, MyList>,
    value: i32,
}

fn test() {
    let mut list = NtBoxingSingleListHead::<MyElement, MyList>::new();

    list.push_back(MyElement {
        value: 42,
        ..Default::default()
    });

    for element in list.iter() {
        println!("{}", element.value);
    }
}

查看 list 模块级别的文档 以获取双向链表的示例。

no_std 支持

该 crate 与 no_std 兼容,因此可以从固件级别的代码到用户模式应用程序使用。

为了在 NtBoxingListHeadNtBoxingSingleListHead 中支持堆分配,该 crate 依赖于 alloc 库。如果您想在纯 no_std 环境中使用该 crate 而不进行堆分配,请使用 default-features = false 包含它以禁用默认的 alloc 功能。

许可协议

此 crate 可在以下任一项许可协议下使用:

任选其一。

除非您明确表示,否则,您故意提交以包含在您的工作中的任何贡献,根据 Apache-2.0 许可协议定义,应如上所述双许可,不附加任何额外条款或条件。

依赖项

~340–780KB
~18K SLoC