1. windows应用程序进程间怎么互相通信?

方法一:共享内存

方法二:共享内存

方法三:网络通信

方法一:管道通信的完整代码

管道通信需要一个服务端与一个客户端。在服务端创建管道,在客户端读取管道。

1.server.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// server.c : This file contains the 'main' function. Program execution begins and ends there.

#include <stdio.h>
#include <windows.h>

int main()
{
HANDLE hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\MyPipe"),
PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1, 1024, 1024, 0, NULL);

ConnectNamedPipe(hPipe, NULL);

char buffer[128];
DWORD bytesRead;
ReadFile(hPipe, buffer, sizeof(buffer), &bytesRead, NULL);

printf("Received: %s\n", buffer);

WriteFile(hPipe, "Hello from server", 17, &bytesRead, NULL);
CloseHandle(hPipe);

}

2.client.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// client.cpp : This file contains the 'main' function. Program execution begins and ends there.

#include <stdio.h>
#include <windows.h>

int main()
{
HANDLE hPipe = CreateFile(TEXT("\\\\.\\pipe\\MyPipe"),
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

DWORD bytesRead;
WriteFile(hPipe, "Hello from client", 17, &bytesRead, NULL);

char buffer[128];
ReadFile(hPipe, buffer, sizeof(buffer), &bytesRead, NULL);

printf("Server replied: %s\n", buffer);
CloseHandle(hPipe);

}

2. 驱动程序与应用程序怎么通信?

应用层程序中需要创建文件后打开文件来发送消息。

驱动程序中需要添加创建文件->打开文件->接受控制码->关闭文件,这四种基本功能。

应用层调用方式 驱动层处理方式 描述
DeviceIoControl IRP_MJ_DEVICE_CONTROL 最灵活、最常用于应用层与驱动通信
ReadFile / WriteFile IRP_MJ_READ / IRP_MJ_WRITE 用于数据读写
CreateFile IRP_MJ_CREATE 打开设备
CloseHandle IRP_MJ_CLOSE 关闭设备句柄

1.在驱动程序中处理创建设备消息与关闭设备消息。

  1. 应用层程序代码

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

    int main() {
    //创建设备
    HANDLE hDevice = CreateFile(
    L"\\\\.\\MyMinimalDevice",
    GENERIC_READ | GENERIC_WRITE,
    0, NULL, OPEN_EXISTING, 0, NULL);

    if (hDevice == INVALID_HANDLE_VALUE) {
    printf("无法打开设备: 错误码 = %d\n", GetLastError());
    return 1;
    }

    printf("设备打开成功。\n");
    //关闭设备
    CloseHandle(hDevice);
    return 0;
    }

  2. 驱动程序代码

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

#define DEVICE_NAME L"\\Device\\MyMinimalDevice"
#define SYMBOLIC_NAME L"\\DosDevices\\MyMinimalDevice"
#define Log(X) DbgPrint("qi:"X##);
PDEVICE_OBJECT g_DeviceObject = NULL; // 全局设备对象

// 函数声明
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);

// 新增:封装设备创建与删除
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
VOID DeleteDeviceAndSymbolicLink();

// DriverEntry: 初始化驱动

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);

NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
if (!NT_SUCCESS(status)) {
return status;
}

DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->DriverUnload = UnloadDriver;

Log("Minimal Driver loaded.\n");
return STATUS_SUCCESS;
}

// 驱动卸载时调用

VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);

DeleteDeviceAndSymbolicLink();
Log("Minimal Driver unloaded.\n");
}

// IRP_MJ_CREATE 处理函数

NTSTATUS DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
Log("IRP_MJ_CREATE received: 设备被打开。\n");

Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}


// IRP_MJ_CLOSE 处理函数

NTSTATUS DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
Log("IRP_MJ_CLOSE received: 设备被关闭。\n");

Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}

//创建设备和符号链接
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);

NTSTATUS status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&g_DeviceObject
);

if (!NT_SUCCESS(status)) {
return status;
}

status = IoCreateSymbolicLink(&symLinkName, &deviceName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
return status;
}

return STATUS_SUCCESS;
}

// 删除设备和符号链接
VOID DeleteDeviceAndSymbolicLink()
{
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);

IoDeleteSymbolicLink(&symLinkName);

if (g_DeviceObject != NULL) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}
}

2.添加read与write功能

  1. 用户层程序使用ReadFile 和 WriteFile通信

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

    #define DEVICE_NAME "\\\\.\\MyMinimalDevice"
    #define BUFFER_SIZE 1024

    BOOL WriteToDevice(HANDLE hDevice, const char* data, DWORD length) {
    DWORD bytesWritten;
    return WriteFile(hDevice, data, length, &bytesWritten, NULL);
    }

    BOOL ReadFromDevice(HANDLE hDevice, char* buffer, DWORD bufferSize, DWORD* bytesRead) {
    return ReadFile(hDevice, buffer, bufferSize, bytesRead, NULL);
    }

    int main() {
    HANDLE hDevice = CreateFileA(
    DEVICE_NAME,
    GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    0,
    NULL
    );

    if (hDevice == INVALID_HANDLE_VALUE) {
    printf("打开设备失败: %d\n", GetLastError());
    return 1;
    }

    const char* message = "Hello from user!";
    if (!WriteToDevice(hDevice, message, (DWORD)strlen(message))) {
    printf("写入失败: %d\n", GetLastError());
    CloseHandle(hDevice);
    return 1;
    }

    char buffer[BUFFER_SIZE] = {0};
    DWORD bytesRead = 0;

    if (!ReadFromDevice(hDevice, buffer, BUFFER_SIZE, &bytesRead)) {
    printf("读取失败: %d\n", GetLastError());
    CloseHandle(hDevice);
    return 1;
    }

    printf("读取成功 (%lu 字节): %.*s\n", bytesRead, bytesRead, buffer);

    CloseHandle(hDevice);
    return 0;
    }

  2. 驱动程序添加read与write消息处理

    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
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    #include <ntddk.h>

    #define DEVICE_NAME L"\\Device\\MyMinimalDevice"
    #define SYMBOLIC_NAME L"\\DosDevices\\MyMinimalDevice"
    #define Log(X) DbgPrint("qi:" X);

    PDEVICE_OBJECT g_DeviceObject = NULL;

    // 缓冲区及长度(简单实现:全局模拟内存)
    #define BUFFER_SIZE 1024
    CHAR g_Buffer[BUFFER_SIZE] = { 0 };
    ULONG g_BufferLength = 0;

    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
    VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
    NTSTATUS DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS DispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS DispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
    VOID DeleteDeviceAndSymbolicLink();

    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
    {
    UNREFERENCED_PARAMETER(RegistryPath);

    NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
    if (!NT_SUCCESS(status)) return status;

    DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
    DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
    DriverObject->DriverUnload = UnloadDriver;

    Log("Minimal Driver loaded.\n");
    return STATUS_SUCCESS;
    }

    VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
    {
    UNREFERENCED_PARAMETER(DriverObject);
    DeleteDeviceAndSymbolicLink();
    Log("Minimal Driver unloaded.\n");
    }

    NTSTATUS DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);
    Log("IRP_MJ_CREATE received\n");

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
    }

    NTSTATUS DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);
    Log("IRP_MJ_CLOSE received\n");

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
    }

    NTSTATUS DispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG length = stack->Parameters.Read.Length;

    ULONG bytesToCopy = min(length, g_BufferLength);
    if (bytesToCopy > 0)
    RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, g_Buffer, bytesToCopy);

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = bytesToCopy;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    Log("IRP_MJ_READ done\n");
    return STATUS_SUCCESS;
    }

    NTSTATUS DispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG length = stack->Parameters.Write.Length;

    ULONG bytesToCopy = min(length, BUFFER_SIZE);
    RtlCopyMemory(g_Buffer, Irp->AssociatedIrp.SystemBuffer, bytesToCopy);
    g_BufferLength = bytesToCopy;

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = bytesToCopy;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    Log("IRP_MJ_WRITE done\n");
    return STATUS_SUCCESS;
    }

    NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
    {
    UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
    UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);

    NTSTATUS status = IoCreateDevice(
    DriverObject,
    0,
    &deviceName,
    FILE_DEVICE_UNKNOWN,
    FILE_DEVICE_SECURE_OPEN,
    FALSE,
    &g_DeviceObject
    );
    if (!NT_SUCCESS(status))
    return status;

    // —— 关键:开启 Buffered I/O
    g_DeviceObject->Flags |= DO_BUFFERED_IO;

    status = IoCreateSymbolicLink(&symLinkName, &deviceName);
    if (!NT_SUCCESS(status)) {
    IoDeleteDevice(g_DeviceObject);
    return status;
    }

    return STATUS_SUCCESS;
    }


    VOID DeleteDeviceAndSymbolicLink()
    {
    UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
    IoDeleteSymbolicLink(&symLinkName);
    if (g_DeviceObject) IoDeleteDevice(g_DeviceObject);
    }

3. 在驱动程序中添加控制码功能,根据控制码来处理创建设置与关闭设备的消息

1.驱动层代码

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
126
127
128
129
130
131
132
#include<ntifs.h>

#define r3 L"\\??\\MyDriver"
#define Log(X) DbgPrint("qi:" X##);

NTSTATUS CreateDevice(PDRIVER_OBJECT driver);//driver驱动对象
void DeleteDevice(PDRIVER_OBJECT pDriver);//删除设备对象

NTSTATUS IRP_CALL(PDEVICE_OBJECT device, PIRP prip)
{
device;
prip;

Log("进入派遣函数\n");
PIO_STACK_LOCATION irpStackL;
//ULONG CtlCode;
//ULONG InputBuffLength;

irpStackL = IoGetCurrentIrpStackLocation(prip);//获取应用层传来的参数

switch (irpStackL->MajorFunction)
{
//case IRP_MJ_DEVICE_CONTROL://DeviceIoControl
//{
// Log(用户层调用了 DeviceIoControl\n");
// break;
//}
case IRP_MJ_CREATE://CreateFile
{
Log("用户层调用了 CreateFile\n");
break;
}
case IRP_MJ_CLOSE: //CloseHandle
{
Log("用户层调用了CloseHandle\n");
break;
}
}


prip->IoStatus.Status = STATUS_SUCCESS;
prip->IoStatus.Information = 4;//返回给DeviceIoControl中的倒数第二个参数IpBytesReturned
IoCompleteRequest(prip, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作 并且不增加优先级
Log("离开派遣函数\n");
return STATUS_SUCCESS; //0返回成功
}
//卸载驱动时会被调用
void DriverUnload(PDRIVER_OBJECT DriverObject)
{
//并且 删除符号链接 删除驱动设备
Log("进入卸载例程driver=%p", DriverObject);
DeleteDevice(DriverObject);
}

//加载驱动时会被调用
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
DriverObject->DriverUnload = DriverUnload; //注册卸载例程 回调函数
DriverObject->MajorFunction[IRP_MJ_CREATE] = IRP_CALL;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = IRP_CALL;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IRP_CALL;
CreateDevice(DriverObject);//创建驱动设备

Log("进入 DriverEntry入口点\nDriverObject=%p\n行号=%d\n", DriverObject, __LINE__);//Debug
//Log("RegistryPath=%s\n", RegistryPath->Buffer);//多字节字符集
Log("RegistryPath=%ws\n", RegistryPath->Buffer);//Unicode 宽字符
return 0;//成功

}

//创建驱动设备对象
NTSTATUS CreateDevice(PDRIVER_OBJECT driver)//driver驱动对象
{
NTSTATUS status;
UNICODE_STRING MyDriver; //驱动字符串
PDEVICE_OBJECT device = NULL;//用于存放设备对象
RtlInitUnicodeString(&MyDriver, L"\\DEVICE\\MyDriver");//驱动设备名字 \\DEVICE\\名字

status = IoCreateDevice(driver,
sizeof(driver->DriverExtension),
&MyDriver,//驱动设备名字
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&device //返回 驱动设备指针
);
if (status == STATUS_SUCCESS)//STATUS_SUCCESS)
{
Log("驱动设备对象创建成功,OK \n");
//创建符号链接
UNICODE_STRING uzSymbolName;//符号链接名字
// L"\\??\\名字
RtlInitUnicodeString(&uzSymbolName, r3);//createFile ReadFile WriteFile DevicIoControl IRP_MJ_CREATE
status = IoCreateSymbolicLink(&uzSymbolName, &MyDriver);
if (status == STATUS_SUCCESS)
{
Log("创建符号链接 %wZ 成功 \n", &uzSymbolName);
}
else
{
Log("创建符号链接 %wZ 失败 status=%X \n", &uzSymbolName, status);
}
}
else
{
Log("驱动设备对象创建失败,删除设备\n");
IoDeleteDevice(device);
}
return status;
}

void DeleteDevice(PDRIVER_OBJECT pDriver)
{
Log("进入了 DeleteDevice例程\n");
if (pDriver->DeviceObject) //驱动设备指针
{
//删除符号链接

UNICODE_STRING uzSymbolName;//符号链接名字
RtlInitUnicodeString(&uzSymbolName, r3);//createFile
Log("删除符号链接=%wz\n", &uzSymbolName);
IoDeleteSymbolicLink(&uzSymbolName);
//
Log("删除驱动设备\n");
IoDeleteDevice(pDriver->DeviceObject);//删除设备对象
}
Log("退出 DeleteDevice例程\n");
}
  1. 应用层代码

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

    #define DEVICE_PATH L"\\\\.\\MyDriver" // ← 用户层要打开的设备名
    static HANDLE DeviceHandle = NULL;

    int main()
    {
    DeviceHandle = CreateFileW(
    DEVICE_PATH, // 这里改为 "\\\\.\\MyDriver"
    GENERIC_READ | GENERIC_WRITE, // 读写权限
    0, // 通常设备不需要共享,设为 0 即可
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL
    );
    if (DeviceHandle == INVALID_HANDLE_VALUE)
    {
    wchar_t msg[256];
    wsprintfW(msg, L"打开设备失败!\nHandle=%p, Error=%d",
    DeviceHandle, GetLastError());
    MessageBoxW(NULL, msg, L"Error", MB_OK);
    return 1;
    }

    // 这里只做了打开/关闭,驱动会打印 CreateFile/CloseHandle 的日志
    CloseHandle(DeviceHandle);
    return 0;
    }

4.使用控制码从应用层发送消息给驱动层

  1. 用户层程序调用控制码发送消息
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
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#define IOCTL_SEND_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

int main()
{
HANDLE hDevice = CreateFile(
L"\\\\.\\MyMinimalDevice",
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);

if (hDevice == INVALID_HANDLE_VALUE) {
printf("无法打开设备: 错误码 = %lu\n", GetLastError());
return 1;
}

printf("设备打开成功。\n");

const char* message = "Hello from user mode!";
DWORD returned = 0;

BOOL result = DeviceIoControl(
hDevice,
IOCTL_SEND_MESSAGE,
(LPVOID)message,
(DWORD)strlen(message),
NULL,
0,
&returned,
NULL);

if (!result) {
printf("发送失败,错误码 = %lu\n", GetLastError());
}
else {
printf("消息已发送。\n");
}

CloseHandle(hDevice);
return 0;
}

2.驱动程序新增控制码支持

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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <ntddk.h>

#define DEVICE_NAME L"\\Device\\MyMinimalDevice"
#define SYMBOLIC_NAME L"\\DosDevices\\MyMinimalDevice"

#define IOCTL_SEND_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

// 安全字符串打印宏
//#define Log(X) DbgPrint("qi:" X)
//#define Log(fmt, ...) DbgPrint("qi: " fmt, __VA_ARGS__)
#define Log(...) DbgPrint("qi: " __VA_ARGS__)
PDEVICE_OBJECT g_DeviceObject = NULL;

// 函数声明
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
VOID DeleteDeviceAndSymbolicLink();

//
// 初始化驱动入口
//
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);

NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
if (!NT_SUCCESS(status)) return status;

for (int i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
DriverObject->MajorFunction[i] = DispatchDeviceControl;

DriverObject->DriverUnload = UnloadDriver;

Log("Driver loaded\n");
return STATUS_SUCCESS;
}

//
// 驱动卸载
//
VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DeleteDeviceAndSymbolicLink();
Log("Driver unloaded\n");
}

//
// 所有请求都走这里,包括 CREATE / CLOSE / IOCTL
//
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG majorFunc = stack->MajorFunction;
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;

switch (majorFunc) {
case IRP_MJ_CREATE:
Log("Device opened\n");
break;

case IRP_MJ_CLOSE:
Log("Device closed\n");
break;

case IRP_MJ_DEVICE_CONTROL:
if (code == IOCTL_SEND_MESSAGE)
{
char* input = (char*)Irp->AssociatedIrp.SystemBuffer;
ULONG inputLen = stack->Parameters.DeviceIoControl.InputBufferLength;

if (input && inputLen > 0) {
// 确保字符串以 null 结尾(调试安全)
char msg[256] = { 0 };
ULONG copyLen = (inputLen < sizeof(msg) - 1) ? inputLen : sizeof(msg) - 1;
RtlCopyMemory(msg, input, copyLen);
Log("Message from user: %s;\n", msg);
}
else {
Log("Received empty message\n");
}
}
else {
Log("Unknown IOCTL code\n");
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
break;

default:
Log("Unhandled IRP\n");
break;
}

Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}

//
// 创建设备与符号链接
//
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);

NTSTATUS status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&g_DeviceObject
);

if (!NT_SUCCESS(status)) return status;

status = IoCreateSymbolicLink(&symLinkName, &deviceName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}

return status;
}

//
// 删除设备与符号链接
//
VOID DeleteDeviceAndSymbolicLink()
{
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
IoDeleteSymbolicLink(&symLinkName);

if (g_DeviceObject) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}
}

5.添加驱动程序向应用层发送消息的功能

  1. 用户层程序

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

    #define IOCTL_SEND_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_GET_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

    #define DEVICE_NAME L"\\\\.\\MyMinimalDevice"
    #define MAX_BUFFER 256

    BOOL WriteMessageToDriver(HANDLE hDevice, const char* msg)
    {
    DWORD returned;
    return DeviceIoControl(
    hDevice,
    IOCTL_SEND_MESSAGE,
    (LPVOID)msg,
    (DWORD)strlen(msg),
    NULL,
    0,
    &returned,
    NULL);
    }

    BOOL ReadMessageFromDriver(HANDLE hDevice, char* outBuffer, DWORD bufSize)
    {
    DWORD returned;
    return DeviceIoControl(
    hDevice,
    IOCTL_GET_MESSAGE,
    NULL,
    0,
    outBuffer,
    bufSize,
    &returned,
    NULL);
    }

    int main()
    {
    HANDLE hDevice = CreateFile(
    DEVICE_NAME,
    GENERIC_READ | GENERIC_WRITE,
    0, NULL, OPEN_EXISTING, 0, NULL);

    if (hDevice == INVALID_HANDLE_VALUE) {
    printf("无法打开设备: 错误码 = %lu\n", GetLastError());
    return 1;
    }

    // 写入消息
    const char* msg = "Hello Kernel!";
    if (WriteMessageToDriver(hDevice, msg))
    printf("已发送消息: %s\n", msg);
    else
    printf("发送失败!错误码 = %lu\n", GetLastError());

    // 读取返回消息
    char buffer[MAX_BUFFER] = { 0 };
    if (ReadMessageFromDriver(hDevice, buffer, sizeof(buffer)))
    printf("从驱动读取到: %s\n", buffer);
    else
    printf("读取失败!错误码 = %lu\n", GetLastError());

    CloseHandle(hDevice);
    return 0;
    }

  2. 驱动程序

    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
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    #include <ntddk.h>

    #define DEVICE_NAME L"\\Device\\MyMinimalDevice"
    #define SYMBOLIC_NAME L"\\DosDevices\\MyMinimalDevice"

    // 控制码定义
    #define IOCTL_SEND_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_GET_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

    #define MAX_BUFFER_SIZE 256
    #define Log(...) DbgPrint("qi: " __VA_ARGS__)

    char g_LastMessage[MAX_BUFFER_SIZE] = "Default Kernel Message";

    PDEVICE_OBJECT g_DeviceObject = NULL;

    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
    VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
    NTSTATUS DispatchAll(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
    VOID DeleteDeviceAndSymbolicLink();

    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
    {
    UNREFERENCED_PARAMETER(RegistryPath);
    NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
    if (!NT_SUCCESS(status)) return status;

    for (int i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
    DriverObject->MajorFunction[i] = DispatchAll;

    DriverObject->DriverUnload = UnloadDriver;
    Log("Driver loaded\n");
    return STATUS_SUCCESS;
    }

    VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
    {
    UNREFERENCED_PARAMETER(DriverObject);
    DeleteDeviceAndSymbolicLink();
    Log("Driver unloaded\n");
    }

    NTSTATUS DispatchAll(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG majorFunc = stack->MajorFunction;
    NTSTATUS status = STATUS_SUCCESS;

    switch (majorFunc)
    {
    case IRP_MJ_CREATE:
    Log("Device opened\n");
    break;

    case IRP_MJ_CLOSE:
    Log("Device closed\n");
    break;

    case IRP_MJ_DEVICE_CONTROL:
    {
    ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
    char* buffer = (char*)Irp->AssociatedIrp.SystemBuffer;
    ULONG inLen = stack->Parameters.DeviceIoControl.InputBufferLength;
    ULONG outLen = stack->Parameters.DeviceIoControl.OutputBufferLength;

    switch (code)
    {
    case IOCTL_SEND_MESSAGE:
    if (buffer && inLen > 0)
    {
    RtlZeroMemory(g_LastMessage, MAX_BUFFER_SIZE);
    RtlCopyMemory(g_LastMessage, buffer, min(inLen, MAX_BUFFER_SIZE - 1));
    Log("Received from user: %s;\n", g_LastMessage);
    }
    else
    {
    Log("Empty user message\n");
    }
    Irp->IoStatus.Information = 0;
    break;

    case IOCTL_GET_MESSAGE:
    if (buffer && outLen > 0)
    {
    size_t msgLen = strnlen(g_LastMessage, MAX_BUFFER_SIZE);
    size_t copyLen = min(msgLen + 1, outLen);
    RtlCopyMemory(buffer, g_LastMessage, copyLen);
    Irp->IoStatus.Information = (ULONG)copyLen;
    Log("Message returned to user\n");
    }
    else
    {
    Irp->IoStatus.Information = 0;
    Log("Invalid output buffer\n");
    }
    break;

    default:
    status = STATUS_INVALID_DEVICE_REQUEST;
    Log("Unknown IOCTL\n");
    break;
    }
    break;
    }

    default:
    Log("Unhandled IRP\n");
    break;
    }

    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
    }

    NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
    {
    UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
    UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);

    NTSTATUS status = IoCreateDevice(
    DriverObject,
    0,
    &deviceName,
    FILE_DEVICE_UNKNOWN,
    FILE_DEVICE_SECURE_OPEN,
    FALSE,
    &g_DeviceObject
    );

    if (!NT_SUCCESS(status)) return status;

    status = IoCreateSymbolicLink(&symLinkName, &deviceName);
    if (!NT_SUCCESS(status)) {
    IoDeleteDevice(g_DeviceObject);
    g_DeviceObject = NULL;
    }

    return status;
    }

    VOID DeleteDeviceAndSymbolicLink()
    {
    UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
    IoDeleteSymbolicLink(&symLinkName);

    if (g_DeviceObject) {
    IoDeleteDevice(g_DeviceObject);
    g_DeviceObject = NULL;
    }
    }

6.驱动层与应用层程序通信的完整框架

  1. 用户层程序

    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
    126
    127
    #include <windows.h>
    #include <stdio.h>

    #define IOCTL_SEND_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_GET_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define DEVICE_NAME L"\\\\.\\MyMinimalDevice"
    #define MAX_BUFFER 256

    HANDLE OpenDevice()
    {
    HANDLE hDevice = CreateFile(
    DEVICE_NAME,
    GENERIC_READ | GENERIC_WRITE,
    0, NULL, OPEN_EXISTING, 0, NULL);

    if (hDevice == INVALID_HANDLE_VALUE)
    printf("无法打开设备,错误码 = %lu\n", GetLastError());
    else
    printf("设备已打开。\n");

    return hDevice;
    }

    // --- IOCTL 通信 ---
    BOOL SendMessageToDriver(HANDLE hDevice, const char* message)
    {
    DWORD returned;
    BOOL result = DeviceIoControl(
    hDevice,
    IOCTL_SEND_MESSAGE,
    (LPVOID)message,
    (DWORD)strlen(message),
    NULL,
    0,
    &returned,
    NULL);

    if (!result)
    printf("发送失败(IOCTL),错误码 = %lu\n", GetLastError());

    return result;
    }

    BOOL ReceiveMessageFromDriver(HANDLE hDevice, char* buffer, DWORD bufferSize)
    {
    DWORD returned;
    BOOL result = DeviceIoControl(
    hDevice,
    IOCTL_GET_MESSAGE,
    NULL,
    0,
    buffer,
    bufferSize,
    &returned,
    NULL);

    if (!result)
    printf("读取失败(IOCTL),错误码 = %lu\n", GetLastError());

    return result;
    }

    // --- ReadFile/WriteFile 测试 ---
    BOOL WriteToDriver(HANDLE hDevice, const char* message)
    {
    DWORD written = 0;
    BOOL result = WriteFile(
    hDevice,
    message,
    (DWORD)strlen(message),
    &written,
    NULL);

    if (!result)
    printf("WriteFile 失败,错误码 = %lu\n", GetLastError());
    else
    printf("WriteFile 写入了 %lu 字节。\n", written);

    return result;
    }

    BOOL ReadFromDriver(HANDLE hDevice, char* buffer, DWORD bufferSize)
    {
    DWORD bytesRead = 0;
    BOOL result = ReadFile(
    hDevice,
    buffer,
    bufferSize,
    &bytesRead,
    NULL);

    if (!result)
    printf("ReadFile 失败,错误码 = %lu\n", GetLastError());
    else
    printf("ReadFile 读取了 %lu 字节。\n", bytesRead);

    return result;
    }

    // --- 主函数 ---
    int main()
    {
    HANDLE hDevice = OpenDevice();
    if (hDevice == INVALID_HANDLE_VALUE) return 1;

    const char* msg = "Hello Kernel via IOCTL!";
    if (SendMessageToDriver(hDevice, msg))
    printf("已发送 (IOCTL): %s\n", msg);

    char buffer[MAX_BUFFER] = { 0 };
    if (ReceiveMessageFromDriver(hDevice, buffer, sizeof(buffer)))
    printf("接收到 (IOCTL): %s\n", buffer);

    // --- 使用 WriteFile 写入 ---
    const char* msg2 = "Hello Kernel via WriteFile!";
    if (WriteToDriver(hDevice, msg2))
    printf("已写入 (WriteFile): %s\n", msg2);

    // --- 使用 ReadFile 读取 ---
    ZeroMemory(buffer, sizeof(buffer));
    if (ReadFromDriver(hDevice, buffer, sizeof(buffer)))
    printf("接收到 (ReadFile): %s\n", buffer);

    CloseHandle(hDevice);
    return 0;
    }

  2. 驱动程序

    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
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    #include <ntddk.h>

    #define DEVICE_NAME L"\\Device\\MyMinimalDevice"
    #define SYMBOLIC_NAME L"\\DosDevices\\MyMinimalDevice"

    #define IOCTL_SEND_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_GET_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

    #define MAX_BUFFER_SIZE 256
    #define Log(...) DbgPrint("qi: " __VA_ARGS__)

    // 内核全局缓冲
    static char g_LastMessage[MAX_BUFFER_SIZE] = "Default Kernel Message";
    static PDEVICE_OBJECT g_DeviceObject = NULL;

    // 前向声明
    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
    VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
    NTSTATUS DispatchCommon(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
    VOID DeleteDeviceAndSymbolicLink();

    // 驱动入口
    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
    {
    UNREFERENCED_PARAMETER(RegistryPath);
    Log("Driver loaded\n");

    NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
    if (!NT_SUCCESS(status)) {
    Log("CreateDevice failed: 0x%X\n", status);
    return status;
    }

    // 分发
    DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCommon;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCommon;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCommon;
    DriverObject->MajorFunction[IRP_MJ_READ] = DispatchCommon;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchCommon;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
    DriverObject->DriverUnload = UnloadDriver;

    return STATUS_SUCCESS;
    }

    // 卸载例程
    VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
    {
    UNREFERENCED_PARAMETER(DriverObject);
    DeleteDeviceAndSymbolicLink();
    Log("Driver unloaded\n");
    }

    // 创建设备 + 符号链接
    NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
    {
    UNICODE_STRING devName = RTL_CONSTANT_STRING(DEVICE_NAME);
    UNICODE_STRING symName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);

    NTSTATUS status = IoCreateDevice(
    DriverObject,
    0,
    &devName,
    FILE_DEVICE_UNKNOWN,
    FILE_DEVICE_SECURE_OPEN,
    FALSE,
    &g_DeviceObject
    );
    if (!NT_SUCCESS(status)) return status;

    // —— 关键:启用 Buffered I/O,否则 SystemBuffer 在 Read/Write/IOCTL 下可能为 NULL
    g_DeviceObject->Flags |= DO_BUFFERED_IO;

    status = IoCreateSymbolicLink(&symName, &devName);
    if (!NT_SUCCESS(status)) {
    IoDeleteDevice(g_DeviceObject);
    g_DeviceObject = NULL;
    }
    return status;
    }

    // 删除设备 + 符号链接
    VOID DeleteDeviceAndSymbolicLink()
    {
    UNICODE_STRING symName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
    IoDeleteSymbolicLink(&symName);

    if (g_DeviceObject) {
    IoDeleteDevice(g_DeviceObject);
    g_DeviceObject = NULL;
    }
    }

    // Create/Close/Cleanup/Read/Write 都走这里
    NTSTATUS DispatchCommon(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS status = STATUS_SUCCESS;
    ULONG info = 0;

    switch (stack->MajorFunction)
    {
    case IRP_MJ_CREATE:
    Log("Device opened\n");
    break;

    case IRP_MJ_CLOSE:
    Log("Device closed\n");
    break;

    case IRP_MJ_CLEANUP:
    Log("Device cleanup\n");
    break;

    case IRP_MJ_READ:
    {
    // 只用 METHOD_BUFFERED,SystemBuffer 一定有效
    char* userBuf = (char*)Irp->AssociatedIrp.SystemBuffer;
    ULONG outLen = stack->Parameters.Read.Length;

    if (userBuf && outLen > 0) {
    size_t msgLen = strnlen(g_LastMessage, MAX_BUFFER_SIZE);
    size_t copyLen = min((size_t)outLen, msgLen + 1);
    RtlCopyMemory(userBuf, g_LastMessage, copyLen);
    info = (ULONG)copyLen;
    Log("Handled IRP_MJ_READ, %u bytes\n", info);
    }
    else {
    status = STATUS_INVALID_PARAMETER;
    }
    break;
    }

    case IRP_MJ_WRITE:
    {
    char* buffer = (char*)Irp->AssociatedIrp.SystemBuffer;
    ULONG writeLen = stack->Parameters.Write.Length;

    if (buffer && writeLen > 0)
    {
    RtlZeroMemory(g_LastMessage, MAX_BUFFER_SIZE);
    RtlCopyMemory(g_LastMessage, buffer,
    min((size_t)writeLen, MAX_BUFFER_SIZE - 1));
    Log("Write from user: %s;\n", g_LastMessage);

    info = writeLen; // <-- 把写入长度告诉 I/O 管理器
    }
    else
    {
    status = STATUS_INVALID_PARAMETER;
    }
    Log("Handled IRP_MJ_WRITE, %u bytes\n", info);
    break;
    }

    default:
    status = STATUS_INVALID_DEVICE_REQUEST;
    Log("Unknown IRP in DispatchCommon: 0x%X\n", stack->MajorFunction);
    break;
    }

    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = info;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
    }

    // 只有 IOCTL 走这里
    NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

    ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
    ULONG inLen = stack->Parameters.DeviceIoControl.InputBufferLength;
    ULONG outLen = stack->Parameters.DeviceIoControl.OutputBufferLength;
    char* buffer = (char*)Irp->AssociatedIrp.SystemBuffer;

    NTSTATUS status = STATUS_SUCCESS;
    ULONG info = 0;

    switch (code)
    {
    case IOCTL_SEND_MESSAGE:
    if (buffer && inLen > 0) {
    RtlZeroMemory(g_LastMessage, MAX_BUFFER_SIZE);
    RtlCopyMemory(g_LastMessage, buffer, min((size_t)inLen, MAX_BUFFER_SIZE - 1));
    Log("Received from user (IOCTL): %s\n", g_LastMessage);
    }
    else {
    status = STATUS_INVALID_PARAMETER;
    Log("Empty IOCTL_SEND_MESSAGE\n");
    }
    break;

    case IOCTL_GET_MESSAGE:
    if (buffer && outLen > 0) {
    size_t msgLen = strnlen(g_LastMessage, MAX_BUFFER_SIZE);
    size_t copyLen = min((size_t)outLen, msgLen + 1);
    RtlCopyMemory(buffer, g_LastMessage, copyLen);
    info = (ULONG)copyLen;
    Log("Returned to user (IOCTL): %s\n", g_LastMessage);
    }
    else {
    status = STATUS_INVALID_PARAMETER;
    Log("Invalid IOCTL_GET_MESSAGE buffer\n");
    }
    break;

    default:
    status = STATUS_INVALID_DEVICE_REQUEST;
    Log("Unknown IOCTL: 0x%X\n", code);
    break;
    }

    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = info;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
    }

7. 应用向驱动发送结构体. 应用向驱动发送结构体

  1. 用户层应用程序

    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
    // user_app.c
    #include <windows.h>
    #include <stdio.h>

    #define IOCTL_SEND_STRUCT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_GET_STRUCT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define DEVICE_NAME L"\\\\.\\MyMinimalDevice"

    typedef struct _MY_MESSAGE {
    int Id;
    char Text[128];
    } MY_MESSAGE, * PMY_MESSAGE;

    HANDLE OpenDevice()
    {
    HANDLE hDevice = CreateFile(
    DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
    0, NULL, OPEN_EXISTING, 0, NULL);

    if (hDevice == INVALID_HANDLE_VALUE)
    printf("无法打开设备,错误码 = %lu\n", GetLastError());
    else
    printf("设备已打开。\n");

    return hDevice;
    }

    BOOL SendStructToDriver(HANDLE hDevice, MY_MESSAGE* msg)
    {
    DWORD returned;
    return DeviceIoControl(hDevice, IOCTL_SEND_STRUCT, msg, sizeof(MY_MESSAGE),
    NULL, 0, &returned, NULL);
    }

    BOOL ReceiveStructFromDriver(HANDLE hDevice, MY_MESSAGE* msg)
    {
    DWORD returned;
    return DeviceIoControl(hDevice, IOCTL_GET_STRUCT, NULL, 0,
    msg, sizeof(MY_MESSAGE), &returned, NULL);
    }

    int main()
    {
    HANDLE hDevice = OpenDevice();
    if (hDevice == INVALID_HANDLE_VALUE) return 1;

    MY_MESSAGE msg = { .Id = 1 };
    strcpy_s(msg.Text, sizeof(msg.Text), "Hello from user!");

    if (SendStructToDriver(hDevice, &msg))
    printf("已发送结构体: Id=%d, Text=%s\n", msg.Id, msg.Text);
    else
    printf("发送结构体失败。\n");

    MY_MESSAGE reply = { 0 };
    if (ReceiveStructFromDriver(hDevice, &reply))
    printf("从驱动接收到: Id=%d, Text=%s\n", reply.Id, reply.Text);
    else
    printf("接收结构体失败。\n");

    CloseHandle(hDevice);
    return 0;
    }
  2. 驱动程序

    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

    // mydriver.c
    #include <ntddk.h>

    #define IOCTL_SEND_STRUCT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_GET_STRUCT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)

    #define Log(...) DbgPrint("qi: " __VA_ARGS__)

    typedef struct _MY_MESSAGE {
    int Id;
    char Text[128];
    } MY_MESSAGE, * PMY_MESSAGE;

    MY_MESSAGE g_StoredMessage = { 0 };

    NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    VOID UnloadDriver(PDRIVER_OBJECT DriverObject);

    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
    {
    UNREFERENCED_PARAMETER(RegistryPath);

    Log("Driver loaded\n");
    UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\MyMinimalDevice");
    UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\DosDevices\\MyMinimalDevice");
    PDEVICE_OBJECT devObj;

    NTSTATUS status = IoCreateDevice(DriverObject, 0, &devName,
    FILE_DEVICE_UNKNOWN, 0, FALSE, &devObj);
    if (!NT_SUCCESS(status)) return status;

    IoCreateSymbolicLink(&symLink, &devName);

    DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
    DriverObject->DriverUnload = UnloadDriver;

    return STATUS_SUCCESS;
    }

    VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
    {
    UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\DosDevices\\MyMinimalDevice");
    IoDeleteSymbolicLink(&symLink);
    IoDeleteDevice(DriverObject->DeviceObject);
    Log("Driver unloaded\n");
    }

    NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);
    Log("Open/Close\n");

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
    }

    NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
    NTSTATUS status = STATUS_SUCCESS;
    ULONG_PTR info = 0;

    switch (code)
    {
    case IOCTL_SEND_STRUCT:
    {
    PMY_MESSAGE pMsg = (PMY_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
    if (pMsg) {
    RtlCopyMemory(&g_StoredMessage, pMsg, sizeof(MY_MESSAGE));
    Log("qi:Received struct: Id=%d, Text=%s;\n", pMsg->Id, pMsg->Text);
    }
    break;
    }

    case IOCTL_GET_STRUCT:
    {
    PMY_MESSAGE pOut = (PMY_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
    if (pOut) {
    g_StoredMessage.Id += 1000;
    strcpy_s(g_StoredMessage.Text, sizeof(g_StoredMessage.Text), "Reply from kernel");
    RtlCopyMemory(pOut, &g_StoredMessage, sizeof(MY_MESSAGE));
    info = sizeof(MY_MESSAGE);
    Log("Returned struct to user\n");
    }
    break;
    }

    default:
    status = STATUS_INVALID_DEVICE_REQUEST;
    break;
    }

    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = info;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
    }


8.分配动态内存传递结构体数据实现双向通信

  1. 用户层程序

    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
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h> // malloc/free

    #define IOCTL_SEND_STRUCT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_GET_STRUCT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define DEVICE_NAME L"\\\\.\\MyMinimalDevice"

    typedef struct _MY_MESSAGE {
    int Id;
    char Text[128];
    } MY_MESSAGE, * PMY_MESSAGE;

    HANDLE OpenDevice()
    {
    HANDLE hDevice = CreateFileW(
    DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
    0, NULL, OPEN_EXISTING, 0, NULL);

    if (hDevice == INVALID_HANDLE_VALUE)
    printf("无法打开设备,错误码 = %lu\n", GetLastError());
    else
    printf("设备已打开。\n");

    return hDevice;
    }

    BOOL SendStructToDriver(HANDLE hDevice, PMY_MESSAGE msg)
    {
    DWORD returned;
    return DeviceIoControl(hDevice, IOCTL_SEND_STRUCT, msg, sizeof(MY_MESSAGE),
    NULL, 0, &returned, NULL);
    }

    BOOL ReceiveStructFromDriver(HANDLE hDevice, PMY_MESSAGE msg)
    {
    DWORD returned;
    return DeviceIoControl(hDevice, IOCTL_GET_STRUCT, NULL, 0,
    msg, sizeof(MY_MESSAGE), &returned, NULL);
    }

    int main()
    {
    HANDLE hDevice = OpenDevice();
    if (hDevice == INVALID_HANDLE_VALUE) return 1;

    PMY_MESSAGE msg = (PMY_MESSAGE)malloc(sizeof(MY_MESSAGE));
    if (!msg) return 1;

    msg->Id = 1;
    strcpy_s(msg->Text, sizeof(msg->Text), "Hello from user!");

    if (SendStructToDriver(hDevice, msg))
    printf("已发送结构体: Id=%d, Text=%s\n", msg->Id, msg->Text);
    else
    printf("发送结构体失败。\n");

    if (ReceiveStructFromDriver(hDevice, msg))
    printf("从驱动接收到: Id=%d, Text=%s\n", msg->Id, msg->Text);
    else
    printf("接收结构体失败。\n");

    free(msg);
    CloseHandle(hDevice);
    return 0;
    }

  2. 驱动程序

    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

    // mydriver.c
    #include <ntddk.h>
    #include <ntstrsafe.h>
    #define Log(...) DbgPrint("qi: " __VA_ARGS__)

    #define IOCTL_SEND_STRUCT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_GET_STRUCT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)


    #define POOL_TAG 'pMyT'
    typedef struct _MY_MESSAGE {
    int Id;
    char Text[128];
    } MY_MESSAGE, * PMY_MESSAGE;

    PMY_MESSAGE g_StoredMessage = NULL;

    NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
    VOID UnloadDriver(PDRIVER_OBJECT DriverObject);

    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
    {
    UNREFERENCED_PARAMETER(RegistryPath);

    Log("Driver loaded\n");
    UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\MyMinimalDevice");
    UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\DosDevices\\MyMinimalDevice");
    PDEVICE_OBJECT devObj;

    NTSTATUS status = IoCreateDevice(DriverObject, 0, &devName,
    FILE_DEVICE_UNKNOWN, 0, FALSE, &devObj);
    if (!NT_SUCCESS(status)) return status;

    IoCreateSymbolicLink(&symLink, &devName);

    DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
    DriverObject->DriverUnload = UnloadDriver;

    return STATUS_SUCCESS;
    }

    VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
    {
    if (g_StoredMessage) {
    ExFreePoolWithTag(g_StoredMessage, POOL_TAG);
    g_StoredMessage = NULL;
    }

    UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\DosDevices\\MyMinimalDevice");
    IoDeleteSymbolicLink(&symLink);
    IoDeleteDevice(DriverObject->DeviceObject);
    Log("Driver unloaded\n");
    }
    NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);
    Log("Open/Close\n");

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
    }

    NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    UNREFERENCED_PARAMETER(DeviceObject);

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
    NTSTATUS status = STATUS_SUCCESS;
    ULONG_PTR info = 0;

    switch (code)
    {
    case IOCTL_SEND_STRUCT:
    {
    PMY_MESSAGE pMsg = (PMY_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
    if (pMsg) {
    if (g_StoredMessage)
    ExFreePoolWithTag(g_StoredMessage, POOL_TAG);

    g_StoredMessage = (PMY_MESSAGE)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(MY_MESSAGE), POOL_TAG);
    if (g_StoredMessage) {
    RtlCopyMemory(g_StoredMessage, pMsg, sizeof(MY_MESSAGE));
    Log("Received struct: Id=%d, Text=%s\n", pMsg->Id, pMsg->Text);
    Log("Receivedd struct: Id=%d, Text=%s\n", g_StoredMessage->Id, g_StoredMessage->Text);
    }
    else {
    status = STATUS_INSUFFICIENT_RESOURCES;
    }
    }
    break;
    }

    case IOCTL_GET_STRUCT:
    {
    PMY_MESSAGE pOut = (PMY_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
    if (pOut && g_StoredMessage) {
    g_StoredMessage->Id += 1000;
    RtlStringCchCopyA(g_StoredMessage->Text, sizeof(g_StoredMessage->Text), "Reply from kernel");
    RtlCopyMemory(pOut, g_StoredMessage, sizeof(MY_MESSAGE));
    info = sizeof(MY_MESSAGE);
    Log("Returned struct to user\n");
    }
    else {
    status = STATUS_NOT_FOUND;
    }
    break;
    }

    default:
    status = STATUS_INVALID_DEVICE_REQUEST;
    break;
    }

    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = info;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
    }

9. 完整的应用与驱动通信读取物理内存

R0

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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include <ntddk.h>
#include <windef.h>

#define DEVICE_NAME L"\\Device\\MyMinimalDevice"
#define SYMBOLIC_NAME L"\\DosDevices\\MyMinimalDevice"
#define MAX_BUFFER_SIZE 256
#define Log(...) DbgPrint("qi: " __VA_ARGS__)
#define IOCTL_SEND_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_GET_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_READ_PHYSICAL_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)

#pragma pack(push, 1)
typedef struct _MESSAGE_STRUCT {
int id;
char text[128];
} MESSAGE_STRUCT;
#pragma pack(pop)

typedef struct _PHYSICAL_MEMORY_REQUEST {
LARGE_INTEGER PhysicalAddress;
ULONG Length;
} PHYSICAL_MEMORY_REQUEST, * PPHYSICAL_MEMORY_REQUEST;

char g_LastMessage[MAX_BUFFER_SIZE] = "Default Kernel Message";
PDEVICE_OBJECT g_DeviceObject = NULL;
MESSAGE_STRUCT* g_pLastMessage = NULL;

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
VOID DeleteDeviceAndSymbolicLink();
NTSTATUS ReadPhysicalMemory(
PVOID InBuffer,
ULONG InLength,
PVOID OutBuffer,
ULONG OutLength,
PULONG BytesReturned
);

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
Log("Driver loaded\n");
NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
if (!NT_SUCCESS(status)) return status;

DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->DriverUnload = UnloadDriver;


return STATUS_SUCCESS;
}

VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DeleteDeviceAndSymbolicLink();
Log("Driver unloaded\n");
}

NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
if (stack->MajorFunction == IRP_MJ_CREATE)
Log("Device opened\n");
else if (stack->MajorFunction == IRP_MJ_CLOSE)
Log("Device closed\n");

Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}

NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
MESSAGE_STRUCT* buffer = (MESSAGE_STRUCT*)Irp->AssociatedIrp.SystemBuffer;
ULONG inLen = stack->Parameters.DeviceIoControl.InputBufferLength;
ULONG outLen = stack->Parameters.DeviceIoControl.OutputBufferLength;
NTSTATUS status = STATUS_SUCCESS;
ULONG info = 0;

switch (code)
{
case IOCTL_SEND_MESSAGE:
if (buffer && inLen >= sizeof(MESSAGE_STRUCT))
{
if (g_pLastMessage)
ExFreePoolWithTag(g_pLastMessage, 'msgT');

g_pLastMessage = (MESSAGE_STRUCT*)ExAllocatePoolWithTag(NonPagedPool, sizeof(MESSAGE_STRUCT), 'msgT');
if (g_pLastMessage) {
RtlCopyMemory(g_pLastMessage, buffer, sizeof(MESSAGE_STRUCT));
Log("驱动收到结构体: id=%d, text=%s;\n", g_pLastMessage->id, g_pLastMessage->text);
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
Irp->IoStatus.Information = 0;
break;

case IOCTL_GET_MESSAGE:
if (buffer && outLen >= sizeof(MESSAGE_STRUCT) && g_pLastMessage)
{
RtlCopyMemory(buffer, g_pLastMessage, sizeof(MESSAGE_STRUCT));
Irp->IoStatus.Information = sizeof(MESSAGE_STRUCT);
Log("结构体返回给用户层\n");
}
else
{
Log("读取失败:无数据或缓冲不足\n");
Irp->IoStatus.Information = 0;
}
break;
case IOCTL_READ_PHYSICAL_MEMORY:
{
ULONG bytesReturned = 0;
status = ReadPhysicalMemory(buffer, inLen, buffer, outLen, &bytesReturned);
Irp->IoStatus.Information = bytesReturned;

if (NT_SUCCESS(status)) {
Log("Read physical memory success\n");
}
else {
Log("Read physical memory failed\n");
}
break;
}
default:
Log("未知IOCTL\n");
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}

Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}

NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);

NTSTATUS status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&g_DeviceObject
);

if (!NT_SUCCESS(status)) return status;

status = IoCreateSymbolicLink(&symLinkName, &deviceName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}

return status;
}

VOID DeleteDeviceAndSymbolicLink()
{
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
IoDeleteSymbolicLink(&symLinkName);

if (g_DeviceObject) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}

if (g_pLastMessage) {
ExFreePoolWithTag(g_pLastMessage, 'msgT');
g_pLastMessage = NULL;
}
}
// 读取物理内存的核心功能封装为模块
NTSTATUS ReadPhysicalMemory(
PVOID InBuffer,
ULONG InLength,
PVOID OutBuffer,
ULONG OutLength,
PULONG BytesReturned
)
{
if (InLength < sizeof(PHYSICAL_MEMORY_REQUEST) || OutLength == 0) {
return STATUS_BUFFER_TOO_SMALL;
}

PPHYSICAL_MEMORY_REQUEST req = (PPHYSICAL_MEMORY_REQUEST)InBuffer;
ULONG bytesToRead = min(req->Length, OutLength);

PVOID mapped = MmMapIoSpace(req->PhysicalAddress, bytesToRead, MmNonCached);
if (!mapped) {
return STATUS_INSUFFICIENT_RESOURCES;
}

NTSTATUS status = STATUS_SUCCESS;
__try {
RtlCopyMemory(OutBuffer, mapped, bytesToRead);
*BytesReturned = bytesToRead;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
*BytesReturned = 0;
}

MmUnmapIoSpace(mapped, bytesToRead);
return status;
}

R3

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

#define DEVICE_NAME L"\\\\.\\MyMinimalDevice"
#define IOCTL_SEND_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_GET_MESSAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_READ_PHYSICAL_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)

// 必须与驱动结构一致
typedef struct _PHYSICAL_MEMORY_REQUEST {
LARGE_INTEGER PhysicalAddress;
ULONG Length;
} PHYSICAL_MEMORY_REQUEST, * PPHYSICAL_MEMORY_REQUEST;

// 打开驱动设备
HANDLE OpenDriverHandle()
{
HANDLE hDevice = CreateFile(
DEVICE_NAME,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);

if (hDevice == INVALID_HANDLE_VALUE) {
printf("打开设备失败: %d\n", GetLastError());
}
return hDevice;
}

// 读取物理内存
BOOL ReadPhysicalMemory(
HANDLE hDevice,
ULONGLONG physicalAddress,
ULONG length,
BYTE* buffer,
DWORD bufferSize,
DWORD* bytesReturned
)
{
if (length > bufferSize) {
printf("缓冲区太小,无法读取指定大小的物理内存。\n");
return FALSE;
}

PHYSICAL_MEMORY_REQUEST request;
request.PhysicalAddress.QuadPart = physicalAddress;
request.Length = length;

return DeviceIoControl(
hDevice,
IOCTL_READ_PHYSICAL_MEMORY,
&request,
sizeof(request),
buffer,
bufferSize,
bytesReturned,
NULL
);
}

// 显示读取到的内存数据
void PrintMemoryBuffer(BYTE* buffer, DWORD length)
{
printf("成功读取 %d 字节的物理内存数据:\n", length);
for (DWORD i = 0; i < length; i++) {
printf("%02X ", buffer[i]);
if ((i + 1) % 16 == 0) printf("\n");
}
if (length % 16 != 0) printf("\n");
}

int main()
{
BYTE buffer[1024] = { 0 };
DWORD bytesReturned = 0;

HANDLE hDevice = OpenDriverHandle();
if (hDevice == INVALID_HANDLE_VALUE) return 1;

ULONGLONG physAddr = 0x100000;
ULONG length = 1024;

BOOL success = ReadPhysicalMemory(hDevice, physAddr, length, buffer, sizeof(buffer), &bytesReturned);
if (!success) {
printf("DeviceIoControl 失败: %d\n", GetLastError());
CloseHandle(hDevice);
return 1;
}

PrintMemoryBuffer(buffer, bytesReturned);

CloseHandle(hDevice);
return 0;
}