Windows驱动开发入门-Minifilter示例代码

NPminifilter.inf、DLL源代码、应用层源代码在教程节都有完整的,这里不贴了。

NPminifilter.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
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
#include "NPminifilter.h"
// Global variables

PFLT_FILTER gFilterHandle;
ULONG gTraceFlags = 0;

PFLT_FILTER gFilterHandle;
PFLT_PORT gServerPort;
PFLT_PORT gClientPort;

NPMINI_COMMAND gCommand = ENUM_PASS;

#define PT_DBG_PRINT( _dbgLevel, _string ) \
(FlagOn(gTraceFlags,(_dbgLevel)) ? \
DbgPrint _string : \
((void)0))

BOOLEAN NPUnicodeStringToChar(PUNICODE_STRING UniName, char Name[])
{
ANSI_STRING AnsiName;
NTSTATUS ntstatus;
char* nameptr;

__try {
ntstatus = RtlUnicodeStringToAnsiString(&AnsiName, UniName, TRUE);

if (AnsiName.Length < 260) {
nameptr = (PCHAR)AnsiName.Buffer;
//Convert into upper case and copy to buffer
strcpy(Name, _strupr(nameptr));
DbgPrint("NPUnicodeStringToChar : %s\n", Name);
}
RtlFreeAnsiString(&AnsiName);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
DbgPrint("NPUnicodeStringToChar EXCEPTION_EXECUTE_HANDLER\n");
return FALSE;
}
return TRUE;
}

NTSTATUS
NPInstanceSetup (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_SETUP_FLAGS Flags,
__in DEVICE_TYPE VolumeDeviceType,
__in FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
UNREFERENCED_PARAMETER( VolumeDeviceType );
UNREFERENCED_PARAMETER( VolumeFilesystemType );

PAGED_CODE();

PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("NPminifilter!NPInstanceSetup: Entered\n") );

return STATUS_SUCCESS;
}


NTSTATUS
NPInstanceQueryTeardown (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );

PAGED_CODE();

PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("NPminifilter!NPInstanceQueryTeardown: Entered\n") );

return STATUS_SUCCESS;
}


VOID
NPInstanceTeardownStart (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );

PAGED_CODE();

PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("NPminifilter!NPInstanceTeardownStart: Entered\n") );
}


VOID
NPInstanceTeardownComplete (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );

PAGED_CODE();

PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("NPminifilter!NPInstanceTeardownComplete: Entered\n") );
}


/*************************************************************************
MiniFilter initialization and unload routines.
*************************************************************************/

NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
PSECURITY_DESCRIPTOR sd;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString; //for communication port name

UNREFERENCED_PARAMETER( RegistryPath );

PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("NPminifilter!DriverEntry: Entered\n") );

//
// Register with FltMgr to tell it our callback routines
//

status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&gFilterHandle );

ASSERT( NT_SUCCESS( status ) );

if (NT_SUCCESS( status )) {

//
// Start filtering i/o
//

status = FltStartFiltering( gFilterHandle );

if (!NT_SUCCESS( status )) {

FltUnregisterFilter( gFilterHandle );
}
}
//Communication Port
status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );

if (!NT_SUCCESS( status )) {
goto final;
}


status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );

if (!NT_SUCCESS( status )) {
goto final;
}


RtlInitUnicodeString( &uniString, MINISPY_PORT_NAME );

InitializeObjectAttributes( &oa,
&uniString,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
sd );

status = FltCreateCommunicationPort( gFilterHandle,
&gServerPort,
&oa,
NULL,
NPMiniConnect,
NPMiniDisconnect,
NPMiniMessage,
1 );

FltFreeSecurityDescriptor( sd );

if (!NT_SUCCESS( status )) {
goto final;
}

final :

if (!NT_SUCCESS( status ) ) {

if (NULL != gServerPort) {
FltCloseCommunicationPort( gServerPort );
}

if (NULL != gFilterHandle) {
FltUnregisterFilter( gFilterHandle );
}
}
return status;
}

NTSTATUS
NPUnload (
__in FLT_FILTER_UNLOAD_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( Flags );

PAGED_CODE();

PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("NPminifilter!NPUnload: Entered\n") );

FltCloseCommunicationPort( gServerPort );

FltUnregisterFilter( gFilterHandle );

return STATUS_SUCCESS;
}


/*************************************************************************
MiniFilter callback routines.
*************************************************************************/

FLT_PREOP_CALLBACK_STATUS
NPPreCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
char FileName[260] = "X:";

NTSTATUS status;
PFLT_FILE_NAME_INFORMATION nameInfo;

UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );

PAGED_CODE();

__try {
status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );
if (NT_SUCCESS( status )) {
// P _ O _
if (gCommand == ENUM_BLOCK) {
FltParseFileNameInformation( nameInfo );
if (NPUnicodeStringToChar(&nameInfo->Name, FileName)) {

if (strstr(FileName, "NOTEPAD.EXE") > 0) {

Data->IoStatus.Status = STATUS_ACCESS_DENIED;
Data->IoStatus.Information = 0;
FltReleaseFileNameInformation( nameInfo );
return FLT_PREOP_COMPLETE;
}
}
}
//release resource
FltReleaseFileNameInformation( nameInfo );
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
DbgPrint("NPPreCreate EXCEPTION_EXECUTE_HANDLER\n");
}

return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}


FLT_POSTOP_CALLBACK_STATUS
NPPostCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
{
FLT_POSTOP_CALLBACK_STATUS returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
PFLT_FILE_NAME_INFORMATION nameInfo;
NTSTATUS status;

UNREFERENCED_PARAMETER( CompletionContext );
UNREFERENCED_PARAMETER( Flags );

//
// If this create was failing anyway, don't bother scanning now.
//

if (!NT_SUCCESS( Data->IoStatus.Status ) ||
(STATUS_REPARSE == Data->IoStatus.Status)) {

return FLT_POSTOP_FINISHED_PROCESSING;
}

//
// Check if we are interested in this file.
//

status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );

if (!NT_SUCCESS( status )) {

return FLT_POSTOP_FINISHED_PROCESSING;
}

return returnStatus;
}

// Puser application Conect
NTSTATUS
NPMiniConnect(
__in PFLT_PORT ClientPort,
__in PVOID ServerPortCookie,
__in_bcount(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
)
{
DbgPrint("[mini-filter] NPMiniConnect");
PAGED_CODE();

UNREFERENCED_PARAMETER( ServerPortCookie );
UNREFERENCED_PARAMETER( ConnectionContext );
UNREFERENCED_PARAMETER( SizeOfContext);
UNREFERENCED_PARAMETER( ConnectionCookie );

ASSERT( gClientPort == NULL );
gClientPort = ClientPort;
return STATUS_SUCCESS;
}

// Puser application Disconect
VOID
NPMiniDisconnect(
__in_opt PVOID ConnectionCookie
)
{
PAGED_CODE();
UNREFERENCED_PARAMETER( ConnectionCookie );
DbgPrint("[mini-filter] NPMiniDisconnect");

// Close our handle
FltCloseClientPort( gFilterHandle, &gClientPort );
}

NTSTATUS
NPMiniMessage (
__in PVOID ConnectionCookie,
__in_bcount_opt(InputBufferSize) PVOID InputBuffer,
__in ULONG InputBufferSize,
__out_bcount_part_opt(OutputBufferSize,*ReturnOutputBufferLength) PVOID OutputBuffer,
__in ULONG OutputBufferSize,
__out PULONG ReturnOutputBufferLength
)
{

NPMINI_COMMAND command;
NTSTATUS status;

PAGED_CODE();

UNREFERENCED_PARAMETER( ConnectionCookie );
UNREFERENCED_PARAMETER( OutputBufferSize );
UNREFERENCED_PARAMETER( OutputBuffer );

DbgPrint("[mini-filter] NPMiniMessage");

// **** PLEASE READ ****
// The INPUT and OUTPUT buffers are raw user mode addresses. The filter
// manager has already done a ProbedForRead (on InputBuffer) and
// ProbedForWrite (on OutputBuffer) which guarentees they are valid
// addresses based on the access (user mode vs. kernel mode). The
// minifilter does not need to do their own probe.
// The filter manager is NOT doing any alignment checking on the pointers.
// The minifilter must do this themselves if they care (see below).
// The minifilter MUST continue to use a try/except around any access to
// these buffers.

if ((InputBuffer != NULL) &&
(InputBufferSize >= (FIELD_OFFSET(COMMAND_MESSAGE,Command) +
sizeof(NPMINI_COMMAND)))) {

try {
// Probe and capture input message: the message is raw user mode
// buffer, so need to protect with exception handler
command = ((PCOMMAND_MESSAGE) InputBuffer)->Command;

} except( EXCEPTION_EXECUTE_HANDLER ) {

return GetExceptionCode();
}

switch (command) {
// } W h
case ENUM_PASS:
{
DbgPrint("[mini-filter] ENUM_PASS");
gCommand = ENUM_PASS;
status = STATUS_SUCCESS;
break;
}
// ׳W h
case ENUM_BLOCK:
{
DbgPrint("[mini-filter] ENUM_BLOCK");
gCommand = ENUM_BLOCK;
status = STATUS_SUCCESS;
break;
}

default:
DbgPrint("[mini-filter] default");
status = STATUS_INVALID_PARAMETER;
break;
}
} else {

status = STATUS_INVALID_PARAMETER;
}

return status;
}

NPminifilter.h

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
#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
#include <ntddscsi.h>

#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")

#define PTDBG_TRACE_ROUTINES 0x00000001
#define PTDBG_TRACE_OPERATION_STATUS 0x00000002

#define MINISPY_PORT_NAME L"\\NPMiniPort"

/**
* 锣传﹃Α
*
* @param UniName IN UNICODE_STRING
* @param Name IN OUT char pointor
* @return BOOLEAN TURE,FALSE
*/
BOOLEAN NPUnicodeStringToChar(PUNICODE_STRING UniName, char Name[]);


/*************************************************************************
Prototypes
*************************************************************************/

NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
);

NTSTATUS
NPInstanceSetup (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_SETUP_FLAGS Flags,
__in DEVICE_TYPE VolumeDeviceType,
__in FLT_FILESYSTEM_TYPE VolumeFilesystemType
);

VOID
NPInstanceTeardownStart (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_TEARDOWN_FLAGS Flags
);

VOID
NPInstanceTeardownComplete (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_TEARDOWN_FLAGS Flags
);

NTSTATUS
NPUnload (
__in FLT_FILTER_UNLOAD_FLAGS Flags
);

NTSTATUS
NPInstanceQueryTeardown (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);

FLT_PREOP_CALLBACK_STATUS
NPPreCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
);

FLT_POSTOP_CALLBACK_STATUS
NPPostCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
);

NTSTATUS
NPMiniMessage (
__in PVOID ConnectionCookie,
__in_bcount_opt(InputBufferSize) PVOID InputBuffer,
__in ULONG InputBufferSize,
__out_bcount_part_opt(OutputBufferSize,*ReturnOutputBufferLength) PVOID OutputBuffer,
__in ULONG OutputBufferSize,
__out PULONG ReturnOutputBufferLength
);

NTSTATUS
NPMiniConnect(
__in PFLT_PORT ClientPort,
__in PVOID ServerPortCookie,
__in_bcount(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
);

VOID
NPMiniDisconnect(
__in_opt PVOID ConnectionCookie
);

// Assign text sections for each routine.
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, NPUnload)
#pragma alloc_text(PAGE, NPInstanceQueryTeardown)
#pragma alloc_text(PAGE, NPInstanceSetup)
#pragma alloc_text(PAGE, NPInstanceTeardownStart)
#pragma alloc_text(PAGE, NPInstanceTeardownComplete)
#pragma alloc_text(PAGE, NPPreCreate)
#pragma alloc_text(PAGE, NPMiniConnect) //for port comunication
#pragma alloc_text(PAGE, NPMiniDisconnect) //for port comunication
#pragma alloc_text(PAGE, NPMiniMessage) //for port comunication
#endif

// operation registration
const FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE,
0,
NPPreCreate,
NPPostCreate },

{ IRP_MJ_OPERATION_END }
};

// This defines what we want to filter with FltMgr
const FLT_REGISTRATION FilterRegistration = {

sizeof( FLT_REGISTRATION ), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags

NULL, // Context
Callbacks, // Operation callbacks

NPUnload, // MiniFilterUnload

NPInstanceSetup, // InstanceSetup
NPInstanceQueryTeardown, // InstanceQueryTeardown
NPInstanceTeardownStart, // InstanceTeardownStart
NPInstanceTeardownComplete, // InstanceTeardownComplete

NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL // NormalizeNameComponent

};

// Defines the commands between the utility and the filter
typedef enum _NPMINI_COMMAND {
ENUM_PASS = 0,
ENUM_BLOCK
} NPMINI_COMMAND;

// Defines the command structure between the utility and the filter.
typedef struct _COMMAND_MESSAGE {
NPMINI_COMMAND Command;
} COMMAND_MESSAGE, *PCOMMAND_MESSAGE;