WDK Mini Filter Example
DataStore.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 2002 - 2003 Microsoft Corporation
4 
5 Module Name:
6 
7  datastore.c
8 
9 Abstract:
10 
11  This module contains routines that provide support for storage and
12  retrieval of the filter metadata manager filter metadata.
13 
14 
15 Environment:
16 
17  Kernel mode
18 
19 
20 --*/
21 
22 #include "pch.h"
23 
24 //
25 // Assign text sections for each routine.
26 //
27 
28 #ifdef ALLOC_PRAGMA
29 #pragma alloc_text(PAGE, FmmOpenMetadata)
30 #pragma alloc_text(PAGE, FmmCloseMetadata)
31 #pragma alloc_text(PAGE, FmmReleaseMetadataFileReferences)
32 #pragma alloc_text(PAGE, FmmReacquireMetadataFileReferences)
33 #pragma alloc_text(PAGE, FmmSetMetadataOpenTriggerFileObject)
34 #pragma alloc_text(PAGE, FmmBeginFileSystemOperation)
35 #pragma alloc_text(PAGE, FmmEndFileSystemOperation)
36 #endif
37 
38 _Requires_lock_held_(_Global_critical_region_)
39 _Requires_lock_held_(InstanceContext->MetadataResource)
40 _IRQL_requires_max_(PASSIVE_LEVEL)
41 NTSTATUS
42 FmmOpenMetadata (
43  _In_ PFMM_INSTANCE_CONTEXT InstanceContext,
44  _In_ BOOLEAN CreateIfNotPresent
45  )
46 /*++
47 
48 Routine Description:
49 
50  This routine opens or creates the Fmm metadata on the specified instance.
51 
52 Arguments:
53 
54  InstanceContext - Supplies the instance context for this instance.
55  CreateIfNotPresent - Supplies if the directory entry must be created if it is not present
56 
57 Return Value:
58 
59  Returns the status of this operation.
60 
61 Note:
62 
63  The caller must hold the instance context resource exclusive when this routine is called.
64 
65 --*/
66 {
67  OBJECT_ATTRIBUTES objectAttributes;
68  IO_STATUS_BLOCK ioStatus;
69  UNICODE_STRING fileName;
70  NTSTATUS status;
71  ULONG length;
72 
73  PAGED_CODE();
74 
75  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
76  ("[Fmm]: Opening metadata file ... (Volume = %p, CreateIfNotPresent = %X)\n",
77  InstanceContext->Volume,
78  CreateIfNotPresent) );
79 
80  status = STATUS_SUCCESS;
81  fileName.Buffer = NULL;
82 
83  //
84  // Get the volume name and construct the full metadata filename.
85  //
86 
87 
89 
90 #pragma warning(push)
91 #pragma warning(disable:4127) // Conditional expression is constant
92  while (TRUE) {
93 
94 #pragma warning(pop)
95 
96  fileName.MaximumLength = (USHORT)length;
97 
98  status = FmmAllocateUnicodeString( &fileName );
99 
100  if (!NT_SUCCESS( status )) {
101 
102  goto FmmOpenMetadataCleanup;
103  }
104 
105  status = FltGetVolumeName( InstanceContext->Volume, &fileName, &length );
106 
107  if (NT_SUCCESS( status )) {
108 
109  status = RtlAppendUnicodeToString( &fileName, FMM_METADATA_FILE_NAME );
110 
111  if (NT_SUCCESS( status )) {
112 
113  break;
114  }
115  } else {
116 
117  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
118  ("[Fmm]: Failed to get volume name (Volume = %p, Status = 0x%x)\n",
119  InstanceContext->Volume,
120  status) );
121  }
122 
123 
124  if (status != STATUS_BUFFER_TOO_SMALL) {
125 
126  goto FmmOpenMetadataCleanup;;
127  }
128 
129  //
130  // Free the filename buffer since a bigger one will be allocated
131  // above
132  //
133 
134  FmmFreeUnicodeString( &fileName );
135 
137  }
138 
139 
140  //
141  // Initialize the object attributes and open the file.
142  //
143 
144  InitializeObjectAttributes( &objectAttributes,
145  &fileName,
146  OBJ_KERNEL_HANDLE,
147  NULL,
148  NULL );
149 
150 
151 
152 
153 RetryFltCreateFile:
154 
155 
156  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
157  ("[Fmm]: Calling FltCreateFile for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
158  &fileName,
159  InstanceContext->Volume,
160  status) );
161 
162 
163  //
164  // Mark the beginning of a file system operation
165  //
166 
167  FmmBeginFileSystemOperation( InstanceContext );
168 
169  status = FltCreateFile( Globals.Filter,
170  InstanceContext->Instance,
171  &InstanceContext->MetadataHandle,
172  FILE_ALL_ACCESS,
173  &objectAttributes,
174  &ioStatus,
175  (PLARGE_INTEGER) NULL,
176  FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
177  FILE_SHARE_READ,
178  (CreateIfNotPresent ? FILE_OPEN_IF : FILE_OPEN),
179  0L,
180  NULL,
181  0L,
182  0 );
183 
184  //
185  // Mark the end of a file system operation
186  //
187 
188  FmmEndFileSystemOperation( InstanceContext );
189 
190 
191  if (!NT_SUCCESS( status )) {
192 
193  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
194  ("[Fmm]: FltCreateFile failure for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
195  &fileName,
196  InstanceContext->Volume,
197  status) );
198 
199  if (CreateIfNotPresent && (status == STATUS_OBJECT_PATH_NOT_FOUND)) {
200 
201  //
202  // We need to create the metadata file and the creation failed
203  // because the SystemVolumeInformation folder does not exist.
204  // So, create the folder and try again.
205  //
206 
207  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
208  ("[Fmm]: Creating SystemVolumeInformation folder for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
209  &fileName,
210  InstanceContext->Volume,
211  status) );
212 
213 
214  //
215  // Mark the beginning of a file system operation
216  //
217 
218  FmmBeginFileSystemOperation( InstanceContext );
219 
220  status = FltCreateSystemVolumeInformationFolder( InstanceContext->Instance );
221 
222  //
223  // Mark the end of a file system operation
224  //
225 
226  FmmEndFileSystemOperation( InstanceContext );
227 
228 
229 
230  if (NT_SUCCESS( status )) {
231 
232  //
233  // We have sucessfully created the SystemVolumeInformation folder
234  // Try to create the metadata file again
235  //
236 
237  goto RetryFltCreateFile;
238  } else {
239 
240  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
241  ("[Fmm]: FltCreateSystemVolumeInformationFolder failure for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
242  &fileName,
243  InstanceContext->Volume,
244  status) );
245  }
246  }
247 
248  goto FmmOpenMetadataCleanup;
249  }
250 
251  //
252  // Retrieve the FileObject from the handle created
253  //
254 
255  status = ObReferenceObjectByHandle( InstanceContext->MetadataHandle,
256  STANDARD_RIGHTS_REQUIRED,
257  *IoFileObjectType,
258  KernelMode,
259  &InstanceContext->MetadataFileObject,
260  NULL );
261  if (!NT_SUCCESS( status )) {
262 
263  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
264  ("[Fmm]: Failure to get file object from handle for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
265  &fileName,
266  InstanceContext->Volume,
267  status) );
268 
269  goto FmmOpenMetadataCleanup;
270  }
271 
272  if (ioStatus.Information == FILE_CREATED) {
273 
274  //
275  // New metadata was created
276  //
277 
278  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
279  ("[Fmm]: Created new metadata file %wZ (Volume = %p, Status = 0x%x)\n",
280  &fileName,
281  InstanceContext->Volume,
282  status) );
283 
284  //
285  // The filter may want to do some initialization on the newly created
286  // metadata file here like adding a header to the file
287  //
288 
289  }
290  else {
291 
292  //
293  // Existing metadata was opened
294  //
295 
296  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
297  ("[Fmm]: Opened existing metadata file %wZ (Volume = %p, Status = 0x%x)\n",
298  &fileName,
299  InstanceContext->Volume,
300  status) );
301 
302  //
303  // The filter may want to do some sanity checks on the metadata file here
304  // like validating the header of the file
305  //
306 
307  }
308 
309  //
310  // Here the filter may read the metadata contents and initialize
311  // its in memory data structures with the data from the metadata
312  // file
313  //
314 
315 
316 FmmOpenMetadataCleanup:
317 
318  if (!NT_SUCCESS( status )) {
319 
320  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
321  ("[Fmm]: Failed to open metadata (Volume = %p, Status = 0x%x)\n",
322  InstanceContext->Volume,
323  status) );
324 
325  //
326  // CLose the handle and dereference the file object
327  //
328 
329  if (InstanceContext->MetadataHandle) {
330 
331 
332  //
333  // Mark the beginning of a file system operation
334  //
335 
336  FmmBeginFileSystemOperation( InstanceContext );
337 
338  FltClose( InstanceContext->MetadataHandle );
339 
340  //
341  // Mark the end of a file system operation
342  //
343 
344  FmmEndFileSystemOperation( InstanceContext );
345 
346  InstanceContext->MetadataHandle = NULL;
347 
348  if (InstanceContext->MetadataFileObject) {
349 
350  ObDereferenceObject( InstanceContext->MetadataFileObject );
351  InstanceContext->MetadataFileObject = NULL;
352  }
353  }
354  } else {
355 
356  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
357  ("[Fmm]: Metadata successfully opened (Volume = %p)\n",
358  InstanceContext->Volume) );
359 
360  //
361  // Set flags to indicate successful open of filter metadata
362  //
363 
364  SetFlag( InstanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED );
365 
366  }
367 
368  if (fileName.Buffer != NULL) {
369 
370  FmmFreeUnicodeString( &fileName );
371  }
372 
373  return status;
374 }
375 
376 
377 _Requires_lock_held_(_Global_critical_region_)
378 _Requires_lock_held_(InstanceContext->MetadataResource)
379 _IRQL_requires_max_(PASSIVE_LEVEL)
380 VOID
381 FmmCloseMetadata (
382  _In_ PFMM_INSTANCE_CONTEXT InstanceContext
383  )
384 /*++
385 
386 Routine Description:
387 
388  This routine closes the filters handle to the metadata file.
389 
390 Arguments:
391 
392  InstanceContext - Instance context for this instance.
393 
394 Return Value:
395 
396  Void.
397 
398 Note:
399 
400  The caller must hold the instance context resource when this routine is called.
401 
402 
403 --*/
404 {
405  PAGED_CODE();
406 
407  FLT_ASSERT( InstanceContext->MetadataHandle );
408  FLT_ASSERT( InstanceContext->MetadataFileObject );
409 
410  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
411  ("[Fmm]: Closing metadata file ... (Volume = %p)\n",
412  InstanceContext->Volume ) );
413 
414  //
415  // Dereference the file object and close the file handle.
416  //
417 
418  ObDereferenceObject( InstanceContext->MetadataFileObject );
419 
420  InstanceContext->MetadataFileObject = NULL;
421 
422 
423  //
424  // Mark the beginning of a file system operation
425  //
426 
427  FmmBeginFileSystemOperation( InstanceContext );
428 
429  FltClose( InstanceContext->MetadataHandle );
430 
431  //
432  // Mark the end of a file system operation
433  //
434 
435  FmmEndFileSystemOperation( InstanceContext );
436 
437 
438  InstanceContext->MetadataHandle = NULL;
439 
440  //
441  // Reset flag to indicate filter metadata is closed
442  //
443 
444  ClearFlag( InstanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED );
445 
446 }
447 
448 NTSTATUS
450  _Inout_ PFLT_CALLBACK_DATA Cbd
451  )
452 /*++
453 
454 Routine Description:
455 
456  This routine releases all references to the metadata file on the specified instance.
457 
458 Arguments:
459 
460  Cbd - Supplies a pointer to the callbackData which
461  declares the requested operation.
462 
463 Return Value:
464 
465  Status
466 
467 Note:
468 
469  This routine takes care of the synchronization needed to access the metadata
470  file object and handle
471 
472  This routine will also set the MetadataOpenTriggerFileObject in the instance context
473  to the file object of the volume that triggered the release of the metadata file
474  references.
475 
476 --*/
477 {
478  NTSTATUS status = STATUS_SUCCESS;
479  PFMM_INSTANCE_CONTEXT instanceContext = NULL;
480 
481  PAGED_CODE();
482 
483  //
484  // Get the instance context
485  //
486 
487  status = FltGetInstanceContext( Cbd->Iopb->TargetInstance,
488  &instanceContext );
489  if (!NT_SUCCESS( status )) {
490 
491  DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
492  ("[Fmm]: FmmReleaseMetadataFileReferences -> Failed to get instance context.\n") );
493 
494  goto FmmReleaseMetadataFileReferencesCleanup;
495  }
496 
497  //
498  // Acquire exclusive access to the instance context
499  //
500 
501  FmmAcquireResourceExclusive( &instanceContext->MetadataResource );
502 
503  if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION)) {
504 
505  //
506  // If this instance context is in a transition state, it implies that
507  // the instance context lock has been released while sending an operation
508  // down to the file system. The reason for doing so is to prevent a potential
509  // deadlock if an underlying filter sends an IO to the top of the filter
510  // stack while we are holding the resource
511  //
512  // We have managed to acquire this resource in this state of transition.
513  // It would be incorrect to use or modify the instance context in any way
514  // in this situation. So we simply let go.
515  //
516 
517  status = STATUS_FILE_LOCK_CONFLICT;
518 
519  DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
520  ("[Fmm]: FmmReleaseMetadataFileReferences -> Failed to get exclusive access to instance context since it is in a state of transition.\n") );
521  } else {
522 
523  //
524  // Close the metadata file if it is open
525  //
526 
527  if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) {
528 
529  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
530  ("[Fmm]: FmmReleaseMetadataFileReferences -> Releasing references to metadata handle and file object (InstanceContext = %p VolumeFileObject = %p)\n",
531  instanceContext,
532  Cbd->Iopb->TargetFileObject) );
533 
534  //
535  // Close the metadata file object
536  //
537 
538  FmmCloseMetadata( instanceContext );
539 
540  //
541  // Save the volume file object for which we are releasing our references
542  //
543 
544  instanceContext->MetadataOpenTriggerFileObject = Cbd->Iopb->TargetFileObject;
545  } else {
546 
547  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
548  ("[Fmm]: FmmReleaseMetadataFileReferences -> Exit without attempting to release references to metadata handle and file object (InstanceContext = %p, VolumeFileObject = %p, MetadataOpenTriggerFileObject = %p, MetadataAlreadyOpen = 0x%x)\n",
549  instanceContext,
550  Cbd->Iopb->TargetFileObject,
551  instanceContext->MetadataOpenTriggerFileObject,
552  FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) );
553  }
554  }
555 
556  //
557  // Relinquish exclusive access to the instance context
558  //
559 
560  FmmReleaseResource( &instanceContext->MetadataResource );
561 
562 
563 FmmReleaseMetadataFileReferencesCleanup:
564 
565  //
566  // Release the references we have acquired
567  //
568 
569  if (instanceContext != NULL) {
570 
571  FltReleaseContext( instanceContext );
572  }
573 
574 
575  return status;
576 }
577 
578 
579 NTSTATUS
581  _Inout_ PFLT_CALLBACK_DATA Cbd
582  )
583 /*++
584 
585 Routine Description:
586 
587  This routine re-acquires references to the metadata file on the specified instance.
588 
589 Arguments:
590 
591  Cbd - Supplies a pointer to the callbackData which
592  declares the requested operation.
593 
594 Return Value:
595 
596  Status
597 
598 Note:
599 
600  This routine takes care of the synchronization needed to access the metadata
601  file object and handle
602 
603 
604  This routine will also NULL the MetadataOpenTriggerFileObject in the instance context
605  if it was successfully able to open the metadata file references.
606 
607 
608 --*/
609 {
610 
611  NTSTATUS status = STATUS_SUCCESS;
612  PFMM_INSTANCE_CONTEXT instanceContext = NULL;
613 
614  PAGED_CODE();
615 
616  //
617  // Get the instance context
618  //
619 
620  status = FltGetInstanceContext( Cbd->Iopb->TargetInstance,
621  &instanceContext );
622  if (!NT_SUCCESS( status )) {
623 
624  DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
625  ("[Fmm]: FmmReacquireMetadataFileReferences -> Failed to get instance context.\n") );
626 
627  goto FmmReacquireMetadataFileReferencesCleanup;
628  }
629 
630  //
631  // Acquire exclusive access to the instance context
632  //
633 
634  FmmAcquireResourceExclusive( &instanceContext->MetadataResource );
635 
636  if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION)) {
637 
638  //
639  // If this instance context is in a transition state, it implies that
640  // the instance context lock has been released while sending an operation
641  // down to the file system. The reason for doing so is to prevent a potential
642  // deadlock if an underlying filter sends an IO to the top of the filter
643  // stack while we are holding the resource
644  //
645  // We have managed to acquire this resource in this state of transition.
646  // It would be incorrect to use or modify the instance context in any way
647  // in this situation. So we simply let go.
648  //
649 
650  status = STATUS_FILE_LOCK_CONFLICT;
651 
652  DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
653  ("[Fmm]: FmmReacquireMetadataFileReferences -> Failed to get exclusive access to instance context since it is in a state of transition.\n") );
654  } else {
655 
656  //
657  // Re-open the metadata only if the trigger file object match the file object that
658  // caused this function to be called
659  //
660 
661  if (instanceContext->MetadataOpenTriggerFileObject == Cbd->Iopb->TargetFileObject) {
662 
663  //
664  // Open the filter metadata file (do not read the file since we already have
665  // stuff in memory and do not create if the file does not exist
666  //
667 
668  if (!FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) {
669 
670  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
671  ("[Fmm]: FmmReacquireMetadataFileReferences -> Re-acquiring references to metadata handle and file object (InstanceContext = %p, VolumeFileObject = %p)\n",
672  instanceContext,
673  Cbd->Iopb->TargetFileObject) );
674 
675  status = FmmOpenMetadata( instanceContext,
676  FALSE );
677 
678  //
679  // Reset the trigger file object since the volume open failed.
680  //
681 
682  instanceContext->MetadataOpenTriggerFileObject = NULL;
683 
684  } else {
685 
686  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
687  ("[Fmm]: FmmReacquireMetadataFileReferences -> Exit without attempting to re-acquire references to metadata handle and file object (InstanceContext = %p, VolumeFileObject = %p, MetadataOpenTriggerFileObject = %p, MetadataAlreadyOpen = 0x%x)\n",
688  instanceContext,
689  Cbd->Iopb->TargetFileObject,
690  instanceContext->MetadataOpenTriggerFileObject,
691  FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) );
692  }
693  } else {
694 
695 
696  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
697  ("[Fmm]: FmmReacquireMetadataFileReferences -> Exit without attempting to re-acquire references to metadata handle and file object (InstanceContext = %p, VolumeFileObject = %p, MetadataOpenTriggerFileObject = %p, MetadataAlreadyOpen = 0x%x)\n",
698  instanceContext,
699  Cbd->Iopb->TargetFileObject,
700  instanceContext->MetadataOpenTriggerFileObject,
701  FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) );
702  }
703  }
704 
705  //
706  // Relinquish exclusive access to the instance context
707  //
708 
709  FmmReleaseResource( &instanceContext->MetadataResource );
710 
711 
712 FmmReacquireMetadataFileReferencesCleanup:
713 
714  //
715  // Release the references we have acquired
716  //
717 
718  if (instanceContext != NULL) {
719 
720  FltReleaseContext( instanceContext );
721  }
722 
723 
724  return status;;
725 
726 }
727 
728 
729 
730 NTSTATUS
732  _Inout_ PFLT_CALLBACK_DATA Cbd
733  )
734 /*++
735 
736 Routine Description:
737 
738  This routine sets the MetadataOpenTriggerFileObject in the instance context
739  to the file object of the volume that triggered the release of the metadata file
740  references.
741 
742 Arguments:
743 
744  Cbd - Supplies a pointer to the callbackData which
745  declares the requested operation.
746 
747 Return Value:
748 
749  Status
750 
751 Note:
752 
753  This routine takes care of the synchronization needed to access the metadata
754  file object and handle
755 
756 
757 --*/
758 {
759  NTSTATUS status = STATUS_SUCCESS;
760  PFMM_INSTANCE_CONTEXT instanceContext = NULL;
761 
762  PAGED_CODE();
763 
764  //
765  // Get the instance context
766  //
767 
768  status = FltGetInstanceContext( Cbd->Iopb->TargetInstance,
769  &instanceContext );
770  if (!NT_SUCCESS( status )) {
771 
772  DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
773  ("[Fmm]: FmmSetMetadataOpenTriggerFileObject -> Failed to get instance context.\n") );
774 
775  goto FmmSetMetadataOpenTriggerFileObjectCleanup;
776  }
777 
778  //
779  // Acquire exclusive access to the instance context
780  //
781 
782  FmmAcquireResourceExclusive( &instanceContext->MetadataResource );
783 
784  if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION)) {
785 
786  //
787  // If this instance context is in a transition state, it implies that
788  // the instance context lock has been released while sending an operation
789  // down to the file system. The reason for doing so is to prevent a potential
790  // deadlock if an underlying filter sends an IO to the top of the filter
791  // stack while we are holding the resource
792  //
793  // We have managed to acquire this resource in this state of transition.
794  // It would be incorrect to use or modify the instance context in any way
795  // in this situation. So we simply let go.
796  //
797 
798  status = STATUS_FILE_LOCK_CONFLICT;
799 
800  DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
801  ("[Fmm]: FmmSetMetadataOpenTriggerFileObject -> Failed to get exclusive access to instance context since it is in a state of transition.\n") );
802  } else {
803 
804  DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
805  ("[Fmm]: FmmSetMetadataOpenTriggerFileObject -> Setting MetadataOpenTriggerFileObject to %p (OldValue = %p).\n",
806  Cbd->Iopb->TargetFileObject,
807  instanceContext->MetadataOpenTriggerFileObject) );
808 
809 
810  //
811  // Save the volume file object as the trigger file object
812  //
813 
814  FLT_ASSERT((instanceContext->MetadataOpenTriggerFileObject == NULL) ||
815  (instanceContext->MetadataOpenTriggerFileObject == Cbd->Iopb->TargetFileObject));
816 
817  instanceContext->MetadataOpenTriggerFileObject = Cbd->Iopb->TargetFileObject;
818  }
819 
820  //
821  // Relinquish exclusive access to the instance context
822  //
823 
824  FmmReleaseResource( &instanceContext->MetadataResource );
825 
826 
827 FmmSetMetadataOpenTriggerFileObjectCleanup:
828 
829  //
830  // Release the references we have acquired
831  //
832 
833  if (instanceContext != NULL) {
834 
835  FltReleaseContext( instanceContext );
836  }
837 
838 
839  return status;;
840 }
841 
842 _Releases_lock_(_Global_critical_region_)
843 _Requires_lock_held_(InstanceContext->MetadataResource)
844 _Releases_lock_(InstanceContext->MetadataResource)
845 _IRQL_requires_max_(APC_LEVEL)
846 FORCEINLINE
847 VOID
848 FmmBeginFileSystemOperation (
849  IN PFMM_INSTANCE_CONTEXT InstanceContext
850  )
851 /*++
852 
853 Routine Description:
854 
855  This routine must be called before the filter performs a file system operation
856  if it is holding an exclusive lock to the instance context resource at the
857  time it needs to perform the file system operation
858 
859 Arguments:
860 
861  InstanceContext - Supplies the instance context for this instance.
862 
863 Return Value:
864 
865  Returns the status of this operation.
866 
867 Note:
868 
869  The caller must hold the instance context resource exclusive when this routine is called.
870 
871 --*/
872 {
873  PAGED_CODE();
874 
875  //
876  // Release the instance context lock before sending an operation down to the
877  // file system. The reason for doing so is to prevent a potential deadlock if
878  // an underlying filter sends an IO to the top of the filter stack while we
879  // are holding the resource
880  //
881  // Before we release the lock we mark the instance context to indicate it is
882  // in a transition state. Any other thread that finds the instance context in a
883  // transition state will not use or modify the instance context
884  //
885  // This thread can however continue to use/modify the instance context since it
886  // is guaranteed exclusive access. Other threads that see the instance context
887  // in a transition state will not use or modify the context
888  //
889 
890  FLT_ASSERT( !FlagOn( InstanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION ) );
891 
892  SetFlag( InstanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION );
893 
894  //
895  // Relinquish exclusive access to the instance context
896  //
897 
898  FmmReleaseResource( &InstanceContext->MetadataResource );
899 
900 }
901 
902 
903 _Acquires_lock_(_Global_critical_region_)
904 _Requires_lock_not_held_(InstanceContext->MetadataResource)
905 _Acquires_exclusive_lock_(InstanceContext->MetadataResource)
906 _IRQL_requires_max_(APC_LEVEL)
907 FORCEINLINE
908 VOID
909 FmmEndFileSystemOperation (
910  IN PFMM_INSTANCE_CONTEXT InstanceContext
911  )
912 /*++
913 
914 Routine Description:
915 
916  This routine must be called after the filter performs a file system operation
917  if it was holding an exclusive lock to the instance context resource at the
918  time it needed to perform the file system operation
919 
920 Arguments:
921 
922  InstanceContext - Supplies the instance context for this instance.
923 
924 Return Value:
925 
926  Returns the status of this operation.
927 
928 Note:
929 
930  The caller will hold the instance context resource exclusive when this routine returns.
931 
932 --*/
933 {
934  PAGED_CODE();
935 
936  //
937  // Acquire exclusive access to the instance context
938  //
939 
940  FmmAcquireResourceExclusive( &InstanceContext->MetadataResource );
941 
942 
943  //
944  // Sanity - nothing should have changed this flag while we dropped the resource
945  // because all other threads will not use or modify the instance context while
946  // this flag is set
947  //
948 
949  FLT_ASSERT( FlagOn( InstanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION ) );
950 
951 
952  //
953  // Reset the flag to indicate that the instance context is no longer in
954  // a transition state
955  //
956 
957  ClearFlag( InstanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION );
958 
959 }
960 
961 
962 
963 #if VERIFY_METADATA_OPENED
964 
965 NTSTATUS
966 FmmIsMetadataOpen (
967  _Inout_ PFLT_CALLBACK_DATA Cbd,
968  _Out_ BOOLEAN* MetadataOpen
969  )
970 /*++
971 
972 Routine Description:
973 
974  This routine returns if the metadata file is open on the specified instance.
975 
976 Arguments:
977 
978  Cbd - Supplies a pointer to the callbackData which
979  declares the requested operation.
980  MetadataOpen - Returns if the metadata file is open
981 
982 Return Value:
983 
984  Status
985 
986 Note:
987 
988  This routine takes care of the synchronization needed to access the metadata
989  file object and handle
990 
991 
992 --*/
993 {
994  NTSTATUS status = STATUS_SUCCESS;
995  PFMM_INSTANCE_CONTEXT instanceContext = NULL;
996 
997 
998  //
999  // Get the instance context
1000  //
1001 
1002  status = FltGetInstanceContext( Cbd->Iopb->TargetInstance,
1003  &instanceContext );
1004  if (!NT_SUCCESS( status )) {
1005 
1006  DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
1007  ("[Fmm]: FmmIsMetadataOpen -> Failed to get instance context.\n") );
1008 
1009  goto FmmIsMetadataOpenCleanup;
1010  }
1011 
1012  //
1013  // Acquire exclusive access to the instance context
1014  //
1015 
1016  FmmAcquireResourceShared( &instanceContext->MetadataResource );
1017 
1018  if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION)) {
1019 
1020  //
1021  // If this instance context is in a transition state, it implies that
1022  // the instance context lock has been released while sending an operation
1023  // down to the file system. The reason for doing so is to prevent a potential
1024  // deadlock if an underlying filter sends an IO to the top of the filter
1025  // stack while we are holding the resource
1026  //
1027  // We have managed to acquire this resource in this state of transition.
1028  // It would be incorrect to use or modify the instance context in any way
1029  // in this situation. So we simply let go.
1030  //
1031 
1032  status = STATUS_FILE_LOCK_CONFLICT;
1033 
1034  DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
1035  ("[Fmm]: FmmIsMetadataOpen -> Failed to get exclusive access to instance context since it is in a state of transition.\n") );
1036  } else {
1037 
1038  //
1039  // Return if the metadata is opened
1040  //
1041 
1042  *MetadataOpen = BooleanFlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED );
1043 
1044  //
1045  // Sanity - verify that this flag is reflecting the correct state of the metadata file
1046  //
1047 
1048  FLT_ASSERT ( (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED ) &&
1049  (instanceContext->MetadataFileObject != NULL) &&
1050  (instanceContext->MetadataHandle != NULL)) ||
1051  (!FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED ) &&
1052  (instanceContext->MetadataFileObject == NULL) &&
1053  (instanceContext->MetadataHandle == NULL)) );
1054 
1055  }
1056 
1057  //
1058  // Relinquish exclusive access to the instance context
1059  //
1060 
1061  FmmReleaseResource( &instanceContext->MetadataResource );
1062 
1063 
1064 FmmIsMetadataOpenCleanup:
1065 
1066  //
1067  // Release the references we have acquired
1068  //
1069 
1070  if (instanceContext != NULL) {
1071 
1072  FltReleaseContext( instanceContext );
1073  }
1074 
1075 
1076  return status;
1077 }
1078 
1079 
1080 #endif
1081 
1082 
NTSTATUS FmmAllocateUnicodeString(_Inout_ PUNICODE_STRING String)
PFILE_OBJECT MetadataOpenTriggerFileObject
#define FMM_METADATA_FILE_NAME_LENGTH
#define DebugTrace(Level, Data)
Definition: cancelSafe.c:36
NTSTATUS FmmSetMetadataOpenTriggerFileObject(_Inout_ PFLT_CALLBACK_DATA Cbd)
Definition: DataStore.c:731
#define INSTANCE_CONTEXT_F_TRANSITION
FLT_ASSERT(IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
return TRUE
AV_SCANNER_GLOBAL_DATA Globals
Definition: avscan.h:152
PFLT_FILTER Filter
Definition: avscan.h:86
#define INSTANCE_CONTEXT_F_METADATA_OPENED
#define FMM_DEFAULT_VOLUME_NAME_LENGTH
#define FlagOn(_F, _SF)
Definition: minispy.h:247
NTSTATUS FmmReacquireMetadataFileReferences(_Inout_ PFLT_CALLBACK_DATA Cbd)
Definition: DataStore.c:580
NcLoadRegistryStringRetry NULL
Definition: ncinit.c:53
PAGED_CODE()
_Acquires_lock_(_Global_critical_region_)
Definition: DataStore.c:903
VOID _IRQL_requires_max_(VOID_IRQL_requires_max_(APC_LEVEL) _IRQL_requires_min_() _IRQL_raises_(PASSIVE_LEVEL) _Requires_lock_held_((CONTAINING_RECORD(DataQueue APC_LEVEL)
Definition: cancelSafe.c:194
_Requires_lock_held_(_Global_critical_region_)
Definition: DataStore.c:38
VOID FmmFreeUnicodeString(_Inout_ PUNICODE_STRING String)
#define FMM_METADATA_FILE_NAME
NTSTATUS FmmReleaseMetadataFileReferences(_Inout_ PFLT_CALLBACK_DATA Cbd)
Definition: DataStore.c:449
_Releases_lock_(_Global_critical_region_)
Definition: DataStore.c:842

Social Network


Services Overview

Architect, implement and test file system filter drivers for a wide range of functionality. We can offer several levels of assistance to meet your specific.

Contact Us

You are welcome to contact us for salse or partnership.

Sales: sales@easefilter.com
Support: support@easefilter.com
Info: info@easefilter.com