/*========================================================================== * * 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 CHAR cSuffix, const DWORD dwQueueSize, const DWORD dwIdleTimeout, const DWORD dwFlags) { HRESULT hResultCode; PSTR pszObjectName = NULL; BOOL bQueueExists = FALSE; DWORD dwFileMapSize; DPFX(DPFPREP, 3,"Parameters: dwPID [0x%lx], cSuffix [%c], dwQueueSize [%ld], dwFlags [0x%lx]", dwPID,cSuffix,dwQueueSize,dwFlags); // 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 = CreateEventA(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 = (PSTR)DNMalloc(1 + (sizeof(DWORD)*2) + 1 + 1)) == NULL) { DPFERR("Could not allocate space for lpszObjectName"); hResultCode = DPNERR_OUTOFMEMORY; goto EXIT_Initialize; } wsprintfA(pszObjectName,"-%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 = CreateFileMappingA(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(MapViewOfFile(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 = CreateSemaphoreA(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 = CreateSemaphoreA(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 = CreateMutexA(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(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); CloseHandle(m_hMutex); m_hMutex = NULL; } if (m_hEvent != NULL) { DPFX(DPFPREP, 5,"Close Event [0x%p]",m_hEvent); CloseHandle(m_hEvent); m_hEvent = NULL; } if (m_hSemaphore != NULL) { DPFX(DPFPREP, 5,"Close Semaphore [0x%p]",m_hSemaphore); CloseHandle(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); CloseHandle(m_hFileMap); m_hFileMap = NULL; } if (m_hReceiveThreadRunningEvent != NULL) { DPFX(DPFPREP, 5,"Close Event [0x%p]",m_hReceiveThreadRunningEvent); CloseHandle(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(&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; } //// DEBUG 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; DPL_MSGQ_HEADER *pHeader; 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 //// DEBUG 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) { //// DEBUG if( Header.dwMsgId == 0xFFFFFFFF ) { DNASSERT( FALSE ); } hResultCode = AddData(reinterpret_cast(&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 *pData; BYTE *pBuffer = NULL; DWORD dwBufferSize = 0; DWORD dwSize; CMessageQueue *pReceiveQueue; BYTE *pMsg; DWORD dwWaitResult; DPFX(DPFPREP, 3,"Parameters: (none)"); COM_CoInitialize(NULL); pReceiveQueue = static_cast(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); }