2 * PROJECT: Filesystem Filter Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/fs_minifilter/fltmgr/Registration.c
5 * PURPOSE: Handles registration of mini filters
6 * PROGRAMMERS: Ged Murphy (gedmurphy@reactos.org)
9 /* INCLUDES ******************************************************************/
17 /* DATA *********************************************************************/
21 FltpStartingToDrainObject(
22 _Inout_ PFLT_OBJECT Object
26 /* EXPORTED FUNCTIONS ******************************************************/
30 FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject
,
31 _In_
const FLT_REGISTRATION
*Registration
,
32 _Out_ PFLT_FILTER
*RetFilter
)
34 PFLT_OPERATION_REGISTRATION Callbacks
;
36 ULONG CallbackBufferSize
;
37 ULONG FilterBufferSize
;
42 Status
= 0; //remove me
44 /* Make sure we're targeting the correct major revision */
45 if ((Registration
->Version
& 0xFF00) != FLT_MAJOR_VERSION
)
47 return STATUS_INVALID_PARAMETER
;
50 /* Make sure our namespace callbacks are valid */
51 if ((!Registration
->GenerateFileNameCallback
&& Registration
->NormalizeNameComponentCallback
) ||
52 (!Registration
->NormalizeNameComponentCallback
&& Registration
->NormalizeContextCleanupCallback
))
54 return STATUS_INVALID_PARAMETER
;
57 /* Count the number of operations that were requested */
58 Callbacks
= (PFLT_OPERATION_REGISTRATION
)Registration
->OperationRegistration
;
63 /* Bail when we find the last one */
64 if (Callbacks
->MajorFunction
== IRP_MJ_OPERATION_END
)
67 /* Move to the next item */
71 /* Calculate the buffer sizes */
72 CallbackBufferSize
= Count
* sizeof(FLT_OPERATION_REGISTRATION
);
73 FilterBufferSize
= sizeof(FLT_FILTER
) + CallbackBufferSize
+
74 DriverObject
->DriverExtension
->ServiceKeyName
.Length
;
76 /* Allocate a buffer to hold our filter data */
77 Filter
= ExAllocatePoolWithTag(NonPagedPool
,
80 if (Filter
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
81 RtlZeroMemory(Filter
, FilterBufferSize
);
83 /* Find the end of the fixed struct */
84 Ptr
= (PCHAR
)(Filter
+ 1);
86 /* Store a copy of the driver object of this filter */
87 Filter
->DriverObject
= DriverObject
;
89 /* Initialize the base object data */
90 Filter
->Base
.Flags
= FLT_OBFL_TYPE_FILTER
;
91 Filter
->Base
.PointerCount
= 1;
92 FltpExInitializeRundownProtection(&Filter
->Base
.RundownRef
);
93 FltObjectReference(&Filter
->Base
);
95 /* Set the callback addresses */
96 Filter
->FilterUnload
= Registration
->FilterUnloadCallback
;
97 Filter
->InstanceSetup
= Registration
->InstanceSetupCallback
;
98 Filter
->InstanceQueryTeardown
= Registration
->InstanceQueryTeardownCallback
;
99 Filter
->InstanceTeardownStart
= Registration
->InstanceTeardownStartCallback
;
100 Filter
->InstanceTeardownComplete
= Registration
->InstanceTeardownCompleteCallback
;
101 Filter
->GenerateFileName
= Registration
->GenerateFileNameCallback
;
102 Filter
->NormalizeNameComponent
= Registration
->NormalizeNameComponentCallback
;
103 Filter
->NormalizeContextCleanup
= Registration
->NormalizeContextCleanupCallback
;
105 /* Initialize the instance list */
106 ExInitializeResourceLite(&Filter
->InstanceList
.rLock
);
107 InitializeListHead(&Filter
->InstanceList
.rList
);
108 Filter
->InstanceList
.rCount
= 0;
110 ExInitializeFastMutex(&Filter
->ActiveOpens
.mLock
);
111 InitializeListHead(&Filter
->ActiveOpens
.mList
);
112 Filter
->ActiveOpens
.mCount
= 0;
114 /* Initialize the usermode port list */
115 ExInitializeFastMutex(&Filter
->PortList
.mLock
);
116 InitializeListHead(&Filter
->PortList
.mList
);
117 Filter
->PortList
.mCount
= 0;
119 /* Check if the caller requested any context data */
120 if (Registration
->ContextRegistration
)
122 // register the context information
125 if (Registration
->OperationRegistration
)
127 /* The callback data comes after the fixed struct */
128 Filter
->Operations
= (PFLT_OPERATION_REGISTRATION
)Ptr
;
129 Ptr
+= (Count
* sizeof(FLT_OPERATION_REGISTRATION
));
131 /* Tag the operation data onto the end of the filter data */
132 RtlCopyMemory(Filter
->Operations
, Registration
->OperationRegistration
, CallbackBufferSize
);
134 /* walk through the requested callbacks */
135 for (Callbacks
= Filter
->Operations
;
136 Callbacks
->MajorFunction
!= IRP_MJ_OPERATION_END
;
139 // http://fsfilters.blogspot.co.uk/2011/03/how-file-system-filters-attach-to_17.html
140 /* Check if this is an attach to a volume */
141 if (Callbacks
->MajorFunction
== IRP_MJ_VOLUME_MOUNT
)
143 Filter
->PreVolumeMount
= Callbacks
->PreOperation
;
144 Filter
->PostVolumeMount
= Callbacks
->PostOperation
;
146 else if (Callbacks
->MajorFunction
== IRP_MJ_SHUTDOWN
)
148 Callbacks
->PostOperation
= NULL
;
153 /* Add the filter name buffer onto the end of the data and fill in the string */
154 Filter
->Name
.Length
= 0;
155 Filter
->Name
.MaximumLength
= DriverObject
->DriverExtension
->ServiceKeyName
.Length
;
156 Filter
->Name
.Buffer
= (PWCH
)Ptr
;
157 RtlCopyUnicodeString(&Filter
->Name
, &DriverObject
->DriverExtension
->ServiceKeyName
);
160 // - Get the altitude string
161 // - Slot the filter into the correct altitude location
166 if (!NT_SUCCESS(Status
))
168 // Add cleanup for context resources
170 ExDeleteResourceLite(&Filter
->InstanceList
.rLock
);
171 ExFreePoolWithTag(Filter
, FM_TAG_FILTER
);
179 FltUnregisterFilter(_In_ PFLT_FILTER Filter
)
181 PFLT_INSTANCE Instance
;
182 PLIST_ENTRY CurrentEntry
;
185 /* Set the draining flag */
186 Status
= FltpStartingToDrainObject(&Filter
->Base
);
187 if (!NT_SUCCESS(Status
))
189 /* Someone already unregistered us, just remove our ref and bail */
190 FltObjectDereference(&Filter
->Base
);
194 /* Lock the instance list */
195 KeEnterCriticalRegion();
196 ExAcquireResourceSharedLite(&Filter
->InstanceList
.rLock
, TRUE
);
198 /* Set the first entry in the list */
199 CurrentEntry
= Filter
->InstanceList
.rList
.Flink
;
201 /* Free all instances referenced by the filter */
202 while (CurrentEntry
!= &Filter
->InstanceList
.rList
)
204 /* Get the record pointer */
205 Instance
= CONTAINING_RECORD(CurrentEntry
, FLT_INSTANCE
, FilterLink
);
209 /* Reset the pointer and move to next entry */
211 CurrentEntry
= CurrentEntry
->Flink
;
214 /* We're done with instances now */
215 ExReleaseResourceLite(&Filter
->InstanceList
.rLock
);
216 KeLeaveCriticalRegion();
218 /* Remove the reference from the base object */
219 FltObjectDereference(&Filter
->Base
);
221 /* Wait until we're sure nothing is using the filter */
222 FltpObjectRundownWait(&Filter
->Base
.RundownRef
);
224 /* Delete the instance list lock */
225 ExDeleteResourceLite(&Filter
->InstanceList
.rLock
);
227 /* We're finished cleaning up now */
228 FltpExRundownCompleted(&Filter
->Base
.RundownRef
);
230 /* Hand the memory back */
231 ExFreePoolWithTag(Filter
, FM_TAG_FILTER
);
235 /* INTERNAL FUNCTIONS ******************************************************/
238 FltpStartingToDrainObject(_Inout_ PFLT_OBJECT Object
)
241 * Set the draining flag for the filter. This let's us force
242 * a post op callback for minifilters currently awaiting one.
244 if (InterlockedOr((PLONG
)&Object
->Flags
, FLT_OBFL_DRAINING
) & 1)
246 /* We've been called once, we're already being deleted */
247 return STATUS_FLT_DELETING_OBJECT
;
250 return STATUS_SUCCESS
;