|
|
/*==========================================================================
* * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved. * * File: DPLMsgQ.h * Content: DirectPlay Lobby Message Queues Header File *@@BEGIN_MSINTERNAL * History: * Date By Reason * ==== == ====== * 02/21/00 mjn Created * 04/26/00 mjn Fixed AddData() to return HRESULT * 07/07/2000 rmt *@@END_MSINTERNAL * ***************************************************************************/
#ifndef __DPLMSGQ_H__
#define __DPLMSGQ_H__
//**********************************************************************
// Constant definitions
//**********************************************************************
//
// Message Queue Object IDs
//
#define DPL_MSGQ_OBJECT_IDCHAR_FILEMAP _T('F')
#define DPL_MSGQ_OBJECT_IDCHAR_MUTEX _T('M')
#define DPL_MSGQ_OBJECT_IDCHAR_EVENT _T('E')
#define DPL_MSGQ_OBJECT_IDCHAR_EVENT2 _T('V')
#define DPL_MSGQ_OBJECT_IDCHAR_SEMAPHORE _T('S')
//
// Message Queue Object Suffixes
//
#define DPL_MSGQ_OBJECT_SUFFIX_CLIENT _T('C')
#define DPL_MSGQ_OBJECT_SUFFIX_APPLICATION _T('A')
//
// Message Queue Flags
//
#define DPL_MSGQ_FLAG_AVAILABLE 0x00001
#define DPL_MSGQ_FLAG_RECEIVING 0x00010
#define DPL_MSGQ_OPEN_FLAG_NO_CREATE 0x10000
//
// Message Queue File Size
//
// Increased so user can send a 64K message
#define DPL_MSGQ_SIZE 0x010030
//
// Internal Message IDs
//
#define DPL_MSGQ_MSGID_SEND 0x0001
#define DPL_MSGQ_MSGID_TERMINATE 0x0003
#define DPL_MSGQ_MSGID_IDLE 0x0004
#define DPL_MSGQ_MSGFLAGS_QUEUESYSTEM 0x0001
#define DPL_MSGQ_MSGFLAGS_USER1 0x0002
#define DPL_MSGQ_MSGFLAGS_USER2 0x0004
#define DPL_MSGQ_SIGNATURE 'QMLD'
#undef DPF_SUBCOMP
#define DPF_SUBCOMP DN_SUBCOMP_LOBBY
//**********************************************************************
// Macro definitions
//**********************************************************************
//**********************************************************************
// Structure definitions
//**********************************************************************
#pragma pack(push,4)
//
// Message Queue File Map Info
//
typedef struct _DPL_MSGQ_INFO { DWORD dwFlags; // Queue usage flags
DWORD dwStartOffset; DWORD dwEndOffset; DWORD dwFreeBytes; DWORD dwQueueSize; LONG lRefCount; // Number of connections
} DPL_MSGQ_INFO, *PDPL_MSGQ_INFO;
//
// Message Queue Send Message
//
typedef struct _DPL_MSGQ_SEND { DWORD dwCurrentSize; // Size of this frame (in BYTES)
DWORD dwTotalSize; // Total size of message
DWORD dwMsgId; // Message ID
DPNHANDLE hSender; DWORD dwFlags; DWORD dwCurrentOffset; // Offset of this frame in message
} DPL_MSGQ_HEADER, *PDPL_MSGQ_HEADER;
//
// Message Queue Terminate Message
//
typedef struct _DPL_MSGQ_TERMINATE { DWORD dwMsgId; } DPL_MSGQ_TERMINATE, *PDPL_MSGQ_TERMINATE;
#pragma pack(pop)
//
// Message Handler Callback
//
typedef HRESULT (*PFNDPLMSGQMESSAGEHANDLER)(PVOID,const DPNHANDLE,DWORD, BYTE *const,const DWORD);
//**********************************************************************
// Variable definitions
//**********************************************************************
//**********************************************************************
// Function prototypes
//**********************************************************************
BOOL DPLIsApplicationAvailable(const DWORD dwPid); HRESULT DPLMakeApplicationUnavailable(const DWORD dwPid); DWORD WINAPI DPLProcessMessageQueue(PVOID pvReceiveQueue);
//**********************************************************************
// Class prototypes
//**********************************************************************
class CMessageQueue { public: CMessageQueue() { m_dwPID = 0; m_hFileMap = NULL; m_hEvent = NULL; m_hMutex = NULL; m_hSemaphore = NULL; m_pFileMapAddress = NULL; m_pInfo = NULL; m_pvContext = NULL; m_pfnMessageHandler = NULL; m_hSender = 0xFFFFFFFF; m_hReceiveThreadRunningEvent = NULL; m_dwIdleTimeout = INFINITE; };
// ~CMessageQueue() { };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::SetMessageHandler"
void CMessageQueue::SetMessageHandler(PVOID pvContext,PFNDPLMSGQMESSAGEHANDLER pfn ) { DNASSERT(pfn != NULL);
m_pvContext = pvContext; m_pfnMessageHandler = pfn; };
void CMessageQueue::SetSenderHandle(DPNHANDLE hSender) { m_hSender = hSender; };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::CallMessageHandler"
HRESULT CMessageQueue::CallMessageHandler(const DPNHANDLE hSender, DWORD dwMessageFlags, BYTE *const pBuffer, const DWORD dwBufferSize) { DNASSERT(m_pfnMessageHandler != NULL);
return((m_pfnMessageHandler)(m_pvContext,hSender,dwMessageFlags,pBuffer,dwBufferSize)); };
HRESULT CMessageQueue::Open(const DWORD dwPID, const TCHAR cSuffix, const DWORD dwQueueSize, const DWORD dwIdleTimeout, const DWORD dwFlags );
void CMessageQueue::Close(void);
LONG CMessageQueue::GetRefCount(void) { DWORD lRefCount;
if (m_pInfo == NULL) return(0);
Lock(); lRefCount = m_pInfo->lRefCount; Unlock();
return(lRefCount); };
HRESULT CMessageQueue::AddData(BYTE *const pBuffer, const DWORD dwSize);
HRESULT CMessageQueue::Send(BYTE *const pBuffer, const DWORD dwSize, const DWORD dwTimeOut, const DWORD dwMessageFlags, const DWORD dwFlags);
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::Lock"
void CMessageQueue::Lock(void) { DNASSERT(m_hMutex != NULL); DNWaitForSingleObject(m_hMutex,INFINITE); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::Unlock"
void CMessageQueue::Unlock(void) { DNASSERT(m_hMutex != NULL); DNReleaseMutex(m_hMutex); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::WaitForMessages"
DWORD CMessageQueue::WaitForMessages(void) { DNASSERT(m_hSemaphore != NULL); return DNWaitForSingleObject(m_hSemaphore,m_dwIdleTimeout); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::IndicateMessage"
void CMessageQueue::IndicateMessage(void) { DNASSERT(m_hSemaphore != NULL); DNReleaseSemaphore(m_hSemaphore,1,NULL); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::WaitForConsumption"
BOOL CMessageQueue::WaitForConsumption(const DWORD dwTimeOut) { DWORD dwError;
DNASSERT(m_hEvent != NULL); dwError = DNWaitForSingleObject(m_hEvent,dwTimeOut); if (dwError==WAIT_OBJECT_0) { return(TRUE); } return(FALSE); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::IndicateConsumption"
void CMessageQueue::IndicateConsumption(void) { DNASSERT(m_hEvent != NULL); //DNSetEvent(m_hEvent); // Will auto-reset (i.e. pulse)
DNReleaseSemaphore( m_hEvent, 1, NULL ); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::MakeAvailable"
void CMessageQueue::MakeAvailable(void) { DNASSERT(m_pInfo != NULL);
Lock();
m_pInfo->dwFlags |= DPL_MSGQ_FLAG_AVAILABLE;
Unlock(); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::MakeUnavailable"
HRESULT CMessageQueue::MakeUnavailable(void) {
HRESULT hResultCode;
DNASSERT(m_pInfo != NULL);
Lock();
if (m_pInfo->dwFlags & DPL_MSGQ_FLAG_AVAILABLE) { m_pInfo->dwFlags &= (~DPL_MSGQ_FLAG_AVAILABLE); hResultCode = DPN_OK; } else { hResultCode = DPNERR_ALREADYCONNECTED; }
Unlock();
return(hResultCode); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::MakeReceiving"
void CMessageQueue::MakeReceiving(void) { DNASSERT(m_pInfo != NULL);
Lock(); m_pInfo->dwFlags |= DPL_MSGQ_FLAG_RECEIVING; Unlock(); DNSetEvent(m_hReceiveThreadRunningEvent); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::MakeNotReceiving"
void CMessageQueue::MakeNotReceiving(void) { DNASSERT(m_pInfo != NULL);
DNResetEvent(m_hReceiveThreadRunningEvent); Lock(); m_pInfo->dwFlags &= (~DPL_MSGQ_FLAG_RECEIVING); Unlock(); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::WaitForReceiveThread"
BOOL CMessageQueue::WaitForReceiveThread(const DWORD dwTimeOut) { DWORD dwError;
DNASSERT(m_hEvent != NULL); dwError = DNWaitForSingleObject(m_hReceiveThreadRunningEvent,dwTimeOut); if (dwError==WAIT_OBJECT_0) { return(TRUE); } return(FALSE); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::IsOpen"
BOOL CMessageQueue::IsOpen(void) const { if (m_hFileMap!= NULL) return(TRUE); else return(FALSE); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::IsAvailable"
BOOL CMessageQueue::IsAvailable(void) const { DNASSERT(m_pInfo != NULL);
if (m_pInfo->dwFlags & DPL_MSGQ_FLAG_AVAILABLE) return(TRUE); else return(FALSE); };
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::IsReceiving"
BOOL CMessageQueue::IsReceiving(void) const { DNASSERT(m_pInfo != NULL);
if (m_pInfo->dwFlags & DPL_MSGQ_FLAG_RECEIVING) return(TRUE); else return(FALSE); };
HRESULT GetNextMessage( PDPL_MSGQ_HEADER pMsgHeader, PBYTE pbPayload, DWORD *pdwBufferSize ); /*
#undef DPF_MODNAME
#define DPF_MODNAME "CMessageQueue::Realign"
void CMessageQueue::Realign(void) { DNASSERT(m_pInfo != NULL);
m_pInfo->dwFirstMsgOffset = 0; m_pInfo->dwFreeSpaceAtEnd = m_pInfo->dwTotalUsableSpace - (m_pInfo->dwNextFreeOffset - m_pInfo->dwFirstMsgOffset); m_pInfo->dwTotalFreeSpace = m_pInfo->dwFreeSpaceAtEnd;
};*/
void CMessageQueue::Terminate(void);
private:
// 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
//
// Needs LOCK()
//
HRESULT GetData( BYTE *pbData, DWORD dwSize );
// Consume
//
// Marks dwSize bytes as consumed
//
// Needs LOCK()
void Consume( const DWORD dwSize );
DWORD m_dwSig; // Signature (ensure initialized)
DWORD m_dwPID; // Queue PID
PBYTE m_pFileMapAddress; // File Mapping address
DPL_MSGQ_INFO *m_pInfo; // Message queue file mapping info
PBYTE m_pData; // Message data starts here
DNHANDLE m_hReceiveThreadRunningEvent;
// Notes:
// Each message queue has four shared memory items: file map, mutex, event, semaphore.
// The file map is a circular queue of messages.
// The mutex controls access to the file map.
// The event signals when an item has been taken off the queue by the consumer.
// The semaphore indicates to the consumer that there are messages in the queue
DNHANDLE m_hFileMap; // File Mapping handle
DNHANDLE m_hMutex; // Mutex handle
DNHANDLE m_hEvent; // Event handle
DNHANDLE m_hSemaphore; // Semaphore handle
PFNDPLMSGQMESSAGEHANDLER m_pfnMessageHandler; PVOID m_pvContext;
DPNHANDLE m_hSender; // For all SEND messages
DWORD m_dwIdleTimeout; // Amount of time between idle messages
};
#undef DPF_MODNAME
#endif // __DPLMSGQ_H__
|