Help on Minifilter To get reply from userMode Application

I am having a problem communicating from kernel to userMode. My requirement is to send a process path in postCreate and get a reply from the user-mode application.
The user-mode process that process path and reply back as boolean.
I have used FltSendMessage to send path to user-mode but in user-mode, I have taken the help of **scanner ** example in Minispy. GetQueuedCompletionStatus doesn’t return anything and it blocks there. I have used the same completionPort but somehow not getting any msg from the kernel.

I am attaching the code also to get help from the experts of OSR.

Code to get msg from the kernel and reply to the kernel

DWORD
RetrieveMsgAndReplyToKernel(
    _In_ PMINISPY_THREAD_CONTEXT Context
)
{
    PMINISPY_NOTIFICATION notification;
    MINISPY_REPLY_MESSAGE reply message;
    PMINISPY_MESSAGE message;
    LPOVERLAPPED pOvlp;
    BOOL result;
    DWORD outSize;
    HRESULT hr;
    ULONG_PTR key;
    UINT errorCode;

    printf("\nThread Func: %s", __FUNCTION__);

    while (TRUE) {
        printf("\ngetting GetQueuedCompletionStatus on completionPort: 0x%p\n", Context->Completion);
        result = GetQueuedCompletionStatus(Context->Completion, &outSize, &key, &pOvlp, INFINITE);
        message = CONTAINING_RECORD(pOvlp, MINISPY_MESSAGE, Ovlp);

        if (!result) {
            errorCode = GetLastError();
            hr = HRESULT_FROM_WIN32(errorCode);
            printf("GetQueuedCompletionStatus Failed! ERROR Code: %d", errorCode);
            break;
        }
        printf("\nReceived message, size %Id\n", pOvlp->InternalHigh);

        notification = &message->Notification;

        //TODO: process processPath and fileName and update the result
        result = strstr(notification->ProcessPath, "firefox") != NULL ? TRUE : FALSE;

        replyMessage.ReplyHeader.Status = 0;
        replyMessage.ReplyHeader.MessageId = message->MessageHeader.MessageId;

        replyMessage.Reply.res = result;

        printf("\nReplying message, Res bool: %d\n", replyMessage.Reply.res);

        hr = FilterReplyMessage(Context->Port,
            (PFILTER_REPLY_HEADER)&replyMessage,
            sizeof(replyMessage));

        if (SUCCEEDED(hr)) {
            printf("\nsuccessfully Replied message!\n");
        }
        else {
            printf("\nMINISPY: Error replying message. Error = 0x%X\n", hr);
            break;
        }
        memset(&message->Ovlp, 0, sizeof(OVERLAPPED));
        hr = FilterGetMessage(Context->Port,
            &message->MessageHeader,
            FIELD_OFFSET(MINISPY_MESSAGE, Ovlp),
            &message->Ovlp);

        if (hr != HRESULT_FROM_WIN32(ERROR_IO_PENDING)) {
            break;
        }
    }

    if (!SUCCEEDED(hr)) {
        if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE)) {
            //
            //  MINISPY port disconncted.
            //
            printf("\nMINISPY: Port is disconnected, probably due to MINISPY filter unloading.\n");
        }
        else {
            printf("\nMINISPY: Unknown error occured. Error = 0x%X\n", hr);
        }
    }
        if (message) {
            free(message);
        }
   
    return hr;
}

And to create a communication port and thread, I have used the following code:

 hResult = FilterConnectCommunicationPort( MINISPY_PORT_NAME, // fully name of port to connect
                                              0,
                                              NULL,
                                              0,
                                              NULL,
                                              &port // receives a handle for the newly created connection port if the call to FilterConnectCommunicationPort succeeds
                                            );

    if (IS_ERROR( hResult )) {
        printf( "Could not connect to filter: 0x%08x\n", hResult );
        DisplayError( hResult );
        goto Main_Exit;
    }
    //
   //  Create a completion port to associate with this handle.
   //
    completion = CreateIoCompletionPort(port,
        NULL,
        0,
        threadCount);

    if (completion == NULL) {
        printf("ERROR: Creating completion port: %d\n", GetLastError());
        CloseHandle(port);
        return 3;
    }
    printf("Minispy: Port = 0x%p Completion = 0x%p\n", port, completion);

    context.Port = port;
    context.Completion = completion;

   // Create the thread to read msg from the kernel and reply bool to the kernel by MiniSpy.sys.

    printf("Creating Msg Repling thread...\n");
    thread2 = CreateThread(NULL,
        0,
        (LPTHREAD_START_ROUTINE)RetrieveMsgAndReplyToKernel,
        &context2,
        0,
        &threadId2);

    printf("Context2 After Thread creation, Minispy: Port = 0x%p Completion = 0x%p\n", context2.Port, context2.Completion);

    if (!thread2) {
        result = GetLastError();
        printf("Could not create MsgReplying thread: %d\n", result);
        DisplayError(result);
        goto Main_Exit;
    }

//**Waiting here **

But GetQueuedCompletionStatus never returns.
What mistakes I am doing?

Note: I have successfully sent msg from the kernel and waiting 5 sec to reply from user mode.

so, please help me. I will be very thankful to you!
Thanks a lot.

I have figured it out. I was not using the FilterGetMessage before the GetQueuedCompletionStatus.That’s why I was not getting any message from the kernel. Thank you all.