|
|
/*==========================================================================
* * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved. * * File: DPLMsgQ.cpp * Content: DirectPlay Lobby Message Queues *@@BEGIN_MSINTERNAL * History: * Date By Reason * ==== == ====== * 02/21/00 mjn Created * 04/26/00 mjn Fixed AddData() to return HRESULT * 07/06/00 rmt Bug #38111 - Fixed prefix bug * 07/08/2000 rmt Bug #38725 - Need to provide method to detect if app was lobby launched * rmt Bug #38757 - Callback messages for connections may return AFTER WaitForConnection returns * rmt Bug #38755 - No way to specify player name in Connection Settings * rmt Bug #38758 - DPLOBBY8.H has incorrect comments * rmt Bug #38783 - pvUserApplicationContext is only partially implemented * rmt Added DPLHANDLE_ALLCONNECTIONS and dwFlags (reserved field to couple of funcs). * 07/21/2000 rmt Removed assert which wasn't needed * 08/05/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles. * 08/31/2000 rmt Bug #171831, 131832 (Prefix Bugs) * 01/31/2001 rmt WINBUG #295562 IDirectPlay8LobbyClient: SetConnectionSettings not sending DPL_CONNECTION_SETTINGS message to App *@@END_MSINTERNAL * ***************************************************************************/
#include "dnlobbyi.h"
// DirectPlay Lobby Message Queues
//
// We will use shared memory circular message buffers to implement this.
// Each MsgQ has a set of synchronization objects to control access to the MsgQs.
// The head of the shared memory file contains state information about the MsgQ:
// pStartAddress
// dwTotalUsableSpace
// dwFirstMsgOffset
// dwNextFreeOffset
// dwFreeSpaceAtEnd
// dwTotalFreeSpace
// Messages are DWORD aligned in the MsgQ.
// Each message in the MsgQ has a header:
// dwMsgId
// dwCurrentOffset
// dwCurrentSize
// dwTotalSize
// Messages which fit in one frame have dwCurrentSize = dwTotalSize and dwCurrentOffset = 0.
// Messages over multiple frames have dwCurrentSize < dwTotalSize.
//**********************************************************************
// Constant definitions
//**********************************************************************
//**********************************************************************
// Macro definitions
//**********************************************************************
//**********************************************************************
// Structure definitions
//**********************************************************************
//**********************************************************************
// Variable definitions
//**********************************************************************
//**********************************************************************
// Function prototypes
//**********************************************************************
//**********************************************************************
// Function definitions
//**********************************************************************
//**********************************************************************
// ------------------------------
// CMessageQueue::Open
//
// Entry: const DWORD dwPID Id associated with this queue (user supplied)
// const CHAR cSuffix Suffix character associated with this Q (user supp.)
// const DWORD dwQueueSize Size of file map to use when implementing msg queue
// const DWORD dwIdleTimeout Amount of time between idle messages == INFINITE to disable idle
// const DWORD dwFlags TBA
//
//
// Exit: HRESULT: DPN_OK If able to open an existing message queue,
// or create a message queue if one didn't exist
// DPNERR_OUTOFMEMORY
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::Open"
HRESULT CMessageQueue::Open(const DWORD dwPID, const TCHAR cSuffix, const DWORD dwQueueSize, const DWORD dwIdleTimeout, const DWORD dwFlags) { HRESULT hResultCode; PTSTR pszObjectName = NULL; BOOL bQueueExists = FALSE; DWORD dwFileMapSize;
#ifdef UNICODE
DPFX(DPFPREP, 3,"Parameters: dwPID [0x%lx], cSuffix [%C], dwQueueSize [%ld], dwFlags [0x%lx]", dwPID,cSuffix,dwQueueSize,dwFlags); #else
DPFX(DPFPREP, 3,"Parameters: dwPID [0x%lx], cSuffix [%c], dwQueueSize [%ld], dwFlags [0x%lx]", dwPID,cSuffix,dwQueueSize,dwFlags); #endif // UNICODE
// Create Receive Thread Running Event
// This will be set by the receive thread once it has spun up. We need it for synchronization
m_hReceiveThreadRunningEvent = DNCreateEvent(NULL,TRUE,FALSE,NULL); if (m_hReceiveThreadRunningEvent == NULL) { DPFERR("Could not create recevie thread"); hResultCode = DPNERR_OUTOFMEMORY; goto EXIT_Initialize; }
// Create shared object name
// pszObjectName : {SharedObjectChar}PID{cSuffix}{\0}
if ((pszObjectName = (PTSTR)DNMalloc((1 + (sizeof(DWORD)*2) + 1 + 1) * sizeof (TCHAR))) == NULL) { DPFERR("Could not allocate space for lpszObjectName"); hResultCode = DPNERR_OUTOFMEMORY; goto EXIT_Initialize; } wsprintf(pszObjectName,_T("-%08X%c"),dwPID,cSuffix);// save first char for object differentiation
DPFX(DPFPREP, 5,"Shared object name [%s]",pszObjectName);
// Set the filemap size big enough that the largest message (text) will be dwQueueSize
// so we add on the MsgQ info structure at the front and 1 Msg header
dwFileMapSize = dwQueueSize + sizeof(DPL_MSGQ_INFO) + sizeof(DPL_MSGQ_HEADER); dwFileMapSize = (dwFileMapSize + 3) & (~0x3); // DWORD align
m_dwIdleTimeout = dwIdleTimeout;
// Create File Mapping Object
*pszObjectName = DPL_MSGQ_OBJECT_IDCHAR_FILEMAP; m_hFileMap = DNCreateFileMapping(INVALID_HANDLE_VALUE,DNGetNullDacl(), PAGE_READWRITE,(DWORD)0,dwQueueSize,pszObjectName); if (m_hFileMap == NULL) { DPFERR("CreateFileMapping() failed"); hResultCode = DPNERR_GENERIC; goto EXIT_Initialize; } if (GetLastError() == ERROR_ALREADY_EXISTS) { bQueueExists = TRUE; }
if ((dwFlags & DPL_MSGQ_OPEN_FLAG_NO_CREATE) && !bQueueExists) { DPFERR("Open existing queue failed - does not exist"); hResultCode = DPNERR_DOESNOTEXIST; goto EXIT_Initialize; }
// Map file
m_pFileMapAddress = reinterpret_cast<BYTE*>(MapViewOfFile(HANDLE_FROM_DNHANDLE(m_hFileMap),FILE_MAP_ALL_ACCESS,0,0,0)); if (m_pFileMapAddress == NULL) { DPFERR("MapViewOfFile() failed"); hResultCode = DPNERR_OUTOFMEMORY; goto EXIT_Initialize; }
// Create semaphore object
*pszObjectName = DPL_MSGQ_OBJECT_IDCHAR_SEMAPHORE; m_hSemaphore = DNCreateSemaphore(DNGetNullDacl(),0, (dwQueueSize/sizeof(DPL_MSGQ_HEADER))+1,pszObjectName); if (m_hSemaphore == NULL) { DPFERR("CreateSemaphore() failed"); hResultCode = DPNERR_OUTOFMEMORY; goto EXIT_Initialize; }
// Create event object
*pszObjectName = DPL_MSGQ_OBJECT_IDCHAR_EVENT;
// Changed to a semaphore to ensure that we never miss an event signal
m_hEvent = DNCreateSemaphore(DNGetNullDacl(), 0, (dwQueueSize/sizeof(DPL_MSGQ_HEADER))+1, pszObjectName );
if( m_hEvent == NULL ) { DPFERR( "CreateSemaphore() failed" ); hResultCode = DPNERR_OUTOFMEMORY; goto EXIT_Initialize; }
// Create mutex object
*pszObjectName = DPL_MSGQ_OBJECT_IDCHAR_MUTEX; m_hMutex = DNCreateMutex(DNGetNullDacl(),FALSE,pszObjectName); if (m_hMutex == NULL) { DPFERR("CreateMutex() failed"); hResultCode = DPNERR_OUTOFMEMORY; goto EXIT_Initialize; }
// Update structure elements
m_dwPID = dwPID; m_pInfo = reinterpret_cast<DPL_MSGQ_INFO*>(m_pFileMapAddress);
// Initialize msg queue if it didn't exist
if (!bQueueExists) { m_pInfo->dwFlags = dwFlags & 0x0000ffff; // Just last two bytes
m_pInfo->dwStartOffset = 0; m_pInfo->dwEndOffset = 0; m_pInfo->dwQueueSize = dwQueueSize - sizeof(DPL_MSGQ_INFO); m_pInfo->dwFreeBytes = m_pInfo->dwQueueSize; m_pInfo->lRefCount = 0; }
m_pData = (BYTE *) &m_pInfo[1]; m_dwSig = DPL_MSGQ_SIGNATURE;
// Increment user count
Lock(); m_pInfo->lRefCount++; Unlock();
// If we made it this far, everything was okay
hResultCode = DPN_OK;
EXIT_Initialize:
// Free object name string
if (pszObjectName != NULL) DNFree(pszObjectName);
// If there was a problem - close handles
if (hResultCode != DPN_OK) { DPFERR("Errors encountered - closing"); Close(); }
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode); return(hResultCode); }
//**********************************************************************
// ------------------------------
// CMessageQueue::Close
//
// Entry: Nothing
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::Close"
void CMessageQueue::Close(void) { DPFX(DPFPREP, 3,"Parameters: (none)");
if (m_hMutex != NULL) { // Decrement user count
Lock(); if( m_pInfo != NULL ) { m_pInfo->lRefCount--; } Unlock();
DPFX(DPFPREP, 5,"Close Mutex [0x%p]",m_hMutex); DNCloseHandle(m_hMutex); m_hMutex = NULL; } if (m_hEvent != NULL) { DPFX(DPFPREP, 5,"Close Event [0x%p]",m_hEvent); DNCloseHandle(m_hEvent); m_hEvent = NULL; } if (m_hSemaphore != NULL) { DPFX(DPFPREP, 5,"Close Semaphore [0x%p]",m_hSemaphore); DNCloseHandle(m_hSemaphore); m_hSemaphore = NULL; } if (m_pFileMapAddress != NULL) { DPFX(DPFPREP, 5,"UnMap View of File [0x%p]",m_pFileMapAddress); UnmapViewOfFile(m_pFileMapAddress); m_pFileMapAddress = NULL; } if (m_hFileMap != NULL) { DPFX(DPFPREP, 5,"Close FileMap [0x%p]",m_hFileMap); DNCloseHandle(m_hFileMap); m_hFileMap = NULL; } if (m_hReceiveThreadRunningEvent != NULL) { DPFX(DPFPREP, 5,"Close Event [0x%p]",m_hReceiveThreadRunningEvent); DNCloseHandle(m_hReceiveThreadRunningEvent); m_hReceiveThreadRunningEvent = NULL; }
m_pInfo = NULL;
DPFX(DPFPREP, 3,"Returning"); }
//**********************************************************************
// ------------------------------
// CMessageQueue::Terminate
//
// Entry: Nothing
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::Terminate"
void CMessageQueue::Terminate(void) {
BOOL bDone = FALSE;
DPL_MSGQ_HEADER Header;
Header.dwCurrentSize = 0; Header.dwTotalSize = 0; Header.dwMsgId = DPL_MSGQ_MSGID_TERMINATE; Header.hSender = 0xFFFFFFFF; Header.dwFlags = DPL_MSGQ_MSGFLAGS_QUEUESYSTEM; Header.dwCurrentOffset = 0;
DPFX(DPFPREP, 3,"Parameters: (none)");
DNASSERT(m_pInfo != NULL);
while (!bDone) { // Wait until there's enough space for the message
while (sizeof(DWORD) > m_pInfo->dwFreeBytes) WaitForConsumption(INFINITE);
Lock();
// Ensure there is space once we get the lock
// (someone else might have beaten us here)
if (sizeof(DWORD) <= m_pInfo->dwFreeBytes) { AddData(reinterpret_cast<BYTE*>(&Header),sizeof(DPL_MSGQ_HEADER)); bDone = TRUE;
IndicateMessage(); }
Unlock(); }
DPFX(DPFPREP, 3,"Returning"); }
// GetNextMessage
//
// Attempts to retrieve the next message from the queue
//
// pMsgHeader must be large enough to hold a message header.
//
// If no message is present in the queue then this function fills pMsgHeader with an
// idle message header
//
HRESULT CMessageQueue::GetNextMessage( PDPL_MSGQ_HEADER pMsgHeader, BYTE *pbPayload, DWORD *pdwBufferSize ) { HRESULT hr;
Lock();
hr = GetData( (BYTE *) pMsgHeader, sizeof( DPL_MSGQ_HEADER ) );
// If there is no header on the queue fill in the header with an
// idle message
if( hr == DPNERR_DOESNOTEXIST ) { pMsgHeader->dwCurrentSize = sizeof( DPL_MSGQ_HEADER ); pMsgHeader->dwTotalSize = sizeof( DPL_MSGQ_HEADER ); pMsgHeader->dwMsgId = DPL_MSGQ_MSGID_IDLE; pMsgHeader->hSender = 0; pMsgHeader->dwFlags = DPL_MSGQ_MSGFLAGS_QUEUESYSTEM; pMsgHeader->dwCurrentOffset = 0; Unlock();
return DPN_OK; } //// DBG
else if( FAILED( hr ) ) { DNASSERT( FALSE ); } else if( pMsgHeader->dwMsgId == 0xFFFFFFFF ) { DNASSERT( FALSE ); }
DWORD dwPayloadSize = pMsgHeader->dwCurrentSize;
// Otherwise it's a valid message of some kind
if( *pdwBufferSize < dwPayloadSize || pbPayload == NULL ) { *pdwBufferSize = dwPayloadSize; Unlock(); return DPNERR_BUFFERTOOSMALL; }
*pdwBufferSize = dwPayloadSize;
Consume( sizeof(DPL_MSGQ_HEADER) );
// There is no payload, only a header. Return here.
if( dwPayloadSize == 0 ) { Unlock(); return DPN_OK; }
hr = GetData( pbPayload, dwPayloadSize );
if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Error getting IPC queue message payload" ); DNASSERT( FALSE ); Unlock(); return hr; }
Consume( dwPayloadSize ); Unlock();
return DPN_OK; }
// Consume
//
// Marks dwSize bytes as consumed
//
// Needs LOCK()
void CMessageQueue::Consume( const DWORD dwSize ) { DWORD dwAlignedSize = (dwSize + 3) & (~0x3);
m_pInfo->dwStartOffset += dwAlignedSize;
if( m_pInfo->dwStartOffset >= m_pInfo->dwQueueSize ) { m_pInfo->dwStartOffset -= m_pInfo->dwQueueSize; }
m_pInfo->dwFreeBytes += dwAlignedSize;
DNASSERT( m_pInfo->dwFreeBytes <= m_pInfo->dwFreeBytes );
IndicateConsumption(); }
// GetData
//
// Get dwSize bytes from the queue. If the queue is empty this function will return
// DPNERR_DOESNOTEXIST. Once this function returns the dwSize bytes will be consumed
//
// REQUIRES LOCK
//
HRESULT CMessageQueue::GetData( BYTE *pbData, DWORD dwSize ) { if( m_pInfo->dwQueueSize == m_pInfo->dwFreeBytes ) { return DPNERR_DOESNOTEXIST; }
if( pbData == NULL ) { return DPNERR_BUFFERTOOSMALL; }
// Calculate aligned size
DWORD dwAlignedSize = (dwSize + 3) & (~0x3);
// Data block we want is wrapped
if( m_pInfo->dwStartOffset+dwAlignedSize > m_pInfo->dwQueueSize ) { DWORD cbBytesLeft = m_pInfo->dwQueueSize - m_pInfo->dwStartOffset; DWORD cbSecondBlockAligned = dwAlignedSize - (cbBytesLeft); DWORD cbSecondBlock = dwSize - (cbBytesLeft);
DNASSERT( dwAlignedSize > cbBytesLeft);
memcpy( pbData, m_pData + m_pInfo->dwStartOffset, cbBytesLeft); memcpy( pbData + cbBytesLeft, m_pData , cbSecondBlock ); } // Data block is contiguous
else { memcpy( pbData, m_pData + m_pInfo->dwStartOffset, dwSize ); }
return DPN_OK; }
//**********************************************************************
// ------------------------------
// CMessageQueue::AddData
//
// Entry: BYTE *const pBuffer
// const DWORD dwSize
//
// Exit: HRESULT
// ------------------------------
//
// REQUIRES LOCK!!
//
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::AddData"
HRESULT CMessageQueue::AddData(BYTE *const pBuffer, const DWORD dwSize) { HRESULT hResultCode; DWORD dwAlignedSize;
DPFX(DPFPREP, 3,"Parameters: pBuffer [0x%p], dwSize [%ld]",pBuffer,dwSize);
dwAlignedSize = (dwSize + 3) & (~0x3);
// Check to ensure there is space
if( dwAlignedSize > m_pInfo->dwFreeBytes ) { hResultCode = DPNERR_BUFFERTOOSMALL; goto Exit; }
// We have a wrapping condition
if( (m_pInfo->dwEndOffset+dwAlignedSize) > m_pInfo->dwQueueSize ) { DWORD cbBytesLeft = m_pInfo->dwQueueSize - m_pInfo->dwEndOffset; DWORD cbSecondBlockAligned = dwAlignedSize - cbBytesLeft; DWORD cbSecondBlock = dwSize - cbBytesLeft;
DNASSERT( dwAlignedSize > cbBytesLeft );
memcpy( m_pData + m_pInfo->dwEndOffset, pBuffer, cbBytesLeft ); memcpy( m_pData, pBuffer + cbBytesLeft, cbSecondBlock );
m_pInfo->dwEndOffset = cbSecondBlockAligned; } // Queue is in the middle
else { memcpy( m_pData + m_pInfo->dwEndOffset, pBuffer, dwSize ); m_pInfo->dwEndOffset += dwAlignedSize; }
m_pInfo->dwFreeBytes -= dwAlignedSize;
hResultCode = DPN_OK;
Exit: DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode); return(hResultCode); }
//**********************************************************************
// ------------------------------
// CMessageQueue::Send
//
// Entry: BYTE *const pBuffer
// const DWORD dwSize
// const DWORD dwFlags
//
// Exit: HRESULT
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::Send"
HRESULT CMessageQueue::Send(BYTE *const pBuffer, const DWORD dwSize, const DWORD dwTimeOut, const DWORD dwMsgFlags, const DWORD dwFlags) { HRESULT hResultCode; DWORD dwMsgSize; // DWORD aligned
DWORD dwTotalMsgSize; // Msg + Header - DWORD aligned
DPL_MSGQ_HEADER Header; BOOL bDone; DWORD dwTimeRemaining; DWORD dwTimeStart; DWORD dwTimeFinish;
DPFX(DPFPREP, 3,"Parameters: pBuffer [0x%p], dwSize [%ld], dwFlags [0x%lx]",pBuffer,dwSize,dwFlags);
DNASSERT( pBuffer != NULL ); DNASSERT( dwSize <= m_pInfo->dwQueueSize );
dwTimeRemaining = dwTimeOut;
// Need DWORD aligned size
dwMsgSize = (dwSize + 3) & (~0x3); dwTotalMsgSize = dwMsgSize + sizeof(DPL_MSGQ_HEADER);
// Place the message into the MsgQ
// Check to see if fragmentation is required
// If we're at the end of the MsgQ and there isn't enough space for a Msg Header, REALIGN
if (dwTotalMsgSize <= m_pInfo->dwQueueSize) { DPFX(DPFPREP, 5,"Message does not need to be fragmented");
Header.dwMsgId = DPL_MSGQ_MSGID_SEND; Header.dwCurrentOffset = 0; Header.dwCurrentSize = dwSize; Header.dwTotalSize = dwSize; Header.hSender = m_hSender; Header.dwFlags = dwMsgFlags; // Mark this as a user message
//// DBG
if( Header.dwMsgId == 0xFFFFFFFF ) { DNASSERT( FALSE ); }
bDone = FALSE; while (!bDone) { // Wait until there's enough space for the message
while (dwTotalMsgSize > m_pInfo->dwFreeBytes) { if (dwTimeOut != INFINITE) { dwTimeStart = GETTIMESTAMP(); }
if (!WaitForConsumption(dwTimeRemaining)) { return(DPNERR_TIMEDOUT); }
if (dwTimeOut != INFINITE) { dwTimeFinish = GETTIMESTAMP(); if ((dwTimeFinish - dwTimeStart) > dwTimeRemaining) { return(DPNERR_TIMEDOUT); } dwTimeRemaining -= (dwTimeFinish - dwTimeStart); } }
Lock();
// Ensure there is space once we get the lock
// (someone else might have beaten us here)
if (dwTotalMsgSize <= m_pInfo->dwFreeBytes) { //// DBG
if( Header.dwMsgId == 0xFFFFFFFF ) { DNASSERT( FALSE ); }
hResultCode = AddData(reinterpret_cast<BYTE*>(&Header),sizeof(DPL_MSGQ_HEADER)); DNASSERT(hResultCode == DPN_OK); hResultCode = AddData(pBuffer,dwSize); DNASSERT(hResultCode == DPN_OK); bDone = TRUE;
IndicateMessage(); }
Unlock(); hResultCode = DPN_OK; } } else { DPFX(DPFPREP, 5,"Message needs to be fragmented"); DNASSERT(FALSE); hResultCode = DPNERR_GENERIC; #pragma TODO(a-minara,"Implement this")
}
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode); return(hResultCode); }
//**********************************************************************
// ------------------------------
// DPLIsApplicationAvailable
//
// Entry: const DWORD dwPID PID to check
//
// Exit: BOOL TRUE If the application's queue's flags were retrieved successfully
// and the application is waiting for a connection
// FALSE Otherwise
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DPLIsApplicationAvailable"
BOOL DPLIsApplicationAvailable(const DWORD dwPID) { BOOL bReturnCode; CMessageQueue MessageQueue;
DPFX(DPFPREP, 3,"Parameters: dwPID [%lx]",dwPID);
if (MessageQueue.Open(dwPID,DPL_MSGQ_OBJECT_SUFFIX_APPLICATION,DPL_MSGQ_SIZE, INFINITE, DPL_MSGQ_OPEN_FLAG_NO_CREATE) != DPN_OK) { DPFERR("Could not open Msg Queue"); return(FALSE); }
bReturnCode = MessageQueue.IsAvailable();
MessageQueue.Close();
DPFX(DPFPREP, 3,"Returning: [%ld]",bReturnCode); return(bReturnCode); }
//**********************************************************************
// ------------------------------
// DPLMakeApplicationUnavailable
//
// Entry: const DWORD dwPID PID to check
//
// Exit: HRESULT DPN_OK If the application was waiting for a connection
// and made unavailable
// DPNERR_INVALIDAPPLICATION
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DPLMakeApplicationUnavailable"
HRESULT DPLMakeApplicationUnavailable(const DWORD dwPID) { HRESULT hResultCode; CMessageQueue MessageQueue;
DPFX(DPFPREP, 3,"Parameters: dwPID [%lx]",dwPID);
if (MessageQueue.Open(dwPID,DPL_MSGQ_OBJECT_SUFFIX_APPLICATION,DPL_MSGQ_SIZE, DPL_MSGQ_OPEN_FLAG_NO_CREATE,INFINITE) != DPN_OK) { DPFERR("Could not open Msg Queue"); return(DPNERR_INVALIDAPPLICATION); }
if ((hResultCode = MessageQueue.MakeUnavailable()) != DPN_OK) { DPFERR("Could not make application unavailable"); hResultCode = DPNERR_INVALIDAPPLICATION; }
MessageQueue.Close();
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode); return(hResultCode); }
//**********************************************************************
// ------------------------------
// DPLProcessMessageQueue
//
// Entry:
//
// Exit: HRESULT DPN_OK If the application was waiting for a connection
// and made unavailable
// DPNERR_INVALIDAPPLICATION
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DPLProcessMessageQueue"
DWORD WINAPI DPLProcessMessageQueue(PVOID pvReceiveQueue) { HRESULT hResultCode; DPL_MSGQ_HEADER dplMsgHeader; BYTE *pBuffer = NULL; DWORD dwBufferSize = 0; DWORD dwSize; CMessageQueue *pReceiveQueue; DWORD dwWaitResult;
DPFX(DPFPREP, 3,"Parameters: (none)");
COM_CoInitialize(NULL);
pReceiveQueue = static_cast<CMessageQueue*>(pvReceiveQueue);
// Indicate we are running
pReceiveQueue->MakeReceiving();
while(1) { dwWaitResult = pReceiveQueue->WaitForMessages();
while( 1 ) { dwSize = dwBufferSize; hResultCode = pReceiveQueue->GetNextMessage(&dplMsgHeader, pBuffer, &dwSize);
if( hResultCode == DPNERR_BUFFERTOOSMALL ) { if( pBuffer ) delete [] pBuffer;
pBuffer = new BYTE[dwSize]; if( pBuffer == NULL ) { DPFX(DPFPREP, 0, "Error allocating memory" ); DNASSERT( FALSE ); goto EXIT_DPLProcessMessageQueue; }
dwBufferSize = dwSize; } else if( FAILED( hResultCode ) ) { DPFX(DPFPREP, 0, "Error while getting messages from the queue" ); DNASSERT( FALSE ); goto EXIT_DPLProcessMessageQueue; } else { break; } }
DPFX(DPFPREP, 5,"dwMsgId [0x%lx] dwTotalSize [0x%lx] dwCurrentSize [0x%lx] dwCurrentOffset [0x%lx] ", dplMsgHeader.dwMsgId, dplMsgHeader.dwTotalSize, dplMsgHeader.dwCurrentSize, dplMsgHeader.dwCurrentOffset );
switch(dplMsgHeader.dwMsgId) { case DPL_MSGQ_MSGID_IDLE: { DPFX(DPFPREP, 6,"Idle message fired" ); DWORD dwMsgId = DPL_MSGID_INTERNAL_IDLE_TIMEOUT; // 7/17/2000(RichGr) - IA64: Change last parm from sizeof(DWORD) to sizeof(BYTE*).
hResultCode = pReceiveQueue->CallMessageHandler(NULL,DPL_MSGQ_MSGFLAGS_USER1,(BYTE *) &dwMsgId,sizeof(BYTE*)); } break; case DPL_MSGQ_MSGID_SEND: { DPFX(DPFPREP, 5,"DPL_MSGQ_MSGID_SEND"); hResultCode = pReceiveQueue->CallMessageHandler(dplMsgHeader.hSender,dplMsgHeader.dwFlags,pBuffer,dwSize); break; }
case DPL_MSGQ_MSGID_TERMINATE: { DPFX(DPFPREP, 5,"DPL_MSGQ_MSGID_TERMINATE"); hResultCode = DPN_OK; goto EXIT_DPLProcessMessageQueue; break; }
default: { DPFX(DPFPREP, 5,"UNKNOWN - should never get here"); DNASSERT(FALSE); hResultCode = DPNERR_GENERIC; goto EXIT_DPLProcessMessageQueue; break; } } }
EXIT_DPLProcessMessageQueue:
if( pBuffer ) delete [] pBuffer;
// Indicate we are no longer running
pReceiveQueue->MakeNotReceiving();
COM_CoUninitialize();
DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode); return(hResultCode); }
|