ReactOS 0.4.15-dev-7961-gdcf9eb0
filtrctx.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fsrtl/filtrctx.c
5 * PURPOSE: File Stream Filter Context support for File System Drivers
6 * PROGRAMMERS: Pierre Schweitzer (pierre.schweitzer@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* PRIVATE FUNCTIONS *********************************************************/
16
18{
22
23/*
24 * @implemented
25 */
26VOID
29{
31
33
34 if (!(FOContext = IoGetFileObjectFilterContext(FileObject)))
35 {
36 return;
37 }
38
40 ASSERT(IsListEmpty(&(FOContext->FilterContexts)));
41
42 ExFreePoolWithTag(FOContext, 'FOCX');
43}
44
45
46/* PUBLIC FUNCTIONS **********************************************************/
47
48/*++
49 * @name FsRtlIsPagingFile
50 * @implemented NT 5.2
51 *
52 * The FsRtlIsPagingFile routine checks if the FileObject is a Paging File.
53 *
54 * @param FileObject
55 * A pointer to the File Object to be tested.
56 *
57 * @return TRUE if the File is a Paging File, FALSE otherwise.
58 *
59 * @remarks None.
60 *
61 *--*/
62LOGICAL
65{
67}
68
69/*
70 * @implemented
71 */
77{
78 PLIST_ENTRY NextEntry;
80 PFSRTL_PER_FILEOBJECT_CONTEXT TmpPerFOContext, PerFOContext = NULL;
81
83 {
84 return NULL;
85 }
86
88
89 /* If list is empty, no need to browse it */
90 if (!IsListEmpty(&(FOContext->FilterContexts)))
91 {
92 for (NextEntry = FOContext->FilterContexts.Flink;
93 NextEntry != &(FOContext->FilterContexts);
94 NextEntry = NextEntry->Flink)
95 {
96 /* If we don't have any criteria for search, first entry will be enough */
97 if (!OwnerId && !InstanceId)
98 {
99 PerFOContext = (PFSRTL_PER_FILEOBJECT_CONTEXT)NextEntry;
100 break;
101 }
102 /* Else, we've to find something that matches with the parameters. */
103 else
104 {
105 TmpPerFOContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_FILEOBJECT_CONTEXT, Links);
106 if ((InstanceId && TmpPerFOContext->InstanceId == InstanceId && TmpPerFOContext->OwnerId == OwnerId) ||
107 (OwnerId && TmpPerFOContext->OwnerId == OwnerId))
108 {
109 PerFOContext = TmpPerFOContext;
110 break;
111 }
112 }
113 }
114 }
115
117
118 return PerFOContext;
119}
120
121/*
122 * @implemented
123 */
125NTAPI
129{
130 PLIST_ENTRY NextEntry;
131 PFSRTL_PER_STREAM_CONTEXT TmpPerStreamContext, PerStreamContext = NULL;
132
133 ASSERT(AdvFcbHeader);
134 ASSERT(FlagOn(AdvFcbHeader->Flags2, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS));
135
136 ExAcquireFastMutex(AdvFcbHeader->FastMutex);
137
138 /* If list is empty, no need to browse it */
139 if (!IsListEmpty(&(AdvFcbHeader->FilterContexts)))
140 {
141 for (NextEntry = AdvFcbHeader->FilterContexts.Flink;
142 NextEntry != &(AdvFcbHeader->FilterContexts);
143 NextEntry = NextEntry->Flink)
144 {
145 /* If we don't have any criteria for search, first entry will be enough */
146 if (!OwnerId && !InstanceId)
147 {
148 PerStreamContext = (PFSRTL_PER_STREAM_CONTEXT)NextEntry;
149 break;
150 }
151 /* Else, we've to find something that matches with the parameters. */
152 else
153 {
154 TmpPerStreamContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_STREAM_CONTEXT, Links);
155 if ((InstanceId && TmpPerStreamContext->InstanceId == InstanceId && TmpPerStreamContext->OwnerId == OwnerId) ||
156 (OwnerId && TmpPerStreamContext->OwnerId == OwnerId))
157 {
158 PerStreamContext = TmpPerStreamContext;
159 break;
160 }
161 }
162 }
163 }
164
165 ExReleaseFastMutex(AdvFcbHeader->FastMutex);
166
167 return PerStreamContext;
168}
169
170/*
171 * @implemented
172 */
174NTAPI
177{
179
180 if (!FileObject)
181 {
183 }
184
186 {
188 }
189
190 /* Get filter contexts */
192 if (!FOContext)
193 {
194 /* If there's none, allocate new structure */
196 if (!FOContext)
197 {
199 }
200
201 /* Initialize it */
203 InitializeListHead(&(FOContext->FilterContexts));
204
205 /* Set it */
207 {
208 /* If it fails, it means that someone else has set it in the meanwhile */
209 ExFreePoolWithTag(FOContext, 'FOCX');
210
211 /* So, we can get it */
213 if (!FOContext)
214 {
215 /* If we fall down here, something went very bad. This shouldn't happen */
216 ASSERT(FALSE);
217 return STATUS_UNSUCCESSFUL;
218 }
219 }
220 }
221
222 /* Finally, insert */
224 InsertHeadList(&(FOContext->FilterContexts), &(Ptr->Links));
226
227 return STATUS_SUCCESS;
228}
229
230/*
231 * @implemented
232 */
234NTAPI
236 IN PFSRTL_PER_STREAM_CONTEXT PerStreamContext)
237{
238 if (!(AdvFcbHeader) || !(AdvFcbHeader->Flags2 & FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS))
239 {
241 }
242
243 ExAcquireFastMutex(AdvFcbHeader->FastMutex);
244 InsertHeadList(&(AdvFcbHeader->FilterContexts), &(PerStreamContext->Links));
245 ExReleaseFastMutex(AdvFcbHeader->FastMutex);
246 return STATUS_SUCCESS;
247}
248
249/*
250 * @implemented
251 */
253NTAPI
257{
258 PLIST_ENTRY NextEntry;
260 PFSRTL_PER_FILEOBJECT_CONTEXT TmpPerFOContext, PerFOContext = NULL;
261
262 if (!FileObject || !(FOContext = IoGetFileObjectFilterContext(FileObject)))
263 {
264 return NULL;
265 }
266
268
269 /* If list is empty, no need to browse it */
270 if (!IsListEmpty(&(FOContext->FilterContexts)))
271 {
272 for (NextEntry = FOContext->FilterContexts.Flink;
273 NextEntry != &(FOContext->FilterContexts);
274 NextEntry = NextEntry->Flink)
275 {
276 /* If we don't have any criteria for search, first entry will be enough */
277 if (!OwnerId && !InstanceId)
278 {
279 PerFOContext = (PFSRTL_PER_FILEOBJECT_CONTEXT)NextEntry;
280 break;
281 }
282 /* Else, we've to find something that matches with the parameters. */
283 else
284 {
285 TmpPerFOContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_FILEOBJECT_CONTEXT, Links);
286 if ((InstanceId && TmpPerFOContext->InstanceId == InstanceId && TmpPerFOContext->OwnerId == OwnerId) ||
287 (OwnerId && TmpPerFOContext->OwnerId == OwnerId))
288 {
289 PerFOContext = TmpPerFOContext;
290 break;
291 }
292 }
293 }
294
295 /* Finally remove entry from list */
296 if (PerFOContext)
297 {
298 RemoveEntryList(&(PerFOContext->Links));
299 }
300 }
301
303
304 return PerFOContext;
305}
306
307/*
308 * @implemented
309 */
311NTAPI
315{
316 PLIST_ENTRY NextEntry;
317 PFSRTL_PER_STREAM_CONTEXT TmpPerStreamContext, PerStreamContext = NULL;
318
319 if (!(AdvFcbHeader) || !(AdvFcbHeader->Flags2 & FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS))
320 {
321 return NULL;
322 }
323
324 ExAcquireFastMutex(AdvFcbHeader->FastMutex);
325 /* If list is empty, no need to browse it */
326 if (!IsListEmpty(&(AdvFcbHeader->FilterContexts)))
327 {
328 for (NextEntry = AdvFcbHeader->FilterContexts.Flink;
329 NextEntry != &(AdvFcbHeader->FilterContexts);
330 NextEntry = NextEntry->Flink)
331 {
332 /* If we don't have any criteria for search, first entry will be enough */
333 if (!OwnerId && !InstanceId)
334 {
335 PerStreamContext = (PFSRTL_PER_STREAM_CONTEXT)NextEntry;
336 break;
337 }
338 /* Else, we've to find something that matches with the parameters. */
339 else
340 {
341 TmpPerStreamContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_STREAM_CONTEXT, Links);
342 if ((InstanceId && TmpPerStreamContext->InstanceId == InstanceId && TmpPerStreamContext->OwnerId == OwnerId) ||
343 (OwnerId && TmpPerStreamContext->OwnerId == OwnerId))
344 {
345 PerStreamContext = TmpPerStreamContext;
346 break;
347 }
348 }
349 }
350
351 /* Finally remove entry from list */
352 if (PerStreamContext)
353 {
354 RemoveEntryList(&(PerStreamContext->Links));
355 }
356 }
357 ExReleaseFastMutex(AdvFcbHeader->FastMutex);
358
359 return PerStreamContext;
360
361}
362
363/*
364 * @implemented
365 */
366VOID
367NTAPI
369{
370 PLIST_ENTRY NextEntry;
371 volatile BOOLEAN IsMutexLocked = FALSE;
372 PFSRTL_PER_STREAM_CONTEXT PerStreamContext;
373
375 {
376 /* Acquire mutex to deal with the list */
377 ExAcquireFastMutex(AdvFcbHeader->FastMutex);
378 IsMutexLocked = TRUE;
379
380 /* While there are items... */
381 while (!IsListEmpty(&(AdvFcbHeader->FilterContexts)))
382 {
383 /* ...remove one */
384 NextEntry = RemoveHeadList(&(AdvFcbHeader->FilterContexts));
385 PerStreamContext = CONTAINING_RECORD(NextEntry, FSRTL_PER_STREAM_CONTEXT, Links);
386
387 /* Release mutex before calling callback */
388 ExReleaseFastMutex(AdvFcbHeader->FastMutex);
389 IsMutexLocked = FALSE;
390
391 /* Call the callback */
392 ASSERT(PerStreamContext->FreeCallback);
393 (*PerStreamContext->FreeCallback)(PerStreamContext);
394
395 /* Relock the list to continue */
396 ExAcquireFastMutex(AdvFcbHeader->FastMutex);
397 IsMutexLocked = TRUE;
398 }
399 }
401 {
402 /* If mutex was locked, release */
403 if (IsMutexLocked)
404 {
405 ExReleaseFastMutex(AdvFcbHeader->FastMutex);
406 }
407 }
408 _SEH2_END;
409}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
struct _FILE_OBJECT_FILTER_CONTEXTS * PFILE_OBJECT_FILTER_CONTEXTS
PFSRTL_PER_FILEOBJECT_CONTEXT NTAPI FsRtlLookupPerFileObjectContext(IN PFILE_OBJECT FileObject, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL)
Definition: filtrctx.c:74
VOID NTAPI FsRtlTeardownPerStreamContexts(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader)
Definition: filtrctx.c:368
LOGICAL NTAPI FsRtlIsPagingFile(IN PFILE_OBJECT FileObject)
Definition: filtrctx.c:64
PFSRTL_PER_FILEOBJECT_CONTEXT NTAPI FsRtlRemovePerFileObjectContext(IN PFILE_OBJECT FileObject, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL)
Definition: filtrctx.c:254
struct _FILE_OBJECT_FILTER_CONTEXTS FILE_OBJECT_FILTER_CONTEXTS
NTSTATUS NTAPI FsRtlInsertPerStreamContext(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, IN PFSRTL_PER_STREAM_CONTEXT PerStreamContext)
Definition: filtrctx.c:235
VOID NTAPI FsRtlPTeardownPerFileObjectContexts(IN PFILE_OBJECT FileObject)
Definition: filtrctx.c:28
NTSTATUS NTAPI FsRtlInsertPerFileObjectContext(IN PFILE_OBJECT FileObject, IN PFSRTL_PER_FILEOBJECT_CONTEXT Ptr)
Definition: filtrctx.c:175
PFSRTL_PER_STREAM_CONTEXT NTAPI FsRtlLookupPerStreamContextInternal(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL)
Definition: filtrctx.c:126
PFSRTL_PER_STREAM_CONTEXT NTAPI FsRtlRemovePerStreamContext(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL)
Definition: filtrctx.c:312
_Must_inspect_result_ _In_opt_ PVOID _In_opt_ PVOID InstanceId
Definition: fsrtlfuncs.h:908
_Must_inspect_result_ _In_opt_ PVOID OwnerId
Definition: fsrtlfuncs.h:907
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
struct _FSRTL_PER_FILEOBJECT_CONTEXT * PFSRTL_PER_FILEOBJECT_CONTEXT
#define FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS
Definition: fsrtltypes.h:55
struct _FSRTL_PER_STREAM_CONTEXT * PFSRTL_PER_STREAM_CONTEXT
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define FO_FILE_OBJECT_HAS_EXTENSION
Definition: iotypes.h:144
NTSTATUS NTAPI IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject, IN PVOID FilterContext, IN BOOLEAN Define)
Definition: file.c:2511
PVOID NTAPI IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject)
Definition: file.c:2496
BOOLEAN NTAPI MmIsFileObjectAPagingFile(PFILE_OBJECT FileObject)
Definition: pagefile.c:119
#define STATUS_SUCCESS
Definition: shellext.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
FAST_MUTEX FilterContextsMutex
Definition: filtrctx.c:19
PFREE_FUNCTION FreeCallback
Definition: fsrtltypes.h:164
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
FAST_MUTEX
Definition: extypes.h:17
* PFILE_OBJECT
Definition: iotypes.h:1998