[FLTMGR] Latest from my branch (#135)
[reactos.git] / drivers / filters / fltmgr / Filter.c
index 71e45ae..92a824c 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "fltmgr.h"
 #include "fltmgrint.h"
+#include "Registry.h"
 
 #define NDEBUG
 #include <debug.h>
@@ -25,6 +26,17 @@ FltpStartingToDrainObject(
     _Inout_ PFLT_OBJECT Object
 );
 
+VOID
+FltpMiniFilterDriverUnload(
+);
+
+static
+NTSTATUS
+GetFilterAltitude(
+    _In_ PFLT_FILTER Filter,
+    _Inout_ PUNICODE_STRING AltitudeString
+);
+
 
 /* EXPORTED FUNCTIONS ******************************************************/
 
@@ -56,8 +68,26 @@ NTSTATUS
 NTAPI
 FltUnloadFilter(_In_ PCUNICODE_STRING FilterName)
 {
-    UNREFERENCED_PARAMETER(FilterName);
-    return STATUS_NOT_IMPLEMENTED;
+    //
+    //FIXME: This is a temp hack, it needs properly implementing
+    //
+
+    UNICODE_STRING DriverServiceName;
+    UNICODE_STRING ServicesKey;
+    CHAR Buffer[MAX_KEY_LENGTH];
+
+    /* Setup the base services key */
+    RtlInitUnicodeString(&ServicesKey, SERVICES_KEY);
+
+    /* Initialize the string data */
+    DriverServiceName.Length = 0;
+    DriverServiceName.Buffer = (PWCH)Buffer;
+    DriverServiceName.MaximumLength = MAX_KEY_LENGTH;
+
+    /* Create the full service key for this filter */
+    RtlCopyUnicodeString(&DriverServiceName, &ServicesKey);
+    RtlAppendUnicodeStringToString(&DriverServiceName, FilterName);
+    return ZwUnloadDriver(&DriverServiceName);
 }
 
 NTSTATUS
@@ -74,6 +104,8 @@ FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject,
     PCHAR Ptr;
     NTSTATUS Status;
 
+    *RetFilter = NULL;
+
     /* Make sure we're targeting the correct major revision */
     if ((Registration->Version & 0xFF00) != FLT_MAJOR_VERSION)
     {
@@ -145,6 +177,10 @@ FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject,
     InitializeListHead(&Filter->ActiveOpens.mList);
     Filter->ActiveOpens.mCount = 0;
 
+    ExInitializeFastMutex(&Filter->ConnectionList.mLock);
+    InitializeListHead(&Filter->ConnectionList.mList);
+    Filter->ConnectionList.mCount = 0;
+
     /* Initialize the usermode port list */
     ExInitializeFastMutex(&Filter->PortList.mLock);
     InitializeListHead(&Filter->PortList.mList);
@@ -199,15 +235,42 @@ FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject,
     Filter->Name.Buffer = (PWCH)Ptr;
     RtlCopyUnicodeString(&Filter->Name, &DriverObject->DriverExtension->ServiceKeyName);
 
+    Status = GetFilterAltitude(Filter, &Filter->DefaultAltitude);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quit;
+    }
+
     //
-    // - Get the altitude string
     // - Slot the filter into the correct altitude location
     // - More stuff??
     //
 
+    /* Store any existing driver unload routine before we make any changes */
+    Filter->OldDriverUnload = (PFLT_FILTER_UNLOAD_CALLBACK)DriverObject->DriverUnload;
+
+    /* Check we opted not to have an unload routine, or if we want to stop the driver from being unloaded */
+    if (!FlagOn(Filter->Flags, FLTFL_REGISTRATION_DO_NOT_SUPPORT_SERVICE_STOP))
+    {
+        DriverObject->DriverUnload = (PDRIVER_UNLOAD)FltpMiniFilterDriverUnload;
+    }
+    else
+    {
+        DriverObject->DriverUnload = (PDRIVER_UNLOAD)NULL;
+    }
+
+
 Quit:
-    if (!NT_SUCCESS(Status))
+
+    if (NT_SUCCESS(Status))
+    {
+        DPRINT1("Loaded FS mini-filter %wZ\n", &DriverObject->DriverExtension->ServiceKeyName);
+        *RetFilter = Filter;
+    }
+    else
     {
+        DPRINT1("Failed to load FS mini-filter %wZ : 0x%X\n", &DriverObject->DriverExtension->ServiceKeyName, Status);
+
         // Add cleanup for context resources
 
         ExDeleteResourceLite(&Filter->InstanceList.rLock);
@@ -319,3 +382,155 @@ FltpStartingToDrainObject(_Inout_ PFLT_OBJECT Object)
 
     return STATUS_SUCCESS;
 }
+
+VOID
+FltpMiniFilterDriverUnload()
+{
+    __debugbreak();
+}
+
+/* PRIVATE FUNCTIONS ******************************************************/
+
+static
+NTSTATUS
+GetFilterAltitude(
+    _In_ PFLT_FILTER Filter,
+    _Inout_ PUNICODE_STRING AltitudeString)
+{
+    UNICODE_STRING InstancesKey = RTL_CONSTANT_STRING(L"Instances");
+    UNICODE_STRING DefaultInstance = RTL_CONSTANT_STRING(L"DefaultInstance");
+    UNICODE_STRING Altitude = RTL_CONSTANT_STRING(L"Altitude");
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING FilterInstancePath;
+    ULONG BytesRequired;
+    HANDLE InstHandle = NULL;
+    HANDLE RootHandle;
+    PWCH InstBuffer = NULL;
+    PWCH AltBuffer = NULL;
+    NTSTATUS Status;
+
+    /* Get a handle to the instances key in the filter's services key */
+    Status = FltpOpenFilterServicesKey(Filter,
+                                       KEY_QUERY_VALUE,
+                                       &InstancesKey,
+                                       &RootHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    /* Read the size 'default instances' string value */
+    Status = FltpReadRegistryValue(RootHandle,
+                                   &DefaultInstance,
+                                   REG_SZ,
+                                   NULL,
+                                   0,
+                                   &BytesRequired);
+
+    /* We should get a buffer too small error */
+    if (Status == STATUS_BUFFER_TOO_SMALL)
+    {
+        /* Allocate the buffer we need to hold the string */
+        InstBuffer = ExAllocatePoolWithTag(PagedPool, BytesRequired, FM_TAG_UNICODE_STRING);
+        if (InstBuffer == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto Quit;
+        }
+
+        /* Now read the string value */
+        Status = FltpReadRegistryValue(RootHandle,
+                                       &DefaultInstance,
+                                       REG_SZ,
+                                       InstBuffer,
+                                       BytesRequired,
+                                       &BytesRequired);
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quit;
+    }
+
+    /* Convert the string to a unicode_string */
+    RtlInitUnicodeString(&FilterInstancePath, InstBuffer);
+
+    /* Setup the attributes using the root key handle */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &FilterInstancePath,
+                               OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+                               RootHandle,
+                               NULL);
+
+    /* Now open the key name which was stored in the default instance */
+    Status = ZwOpenKey(&InstHandle, KEY_QUERY_VALUE, &ObjectAttributes);
+    if (NT_SUCCESS(Status))
+    {
+        /* Get the size of the buffer that holds the altitude */
+        Status = FltpReadRegistryValue(InstHandle,
+                                       &Altitude,
+                                       REG_SZ,
+                                       NULL,
+                                       0,
+                                       &BytesRequired);
+        if (Status == STATUS_BUFFER_TOO_SMALL)
+        {
+            /* Allocate the required buffer */
+            AltBuffer = ExAllocatePoolWithTag(PagedPool, BytesRequired, FM_TAG_UNICODE_STRING);
+            if (AltBuffer == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto Quit;
+            }
+
+            /* And now finally read in the actual altitude string */
+            Status = FltpReadRegistryValue(InstHandle,
+                                           &Altitude,
+                                           REG_SZ,
+                                           AltBuffer,
+                                           BytesRequired,
+                                           &BytesRequired);
+            if (NT_SUCCESS(Status))
+            {
+                /* We made it, setup the return buffer */
+                AltitudeString->Length = BytesRequired;
+                AltitudeString->MaximumLength = BytesRequired;
+                AltitudeString->Buffer = AltBuffer;
+            }
+        }
+    }
+
+Quit:
+    if (!NT_SUCCESS(Status))
+    {
+        if (AltBuffer)
+        {
+            ExFreePoolWithTag(AltBuffer, FM_TAG_UNICODE_STRING);
+        }
+    }
+
+    if (InstBuffer)
+    {
+        ExFreePoolWithTag(InstBuffer, FM_TAG_UNICODE_STRING);
+    }
+
+    if (InstHandle)
+    {
+        ZwClose(InstHandle);
+    }
+    ZwClose(RootHandle);
+
+    return Status;
+}
+
+
+
+NTSTATUS
+FltpReadRegistryValue(
+    _In_ HANDLE KeyHandle,
+    _In_ PUNICODE_STRING ValueName,
+    _In_opt_ ULONG Type,
+    _Out_writes_bytes_(BufferSize) PVOID Buffer,
+    _In_ ULONG BufferSize,
+    _Out_opt_ PULONG BytesRequired
+);
\ No newline at end of file