text: /*
   * PROJECT:         ReactOS kernel-mode tests - Filter Manager
   * LICENSE:         GPLv2+ - See COPYING in the top level directory
   * PURPOSE:         Tests for checking filter registration
   * PROGRAMMER:      Ged Murphy <gedmurphy@reactos.org>
   */
  
  // This tests needs to be run via a standalone driver because FltRegisterFilter
  // uses the DriverObject in its internal structures, and we don't want it to be
  // linked to a device object from the test suite itself.
  
  #include <kmt_test.h>
  #include <fltkernel.h>
  #include <fltmgrint.h>
  
  //#define NDEBUG
  #include <debug.h>
  
  #define RESET_REGISTRATION(basic) \
      do { \
          RtlZeroMemory(&FilterRegistration, sizeof(FLT_REGISTRATION)); \
          if (basic) { \
              FilterRegistration.Size = sizeof(FLT_REGISTRATION); \
              FilterRegistration.Version = FLT_REGISTRATION_VERSION; \
          } \
      } while (0)
  
  #define RESET_UNLOAD(DO) DO->DriverUnload = NULL;
  
  
  NTSTATUS
  FLTAPI
  TestRegFilterUnload(
      _In_ FLT_FILTER_UNLOAD_FLAGS Flags
  );
  
  /* Globals */
  static PDRIVER_OBJECT TestDriverObject;
  static FLT_REGISTRATION FilterRegistration;
  static PFLT_FILTER TestFilter = NULL;
  
  
  
  
  BOOLEAN
  TestFltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject)
  {
      UNICODE_STRING Altitude;
      UNICODE_STRING Name;
      PFLT_FILTER Filter = NULL;
      PFLT_FILTER Temp = NULL;
      NTSTATUS Status;
  
      RESET_REGISTRATION(FALSE);
  #if 0
      KmtStartSeh()
          Status = FltRegisterFilter(NULL, &FilterRegistration, &Filter);
      KmtEndSeh(STATUS_INVALID_PARAMETER);
  
      KmtStartSeh()
          Status = FltRegisterFilter(DriverObject, NULL, &Filter);
      KmtEndSeh(STATUS_INVALID_PARAMETER);
  
      KmtStartSeh()
          Status = FltRegisterFilter(DriverObject, &FilterRegistration, NULL);
      KmtEndSeh(STATUS_INVALID_PARAMETER)
  #endif
  
      RESET_REGISTRATION(TRUE);
      FilterRegistration.Version = 0x0100;
      Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
      ok_eq_hex(Status, STATUS_INVALID_PARAMETER);
  
      RESET_REGISTRATION(TRUE);
      FilterRegistration.Version = 0x0300;
      Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
      ok_eq_hex(Status, STATUS_INVALID_PARAMETER);
  
      RESET_REGISTRATION(TRUE);
      FilterRegistration.Version = 0x0200;
      Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
      ok_eq_hex(Status, STATUS_SUCCESS);
      FltUnregisterFilter(Filter);
  
  
      /* Test invalid sizes. MSDN says this is required, but it doesn't appear to be */
      RESET_REGISTRATION(TRUE);
      FilterRegistration.Size = 0;
      Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
      ok_eq_hex(Status, STATUS_SUCCESS);
      FltUnregisterFilter(Filter);
  
      RESET_REGISTRATION(TRUE);
      FilterRegistration.Size = 0xFFFF;
      Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
      ok_eq_hex(Status, STATUS_SUCCESS);
      FltUnregisterFilter(Filter);
  
  
      /* Now make a valid registration */
      RESET_REGISTRATION(TRUE);
      Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
      ok_eq_hex(Status, STATUS_SUCCESS);
  
      /* Try to register again */
      Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Temp);
      ok_eq_hex(Status, STATUS_FLT_INSTANCE_ALTITUDE_COLLISION);
  
  
      ok_eq_hex(Filter->Base.Flags, FLT_OBFL_TYPE_FILTER);
      
      /* Check we have the right filter name */
      RtlInitUnicodeString(&Name, L"Kmtest-FltMgrReg");
      ok_eq_long(RtlCompareUnicodeString(&Filter->Name, &Name, FALSE), 0);
  
      /* And the altitude is corect */
      RtlInitUnicodeString(&Altitude, L"123456");
      ok_eq_long(RtlCompareUnicodeString(&Filter->DefaultAltitude, &Altitude, FALSE), 0);
  
      //
      // FIXME: More checks
      //
  
      /* Cleanup the valid registration */
      FltUnregisterFilter(Filter);
  
      /*
       * The last thing we'll do before we exit is to properly register with the filter manager 
       * and set an unload routine. This'll let us test the FltUnregisterFilter routine
       */
      RESET_REGISTRATION(TRUE);
  
      /* Set a fake unload routine we'll use to test */
      DriverObject->DriverUnload = (PDRIVER_UNLOAD)0x1234FFFF;
  
      FilterRegistration.FilterUnloadCallback = TestRegFilterUnload;
      Status = FltRegisterFilter(DriverObject, &FilterRegistration, &TestFilter);
      ok_eq_hex(Status, STATUS_SUCCESS);
      
      /* Test all the unlod routines */
      ok_eq_pointer(TestFilter->FilterUnload, TestRegFilterUnload);
      ok_eq_pointer(TestFilter->OldDriverUnload, (PFLT_FILTER_UNLOAD_CALLBACK)0x1234FFFF);
  
      // This should equal the fltmgr's private unload routine, but there's no easy way of testing it...
      //ok_eq_pointer(DriverObject->DriverUnload, FltpMiniFilterDriverUnload);
  
      /* Make sure our test address is never actually called */
      TestFilter->OldDriverUnload = (PFLT_FILTER_UNLOAD_CALLBACK)NULL;
  
      return TRUE;
  }
  
  
  NTSTATUS
  FLTAPI
  TestRegFilterUnload(
      _In_ FLT_FILTER_UNLOAD_FLAGS Flags)
  {
      //__debugbreak();
  
      ok_irql(PASSIVE_LEVEL);
      ok(TestFilter != NULL, "Buffer is NULL\n");
  
      //
      // FIXME: Add tests
      //
  
      FltUnregisterFilter(TestFilter);
  
      //
      // FIXME: Add tests
      //
  
      return STATUS_SUCCESS;
  }
  
  
  
  
  
  
  
  
  
  
  /*
   * KMT Callback routines
   */
  
  NTSTATUS
  TestEntry(
      IN PDRIVER_OBJECT DriverObject,
      IN PCUNICODE_STRING RegistryPath,
      OUT PCWSTR *DeviceName,
      IN OUT INT *Flags)
  {
      NTSTATUS Status = STATUS_SUCCESS;
  
      PAGED_CODE();
  
      UNREFERENCED_PARAMETER(RegistryPath);
  
      DPRINT("FltMgrReg Entry!\n");
      trace("Entered FltMgrReg tests\n");
  
      /* We'll do the work ourselves in this test */
      *Flags = TESTENTRY_NO_ALL;
  
      ok_irql(PASSIVE_LEVEL);
      TestDriverObject = DriverObject;
  
  
      /* Run the tests */
      (VOID)TestFltRegisterFilter(DriverObject);
  
      return Status;
  }
  
  VOID
  TestFilterUnload(
      IN ULONG Flags)
  {
      PAGED_CODE();
      ok_irql(PASSIVE_LEVEL);
  }
  
  NTSTATUS
  TestInstanceSetup(
      _In_ PCFLT_RELATED_OBJECTS FltObjects,
      _In_ FLT_INSTANCE_SETUP_FLAGS Flags,
      _In_ DEVICE_TYPE VolumeDeviceType,
      _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType,
      _In_ PUNICODE_STRING VolumeName,
      _In_ ULONG SectorSize,
      _In_ ULONG ReportedSectorSize
  )
  {
      return STATUS_FLT_DO_NOT_ATTACH;
  }
  
  VOID
  TestQueryTeardown(
      _In_ PCFLT_RELATED_OBJECTS FltObjects,
      _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
  {
      UNREFERENCED_PARAMETER(FltObjects);
      UNREFERENCED_PARAMETER(Flags);
  }
  