I want to call a C++ DLL from a C KMDF, I made this code
C++ Code
dll.h
    extern "C" {
        __declspec(dllexport) void MyFunction();
    }
dll.cpp
    void MyFunction()
    {
        std::cout << "Hello from MyFunction in C++ MyLibrary.dll" << std::endl;
    }
c Code
Source.c
#include <ntddk.h>
#include <wdf.h>
#define CALL_DLL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)
NTSTATUS GetModuleBaseAddress(PUNICODE_STRING ModuleName, PVOID* ModuleBase)
{
    NTSTATUS status = STATUS_SUCCESS;
    PVOID systemModuleInfo = NULL;
    
    // Query system information to obtain module information
    ULONG systemModuleInfoSize = 0;
    status = ZwQuerySystemInformation(SystemModuleInformation, &systemModuleInfo, systemModuleInfoSize, &systemModuleInfoSize);
    
    if (status == STATUS_INFO_LENGTH_MISMATCH)
    {
        // Allocate memory for the module information
        systemModuleInfo = ExAllocatePool(NonPagedPool, systemModuleInfoSize);
        if (systemModuleInfo)
        {
            // Retrieve the module information
            status = ZwQuerySystemInformation(SystemModuleInformation, systemModuleInfo, systemModuleInfoSize, &systemModuleInfoSize);
            if (NT_SUCCESS(status))
            {
                // Iterate through the module list
                PSYSTEM_MODULE_INFORMATION moduleInfo = (PSYSTEM_MODULE_INFORMATION)systemModuleInfo;
                ULONG moduleCount = systemModuleInfoSize / sizeof(SYSTEM_MODULE_INFORMATION);
                for (ULONG i = 0; i < moduleCount; i++)
                {
                    UNICODE_STRING moduleName;
                    RtlInitUnicodeString(&moduleName, moduleInfo[i].ImageName);
                    if (RtlEqualUnicodeString(&moduleName, ModuleName, TRUE))
                    {
                        *ModuleBase = moduleInfo[i].Base;
                        status = STATUS_SUCCESS;
                        break;
                    }
                }
                if (NT_SUCCESS(status))
                {
                    // Module found
                    status = STATUS_SUCCESS;
                }
                else
                {
                    // Module not found
                    status = STATUS_NOT_FOUND;
                }
            }
            // Free the allocated memory
            ExFreePool(systemModuleInfo);
        }
        else
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
    }
    else
    {
        status = STATUS_UNSUCCESSFUL;
    }
    return status;
}
NTSTATUS LoadDllAndCallFunction(PUNICODE_STRING DllPath, PUNICODE_STRING ModuleName, PUNICODE_STRING FunctionName)
{
    NTSTATUS status = STATUS_SUCCESS;
    PVOID dllBase = NULL;
    HANDLE fileHandle = NULL;
    // Open the DLL file
    OBJECT_ATTRIBUTES objectAttributes;
    InitializeObjectAttributes(&objectAttributes, DllPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
    IO_STATUS_BLOCK ioStatus;
    status = ZwCreateFile(&fileHandle, GENERIC_READ, &objectAttributes, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
    if (!NT_SUCCESS(status))
    {
        // Handle the error when opening the file
        return status;
    }
    // Load the DLL
    status = PsLoadImage(DllPath, NULL, NULL, 0, &dllBase);
    if (!NT_SUCCESS(status))
    {
        // Handle the error when loading the DLL
        ZwClose(fileHandle);
        return status;
    }
    // Get the base address of the module
    PVOID moduleBase = NULL;
    status = GetModuleBaseAddress(ModuleName, &moduleBase);
    if (!NT_SUCCESS(status))
    {
        // Handle the error when getting the module base address
        PsUnloadImage(dllBase);
        ZwClose(fileHandle);
        return status;
    }
    // Get the function address
    PVOID functionAddress = NULL;
    status = LdrGetProcedureAddress(moduleBase, FunctionName, 0, &functionAddress);
    if (!NT_SUCCESS(status))
    {
        // Handle the error when getting the function address
        PsUnloadImage(dllBase);
        ZwClose(fileHandle);
        return status;
    }
    // Call the function
    typedef VOID(*FunctionPtr)();
    FunctionPtr function = (FunctionPtr)functionAddress;
    function();
    // Unload the DLL
    status = PsUnloadImage(dllBase);
    if (!NT_SUCCESS(status))
    {
        // Handle the error when unloading the DLL
    }
    ZwClose(fileHandle);
    return status;
}
//VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
//{
//    UNREFERENCED_PARAMETER(DriverObject);
//    // Unload any resources
//}
void initDevice()
{
    KdPrint(("KMD - The DEVICE must be INIT \r\n"));
    //UNREFERENCED_PARAMETER(RegistryPath);
    //DriverObject->DriverUnload = DriverUnload;
    UNICODE_STRING dllPath;
    RtlInitUnicodeString(&dllPath, L"C:\\path\\MyLibrary.dll");  // Path to the user DLL
    UNICODE_STRING moduleName;
    RtlInitUnicodeString(&moduleName, L"MyLibrary.dll"); // Name of the module to load
    UNICODE_STRING functionName;
    RtlInitUnicodeString(&functionName, L"MyFunction"); // Name of the function to call
    NTSTATUS status = LoadDllAndCallFunction(&dllPath, &moduleName, &functionName);
    if (!NT_SUCCESS(status))
    {
        // Handle the error
        return;
    }
    return STATUS_SUCCESS;
}
NTSTATUS DispatchDevCTL(PDEVICE_OBJECT DeviceObject_local, PIRP Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject_local);
    PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS status = STATUS_SUCCESS;
    ULONG returnLength = 0;
    PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
    ULONG inLength = irpsp->Parameters.DeviceIoControl.InputBufferLength;
    ULONG outLength = irpsp->Parameters.DeviceIoControl.OutputBufferLength;
    WCHAR* demo = L"Sample returned from driver";
    HANDLE threadHandle;
    UNREFERENCED_PARAMETER(outLength);
    UNREFERENCED_PARAMETER(inLength);
    switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
    {
    case CALL_DLL:
         status = PsCreateSystemThread(&threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, initDevice, NULL);
        if (!NT_SUCCESS(status))
        {
            // Handle the error
            return status;
        }
        // Close the thread handle
        ZwClose(threadHandle);
        // Complete the IRP
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        break;
    default:
        status = STATUS_INVALID_PARAMETER;
        break;
    }
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = returnLength;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    NTSTATUS status;
    int i;
    //The UNREFERENCED_PARAMETER is used to indicate to the compiler that the parameter is not being used intentionality in the code and skip the warning (C4100)
    UNREFERENCED_PARAMETER(DriverObject);
    UNREFERENCED_PARAMETER(RegistryPath);
    //KdPrint(("Hello World \r\n"));
    DriverObject->DriverUnload = Unload;
    status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("KMD - Creating device failed \r\n"));
        return status;
    }
    status = IoCreateSymbolicLink(&SymLinkName, &DeviceName);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("KMD - Creating symbolic link failed \r\n"));
        IoDeleteDevice(DeviceObject);
        return status;
    }
    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction[i] = DispatchPassThru;
    }
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDevCTL;
    //DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchCustom1;
    KdPrint(("KMD - Driver Loaded \r\n"));
    return status;
}
I'm using VS2019, with this Project configuration

When I build the project, those errors are shown:

- 'ZwQuerySystemInformation' undefined; assuming extern returning int
 - 'PsLoadImage' undefined; assuming extern returning int
 - 'PsUnloadImage' undefined; assuming extern returning int
 - 'LdrGetProcedureAddress' undefined; assuming extern returning int
 
What am I making wrong? or exist another way to call a DLL from a Driver?