C++编写驱动程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <ntddk.h>

// 宏定义改为 C++ 风格
#define Log(x) DbgPrint("qi:" x)

// DriverUnload 必须使用 extern "C"
extern "C"
void UnloadDriver(PDRIVER_OBJECT DriverObject)
{
Log("Unloaded Successfully!\n");
}

// DriverEntry 也必须使用 extern "C"
extern "C"
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = UnloadDriver;
Log("Loaded Successfully!\n");
return STATUS_SUCCESS;
}

在 Windows 下使用 C++ 开发内核驱动程序 是完全可行的,但需要注意几点特殊事项,因为 Windows 内核是以 C 为主的环境,默认的运行时库和异常处理机制不完全支持 C++。下面会详细说明如何在你的 C 驱动中切换到 C++ 编写方式,包括项目配置、语法规则和注意事项。


✅ 一、如何将驱动改为 C++ 编写

1. 修改源文件扩展名

.c 文件重命名为 .cpp,让编译器使用 C++ 编译器编译该文件。

2. 修改函数声明方式

Windows 驱动的入口函数和卸载函数必须使用 extern "C" 来防止 C++ 名字修饰(name mangling):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <ntddk.h>

// 宏定义改为 C++ 风格
#define Log(x) DbgPrint("qi:" x)

// DriverUnload 必须使用 extern "C"
extern "C"
void UnloadDriver(PDRIVER_OBJECT DriverObject)
{
Log("Unloaded Successfully!\n");
}

// DriverEntry 也必须使用 extern "C"
extern "C"
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = UnloadDriver;
Log("Loaded Successfully!\n");
return STATUS_SUCCESS;
}

✅ 二、配置 Visual Studio 项目使用 C++ 编译驱动

  1. 右键驱动项目 → 属性 → C/C++ → 常规
    • 设置 编译为 为:编译为 C++ 代码 (/TP)
  2. 链接器 → 高级
    • 确保启用了 /INTEGRITYCHECK:NO(除非你在做签名测试)。
  3. 链接器 → 输入
    • 如果你用了 C++ 标准库,请小心!内核驱动不支持用户态 C++ 运行时(如 iostream、std::string、new/delete)。

✅ 三、使用 C++ 类和封装(示例)

你可以在内核驱动中使用 C++ 类来封装逻辑,例如:

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
#include<ntifs.h>

class Logger {
public:
void Info(const char* msg) {
DbgPrint("[LOG] %s\n", msg);
}
};

// 全局对象(尽量避免使用静态构造)
Logger g_Logger;

extern "C"
void UnloadDriver(PDRIVER_OBJECT DriverObject)
{
g_Logger.Info("Driver unloaded.");

}

extern "C"
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
g_Logger.Info("Driver loaded.");
DriverObject->DriverUnload = UnloadDriver;
return STATUS_SUCCESS;
}



⚠️ 注意事项

  1. 不要使用 C++ STL

    • 内核中不能使用 std::string, std::vector, iostream 等,因为这些依赖用户态运行时库。
  2. 不要使用异常机制(try/catch)

    • C++ 异常机制依赖 SEH(结构化异常处理),这在内核中不安全,可能引发不可预期行为甚至蓝屏。
  3. 尽量避免构造/析构全局对象

    • 它们的构造顺序可能不确定,且析构在驱动卸载时可能不会被自动调用。
  4. 使用 new / delete 要自定义内核分配器

    1
    2
    3
    4
    5
    6
    7
    void* operator new(size_t size) {
    return ExAllocatePoolWithTag(NonPagedPool, size, 'Tag1');
    }

    void operator delete(void* ptr) {
    ExFreePoolWithTag(ptr, 'Tag1');
    }

✅ 总结

项目 支持情况
类 / 封装 ✅ 支持
STL ❌ 不建议
异常处理(try/catch) ❌ 不建议
全局构造/析构 ⚠️ 有风险
new/delete ⚠️ 自定义必需
RAII(局部类析构管理资源) ✅ 可用