|
|
/*==========================================================================
* * Copyright (C) 2000 Microsoft Corporation. All Rights Reserved. * * File: DPNSVRQ.h * Content: DirectPlay8 Server Queues Header *@@BEGIN_MSINTERNAL * History: * Date By Reason * ==== == ====== * 03/19/00 rmt Modified from dplmsgq * 04/03/2001 RichGr Bug #325752 - Improved Queue mutex so opens, updates and closes don't clash. *@@END_MSINTERNAL * ***************************************************************************/
#ifndef __DPNSVRQ_H__
#define __DPNSVRQ_H__
#define DPNSVR_MSGQ_SIGNATURE 'QMSD'
//**********************************************************************
// Constant definitions
//**********************************************************************
#define DPNSVR_MSGQ_OBJECT_IDCHAR_FILEMAP 'F'
#define DPNSVR_MSGQ_OBJECT_IDCHAR_MUTEX 'M'
#define DPNSVR_MSGQ_OBJECT_IDCHAR_EVENT 'E'
#define DPNSVR_MSGQ_OBJECT_IDCHAR_EVENT2 'V'
#define DPNSVR_MSGQ_OBJECT_IDCHAR_SEMAPHORE 'S'
//
// Message Queue Flags
//
#define DPNSVR_MSGQ_FLAG_AVAILABLE 0x00001
#define DPNSVR_MSGQ_FLAG_RECEIVING 0x00010
#define DPNSVR_MSGQ_OPEN_FLAG_NO_CREATE 0x10000
//
// Message Queue File Size
//
#define DPNSVR_MSGQ_SIZE 0x010000
//
// Internal Message IDs
//
#define DPNSVR_MSGQ_MSGID_SEND 0x0001
#define DPNSVR_MSGQ_MSGID_TERMINATE 0x0003
#define DPNSVR_MSGQ_MSGID_IDLE 0x0004
#define DPNSVR_MSGQ_MSGFLAGS_QUEUESYSTEM 0x0001
#define DPNSVR_MSGQ_MSGFLAGS_USER1 0x0002
#define DPNSVR_MSGQ_MSGFLAGS_USER2 0x0004
//**********************************************************************
// Macro definitions
//**********************************************************************
//**********************************************************************
// Structure definitions
//**********************************************************************
#pragma pack(push,4)
//
// Message Queue File Map Info
//
typedef struct _DPNSVR_MSGQ_INFO { DWORD dwFlags; // Queue usage flags
DWORD dwStartOffset; DWORD dwEndOffset; DWORD dwFreeBytes; DWORD dwQueueSize; LONG lRefCount; // Number of connections
} DPNSVR_MSGQ_INFO, *PDPNSVR_MSGQ_INFO;
//
// Message Queue Send Message
//
typedef struct _DPNSVR_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
} DPNSVR_MSGQ_HEADER, *PDPNSVR_MSGQ_HEADER;
//
// Message Queue Terminate Message
//
typedef struct _DPNSVR_MSGQ_TERMINATE { DWORD dwMsgId; } DPNSVR_MSGQ_TERMINATE, *PDPNSVR_MSGQ_TERMINATE;
#pragma pack(pop)
//
// Message Handler Callback
//
typedef HRESULT (*PFNDPNSVRMSGQMESSAGEHANDLER)(DPNHANDLE,const PVOID,DWORD,BYTE *const,const DWORD);
//**********************************************************************
// Variable definitions
//**********************************************************************
//**********************************************************************
// Function prototypes
//**********************************************************************
//**********************************************************************
// Class prototypes
//**********************************************************************
class CDPNSVRIPCQueue { public: CDPNSVRIPCQueue() { m_hFileMap = NULL; m_hEvent = NULL; m_hQueueGUIDMutex = NULL; m_hSemaphore = NULL; m_pFileMapAddress = NULL; m_pInfo = NULL; m_pData = NULL; m_hSender = NULL; m_pfnMessageHandler = NULL; m_pvSenderContext = NULL; m_hReceiveThreadRunningEvent = NULL; };
~CDPNSVRIPCQueue() { };
void SetMessageHandler(DPNHANDLE hSender,PFNDPNSVRMSGQMESSAGEHANDLER pfn) { m_hSender = hSender; m_pfnMessageHandler = pfn; };
void SetSenderContext(PVOID pvSenderContext) { m_pvSenderContext = pvSenderContext; };
HRESULT CallMessageHandler(const PVOID pvSenderContext,DWORD dwMessageFlags,BYTE *const pBuffer,const DWORD dwBufferSize) { return((m_pfnMessageHandler)(m_hSender,pvSenderContext,dwMessageFlags,pBuffer,dwBufferSize)); };
HRESULT Open(const GUID * const pguidQueueName, const DWORD dwQueueSize, const DWORD dwFlags); void Close(void); void CloseHandles(void);
LONG GetRefCount(void) { DWORD lRefCount;
if (m_pInfo == NULL) { return(0); }
Lock(); lRefCount = m_pInfo->lRefCount; Unlock();
return(lRefCount); };
HRESULT AddData( BYTE *const pBuffer,const DWORD dwSize );
HRESULT Send(BYTE *const pBuffer,const DWORD dwSize,const DWORD dwTimeOut,const DWORD dwMessageFlags,const DWORD dwFlags);
void Lock(void) { DNWaitForSingleObject(m_hQueueGUIDMutex,INFINITE); };
void Unlock(void) { DNReleaseMutex(m_hQueueGUIDMutex); };
void WaitForMessages(void) { DNWaitForSingleObject(m_hSemaphore,INFINITE); };
void IndicateMessage(void) { DNReleaseSemaphore(m_hSemaphore,1,NULL); };
BOOL WaitForConsumption(const DWORD dwTimeOut) { DWORD dwError;
dwError = DNWaitForSingleObject(m_hEvent,dwTimeOut); if (dwError==WAIT_OBJECT_0) { return(TRUE); } return(FALSE); };
void IndicateConsumption(void) { //DNSetEvent(m_hEvent); // Will auto-reset (i.e. pulse)
DNReleaseSemaphore( m_hEvent, 1, NULL ); };
void MakeAvailable(void) { Lock(); m_pInfo->dwFlags |= DPNSVR_MSGQ_FLAG_AVAILABLE; Unlock(); };
HRESULT MakeUnavailable(void) {
HRESULT hResultCode;
Lock(); if (m_pInfo->dwFlags & DPNSVR_MSGQ_FLAG_AVAILABLE) { m_pInfo->dwFlags &= (~DPNSVR_MSGQ_FLAG_AVAILABLE); hResultCode = DPN_OK; } else { hResultCode = DPNERR_ALREADYCONNECTED; } Unlock();
return(hResultCode); };
void MakeReceiving(void) { Lock(); m_pInfo->dwFlags |= DPNSVR_MSGQ_FLAG_RECEIVING; Unlock(); DNSetEvent(m_hReceiveThreadRunningEvent); };
void MakeNotReceiving(void) { DNResetEvent(m_hReceiveThreadRunningEvent); Lock(); m_pInfo->dwFlags &= (~DPNSVR_MSGQ_FLAG_RECEIVING); Unlock(); };
BOOL WaitForReceiveThread(const DWORD dwTimeOut) { DWORD dwError;
dwError = DNWaitForSingleObject(m_hReceiveThreadRunningEvent,dwTimeOut); if (dwError==WAIT_OBJECT_0) { return(TRUE); } return(FALSE); };
BOOL IsOpen(void) const { if (m_hFileMap!= NULL) { return(TRUE); } return(FALSE); };
BOOL IsAvailable(void) const { if (m_pInfo->dwFlags & DPNSVR_MSGQ_FLAG_AVAILABLE) { return(TRUE); } return(FALSE); };
BOOL IsReceiving(void) const { if (m_pInfo->dwFlags & DPNSVR_MSGQ_FLAG_RECEIVING) { return(TRUE); } };
HRESULT GetNextMessage( PDPNSVR_MSGQ_HEADER pMsgHeader, PBYTE pbPayload, DWORD *pdwBufferSize );
void Terminate(void);
DNHANDLE GetReceiveSemaphoreHandle() { return m_hSemaphore; };
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)
PBYTE m_pFileMapAddress; // File Mapping address
DPNSVR_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_hQueueGUIDMutex; // Mutex handle
DNHANDLE m_hEvent; // Event handle
DNHANDLE m_hSemaphore; // Semaphore handle
PFNDPNSVRMSGQMESSAGEHANDLER m_pfnMessageHandler; DPNHANDLE m_hSender;
PVOID m_pvSenderContext; // For all SEND messages
};
#undef DPF_MODNAME
#undef DPF_SUBCOMP
#endif // __DPLMSGQ_H__
|