450 lines
12 KiB
C
450 lines
12 KiB
C
|
|
|||
|
// 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
|
|||
|
|