windows-nt/Source/XPSP1/NT/multimedia/media/dplay/misc/queue.cpp

388 lines
9.2 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <windowsx.h>
#include <winsock.h>
#ifndef _MT
#define _MT
#endif
#include <dplay.h>
#include <logit.h>
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);
}