diff -ruN fsfilter-rs-0.8.0/minifilter/snFilter/install.cmd fsfilter-rs-0.8.1/minifilter/snFilter/install.cmd
--- fsfilter-rs-0.8.0/minifilter/snFilter/install.cmd	1969-12-31 16:00:00.000000000 -0800
+++ fsfilter-rs-0.8.1/minifilter/snFilter/install.cmd	2023-07-31 09:53:43.917926800 -0700
@@ -0,0 +1,8 @@
+echo Removing old version if exist > "%~dp0\install.log"
+start /wait /b sc stop snFilter >> "%~dp0\install.log" 2>&1
+start /wait /b sc delete snFilter >> "%~dp0\install.log" 2>&1
+start /wait /b pnputil -d %~dp0\snFilter.inf >> "%~dp0\install.log" 2>&1
+
+echo Installing new version >> "%~dp0\install.log" 2>&1
+start /wait /b pnputil -i -a %~dp0\snFilter.inf >> "%~dp0\install.log" 2>&1
+start /wait /b sc start snFilter >> "%~dp0\install.log" 2>&1
diff -ruN fsfilter-rs-0.8.0/minifilter/snFilter/snFilter.cpp fsfilter-rs-0.8.1/minifilter/snFilter/snFilter.cpp
--- fsfilter-rs-0.8.0/minifilter/snFilter/snFilter.cpp	2023-07-31 09:48:09.770588900 -0700
+++ fsfilter-rs-0.8.1/minifilter/snFilter/snFilter.cpp	2023-07-19 16:52:07.351275600 -0700
@@ -1,1266 +1,1266 @@
-#pragma clang diagnostic push
-#pragma ide diagnostic ignored "UnreachableCode"
-
-/*++
-
-Module Name:
-
-    snFilter.c
-
-Abstract:
-
-    This is the main module of the snFilter miniFilter driver.
-
-Environment:
-
-    Kernel mode
-
---*/
-
-#include "snFilter.h"
-
-#pragma prefast(disable                                                        \
-                : __WARNING_ENCODE_MEMBER_FUNCTION_POINTER,                    \
-                  "Not valid for kernel mode drivers")
-
-#define POOL_FLAG_NON_PAGED 0x0000000000000040UI64 // Non paged pool NX
-
-//  Structure that contains all the global data structures used throughout the
-//  driver.
-
-EXTERN_C_START
-
-DRIVER_INITIALIZE DriverEntry;
-
-NTSTATUS
-DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
-
-EXTERN_C_END
-
-//
-//  Constant FLT_REGISTRATION structure for our filter.  This
-//  initializes the callback routines our filter wants to register
-//  for.  This is only used to register with the filter manager
-//
-
-CONST
-FLT_OPERATION_REGISTRATION Callbacks[] =
-    { //{IRP_MJ_CREATE, 0, FSPreOperation, FSPostOperation},
-        {IRP_MJ_CLOSE, 0, FSPreOperation, FSPostOperation},
-        {IRP_MJ_READ, 0, FSPreOperation, FSPostOperation},
-        //{IRP_MJ_CLEANUP, 0, FSPreOperation, NULL},
-        {IRP_MJ_WRITE, 0, FSPreOperation, NULL},
-        //{IRP_MJ_SET_INFORMATION, 0, FSPreOperation, NULL},
-        {IRP_MJ_OPERATION_END}};
-
-/*++
-
-FilterRegistration Defines what we want to filter with the driver
-
---*/
-CONST FLT_REGISTRATION FilterRegistration = {
-    sizeof(FLT_REGISTRATION),   //  Size
-    FLT_REGISTRATION_VERSION,   //  Version
-    0,                          //  Flags
-    NULL,                       //  Context Registration.
-    Callbacks,                  //  Operation callbacks
-    FSUnloadDriver,             //  FilterUnload
-    FSInstanceSetup,            //  InstanceSetup
-    FSInstanceQueryTeardown,    //  InstanceQueryTeardown
-    FSInstanceTeardownStart,    //  InstanceTeardownStart
-    FSInstanceTeardownComplete, //  InstanceTeardownComplete
-    NULL,                       //  GenerateFileName
-    NULL,                       //  GenerateDestinationFileName
-    NULL                        //  NormalizeNameComponent
-};
-
-////////////////////////////////////////////////////////////////////////////
-//
-//    Filter initialization and unload routines.
-//
-////////////////////////////////////////////////////////////////////////////
-
-DRIVER_INITIALIZE DriverEntry;
-
-NTSTATUS
-DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
-/*++
-
-Routine Description:
-
-    This is the initialization routine for the Filter driver.  This
-    registers the Filter with the filter manager and initializes all
-    its global data structures.
-
-Arguments:
-
-    DriverObject - Pointer to a driver object created by the system to
-        represent this driver.
-
-    RegistryPath - Unicode string identifying where the parameters for this
-        driver are located in the registry.
-
-Return Value:
-
-    Returns STATUS_SUCCESS.
---*/
-{
-  UNREFERENCED_PARAMETER(RegistryPath);
-  NTSTATUS status;
-
-  //
-  //  Default to NonPagedPoolNx for non paged pool allocations where supported.
-  //
-
-  ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
-
-  //
-  //  Register with filter manager.
-  //
-
-  driverData = new DriverData(DriverObject);
-  if (driverData == NULL) {
-    return STATUS_MEMORY_NOT_ALLOCATED;
-  }
-
-  PFLT_FILTER *FilterAdd = driverData->getFilterAdd();
-
-  status = FltRegisterFilter(DriverObject, &FilterRegistration, FilterAdd);
-
-  if (!NT_SUCCESS(status)) {
-    delete driverData;
-    return status;
-  }
-
-  commHandle = new CommHandler(driverData->getFilter());
-  if (commHandle == NULL) {
-    delete driverData;
-    return STATUS_MEMORY_NOT_ALLOCATED;
-  }
-
-  status = InitCommData();
-
-  if (!NT_SUCCESS(status)) {
-    FltUnregisterFilter(driverData->
-
-                        getFilter()
-
-    );
-    delete driverData;
-    delete commHandle;
-    return status;
-  }
-  //
-  //  Start filtering I/O.
-  //
-  status = FltStartFiltering(driverData->getFilter());
-
-  if (!NT_SUCCESS(status)) {
-    CommClose();
-
-    FltUnregisterFilter(driverData->
-
-                        getFilter()
-
-    );
-    delete driverData;
-    delete commHandle;
-    return status;
-  }
-  driverData->
-
-      setFilterStart();
-
-  DbgPrint("loaded scanner successfully");
-  // new code
-  // TODO: check status and release in unload
-  PsSetCreateProcessNotifyRoutine(AddRemProcessRoutine, FALSE);
-  return STATUS_SUCCESS;
-}
-
-NTSTATUS
-FSUnloadDriver(_In_ FLT_FILTER_UNLOAD_FLAGS Flags)
-/*++
-
-Routine Description:
-
-    This is to unload routine for the Filter driver.This is unregistering the
-    Filter with the filter manager and frees any allocated global data
-    structures.
-
-Arguments:
-
-    None.
-
-Return Value:
-
-    Returns the final status of the de-allocation routines.
-
---*/
-{
-  UNREFERENCED_PARAMETER(Flags);
-
-  //
-  //  Close the server port.
-  //
-  driverData->setFilterStop();
-  CommClose();
-
-  //
-  //  Unregister the filter
-  //
-
-  FltUnregisterFilter(driverData->getFilter());
-  delete driverData;
-  delete commHandle;
-  PsSetCreateProcessNotifyRoutine(AddRemProcessRoutine, TRUE);
-  return STATUS_SUCCESS;
-}
-
-NTSTATUS
-FSInstanceSetup(_In_ PCFLT_RELATED_OBJECTS FltObjects,
-                _In_ FLT_INSTANCE_SETUP_FLAGS Flags,
-                _In_ DEVICE_TYPE VolumeDeviceType,
-                _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType)
-/*++
-
-Routine Description:
-
-This routine is called whenever a new instance is created on a volume. This
-gives us a chance to decide if we need to attach to this volume or not.
-
-If this routine is not defined in the registration structure, automatic
-instances are always created.
-
-Arguments:
-
-FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
-opaque handles to this filter, instance and its associated volume.
-
-Flags - Flags describing the reason for this attach request.
-
-Return Value:
-
-STATUS_SUCCESS - attach
-STATUS_FLT_DO_NOT_ATTACH - do not attach
-
---*/
-{
-  UNREFERENCED_PARAMETER(FltObjects);
-  UNREFERENCED_PARAMETER(Flags);
-  UNREFERENCED_PARAMETER(VolumeDeviceType);
-  UNREFERENCED_PARAMETER(VolumeFilesystemType);
-
-  DbgPrint("snFilter: Entered FSInstanceSetup\n");
-
-  WCHAR newTemp[40];
-
-  GvolumeData.MaximumLength = 80;
-  GvolumeData.Buffer = newTemp;
-  GvolumeData.Length = 0;
-
-  NTSTATUS hr = STATUS_SUCCESS;
-  PDEVICE_OBJECT devObject;
-  hr = FltGetDiskDeviceObject(FltObjects->Volume, &devObject);
-  if (!NT_SUCCESS(hr)) {
-    return STATUS_SUCCESS;
-    // return hr;
-  }
-  hr = IoVolumeDeviceToDosName(devObject, &GvolumeData);
-  if (!NT_SUCCESS(hr)) {
-    //	return STATUS_SUCCESS;
-
-    return hr;
-  }
-  return STATUS_SUCCESS;
-}
-
-NTSTATUS
-FSInstanceQueryTeardown(_In_ PCFLT_RELATED_OBJECTS FltObjects,
-                        _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
-/*++
-
-Routine Description:
-
-This is called when an instance is being manually deleted by a
-call to FltDetachVolume or FilterDetach thereby giving us a
-chance to fail that detach request.
-
-If this routine is not defined in the registration structure, explicit
-detach requests via FltDetachVolume or FilterDetach will always be
-failed.
-
-Arguments:
-
-FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
-opaque handles to this filter, instance and its associated volume.
-
-Flags - Indicating where this detached request came from.
-
-Return Value:
-
-Returns the status of this operation.
-
---*/
-{
-  UNREFERENCED_PARAMETER(FltObjects);
-  UNREFERENCED_PARAMETER(Flags);
-
-  DbgPrint("snFilter: Entered FSInstanceQueryTeardown\n");
-
-  return STATUS_SUCCESS;
-}
-
-VOID FSInstanceTeardownStart(_In_ PCFLT_RELATED_OBJECTS FltObjects,
-                             _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags)
-/*++
-
-Routine Description:
-
-This routine is called at the start of instance teardown.
-
-Arguments:
-
-FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
-opaque handles to this filter, instance and its associated volume.
-
-Flags - Reason why this instance is being deleted.
-
-Return Value:
-
-None.
-
---*/
-{
-  UNREFERENCED_PARAMETER(FltObjects);
-  UNREFERENCED_PARAMETER(Flags);
-
-  DbgPrint("snFilter: Entered FSInstanceTeardownStart\n");
-}
-
-VOID FSInstanceTeardownComplete(_In_ PCFLT_RELATED_OBJECTS FltObjects,
-                                _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags)
-/*++
-
-Routine Description:
-
-This routine is called at the end of instance teardown.
-
-Arguments:
-
-FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
-opaque handles to this filter, instance and its associated volume.
-
-Flags - Reason why this instance is being deleted.
-
-Return Value:
-
-None.
-
---*/
-{
-  UNREFERENCED_PARAMETER(FltObjects);
-  UNREFERENCED_PARAMETER(Flags);
-  DbgPrint("snFilter: Entered FSInstanceTeardownComplete\n");
-}
-
-FLT_PREOP_CALLBACK_STATUS
-FSPreOperation(_Inout_ PFLT_CALLBACK_DATA Data,
-               _In_ PCFLT_RELATED_OBJECTS FltObjects,
-               _Flt_CompletionContext_Outptr_ PVOID
-
-                   *CompletionContext)
-/*++
-
-Routine Description:
-
-    Pre operations callback
-
-Arguments:
-
-    Data - The structure which describes the operation parameters.
-
-    FltObject - The structure which describes the objects affected by this
-        operation.
-
-    CompletionContext - Output parameter which can be used to pass a context
-        from this pre-create callback to the post-create callback.
-
-Return Value:
-
-   FLT_PREOP_SUCCESS_WITH_CALLBACK - If this is not our user-mode process.
-   FLT_PREOP_SUCCESS_NO_CALLBACK - All other threads.
-
---*/
-{
-  NTSTATUS hr = STATUS_SUCCESS;
-  //  See if this "create" is being done by our user process.
-  if (FltGetRequestorProcessId(Data) == 4)
-    return FLT_PREOP_SUCCESS_NO_CALLBACK; // system process-skip
-  if (FltGetRequestorProcessId(Data) == driverData->getPID()) {
-    if (IS_DEBUG_IRP)
-      DbgPrint(
-          "!!! snFilter: Allowing pre op for trusted process, no post op\n");
-
-    return FLT_PREOP_SUCCESS_NO_CALLBACK;
-  }
-  if (FltObjects->FileObject == NULL) { // no file object
-    return FLT_PREOP_SUCCESS_NO_CALLBACK;
-  }
-  // create tested only on post-op, can't check here
-  if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
-    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
-  }
-  hr = FSProcessPreOperartion(Data, FltObjects, CompletionContext);
-  if (hr == FLT_PREOP_SUCCESS_WITH_CALLBACK)
-    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
-
-  return FLT_PREOP_SUCCESS_NO_CALLBACK;
-}
-
-NTSTATUS
-FSProcessPreOperartion(_Inout_ PFLT_CALLBACK_DATA Data,
-                       _In_ PCFLT_RELATED_OBJECTS FltObjects,
-                       _Flt_CompletionContext_Outptr_ PVOID
-
-                           *CompletionContext) {
-  // no communication
-  if (driverData->
-
-      isFilterClosed()
-
-      ||
-
-      IsCommClosed()
-
-  ) {
-    // DbgPrint("!!! snFilter: Filter is closed, or Port is closed, skipping
-    // data\n");
-    return FLT_PREOP_SUCCESS_NO_CALLBACK;
-  }
-  NTSTATUS hr = FLT_PREOP_SUCCESS_NO_CALLBACK;
-
-  PFLT_FILE_NAME_INFORMATION nameInfo;
-  hr = FltGetFileNameInformation(
-      Data,
-      FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
-      &nameInfo);
-  if (!NT_SUCCESS(hr))
-    return hr;
-
-  BOOLEAN isDir;
-  hr = FltIsDirectory(Data->Iopb->TargetFileObject, Data->Iopb->TargetInstance,
-                      &isDir);
-  if (!NT_SUCCESS(hr))
-    return hr;
-  if (isDir)
-    return FLT_PREOP_SUCCESS_NO_CALLBACK;
-  PIRP_ENTRY newEntry = new IRP_ENTRY();
-  if (newEntry == NULL) {
-    FltReferenceFileNameInformation(nameInfo);
-    return hr;
-  }
-  // reset
-  PDRIVER_MESSAGE newItem = &newEntry->data;
-  PUNICODE_STRING FilePath = &(newEntry->filePath);
-
-  hr = GetFileNameInfo(FltObjects, FilePath, nameInfo);
-  if (!NT_SUCCESS(hr)) {
-    FltReferenceFileNameInformation(nameInfo);
-    delete newEntry;
-    return hr;
-  }
-
-  // get pid
-  newItem->PID = FltGetRequestorProcessId(Data);
-
-  BOOLEAN isGidFound;
-  ULONGLONG gid = driverData->GetProcessGid(newItem->PID, &isGidFound);
-  if (gid == 0 || !isGidFound) {
-    if (IS_DEBUG_IRP)
-      DbgPrint("!!! snFilter: Item does not have a gid, skipping\n");
-    FltReferenceFileNameInformation(nameInfo);
-    delete newEntry;
-    return FLT_PREOP_SUCCESS_NO_CALLBACK;
-  }
-  newItem->Gid = gid;
-
-  if (IS_DEBUG_IRP)
-    DbgPrint("!!! snFilter: Registering new irp for Gid: %d with pid: %d\n",
-             (int)gid, newItem->PID);
-
-  // get file id
-  hr = CopyFileIdInfo(Data, newItem);
-  if (!NT_SUCCESS(hr)) {
-    FltReferenceFileNameInformation(nameInfo);
-    delete newEntry;
-    return hr;
-  }
-
-  if (FSIsFileNameInScanDirs(FilePath)) {
-    if (IS_DEBUG_IRP)
-      DbgPrint("!!! snFilter: File in scan area \n");
-    newItem->FileLocationInfo = FILE_PROTECTED;
-  }
-
-  if (Data->Iopb->MajorFunction == IRP_MJ_READ ||
-      Data->Iopb->MajorFunction == IRP_MJ_WRITE) {
-    CopyExtension(newItem->Extension, nameInfo);
-  }
-
-  if (IS_DEBUG_IRP)
-    DbgPrint("!!! snFilter: Logging IRP op: %s \n",
-             FltGetIrpName(Data->Iopb->MajorFunction));
-
-  if (Data->Iopb->MajorFunction != IRP_MJ_SET_INFORMATION)
-    FltReleaseFileNameInformation(nameInfo);
-
-  switch (Data->Iopb->MajorFunction) {
-  // create is handled on post-operation, read is created here but calculated on
-  // post(data avilable
-  case IRP_MJ_READ: {
-    newItem->IRP_OP = IRP_READ;
-    if (Data->Iopb->Parameters.Read.Length == 0) // no data to read
-    {
-      delete newEntry;
-      DbgPrint("snFilter: IRP READ NOCALLBACK LENGTH IS ZERO! \n");
-      return FLT_PREOP_SUCCESS_NO_CALLBACK;
-    }
-    if (IS_DEBUG_IRP)
-      DbgPrint("!!! snFilter: Preop IRP_MJ_READ, return with postop \n");
-    // save context for post, we calculate the entropy of read, we pass the irp
-    // to application on post-op
-    *CompletionContext = newEntry;
-    DbgPrint("snFilter: IRP READ WITH CALLBACK! ****************** \n");
-    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
-  }
-  case IRP_MJ_CLEANUP:
-    newItem->IRP_OP = IRP_CLEANUP;
-    break;
-  case IRP_MJ_WRITE: {
-    newItem->IRP_OP = IRP_WRITE;
-    // if (newItem->FileLocationInfo == FILE_NOT_PROTECTED) {
-    //	delete newEntry;
-    //	return FLT_PREOP_SUCCESS_NO_CALLBACK;
-    // }
-    newItem->FileChange = FILE_CHANGE_WRITE;
-    PVOID writeBuffer = NULL;
-    if (Data->Iopb->Parameters.Write.Length == 0) // no data to write
-    {
-      break;
-    }
-
-    // prepare buffer for entropy calc
-    if (Data->Iopb->Parameters.Write.MdlAddress ==
-        NULL) { // there's mdl buffer, we use it
-      writeBuffer = Data->Iopb->Parameters.Write.WriteBuffer;
-    } else {
-      writeBuffer = MmGetSystemAddressForMdlSafe(
-          Data->Iopb->Parameters.Write.MdlAddress,
-          NormalPagePriority | MdlMappingNoExecute);
-    }
-    if (writeBuffer == NULL) { // alloc failed
-      delete newEntry;
-      // fail the irp request
-      Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
-      Data->IoStatus.Information = 0;
-      return FLT_PREOP_COMPLETE;
-    }
-    newItem->MemSizeUsed = Data->Iopb->Parameters.Write.Length;
-
-    // we catch EXCEPTION_EXECUTE_HANDLER so to prevent crash when calculating
-    KFLOATING_SAVE SaveState;
-    NTSTATUS Status = KeSaveFloatingPointState(&SaveState);
-    if (NT_SUCCESS(Status)) {
-      __try {
-        newItem->Entropy =
-            shannonEntropy((PUCHAR)writeBuffer, newItem->MemSizeUsed);
-        newItem->isEntropyCalc = TRUE;
-      } __except (EXCEPTION_EXECUTE_HANDLER) {
-        if (IS_DEBUG_IRP)
-          DbgPrint("!!! snFilter: Failed to calc entropy\n");
-        delete newEntry;
-        // fail the irp request
-        Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
-        Data->IoStatus.Information = 0;
-        return FLT_PREOP_COMPLETE;
-      }
-    } else {
-      if (IS_DEBUG_IRP)
-        DbgPrint("!!! snFilter: Failed to calc entropy\n");
-      delete newEntry;
-      // fail the irp request
-      Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
-      Data->IoStatus.Information = 0;
-      return FLT_PREOP_COMPLETE;
-    }
-    KeRestoreFloatingPointState(&SaveState);
-  } break;
-  case IRP_MJ_SET_INFORMATION: {
-    newItem->IRP_OP = IRP_SETINFO;
-    // we check for delete later and renaming
-    FILE_INFORMATION_CLASS fileInfo =
-        Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
-
-    if (fileInfo == FileDispositionInformation && // handle delete later
-        (((PFILE_DISPOSITION_INFORMATION)(Data->Iopb->Parameters
-                                              .SetFileInformation.InfoBuffer))
-             ->DeleteFile)) {
-      newItem->FileChange = FILE_CHANGE_DELETE_FILE;
-    } // end delete 1
-
-    else if (fileInfo == FileDispositionInformationEx &&
-             FlagOn(((PFILE_DISPOSITION_INFORMATION_EX)(Data->Iopb->Parameters
-                                                            .SetFileInformation
-                                                            .InfoBuffer))
-                        ->Flags,
-                    FILE_DISPOSITION_DELETE)) {
-      newItem->FileChange = FILE_CHANGE_DELETE_FILE;
-    } // end delete 2
-
-    else if (fileInfo == FileRenameInformation ||
-             fileInfo == FileRenameInformationEx) {
-      // OPTIONAL: get new name?
-
-      newItem->FileChange = FILE_CHANGE_RENAME_FILE;
-      PFILE_RENAME_INFORMATION renameInfo =
-          (PFILE_RENAME_INFORMATION)
-              Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
-      PFLT_FILE_NAME_INFORMATION newNameInfo;
-      WCHAR Buffer[MAX_FILE_NAME_LENGTH];
-      UNICODE_STRING NewFilePath;
-      NewFilePath.Buffer = Buffer;
-      NewFilePath.Length = 0;
-      NewFilePath.MaximumLength = MAX_FILE_NAME_SIZE;
-
-      hr = FltGetDestinationFileNameInformation(
-          FltObjects->Instance, FltObjects->FileObject,
-          renameInfo->RootDirectory, renameInfo->FileName,
-          renameInfo->FileNameLength,
-          FLT_FILE_NAME_QUERY_DEFAULT |
-              FLT_FILE_NAME_REQUEST_FROM_CURRENT_PROVIDER |
-              FLT_FILE_NAME_OPENED,
-          &newNameInfo);
-      if (!NT_SUCCESS(hr)) {
-        delete newEntry;
-        FltReleaseFileNameInformation(nameInfo);
-        return hr;
-      }
-
-      NTSTATUS status = GetFileNameInfo(FltObjects, &NewFilePath, newNameInfo);
-      if (!NT_SUCCESS(status)) {
-        delete newEntry;
-        FltReleaseFileNameInformation(nameInfo);
-        FltReleaseFileNameInformation(newNameInfo);
-        return FLT_PREOP_SUCCESS_NO_CALLBACK;
-      }
-
-      RtlCopyBytes(newEntry->Buffer, Buffer,
-                   MAX_FILE_NAME_SIZE); // replace buffer data with new file
-      newItem->FileLocationInfo = FILE_MOVED_OUT;
-      /*
-      if (FSIsFileNameInScanDirs(&NewFilePath)) {
-      if (newItem->FileLocationInfo == FILE_NOT_PROTECTED) { // moved in -
-      report new file name newItem->FileLocationInfo = FILE_MOVED_IN;
-      //newEntry->filePath = NewFilePath; // remember file moved in
-      RtlCopyBytes(newEntry->Buffer, Buffer, MAX_FILE_NAME_SIZE); // replace
-      buffer data with new file } // else we still report old file name, so we
-      know it was changed
-      }
-      else { // new file name not protected
-      if (newItem->FileLocationInfo == FILE_PROTECTED) { // moved out - report
-      old file name newItem->FileLocationInfo = FILE_MOVED_OUT;
-      }
-      /*else { // we dont care - rename of file in unprotected area to
-      unprotected area delete newEntry; FltReleaseFileNameInformation(nameInfo);
-      FltReleaseFileNameInformation(newNameInfo);
-      return FLT_PREOP_SUCCESS_NO_CALLBACK;
-      }
-      }
-      */
-
-      CopyExtension(newItem->Extension, newNameInfo);
-      FltReleaseFileNameInformation(newNameInfo);
-      for (LONG i = 0; i < FILE_OBJEC_MAX_EXTENSION_SIZE; i++) {
-        if (i == (nameInfo->Extension.Length / 2))
-          break;
-        if (newItem->Extension[i] != nameInfo->Extension.Buffer[i]) {
-          newItem->FileChange = FILE_CHANGE_EXTENSION_CHANGED;
-          break;
-        }
-      }
-      FltReleaseFileNameInformation(nameInfo);
-    }    // end rename
-    else // not rename or delete (set info)
-    {
-      delete newEntry;
-      FltReleaseFileNameInformation(nameInfo);
-      return FLT_PREOP_SUCCESS_NO_CALLBACK;
-    }
-    break;
-  }
-  default:
-    delete newEntry;
-    return FLT_PREOP_SUCCESS_NO_CALLBACK;
-  }
-  if (IS_DEBUG_IRP)
-    DbgPrint("!!! snFilter: Adding entry to irps %s\n",
-             FltGetIrpName(Data->Iopb->MajorFunction));
-  if (!driverData->AddIrpMessage(newEntry)) {
-    delete newEntry;
-  }
-  return FLT_PREOP_SUCCESS_NO_CALLBACK;
-}
-
-FLT_POSTOP_CALLBACK_STATUS
-FSPostOperation(_Inout_ PFLT_CALLBACK_DATA Data,
-                _In_ PCFLT_RELATED_OBJECTS FltObjects,
-                _In_opt_ PVOID CompletionContext,
-                _In_ FLT_POST_OPERATION_FLAGS Flags)
-/*++
-
-Routine Description:
-
-    Post-operation callback. we reach here in case of IRP_MJ_CREATE or
-IRP_MJ_READ
-
-Arguments:
-
-    Data - The structure which describes the operation parameters.
-
-    FltObject - The structure which describes the objects affected by this
-        operation.
-
-    CompletionContext - The operation context passed fron the pre-create
-        callback.
-
-    Flags - Flags to say why we are getting this post-operation callback.
-
-Return Value:
-
-    FLT_POSTOP_FINISHED_PROCESSING - ok to open the file, or we wish to deny
-                                     access to this file, hence undo the open
-
---*/
-{
-  // DbgPrint("!!! snFilter: Enter post op for irp: %s, pid of process: %u\n",
-  // FltGetIrpName(Data->Iopb->MajorFunction), FltGetRequestorProcessId(Data));
-  if (!NT_SUCCESS(Data->IoStatus.Status) ||
-      (STATUS_REPARSE == Data->IoStatus.Status)) {
-    // DbgPrint("!!! snFilter: finished post operation, already failed \n");
-    if (CompletionContext != nullptr &&
-        Data->Iopb->MajorFunction == IRP_MJ_READ) {
-      delete (PIRP_ENTRY)CompletionContext;
-    }
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
-    return FSProcessCreateIrp(Data, FltObjects);
-  } else if (Data->Iopb->MajorFunction == IRP_MJ_READ) {
-    // return FLT_POSTOP_FINISHED_PROCESSING;
-    return FSProcessPostReadIrp(Data, FltObjects, CompletionContext, Flags);
-  }
-  return FLT_POSTOP_FINISHED_PROCESSING;
-}
-
-FLT_POSTOP_CALLBACK_STATUS
-FSProcessCreateIrp(_Inout_ PFLT_CALLBACK_DATA Data,
-                   _In_ PCFLT_RELATED_OBJECTS FltObjects) {
-  NTSTATUS hr;
-  if (FlagOn(Data->Iopb->OperationFlags, SL_OPEN_TARGET_DIRECTORY) ||
-      FlagOn(Data->Iopb->OperationFlags, SL_OPEN_PAGING_FILE)) {
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  if (driverData->isFilterClosed() || IsCommClosed()) {
-    // DbgPrint("!!! snFilter: filter closed or comm closed, skip irp\n");
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  BOOLEAN isDir;
-  hr = FltIsDirectory(Data->Iopb->TargetFileObject, Data->Iopb->TargetInstance,
-                      &isDir);
-  if (!NT_SUCCESS(hr)) {
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  PFLT_FILE_NAME_INFORMATION nameInfo;
-  hr = FltGetFileNameInformation(
-      Data,
-      FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
-      &nameInfo);
-  if (!NT_SUCCESS(hr)) {
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  PIRP_ENTRY newEntry = new IRP_ENTRY();
-  if (newEntry == NULL) {
-    FltReleaseFileNameInformation(nameInfo);
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-  PDRIVER_MESSAGE newItem = &newEntry->data;
-
-  newItem->PID = FltGetRequestorProcessId(Data);
-  newItem->IRP_OP = IRP_CREATE;
-  newItem->FileLocationInfo = FILE_PROTECTED;
-  PUNICODE_STRING FilePath = &(newEntry->filePath);
-
-  BOOLEAN isGidFound;
-  ULONGLONG gid = driverData->GetProcessGid(newItem->PID, &isGidFound);
-  if (gid == 0 || !isGidFound) {
-    // DbgPrint("!!! snFilter: Item does not have a gid, skipping\n"); // TODO:
-    // incase it doesnt exist we can add it with our method that checks for
-    // system process
-    FltReferenceFileNameInformation(nameInfo);
-    delete newEntry;
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-  newItem->Gid = gid;
-  DbgPrint("!!! snFilter: Registering new irp for Gid: %d with pid: %d\n",
-           (int)gid,
-           newItem->PID); // TODO: incase it doesnt exist we can add it with our
-                          // method that checks for system process
-
-  // get file id
-  hr = CopyFileIdInfo(Data, newItem);
-  if (!NT_SUCCESS(hr)) {
-    delete newEntry;
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  hr = GetFileNameInfo(FltObjects, FilePath, nameInfo);
-  if (!NT_SUCCESS(hr)) {
-    delete newEntry;
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  CopyExtension(newItem->Extension, nameInfo);
-
-  FltReleaseFileNameInformation(nameInfo);
-
-  /*
-  if (!FSIsFileNameInScanDirs(FilePath)) {
-      if (IS_DEBUG_IRP) DbgPrint("!!! snFilter: Skipping uninterented file, not
-  in scan area \n"); delete newEntry; return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-  */
-
-  if (isDir && (Data->IoStatus.Information) == FILE_OPENED) {
-    if (IS_DEBUG_IRP)
-      DbgPrint("!!! snFilter: Dir listing opened on existing directory\n");
-    newItem->FileChange = FILE_OPEN_DIRECTORY;
-  } else if (isDir) {
-    if (IS_DEBUG_IRP)
-      DbgPrint("!!! snFilter: Dir but not listing, not important \n");
-    delete newEntry;
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  } else if ((Data->IoStatus.Information) == FILE_OVERWRITTEN ||
-             (Data->IoStatus.Information) == FILE_SUPERSEDED) {
-    newItem->FileChange = FILE_CHANGE_OVERWRITE_FILE;
-  } else if (FlagOn(Data->Iopb->Parameters.Create.Options,
-                    FILE_DELETE_ON_CLOSE)) {
-    newItem->FileChange = FILE_CHANGE_DELETE_FILE;
-    if ((Data->IoStatus.Information) == FILE_CREATED) {
-      newItem->FileChange = FILE_CHANGE_DELETE_NEW_FILE;
-    }
-  } else if ((Data->IoStatus.Information) == FILE_CREATED) {
-    newItem->FileChange = FILE_CHANGE_NEW_FILE;
-  }
-  if (IS_DEBUG_IRP)
-    DbgPrint("!!! snFilter: Adding entry to irps\n");
-  if (!driverData->AddIrpMessage(newEntry)) {
-    delete newEntry;
-  }
-  return FLT_POSTOP_FINISHED_PROCESSING;
-}
-
-FLT_POSTOP_CALLBACK_STATUS
-FSProcessPostReadIrp(_Inout_ PFLT_CALLBACK_DATA Data,
-                     _In_ PCFLT_RELATED_OBJECTS FltObjects,
-                     _In_opt_ PVOID CompletionContext,
-                     _In_ FLT_POST_OPERATION_FLAGS Flags) {
-  if (CompletionContext == NULL) {
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  PIRP_ENTRY entry = (PIRP_ENTRY)CompletionContext;
-
-  if (driverData->isFilterClosed() || IsCommClosed()) {
-    if (IS_DEBUG_IRP)
-      DbgPrint("!!! snFilter: Post op read, comm or filter closed\n");
-    delete entry;
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-
-  FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING;
-
-  PVOID ReadBuffer = NULL;
-
-  // prepare buffer for entropy calc
-  if (Data->Iopb->Parameters.Read.MdlAddress !=
-      NULL) { // there's mdl buffer, we use it
-    ReadBuffer =
-        MmGetSystemAddressForMdlSafe(Data->Iopb->Parameters.Read.MdlAddress,
-                                     NormalPagePriority | MdlMappingNoExecute);
-  } else if (FlagOn(Data->Flags, FLTFL_CALLBACK_DATA_SYSTEM_BUFFER)) // safe
-  {
-    ReadBuffer = Data->Iopb->Parameters.Read.ReadBuffer;
-  } else {
-    if (FltDoCompletionProcessingWhenSafe(
-            Data, FltObjects, CompletionContext, Flags, FSProcessPostReadSafe,
-            &status)) { // post to worker thread or run if irql is ok
-      return FLT_POSTOP_FINISHED_PROCESSING;
-    } else {
-      Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
-      Data->IoStatus.Information = 0;
-      delete entry;
-      return status;
-    }
-  }
-  if (!ReadBuffer) {
-    delete entry;
-    Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
-    Data->IoStatus.Information = 0;
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-  entry->data.MemSizeUsed =
-      (ULONG)Data->IoStatus.Information; // successful read data
-
-  // we catch EXCEPTION_EXECUTE_HANDLER so to prevent crash when calculating
-  KFLOATING_SAVE SaveState;
-  NTSTATUS Status = KeSaveFloatingPointState(&SaveState);
-  if (NT_SUCCESS(Status)) {
-    __try {
-      entry->data.Entropy =
-          shannonEntropy((PUCHAR)ReadBuffer, Data->IoStatus.Information);
-      entry->data.isEntropyCalc = TRUE;
-    } __except (EXCEPTION_EXECUTE_HANDLER) {
-      delete entry;
-      // fail the irp request
-      Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
-      Data->IoStatus.Information = 0;
-      return FLT_POSTOP_FINISHED_PROCESSING;
-    }
-  } else {
-    delete entry;
-    // fail the irp request
-    Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
-    Data->IoStatus.Information = 0;
-    return FLT_POSTOP_FINISHED_PROCESSING;
-  }
-  KeRestoreFloatingPointState(&SaveState);
-
-  if (IS_DEBUG_IRP)
-    DbgPrint("!!! snFilter: Adding entry to irps IRP_MJ_READ\n");
-  if (!driverData->AddIrpMessage(entry)) {
-    delete entry;
-  }
-  return FLT_POSTOP_FINISHED_PROCESSING;
-}
-
-FLT_POSTOP_CALLBACK_STATUS FSProcessPostReadSafe(
-    _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects,
-    _In_opt_ PVOID CompletionContext, _In_ FLT_POST_OPERATION_FLAGS Flags) {
-  UNREFERENCED_PARAMETER(Flags);
-  UNREFERENCED_PARAMETER(FltObjects);
-
-  NTSTATUS status = STATUS_SUCCESS;
-  PIRP_ENTRY entry = (PIRP_ENTRY)CompletionContext;
-  ASSERT(entry != nullptr);
-  status = FltLockUserBuffer(Data);
-  if (NT_SUCCESS(status)) {
-    PVOID ReadBuffer =
-        MmGetSystemAddressForMdlSafe(Data->Iopb->Parameters.Read.MdlAddress,
-                                     NormalPagePriority | MdlMappingNoExecute);
-    if (ReadBuffer != NULL) {
-      KFLOATING_SAVE SaveState;
-      NTSTATUS Status = KeSaveFloatingPointState(&SaveState);
-      if (NT_SUCCESS(Status)) {
-        __try {
-          if (entry != nullptr) {
-            entry->data.Entropy =
-                shannonEntropy((PUCHAR)ReadBuffer, Data->IoStatus.Information);
-            entry->data.MemSizeUsed = Data->IoStatus.Information;
-            entry->data.isEntropyCalc = TRUE;
-          }
-          if (IS_DEBUG_IRP)
-            DbgPrint("!!! snFilter: Adding entry to irps IRP_MJ_READ\n");
-          if (driverData->AddIrpMessage(entry)) {
-            return FLT_POSTOP_FINISHED_PROCESSING;
-          }
-        } __except (EXCEPTION_EXECUTE_HANDLER) {
-          status = STATUS_INTERNAL_ERROR;
-        }
-      } else {
-        status = STATUS_INTERNAL_ERROR;
-      }
-      KeRestoreFloatingPointState(&SaveState);
-    }
-    status = STATUS_INSUFFICIENT_RESOURCES;
-  }
-  delete entry;
-  return FLT_POSTOP_FINISHED_PROCESSING;
-}
-
-BOOLEAN
-FSIsFileNameInScanDirs(CONST PUNICODE_STRING path) {
-  // ASSERT(driverData != NULL);
-  return driverData->IsContainingDirectory(path);
-}
-
-NTSTATUS
-FSEntrySetFileName(CONST PFLT_VOLUME Volume,
-                   PFLT_FILE_NAME_INFORMATION nameInfo,
-                   PUNICODE_STRING uString) {
-  NTSTATUS hr = STATUS_SUCCESS;
-  PDEVICE_OBJECT devObject;
-  USHORT volumeDosNameSize;
-  USHORT finalNameSize;
-  USHORT volumeNameSize = nameInfo->Volume.Length; // in bytes
-  USHORT origNameSize = nameInfo->Name.Length;     // in bytes
-
-  WCHAR newTemp[40];
-
-  UNICODE_STRING volumeData;
-  volumeData.MaximumLength = 80;
-  volumeData.Buffer = newTemp;
-  volumeData.Length = 0;
-
-  hr = FltGetDiskDeviceObject(Volume, &devObject);
-  if (!NT_SUCCESS(hr)) {
-    return hr;
-  }
-  /*if (KeAreAllApcsDisabled()) {
-  return hr;
-  }*/
-
-  if (!
-
-      KeAreAllApcsDisabled()
-
-  ) {
-    hr = IoVolumeDeviceToDosName(devObject, &GvolumeData);
-  }
-  volumeDosNameSize = GvolumeData.Length;
-  finalNameSize = origNameSize - volumeNameSize +
-                  volumeDosNameSize; // not null terminated, in bytes
-
-  // DbgPrint("Volume name: %wZ, Size: %d, finalNameSize: %d, volumeNameSize:
-  // %d\n", volumeData, volumeDosNameSize, finalNameSize, volumeNameSize);
-  // DbgPrint("Name buffer: %wZ\n", nameInfo->Name);
-
-  if (uString == NULL) {
-    ObDereferenceObject(devObject);
-    return STATUS_INVALID_ADDRESS;
-  }
-  if (volumeNameSize ==
-      origNameSize) { // file is the volume, don't need to do anything
-    ObDereferenceObject(devObject);
-    return RtlUnicodeStringCopy(uString, &nameInfo->Name);
-  }
-
-  if (NT_SUCCESS(hr = RtlUnicodeStringCopy(
-                     uString, &GvolumeData))) { // prefix of volume e.g. C:
-
-    // DbgPrint("File name: %wZ\n", uString);
-    RtlCopyMemory(uString->Buffer + (volumeDosNameSize / 2),
-                  nameInfo->Name.Buffer + (volumeNameSize / 2),
-                  ((finalNameSize - volumeDosNameSize >
-                    MAX_FILE_NAME_SIZE - volumeDosNameSize)
-                       ? (MAX_FILE_NAME_SIZE - volumeDosNameSize)
-                       : (finalNameSize - volumeDosNameSize)));
-    uString->Length = (finalNameSize > MAX_FILE_NAME_SIZE) ? MAX_FILE_NAME_SIZE
-                                                           : finalNameSize;
-    // DbgPrint("File name: %wZ\n", uString);
-  }
-  ObDereferenceObject(devObject);
-  return hr;
-}
-
-NTSTATUS
-CopyFileIdInfo(_Inout_ PFLT_CALLBACK_DATA Data, PDRIVER_MESSAGE newItem) {
-  FILE_ID_INFORMATION fileInformation;
-  NTSTATUS hr = FltQueryInformationFile(
-      Data->Iopb->TargetInstance, Data->Iopb->TargetFileObject,
-      &fileInformation, sizeof(FILE_ID_INFORMATION), FileIdInformation, NULL);
-  RtlCopyMemory(&(newItem->FileID), &fileInformation,
-                sizeof(FILE_ID_INFORMATION));
-  return hr;
-}
-
-NTSTATUS GetFileNameInfo(_In_ PCFLT_RELATED_OBJECTS FltObjects,
-                         PUNICODE_STRING FilePath,
-                         PFLT_FILE_NAME_INFORMATION nameInfo) {
-  NTSTATUS hr;
-  hr = FltParseFileNameInformation(nameInfo);
-  if (!NT_SUCCESS(hr)) {
-    FltReleaseFileNameInformation(nameInfo);
-    return hr;
-  }
-  hr = FSEntrySetFileName(FltObjects->Volume, nameInfo, FilePath);
-  // DbgPrint("!!!snFilter DEBUG EntryFileName %d \n", NT_SUCCESS(hr));
-  if (!NT_SUCCESS(hr)) {
-    FltReleaseFileNameInformation(nameInfo);
-  }
-  return hr;
-}
-
-VOID CopyExtension(PWCHAR dest, PFLT_FILE_NAME_INFORMATION nameInfo) {
-  if (IS_DEBUG_IRP)
-    DbgPrint("!!! snFilter: copying the file type extension, extension length: "
-             "%d, name: %wZ\n",
-             nameInfo->Extension.Length, nameInfo->Extension);
-  RtlZeroBytes(dest, (FILE_OBJEC_MAX_EXTENSION_SIZE + 1) * sizeof(WCHAR));
-  for (LONG i = 0; i < FILE_OBJEC_MAX_EXTENSION_SIZE; i++) {
-    if (i == (nameInfo->Extension.Length / 2))
-      break;
-    dest[i] = nameInfo->Extension.Buffer[i];
-  }
-}
-
-static NTSTATUS GetProcessNameByHandle(_In_ HANDLE ProcessHandle,
-                                       _Out_ PUNICODE_STRING
-
-                                           *Name) {
-  ULONG retLength = 0;
-  ULONG pniSize = 512;
-  PUNICODE_STRING pni = NULL;
-  NTSTATUS status = STATUS_UNSUCCESSFUL;
-
-  do {
-    pni = (PUNICODE_STRING)ExAllocatePool2(POOL_FLAG_NON_PAGED, pniSize, 'RW');
-    if (pni != NULL) {
-      status = ZwQueryInformationProcess(ProcessHandle, ProcessImageFileName,
-                                         pni, pniSize, &retLength);
-      if (!NT_SUCCESS(status)) {
-        ExFreePoolWithTag(pni, 'RW');
-        pniSize *= 2;
-      }
-    } else
-      status = STATUS_INSUFFICIENT_RESOURCES;
-  } while (status == STATUS_INFO_LENGTH_MISMATCH);
-
-  if (NT_SUCCESS(status))
-    *Name = pni;
-
-  return status;
-}
-
-// new code process recording
-_IRQL_raises_(DISPATCH_LEVEL) VOID
-    AddRemProcessRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create) {
-  if (commHandle->CommClosed)
-    return;
-  if (Create) {
-    NTSTATUS hr;
-    if (ZwQueryInformationProcess == NULL) {
-      UNICODE_STRING routineName =
-          RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
-
-      ZwQueryInformationProcess =
-          (QUERY_INFO_PROCESS)MmGetSystemRoutineAddress(&routineName);
-
-      if (ZwQueryInformationProcess == NULL) {
-        DbgPrint("Cannot resolve ZwQueryInformationProcess\n");
-        hr = STATUS_UNSUCCESSFUL;
-        return;
-      }
-    }
-    HANDLE procHandleParent;
-    HANDLE procHandleProcess;
-
-    CLIENT_ID clientIdParent;
-    clientIdParent.UniqueProcess = ParentId;
-    clientIdParent.UniqueThread = 0;
-
-    CLIENT_ID clientIdProcess;
-    clientIdProcess.UniqueProcess = ProcessId;
-    clientIdProcess.UniqueThread = 0;
-
-    OBJECT_ATTRIBUTES objAttribs;
-
-    InitializeObjectAttributes(&objAttribs, NULL, OBJ_KERNEL_HANDLE, NULL,
-                               NULL);
-
-    hr = ZwOpenProcess(&procHandleParent, PROCESS_ALL_ACCESS, &objAttribs,
-                       &clientIdParent);
-    if (!NT_SUCCESS(hr)) {
-      DbgPrint("!!! snFilter: Failed to open process: %#010x.\n", hr);
-      return;
-    }
-    hr = ZwOpenProcess(&procHandleProcess, PROCESS_ALL_ACCESS, &objAttribs,
-                       &clientIdProcess);
-    if (!NT_SUCCESS(hr)) {
-      DbgPrint("!!! snFilter: Failed to open process: %#010x.\n", hr);
-      hr = FltClose(procHandleParent);
-      if (!NT_SUCCESS(hr)) {
-        DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
-        return;
-      }
-      return;
-    }
-
-    PUNICODE_STRING procName;
-    PUNICODE_STRING parentName;
-    hr = GetProcessNameByHandle(procHandleParent, &parentName);
-    if (!NT_SUCCESS(hr)) {
-      DbgPrint("!!! snFilter: Failed to get parent name: %#010x\n", hr);
-      return;
-    }
-    hr = GetProcessNameByHandle(procHandleProcess, &procName);
-    if (!NT_SUCCESS(hr)) {
-      DbgPrint("!!! snFilter: Failed to get process name: %#010x\n", hr);
-      return;
-    }
-
-    DbgPrint("!!! snFilter: New Process, parent: %wZ. Pid: %d\n", parentName,
-             (ULONG)(ULONG_PTR)ParentId);
-
-    hr = FltClose(procHandleParent);
-    if (!NT_SUCCESS(hr)) {
-      DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
-      return;
-    }
-    hr = FltClose(procHandleProcess);
-    if (!NT_SUCCESS(hr)) {
-      DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
-      return;
-    }
-    DbgPrint("!!! snFilter: New Process, process: %wZ , pid: %d.\n", procName,
-             (ULONG)(ULONG_PTR)ProcessId);
-
-    BOOLEAN found = FALSE;
-    if (startsWith(procName,
-                   driverData->GetSystemRootPath()) && // process in safe area
-        startsWith(parentName,
-                   driverData->GetSystemRootPath()) && // parent in safe area
-        (driverData->GetProcessGid((ULONG)(ULONG_PTR)ParentId, &found) == 0) &&
-        !found) // parent is not documented, if it was, there was a recursive
-                // call from a not safe process which
-    // resulted in safe are in windows dir
-    {
-      DbgPrint("!!! snFilter: Open Process not recorded, both parent and "
-               "process are safe\n");
-      delete parentName;
-      delete procName;
-      return;
-    }
-    // options to reach: a process is not safe (parent safe or not),
-    // process safe parent is not, both safe, but before
-    // parent there was an unsafe process
-    DbgPrint("!!! snFilter: Open Process recording, is parent safe: %d, is "
-             "process safe: %d\n",
-             startsWith(procName, driverData->GetSystemRootPath()),
-             startsWith(parentName, driverData->GetSystemRootPath()));
-    driverData->RecordNewProcess(procName, (ULONG)(ULONG_PTR)ProcessId,
-                                 (ULONG)(ULONG_PTR)ParentId);
-    delete parentName;
-  } else {
-    DbgPrint("!!! snFilter: Terminate Process, Process: %d pid\n",
-             (ULONG)(ULONG_PTR)ProcessId);
-    driverData->RemoveProcess((ULONG)(ULONG_PTR)ProcessId);
-  }
-}
-
-#pragma clang diagnostic pop
\ No newline at end of file
+#pragma clang diagnostic push
+#pragma ide diagnostic ignored "UnreachableCode"
+
+/*++
+
+Module Name:
+
+    snFilter.c
+
+Abstract:
+
+    This is the main module of the snFilter miniFilter driver.
+
+Environment:
+
+    Kernel mode
+
+--*/
+
+#include "snFilter.h"
+
+#pragma prefast(disable                                                        \
+                : __WARNING_ENCODE_MEMBER_FUNCTION_POINTER,                    \
+                  "Not valid for kernel mode drivers")
+
+#define POOL_FLAG_NON_PAGED 0x0000000000000040UI64 // Non paged pool NX
+
+//  Structure that contains all the global data structures used throughout the
+//  driver.
+
+EXTERN_C_START
+
+DRIVER_INITIALIZE DriverEntry;
+
+NTSTATUS
+DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
+
+EXTERN_C_END
+
+//
+//  Constant FLT_REGISTRATION structure for our filter.  This
+//  initializes the callback routines our filter wants to register
+//  for.  This is only used to register with the filter manager
+//
+
+CONST
+FLT_OPERATION_REGISTRATION Callbacks[] =
+    { //{IRP_MJ_CREATE, 0, FSPreOperation, FSPostOperation},
+        {IRP_MJ_CLOSE, 0, FSPreOperation, FSPostOperation},
+        {IRP_MJ_READ, 0, FSPreOperation, FSPostOperation},
+        //{IRP_MJ_CLEANUP, 0, FSPreOperation, NULL},
+        {IRP_MJ_WRITE, 0, FSPreOperation, NULL},
+        {IRP_MJ_SET_INFORMATION, 0, FSPreOperation, NULL},
+        {IRP_MJ_OPERATION_END}};
+
+/*++
+
+FilterRegistration Defines what we want to filter with the driver
+
+--*/
+CONST FLT_REGISTRATION FilterRegistration = {
+    sizeof(FLT_REGISTRATION),   //  Size
+    FLT_REGISTRATION_VERSION,   //  Version
+    0,                          //  Flags
+    NULL,                       //  Context Registration.
+    Callbacks,                  //  Operation callbacks
+    FSUnloadDriver,             //  FilterUnload
+    FSInstanceSetup,            //  InstanceSetup
+    FSInstanceQueryTeardown,    //  InstanceQueryTeardown
+    FSInstanceTeardownStart,    //  InstanceTeardownStart
+    FSInstanceTeardownComplete, //  InstanceTeardownComplete
+    NULL,                       //  GenerateFileName
+    NULL,                       //  GenerateDestinationFileName
+    NULL                        //  NormalizeNameComponent
+};
+
+////////////////////////////////////////////////////////////////////////////
+//
+//    Filter initialization and unload routines.
+//
+////////////////////////////////////////////////////////////////////////////
+
+DRIVER_INITIALIZE DriverEntry;
+
+NTSTATUS
+DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+/*++
+
+Routine Description:
+
+    This is the initialization routine for the Filter driver.  This
+    registers the Filter with the filter manager and initializes all
+    its global data structures.
+
+Arguments:
+
+    DriverObject - Pointer to a driver object created by the system to
+        represent this driver.
+
+    RegistryPath - Unicode string identifying where the parameters for this
+        driver are located in the registry.
+
+Return Value:
+
+    Returns STATUS_SUCCESS.
+--*/
+{
+  UNREFERENCED_PARAMETER(RegistryPath);
+  NTSTATUS status;
+
+  //
+  //  Default to NonPagedPoolNx for non paged pool allocations where supported.
+  //
+
+  ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+
+  //
+  //  Register with filter manager.
+  //
+
+  driverData = new DriverData(DriverObject);
+  if (driverData == NULL) {
+    return STATUS_MEMORY_NOT_ALLOCATED;
+  }
+
+  PFLT_FILTER *FilterAdd = driverData->getFilterAdd();
+
+  status = FltRegisterFilter(DriverObject, &FilterRegistration, FilterAdd);
+
+  if (!NT_SUCCESS(status)) {
+    delete driverData;
+    return status;
+  }
+
+  commHandle = new CommHandler(driverData->getFilter());
+  if (commHandle == NULL) {
+    delete driverData;
+    return STATUS_MEMORY_NOT_ALLOCATED;
+  }
+
+  status = InitCommData();
+
+  if (!NT_SUCCESS(status)) {
+    FltUnregisterFilter(driverData->
+
+                        getFilter()
+
+    );
+    delete driverData;
+    delete commHandle;
+    return status;
+  }
+  //
+  //  Start filtering I/O.
+  //
+  status = FltStartFiltering(driverData->getFilter());
+
+  if (!NT_SUCCESS(status)) {
+    CommClose();
+
+    FltUnregisterFilter(driverData->
+
+                        getFilter()
+
+    );
+    delete driverData;
+    delete commHandle;
+    return status;
+  }
+  driverData->
+
+      setFilterStart();
+
+  DbgPrint("loaded scanner successfully");
+  // new code
+  // TODO: check status and release in unload
+  PsSetCreateProcessNotifyRoutine(AddRemProcessRoutine, FALSE);
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FSUnloadDriver(_In_ FLT_FILTER_UNLOAD_FLAGS Flags)
+/*++
+
+Routine Description:
+
+    This is to unload routine for the Filter driver.This is unregistering the
+    Filter with the filter manager and frees any allocated global data
+    structures.
+
+Arguments:
+
+    None.
+
+Return Value:
+
+    Returns the final status of the de-allocation routines.
+
+--*/
+{
+  UNREFERENCED_PARAMETER(Flags);
+
+  //
+  //  Close the server port.
+  //
+  driverData->setFilterStop();
+  CommClose();
+
+  //
+  //  Unregister the filter
+  //
+
+  FltUnregisterFilter(driverData->getFilter());
+  delete driverData;
+  delete commHandle;
+  PsSetCreateProcessNotifyRoutine(AddRemProcessRoutine, TRUE);
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FSInstanceSetup(_In_ PCFLT_RELATED_OBJECTS FltObjects,
+                _In_ FLT_INSTANCE_SETUP_FLAGS Flags,
+                _In_ DEVICE_TYPE VolumeDeviceType,
+                _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType)
+/*++
+
+Routine Description:
+
+This routine is called whenever a new instance is created on a volume. This
+gives us a chance to decide if we need to attach to this volume or not.
+
+If this routine is not defined in the registration structure, automatic
+instances are always created.
+
+Arguments:
+
+FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
+opaque handles to this filter, instance and its associated volume.
+
+Flags - Flags describing the reason for this attach request.
+
+Return Value:
+
+STATUS_SUCCESS - attach
+STATUS_FLT_DO_NOT_ATTACH - do not attach
+
+--*/
+{
+  UNREFERENCED_PARAMETER(FltObjects);
+  UNREFERENCED_PARAMETER(Flags);
+  UNREFERENCED_PARAMETER(VolumeDeviceType);
+  UNREFERENCED_PARAMETER(VolumeFilesystemType);
+
+  DbgPrint("snFilter: Entered FSInstanceSetup\n");
+
+  WCHAR newTemp[40];
+
+  GvolumeData.MaximumLength = 80;
+  GvolumeData.Buffer = newTemp;
+  GvolumeData.Length = 0;
+
+  NTSTATUS hr = STATUS_SUCCESS;
+  PDEVICE_OBJECT devObject;
+  hr = FltGetDiskDeviceObject(FltObjects->Volume, &devObject);
+  if (!NT_SUCCESS(hr)) {
+    return STATUS_SUCCESS;
+    // return hr;
+  }
+  hr = IoVolumeDeviceToDosName(devObject, &GvolumeData);
+  if (!NT_SUCCESS(hr)) {
+    //	return STATUS_SUCCESS;
+
+    return hr;
+  }
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FSInstanceQueryTeardown(_In_ PCFLT_RELATED_OBJECTS FltObjects,
+                        _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
+/*++
+
+Routine Description:
+
+This is called when an instance is being manually deleted by a
+call to FltDetachVolume or FilterDetach thereby giving us a
+chance to fail that detach request.
+
+If this routine is not defined in the registration structure, explicit
+detach requests via FltDetachVolume or FilterDetach will always be
+failed.
+
+Arguments:
+
+FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
+opaque handles to this filter, instance and its associated volume.
+
+Flags - Indicating where this detached request came from.
+
+Return Value:
+
+Returns the status of this operation.
+
+--*/
+{
+  UNREFERENCED_PARAMETER(FltObjects);
+  UNREFERENCED_PARAMETER(Flags);
+
+  DbgPrint("snFilter: Entered FSInstanceQueryTeardown\n");
+
+  return STATUS_SUCCESS;
+}
+
+VOID FSInstanceTeardownStart(_In_ PCFLT_RELATED_OBJECTS FltObjects,
+                             _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags)
+/*++
+
+Routine Description:
+
+This routine is called at the start of instance teardown.
+
+Arguments:
+
+FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
+opaque handles to this filter, instance and its associated volume.
+
+Flags - Reason why this instance is being deleted.
+
+Return Value:
+
+None.
+
+--*/
+{
+  UNREFERENCED_PARAMETER(FltObjects);
+  UNREFERENCED_PARAMETER(Flags);
+
+  DbgPrint("snFilter: Entered FSInstanceTeardownStart\n");
+}
+
+VOID FSInstanceTeardownComplete(_In_ PCFLT_RELATED_OBJECTS FltObjects,
+                                _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags)
+/*++
+
+Routine Description:
+
+This routine is called at the end of instance teardown.
+
+Arguments:
+
+FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
+opaque handles to this filter, instance and its associated volume.
+
+Flags - Reason why this instance is being deleted.
+
+Return Value:
+
+None.
+
+--*/
+{
+  UNREFERENCED_PARAMETER(FltObjects);
+  UNREFERENCED_PARAMETER(Flags);
+  DbgPrint("snFilter: Entered FSInstanceTeardownComplete\n");
+}
+
+FLT_PREOP_CALLBACK_STATUS
+FSPreOperation(_Inout_ PFLT_CALLBACK_DATA Data,
+               _In_ PCFLT_RELATED_OBJECTS FltObjects,
+               _Flt_CompletionContext_Outptr_ PVOID
+
+                   *CompletionContext)
+/*++
+
+Routine Description:
+
+    Pre operations callback
+
+Arguments:
+
+    Data - The structure which describes the operation parameters.
+
+    FltObject - The structure which describes the objects affected by this
+        operation.
+
+    CompletionContext - Output parameter which can be used to pass a context
+        from this pre-create callback to the post-create callback.
+
+Return Value:
+
+   FLT_PREOP_SUCCESS_WITH_CALLBACK - If this is not our user-mode process.
+   FLT_PREOP_SUCCESS_NO_CALLBACK - All other threads.
+
+--*/
+{
+  NTSTATUS hr = STATUS_SUCCESS;
+  //  See if this "create" is being done by our user process.
+  if (FltGetRequestorProcessId(Data) == 4)
+    return FLT_PREOP_SUCCESS_NO_CALLBACK; // system process-skip
+  if (FltGetRequestorProcessId(Data) == driverData->getPID()) {
+    if (IS_DEBUG_IRP)
+      DbgPrint(
+          "!!! snFilter: Allowing pre op for trusted process, no post op\n");
+
+    return FLT_PREOP_SUCCESS_NO_CALLBACK;
+  }
+  if (FltObjects->FileObject == NULL) { // no file object
+    return FLT_PREOP_SUCCESS_NO_CALLBACK;
+  }
+  // create tested only on post-op, can't check here
+  if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
+    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
+  }
+  hr = FSProcessPreOperartion(Data, FltObjects, CompletionContext);
+  if (hr == FLT_PREOP_SUCCESS_WITH_CALLBACK)
+    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
+
+  return FLT_PREOP_SUCCESS_NO_CALLBACK;
+}
+
+NTSTATUS
+FSProcessPreOperartion(_Inout_ PFLT_CALLBACK_DATA Data,
+                       _In_ PCFLT_RELATED_OBJECTS FltObjects,
+                       _Flt_CompletionContext_Outptr_ PVOID
+
+                           *CompletionContext) {
+  // no communication
+  if (driverData->
+
+      isFilterClosed()
+
+      ||
+
+      IsCommClosed()
+
+  ) {
+    // DbgPrint("!!! snFilter: Filter is closed, or Port is closed, skipping
+    // data\n");
+    return FLT_PREOP_SUCCESS_NO_CALLBACK;
+  }
+  NTSTATUS hr = FLT_PREOP_SUCCESS_NO_CALLBACK;
+
+  PFLT_FILE_NAME_INFORMATION nameInfo;
+  hr = FltGetFileNameInformation(
+      Data,
+      FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
+      &nameInfo);
+  if (!NT_SUCCESS(hr))
+    return hr;
+
+  BOOLEAN isDir;
+  hr = FltIsDirectory(Data->Iopb->TargetFileObject, Data->Iopb->TargetInstance,
+                      &isDir);
+  if (!NT_SUCCESS(hr))
+    return hr;
+  if (isDir)
+    return FLT_PREOP_SUCCESS_NO_CALLBACK;
+  PIRP_ENTRY newEntry = new IRP_ENTRY();
+  if (newEntry == NULL) {
+    FltReferenceFileNameInformation(nameInfo);
+    return hr;
+  }
+  // reset
+  PDRIVER_MESSAGE newItem = &newEntry->data;
+  PUNICODE_STRING FilePath = &(newEntry->filePath);
+
+  hr = GetFileNameInfo(FltObjects, FilePath, nameInfo);
+  if (!NT_SUCCESS(hr)) {
+    FltReferenceFileNameInformation(nameInfo);
+    delete newEntry;
+    return hr;
+  }
+
+  // get pid
+  newItem->PID = FltGetRequestorProcessId(Data);
+
+  BOOLEAN isGidFound;
+  ULONGLONG gid = driverData->GetProcessGid(newItem->PID, &isGidFound);
+  if (gid == 0 || !isGidFound) {
+    if (IS_DEBUG_IRP)
+      DbgPrint("!!! snFilter: Item does not have a gid, skipping\n");
+    FltReferenceFileNameInformation(nameInfo);
+    delete newEntry;
+    return FLT_PREOP_SUCCESS_NO_CALLBACK;
+  }
+  newItem->Gid = gid;
+
+  if (IS_DEBUG_IRP)
+    DbgPrint("!!! snFilter: Registering new irp for Gid: %d with pid: %d\n",
+             (int)gid, newItem->PID);
+
+  // get file id
+  hr = CopyFileIdInfo(Data, newItem);
+  if (!NT_SUCCESS(hr)) {
+    FltReferenceFileNameInformation(nameInfo);
+    delete newEntry;
+    return hr;
+  }
+
+  if (FSIsFileNameInScanDirs(FilePath)) {
+    if (IS_DEBUG_IRP)
+      DbgPrint("!!! snFilter: File in scan area \n");
+    newItem->FileLocationInfo = FILE_PROTECTED;
+  }
+
+  if (Data->Iopb->MajorFunction == IRP_MJ_READ ||
+      Data->Iopb->MajorFunction == IRP_MJ_WRITE) {
+    CopyExtension(newItem->Extension, nameInfo);
+  }
+
+  if (IS_DEBUG_IRP)
+    DbgPrint("!!! snFilter: Logging IRP op: %s \n",
+             FltGetIrpName(Data->Iopb->MajorFunction));
+
+  if (Data->Iopb->MajorFunction != IRP_MJ_SET_INFORMATION)
+    FltReleaseFileNameInformation(nameInfo);
+
+  switch (Data->Iopb->MajorFunction) {
+  // create is handled on post-operation, read is created here but calculated on
+  // post(data avilable
+  case IRP_MJ_READ: {
+    newItem->IRP_OP = IRP_READ;
+    if (Data->Iopb->Parameters.Read.Length == 0) // no data to read
+    {
+      delete newEntry;
+      DbgPrint("snFilter: IRP READ NOCALLBACK LENGTH IS ZERO! \n");
+      return FLT_PREOP_SUCCESS_NO_CALLBACK;
+    }
+    if (IS_DEBUG_IRP)
+      DbgPrint("!!! snFilter: Preop IRP_MJ_READ, return with postop \n");
+    // save context for post, we calculate the entropy of read, we pass the irp
+    // to application on post-op
+    *CompletionContext = newEntry;
+    DbgPrint("snFilter: IRP READ WITH CALLBACK! ****************** \n");
+    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
+  }
+  case IRP_MJ_CLEANUP:
+    newItem->IRP_OP = IRP_CLEANUP;
+    break;
+  case IRP_MJ_WRITE: {
+    newItem->IRP_OP = IRP_WRITE;
+    // if (newItem->FileLocationInfo == FILE_NOT_PROTECTED) {
+    //	delete newEntry;
+    //	return FLT_PREOP_SUCCESS_NO_CALLBACK;
+    // }
+    newItem->FileChange = FILE_CHANGE_WRITE;
+    PVOID writeBuffer = NULL;
+    if (Data->Iopb->Parameters.Write.Length == 0) // no data to write
+    {
+      break;
+    }
+
+    // prepare buffer for entropy calc
+    if (Data->Iopb->Parameters.Write.MdlAddress ==
+        NULL) { // there's mdl buffer, we use it
+      writeBuffer = Data->Iopb->Parameters.Write.WriteBuffer;
+    } else {
+      writeBuffer = MmGetSystemAddressForMdlSafe(
+          Data->Iopb->Parameters.Write.MdlAddress,
+          NormalPagePriority | MdlMappingNoExecute);
+    }
+    if (writeBuffer == NULL) { // alloc failed
+      delete newEntry;
+      // fail the irp request
+      Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+      Data->IoStatus.Information = 0;
+      return FLT_PREOP_COMPLETE;
+    }
+    newItem->MemSizeUsed = Data->Iopb->Parameters.Write.Length;
+
+    // we catch EXCEPTION_EXECUTE_HANDLER so to prevent crash when calculating
+    KFLOATING_SAVE SaveState;
+    NTSTATUS Status = KeSaveFloatingPointState(&SaveState);
+    if (NT_SUCCESS(Status)) {
+      __try {
+        newItem->Entropy =
+            shannonEntropy((PUCHAR)writeBuffer, newItem->MemSizeUsed);
+        newItem->isEntropyCalc = TRUE;
+      } __except (EXCEPTION_EXECUTE_HANDLER) {
+        if (IS_DEBUG_IRP)
+          DbgPrint("!!! snFilter: Failed to calc entropy\n");
+        delete newEntry;
+        // fail the irp request
+        Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
+        Data->IoStatus.Information = 0;
+        return FLT_PREOP_COMPLETE;
+      }
+    } else {
+      if (IS_DEBUG_IRP)
+        DbgPrint("!!! snFilter: Failed to calc entropy\n");
+      delete newEntry;
+      // fail the irp request
+      Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
+      Data->IoStatus.Information = 0;
+      return FLT_PREOP_COMPLETE;
+    }
+    KeRestoreFloatingPointState(&SaveState);
+  } break;
+  case IRP_MJ_SET_INFORMATION: {
+    newItem->IRP_OP = IRP_SETINFO;
+    // we check for delete later and renaming
+    FILE_INFORMATION_CLASS fileInfo =
+        Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
+
+    if (fileInfo == FileDispositionInformation && // handle delete later
+        (((PFILE_DISPOSITION_INFORMATION)(Data->Iopb->Parameters
+                                              .SetFileInformation.InfoBuffer))
+             ->DeleteFile)) {
+      newItem->FileChange = FILE_CHANGE_DELETE_FILE;
+    } // end delete 1
+
+    else if (fileInfo == FileDispositionInformationEx &&
+             FlagOn(((PFILE_DISPOSITION_INFORMATION_EX)(Data->Iopb->Parameters
+                                                            .SetFileInformation
+                                                            .InfoBuffer))
+                        ->Flags,
+                    FILE_DISPOSITION_DELETE)) {
+      newItem->FileChange = FILE_CHANGE_DELETE_FILE;
+    } // end delete 2
+
+    else if (fileInfo == FileRenameInformation ||
+             fileInfo == FileRenameInformationEx) {
+      // OPTIONAL: get new name?
+
+      newItem->FileChange = FILE_CHANGE_RENAME_FILE;
+      PFILE_RENAME_INFORMATION renameInfo =
+          (PFILE_RENAME_INFORMATION)
+              Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
+      PFLT_FILE_NAME_INFORMATION newNameInfo;
+      WCHAR Buffer[MAX_FILE_NAME_LENGTH];
+      UNICODE_STRING NewFilePath;
+      NewFilePath.Buffer = Buffer;
+      NewFilePath.Length = 0;
+      NewFilePath.MaximumLength = MAX_FILE_NAME_SIZE;
+
+      hr = FltGetDestinationFileNameInformation(
+          FltObjects->Instance, FltObjects->FileObject,
+          renameInfo->RootDirectory, renameInfo->FileName,
+          renameInfo->FileNameLength,
+          FLT_FILE_NAME_QUERY_DEFAULT |
+              FLT_FILE_NAME_REQUEST_FROM_CURRENT_PROVIDER |
+              FLT_FILE_NAME_OPENED,
+          &newNameInfo);
+      if (!NT_SUCCESS(hr)) {
+        delete newEntry;
+        FltReleaseFileNameInformation(nameInfo);
+        return hr;
+      }
+
+      NTSTATUS status = GetFileNameInfo(FltObjects, &NewFilePath, newNameInfo);
+      if (!NT_SUCCESS(status)) {
+        delete newEntry;
+        FltReleaseFileNameInformation(nameInfo);
+        FltReleaseFileNameInformation(newNameInfo);
+        return FLT_PREOP_SUCCESS_NO_CALLBACK;
+      }
+
+      RtlCopyBytes(newEntry->Buffer, Buffer,
+                   MAX_FILE_NAME_SIZE); // replace buffer data with new file
+      newItem->FileLocationInfo = FILE_MOVED_OUT;
+      /*
+      if (FSIsFileNameInScanDirs(&NewFilePath)) {
+      if (newItem->FileLocationInfo == FILE_NOT_PROTECTED) { // moved in -
+      report new file name newItem->FileLocationInfo = FILE_MOVED_IN;
+      //newEntry->filePath = NewFilePath; // remember file moved in
+      RtlCopyBytes(newEntry->Buffer, Buffer, MAX_FILE_NAME_SIZE); // replace
+      buffer data with new file } // else we still report old file name, so we
+      know it was changed
+      }
+      else { // new file name not protected
+      if (newItem->FileLocationInfo == FILE_PROTECTED) { // moved out - report
+      old file name newItem->FileLocationInfo = FILE_MOVED_OUT;
+      }
+      /*else { // we dont care - rename of file in unprotected area to
+      unprotected area delete newEntry; FltReleaseFileNameInformation(nameInfo);
+      FltReleaseFileNameInformation(newNameInfo);
+      return FLT_PREOP_SUCCESS_NO_CALLBACK;
+      }
+      }
+      */
+
+      CopyExtension(newItem->Extension, newNameInfo);
+      FltReleaseFileNameInformation(newNameInfo);
+      for (LONG i = 0; i < FILE_OBJEC_MAX_EXTENSION_SIZE; i++) {
+        if (i == (nameInfo->Extension.Length / 2))
+          break;
+        if (newItem->Extension[i] != nameInfo->Extension.Buffer[i]) {
+          newItem->FileChange = FILE_CHANGE_EXTENSION_CHANGED;
+          break;
+        }
+      }
+      FltReleaseFileNameInformation(nameInfo);
+    }    // end rename
+    else // not rename or delete (set info)
+    {
+      delete newEntry;
+      FltReleaseFileNameInformation(nameInfo);
+      return FLT_PREOP_SUCCESS_NO_CALLBACK;
+    }
+    break;
+  }
+  default:
+    delete newEntry;
+    return FLT_PREOP_SUCCESS_NO_CALLBACK;
+  }
+  if (IS_DEBUG_IRP)
+    DbgPrint("!!! snFilter: Adding entry to irps %s\n",
+             FltGetIrpName(Data->Iopb->MajorFunction));
+  if (!driverData->AddIrpMessage(newEntry)) {
+    delete newEntry;
+  }
+  return FLT_PREOP_SUCCESS_NO_CALLBACK;
+}
+
+FLT_POSTOP_CALLBACK_STATUS
+FSPostOperation(_Inout_ PFLT_CALLBACK_DATA Data,
+                _In_ PCFLT_RELATED_OBJECTS FltObjects,
+                _In_opt_ PVOID CompletionContext,
+                _In_ FLT_POST_OPERATION_FLAGS Flags)
+/*++
+
+Routine Description:
+
+    Post-operation callback. we reach here in case of IRP_MJ_CREATE or
+IRP_MJ_READ
+
+Arguments:
+
+    Data - The structure which describes the operation parameters.
+
+    FltObject - The structure which describes the objects affected by this
+        operation.
+
+    CompletionContext - The operation context passed fron the pre-create
+        callback.
+
+    Flags - Flags to say why we are getting this post-operation callback.
+
+Return Value:
+
+    FLT_POSTOP_FINISHED_PROCESSING - ok to open the file, or we wish to deny
+                                     access to this file, hence undo the open
+
+--*/
+{
+  // DbgPrint("!!! snFilter: Enter post op for irp: %s, pid of process: %u\n",
+  // FltGetIrpName(Data->Iopb->MajorFunction), FltGetRequestorProcessId(Data));
+  if (!NT_SUCCESS(Data->IoStatus.Status) ||
+      (STATUS_REPARSE == Data->IoStatus.Status)) {
+    // DbgPrint("!!! snFilter: finished post operation, already failed \n");
+    if (CompletionContext != nullptr &&
+        Data->Iopb->MajorFunction == IRP_MJ_READ) {
+      delete (PIRP_ENTRY)CompletionContext;
+    }
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
+    return FSProcessCreateIrp(Data, FltObjects);
+  } else if (Data->Iopb->MajorFunction == IRP_MJ_READ) {
+    // return FLT_POSTOP_FINISHED_PROCESSING;
+    return FSProcessPostReadIrp(Data, FltObjects, CompletionContext, Flags);
+  }
+  return FLT_POSTOP_FINISHED_PROCESSING;
+}
+
+FLT_POSTOP_CALLBACK_STATUS
+FSProcessCreateIrp(_Inout_ PFLT_CALLBACK_DATA Data,
+                   _In_ PCFLT_RELATED_OBJECTS FltObjects) {
+  NTSTATUS hr;
+  if (FlagOn(Data->Iopb->OperationFlags, SL_OPEN_TARGET_DIRECTORY) ||
+      FlagOn(Data->Iopb->OperationFlags, SL_OPEN_PAGING_FILE)) {
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  if (driverData->isFilterClosed() || IsCommClosed()) {
+    // DbgPrint("!!! snFilter: filter closed or comm closed, skip irp\n");
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  BOOLEAN isDir;
+  hr = FltIsDirectory(Data->Iopb->TargetFileObject, Data->Iopb->TargetInstance,
+                      &isDir);
+  if (!NT_SUCCESS(hr)) {
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  PFLT_FILE_NAME_INFORMATION nameInfo;
+  hr = FltGetFileNameInformation(
+      Data,
+      FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
+      &nameInfo);
+  if (!NT_SUCCESS(hr)) {
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  PIRP_ENTRY newEntry = new IRP_ENTRY();
+  if (newEntry == NULL) {
+    FltReleaseFileNameInformation(nameInfo);
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+  PDRIVER_MESSAGE newItem = &newEntry->data;
+
+  newItem->PID = FltGetRequestorProcessId(Data);
+  newItem->IRP_OP = IRP_CREATE;
+  newItem->FileLocationInfo = FILE_PROTECTED;
+  PUNICODE_STRING FilePath = &(newEntry->filePath);
+
+  BOOLEAN isGidFound;
+  ULONGLONG gid = driverData->GetProcessGid(newItem->PID, &isGidFound);
+  if (gid == 0 || !isGidFound) {
+    // DbgPrint("!!! snFilter: Item does not have a gid, skipping\n"); // TODO:
+    // incase it doesnt exist we can add it with our method that checks for
+    // system process
+    FltReferenceFileNameInformation(nameInfo);
+    delete newEntry;
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+  newItem->Gid = gid;
+  DbgPrint("!!! snFilter: Registering new irp for Gid: %d with pid: %d\n",
+           (int)gid,
+           newItem->PID); // TODO: incase it doesnt exist we can add it with our
+                          // method that checks for system process
+
+  // get file id
+  hr = CopyFileIdInfo(Data, newItem);
+  if (!NT_SUCCESS(hr)) {
+    delete newEntry;
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  hr = GetFileNameInfo(FltObjects, FilePath, nameInfo);
+  if (!NT_SUCCESS(hr)) {
+    delete newEntry;
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  CopyExtension(newItem->Extension, nameInfo);
+
+  FltReleaseFileNameInformation(nameInfo);
+
+  /*
+  if (!FSIsFileNameInScanDirs(FilePath)) {
+      if (IS_DEBUG_IRP) DbgPrint("!!! snFilter: Skipping uninterented file, not
+  in scan area \n"); delete newEntry; return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+  */
+
+  if (isDir && (Data->IoStatus.Information) == FILE_OPENED) {
+    if (IS_DEBUG_IRP)
+      DbgPrint("!!! snFilter: Dir listing opened on existing directory\n");
+    newItem->FileChange = FILE_OPEN_DIRECTORY;
+  } else if (isDir) {
+    if (IS_DEBUG_IRP)
+      DbgPrint("!!! snFilter: Dir but not listing, not important \n");
+    delete newEntry;
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  } else if ((Data->IoStatus.Information) == FILE_OVERWRITTEN ||
+             (Data->IoStatus.Information) == FILE_SUPERSEDED) {
+    newItem->FileChange = FILE_CHANGE_OVERWRITE_FILE;
+  } else if (FlagOn(Data->Iopb->Parameters.Create.Options,
+                    FILE_DELETE_ON_CLOSE)) {
+    newItem->FileChange = FILE_CHANGE_DELETE_FILE;
+    if ((Data->IoStatus.Information) == FILE_CREATED) {
+      newItem->FileChange = FILE_CHANGE_DELETE_NEW_FILE;
+    }
+  } else if ((Data->IoStatus.Information) == FILE_CREATED) {
+    newItem->FileChange = FILE_CHANGE_NEW_FILE;
+  }
+  if (IS_DEBUG_IRP)
+    DbgPrint("!!! snFilter: Adding entry to irps\n");
+  if (!driverData->AddIrpMessage(newEntry)) {
+    delete newEntry;
+  }
+  return FLT_POSTOP_FINISHED_PROCESSING;
+}
+
+FLT_POSTOP_CALLBACK_STATUS
+FSProcessPostReadIrp(_Inout_ PFLT_CALLBACK_DATA Data,
+                     _In_ PCFLT_RELATED_OBJECTS FltObjects,
+                     _In_opt_ PVOID CompletionContext,
+                     _In_ FLT_POST_OPERATION_FLAGS Flags) {
+  if (CompletionContext == NULL) {
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  PIRP_ENTRY entry = (PIRP_ENTRY)CompletionContext;
+
+  if (driverData->isFilterClosed() || IsCommClosed()) {
+    if (IS_DEBUG_IRP)
+      DbgPrint("!!! snFilter: Post op read, comm or filter closed\n");
+    delete entry;
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+
+  FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING;
+
+  PVOID ReadBuffer = NULL;
+
+  // prepare buffer for entropy calc
+  if (Data->Iopb->Parameters.Read.MdlAddress !=
+      NULL) { // there's mdl buffer, we use it
+    ReadBuffer =
+        MmGetSystemAddressForMdlSafe(Data->Iopb->Parameters.Read.MdlAddress,
+                                     NormalPagePriority | MdlMappingNoExecute);
+  } else if (FlagOn(Data->Flags, FLTFL_CALLBACK_DATA_SYSTEM_BUFFER)) // safe
+  {
+    ReadBuffer = Data->Iopb->Parameters.Read.ReadBuffer;
+  } else {
+    if (FltDoCompletionProcessingWhenSafe(
+            Data, FltObjects, CompletionContext, Flags, FSProcessPostReadSafe,
+            &status)) { // post to worker thread or run if irql is ok
+      return FLT_POSTOP_FINISHED_PROCESSING;
+    } else {
+      Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
+      Data->IoStatus.Information = 0;
+      delete entry;
+      return status;
+    }
+  }
+  if (!ReadBuffer) {
+    delete entry;
+    Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+    Data->IoStatus.Information = 0;
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+  entry->data.MemSizeUsed =
+      (ULONG)Data->IoStatus.Information; // successful read data
+
+  // we catch EXCEPTION_EXECUTE_HANDLER so to prevent crash when calculating
+  KFLOATING_SAVE SaveState;
+  NTSTATUS Status = KeSaveFloatingPointState(&SaveState);
+  if (NT_SUCCESS(Status)) {
+    __try {
+      entry->data.Entropy =
+          shannonEntropy((PUCHAR)ReadBuffer, Data->IoStatus.Information);
+      entry->data.isEntropyCalc = TRUE;
+    } __except (EXCEPTION_EXECUTE_HANDLER) {
+      delete entry;
+      // fail the irp request
+      Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
+      Data->IoStatus.Information = 0;
+      return FLT_POSTOP_FINISHED_PROCESSING;
+    }
+  } else {
+    delete entry;
+    // fail the irp request
+    Data->IoStatus.Status = STATUS_INTERNAL_ERROR;
+    Data->IoStatus.Information = 0;
+    return FLT_POSTOP_FINISHED_PROCESSING;
+  }
+  KeRestoreFloatingPointState(&SaveState);
+
+  if (IS_DEBUG_IRP)
+    DbgPrint("!!! snFilter: Adding entry to irps IRP_MJ_READ\n");
+  if (!driverData->AddIrpMessage(entry)) {
+    delete entry;
+  }
+  return FLT_POSTOP_FINISHED_PROCESSING;
+}
+
+FLT_POSTOP_CALLBACK_STATUS FSProcessPostReadSafe(
+    _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects,
+    _In_opt_ PVOID CompletionContext, _In_ FLT_POST_OPERATION_FLAGS Flags) {
+  UNREFERENCED_PARAMETER(Flags);
+  UNREFERENCED_PARAMETER(FltObjects);
+
+  NTSTATUS status = STATUS_SUCCESS;
+  PIRP_ENTRY entry = (PIRP_ENTRY)CompletionContext;
+  ASSERT(entry != nullptr);
+  status = FltLockUserBuffer(Data);
+  if (NT_SUCCESS(status)) {
+    PVOID ReadBuffer =
+        MmGetSystemAddressForMdlSafe(Data->Iopb->Parameters.Read.MdlAddress,
+                                     NormalPagePriority | MdlMappingNoExecute);
+    if (ReadBuffer != NULL) {
+      KFLOATING_SAVE SaveState;
+      NTSTATUS Status = KeSaveFloatingPointState(&SaveState);
+      if (NT_SUCCESS(Status)) {
+        __try {
+          if (entry != nullptr) {
+            entry->data.Entropy =
+                shannonEntropy((PUCHAR)ReadBuffer, Data->IoStatus.Information);
+            entry->data.MemSizeUsed = Data->IoStatus.Information;
+            entry->data.isEntropyCalc = TRUE;
+          }
+          if (IS_DEBUG_IRP)
+            DbgPrint("!!! snFilter: Adding entry to irps IRP_MJ_READ\n");
+          if (driverData->AddIrpMessage(entry)) {
+            return FLT_POSTOP_FINISHED_PROCESSING;
+          }
+        } __except (EXCEPTION_EXECUTE_HANDLER) {
+          status = STATUS_INTERNAL_ERROR;
+        }
+      } else {
+        status = STATUS_INTERNAL_ERROR;
+      }
+      KeRestoreFloatingPointState(&SaveState);
+    }
+    status = STATUS_INSUFFICIENT_RESOURCES;
+  }
+  delete entry;
+  return FLT_POSTOP_FINISHED_PROCESSING;
+}
+
+BOOLEAN
+FSIsFileNameInScanDirs(CONST PUNICODE_STRING path) {
+  // ASSERT(driverData != NULL);
+  return driverData->IsContainingDirectory(path);
+}
+
+NTSTATUS
+FSEntrySetFileName(CONST PFLT_VOLUME Volume,
+                   PFLT_FILE_NAME_INFORMATION nameInfo,
+                   PUNICODE_STRING uString) {
+  NTSTATUS hr = STATUS_SUCCESS;
+  PDEVICE_OBJECT devObject;
+  USHORT volumeDosNameSize;
+  USHORT finalNameSize;
+  USHORT volumeNameSize = nameInfo->Volume.Length; // in bytes
+  USHORT origNameSize = nameInfo->Name.Length;     // in bytes
+
+  WCHAR newTemp[40];
+
+  UNICODE_STRING volumeData;
+  volumeData.MaximumLength = 80;
+  volumeData.Buffer = newTemp;
+  volumeData.Length = 0;
+
+  hr = FltGetDiskDeviceObject(Volume, &devObject);
+  if (!NT_SUCCESS(hr)) {
+    return hr;
+  }
+  /*if (KeAreAllApcsDisabled()) {
+  return hr;
+  }*/
+
+  if (!
+
+      KeAreAllApcsDisabled()
+
+  ) {
+    hr = IoVolumeDeviceToDosName(devObject, &GvolumeData);
+  }
+  volumeDosNameSize = GvolumeData.Length;
+  finalNameSize = origNameSize - volumeNameSize +
+                  volumeDosNameSize; // not null terminated, in bytes
+
+  // DbgPrint("Volume name: %wZ, Size: %d, finalNameSize: %d, volumeNameSize:
+  // %d\n", volumeData, volumeDosNameSize, finalNameSize, volumeNameSize);
+  // DbgPrint("Name buffer: %wZ\n", nameInfo->Name);
+
+  if (uString == NULL) {
+    ObDereferenceObject(devObject);
+    return STATUS_INVALID_ADDRESS;
+  }
+  if (volumeNameSize ==
+      origNameSize) { // file is the volume, don't need to do anything
+    ObDereferenceObject(devObject);
+    return RtlUnicodeStringCopy(uString, &nameInfo->Name);
+  }
+
+  if (NT_SUCCESS(hr = RtlUnicodeStringCopy(
+                     uString, &GvolumeData))) { // prefix of volume e.g. C:
+
+    // DbgPrint("File name: %wZ\n", uString);
+    RtlCopyMemory(uString->Buffer + (volumeDosNameSize / 2),
+                  nameInfo->Name.Buffer + (volumeNameSize / 2),
+                  ((finalNameSize - volumeDosNameSize >
+                    MAX_FILE_NAME_SIZE - volumeDosNameSize)
+                       ? (MAX_FILE_NAME_SIZE - volumeDosNameSize)
+                       : (finalNameSize - volumeDosNameSize)));
+    uString->Length = (finalNameSize > MAX_FILE_NAME_SIZE) ? MAX_FILE_NAME_SIZE
+                                                           : finalNameSize;
+    // DbgPrint("File name: %wZ\n", uString);
+  }
+  ObDereferenceObject(devObject);
+  return hr;
+}
+
+NTSTATUS
+CopyFileIdInfo(_Inout_ PFLT_CALLBACK_DATA Data, PDRIVER_MESSAGE newItem) {
+  FILE_ID_INFORMATION fileInformation;
+  NTSTATUS hr = FltQueryInformationFile(
+      Data->Iopb->TargetInstance, Data->Iopb->TargetFileObject,
+      &fileInformation, sizeof(FILE_ID_INFORMATION), FileIdInformation, NULL);
+  RtlCopyMemory(&(newItem->FileID), &fileInformation,
+                sizeof(FILE_ID_INFORMATION));
+  return hr;
+}
+
+NTSTATUS GetFileNameInfo(_In_ PCFLT_RELATED_OBJECTS FltObjects,
+                         PUNICODE_STRING FilePath,
+                         PFLT_FILE_NAME_INFORMATION nameInfo) {
+  NTSTATUS hr;
+  hr = FltParseFileNameInformation(nameInfo);
+  if (!NT_SUCCESS(hr)) {
+    FltReleaseFileNameInformation(nameInfo);
+    return hr;
+  }
+  hr = FSEntrySetFileName(FltObjects->Volume, nameInfo, FilePath);
+  // DbgPrint("!!!snFilter DEBUG EntryFileName %d \n", NT_SUCCESS(hr));
+  if (!NT_SUCCESS(hr)) {
+    FltReleaseFileNameInformation(nameInfo);
+  }
+  return hr;
+}
+
+VOID CopyExtension(PWCHAR dest, PFLT_FILE_NAME_INFORMATION nameInfo) {
+  if (IS_DEBUG_IRP)
+    DbgPrint("!!! snFilter: copying the file type extension, extension length: "
+             "%d, name: %wZ\n",
+             nameInfo->Extension.Length, nameInfo->Extension);
+  RtlZeroBytes(dest, (FILE_OBJEC_MAX_EXTENSION_SIZE + 1) * sizeof(WCHAR));
+  for (LONG i = 0; i < FILE_OBJEC_MAX_EXTENSION_SIZE; i++) {
+    if (i == (nameInfo->Extension.Length / 2))
+      break;
+    dest[i] = nameInfo->Extension.Buffer[i];
+  }
+}
+
+static NTSTATUS GetProcessNameByHandle(_In_ HANDLE ProcessHandle,
+                                       _Out_ PUNICODE_STRING
+
+                                           *Name) {
+  ULONG retLength = 0;
+  ULONG pniSize = 512;
+  PUNICODE_STRING pni = NULL;
+  NTSTATUS status = STATUS_UNSUCCESSFUL;
+
+  do {
+    pni = (PUNICODE_STRING)ExAllocatePool2(POOL_FLAG_NON_PAGED, pniSize, 'RW');
+    if (pni != NULL) {
+      status = ZwQueryInformationProcess(ProcessHandle, ProcessImageFileName,
+                                         pni, pniSize, &retLength);
+      if (!NT_SUCCESS(status)) {
+        ExFreePoolWithTag(pni, 'RW');
+        pniSize *= 2;
+      }
+    } else
+      status = STATUS_INSUFFICIENT_RESOURCES;
+  } while (status == STATUS_INFO_LENGTH_MISMATCH);
+
+  if (NT_SUCCESS(status))
+    *Name = pni;
+
+  return status;
+}
+
+// new code process recording
+_IRQL_raises_(DISPATCH_LEVEL) VOID
+    AddRemProcessRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create) {
+  if (commHandle->CommClosed)
+    return;
+  if (Create) {
+    NTSTATUS hr;
+    if (ZwQueryInformationProcess == NULL) {
+      UNICODE_STRING routineName =
+          RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
+
+      ZwQueryInformationProcess =
+          (QUERY_INFO_PROCESS)MmGetSystemRoutineAddress(&routineName);
+
+      if (ZwQueryInformationProcess == NULL) {
+        DbgPrint("Cannot resolve ZwQueryInformationProcess\n");
+        hr = STATUS_UNSUCCESSFUL;
+        return;
+      }
+    }
+    HANDLE procHandleParent;
+    HANDLE procHandleProcess;
+
+    CLIENT_ID clientIdParent;
+    clientIdParent.UniqueProcess = ParentId;
+    clientIdParent.UniqueThread = 0;
+
+    CLIENT_ID clientIdProcess;
+    clientIdProcess.UniqueProcess = ProcessId;
+    clientIdProcess.UniqueThread = 0;
+
+    OBJECT_ATTRIBUTES objAttribs;
+
+    InitializeObjectAttributes(&objAttribs, NULL, OBJ_KERNEL_HANDLE, NULL,
+                               NULL);
+
+    hr = ZwOpenProcess(&procHandleParent, PROCESS_ALL_ACCESS, &objAttribs,
+                       &clientIdParent);
+    if (!NT_SUCCESS(hr)) {
+      DbgPrint("!!! snFilter: Failed to open process: %#010x.\n", hr);
+      return;
+    }
+    hr = ZwOpenProcess(&procHandleProcess, PROCESS_ALL_ACCESS, &objAttribs,
+                       &clientIdProcess);
+    if (!NT_SUCCESS(hr)) {
+      DbgPrint("!!! snFilter: Failed to open process: %#010x.\n", hr);
+      hr = FltClose(procHandleParent);
+      if (!NT_SUCCESS(hr)) {
+        DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
+        return;
+      }
+      return;
+    }
+
+    PUNICODE_STRING procName;
+    PUNICODE_STRING parentName;
+    hr = GetProcessNameByHandle(procHandleParent, &parentName);
+    if (!NT_SUCCESS(hr)) {
+      DbgPrint("!!! snFilter: Failed to get parent name: %#010x\n", hr);
+      return;
+    }
+    hr = GetProcessNameByHandle(procHandleProcess, &procName);
+    if (!NT_SUCCESS(hr)) {
+      DbgPrint("!!! snFilter: Failed to get process name: %#010x\n", hr);
+      return;
+    }
+
+    DbgPrint("!!! snFilter: New Process, parent: %wZ. Pid: %d\n", parentName,
+             (ULONG)(ULONG_PTR)ParentId);
+
+    hr = FltClose(procHandleParent);
+    if (!NT_SUCCESS(hr)) {
+      DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
+      return;
+    }
+    hr = FltClose(procHandleProcess);
+    if (!NT_SUCCESS(hr)) {
+      DbgPrint("!!! snFilter: Failed to close process: %#010x.\n", hr);
+      return;
+    }
+    DbgPrint("!!! snFilter: New Process, process: %wZ , pid: %d.\n", procName,
+             (ULONG)(ULONG_PTR)ProcessId);
+
+    BOOLEAN found = FALSE;
+    if (startsWith(procName,
+                   driverData->GetSystemRootPath()) && // process in safe area
+        startsWith(parentName,
+                   driverData->GetSystemRootPath()) && // parent in safe area
+        (driverData->GetProcessGid((ULONG)(ULONG_PTR)ParentId, &found) == 0) &&
+        !found) // parent is not documented, if it was, there was a recursive
+                // call from a not safe process which
+    // resulted in safe are in windows dir
+    {
+      DbgPrint("!!! snFilter: Open Process not recorded, both parent and "
+               "process are safe\n");
+      delete parentName;
+      delete procName;
+      return;
+    }
+    // options to reach: a process is not safe (parent safe or not),
+    // process safe parent is not, both safe, but before
+    // parent there was an unsafe process
+    DbgPrint("!!! snFilter: Open Process recording, is parent safe: %d, is "
+             "process safe: %d\n",
+             startsWith(procName, driverData->GetSystemRootPath()),
+             startsWith(parentName, driverData->GetSystemRootPath()));
+    driverData->RecordNewProcess(procName, (ULONG)(ULONG_PTR)ProcessId,
+                                 (ULONG)(ULONG_PTR)ParentId);
+    delete parentName;
+  } else {
+    DbgPrint("!!! snFilter: Terminate Process, Process: %d pid\n",
+             (ULONG)(ULONG_PTR)ProcessId);
+    driverData->RemoveProcess((ULONG)(ULONG_PTR)ProcessId);
+  }
+}
+
+#pragma clang diagnostic pop
diff -ruN fsfilter-rs-0.8.0/minifilter/snFilter/snFilter.vcxproj fsfilter-rs-0.8.1/minifilter/snFilter/snFilter.vcxproj
--- fsfilter-rs-0.8.0/minifilter/snFilter/snFilter.vcxproj	2023-07-31 09:48:09.820589900 -0700
+++ fsfilter-rs-0.8.1/minifilter/snFilter/snFilter.vcxproj	2023-07-31 09:54:38.677779400 -0700
@@ -30,6 +30,9 @@
     <RootNamespace>snFilter</RootNamespace>
     <ProjectName>snFilter</ProjectName>
     <WindowsTargetPlatformVersion>10.0.22621.0</WindowsTargetPlatformVersion>
+    <RemoveDriver>False</RemoveDriver>
+    <InstallMode>CustomCommand</InstallMode>
+    <CommandLine>%SystemDrive%\DriverTest\Drivers\install.cmd</CommandLine>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@@ -88,7 +91,7 @@
       <WholeProgramOptimization>true</WholeProgramOptimization>
     </ClCompile>
     <DriverSign>
-      <FileDigestAlgorithm>SHA1</FileDigestAlgorithm>
+      <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>
     </DriverSign>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -114,6 +117,7 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <FilesToPackage Include="$(TargetPath)" />
+    <FilesToPackage Include="install.cmd" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Communication.h" />
@@ -124,6 +128,9 @@
     <ClInclude Include="KernelString.h" />
     <ClInclude Include="ShanonEntropy.h" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="install.cmd" />
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
diff -ruN fsfilter-rs-0.8.0/src/bin/minifilter.rs fsfilter-rs-0.8.1/src/bin/minifilter.rs
--- fsfilter-rs-0.8.0/src/bin/minifilter.rs	2023-07-31 09:48:10.140609400 -0700
+++ fsfilter-rs-0.8.1/src/bin/minifilter.rs	2023-07-12 11:30:38.625518400 -0700
@@ -42,7 +42,13 @@
         loop {
             if let Ok(mut io_message) = rx_iomsgs.recv() {
                 io_message.exepath();
-                write!(lock, "{io_message:?}");
+                writeln!(lock, "File:\n{:?}\n{:?}\n{:?}\n{:?}\n{:?}\n{:?}",
+                    io_message.filepathstr,
+                    io_message.extension,
+                    io_message.runtime_features.exepath,
+                    io_message.pid,
+                    io_message.irp_op,
+                    io_message.file_change);
                 lock.flush();
             }
         }
diff -ruN fsfilter-rs-0.8.0/src/shared_def.rs fsfilter-rs-0.8.1/src/shared_def.rs
--- fsfilter-rs-0.8.0/src/shared_def.rs	2023-07-31 09:48:10.120590600 -0700
+++ fsfilter-rs-0.8.1/src/shared_def.rs	2023-07-12 09:48:01.376654600 -0700
@@ -1,398 +1,398 @@
-//! Contains all definitions shared between this user-mode app and the minifilter in order to
-//! communicate properly. Those are C-representation of structures sent or received from the minifilter.
-
-use std::cmp::Ordering;
-use std::fmt;
-use std::os::raw::{c_uchar, c_ulong, c_ulonglong, c_ushort};
-use std::path::PathBuf;
-use std::time::SystemTime;
-
-use num_derive::FromPrimitive;
-use serde::{Deserialize, Serialize};
-use wchar::wchar_t;
-use windows::Win32::Foundation::{CloseHandle, GetLastError};
-use windows::Win32::Storage::FileSystem::FILE_ID_INFO;
-use windows::Win32::System::ProcessStatus::K32GetProcessImageFileNameA;
-use windows::Win32::System::Threading::{OpenProcess, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ};
-
-/// See [`IOMessage`] struct. Used with [`IrpSetInfo`](crate::driver_comm::IrpMajorOp::IrpSetInfo)
-#[derive(FromPrimitive)]
-#[repr(C)]
-pub enum FileChangeInfo {
-    FileChangeNotSet,
-    FileOpenDirectory,
-    FileChangeWrite,
-    FileChangeNewFile,
-    FileChangeRenameFile,
-    FileChangeExtensionChanged,
-    FileChangeDeleteFile,
-    /// Temp file: created and deleted on close
-    FileChangeDeleteNewFile,
-    FileChangeOverwriteFile,
-}
-
-/// See [`IOMessage`] struct.
-#[derive(FromPrimitive)]
-#[repr(C)]
-pub enum FileLocationInfo {
-    FileNotProtected,
-    FileProtected,
-    FileMovedIn,
-    FileMovedOut,
-}
-
-/// Low-level C-like object to communicate with the minifilter.
-/// The minifilter yields `ReplyIrp` objects (retrieved by [`get_irp`](crate::driver_comm::Driver::get_irp) to
-/// manage the fixed size of the *data buffer.
-/// In other words, a `ReplyIrp` is a collection of [`CDriverMsg`] with a capped size.
-#[derive(Debug, Copy, Clone)]
-#[repr(C)]
-pub struct ReplyIrp {
-    /// The size od the collection.
-    pub data_size: c_ulonglong,
-    /// The C pointer to the buffer containing the [`CDriverMsg`] events.
-    pub data: *const CDriverMsg,
-    /// The number of different operations in this collection.
-    pub num_ops: u64,
-}
-
-impl ReplyIrp {
-    /// Iterate through `self.data` and returns the collection of [`CDriverMsg`]
-    #[inline]
-    fn unpack_drivermsg(&self) -> Vec<&CDriverMsg> {
-        let mut res = vec![];
-        unsafe {
-            let mut msg = &*self.data;
-            res.push(msg);
-            for _ in 0..(self.num_ops) {
-                if msg.next.is_null() {
-                    break;
-                }
-                msg = &*msg.next;
-                res.push(msg);
-            }
-        }
-        res
-    }
-}
-
-/// This class is the straight Rust translation of the Win32 API
-/// [`UNICODE_STRING`](https://docs.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_unicode_string),
-/// returned by the driver.
-#[derive(Debug, Copy, Clone)]
-#[repr(C)]
-pub struct UnicodeString {
-    pub length: c_ushort,
-    pub maximum_length: c_ushort,
-    pub buffer: *const wchar_t,
-}
-
-impl UnicodeString {
-    /*
-    pub fn to_string(&self) -> String {
-        unsafe {
-            let str_slice = std::slice::from_raw_parts(self.buffer, self.length as usize);
-            let mut first_zero_index = 0;
-            for (i, c) in str_slice.iter().enumerate() {
-                if *c == 0 {
-                    first_zero_index = i;
-                    break;
-                }
-            }
-            String::from_utf16_lossy(&str_slice[..first_zero_index])
-        }
-    }
-    */
-
-    /// Get the file path from the `UnicodeString` path and the extension returned by the driver.
-    #[inline]
-    #[must_use]
-    pub fn to_string_ext(&self, extension: [wchar_t; 12]) -> String {
-        unsafe {
-            let str_slice = std::slice::from_raw_parts(self.buffer, self.length as usize);
-            let mut first_zero_index = 0;
-            let mut last_dot_index = 0;
-            let mut first_zero_index_ext = 0;
-
-            // Filepath
-            for (i, c) in str_slice.iter().enumerate() {
-                if *c == 46 {
-                    last_dot_index = i + 1;
-                }
-                if *c == 0 {
-                    first_zero_index = i;
-                    break;
-                }
-            }
-
-            if first_zero_index_ext > 0 && last_dot_index > 0 {
-                // Extension
-                for (i, c) in extension.iter().enumerate() {
-                    if *c == 0 {
-                        first_zero_index_ext = i;
-                        break;
-                    } else if *c != str_slice[last_dot_index + i] {
-                        first_zero_index_ext = 0;
-                        break;
-                    }
-                }
-                String::from_utf16_lossy(
-                    &[
-                        &str_slice[..last_dot_index],
-                        &extension[..first_zero_index_ext],
-                    ]
-                    .concat(),
-                )
-            } else {
-                String::from_utf16_lossy(&str_slice[..first_zero_index])
-            }
-        }
-    }
-}
-
-impl fmt::Display for UnicodeString {
-    #[inline]
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        unsafe {
-            let str_slice = std::slice::from_raw_parts(self.buffer, self.length as usize);
-            let mut first_zero_index = 0;
-            for (i, c) in str_slice.iter().enumerate() {
-                if *c == 0 {
-                    first_zero_index = i;
-                    break;
-                }
-            }
-            write!(
-                f,
-                "{}",
-                String::from_utf16_lossy(&str_slice[..first_zero_index])
-            )
-        }
-    }
-}
-
-/// Represents a driver message.
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[repr(C)]
-pub struct IOMessage {
-    /// The file extension
-    pub extension: [wchar_t; 12],
-    /// Hard Disk Volume Serial Number where the file is saved (from [`FILE_ID_INFO`])
-    pub file_id_vsn: c_ulonglong,
-    /// File ID on the disk ([`FILE_ID_INFO`])
-    pub file_id_id: [u8; 16],
-    /// Number of bytes transferred (`IO_STATUS_BLOCK.Information`)
-    pub mem_sized_used: c_ulonglong,
-    /// (Optional) File Entropy calculated by the driver
-    pub entropy: f64,
-    /// Pid responsible for this io activity
-    pub pid: c_ulong,
-    /// Windows IRP Type caught by the minifilter:
-    /// - NONE (0)
-    /// - READ (1)
-    /// - WRITE (2)
-    /// - SETINFO (3)
-    /// - CREATE (4)
-    /// - CLEANUP (5)
-    pub irp_op: c_uchar,
-    /// Is the entropy calculated?
-    pub is_entropy_calc: u8,
-    /// Type of i/o operation:
-    /// - FILE_CHANGE_NOT_SET (0)
-    /// - FILE_OPEN_DIRECTORY (1)
-    /// - FILE_CHANGE_WRITE (2)
-    /// - FILE_CHANGE_NEW_FILE (3)
-    /// - FILE_CHANGE_RENAME_FILE (4)
-    /// - FILE_CHANGE_EXTENSION_CHANGED (5)
-    /// - FILE_CHANGE_DELETE_FILE (6)
-    /// - FILE_CHANGE_DELETE_NEW_FILE (7)
-    /// - FILE_CHANGE_OVERWRITE_FILE (8)
-    pub file_change: c_uchar,
-    /// The driver has the ability to monitor specific directories only (feature currently not used):
-    /// - FILE_NOT_PROTECTED (0): Monitored dirs do not contained this file
-    /// - FILE_PROTECTED (1)
-    /// - FILE_MOVED_IN (2)
-    /// - FILE_MOVED_OUT (3)
-    pub file_location_info: c_uchar,
-    /// File path on the disk
-    pub filepathstr: String,
-    /// Group Identifier (maintained by the minifilter) of the operation
-    pub gid: c_ulonglong,
-    /// see class [`RuntimeFeatures`]
-    pub runtime_features: RuntimeFeatures,
-    /// Size of the file. Can be equal to -1 if the file path is not found.
-    pub file_size: i64,
-    /// Rough time at which the IRP was created
-    pub time: SystemTime,
-}
-
-impl IOMessage {
-    /// Make a new [`IOMessage`] from a received [`CDriverMsg`]
-    #[inline]
-    #[must_use]
-    pub fn from(c_drivermsg: &CDriverMsg) -> Self {
-        Self {
-            extension: c_drivermsg.extension,
-            file_id_vsn: c_drivermsg.file_id.VolumeSerialNumber,
-            file_id_id: c_drivermsg.file_id.FileId.Identifier,
-            mem_sized_used: c_drivermsg.mem_sized_used,
-            entropy: c_drivermsg.entropy,
-            pid: c_drivermsg.pid,
-            irp_op: c_drivermsg.irp_op,
-            is_entropy_calc: c_drivermsg.is_entropy_calc,
-            file_change: c_drivermsg.file_change,
-            file_location_info: c_drivermsg.file_location_info,
-            filepathstr: c_drivermsg.filepath.to_string_ext(c_drivermsg.extension),
-            gid: c_drivermsg.gid,
-            runtime_features: RuntimeFeatures::new(),
-            file_size: match PathBuf::from(
-                &c_drivermsg.filepath.to_string_ext(c_drivermsg.extension),
-            )
-            .metadata()
-            {
-                Ok(f) => f.len() as i64,
-                Err(_e) => -1,
-            },
-            time: SystemTime::now(),
-        }
-    }
-
-    /// Opens an existing local process object to retrieve the name of the executable file for the
-    /// specified process.
-    #[inline]
-    pub fn exepath(&mut self) {
-        let pid = self.pid;
-        unsafe {
-            let r_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid);
-            if let Ok(handle) = r_handle {
-                if !(handle.is_invalid() || handle.0 == 0) {
-                    let mut buffer: Vec<u8> = Vec::new();
-                    buffer.resize(1024, 0);
-                    let res = K32GetProcessImageFileNameA(handle, buffer.as_mut_slice());
-
-                    CloseHandle(handle);
-                    if res == 0 {
-                        let _errorcode = GetLastError().0;
-                    } else {
-                        let pathbuf = PathBuf::from(
-                            String::from_utf8_unchecked(buffer).trim_matches(char::from(0)),
-                        );
-                        self.runtime_features.exe_still_exists = true;
-                        self.runtime_features.exepath = pathbuf.file_name().map_or_else(
-                            || PathBuf::from(r"DEFAULT"),
-                            |filename| PathBuf::from(filename.to_string_lossy().to_string()),
-                        );
-                    }
-                    // dbg!(is_closed_handle);
-                }
-            }
-        }
-    }
-}
-
-impl Eq for IOMessage {}
-
-impl Ord for IOMessage {
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.time.cmp(&other.time)
-    }
-}
-
-impl PartialOrd for IOMessage {
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        Some(self.time.cmp(&other.time))
-    }
-}
-
-impl PartialEq for IOMessage {
-    fn eq(&self, other: &Self) -> bool {
-        self.time == other.time
-    }
-}
-
-/// Stores runtime features that come from our application (and not the minifilter).
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[repr(C)]
-pub struct RuntimeFeatures {
-    /// The path of the gid root process
-    pub exepath: PathBuf,
-    ///  Did the root exe file still existed (at the moment of this specific *DriverMessage* operation)?
-    pub exe_still_exists: bool,
-}
-
-impl RuntimeFeatures {
-    /// Make a new [`RuntimeFeatures`]
-    #[inline]
-    #[must_use]
-    pub fn new() -> Self {
-        Self {
-            exepath: PathBuf::new(),
-            exe_still_exists: true,
-        }
-    }
-}
-
-impl Default for RuntimeFeatures {
-    #[inline]
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-/// The C object returned by the minifilter, available through [`ReplyIrp`].
-/// It is low level and use C pointers logic which is not always compatible with RUST (in particular
-/// the lifetime of `*next`). That's why we convert it asap to a plain Rust [`IOMessage`] object.
-///
-/// `next` is null `(0x0)` when there is no [`IOMessage`] remaining.
-#[derive(Debug, Copy, Clone)]
-#[repr(C)]
-pub struct CDriverMsg {
-    pub extension: [wchar_t; 12],
-    pub file_id: FILE_ID_INFO,
-    pub mem_sized_used: c_ulonglong,
-    pub entropy: f64,
-    pub pid: c_ulong,
-    pub irp_op: c_uchar,
-    pub is_entropy_calc: u8,
-    pub file_change: c_uchar,
-    pub file_location_info: c_uchar,
-    pub filepath: UnicodeString,
-    pub gid: c_ulonglong,
-    /// null (0x0) when there is no [`IOMessage`] remaining
-    pub next: *const CDriverMsg,
-}
-
-/// To iterate easily over a collection of [`IOMessage`] received from the minifilter, before they are
-/// converted to [`IOMessage`].
-#[repr(C)]
-pub struct CDriverMsgs<'a> {
-    drivermsgs: Vec<&'a CDriverMsg>,
-    index: usize,
-}
-
-impl CDriverMsgs<'_> {
-    /// Make a new [`CDriverMsgs`] from a received [`ReplyIrp`]
-    #[inline]
-    #[must_use]
-    pub fn new(irp: &ReplyIrp) -> CDriverMsgs {
-        CDriverMsgs {
-            drivermsgs: irp.unpack_drivermsg(),
-            index: 0,
-        }
-    }
-}
-
-impl Iterator for CDriverMsgs<'_> {
-    type Item = CDriverMsg;
-
-    #[inline]
-    fn next(&mut self) -> Option<Self::Item> {
-        if self.index == self.drivermsgs.len() {
-            None
-        } else {
-            let res = *self.drivermsgs[self.index];
-            self.index += 1;
-            Some(res)
-        }
-    }
-}
+//! Contains all definitions shared between this user-mode app and the minifilter in order to
+//! communicate properly. Those are C-representation of structures sent or received from the minifilter.
+
+use std::cmp::Ordering;
+use std::fmt;
+use std::os::raw::{c_uchar, c_ulong, c_ulonglong, c_ushort};
+use std::path::PathBuf;
+use std::time::SystemTime;
+
+use num_derive::FromPrimitive;
+use serde::{Deserialize, Serialize};
+use wchar::wchar_t;
+use windows::Win32::Foundation::{CloseHandle, GetLastError};
+use windows::Win32::Storage::FileSystem::FILE_ID_INFO;
+use windows::Win32::System::ProcessStatus::K32GetProcessImageFileNameA;
+use windows::Win32::System::Threading::{OpenProcess, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ};
+
+/// See [`IOMessage`] struct. Used with [`IrpSetInfo`](crate::driver_comm::IrpMajorOp::IrpSetInfo)
+#[derive(FromPrimitive)]
+#[repr(C)]
+pub enum FileChangeInfo {
+    FileChangeNotSet,
+    FileOpenDirectory,
+    FileChangeWrite,
+    FileChangeNewFile,
+    FileChangeRenameFile,
+    FileChangeExtensionChanged,
+    FileChangeDeleteFile,
+    /// Temp file: created and deleted on close
+    FileChangeDeleteNewFile,
+    FileChangeOverwriteFile,
+}
+
+/// See [`IOMessage`] struct.
+#[derive(FromPrimitive)]
+#[repr(C)]
+pub enum FileLocationInfo {
+    FileNotProtected,
+    FileProtected,
+    FileMovedIn,
+    FileMovedOut,
+}
+
+/// Low-level C-like object to communicate with the minifilter.
+/// The minifilter yields `ReplyIrp` objects (retrieved by [`get_irp`](crate::driver_comm::Driver::get_irp) to
+/// manage the fixed size of the *data buffer.
+/// In other words, a `ReplyIrp` is a collection of [`CDriverMsg`] with a capped size.
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct ReplyIrp {
+    /// The size od the collection.
+    pub data_size: c_ulonglong,
+    /// The C pointer to the buffer containing the [`CDriverMsg`] events.
+    pub data: *const CDriverMsg,
+    /// The number of different operations in this collection.
+    pub num_ops: u64,
+}
+
+impl ReplyIrp {
+    /// Iterate through `self.data` and returns the collection of [`CDriverMsg`]
+    #[inline]
+    fn unpack_drivermsg(&self) -> Vec<&CDriverMsg> {
+        let mut res = vec![];
+        unsafe {
+            let mut msg = &*self.data;
+            res.push(msg);
+            for _ in 0..(self.num_ops) {
+                if msg.next.is_null() {
+                    break;
+                }
+                msg = &*msg.next;
+                res.push(msg);
+            }
+        }
+        res
+    }
+}
+
+/// This class is the straight Rust translation of the Win32 API
+/// [`UNICODE_STRING`](https://docs.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_unicode_string),
+/// returned by the driver.
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct UnicodeString {
+    pub length: c_ushort,
+    pub maximum_length: c_ushort,
+    pub buffer: *const wchar_t,
+}
+
+impl UnicodeString {
+    /*
+    pub fn to_string(&self) -> String {
+        unsafe {
+            let str_slice = std::slice::from_raw_parts(self.buffer, self.length as usize);
+            let mut first_zero_index = 0;
+            for (i, c) in str_slice.iter().enumerate() {
+                if *c == 0 {
+                    first_zero_index = i;
+                    break;
+                }
+            }
+            String::from_utf16_lossy(&str_slice[..first_zero_index])
+        }
+    }
+    */
+
+    /// Get the file path from the `UnicodeString` path and the extension returned by the driver.
+    #[inline]
+    #[must_use]
+    pub fn to_string_ext(&self, extension: [wchar_t; 24]) -> String {
+        unsafe {
+            let str_slice = std::slice::from_raw_parts(self.buffer, self.length as usize);
+            let mut first_zero_index = 0;
+            let mut last_dot_index = 0;
+            let mut first_zero_index_ext = 0;
+
+            // Filepath
+            for (i, c) in str_slice.iter().enumerate() {
+                if *c == 46 {
+                    last_dot_index = i + 1;
+                }
+                if *c == 0 {
+                    first_zero_index = i;
+                    break;
+                }
+            }
+
+            if first_zero_index_ext > 0 && last_dot_index > 0 {
+                // Extension
+                for (i, c) in extension.iter().enumerate() {
+                    if *c == 0 {
+                        first_zero_index_ext = i;
+                        break;
+                    } else if *c != str_slice[last_dot_index + i] {
+                        first_zero_index_ext = 0;
+                        break;
+                    }
+                }
+                String::from_utf16_lossy(
+                    &[
+                        &str_slice[..last_dot_index],
+                        &extension[..first_zero_index_ext],
+                    ]
+                    .concat(),
+                )
+            } else {
+                String::from_utf16_lossy(&str_slice[..first_zero_index])
+            }
+        }
+    }
+}
+
+impl fmt::Display for UnicodeString {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        unsafe {
+            let str_slice = std::slice::from_raw_parts(self.buffer, self.length as usize);
+            let mut first_zero_index = 0;
+            for (i, c) in str_slice.iter().enumerate() {
+                if *c == 0 {
+                    first_zero_index = i;
+                    break;
+                }
+            }
+            write!(
+                f,
+                "{}",
+                String::from_utf16_lossy(&str_slice[..first_zero_index])
+            )
+        }
+    }
+}
+
+/// Represents a driver message.
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[repr(C)]
+pub struct IOMessage {
+    /// The file extension
+    pub extension: [wchar_t; 24],
+    /// Hard Disk Volume Serial Number where the file is saved (from [`FILE_ID_INFO`])
+    pub file_id_vsn: c_ulonglong,
+    /// File ID on the disk ([`FILE_ID_INFO`])
+    pub file_id_id: [u8; 16],
+    /// Number of bytes transferred (`IO_STATUS_BLOCK.Information`)
+    pub mem_sized_used: c_ulonglong,
+    /// (Optional) File Entropy calculated by the driver
+    pub entropy: f64,
+    /// Pid responsible for this io activity
+    pub pid: c_ulong,
+    /// Windows IRP Type caught by the minifilter:
+    /// - NONE (0)
+    /// - READ (1)
+    /// - WRITE (2)
+    /// - SETINFO (3)
+    /// - CREATE (4)
+    /// - CLEANUP (5)
+    pub irp_op: c_uchar,
+    /// Is the entropy calculated?
+    pub is_entropy_calc: u8,
+    /// Type of i/o operation:
+    /// - FILE_CHANGE_NOT_SET (0)
+    /// - FILE_OPEN_DIRECTORY (1)
+    /// - FILE_CHANGE_WRITE (2)
+    /// - FILE_CHANGE_NEW_FILE (3)
+    /// - FILE_CHANGE_RENAME_FILE (4)
+    /// - FILE_CHANGE_EXTENSION_CHANGED (5)
+    /// - FILE_CHANGE_DELETE_FILE (6)
+    /// - FILE_CHANGE_DELETE_NEW_FILE (7)
+    /// - FILE_CHANGE_OVERWRITE_FILE (8)
+    pub file_change: c_uchar,
+    /// The driver has the ability to monitor specific directories only (feature currently not used):
+    /// - FILE_NOT_PROTECTED (0): Monitored dirs do not contained this file
+    /// - FILE_PROTECTED (1)
+    /// - FILE_MOVED_IN (2)
+    /// - FILE_MOVED_OUT (3)
+    pub file_location_info: c_uchar,
+    /// File path on the disk
+    pub filepathstr: String,
+    /// Group Identifier (maintained by the minifilter) of the operation
+    pub gid: c_ulonglong,
+    /// see class [`RuntimeFeatures`]
+    pub runtime_features: RuntimeFeatures,
+    /// Size of the file. Can be equal to -1 if the file path is not found.
+    pub file_size: i64,
+    /// Rough time at which the IRP was created
+    pub time: SystemTime,
+}
+
+impl IOMessage {
+    /// Make a new [`IOMessage`] from a received [`CDriverMsg`]
+    #[inline]
+    #[must_use]
+    pub fn from(c_drivermsg: &CDriverMsg) -> Self {
+        Self {
+            extension: c_drivermsg.extension,
+            file_id_vsn: c_drivermsg.file_id.VolumeSerialNumber,
+            file_id_id: c_drivermsg.file_id.FileId.Identifier,
+            mem_sized_used: c_drivermsg.mem_sized_used,
+            entropy: c_drivermsg.entropy,
+            pid: c_drivermsg.pid,
+            irp_op: c_drivermsg.irp_op,
+            is_entropy_calc: c_drivermsg.is_entropy_calc,
+            file_change: c_drivermsg.file_change,
+            file_location_info: c_drivermsg.file_location_info,
+            filepathstr: c_drivermsg.filepath.to_string_ext(c_drivermsg.extension),
+            gid: c_drivermsg.gid,
+            runtime_features: RuntimeFeatures::new(),
+            file_size: match PathBuf::from(
+                &c_drivermsg.filepath.to_string_ext(c_drivermsg.extension),
+            )
+            .metadata()
+            {
+                Ok(f) => f.len() as i64,
+                Err(_e) => -1,
+            },
+            time: SystemTime::now(),
+        }
+    }
+
+    /// Opens an existing local process object to retrieve the name of the executable file for the
+    /// specified process.
+    #[inline]
+    pub fn exepath(&mut self) {
+        let pid = self.pid;
+        unsafe {
+            let r_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid);
+            if let Ok(handle) = r_handle {
+                if !(handle.is_invalid() || handle.0 == 0) {
+                    let mut buffer: Vec<u8> = Vec::new();
+                    buffer.resize(1024, 0);
+                    let res = K32GetProcessImageFileNameA(handle, buffer.as_mut_slice());
+
+                    CloseHandle(handle);
+                    if res == 0 {
+                        let _errorcode = GetLastError().0;
+                    } else {
+                        let pathbuf = PathBuf::from(
+                            String::from_utf8_unchecked(buffer).trim_matches(char::from(0)),
+                        );
+                        self.runtime_features.exe_still_exists = true;
+                        self.runtime_features.exepath = pathbuf.file_name().map_or_else(
+                            || PathBuf::from(r"DEFAULT"),
+                            |filename| PathBuf::from(filename.to_string_lossy().to_string()),
+                        );
+                    }
+                    // dbg!(is_closed_handle);
+                }
+            }
+        }
+    }
+}
+
+impl Eq for IOMessage {}
+
+impl Ord for IOMessage {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.time.cmp(&other.time)
+    }
+}
+
+impl PartialOrd for IOMessage {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.time.cmp(&other.time))
+    }
+}
+
+impl PartialEq for IOMessage {
+    fn eq(&self, other: &Self) -> bool {
+        self.time == other.time
+    }
+}
+
+/// Stores runtime features that come from our application (and not the minifilter).
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[repr(C)]
+pub struct RuntimeFeatures {
+    /// The path of the gid root process
+    pub exepath: PathBuf,
+    ///  Did the root exe file still existed (at the moment of this specific *DriverMessage* operation)?
+    pub exe_still_exists: bool,
+}
+
+impl RuntimeFeatures {
+    /// Make a new [`RuntimeFeatures`]
+    #[inline]
+    #[must_use]
+    pub fn new() -> Self {
+        Self {
+            exepath: PathBuf::new(),
+            exe_still_exists: true,
+        }
+    }
+}
+
+impl Default for RuntimeFeatures {
+    #[inline]
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+/// The C object returned by the minifilter, available through [`ReplyIrp`].
+/// It is low level and use C pointers logic which is not always compatible with RUST (in particular
+/// the lifetime of `*next`). That's why we convert it asap to a plain Rust [`IOMessage`] object.
+///
+/// `next` is null `(0x0)` when there is no [`IOMessage`] remaining.
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct CDriverMsg {
+    pub extension: [wchar_t; 24],
+    pub file_id: FILE_ID_INFO,
+    pub mem_sized_used: c_ulonglong,
+    pub entropy: f64,
+    pub pid: c_ulong,
+    pub irp_op: c_uchar,
+    pub is_entropy_calc: u8,
+    pub file_change: c_uchar,
+    pub file_location_info: c_uchar,
+    pub filepath: UnicodeString,
+    pub gid: c_ulonglong,
+    /// null (0x0) when there is no [`IOMessage`] remaining
+    pub next: *const CDriverMsg,
+}
+
+/// To iterate easily over a collection of [`IOMessage`] received from the minifilter, before they are
+/// converted to [`IOMessage`].
+#[repr(C)]
+pub struct CDriverMsgs<'a> {
+    drivermsgs: Vec<&'a CDriverMsg>,
+    index: usize,
+}
+
+impl CDriverMsgs<'_> {
+    /// Make a new [`CDriverMsgs`] from a received [`ReplyIrp`]
+    #[inline]
+    #[must_use]
+    pub fn new(irp: &ReplyIrp) -> CDriverMsgs {
+        CDriverMsgs {
+            drivermsgs: irp.unpack_drivermsg(),
+            index: 0,
+        }
+    }
+}
+
+impl Iterator for CDriverMsgs<'_> {
+    type Item = CDriverMsg;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.index == self.drivermsgs.len() {
+            None
+        } else {
+            let res = *self.drivermsgs[self.index];
+            self.index += 1;
+            Some(res)
+        }
+    }
+}
