xref: /reactos/drivers/filters/fltmgr/Filter.c (revision fa46f362)
1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT:         Filesystem Filter Manager
3c2c66affSColin Finck * LICENSE:         GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE:            drivers/filters/fltmgr/Filter.c
5c2c66affSColin Finck * PURPOSE:         Handles registration of mini filters
6c2c66affSColin Finck * PROGRAMMERS:     Ged Murphy (gedmurphy@reactos.org)
7c2c66affSColin Finck */
8c2c66affSColin Finck 
9c2c66affSColin Finck /* INCLUDES ******************************************************************/
10c2c66affSColin Finck 
11c2c66affSColin Finck #include "fltmgr.h"
12c2c66affSColin Finck #include "fltmgrint.h"
13dfb77638SGed Murphy #include "Registry.h"
14c2c66affSColin Finck 
15c2c66affSColin Finck #define NDEBUG
16c2c66affSColin Finck #include <debug.h>
17c2c66affSColin Finck 
18c2c66affSColin Finck 
19c2c66affSColin Finck /* DATA *********************************************************************/
20c2c66affSColin Finck 
21c2c66affSColin Finck #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
22c2c66affSColin Finck #define MAX_KEY_LENGTH  0x200
23c2c66affSColin Finck 
24*fa46f362SGed Murphy LIST_ENTRY FilterList;
25*fa46f362SGed Murphy ERESOURCE FilterListLock;
26*fa46f362SGed Murphy 
27c2c66affSColin Finck NTSTATUS
28c2c66affSColin Finck FltpStartingToDrainObject(
29c2c66affSColin Finck     _Inout_ PFLT_OBJECT Object
30c2c66affSColin Finck );
31c2c66affSColin Finck 
32dfb77638SGed Murphy VOID
33dfb77638SGed Murphy FltpMiniFilterDriverUnload(
34dfb77638SGed Murphy );
35dfb77638SGed Murphy 
36*fa46f362SGed Murphy NTSTATUS
37*fa46f362SGed Murphy FltpAttachFrame(
38*fa46f362SGed Murphy     _In_ PUNICODE_STRING Altitude,
39*fa46f362SGed Murphy     _Inout_ PFLTP_FRAME *Frame
40*fa46f362SGed Murphy );
41*fa46f362SGed Murphy 
42dfb77638SGed Murphy static
43dfb77638SGed Murphy NTSTATUS
44dfb77638SGed Murphy GetFilterAltitude(
45dfb77638SGed Murphy     _In_ PFLT_FILTER Filter,
46dfb77638SGed Murphy     _Inout_ PUNICODE_STRING AltitudeString
47dfb77638SGed Murphy );
48dfb77638SGed Murphy 
49*fa46f362SGed Murphy static
50*fa46f362SGed Murphy NTSTATUS
51*fa46f362SGed Murphy GetFilterFrame(
52*fa46f362SGed Murphy     _In_ PFLT_FILTER Filter,
53*fa46f362SGed Murphy     _In_ PUNICODE_STRING Altitude,
54*fa46f362SGed Murphy     _Out_ PFLTP_FRAME *Frame
55*fa46f362SGed Murphy );
56*fa46f362SGed Murphy 
57c2c66affSColin Finck 
58c2c66affSColin Finck /* EXPORTED FUNCTIONS ******************************************************/
59c2c66affSColin Finck 
60c2c66affSColin Finck NTSTATUS
61c2c66affSColin Finck NTAPI
FltLoadFilter(_In_ PCUNICODE_STRING FilterName)62c2c66affSColin Finck FltLoadFilter(_In_ PCUNICODE_STRING FilterName)
63c2c66affSColin Finck {
64c2c66affSColin Finck     UNICODE_STRING DriverServiceName;
65c2c66affSColin Finck     UNICODE_STRING ServicesKey;
66c2c66affSColin Finck     CHAR Buffer[MAX_KEY_LENGTH];
67c2c66affSColin Finck 
68c2c66affSColin Finck     /* Setup the base services key */
69c2c66affSColin Finck     RtlInitUnicodeString(&ServicesKey, SERVICES_KEY);
70c2c66affSColin Finck 
71c2c66affSColin Finck     /* Initialize the string data */
72c2c66affSColin Finck     DriverServiceName.Length = 0;
73c2c66affSColin Finck     DriverServiceName.Buffer = (PWCH)Buffer;
74c2c66affSColin Finck     DriverServiceName.MaximumLength = MAX_KEY_LENGTH;
75c2c66affSColin Finck 
76c2c66affSColin Finck     /* Create the full service key for this filter */
77c2c66affSColin Finck     RtlCopyUnicodeString(&DriverServiceName, &ServicesKey);
78c2c66affSColin Finck     RtlAppendUnicodeStringToString(&DriverServiceName, FilterName);
79c2c66affSColin Finck 
80c2c66affSColin Finck     /* Ask the kernel to load it for us */
81c2c66affSColin Finck     return ZwLoadDriver(&DriverServiceName);
82c2c66affSColin Finck }
83c2c66affSColin Finck 
84c2c66affSColin Finck NTSTATUS
85c2c66affSColin Finck NTAPI
FltUnloadFilter(_In_ PCUNICODE_STRING FilterName)86c2c66affSColin Finck FltUnloadFilter(_In_ PCUNICODE_STRING FilterName)
87c2c66affSColin Finck {
88dfb77638SGed Murphy     //
89dfb77638SGed Murphy     //FIXME: This is a temp hack, it needs properly implementing
90dfb77638SGed Murphy     //
91dfb77638SGed Murphy 
92dfb77638SGed Murphy     UNICODE_STRING DriverServiceName;
93dfb77638SGed Murphy     UNICODE_STRING ServicesKey;
94dfb77638SGed Murphy     CHAR Buffer[MAX_KEY_LENGTH];
95dfb77638SGed Murphy 
96dfb77638SGed Murphy     /* Setup the base services key */
97dfb77638SGed Murphy     RtlInitUnicodeString(&ServicesKey, SERVICES_KEY);
98dfb77638SGed Murphy 
99dfb77638SGed Murphy     /* Initialize the string data */
100dfb77638SGed Murphy     DriverServiceName.Length = 0;
101dfb77638SGed Murphy     DriverServiceName.Buffer = (PWCH)Buffer;
102dfb77638SGed Murphy     DriverServiceName.MaximumLength = MAX_KEY_LENGTH;
103dfb77638SGed Murphy 
104dfb77638SGed Murphy     /* Create the full service key for this filter */
105dfb77638SGed Murphy     RtlCopyUnicodeString(&DriverServiceName, &ServicesKey);
106dfb77638SGed Murphy     RtlAppendUnicodeStringToString(&DriverServiceName, FilterName);
107dfb77638SGed Murphy     return ZwUnloadDriver(&DriverServiceName);
108c2c66affSColin Finck }
109c2c66affSColin Finck 
110c2c66affSColin Finck NTSTATUS
111c2c66affSColin Finck NTAPI
FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject,_In_ const FLT_REGISTRATION * Registration,_Out_ PFLT_FILTER * RetFilter)112c2c66affSColin Finck FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject,
113c2c66affSColin Finck                   _In_ const FLT_REGISTRATION *Registration,
114c2c66affSColin Finck                   _Out_ PFLT_FILTER *RetFilter)
115c2c66affSColin Finck {
116c2c66affSColin Finck     PFLT_OPERATION_REGISTRATION Callbacks;
117c2c66affSColin Finck     PFLT_FILTER Filter;
118*fa46f362SGed Murphy     PFLTP_FRAME Frame;
119c2c66affSColin Finck     ULONG CallbackBufferSize;
120c2c66affSColin Finck     ULONG FilterBufferSize;
121c2c66affSColin Finck     ULONG Count = 0;
122c2c66affSColin Finck     PCHAR Ptr;
123c2c66affSColin Finck     NTSTATUS Status;
124c2c66affSColin Finck 
125dfb77638SGed Murphy     *RetFilter = NULL;
126dfb77638SGed Murphy 
127c2c66affSColin Finck     /* Make sure we're targeting the correct major revision */
128c2c66affSColin Finck     if ((Registration->Version & 0xFF00) != FLT_MAJOR_VERSION)
129c2c66affSColin Finck     {
130c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
131c2c66affSColin Finck     }
132c2c66affSColin Finck 
133c2c66affSColin Finck     /* Make sure our namespace callbacks are valid */
134c2c66affSColin Finck     if ((!Registration->GenerateFileNameCallback && Registration->NormalizeNameComponentCallback) ||
135c2c66affSColin Finck         (!Registration->NormalizeNameComponentCallback && Registration->NormalizeContextCleanupCallback))
136c2c66affSColin Finck     {
137c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
138c2c66affSColin Finck     }
139c2c66affSColin Finck 
140c2c66affSColin Finck     /* Count the number of operations that were requested */
141c2c66affSColin Finck     Callbacks = (PFLT_OPERATION_REGISTRATION)Registration->OperationRegistration;
142c2c66affSColin Finck     while (Callbacks)
143c2c66affSColin Finck     {
144c2c66affSColin Finck         Count++;
145c2c66affSColin Finck 
146c2c66affSColin Finck         /* Bail when we find the last one */
147c2c66affSColin Finck         if (Callbacks->MajorFunction == IRP_MJ_OPERATION_END)
148c2c66affSColin Finck             break;
149c2c66affSColin Finck 
150c2c66affSColin Finck         /* Move to the next item */
151c2c66affSColin Finck         Callbacks++;
152c2c66affSColin Finck     }
153c2c66affSColin Finck 
154c2c66affSColin Finck     /* Calculate the buffer sizes */
155c2c66affSColin Finck     CallbackBufferSize = Count * sizeof(FLT_OPERATION_REGISTRATION);
156c2c66affSColin Finck     FilterBufferSize = sizeof(FLT_FILTER) +
157c2c66affSColin Finck                        CallbackBufferSize +
158c2c66affSColin Finck                        DriverObject->DriverExtension->ServiceKeyName.Length;
159c2c66affSColin Finck 
160c2c66affSColin Finck     /* Allocate a buffer to hold our filter data */
161c2c66affSColin Finck     Filter = ExAllocatePoolWithTag(NonPagedPool,
162c2c66affSColin Finck                                    FilterBufferSize,
163c2c66affSColin Finck                                    FM_TAG_FILTER);
164c2c66affSColin Finck     if (Filter == NULL) return STATUS_INSUFFICIENT_RESOURCES;
165c2c66affSColin Finck     RtlZeroMemory(Filter, FilterBufferSize);
166c2c66affSColin Finck 
167c2c66affSColin Finck     /* Find the end of the fixed struct */
168c2c66affSColin Finck     Ptr = (PCHAR)(Filter + 1);
169c2c66affSColin Finck 
170c2c66affSColin Finck     /* Store a copy of the driver object of this filter */
171c2c66affSColin Finck     Filter->DriverObject = DriverObject;
172c2c66affSColin Finck 
173c2c66affSColin Finck     /* Initialize the base object data */
174c2c66affSColin Finck     Filter->Base.Flags = FLT_OBFL_TYPE_FILTER;
175c2c66affSColin Finck     Filter->Base.PointerCount = 1;
176c2c66affSColin Finck     FltpExInitializeRundownProtection(&Filter->Base.RundownRef);
177c2c66affSColin Finck     FltObjectReference(&Filter->Base);
178c2c66affSColin Finck 
179c2c66affSColin Finck     /* Set the callback addresses */
180c2c66affSColin Finck     Filter->FilterUnload = Registration->FilterUnloadCallback;
181c2c66affSColin Finck     Filter->InstanceSetup = Registration->InstanceSetupCallback;
182c2c66affSColin Finck     Filter->InstanceQueryTeardown = Registration->InstanceQueryTeardownCallback;
183c2c66affSColin Finck     Filter->InstanceTeardownStart = Registration->InstanceTeardownStartCallback;
184c2c66affSColin Finck     Filter->InstanceTeardownComplete = Registration->InstanceTeardownCompleteCallback;
185c2c66affSColin Finck     Filter->GenerateFileName = Registration->GenerateFileNameCallback;
186c2c66affSColin Finck     Filter->NormalizeNameComponent = Registration->NormalizeNameComponentCallback;
187c2c66affSColin Finck     Filter->NormalizeContextCleanup = Registration->NormalizeContextCleanupCallback;
188c2c66affSColin Finck 
189c2c66affSColin Finck     /* Initialize the instance list */
190c2c66affSColin Finck     ExInitializeResourceLite(&Filter->InstanceList.rLock);
191c2c66affSColin Finck     InitializeListHead(&Filter->InstanceList.rList);
192c2c66affSColin Finck     Filter->InstanceList.rCount = 0;
193c2c66affSColin Finck 
194c2c66affSColin Finck     ExInitializeFastMutex(&Filter->ActiveOpens.mLock);
195c2c66affSColin Finck     InitializeListHead(&Filter->ActiveOpens.mList);
196c2c66affSColin Finck     Filter->ActiveOpens.mCount = 0;
197c2c66affSColin Finck 
198dfb77638SGed Murphy     ExInitializeFastMutex(&Filter->ConnectionList.mLock);
199dfb77638SGed Murphy     InitializeListHead(&Filter->ConnectionList.mList);
200dfb77638SGed Murphy     Filter->ConnectionList.mCount = 0;
201dfb77638SGed Murphy 
202c2c66affSColin Finck     /* Initialize the usermode port list */
203c2c66affSColin Finck     ExInitializeFastMutex(&Filter->PortList.mLock);
204c2c66affSColin Finck     InitializeListHead(&Filter->PortList.mList);
205c2c66affSColin Finck     Filter->PortList.mCount = 0;
206c2c66affSColin Finck 
207c2c66affSColin Finck     /* We got this far, assume success from here */
208c2c66affSColin Finck     Status = STATUS_SUCCESS;
209c2c66affSColin Finck 
210c2c66affSColin Finck     /* Check if the caller requested any context data */
211c2c66affSColin Finck     if (Registration->ContextRegistration)
212c2c66affSColin Finck     {
213c2c66affSColin Finck         /* Register the contexts for this filter */
214c2c66affSColin Finck         Status = FltpRegisterContexts(Filter, Registration->ContextRegistration);
215c2c66affSColin Finck         if (NT_SUCCESS(Status))
216c2c66affSColin Finck         {
217c2c66affSColin Finck             goto Quit;
218c2c66affSColin Finck         }
219c2c66affSColin Finck     }
220c2c66affSColin Finck 
221c2c66affSColin Finck     /* Check if the caller is registering any callbacks */
222c2c66affSColin Finck     if (Registration->OperationRegistration)
223c2c66affSColin Finck     {
224c2c66affSColin Finck         /* The callback data comes after the fixed struct */
225c2c66affSColin Finck         Filter->Operations = (PFLT_OPERATION_REGISTRATION)Ptr;
226c2c66affSColin Finck         Ptr += (Count * sizeof(FLT_OPERATION_REGISTRATION));
227c2c66affSColin Finck 
228c2c66affSColin Finck         /* Tag the operation data onto the end of the filter data */
229c2c66affSColin Finck         RtlCopyMemory(Filter->Operations, Registration->OperationRegistration, CallbackBufferSize);
230c2c66affSColin Finck 
231c2c66affSColin Finck         /* walk through the requested callbacks */
232c2c66affSColin Finck         for (Callbacks = Filter->Operations;
233c2c66affSColin Finck              Callbacks->MajorFunction != IRP_MJ_OPERATION_END;
234c2c66affSColin Finck              Callbacks++)
235c2c66affSColin Finck         {
236c2c66affSColin Finck             // http://fsfilters.blogspot.co.uk/2011/03/how-file-system-filters-attach-to_17.html
237c2c66affSColin Finck             /* Check if this is an attach to a volume */
238c2c66affSColin Finck             if (Callbacks->MajorFunction == IRP_MJ_VOLUME_MOUNT)
239c2c66affSColin Finck             {
240c2c66affSColin Finck                 Filter->PreVolumeMount = Callbacks->PreOperation;
241c2c66affSColin Finck                 Filter->PostVolumeMount = Callbacks->PostOperation;
242c2c66affSColin Finck             }
243c2c66affSColin Finck             else if (Callbacks->MajorFunction == IRP_MJ_SHUTDOWN)
244c2c66affSColin Finck             {
245c2c66affSColin Finck                 Callbacks->PostOperation = NULL;
246c2c66affSColin Finck             }
247c2c66affSColin Finck         }
248c2c66affSColin Finck     }
249c2c66affSColin Finck 
250c2c66affSColin Finck     /* Add the filter name buffer onto the end of the data and fill in the string */
251c2c66affSColin Finck     Filter->Name.Length = 0;
252c2c66affSColin Finck     Filter->Name.MaximumLength = DriverObject->DriverExtension->ServiceKeyName.Length;
253c2c66affSColin Finck     Filter->Name.Buffer = (PWCH)Ptr;
254c2c66affSColin Finck     RtlCopyUnicodeString(&Filter->Name, &DriverObject->DriverExtension->ServiceKeyName);
255c2c66affSColin Finck 
256*fa46f362SGed Murphy     /* Lookup the altitude of the mini-filter */
257dfb77638SGed Murphy     Status = GetFilterAltitude(Filter, &Filter->DefaultAltitude);
258dfb77638SGed Murphy     if (!NT_SUCCESS(Status))
259dfb77638SGed Murphy     {
260dfb77638SGed Murphy         goto Quit;
261dfb77638SGed Murphy     }
262dfb77638SGed Murphy 
263*fa46f362SGed Murphy     /* Lookup the filter frame */
264*fa46f362SGed Murphy     Status = GetFilterFrame(Filter, &Filter->DefaultAltitude, &Frame);
265*fa46f362SGed Murphy     if (Status == STATUS_NOT_FOUND)
266*fa46f362SGed Murphy     {
267*fa46f362SGed Murphy         /* Store the frame this mini-filter's main struct */
268*fa46f362SGed Murphy         Filter->Frame = Frame;
269*fa46f362SGed Murphy 
270*fa46f362SGed Murphy         Status = FltpAttachFrame(&Filter->DefaultAltitude, &Frame);
271*fa46f362SGed Murphy     }
272*fa46f362SGed Murphy 
273*fa46f362SGed Murphy     if (!NT_SUCCESS(Status))
274*fa46f362SGed Murphy     {
275*fa46f362SGed Murphy         goto Quit;
276*fa46f362SGed Murphy     }
277*fa46f362SGed Murphy 
278c2c66affSColin Finck     //
279c2c66affSColin Finck     // - Slot the filter into the correct altitude location
280c2c66affSColin Finck     // - More stuff??
281c2c66affSColin Finck     //
282c2c66affSColin Finck 
283dfb77638SGed Murphy     /* Store any existing driver unload routine before we make any changes */
284dfb77638SGed Murphy     Filter->OldDriverUnload = (PFLT_FILTER_UNLOAD_CALLBACK)DriverObject->DriverUnload;
285dfb77638SGed Murphy 
286dfb77638SGed Murphy     /* Check we opted not to have an unload routine, or if we want to stop the driver from being unloaded */
287c73c1825SGed Murphy     if (Registration->FilterUnloadCallback && !FlagOn(Filter->Flags, FLTFL_REGISTRATION_DO_NOT_SUPPORT_SERVICE_STOP))
288c2c66affSColin Finck     {
289dfb77638SGed Murphy         DriverObject->DriverUnload = (PDRIVER_UNLOAD)FltpMiniFilterDriverUnload;
290dfb77638SGed Murphy     }
291dfb77638SGed Murphy     else
292dfb77638SGed Murphy     {
293dfb77638SGed Murphy         DriverObject->DriverUnload = (PDRIVER_UNLOAD)NULL;
294dfb77638SGed Murphy     }
295dfb77638SGed Murphy 
296dfb77638SGed Murphy 
297dfb77638SGed Murphy Quit:
298dfb77638SGed Murphy 
299dfb77638SGed Murphy     if (NT_SUCCESS(Status))
300dfb77638SGed Murphy     {
301dfb77638SGed Murphy         DPRINT1("Loaded FS mini-filter %wZ\n", &DriverObject->DriverExtension->ServiceKeyName);
302dfb77638SGed Murphy         *RetFilter = Filter;
303dfb77638SGed Murphy     }
304dfb77638SGed Murphy     else
305dfb77638SGed Murphy     {
306dfb77638SGed Murphy         DPRINT1("Failed to load FS mini-filter %wZ : 0x%X\n", &DriverObject->DriverExtension->ServiceKeyName, Status);
307dfb77638SGed Murphy 
308c2c66affSColin Finck         // Add cleanup for context resources
309c2c66affSColin Finck 
310c2c66affSColin Finck         ExDeleteResourceLite(&Filter->InstanceList.rLock);
311c2c66affSColin Finck         ExFreePoolWithTag(Filter, FM_TAG_FILTER);
312c2c66affSColin Finck     }
313c2c66affSColin Finck 
314c2c66affSColin Finck     return Status;
315c2c66affSColin Finck }
316c2c66affSColin Finck 
317c2c66affSColin Finck VOID
318c2c66affSColin Finck FLTAPI
FltUnregisterFilter(_In_ PFLT_FILTER Filter)319c2c66affSColin Finck FltUnregisterFilter(_In_ PFLT_FILTER Filter)
320c2c66affSColin Finck {
321c2c66affSColin Finck     PFLT_INSTANCE Instance;
322c2c66affSColin Finck     PLIST_ENTRY CurrentEntry;
323c2c66affSColin Finck     NTSTATUS Status;
324c2c66affSColin Finck 
325c2c66affSColin Finck     /* Set the draining flag */
326c2c66affSColin Finck     Status = FltpStartingToDrainObject(&Filter->Base);
327c2c66affSColin Finck     if (!NT_SUCCESS(Status))
328c2c66affSColin Finck     {
329c2c66affSColin Finck         /* Someone already unregistered us, just remove our ref and bail */
330c2c66affSColin Finck         FltObjectDereference(&Filter->Base);
331c2c66affSColin Finck         return;
332c2c66affSColin Finck     }
333c2c66affSColin Finck 
334c2c66affSColin Finck     /* Lock the instance list */
335c2c66affSColin Finck     KeEnterCriticalRegion();
336c2c66affSColin Finck     ExAcquireResourceSharedLite(&Filter->InstanceList.rLock, TRUE);
337c2c66affSColin Finck 
338c2c66affSColin Finck     /* Set the first entry in the list */
339c2c66affSColin Finck     CurrentEntry = Filter->InstanceList.rList.Flink;
340c2c66affSColin Finck 
341c2c66affSColin Finck     /* Free all instances referenced by the filter */
342c2c66affSColin Finck     while (CurrentEntry != &Filter->InstanceList.rList)
343c2c66affSColin Finck     {
344c2c66affSColin Finck         /* Get the record pointer */
345c2c66affSColin Finck         Instance = CONTAINING_RECORD(CurrentEntry, FLT_INSTANCE, FilterLink);
346c2c66affSColin Finck 
347c2c66affSColin Finck         // FIXME: implement
348c2c66affSColin Finck         (void)Instance;
349c2c66affSColin Finck 
350c2c66affSColin Finck         /* Reset the pointer and move to next entry */
351c2c66affSColin Finck         Instance = NULL;
352c2c66affSColin Finck         CurrentEntry = CurrentEntry->Flink;
353c2c66affSColin Finck     }
354c2c66affSColin Finck 
355c2c66affSColin Finck     /* We're done with instances now */
356c2c66affSColin Finck     ExReleaseResourceLite(&Filter->InstanceList.rLock);
357c2c66affSColin Finck     KeLeaveCriticalRegion();
358c2c66affSColin Finck 
359c2c66affSColin Finck     /* Remove the reference from the base object */
360c2c66affSColin Finck     FltObjectDereference(&Filter->Base);
361c2c66affSColin Finck 
362c2c66affSColin Finck     /* Wait until we're sure nothing is using the filter */
363c2c66affSColin Finck     FltpObjectRundownWait(&Filter->Base.RundownRef);
364c2c66affSColin Finck 
365c2c66affSColin Finck     /* Delete the instance list lock */
366c2c66affSColin Finck     ExDeleteResourceLite(&Filter->InstanceList.rLock);
367c2c66affSColin Finck 
368c2c66affSColin Finck     /* We're finished cleaning up now */
369c2c66affSColin Finck     FltpExRundownCompleted(&Filter->Base.RundownRef);
370c2c66affSColin Finck 
371c2c66affSColin Finck     /* Hand the memory back */
372c2c66affSColin Finck     ExFreePoolWithTag(Filter, FM_TAG_FILTER);
373c2c66affSColin Finck }
374c2c66affSColin Finck 
375c2c66affSColin Finck NTSTATUS
376c2c66affSColin Finck NTAPI
FltStartFiltering(_In_ PFLT_FILTER Filter)377c2c66affSColin Finck FltStartFiltering(_In_ PFLT_FILTER Filter)
378c2c66affSColin Finck {
379c2c66affSColin Finck     NTSTATUS Status;
380c2c66affSColin Finck 
381c2c66affSColin Finck     /* Grab a ref to the filter */
382c2c66affSColin Finck     Status = FltObjectReference(&Filter->Base);
383c2c66affSColin Finck     if (NT_SUCCESS(Status))
384c2c66affSColin Finck     {
385c2c66affSColin Finck         /* Make sure we aren't already starting up */
386c2c66affSColin Finck         if (!(Filter->Flags & FLTFL_FILTERING_INITIATED))
387c2c66affSColin Finck         {
388c2c66affSColin Finck             // Startup
389c2c66affSColin Finck         }
390c2c66affSColin Finck         else
391c2c66affSColin Finck         {
392c2c66affSColin Finck             Status = STATUS_INVALID_PARAMETER;
393c2c66affSColin Finck         }
394c2c66affSColin Finck 
395c2c66affSColin Finck         FltObjectDereference(&Filter->Base);
396c2c66affSColin Finck     }
397c2c66affSColin Finck 
398c2c66affSColin Finck     return Status;
399c2c66affSColin Finck }
400c2c66affSColin Finck 
401*fa46f362SGed Murphy NTSTATUS
402*fa46f362SGed Murphy NTAPI
FltGetFilterFromName(_In_ PCUNICODE_STRING FilterName,_Out_ PFLT_FILTER * RetFilter)403*fa46f362SGed Murphy FltGetFilterFromName(_In_ PCUNICODE_STRING FilterName,
404*fa46f362SGed Murphy                      _Out_ PFLT_FILTER *RetFilter)
405*fa46f362SGed Murphy {
406*fa46f362SGed Murphy    UNIMPLEMENTED;
407*fa46f362SGed Murphy     UNREFERENCED_PARAMETER(FilterName);
408*fa46f362SGed Murphy     *RetFilter = NULL;
409*fa46f362SGed Murphy     return STATUS_NOT_IMPLEMENTED;
410*fa46f362SGed Murphy }
411*fa46f362SGed Murphy 
412c2c66affSColin Finck 
413c2c66affSColin Finck /* INTERNAL FUNCTIONS ******************************************************/
414c2c66affSColin Finck 
415c2c66affSColin Finck NTSTATUS
FltpStartingToDrainObject(_Inout_ PFLT_OBJECT Object)416c2c66affSColin Finck FltpStartingToDrainObject(_Inout_ PFLT_OBJECT Object)
417c2c66affSColin Finck {
418c2c66affSColin Finck     /*
419c2c66affSColin Finck      * Set the draining flag for the filter. This let's us force
420c2c66affSColin Finck      * a post op callback for minifilters currently awaiting one.
421c2c66affSColin Finck      */
422c2c66affSColin Finck     if (InterlockedOr((PLONG)&Object->Flags, FLT_OBFL_DRAINING) & 1)
423c2c66affSColin Finck     {
424c2c66affSColin Finck         /* We've been called once, we're already being deleted */
425c2c66affSColin Finck         return STATUS_FLT_DELETING_OBJECT;
426c2c66affSColin Finck     }
427c2c66affSColin Finck 
428c2c66affSColin Finck     return STATUS_SUCCESS;
429c2c66affSColin Finck }
430dfb77638SGed Murphy 
431dfb77638SGed Murphy VOID
FltpMiniFilterDriverUnload()432dfb77638SGed Murphy FltpMiniFilterDriverUnload()
433dfb77638SGed Murphy {
434dfb77638SGed Murphy     __debugbreak();
435dfb77638SGed Murphy }
436dfb77638SGed Murphy 
437*fa46f362SGed Murphy 
438*fa46f362SGed Murphy NTSTATUS
FltpAttachFrame(_In_ PUNICODE_STRING Altitude,_Inout_ PFLTP_FRAME * Frame)439*fa46f362SGed Murphy FltpAttachFrame(
440*fa46f362SGed Murphy     _In_ PUNICODE_STRING Altitude,
441*fa46f362SGed Murphy     _Inout_ PFLTP_FRAME *Frame)
442*fa46f362SGed Murphy {
443*fa46f362SGed Murphy     UNIMPLEMENTED;
444*fa46f362SGed Murphy     UNREFERENCED_PARAMETER(Altitude);
445*fa46f362SGed Murphy     *Frame = NULL;
446*fa46f362SGed Murphy     return STATUS_SUCCESS;
447*fa46f362SGed Murphy }
448*fa46f362SGed Murphy 
449dfb77638SGed Murphy /* PRIVATE FUNCTIONS ******************************************************/
450dfb77638SGed Murphy 
451dfb77638SGed Murphy static
452dfb77638SGed Murphy NTSTATUS
GetFilterAltitude(_In_ PFLT_FILTER Filter,_Inout_ PUNICODE_STRING AltitudeString)453*fa46f362SGed Murphy GetFilterAltitude(_In_ PFLT_FILTER Filter,
454dfb77638SGed Murphy                   _Inout_ PUNICODE_STRING AltitudeString)
455dfb77638SGed Murphy {
456dfb77638SGed Murphy     UNICODE_STRING InstancesKey = RTL_CONSTANT_STRING(L"Instances");
457dfb77638SGed Murphy     UNICODE_STRING DefaultInstance = RTL_CONSTANT_STRING(L"DefaultInstance");
458dfb77638SGed Murphy     UNICODE_STRING Altitude = RTL_CONSTANT_STRING(L"Altitude");
459dfb77638SGed Murphy     OBJECT_ATTRIBUTES ObjectAttributes;
460dfb77638SGed Murphy     UNICODE_STRING FilterInstancePath;
461dfb77638SGed Murphy     ULONG BytesRequired;
462dfb77638SGed Murphy     HANDLE InstHandle = NULL;
463dfb77638SGed Murphy     HANDLE RootHandle;
464dfb77638SGed Murphy     PWCH InstBuffer = NULL;
465dfb77638SGed Murphy     PWCH AltBuffer = NULL;
466dfb77638SGed Murphy     NTSTATUS Status;
467dfb77638SGed Murphy 
468dfb77638SGed Murphy     /* Get a handle to the instances key in the filter's services key */
469dfb77638SGed Murphy     Status = FltpOpenFilterServicesKey(Filter,
470dfb77638SGed Murphy                                        KEY_QUERY_VALUE,
471dfb77638SGed Murphy                                        &InstancesKey,
472dfb77638SGed Murphy                                        &RootHandle);
473dfb77638SGed Murphy     if (!NT_SUCCESS(Status))
474dfb77638SGed Murphy     {
475dfb77638SGed Murphy         return Status;
476dfb77638SGed Murphy     }
477dfb77638SGed Murphy 
478dfb77638SGed Murphy     /* Read the size 'default instances' string value */
479dfb77638SGed Murphy     Status = FltpReadRegistryValue(RootHandle,
480dfb77638SGed Murphy                                    &DefaultInstance,
481dfb77638SGed Murphy                                    REG_SZ,
482dfb77638SGed Murphy                                    NULL,
483dfb77638SGed Murphy                                    0,
484dfb77638SGed Murphy                                    &BytesRequired);
485dfb77638SGed Murphy 
486dfb77638SGed Murphy     /* We should get a buffer too small error */
487dfb77638SGed Murphy     if (Status == STATUS_BUFFER_TOO_SMALL)
488dfb77638SGed Murphy     {
489dfb77638SGed Murphy         /* Allocate the buffer we need to hold the string */
490dfb77638SGed Murphy         InstBuffer = ExAllocatePoolWithTag(PagedPool, BytesRequired, FM_TAG_UNICODE_STRING);
491dfb77638SGed Murphy         if (InstBuffer == NULL)
492dfb77638SGed Murphy         {
493dfb77638SGed Murphy             Status = STATUS_INSUFFICIENT_RESOURCES;
494dfb77638SGed Murphy             goto Quit;
495dfb77638SGed Murphy         }
496dfb77638SGed Murphy 
497dfb77638SGed Murphy         /* Now read the string value */
498dfb77638SGed Murphy         Status = FltpReadRegistryValue(RootHandle,
499dfb77638SGed Murphy                                        &DefaultInstance,
500dfb77638SGed Murphy                                        REG_SZ,
501dfb77638SGed Murphy                                        InstBuffer,
502dfb77638SGed Murphy                                        BytesRequired,
503dfb77638SGed Murphy                                        &BytesRequired);
504dfb77638SGed Murphy     }
505dfb77638SGed Murphy 
506dfb77638SGed Murphy     if (!NT_SUCCESS(Status))
507dfb77638SGed Murphy     {
508dfb77638SGed Murphy         goto Quit;
509dfb77638SGed Murphy     }
510dfb77638SGed Murphy 
511dfb77638SGed Murphy     /* Convert the string to a unicode_string */
512dfb77638SGed Murphy     RtlInitUnicodeString(&FilterInstancePath, InstBuffer);
513dfb77638SGed Murphy 
514dfb77638SGed Murphy     /* Setup the attributes using the root key handle */
515dfb77638SGed Murphy     InitializeObjectAttributes(&ObjectAttributes,
516dfb77638SGed Murphy                                &FilterInstancePath,
517dfb77638SGed Murphy                                OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
518dfb77638SGed Murphy                                RootHandle,
519dfb77638SGed Murphy                                NULL);
520dfb77638SGed Murphy 
521dfb77638SGed Murphy     /* Now open the key name which was stored in the default instance */
522dfb77638SGed Murphy     Status = ZwOpenKey(&InstHandle, KEY_QUERY_VALUE, &ObjectAttributes);
523dfb77638SGed Murphy     if (NT_SUCCESS(Status))
524dfb77638SGed Murphy     {
525dfb77638SGed Murphy         /* Get the size of the buffer that holds the altitude */
526dfb77638SGed Murphy         Status = FltpReadRegistryValue(InstHandle,
527dfb77638SGed Murphy                                        &Altitude,
528dfb77638SGed Murphy                                        REG_SZ,
529dfb77638SGed Murphy                                        NULL,
530dfb77638SGed Murphy                                        0,
531dfb77638SGed Murphy                                        &BytesRequired);
532dfb77638SGed Murphy         if (Status == STATUS_BUFFER_TOO_SMALL)
533dfb77638SGed Murphy         {
534dfb77638SGed Murphy             /* Allocate the required buffer */
535dfb77638SGed Murphy             AltBuffer = ExAllocatePoolWithTag(PagedPool, BytesRequired, FM_TAG_UNICODE_STRING);
536dfb77638SGed Murphy             if (AltBuffer == NULL)
537dfb77638SGed Murphy             {
538dfb77638SGed Murphy                 Status = STATUS_INSUFFICIENT_RESOURCES;
539dfb77638SGed Murphy                 goto Quit;
540dfb77638SGed Murphy             }
541dfb77638SGed Murphy 
542dfb77638SGed Murphy             /* And now finally read in the actual altitude string */
543dfb77638SGed Murphy             Status = FltpReadRegistryValue(InstHandle,
544dfb77638SGed Murphy                                            &Altitude,
545dfb77638SGed Murphy                                            REG_SZ,
546dfb77638SGed Murphy                                            AltBuffer,
547dfb77638SGed Murphy                                            BytesRequired,
548dfb77638SGed Murphy                                            &BytesRequired);
549dfb77638SGed Murphy             if (NT_SUCCESS(Status))
550dfb77638SGed Murphy             {
551dfb77638SGed Murphy                 /* We made it, setup the return buffer */
552dfb77638SGed Murphy                 AltitudeString->Length = BytesRequired;
553dfb77638SGed Murphy                 AltitudeString->MaximumLength = BytesRequired;
554dfb77638SGed Murphy                 AltitudeString->Buffer = AltBuffer;
555dfb77638SGed Murphy             }
556dfb77638SGed Murphy         }
557dfb77638SGed Murphy     }
558dfb77638SGed Murphy 
559dfb77638SGed Murphy Quit:
560dfb77638SGed Murphy     if (!NT_SUCCESS(Status))
561dfb77638SGed Murphy     {
562dfb77638SGed Murphy         if (AltBuffer)
563dfb77638SGed Murphy         {
564dfb77638SGed Murphy             ExFreePoolWithTag(AltBuffer, FM_TAG_UNICODE_STRING);
565dfb77638SGed Murphy         }
566dfb77638SGed Murphy     }
567dfb77638SGed Murphy 
568dfb77638SGed Murphy     if (InstBuffer)
569dfb77638SGed Murphy     {
570dfb77638SGed Murphy         ExFreePoolWithTag(InstBuffer, FM_TAG_UNICODE_STRING);
571dfb77638SGed Murphy     }
572dfb77638SGed Murphy 
573dfb77638SGed Murphy     if (InstHandle)
574dfb77638SGed Murphy     {
575dfb77638SGed Murphy         ZwClose(InstHandle);
576dfb77638SGed Murphy     }
577dfb77638SGed Murphy     ZwClose(RootHandle);
578dfb77638SGed Murphy 
579dfb77638SGed Murphy     return Status;
580dfb77638SGed Murphy }
581dfb77638SGed Murphy 
582*fa46f362SGed Murphy static
583dfb77638SGed Murphy NTSTATUS
GetFilterFrame(_In_ PFLT_FILTER Filter,_In_ PUNICODE_STRING Altitude,_Out_ PFLTP_FRAME * Frame)584*fa46f362SGed Murphy GetFilterFrame(_In_ PFLT_FILTER Filter,
585*fa46f362SGed Murphy                _In_ PUNICODE_STRING Altitude,
586*fa46f362SGed Murphy                _Out_ PFLTP_FRAME *Frame)
587*fa46f362SGed Murphy {
588*fa46f362SGed Murphy     UNIMPLEMENTED;
589*fa46f362SGed Murphy     UNREFERENCED_PARAMETER(Filter);
590*fa46f362SGed Murphy     UNREFERENCED_PARAMETER(Altitude);
591*fa46f362SGed Murphy 
592*fa46f362SGed Murphy     //
593*fa46f362SGed Murphy     // Try to find a frame from our existing filter list (see FilterList)
594*fa46f362SGed Murphy     // If none exists, create a new frame, add it and return it
595*fa46f362SGed Murphy     //
596*fa46f362SGed Murphy 
597*fa46f362SGed Murphy     *Frame = NULL;
598*fa46f362SGed Murphy     return STATUS_SUCCESS;
599*fa46f362SGed Murphy }
600