WNF while always maintaining WNF communication structure my usermode application similar to this c++ usermode aplication to not remove core functions off my C# code just make it similar strcuture

my c# aplication 
using System;
using NtApiDotNet;
using System.Threading;
using System.Runtime.InteropServices;
using System.Text;

namespace WnfSubscriber {
    class Program {
        // Define the WNF state name
        private const ulong MY_WNF_STATE_NAME = 0x41C64E6DA3BC1074;

        static void Main(string[] args)
        {
            WnfClient client = new WnfClient();

            // Subscribe to the WNF state
            client.SubscribeState(new WnfStateName(MY_WNF_STATE_NAME), OnWnfStateChange);

            Console.WriteLine("Subscribed to WNF state. Sending 'Hi' to kernel-mode.");

            // Send 'Hi' to kernel-mode
            SendMessageToKernel("Hi");

            // Keep the application running
            while (true)
            {
                Thread.Sleep(1000);
            }
        }

        static void SendMessageToKernel(string message)
        {
            // Convert the message to bytes
            byte[] dataToSend = Encoding.ASCII.GetBytes(message);

            // Publish the state
            NtWnf.PublishStateData(new WnfStateName(MY_WNF_STATE_NAME), dataToSend);
            Console.WriteLine("Sent message to kernel-mode: " + message);
        }

        // Callback when WNF state changes
        static void OnWnfStateChange(WnfStateChange change)
        {
            Console.WriteLine("WNF State Changed!");

            // Convert the received data to a string
            string receivedMessage = Encoding.ASCII.GetString(change.Data.ToArray());
            Console.WriteLine("Received message from kernel-mode: " + receivedMessage);

            if (receivedMessage == "Hi")
            {
                Console.WriteLine("Received 'Hi' from kernel-mode. Sending instructions...");

                // Prepare instructions
                INSTRUCTIONS instructions = new INSTRUCTIONS
                {
                    close = 0,
                    read = 1,
                    reqBase = 0,
                    bufferAddress = IntPtr.Zero,
                    address = UIntPtr.Zero,
                    size = 0,
                    output = IntPtr.Zero,
                    baseAddress = 0,
                    moduleName = "ExampleModule"
                };

                // Send instructions
                SendInstructionsToKernel(instructions);
            }
            else if (receivedMessage == "Read operation completed")
            {
                Console.WriteLine("Kernel-mode has completed the read operation.");
                // Process the results if any
                // ...
            }
            else
            {
                // Handle other messages or results
                Console.WriteLine("Received data: " + receivedMessage);
            }
        }

        static void SendInstructionsToKernel(INSTRUCTIONS instructions)
        {
            int size = Marshal.SizeOf(instructions);
            IntPtr ptr = Marshal.AllocHGlobal(size);
            try
            {
                Marshal.StructureToPtr(instructions, ptr, false);

                byte[] dataToSend = new byte[size];
                Marshal.Copy(ptr, dataToSend, 0, size);

                NtWnf.PublishStateData(new WnfStateName(MY_WNF_STATE_NAME), dataToSend);
                Console.WriteLine("Sent instructions to kernel-mode.");
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }
        }

        // Define the INSTRUCTIONS structure
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        struct INSTRUCTIONS {
            public byte close;
            public byte read;
            public byte reqBase;
            public IntPtr bufferAddress;
            public UIntPtr address;
            public ulong size;
            public IntPtr output;
            public ulong baseAddress;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string moduleName;
        }
    }
}
c++
#pragma once
#include <Windows.h>
#include <iostream>
#include <TlHelp32.h>
 
HANDLE hMapFileW;
HANDLE hMapFileR;
SECURITY_ATTRIBUTES sa;
 
 
 
typedef struct _INSTRUCTIONS
{
    BOOLEAN close;
    BOOLEAN read;
    BOOLEAN reqBase;
    void* bufferAddress;
    UINT_PTR address;
    ULONGLONG size;
    void* output;
    ULONG64 baseAddress;
    const char* moduleName;
} INSTRUCTIONS;
 
class KernelCom
{
public:
    bool OpenSharedMemory()
    {
        hMapFileW = OpenFileMappingA(FILE_MAP_WRITE, FALSE, "Global\\SharedMem");
        if (!hMapFileW || hMapFileW == INVALID_HANDLE_VALUE) {
            return false;
        }
        hMapFileR = OpenFileMappingA(FILE_MAP_READ, FALSE, "Global\\SharedMem");
        if (!hMapFileR || hMapFileR == INVALID_HANDLE_VALUE) {
            CloseHandle(hMapFileW);
            return false;
        }
        std::cout << "[+] Complete Shared Memory is available to use!" << std::endl;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xA);
        return true;
    }
    bool WriteToMem(INSTRUCTIONS* instructions)
    {
        auto pBuf = (INSTRUCTIONS*)MapViewOfFile(hMapFileW, FILE_MAP_WRITE, 0, 0, sizeof(INSTRUCTIONS));
        if (!pBuf)
        {
            printf("MapViewOfFile(write) fail! Error: %u\n", GetLastError());
            return false;
        }
        RtlCopyMemory(pBuf, instructions, sizeof(INSTRUCTIONS));
        UnmapViewOfFile(pBuf);
        return true;
    }
    bool CloseDriver()
    {
        INSTRUCTIONS instructions;
        instructions.close = TRUE;
        instructions.read = FALSE;
        instructions.reqBase = FALSE;
        if (WriteToMem(&instructions))
        {
            std::cout << "Sent Close Request!" << std::endl;
            return true;
        }
        else { return false; }
    }
    bool GetModuleBaseAddress()
    {
        INSTRUCTIONS instructions;
        instructions.reqBase = TRUE;
        instructions.read = FALSE;
        instructions.close = FALSE;
        instructions.moduleName = "Notepad.exe";
        instructions.baseAddress = NULL;
        if (WriteToMem(&instructions))
        {
            std::cout << "Sent ReqBaseAddr" << std::endl;
 
            auto pBuf = (INSTRUCTIONS*)MapViewOfFile(hMapFileR, FILE_MAP_READ, 0, 0, sizeof(INSTRUCTIONS));
            if (pBuf)
            {
                std::cout << "Received baseAddress from driver: 0x" << std::hex << pBuf->output << std::endl;
                UnmapViewOfFile(pBuf);
                return true;
            }
            return false;
        }
        return false;
    }
    template <class T>
    T Read(UINT_PTR address, PVOID buffer, SIZE_T size)
    {
 
    }
    bool CloseHandles()
    {
        if (hMapFileW)
            CloseHandle(hMapFileW);
        if (hMapFileR)
            CloseHandle(hMapFileR);
        return true;
    }
};
main.cpp
Code:
#include "driver.h"
 
uintptr_t pid;
uintptr_t moduleBase;
 
KernelCom* kernelCom;
 
int main()
{
    while (true)
    {
        if (kernelCom->OpenSharedMemory())
        {
            system("cls");
            break;
        }
        if (!kernelCom->OpenSharedMemory())
        {
            std::cerr << "Failed to open shared memory." << std::endl;
        }
        system("cls");
        std::cout << "[>] Waiting For Driver..." << std::endl;
        Sleep(1000);
    }
    kernelCom->GetModuleBaseAddress();
    
    kernelCom->CloseDriver();
    kernelCom->CloseHandles();
    std::cin.get();
    return 0;
}