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
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
|
/*++
Copyright (c) Microsoft Corporation
Module Name:
Filter.h
Abstract:
This module contains all prototypes and macros for filter code.
Notes:
--*/
#ifndef _FILT_H
#define _FILT_H
#pragma warning(disable:28930) // Unused assignment of pointer, by design in samples
#pragma warning(disable:28931) // Unused assignment of variable, by design in samples
// TODO: Customize these to hint at your component for memory leak tracking.
// These should be treated like a pooltag.
#define FILTER_REQUEST_ID 'RTLF'
#define FILTER_ALLOC_TAG 'tliF'
#define FILTER_TAG 'dnTF'
// TODO: Specify which version of the NDIS contract you will use here.
// In many cases, 6.0 is the best choice. You only need to select a later
// version if you need a feature that is not available in 6.0.
//
// Legal values include:
// 6.0 Available starting with Windows Vista RTM
// 6.1 Available starting with Windows Vista SP1 / Windows Server 2008
// 6.20 Available starting with Windows 7 / Windows Server 2008 R2
// 6.30 Available starting with Windows 8 / Windows Server "8"
// Or, just use NDIS_FILTER_MAJOR_VERSION / NDIS_FILTER_MINOR_VERSION
// to pick up whatever version is defined by your build system
// (for example, "-DNDIS630").
#define FILTER_MAJOR_NDIS_VERSION NDIS_FILTER_MAJOR_VERSION
#define FILTER_MINOR_NDIS_VERSION NDIS_FILTER_MINOR_VERSION
//
// Global variables
//
extern NDIS_HANDLE FilterDriverHandle; // NDIS handle for filter driver
extern NDIS_HANDLE FilterDriverObject;
extern NDIS_HANDLE NdisFilterDeviceHandle;
extern PDEVICE_OBJECT NdisDeviceObject;
extern FILTER_LOCK FilterListLock;
extern LIST_ENTRY FilterModuleList;
#if NDISLWF
#define FILTER_FRIENDLY_NAME L"NDIS Sample LightWeight Filter"
// TODO: Customize this to match the GUID in the INF
#define FILTER_UNIQUE_NAME L"{5cbf81bd-5055-47cd-9055-a76b2b4e3697}" //unique name, quid name
// TODO: Customize this to match the service name in the INF
#define FILTER_SERVICE_NAME L"NDISLWF"
//
// The filter needs to handle IOCTLs
//
#define LINKNAME_STRING L"\\DosDevices\\NDISLWF"
#define NTDEVICE_STRING L"\\Device\\NDISLWF"
#endif
#if NDISLWF1
#define FILTER_FRIENDLY_NAME L"NDIS Sample LightWeight Filter 1"
#define FILTER_UNIQUE_NAME L"{5cbf81be-5055-47cd-9055-a76b2b4e3697}" //unique name, quid name
#define FILTER_SERVICE_NAME L"NDISLWF1"
//
// The filter needs to handle IOCTRLs
//
#define LINKNAME_STRING L"\\DosDevices\\NDISLWF1"
#define NTDEVICE_STRING L"\\Device\\NDISLWF1"
#endif
#if NDISMON
#define FILTER_FRIENDLY_NAME L"NDIS Sample Monitor LightWeight Filter"
#define FILTER_UNIQUE_NAME L"{5cbf81bf-5055-47cd-9055-a76b2b4e3697}" //unique name, quid name
#define FILTER_SERVICE_NAME L"NDISMON"
//
// The filter needs to handle IOCTRLs
//
#define LINKNAME_STRING L"\\DosDevices\\NDISMON"
#define NTDEVICE_STRING L"\\Device\\NDISMON"
#endif
#if NDISMON1
#define FILTER_FRIENDLY_NAME L"NDIS Sample Monitor 1 LightWeight Filter"
#define FILTER_UNIQUE_NAME L"{5cbf81c0-5055-47cd-9055-a76b2b4e3697}" //unique name, quid name
#define FILTER_SERVICE_NAME L"NDISMON1"
//
// The filter needs to handle IOCTRLs
//
#define LINKNAME_STRING L"\\DosDevices\\NDISMON1"
#define NTDEVICE_STRING L"\\Device\\NDISMON1"
#endif
//
// Types and macros to manipulate packet queue
//
typedef struct _QUEUE_ENTRY
{
struct _QUEUE_ENTRY * Next;
}QUEUE_ENTRY, *PQUEUE_ENTRY;
typedef struct _QUEUE_HEADER
{
PQUEUE_ENTRY Head;
PQUEUE_ENTRY Tail;
} QUEUE_HEADER, *PQUEUE_HEADER;
#if TRACK_RECEIVES
UINT filterLogReceiveRefIndex = 0;
ULONG_PTR filterLogReceiveRef[0x10000];
#endif
#if TRACK_SENDS
UINT filterLogSendRefIndex = 0;
ULONG_PTR filterLogSendRef[0x10000];
#endif
#if TRACK_RECEIVES
#define FILTER_LOG_RCV_REF(_O, _Instance, _NetBufferList, _Ref) \
{\
filterLogReceiveRef[filterLogReceiveRefIndex++] = (ULONG_PTR)(_O); \
filterLogReceiveRef[filterLogReceiveRefIndex++] = (ULONG_PTR)(_Instance); \
filterLogReceiveRef[filterLogReceiveRefIndex++] = (ULONG_PTR)(_NetBufferList); \
filterLogReceiveRef[filterLogReceiveRefIndex++] = (ULONG_PTR)(_Ref); \
if (filterLogReceiveRefIndex >= (0x10000 - 5)) \
{ \
filterLogReceiveRefIndex = 0; \
} \
}
#else
#define FILTER_LOG_RCV_REF(_O, _Instance, _NetBufferList, _Ref)
#endif
#if TRACK_SENDS
#define FILTER_LOG_SEND_REF(_O, _Instance, _NetBufferList, _Ref) \
{\
filterLogSendRef[filterLogSendRefIndex++] = (ULONG_PTR)(_O); \
filterLogSendRef[filterLogSendRefIndex++] = (ULONG_PTR)(_Instance); \
filterLogSendRef[filterLogSendRefIndex++] = (ULONG_PTR)(_NetBufferList); \
filterLogSendRef[filterLogSendRefIndex++] = (ULONG_PTR)(_Ref); \
if (filterLogSendRefIndex >= (0x10000 - 5)) \
{ \
filterLogSendRefIndex = 0; \
} \
}
#else
#define FILTER_LOG_SEND_REF(_O, _Instance, _NetBufferList, _Ref)
#endif
//
// DEBUG related macros.
//
#if DBG
#define FILTER_ALLOC_MEM(_NdisHandle, _Size) \
filterAuditAllocMem( \
_NdisHandle, \
_Size, \
__FILENUMBER, \
__LINE__);
#define FILTER_FREE_MEM(_pMem) \
filterAuditFreeMem(_pMem);
#else
#define FILTER_ALLOC_MEM(_NdisHandle, _Size) \
NdisAllocateMemoryWithTagPriority(_NdisHandle, _Size, FILTER_ALLOC_TAG, LowPoolPriority)
#define FILTER_FREE_MEM(_pMem) NdisFreeMemory(_pMem, 0, 0)
#endif //DBG
#if DBG_SPIN_LOCK
#define FILTER_INIT_LOCK(_pLock) \
filterAllocateSpinLock(_pLock, __FILENUMBER, __LINE__)
#define FILTER_FREE_LOCK(_pLock) filterFreeSpinLock(_pLock)
#define FILTER_ACQUIRE_LOCK(_pLock, DispatchLevel) \
filterAcquireSpinLock(_pLock, __FILENUMBER, __LINE__, DisaptchLevel)
#define FILTER_RELEASE_LOCK(_pLock, DispatchLevel) \
filterReleaseSpinLock(_pLock, __FILENUMBER, __LINE__, DispatchLevel)
#else
#define FILTER_INIT_LOCK(_pLock) NdisAllocateSpinLock(_pLock)
#define FILTER_FREE_LOCK(_pLock) NdisFreeSpinLock(_pLock)
#define FILTER_ACQUIRE_LOCK(_pLock, DispatchLevel) \
{ \
if (DispatchLevel) \
{ \
NdisDprAcquireSpinLock(_pLock); \
} \
else \
{ \
NdisAcquireSpinLock(_pLock); \
} \
}
#define FILTER_RELEASE_LOCK(_pLock, DispatchLevel) \
{ \
if (DispatchLevel) \
{ \
NdisDprReleaseSpinLock(_pLock); \
} \
else \
{ \
NdisReleaseSpinLock(_pLock); \
} \
}
#endif //DBG_SPIN_LOCK
#define NET_BUFFER_LIST_LINK_TO_ENTRY(_pNBL) ((PQUEUE_ENTRY)(NET_BUFFER_LIST_NEXT_NBL(_pNBL)))
#define ENTRY_TO_NET_BUFFER_LIST(_pEnt) (CONTAINING_RECORD((_pEnt), NET_BUFFER_LIST, Next))
#define InitializeQueueHeader(_QueueHeader) \
{ \
(_QueueHeader)->Head = (_QueueHeader)->Tail = NULL; \
}
//
// Macros for queue operations
//
#define IsQueueEmpty(_QueueHeader) ((_QueueHeader)->Head == NULL)
#define RemoveHeadQueue(_QueueHeader) \
(_QueueHeader)->Head; \
{ \
PQUEUE_ENTRY pNext; \
ASSERT((_QueueHeader)->Head); \
pNext = (_QueueHeader)->Head->Next; \
(_QueueHeader)->Head = pNext; \
if (pNext == NULL) \
(_QueueHeader)->Tail = NULL; \
}
#define InsertHeadQueue(_QueueHeader, _QueueEntry) \
{ \
((PQUEUE_ENTRY)(_QueueEntry))->Next = (_QueueHeader)->Head; \
(_QueueHeader)->Head = (PQUEUE_ENTRY)(_QueueEntry); \
if ((_QueueHeader)->Tail == NULL) \
(_QueueHeader)->Tail = (PQUEUE_ENTRY)(_QueueEntry); \
}
#define InsertTailQueue(_QueueHeader, _QueueEntry) \
{ \
((PQUEUE_ENTRY)(_QueueEntry))->Next = NULL; \
if ((_QueueHeader)->Tail) \
(_QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(_QueueEntry); \
else \
(_QueueHeader)->Head = (PQUEUE_ENTRY)(_QueueEntry); \
(_QueueHeader)->Tail = (PQUEUE_ENTRY)(_QueueEntry); \
}
//
// Enum of filter's states
// Filter can only be in one state at one time
//
typedef enum _FILTER_STATE
{
FilterStateUnspecified,
FilterInitialized,
FilterPausing,
FilterPaused,
FilterRunning,
FilterRestarting,
FilterDetaching
} FILTER_STATE;
typedef struct _FILTER_REQUEST
{
NDIS_OID_REQUEST Request;
NDIS_EVENT ReqEvent;
NDIS_STATUS Status;
} FILTER_REQUEST, *PFILTER_REQUEST;
//
// Define the filter struct
//
typedef struct _MS_FILTER
{
LIST_ENTRY FilterModuleLink;
//Reference to this filter
ULONG RefCount;
NDIS_HANDLE FilterHandle;
NDIS_STRING FilterModuleName;
NDIS_STRING MiniportFriendlyName;
NDIS_STRING MiniportName;
NET_IFINDEX MiniportIfIndex;
NDIS_STATUS Status;
NDIS_EVENT Event;
ULONG BackFillSize;
FILTER_LOCK Lock; // Lock for protection of state and outstanding sends and recvs
FILTER_STATE State; // Which state the filter is in
ULONG OutstandingSends;
ULONG OutstandingRequest;
ULONG OutstandingRcvs;
FILTER_LOCK SendLock;
FILTER_LOCK RcvLock;
QUEUE_HEADER SendNBLQueue;
QUEUE_HEADER RcvNBLQueue;
NDIS_STRING FilterName;
ULONG CallsRestart;
BOOLEAN TrackReceives;
BOOLEAN TrackSends;
#if DBG
BOOLEAN bIndicating;
#endif
PNDIS_OID_REQUEST PendingOidRequest;
}MS_FILTER, * PMS_FILTER;
typedef struct _FILTER_DEVICE_EXTENSION
{
ULONG Signature;
NDIS_HANDLE Handle;
} FILTER_DEVICE_EXTENSION, *PFILTER_DEVICE_EXTENSION;
#define FILTER_READY_TO_PAUSE(_Filter) \
((_Filter)->State == FilterPausing)
//
// The driver should maintain a list of NDIS filter handles
//
typedef struct _FL_NDIS_FILTER_LIST
{
LIST_ENTRY Link;
NDIS_HANDLE ContextHandle;
NDIS_STRING FilterInstanceName;
} FL_NDIS_FILTER_LIST, *PFL_NDIS_FILTER_LIST;
//
// The context inside a cloned request
//
typedef struct _NDIS_OID_REQUEST *FILTER_REQUEST_CONTEXT,**PFILTER_REQUEST_CONTEXT;
//
// function prototypes
//
DRIVER_INITIALIZE DriverEntry;
FILTER_SET_OPTIONS FilterRegisterOptions;
FILTER_ATTACH FilterAttach;
FILTER_DETACH FilterDetach;
DRIVER_UNLOAD FilterUnload;
FILTER_RESTART FilterRestart;
FILTER_PAUSE FilterPause;
FILTER_OID_REQUEST FilterOidRequest;
FILTER_CANCEL_OID_REQUEST FilterCancelOidRequest;
FILTER_STATUS FilterStatus;
FILTER_DEVICE_PNP_EVENT_NOTIFY FilterDevicePnPEventNotify;
FILTER_NET_PNP_EVENT FilterNetPnPEvent;
FILTER_OID_REQUEST_COMPLETE FilterOidRequestComplete;
FILTER_SEND_NET_BUFFER_LISTS FilterSendNetBufferLists;
FILTER_RETURN_NET_BUFFER_LISTS FilterReturnNetBufferLists;
FILTER_SEND_NET_BUFFER_LISTS_COMPLETE FilterSendNetBufferListsComplete;
FILTER_RECEIVE_NET_BUFFER_LISTS FilterReceiveNetBufferLists;
FILTER_CANCEL_SEND_NET_BUFFER_LISTS FilterCancelSendNetBufferLists;
FILTER_SET_MODULE_OPTIONS FilterSetModuleOptions;
_IRQL_requires_max_(PASSIVE_LEVEL)
NDIS_STATUS
FilterRegisterDevice(
VOID
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
FilterDeregisterDevice(
VOID
);
DRIVER_DISPATCH FilterDispatch;
DRIVER_DISPATCH FilterDeviceIoControl;
_IRQL_requires_max_(DISPATCH_LEVEL)
PMS_FILTER
filterFindFilterModule(
_In_reads_bytes_(BufferLength)
PUCHAR Buffer,
_In_ ULONG BufferLength
);
_IRQL_requires_max_(DISPATCH_LEVEL)
NDIS_STATUS
filterDoInternalRequest(
_In_ PMS_FILTER FilterModuleContext,
_In_ NDIS_REQUEST_TYPE RequestType,
_In_ NDIS_OID Oid,
_Inout_updates_bytes_to_(InformationBufferLength, *pBytesProcessed)
PVOID InformationBuffer,
_In_ ULONG InformationBufferLength,
_In_opt_ ULONG OutputBufferLength,
_In_ ULONG MethodId,
_Out_ PULONG pBytesProcessed
);
VOID
filterInternalRequestComplete(
_In_ NDIS_HANDLE FilterModuleContext,
_In_ PNDIS_OID_REQUEST NdisRequest,
_In_ NDIS_STATUS Status
);
#endif //_FILT_H
|