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