Exemple #1
0
DWORD WINAPI BrokerThreadBusEmulation(LPVOID pVoid)
{
    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;

    // Validate certain required pointers
    //VALIDATE_POINTER_RETURN_VALUE_LOG(pThreadParam, -1);
    //VALIDATE_POINTER_RETURN_VALUE_LOG(pThreadParam->m_hActionEvent, -1);

    // Get hold of the bus simulation and error logger interfaces
    HRESULT hResult = CoInitialize(NULL);

    ISimENG* pISimENG = NULL;
    hResult = CoCreateInstance(CLSID_SimENG, NULL, CLSCTX_LOCAL_SERVER,
                               IID_ISimENG, (LPVOID*) &pISimENG);
    if ((S_OK != hResult) || (NULL == pISimENG))
    {
        return 0L;
    }


    bool bLoopON = true;

    while (bLoopON)
    {
        WaitForSingleObject(pThreadParam->m_hActionEvent, INFINITE);

        switch (pThreadParam->m_unActionCode)
        {
            case CONNECT:
            {
                sg_hResult = Worker_Connect(pISimENG, sg_pIlog);
                SetEvent(sg_hNotifyFinish);
            }
            break;
            case DISCONNECT:
            {
                sg_hResult = Worker_Disconnect(pISimENG, sg_pIlog);
                SetEvent(sg_hNotifyFinish);
            }
            break;
            case STOP_HARDWARE:
            {
                sg_hResult = Worker_StopHardware(pISimENG, sg_pIlog);
                SetEvent(sg_hNotifyFinish);
            }
            break;
            case START_HARDWARE:
            {
                sg_hResult = Worker_StartHardware(pISimENG, sg_pIlog);
                SetEvent(sg_hNotifyFinish);
            }
            break;
            case SEND_MESSAGE:
            {
                sg_hResult = Worker_SendCanMsg(pISimENG, sg_pIlog, sg_pouCanTxMsg);
                SetEvent(sg_hNotifyFinish); 
            }
            break;
            case GET_TIME_MAP:
            {
                sg_hResult = Worker_GetTimeModeMapping(pISimENG, sg_pIlog);
                SetEvent(sg_hNotifyFinish);
            }
            break;
            case REGISTER:
            {
                sg_hResult = Worker_RegisterClient(pISimENG, sg_pIlog);
                SetEvent(sg_hNotifyFinish);
            }
            break;
            case UNREGISTER:
            {
                sg_hResult = Worker_UnregisterClient(pISimENG, sg_pIlog);
                SetEvent(sg_hNotifyFinish);
            }
            break;
            case EXIT_THREAD:
            {
                bLoopON = false;
            }
            break;
            default:
            case INACTION:
            {
                // nothing right at this moment
            }
            break;
        }
    }

    // Release the bus simulation & error logger out-of-proc server components
    //pISimENG->Release();

    // Reset the interface pointers
    pISimENG = NULL;

    SetEvent(pThreadParam->hGetExitNotifyEvent());

    return 0;
}
/**
* \brief         Read thread procedure
* \param[in]     pVoid contains the CPARAM_THREADPROC class object
* \return        void
* \authors       Prince Varghese
* \date          09.04.2013 Created
*/
DWORD WINAPI CanMsgReadThreadProc_CAN_ISolar_Eve(LPVOID pVoid)
{
    USES_CONVERSION;

    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;

    /* Assign thread action to CREATE_TIME_MAP */
    pThreadParam->m_unActionCode = CREATE_TIME_MAP;

    bool bLoopON = true;

    while (bLoopON)
    {
        Sleep (10); // To avoid continuous loop as there is no event mechanism
        switch (pThreadParam->m_unActionCode)
        {
            case INVOKE_FUNCTION:
            {

                int functionType = 0;
                unsigned int dataSize = 0;

                if (ReceiveCommandFromClient(&functionType, &dataSize) >= 0)
                {
                    switch (functionType)
                    {
                        case SEND_MESSAGE:
                        {
                            STCAN_MSG RxMsg;
                            int receiveResult = ReceiveCANMessageFromClient(&RxMsg);
                            if (receiveResult > 0)
                            {
                                sg_EVE_CANMsg.m_uDataInfo.m_sCANMsg.m_bCANFD = false;
                                sg_EVE_CANMsg.m_ucDataType = receiveResult;
                                sg_EVE_CANMsg.m_uDataInfo.m_sCANMsg = RxMsg;

                                RxMsg.m_ucChannel = 1;
                                vWriteIntoClientsBuffer(sg_EVE_CANMsg);
                            }
                        }
                        break;

                        default:
                            break;
                    }
                }
            }
            break;
            case EXIT_THREAD:
            {
                bLoopON = false;
            }
            break;
            case CREATE_TIME_MAP:
            {
                SetEvent(pThreadParam->m_hActionEvent);
                pThreadParam->m_unActionCode = INVOKE_FUNCTION;
            }
            break;
            default:
            case INACTION:
            {
                // nothing right at this moment
            }
            break;
        }

    }
    SetEvent(pThreadParam->hGetExitNotifyEvent());
    pThreadParam->m_hActionEvent = NULL;

    return 0;
}
DWORD WINAPI DataCopyThreadProc(LPVOID pVoid)
{
    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;
    if (pThreadParam == NULL)
    {
        // TBD
    }
    CFrameProcessor_Common* pCurrObj = NULL;
    if(pThreadParam != NULL)
    {
        pCurrObj = (CFrameProcessor_Common*) pThreadParam->m_pBuffer;
    }
    if (pCurrObj == NULL)
    {
        // TBD
    }

    //pThreadParam->m_unActionCode = INACTION;

    bool bLoopON = true;

    while (bLoopON)
    {
        // PTV CPP
        if(pCurrObj != NULL)
        {
            pCurrObj->m_bIsThreadBlocked = TRUE;
        }

        WaitForSingleObject(pThreadParam->m_hActionEvent, INFINITE);

        switch (pThreadParam->m_unActionCode)
        {
            case INVOKE_FUNCTION:
            {
                // Retrieve message from the driver
                pCurrObj->vRetrieveDataFromBuffer();
                ResetEvent(pThreadParam->m_hActionEvent);
            }
            break;
            case EXIT_THREAD:
            {
                bLoopON = false;
            }
            break;
            case CREATE_TIME_MAP:
            {
                pCurrObj->m_bIsThreadBlocked = FALSE;
                pCurrObj->InitTimeParams();
                pThreadParam->m_unActionCode = INVOKE_FUNCTION;
                SetEvent(pThreadParam->m_hActionEvent);
            }
            break;
            default:
            case INACTION:
            {
                // nothing right at this moment
            }
            break;
        }
    }
    SetEvent(pThreadParam->hGetExitNotifyEvent());

    return 0;
}
Exemple #4
0
/**
 * Read thread procedure
 */
DWORD WINAPI EthernetMsgReadThreadProc(LPVOID pVoid)
{
    USES_CONVERSION;

    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;

    // Validate certain required pointers
    VALIDATE_POINTER_RETURN_VALUE_LOG(pThreadParam, (DWORD)-1);
    // Assign thread action to CREATE_TIME_MAP
    pThreadParam->m_unActionCode = INVOKE_FUNCTION;

    //Set event object for reading from the socket
    //SOCKET ClientSocket = sg_Connector.GetClientSocket();
    //int rc = WSAEventSelect(ClientSocket, g_hReadEventObject, FD_READ);
    int rc = 0;
    if(rc == SOCKET_ERROR)
    {
        //unable to add event for reading
        return 1;
    }

    HANDLE hDataEvent = sg_Connector.GetEvent();
    HANDLE hEvents[] = {sg_hDataReceivedEvent, g_hInformStopTx};
    bool bLoopON = true;
    sg_Connector.SetReceiveCallBackFn();
    PPKTHDR *pHeader = new PPKTHDR;
    u_char *pkt_data = new u_char[1540];

    while (bLoopON)
    {
        //g_hReadEventObject is the event triggered on reception of the Data in ethernet port
        //Event should listen to the client socket in CConnector class

        WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
        //WaitForSingleObject(sg_hDataReceivedEvent, INFINITE);

        if(sg_bIsConnected == false)
        {
            pThreadParam->m_unActionCode = EXIT_THREAD;
            break;
        }
        switch (pThreadParam->m_unActionCode)
        {
        case INVOKE_FUNCTION:
        {
            int nResult = 0;
            do {

                string strError;

                nResult = sg_Connector.ReceivePackets(&pHeader,&pkt_data);

                if(nResult == S_FALSE)
                {
                    sg_pIlog->vLogAMessage(A2T(__FILE__), __LINE__, strError);
                    break;
                }
                ProcessMsg(pHeader,pkt_data );
                ResetEvent(sg_hDataReceivedEvent);
                //delete(pHeader);
                //delete(pkt_data);
            } while (nResult > 0);

        }
        break;
        case EXIT_THREAD:
        {
            bLoopON = false;
        }
        break;
        case CREATE_TIME_MAP:
        {
            SetEvent(pThreadParam->m_hActionEvent);
            pThreadParam->m_unActionCode = INVOKE_FUNCTION;
        }
        break;
        default:
        case INACTION:
        {
            // nothing right at this moment
        }
        break;
        }
    }
    /*delete(pHeader);
    	delete(pkt_data);*/


    SetEvent(pThreadParam->hGetExitNotifyEvent());
    ResetEvent(sg_hDataReceivedEvent);
    //g_hReadEventObject = NULL;
    /* for (UINT i = 0; i < sg_unClientCnt; i++)
    {
        ResetEvent(hReadEventObject);
        g_hDataEvent[i] = NULL;
    }*/
    pThreadParam->m_hActionEvent = NULL;

    return 0;
}
DWORD WINAPI ReadDILCANMsg(LPVOID pVoid)
{
    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;
    if (pThreadParam != NULL)
    {
        CReadCanMsg* pCurrObj = (CReadCanMsg*) pThreadParam->m_pBuffer;
        if (pCurrObj != NULL)
        {
            pThreadParam->m_unActionCode = INVOKE_FUNCTION; // Set default action
            // Create the action event. In this case this will be used solely for
            // thread exit procedure. The first entry will be used.
            pThreadParam->m_hActionEvent = pCurrObj->m_ahActionEvent[0];

            DWORD dwWaitRet;
            BYTE byHIndex;
            bool bLoopON = true;
            while (bLoopON)
            {
                dwWaitRet = WaitForMultipleObjects(pCurrObj->m_nEvents,
                                                   pCurrObj->m_ahActionEvent, FALSE, INFINITE);

                ///// TEMP : BEGIN
                DWORD dwLLimit = WAIT_OBJECT_0;
                DWORD dwULimit = WAIT_OBJECT_0 + pCurrObj->m_nEvents - 1;
                DWORD dwLLError = WAIT_ABANDONED_0;
                DWORD dwULError = WAIT_ABANDONED_0 + pCurrObj->m_nEvents - 1;

                if ((dwWaitRet >= dwLLimit) && (dwWaitRet <= dwULimit))
                {
                    switch (pThreadParam->m_unActionCode)
                    {
                        case INVOKE_FUNCTION:
                        {
                            //Get the handle's index and pass it
                            byHIndex = (BYTE)(dwWaitRet - WAIT_OBJECT_0);
                            HANDLE hHandleSet = pCurrObj->m_ahActionEvent[byHIndex];
                            BYTE byNodeIndex;
                            if( pCurrObj->m_omHandleToNodeMgrMap.Lookup(hHandleSet, byNodeIndex))
                            {
                                //vRetrieveDataFromBuffer to read from that buffer
                                pCurrObj->vRetrieveDataFromBuffer(byNodeIndex);
                            }
                            //BOOL Result = ResetEvent(hHandleSet);
                            ResetEvent(hHandleSet);
                        }
                        break;
                        case EXIT_THREAD:
                        {
                            bLoopON = false;
                        }
                        break;
                        case INACTION:
                        {
                            // Signal the owner
                            SetEvent(pThreadParam->m_hThread2Owner);
                            Sleep(0);
                            // Wait until owner signals back.
                            WaitForSingleObject(pThreadParam->m_hOwner2Thread, INFINITE);
                            // Signal the owner
                            SetEvent(pThreadParam->m_hThread2Owner);
                            Sleep(0);
                        }
                        break;
                        case CREATE_TIME_MAP:
                        default:
                            break;
                    }
                }
                else if ((dwWaitRet >= dwLLError) && (dwWaitRet <= dwULError))
                {
                    TRACE(_T(_("Abandoned... %X %d\n")), dwWaitRet, g_unCount++);
                }
                else if ( dwWaitRet == WAIT_TIMEOUT)
                {
                    TRACE(_T("ReadDILCANMsg->WAIT_TIMEOUT %d\n"), g_unCount++);
                }
                else if (dwWaitRet == WAIT_FAILED)
                {
                    TRACE(_T("WAIT_FAILED... %X %d\n"), GetLastError(), g_unCount++);
                }
                ///// TEMP : END
            }
            SetEvent(pThreadParam->hGetExitNotifyEvent());
        }
    }
    return 0;
}
/* Thread function used for sending messages cyclically */
DWORD WINAPI Cyclic_Transmission_Thread(LPVOID pVoid)
{
    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;
    if (pThreadParam == NULL)
    {
        return (DWORD)-1;
    }

    CTxMsgWndJ1939* pTxMsgWndJ1939 = static_cast<CTxMsgWndJ1939*> (pThreadParam->m_pBuffer);

    if (pTxMsgWndJ1939 == NULL)
    {
        return (DWORD)-1;
    }
    bool bLoopON = true;
    DWORD dwMiliSecs = INFINITE;
    while (bLoopON) // Continue so long as the loop is ON.
    {

        WaitForSingleObject(pThreadParam->m_hActionEvent,
                            dwMiliSecs);
        dwMiliSecs = pTxMsgWndJ1939->unGetTimerVal();
        ESTATE_TRANS eTransState = pTxMsgWndJ1939->eGetTransState();
        if ((eTransState == TRANS_TO_BE_STOPPED)
                || (eTransState == TRANS_STOPPED))
        {
            if (NULL != pTxMsgWndJ1939 && IsWindow(pTxMsgWndJ1939->m_hWnd))
            {
                pTxMsgWndJ1939->vProcessTransmission(FALSE);
                dwMiliSecs = INFINITE;
                ResetEvent(pThreadParam->m_hActionEvent);
            }
        }
        else if (eTransState == TRANS_STARTED)
        {
            switch (pThreadParam->m_unActionCode)
            {
                case INVOKE_FUNCTION:
                {
                    if (pTxMsgWndJ1939->SendSavedMessage() == S_OK)
                    {
                        if (pTxMsgWndJ1939->m_sMsgToBeSent.m_unDLC > 8)
                        {
                            WaitForSingleObject(sg_hMsgSent, INFINITE);
                        }
                    }
                }
                break;
                case EXIT_THREAD:
                {
                    bLoopON = false;
                }
                break;

                case IDLE:
                    break;

                default:
                    break;
            }
        }
    }
    SetEvent(pThreadParam->hGetExitNotifyEvent()); // Signal the owner that the thread
    Sleep(0);                         // is going to terminate the infinite loop.
    return 0;
}
Exemple #7
0
DWORD WINAPI FlexMsgReadThreadProc_Stub(LPVOID pVoid)
{
    VALIDATE_POINTER_RETURN_VAL(sg_pIlog, (DWORD)-1);

    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;

    pThreadParam->m_unActionCode = CREATE_TIME_MAP;
    // Validate certain required pointers

    //Set the action event
    if ( sg_unClientCnt > 0 )
    {
        pThreadParam->m_hActionEvent = sg_asClientToBufMap[0].hClientHandle;
    }

    bool bLoopON = true;

    while (bLoopON)
    {
        static HANDLE ahClientReadHandle[MAX_CLIENT_ALLOWED] = {0};
        for (UINT i = 0; i < sg_unClientCnt; i++)
        {
            ahClientReadHandle[i] = sg_asClientToBufMap[i].hClientHandle;
        }
        DWORD dwIndex = WaitForMultipleObjects(sg_unClientCnt, ahClientReadHandle, FALSE, INFINITE);

        if (dwIndex == WAIT_FAILED)
        {
            GetSystemErrorString();
        }
        else
        {
            UINT Index = dwIndex - WAIT_OBJECT_0;
            switch (pThreadParam->m_unActionCode)
            {
                case INVOKE_FUNCTION:
                {
                    // Retrieve message from the pipe
                    ProcessCanMsg(sg_asClientToBufMap[Index].hPipeFileHandle, Index);
                }
                break;
                case CREATE_TIME_MAP:
                {
                    PerformAnOperation(GET_TIME_MAP);
                    ProcessCanMsg(sg_asClientToBufMap[Index].hPipeFileHandle, Index);
                    pThreadParam->m_unActionCode = INVOKE_FUNCTION;
                }
                break;
                case EXIT_THREAD:
                {
                    bLoopON = false;
                }
                break;
                default:
                case INACTION:
                {
                    // nothing right at this moment
                }
                break;
            }
        }
    }
    SetEvent(pThreadParam->hGetExitNotifyEvent());

    return 0;
}
/**
* \brief         Read thread procedure
* \param[in]     pVoid contains the CPARAM_THREADPROC class object
* \return        void
* \authors       Arunkumar Karri
* \date          07.19.2013 Created
*/
DWORD WINAPI CDIL_LIN_VectorXL::LINMsgReadThreadProc_LIN_Vector_XL(LPVOID pVoid)
{
    USES_CONVERSION;

    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;
    XLstatus xlStatus = XL_SUCCESS;

    /* Assign thread action to CREATE_TIME_MAP */
    pThreadParam->m_unActionCode = CREATE_TIME_MAP;

    /* Set the event to LIN_Vector_XL driver for wakeup and frame arrival notification */
    //for (UINT i = 0; i < sg_unClientCnt; i++)
    {
        xlStatus = xlSetNotification (g_xlPortHandle[0], &g_hDataEvent[0], 1);
    }

    /* Set the thread action event to first notification event handle */
    if (g_hDataEvent[0] != nullptr)
    {
        pThreadParam->m_hActionEvent = g_hDataEvent[0];
    }


    /* Get the handle to the controller and validate it */
    VALIDATE_POINTER_RETURN_VALUE_LOG(pThreadParam->m_hActionEvent, (DWORD)-1);

    DWORD dwResult = 0;
    unsigned int msgsrx;
    XLevent  xlEvent;

    bool bLoopON = true;

    while (bLoopON)
    {
        WaitForSingleObject(g_hDataEvent[0], INFINITE);
        switch (pThreadParam->m_unActionCode)
        {
            case INVOKE_FUNCTION:
            {
                bool bMoreDataExist;
                msgsrx = RECEIVE_EVENT_SIZE;
                xlStatus = xlReceive(g_xlPortHandle[0], &msgsrx, &xlEvent);
                while (xlStatus == XL_SUCCESS )
                {
                    switch (xlStatus)
                    {
                        case XL_SUCCESS:
                        {
                            if ( g_pouDIL_LIN_Vector_XL != nullptr )
                            {
                                g_pouDIL_LIN_Vector_XL->ProcessLINMsg(xlEvent);
                                bMoreDataExist = true;
                            }
                        }
                        break;

                        default:
                            break;
                    }
                    xlStatus = xlReceive(g_xlPortHandle[0], &msgsrx, &xlEvent);;
                }
            }
            break;
            case EXIT_THREAD:
            {
                bLoopON = false;
            }
            break;
            case CREATE_TIME_MAP:
            {
                //vCreateTimeModeMapping(pThreadParam->m_hActionEvent);
                SetEvent(pThreadParam->m_hActionEvent);
                pThreadParam->m_unActionCode = INVOKE_FUNCTION;
            }
            break;
            default:
            case INACTION:
            {
                // nothing right at this moment
            }
            break;
        }
    }
    SetEvent(pThreadParam->hGetExitNotifyEvent());

    {
        ResetEvent(g_hDataEvent[0]);
        g_hDataEvent[0] = nullptr;
    }
    pThreadParam->m_hActionEvent = nullptr;

    return 0;
}
/**
* \brief         Read thread procedure
* \param[in]     pVoid contains the CPARAM_THREADPROC class object
* \return        void
* \authors       Prince Varghese
* \date          09.04.2013 Created
*/
DWORD WINAPI LinMsgReadThreadProc_LIN_ISolar_Eve(LPVOID pVoid)
{
    USES_CONVERSION;

    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pVoid;

    /* Assign thread action to CREATE_TIME_MAP */
    pThreadParam->m_unActionCode = CREATE_TIME_MAP;

    /* Dummy action event */
    pThreadParam->m_hActionEvent = CreateEvent(nullptr, false, false, nullptr);

    bool bLoopON = true;

    while (bLoopON)
    {
        Sleep (10);
        switch (pThreadParam->m_unActionCode)
        {
            case INVOKE_FUNCTION:
            {
                static STLIN_FRAME RxFrame;
                static STLIN_MSG RxMsg;
                static int iRxLength;
                int iChecksum = 0;
                RxMsg.m_ucDataLen = 0;
                unsigned int uiDataType = ReceiveLINMessageFromClient(&RxFrame, &iRxLength);


                if (iRxLength == LIN_PID_LENGTH)
                {
                    RxMsg.m_ucMsgID   =  RxFrame.m_ucMsgID;
                    RxMsg.m_ucChksum  = 0;

                    vValidateReceivedLinPID(RxMsg);

                    /*sg_EVE_LINMsg.m_ucDataType = TX_FLAG;*/
                    sg_EVE_LINMsg.m_uDataInfo.m_sLINMsg = RxMsg;
                    RxMsg.m_ucChannel = LIN_CHANNEL_1;
                    //vWriteIntoClientsBuffer(sg_EVE_LINMsg);
                }
                else if (iRxLength > LIN_PID_LENGTH)
                {
                    RxMsg.m_ucMsgID   =  RxFrame.m_ucMsgID;
                    RxMsg.m_ucChksum  =  RxFrame.m_ucChksum;
                    RxMsg.m_ucDataLen =  iRxLength - (LIN_PID_LENGTH + LIN_CHECKSUM_LENGTH); // 2 (1 byte checksum and 1byte pid)

                    for(int i=0; i<8; i++)
                    {
                        RxMsg.m_ucData[i] = RxFrame.m_ucData[i];
                        iChecksum = iChecksum + RxFrame.m_ucData[i];
                        if (iChecksum > 255)
                        {
                            iChecksum = iChecksum - 255;
                        }
                    }
                    RxMsg.m_ucChksum = 255 - iChecksum;

                    if((RxMsg.m_ucChksum != RxFrame.m_ucChksum))
                    {
                        RxMsg.m_ucMsgTyp = LIN_CHECKSUM_ERROR;
                        RxMsg.m_ucChksum = RxFrame.m_ucChksum;
                    }
                    else
                    {
                        vValidateReceivedLinMsg(RxMsg);
                    }

                    if(uiDataType == TX_LOOPBACK_UDP_DATA)
                    {
                        sg_EVE_LINMsg.m_ucDataType = TX_FLAG;
                    }
                    else if((uiDataType == RX_UDP_PID)||(uiDataType == RX_UDP_DATA))
                    {
                        sg_EVE_LINMsg.m_ucDataType = RX_FLAG;
                    }

                    RxMsg.m_ucChannel = LIN_CHANNEL_1;

                    sg_EVE_LINMsg.m_uDataInfo.m_sLINMsg = RxMsg;
                    RxMsg.m_ucChannel = 1;
                    vWriteIntoClientsBuffer(sg_EVE_LINMsg);
                }
            }
            break;
            case EXIT_THREAD:
            {
                bLoopON = false;
            }
            break;
            case CREATE_TIME_MAP:
            {
                SetEvent(pThreadParam->m_hActionEvent);
                pThreadParam->m_unActionCode = INVOKE_FUNCTION;
            }
            break;
            default:
            case INACTION:
            {
                // nothing right at this moment
            }
            break;
        }

    }
    SetEvent(pThreadParam->hGetExitNotifyEvent());
    pThreadParam->m_hActionEvent = nullptr;

    return 0;
}
Exemple #10
0
DWORD WINAPI MsgDelegatingThread(LPVOID pParam)
{
    CPARAM_THREADPROC* pThreadParam = (CPARAM_THREADPROC*) pParam;

    WORD wSenderID = 0;
    INT Type = -1;
    UINT64 TimeStamp = 0x0;

    bool bLoopON = true;

    while (bLoopON)
    {
        WaitForSingleObject(pThreadParam->m_hActionEvent, INFINITE);

        switch (pThreadParam->m_unActionCode)
        {
            case INVOKE_FUNCTION:
            {
                // Retrieve message from the circular buffer
                while (sg_MessageBuf.GetMsgCount() > 0)
                {
                    EnterCriticalSection(&sg_CriticalSection);

                    BYTE* pbCurrEntry = sg_pbEntry2;
                    INT CurrLength = sg_nEntryLen2;
                    sg_MessageBuf.ReadFromBuffer(Type, pbCurrEntry, CurrLength);

                    // Save the sender id for reference
                    memcpy(&TimeStamp, pbCurrEntry + 1, SIZE_TIMESTAMP);
                    wSenderID = (WORD) TimeStamp;

                    // Calculate the current time stamp assigning the same to
                    // the message
                    LARGE_INTEGER CurrCounter;
                    QueryPerformanceCounter(&CurrCounter);
                    // Convert it to time stamp with the granularity of hundreds of us
                    if (CurrCounter.QuadPart * 10000 > CurrCounter.QuadPart)
                    {
                        TimeStamp =
                            (CurrCounter.QuadPart * 10000) / sg_lnFrequency.QuadPart;
                    }
                    else
                    {
                        TimeStamp =
                            (CurrCounter.QuadPart / sg_lnFrequency.QuadPart) * 10000;
                    }

                    // Now save the time stamp calculated
                    memcpy(pbCurrEntry + 1, &TimeStamp, SIZE_TIMESTAMP);

                    CLIENT_MAP::iterator itr = sg_ClientMap.begin();
                    while (itr != sg_ClientMap.end())
                    {
                        BOOL Result = TRUE;
                        // If the current client is meant for the same bus,
                        // then continue with the same.
                        if (itr->second.m_nBus == Type)
                        {
                            Result = itr->second.m_bActive;
                        }
                        if (Result)
                        {
                            if (itr->first == wSenderID)
                            {
                                // Make the self reception bit up
                                //CurrMsgDat.stcDataMsg.dwHeaderInfoFlags |= 0x800;
                                *pbCurrEntry = 0x1;
                            }
                            DWORD Count = 0;
                            Result = WriteFile(itr->second.m_hWrite, pbCurrEntry,
                                               itr->second.m_dwDataSize, &Count, NULL);
                            //&CurrMsgDat, SIZE_ENTRY, &Count, NULL);
                            SetEvent(itr->second.m_hEvent);
                            FlushFileBuffers(itr->second.m_hWrite);
                            if (itr->first == wSenderID)
                            {
                                // Make the self reception bit down
                                //CurrMsgDat.stcDataMsg.dwHeaderInfoFlags &= ~0x800;
                                *pbCurrEntry = 0x0;
                            }
                        }
                        itr++;
                    }
                    LeaveCriticalSection(&sg_CriticalSection);
                }
                ResetEvent(pThreadParam->m_hActionEvent);
            }
            break;
            case EXIT_THREAD:
            {
                bLoopON = false;
            }
            break;
            default:
            case INACTION:
            {
                // nothing right at this moment
            }
            break;
        }
    }
    SetEvent(pThreadParam->hGetExitNotifyEvent());

    return 0;
}