ReactOS  0.4.14-dev-552-g2fad488
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  */
26 VOID
27 NTAPI
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  *--*/
62 LOGICAL
63 NTAPI
65 {
67 }
68 
69 /*
70  * @implemented
71  */
73 NTAPI
77 {
78  PLIST_ENTRY NextEntry;
80  PFSRTL_PER_FILEOBJECT_CONTEXT TmpPerFOContext, PerFOContext = NULL;
81 
82  if (!FileObject || !(FOContext = IoGetFileObjectFilterContext(FileObject)))
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  */
125 NTAPI
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  */
173 NTSTATUS
174 NTAPI
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 */
195  FOContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_OBJECT_FILTER_CONTEXTS), 'FOCX');
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  */
233 NTSTATUS
234 NTAPI
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  */
253 NTAPI
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  */
311 NTAPI
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  */
366 VOID
367 NTAPI
369 {
370  PLIST_ENTRY NextEntry;
371  volatile BOOLEAN IsMutexLocked = FALSE;
372  PFSRTL_PER_STREAM_CONTEXT PerStreamContext;
373 
374  _SEH2_TRY
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 }
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID NTAPI FsRtlPTeardownPerFileObjectContexts(IN PFILE_OBJECT FileObject)
Definition: filtrctx.c:28
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
NTSTATUS NTAPI FsRtlInsertPerFileObjectContext(IN PFILE_OBJECT FileObject, IN PFSRTL_PER_FILEOBJECT_CONTEXT Ptr)
Definition: filtrctx.c:175
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
FAST_MUTEX FilterContextsMutex
Definition: filtrctx.c:19
_SEH2_TRY
Definition: create.c:4250
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
PFREE_FUNCTION FreeCallback
Definition: fsrtltypes.h:164
_Must_inspect_result_ _In_opt_ PVOID _In_opt_ PVOID InstanceId
Definition: fsrtlfuncs.h:907
LOGICAL NTAPI FsRtlIsPagingFile(IN PFILE_OBJECT FileObject)
Definition: filtrctx.c:64
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FAST_MUTEX
Definition: extypes.h:17
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID NTAPI FsRtlTeardownPerStreamContexts(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader)
Definition: filtrctx.c:368
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
PVOID NTAPI IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject)
Definition: file.c:2495
#define FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS
Definition: fsrtltypes.h:55
* PFILE_OBJECT
Definition: iotypes.h:1955
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define FO_FILE_OBJECT_HAS_EXTENSION
Definition: iotypes.h:144
Definition: typedefs.h:117
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
struct _FSRTL_PER_FILEOBJECT_CONTEXT * PFSRTL_PER_FILEOBJECT_CONTEXT
_SEH2_END
Definition: create.c:4424
PFSRTL_PER_FILEOBJECT_CONTEXT NTAPI FsRtlRemovePerFileObjectContext(IN PFILE_OBJECT FileObject, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL)
Definition: filtrctx.c:254
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
PFSRTL_PER_STREAM_CONTEXT NTAPI FsRtlRemovePerStreamContext(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL)
Definition: filtrctx.c:312
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
struct _FSRTL_PER_STREAM_CONTEXT * PFSRTL_PER_STREAM_CONTEXT
_SEH2_FINALLY
Definition: create.c:4395
NTSTATUS NTAPI IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject, IN PVOID FilterContext, IN BOOLEAN Define)
Definition: file.c:2510
PFSRTL_PER_FILEOBJECT_CONTEXT NTAPI FsRtlLookupPerFileObjectContext(IN PFILE_OBJECT FileObject, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL)
Definition: filtrctx.c:74
struct _FILE_OBJECT_FILTER_CONTEXTS * PFILE_OBJECT_FILTER_CONTEXTS
NTSTATUS NTAPI FsRtlInsertPerStreamContext(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, IN PFSRTL_PER_STREAM_CONTEXT PerStreamContext)
Definition: filtrctx.c:235
BOOLEAN NTAPI MmIsFileObjectAPagingFile(PFILE_OBJECT FileObject)
Definition: pagefile.c:109
struct _FILE_OBJECT_FILTER_CONTEXTS FILE_OBJECT_FILTER_CONTEXTS
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_Must_inspect_result_ _In_opt_ PVOID OwnerId
Definition: fsrtlfuncs.h:907
return STATUS_SUCCESS
Definition: btrfs.c:2938
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
PFSRTL_PER_STREAM_CONTEXT NTAPI FsRtlLookupPerStreamContextInternal(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader, IN PVOID OwnerId OPTIONAL, IN PVOID InstanceId OPTIONAL)
Definition: filtrctx.c:126