|
|
// Direct Play object class implementation
#ifndef _DP_SPIMP_H
#define _DP_SPIMP_H
#include "..\dplay\dplayi.h"
#include "socket.h"
// Begin: declaration of main implementation class for IDirectPlay
#define MAX_MSG (512 + sizeof(DPHDR))
#define MAX_PLAYERS 256
typedef struct { DPID pid; char chNickName[DPSHORTNAMELEN]; char chFullName[DPLONGNAMELEN ]; HANDLE hEvent; BOOL bPlayer; BOOL bValid; BOOL bLocal; DPID *aGroup; SOCKADDR sockaddr; } PLAYER_RECORD;
typedef struct { DPSESSIONDESC dpDesc; SOCKADDR sockaddr; DWORD dwUnique; USHORT usGamePort; } NS_SESSION_SAVE;
/****************************************************************************
* * DIRECTPLAY MESSAGES * * Errors are represented by negative values and cannot be combined. * ****************************************************************************/
#pragma pack(push, 1)
#define SYS_MSG 0x8000
typedef struct { union { DWORD dwConnect1; struct { USHORT usCookie; USHORT usGame; }; }; union { DWORD dwConnect2; struct { USHORT to; USHORT from; }; }; union { DWORD dwConnect3; struct { USHORT usSeq; USHORT usCount; }; }; } DPHDR;
typedef struct { DPHDR dpHdr; char chMsgCompose[1000]; } MSG_BUILDER;
#define SP_ENUM_COOKIE 0x794b
typedef struct { DPHDR dpHdr; DPMSG_GENERIC sMsg; } SPMSG_GENERIC;
#define SIZE_GENERIC (sizeof(SPMSG_GENERIC) - sizeof(DPHDR))
typedef struct { DWORD dwType; DPID dpId; } DPMSG_GETPLAYER;
typedef struct { DPHDR dpHdr; DPMSG_GETPLAYER sMsg; } SPMSG_GETPLAYER; #define SIZE_GETPLAYER (sizeof(SPMSG_GETPLAYER) - sizeof(DPHDR))
typedef struct { DPHDR dpHdr; DPMSG_ADDPLAYER sMsg; SOCKADDR sockaddr; DWORD dwUnique; } SPMSG_ADDPLAYER;
#define SIZE_ADDPLAYER (sizeof(SPMSG_ADDPLAYER) - sizeof(DPHDR))
typedef SPMSG_ADDPLAYER SPMSG_SETPLAYER;
#define SIZE_SETPLAYER (sizeof(SPMSG_SETPLAYER) - sizeof(DPHDR))
typedef struct { DPHDR dpHdr; DPMSG_GROUPADD sMsg; } SPMSG_GROUPADD;
#define SIZE_GROUPADD (sizeof(SPMSG_GROUPADD) - sizeof(DPHDR))
typedef struct { DPHDR dpHdr; DWORD dwType; DWORD dwTicks; } SPMSG_PING;
#define SIZE_PING (sizeof(SPMSG_PING) - sizeof(DPHDR))
typedef struct { DPHDR dpHdr; DWORD dwType; GUID guid; } SPMSG_INVITE;
typedef struct { DPHDR dpHdr; DWORD dwType; DPCAPS dpCaps; } SPMSG_GETPLAYERCAPS;
#define SIZE_GETPLAYERCAPS (sizeof(SPMSG_GETPLAYERCAPS) - sizeof(DPHDR))
typedef struct { DWORD dwType; DPSESSIONDESC dpDesc; } DPMSG_SENDDESC;
typedef struct { DPHDR dpHdr; DPMSG_SENDDESC sMsg; } SPMSG_SENDDESC;
#define SIZE_SENDDESC (sizeof(SPMSG_SENDDESC) - sizeof(DPHDR))
typedef struct { DWORD dwType; BOOL bEnable; } DPMSG_ENABLEPLAYER; typedef struct { DPHDR dpHdr; DPMSG_ENABLEPLAYER sMsg; } SPMSG_ENABLEPLAYER;
typedef struct { DPHDR dpHdr; DWORD dwType; DPSESSIONDESC dpSessionDesc; DWORD dwUnique; USHORT usPort; USHORT usVerMajor; USHORT usVerMinor; } SPMSG_ENUM;
#pragma pack(pop, 1)
class CImpIDP_SP : public IDirectPlaySP { public: // IUnknown methods
// IDirectPlay methods
virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID iid, LPVOID *ppvObj ); virtual ULONG STDMETHODCALLTYPE AddRef( void); virtual ULONG STDMETHODCALLTYPE Release( void );
virtual HRESULT STDMETHODCALLTYPE AddPlayerToGroup( DPID dwDPIDGroup, DPID dwDPIDPlayer); virtual HRESULT STDMETHODCALLTYPE Close(DWORD); virtual HRESULT STDMETHODCALLTYPE CreatePlayer( LPDPID pPlayerID, LPSTR pNickName, LPSTR pFullName, LPHANDLE lpReceiveEvent, BOOL bPlayer);
virtual HRESULT STDMETHODCALLTYPE DeletePlayerFromGroup( DPID DPid, DPID dwDPIDPlayer); virtual HRESULT STDMETHODCALLTYPE DestroyPlayer( DPID pPlayerID, BOOL ); virtual HRESULT STDMETHODCALLTYPE EnumGroupPlayers( DPID dwGroupPid, LPDPENUMPLAYERSCALLBACK EnumCallback, LPVOID pContext, DWORD dwFlags);
virtual HRESULT STDMETHODCALLTYPE EnumPlayers( DWORD dwSessionID, LPDPENUMPLAYERSCALLBACK EnumCallback, LPVOID pContext, DWORD dwFlags);
virtual HRESULT STDMETHODCALLTYPE EnumSessions( LPDPSESSIONDESC, DWORD dwTimeout, LPDPENUMSESSIONSCALLBACK EnumCallback, LPVOID, DWORD);
virtual HRESULT STDMETHODCALLTYPE GetCaps(LPDPCAPS lpDPCaps); virtual HRESULT STDMETHODCALLTYPE GetMessageCount(DPID pidPlayer, LPDWORD lpdwCount); virtual HRESULT STDMETHODCALLTYPE GetPlayerCaps( DPID dwDPId, LPDPCAPS lpDPCaps); virtual HRESULT STDMETHODCALLTYPE GetPlayerName(DPID dpID, LPSTR lpFriendlyName, // buffer to hold name
LPDWORD pdwFriendlyNameLength, // length of name buffer
LPSTR lpFormalName, LPDWORD pdwFormalNameLength );
virtual HRESULT STDMETHODCALLTYPE Initialize(LPGUID lpguid); virtual HRESULT STDMETHODCALLTYPE Open( LPDPSESSIONDESC lpSDesc, HANDLE hEvent);
virtual HRESULT STDMETHODCALLTYPE Receive( LPDPID from, LPDPID to, DWORD dwReceiveFlags, LPVOID, LPDWORD);
virtual HRESULT STDMETHODCALLTYPE SaveSession(LPVOID lpv, LPDWORD lpdw);
virtual HRESULT STDMETHODCALLTYPE SetPrevPlayer(LPSTR lpName, LPVOID lpv, DWORD dw);
virtual HRESULT STDMETHODCALLTYPE SetPrevSession(LPSTR lpName, LPVOID lpv, DWORD dw);
virtual HRESULT STDMETHODCALLTYPE EnableNewPlayers(BOOL bEnable);
virtual HRESULT STDMETHODCALLTYPE Send( DPID from, DPID to, DWORD dwFlags, LPVOID lpvMsg, DWORD dwLength); virtual HRESULT STDMETHODCALLTYPE SetPlayerName( DPID from, LPSTR lpFriendlyName, LPSTR lpFormalName, BOOL bPlayer);
static CImpIDP_SP* NewCImpIDP_SP(int af);
DWORD ServerThreadProc(); DWORD ClientThreadProc(); BOOL CompareSessions(DWORD dwType, LPDPSESSIONDESC lpSDesc);
VOID HandleConnect(LPVOID lpv, DWORD dwSize, SOCKADDR *pSAddr, INT SockAddrLen); VOID HandleMessage(LPVOID lpv, DWORD dwSize, SOCKADDR *pSAddr, INT SockAddrLen); VOID PulseBlock() {PulseEvent(m_hBlockingEvent);} VOID SetBlock() {SetEvent(m_hBlockingEvent);} DWORD BlockNicely(DWORD dwTimeout); VOID SendDesc(LPDPSESSIONDESC); VOID SendPing(); VOID ISend(LONG, LONG, DWORD, LPVOID, DWORD); VOID LocalMsg(LONG, LPVOID, DWORD); VOID RemoteMsg(LONG, LPVOID, DWORD); LONG FindInvalidIndex(); VOID ConnectPlayers(SOCKADDR *pSAddr, INT SockAddrLen); VOID DeleteRemotePlayers(); VOID ResetSessionDesc() {memset(&m_dpDesc, 0x00, sizeof(DPSESSIONDESC));} BOOL GetSockAddress(SOCKADDR *pSAddr, LPINT pSAddrLen, USHORT usPort, SOCKET *pSocket, BOOL bBroadcast); BOOL PostGameMessage(LPVOID lpv, DWORD dw); BOOL PostPlayerMessage(LONG iIndex, LPVOID lpv, DWORD dw); BOOL PostNSMessage(LPVOID lpv, DWORD dw); USHORT NextSequence(); USHORT UpdateSequence(USHORT us); VOID SaveSessionData(NS_SESSION_SAVE *lpSDesc); BOOL GetSessionData(DWORD dwSession);
BOOL m_bConnected; BOOL m_bPlayer0; // If I created the call, I am player
// zero.
void *operator new( size_t size ); void operator delete( void *ptr );
protected: void EnumDataLock(); void EnumDataUnlock(); void PlayerDataLock(); void PlayerDataUnlock(); void ParanoiaLock(); void ParanoiaUnlock();
private: LONG GetPlayerIndex(DPID); BOOL SetSession(DWORD dw); CImpIDP_SP(void); ~CImpIDP_SP(void);
DWORD m_dwPingSent; HANDLE m_hBlockingEvent; HANDLE m_hEnumBlkEventMain; // User Thread can run.
HANDLE m_hEnumBlkEventRead; // Enum Thread can read again.
HANDLE m_hPlayerBlkEventMain; // User Thread can run.
HANDLE m_hPlayerBlkEventRead; // Enum Thread can read again.
DWORD m_dwNextPlayer; BOOL m_bEnablePlayerAdd;
volatile LPDPENUMSESSIONSCALLBACK m_fpEnumSessions; volatile BOOL m_bRunEnumReceiveLoop; LPDPENUMPLAYERSCALLBACK m_fpEnumPlayers; LPVOID m_lpvSessionContext; LPVOID m_lpvPlayersContext; PLAYER_RECORD m_aPlayer[MAX_PLAYERS]; LONG m_iPlayerIndex; DPSESSIONDESC m_dpDesc;
int m_refCount; CRITICAL_SECTION m_critSection; CRITICAL_SECTION m_critSectionPlayer; CRITICAL_SECTION m_critSectionParanoia; DPCAPS m_dpcaps; HANDLE m_hNewPlayerEvent;
char **m_ppSessionArray; DWORD m_dwSessionPrev; DWORD m_dwSessionAlloc; int m_af;
DWORD m_remoteaddrlen; char m_chComputerName[64]; BOOL m_bShutDown; HANDLE m_hNSThread; DWORD m_dwNSId; USHORT m_usGamePort; USHORT m_usGameCookie; HANDLE m_hClientThread; DWORD m_dwClientId; volatile HANDLE m_hEnumThread; DWORD m_dwEnumId;
volatile SOCKET m_ServerSocket; volatile SOCKET m_ClientSocket; volatile SOCKET m_EnumSocket; BOOL m_bEnumSocket; BOOL m_bClientSocket;
DWORD m_dwSession; SOCKADDR m_NSSockAddr; INT m_SessionAddrLen; SOCKADDR m_GameSockAddr;
USHORT m_usSeq; USHORT m_usSeqSys;
SOCKADDR *m_aMachineAddr; DWORD m_cMachines; DWORD m_dwUnique; volatile SPMSG_ENUM m_spmsgEnum; volatile SPMSG_ADDPLAYER m_spmsgAddPlayer;
};
BOOL SetIDP_SP( CImpIDP_SP *pSP);
// End : declaration of main implementation class for IDirectPlay
extern BOOL AddMessage(LPVOID lpvMsg, DWORD dwSize, DPID pidTo, DPID pidFrom, BOOL bHigh); extern HRESULT GetQMessage(LPVOID lpvMsg, LPDWORD pdwSize, DPID *ppidTo, DPID *ppidFrom, DWORD dwFlags, BOOL bPeek); extern VOID FlushQueue(DPID pid); extern DWORD GetPlayerCount(DPID spid);
#define DPSYS_JOHN 0x6e686f4a
// Enumeration Messages
//
// Thread Messages
//
#define PWM_BASE 0x00007000
#define PWM_COMMWRITE PWM_BASE +1
#define PWM_SETIDP PWM_BASE +2
#define PWM_HANGUP PWM_BASE +3
#define PWM_CLOSE PWM_BASE +4
#define DPNS_PORT 8787
#endif
|