#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #include #include #ifndef _MT #define _MT #endif #include #include DWORD dwMsgSeq = 1; DWORD dwQMsgs = 0; DWORD dwMsgIndx = 0; DWORD dwMaxMsgs; static CRITICAL_SECTION q_Section; typedef struct { DWORD dwSeq; DWORD dwSize; BOOL bValid; DWORD dwIndex; DPID pidTo; DPID pidFrom; } MSG_ARRAY; typedef struct { DWORD dwCount; DPID pid; HANDLE hEvent; } PLAYER_NOTIFY; char *pmsgElements = NULL; MSG_ARRAY *pmsgArray = NULL; PLAYER_NOTIFY *aNotify = NULL; HANDLE hSystemMsg = NULL; #define malloc(a) LocalAlloc(LMEM_FIXED, (a)) #define free(a) LocalFree((HLOCAL)(a)) #define min(a,b) (((a) < (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b)) DWORD g_maxMsg = 0; DWORD g_maxPlayers = 0; BOOL CreateQueue(DWORD dwElements, DWORD dwmaxMsg, DWORD dwmaxPlayers) { DWORD ii; if (pmsgElements) return(FALSE); pmsgElements = (char *) malloc(dwElements * dwmaxMsg); pmsgArray = (MSG_ARRAY *) malloc(dwElements * sizeof(MSG_ARRAY)); aNotify = (PLAYER_NOTIFY *) malloc(dwmaxPlayers * sizeof(PLAYER_NOTIFY)); if (!pmsgElements || !pmsgArray || !aNotify) { if (pmsgElements) free(pmsgElements); if (pmsgArray) free(pmsgArray); if (aNotify) free(aNotify); pmsgElements = NULL; pmsgArray = NULL; aNotify = NULL; return(FALSE); } for (ii = 0; ii < dwmaxPlayers; ii++) { aNotify[ii].dwCount = 0; aNotify[ii].pid = 0; aNotify[ii].hEvent = 0; } for (ii = 0; ii < dwElements; ii++) { pmsgArray[ii].dwSeq = 0; pmsgArray[ii].bValid = FALSE; pmsgArray[ii].dwIndex = ii; pmsgArray[ii].pidTo = 0; pmsgArray[ii].pidFrom = 0; } dwMaxMsgs = dwElements; dwMsgSeq = 1; dwQMsgs = 0; dwMsgIndx = 0; g_maxMsg = dwmaxMsg; g_maxPlayers = dwmaxPlayers; InitializeCriticalSection( &q_Section ); return(TRUE); } BOOL DeleteQueue() { if (pmsgElements) free(pmsgElements); if (pmsgArray) free(pmsgArray); if (aNotify) free(aNotify); pmsgElements = NULL; pmsgArray = NULL; aNotify = NULL; DeleteCriticalSection( &q_Section ); return(TRUE); } BOOL AddMessage(LPVOID lpvMsg, DWORD dwSize, DPID pidTo, DPID pidFrom, BOOL bHigh) { DWORD dwSeq; DWORD dwIndex; DWORD ii; DPID pid; if (dwSize > g_maxMsg) return(FALSE); // DBG_INFO((DBGARG, "AddMessage. Seq %d Current %d", dwMsgSeq, dwQMsgs)); EnterCriticalSection( &q_Section ); dwMsgSeq++; if (dwQMsgs == dwMaxMsgs) { TSHELL_INFO("Queue over-run, start dumping old messages"); dwSeq = 0xffffffff; for (ii = 0; ii < dwMaxMsgs; ii++) { dwSeq = min(dwSeq, pmsgArray[ii].dwSeq); if (dwSeq == pmsgArray[ii].dwSeq) dwIndex = ii; } pid = pmsgArray[dwIndex].pidTo; pmsgArray[dwIndex].bValid = FALSE; for (ii = 0; ii < g_maxPlayers; ii++) if (aNotify[ii].pid == pid) aNotify[ii].dwCount--; dwQMsgs--; } else { dwQMsgs++; for (ii = 0; ii < dwMaxMsgs && (pmsgArray[dwMsgIndx].bValid == TRUE); ii++) { dwMsgIndx++; dwMsgIndx %= dwMaxMsgs; } dwIndex = dwMsgIndx; } if (pmsgArray[dwIndex].bValid == TRUE) { TSHELL_INFO("Invalid Message State!"); } // DBG_INFO((DBGARG, "Message index %d", dwIndex)); pmsgArray[dwIndex].dwSeq = dwMsgSeq; pmsgArray[dwIndex].dwSize = dwSize; pmsgArray[dwIndex].bValid = TRUE; pmsgArray[dwIndex].pidTo = pidTo; pmsgArray[dwIndex].pidFrom = pidFrom; if (bHigh) { pmsgArray[dwIndex].dwSeq += 0x80000000; } memcpy( pmsgElements + (dwIndex * g_maxMsg), lpvMsg, dwSize); // TSHELL_INFO("Message in buffer, now handle increments and events"); // DBG_INFO((DBGARG, "pidTo %d pidFrom %d", pidTo, pidFrom)); if (pidTo != 0) { for (ii = 0; ii < g_maxPlayers; ii++) if (aNotify[ii].pid == pidTo) { // TSHELL_INFO("Increment"); InterlockedIncrement((LONG *) &(aNotify[ii].dwCount)); if (aNotify[ii].hEvent) { // TSHELL_INFO("Set Event"); SetEvent(aNotify[ii].hEvent); // DBG_INFO((DBGARG, "Signal Event %8x", aNotify[ii].hEvent)); } else { TSHELL_INFO("No Event to Signal."); } break; } } LeaveCriticalSection( &q_Section ); return(TRUE); } HRESULT GetQMessage(LPVOID lpvMsg, LPDWORD pdwSize, DPID *ppidTo, DPID *ppidFrom, DWORD dwFlags, BOOL bPeek) { DWORD dwSeq; DWORD dwIndex; DWORD dwSeqH; DWORD dwIndexH; DWORD ii; HRESULT hr = DP_OK; // TSHELL_INFO("Retrieve Messages."); if (dwQMsgs == 0) return(DPERR_NOMESSAGES); if (!lpvMsg && !pdwSize) return(DPERR_INVALIDPARAM); EnterCriticalSection( &q_Section ); dwSeq = 0xffffffff; dwIndex = 0xffffffff; dwSeqH = 0xffffffff; dwIndexH = 0xffffffff; for (ii = 0; ii < dwMaxMsgs; ii++) { if (pmsgArray[ii].bValid) { if ( (dwFlags & DPRECEIVE_ALL) || ((dwFlags & DPRECEIVE_TOPLAYER) && (pmsgArray[ii].pidTo == *ppidTo)) || ((dwFlags & DPRECEIVE_FROMPLAYER) && (pmsgArray[ii].pidFrom == *ppidFrom))) { // DBG_INFO((DBGARG, "Msg %d Seq %x valid and meets criteria.", // ii, pmsgArray[ii].dwSeq)); if (0x80000000 & pmsgArray[ii].dwSeq) { if (dwSeqH > pmsgArray[ii].dwSeq) { dwSeqH = pmsgArray[ii].dwSeq; dwIndexH = ii; } } else { if (dwSeq > pmsgArray[ii].dwSeq) { dwSeq = pmsgArray[ii].dwSeq; dwIndex = ii; } } } else { DBG_INFO((DBGARG, "Msg %d valid but doesn't meet criteria. for Flags %8x", ii, dwFlags)); } } } if (dwIndexH != 0xffffffff) { dwIndex = dwIndexH; } if (dwIndex != 0xffffffff) { // TSHELL_INFO("Return a message."); if (lpvMsg == NULL || (*pdwSize < pmsgArray[dwIndex].dwSize)) { *pdwSize = pmsgArray[dwIndex].dwSize; hr = DPERR_BUFFERTOOSMALL; } else { memcpy( lpvMsg, pmsgElements + (dwIndex * g_maxMsg), pmsgArray[dwIndex].dwSize); *pdwSize = pmsgArray[dwIndex].dwSize; *ppidTo = pmsgArray[dwIndex].pidTo; *ppidFrom = pmsgArray[dwIndex].pidFrom; if (!(dwFlags & DPRECEIVE_PEEK)) { dwQMsgs--; pmsgArray[dwIndex].bValid = FALSE; for (ii = 0; ii < g_maxPlayers; ii++) if (aNotify[ii].pid == pmsgArray[dwIndex].pidTo) { InterlockedDecrement((LONG *) &aNotify[ii].dwCount); if (aNotify[ii].dwCount == 0 && aNotify[ii].hEvent) ResetEvent(aNotify[ii].hEvent); } } } } else { TSHELL_INFO("No messages found."); hr = DPERR_NOMESSAGES; } // TSHELL_INFO("LeaveGetQMessage."); LeaveCriticalSection( &q_Section ); return(hr); } VOID FlushQueue(DPID pid) { HRESULT hr = DP_OK; DWORD ii; EnterCriticalSection( &q_Section ); for (ii = 0; ii < g_maxPlayers; ii++) { if (aNotify[ii].pid == pid) { aNotify[ii].dwCount = 0; if (aNotify[ii].hEvent) aNotify[ii].hEvent = NULL; } } for (ii = 0; ii < dwMaxMsgs; ii++) { if (pmsgArray[ii].bValid && pmsgArray[ii].pidTo == pid) { dwQMsgs--; pmsgArray[ii].bValid = FALSE; } } LeaveCriticalSection( &q_Section ); } BOOL SetupLocalPlayer(DPID pid, HANDLE hEvent) { DWORD ii; if (pid == 0) return(FALSE); for (ii = 0; ii < g_maxPlayers; ii++) { if (aNotify[ii].pid == 0) { aNotify[ii].pid = pid; aNotify[ii].hEvent = hEvent; // DBG_INFO((DBGARG, "Pid %d index %d in Queue with event %8x", // pid, ii, hEvent)); return(TRUE); } } return(FALSE); } DWORD GetPlayerCount(DPID spid) { DWORD ii; for (ii = 0; ii < g_maxPlayers; ii++) if (aNotify[ii].pid == spid) return(aNotify[ii].dwCount); return(0); }