Files
Descent3/networking/directplay.cpp
Kevin Bentley df209742fc Initial import
2024-04-15 21:43:29 -06:00

1156 lines
32 KiB
C++

/*
* $Logfile: /DescentIII/Main/directplay/directplay.cpp $
* $Revision: 12 $
* $Date: 4/14/99 1:12a $
* $Author: Jeff $
*
* Directplay API
*
* $Log: /DescentIII/Main/directplay/directplay.cpp $
*
* 12 4/14/99 1:12a Jeff
* fixed case mismatched #includes
*
* 11 2/16/99 12:36a Kevin
* Fixes for release builds of OEM V3 and KAtmai
*
* 10 2/15/99 1:22p Kevin
* Changes for GameGauge
*
* 9 1/21/99 11:15p Jeff
* pulled out some structs and defines from header files and moved them
* into seperate header files so that multiplayer dlls don't require major
* game headers, just those new headers. Side effect is a shorter build
* time. Also cleaned up some header file #includes that weren't needed.
* This affected polymodel.h, object.h, player.h, vecmat.h, room.h,
* manage.h and multi.h
*
* 8 10/08/98 5:20p Kevin
* Fixed dependancies and fixed demo config
*
* 7 9/02/98 6:54p Kevin
* Fixed general directplay support up, and got modem-modem working
*
* 6 8/24/98 10:55a Kevin
* new directplay stuff
*
* 5 8/19/98 11:49a Kevin
* Got DirectPlay IPX working, and localized connection DLLs
*
* 4 8/14/98 4:54p Kevin
* More directplay stuff
*
* 3 8/13/98 6:36p Kevin
* checked that lpDirectPlay4A was non null
*
* 2 8/13/98 6:32p Kevin
* Initial implementation of directplay API
*
* 1 8/13/98 6:25p Kevin
*
*/
#include <windows.h>
#include <winsock.h>
#include <wsipx.h>
#include <ras.h>
#include <objbase.h>
#include "descent.h"
#include "player.h"
#include "appdatabase.h"
#include "pstypes.h"
#include "pserror.h"
#include "mono.h"
#include "networking.h"
#include "ddio.h"
#include "mem.h"
#include "multi.h"
#include "directplay.h"
bool Use_DirectPlay = false;
DPSESSIONDESC2 Directplay_sessions[MAX_DP_GAMES];
int Num_directplay_games = 0;
char Directplay_session_desc[MAX_DP_GAMES][200];
bool Directplay_lobby_launched_game = false;
void * lpAddress = NULL;
//char Directplay_modem_list[MAX_MODEMS][200];
modem_list Modems_found[MAX_MODEMS];
int Num_modems_found = 0;
LPVOID lpConnectionBuffer;
LPDIRECTPLAY4A lpDirectPlay4A = NULL;
LPDIRECTPLAYLOBBY3A lpDirectPlayLobby3A = NULL;
LPDPLCONNECTION lpdplconnection = NULL;
// {915CE160-3125-11d2-BB3D-00104B27BFF0}
static const GUID DPD3_GUID =
{ 0x915ce160, 0x3125, 0x11d2, { 0xbb, 0x3d, 0x0, 0x10, 0x4b, 0x27, 0xbf, 0xf0 } };
unsigned long Pending_dp_conn[MAX_PENDING_NEW_CONNECTIONS];
typedef struct _dpconnections
{
char name[100];
void *conn;
}dpconnections;
dpconnections dpconns[MAX_DIRECTPLAY_CONNECTIONS];
BOOL FAR PASCAL DirectPlayEnumConnectionsCallback(
LPCGUID lpguidSP, LPVOID lpConnection, DWORD dwConnectionSize,
LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext)
{
mprintf((0,"Directplay connection found: %s\n",lpName->lpszShortNameA));
//Do something with the list of connections
for(int i=0;i<MAX_DIRECTPLAY_CONNECTIONS;i++)
{
if(dpconns[i].conn==NULL)
{
dpconns[i].conn = mem_malloc(dwConnectionSize);
memcpy(dpconns[i].conn,lpConnection,dwConnectionSize);
strcpy(dpconns[i].name,lpName->lpszShortNameA);
return (TRUE);
}
}
mprintf((0,"No space for Directplay entry.\n"));
return (TRUE);
}
BOOL FAR PASCAL EnumSessionsCallback(
LPCDPSESSIONDESC2 lpSessionDesc, LPDWORD lpdwTimeOut,
DWORD dwFlags, LPVOID lpContext)
{
if(!lpSessionDesc)
return (FALSE);
if(Num_directplay_games<MAX_DP_GAMES)
{
mprintf((0,"Found Directplay game[%d]: %s\n",Num_directplay_games,lpSessionDesc->lpszSessionNameA));
memcpy(&Directplay_sessions[Num_directplay_games],lpSessionDesc,sizeof(DPSESSIONDESC2));
strcpy(Directplay_session_desc[Num_directplay_games],lpSessionDesc->lpszSessionNameA);
Directplay_sessions[Num_directplay_games].lpszSessionNameA = Directplay_session_desc[Num_directplay_games];
//mprintf((0,"Found Directplay game[%d]: %s\n",Num_directplay_games,Directplay_sessions[Num_directplay_games].lpszSessionNameA));
Num_directplay_games++;
}
else
return FALSE;
return (TRUE);
}
int dp_SelectDirectPlayConnection(char *name)
{
HRESULT hr;
void * connection = NULL;
int i;
if(!lpDirectPlay4A)
return 0;
if(name)
{
if(lpAddress)
mem_free(lpAddress);
lpAddress = NULL;
for(i=0;i<MAX_DIRECTPLAY_CONNECTIONS;i++)
{
if(strcmpi(dpconns[i].name,name)==0)
{
mprintf((0,"Found DirectPlay connection: %s\n",name));
connection = dpconns[i].conn;
break;
}
}
if(!connection)
{
mprintf((0,"Unable to find DirectPlay connection: %s\n",name));
return 0;
}
}
else
connection = lpAddress;
memset(&dpconns,0,sizeof(dpconnections)*MAX_DIRECTPLAY_CONNECTIONS);
hr = lpDirectPlay4A->InitializeConnection(connection, 0);
for(i=0;i<MAX_DIRECTPLAY_CONNECTIONS;i++)
{
if(dpconns[i].conn!=NULL)
{
mem_free(dpconns[i].conn);
dpconns[i].conn = NULL;
dpconns[i].name[0]=NULL;
}
}
if(FAILED(hr))
{
mprintf((0,"lpDirectPlay4A->InitializeConnection() failed.\n"));
switch(hr)
{
case DPERR_ALREADYINITIALIZED:
mprintf((0,"Error: DPERR_ALREADYINITIALIZED\n"));
break;
case DPERR_INVALIDFLAGS:
mprintf((0,"Error: DPERR_INVALIDFLAGS\n"));
break;
case DPERR_INVALIDPARAMS:
mprintf((0,"Error: DPERR_INVALIDPARAMS\n"));
break;
case DPERR_UNAVAILABLE:
mprintf((0,"Error: DPERR_UNAVAILABLE\n"));
break;
default:
mprintf((0,"Error: Unknown\n"));
}
return 0;
}
else
return 1;
}
int dp_InitDirectPlay(char *conn_name, void *parms,int num_elements)
{
unsigned long dwAddressSize;
HRESULT hr;
char *conn = conn_name;
for(int i=0;i<MAX_PENDING_NEW_CONNECTIONS;i++)
Pending_dp_conn[i] = DPID_UNKNOWN;
// Delete any previous directplay instance
if(lpDirectPlay4A)
lpDirectPlay4A->Release();
if(SUCCEEDED(CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectPlay4A, (LPVOID*)&lpDirectPlay4A)))
{
lpDirectPlay4A->EnumConnections(&DPD3_GUID,
DirectPlayEnumConnectionsCallback, 0, 0);
}
else
{
lpDirectPlay4A=NULL;
}
if(parms)
{
if(lpDirectPlayLobby3A)
{
lpDirectPlayLobby3A->Release();
lpDirectPlayLobby3A = NULL;
}
hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectPlayLobby3A, (LPVOID*)&lpDirectPlayLobby3A);
if(SUCCEEDED(hr))
{
hr = lpDirectPlayLobby3A->CreateCompoundAddress((LPDPCOMPOUNDADDRESSELEMENT)parms,num_elements,NULL,&dwAddressSize);
if(hr==DPERR_BUFFERTOOSMALL)
{
if(lpAddress)
mem_free(lpAddress);
lpAddress = mem_malloc(dwAddressSize);
hr = lpDirectPlayLobby3A->CreateCompoundAddress((LPDPCOMPOUNDADDRESSELEMENT)parms,num_elements,lpAddress,&dwAddressSize);
if(FAILED(hr))
{
mprintf((0,"lpDirectPlayLobby3A->CreateCompoundAddress() failed. DirectPlay *NOT* initialized!\n"));
return 0;
}
else
{
mprintf((0,"lpDirectPlayLobby3A->CreateCompoundAddress() succeeded!\n"));
}
}
else
{
mprintf((0,"lpDirectPlayLobby3A->CreateCompoundAddress() buffer size request failed. DirectPlay *NOT* initialized!\n"));
}
}
}
if(dp_SelectDirectPlayConnection(conn))
{
DP_active = TRUE;
mprintf((0,"DirectPlay Initialized\n"));
return 1;
}
return 0;
}
// Everyone should call this when leaving the game.
void dp_EndGame()
{
mprintf((0,"Ending DirectPlay game.\n"));
if((!DP_active)||(!lpDirectPlay4A))
return;
lpDirectPlay4A->Close();
lpDirectPlay4A->Release();
lpDirectPlay4A = NULL;
}
//This function gets called when a game is started, so Direcplay knows the title, and to listen
int dp_StartGame(char *gamename)
{
long hres;
DPNAME server_player;
DPSESSIONDESC2 sessionDesc;
mprintf((0,"Starting DirectPlay game: %s\n",gamename));
if((!DP_active)||(!lpDirectPlay4A))
{
mprintf((0,"Can't start game because DirectPlay isn't initialized!\n"));
return 0;
}
// Host a new session.
ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
sessionDesc.dwFlags = DPSESSION_CLIENTSERVER | DPSESSION_KEEPALIVE | DPSESSION_OPTIMIZELATENCY | DPSESSION_DIRECTPLAYPROTOCOL ;
sessionDesc.guidApplication = DPD3_GUID;
sessionDesc.dwMaxPlayers = MAX_NET_PLAYERS;
sessionDesc.dwCurrentPlayers = 1; //The server is a player
sessionDesc.lpszSessionNameA = gamename;
ZeroMemory(&server_player, sizeof(DPNAME));
server_player.dwSize = sizeof(DPNAME);
server_player.lpszShortNameA = Players[Player_num].callsign;
server_player.lpszLongNameA = NULL;
//if(lpAddress)
//{
// hres = lpDirectPlay4A->Open((DPSESSIONDESC2 *)lpAddress, DPOPEN_CREATE | DPOPEN_RETURNSTATUS);
//}
//else
//{
hres = lpDirectPlay4A->Open(&sessionDesc, DPOPEN_CREATE | DPOPEN_RETURNSTATUS);
//}
if(SUCCEEDED(hres))
{
NetPlayers[Player_num].hPlayerEvent = CreateEvent(NULL, // no security
FALSE, // auto reset
FALSE, // initial event reset
NULL); // no name
if (NetPlayers[Player_num].hPlayerEvent == NULL)
{
mprintf((0,"Failed to create directplay notification event!\n"));
dp_EndGame();
DP_active = false;
return 0;
}
hres = lpDirectPlay4A->CreatePlayer( &NetPlayers[Player_num].dpidPlayer, &server_player, NetPlayers[Player_num].hPlayerEvent,
NULL,0, DPPLAYER_SERVERPLAYER);
if(FAILED(hres))
{
mprintf((0,"Failed to create directplay player in dp_StartGame()\n"));
switch(hres)
{
case DPERR_CANTADDPLAYER:
mprintf((0,"Unable to create player. Error code: DPERR_CANTADDPLAYER\n"));
break;
case DPERR_CANTCREATEPLAYER:
mprintf((0,"Unable to create player. Error code: DPERR_CANTCREATEPLAYER\n"));
break;
case DPERR_CONNECTIONLOST:
mprintf((0,"Unable to create player. Error code: DPERR_CONNECTIONLOST\n"));
break;
case DPERR_INVALIDFLAGS:
mprintf((0,"Unable to create player. Error code: DPERR_INVALIDFLAGS\n"));
break;
case DPERR_INVALIDPARAMS:
mprintf((0,"Unable to create player. Error code: DPERR_INVALIDPARAMS\n"));
break;
case DPERR_NOCONNECTION:
mprintf((0,"Unable to create player. Error code: DPERR_NOCONNECTION\n"));
break;
default:
mprintf((0,"Unable to create player. Error code: Unknown\n"));
break;
}
return 0;
}
//Success
return 1;
}
else
{
switch(hres)
{
case DPERR_ACCESSDENIED:
mprintf((0,"Failed to create Directplay session (DPERR_ACCESSDENIED)!\n"));
break;
case DPERR_ALREADYINITIALIZED:
mprintf((0,"Failed to create Directplay session (DPERR_ALREADYINITIALIZED)!\n"));
break;
case DPERR_AUTHENTICATIONFAILED:
mprintf((0,"Failed to create Directplay session (DPERR_AUTHENTICATIONFAILED)!\n"));
break;
case DPERR_CANNOTCREATESERVER:
mprintf((0,"Failed to create Directplay session (DPERR_CANNOTCREATESERVER)!\n"));
break;
case DPERR_CANTLOADCAPI:
mprintf((0,"Failed to create Directplay session (DPERR_CANTLOADCAPI)!\n"));
break;
case DPERR_CANTLOADSECURITYPACKAGE:
mprintf((0,"Failed to create Directplay session (DPERR_CANTLOADSECURITYPACKAGE)!\n"));
break;
case DPERR_CANTLOADSSPI:
mprintf((0,"Failed to create Directplay session (DPERR_CANTLOADSSPI)!\n"));
break;
case DPERR_CONNECTING:
mprintf((0,"Failed to create Directplay session (DPERR_CONNECTING)!\n"));
break;
case DPERR_CONNECTIONLOST:
mprintf((0,"Failed to create Directplay session (DPERR_CONNECTIONLOST)!\n"));
break;
case DPERR_ENCRYPTIONFAILED:
mprintf((0,"Failed to create Directplay session (DPERR_ENCRYPTIONFAILED)!\n"));
break;
case DPERR_ENCRYPTIONNOTSUPPORTED:
mprintf((0,"Failed to create Directplay session (DPERR_ENCRYPTIONNOTSUPPORTED)!\n"));
break;
case DPERR_INVALIDFLAGS:
mprintf((0,"Failed to create Directplay session (DPERR_INVALIDFLAGS)!\n"));
break;
case DPERR_INVALIDPARAMS:
mprintf((0,"Failed to create Directplay session (DPERR_INVALIDPARAMS)!\n"));
break;
case DPERR_INVALIDPASSWORD:
mprintf((0,"Failed to create Directplay session (DPERR_INVALIDPASSWORD)!\n"));
break;
case DPERR_LOGONDENIED:
mprintf((0,"Failed to create Directplay session (DPERR_LOGONDENIED)!\n"));
break;
case DPERR_NOCONNECTION:
mprintf((0,"Failed to create Directplay session (DPERR_NOCONNECTION)!\n"));
break;
case DPERR_NONEWPLAYERS:
mprintf((0,"Failed to create Directplay session (DPERR_NONEWPLAYERS)!\n"));
break;
case DPERR_NOSESSIONS:
mprintf((0,"Failed to create Directplay session (DPERR_NOSESSIONS)!\n"));
break;
case DPERR_SIGNFAILED:
mprintf((0,"Failed to create Directplay session (DPERR_SIGNFAILED)!\n"));
break;
case DPERR_TIMEOUT:
mprintf((0,"Failed to create Directplay session (DPERR_TIMEOUT)!\n"));
break;
case DPERR_UNINITIALIZED:
mprintf((0,"Failed to create Directplay session (DPERR_UNINITIALIZED)!\n"));
break;
case DPERR_USERCANCEL:
mprintf((0,"Failed to create Directplay session (DPERR_USERCANCEL)!\n"));
break;
default:
mprintf((0,"Failed to create Directplay session (unknown)!\n"));
}
}
return 0;
}
int dp_ListDirectPlayGames()
{
DPSESSIONDESC2 sessionDesc;
HRESULT hr;
if(!DP_active)
return DPERR_EXCEPTION;
if(!lpDirectPlay4A)
return DPERR_EXCEPTION;
Num_directplay_games = 0;
// Search for this kind of session.
ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
sessionDesc.guidApplication = DPD3_GUID;
hr = lpDirectPlay4A->EnumSessions(&sessionDesc, 0, EnumSessionsCallback,
0, DPENUMSESSIONS_AVAILABLE | DPENUMSESSIONS_RETURNSTATUS | DPENUMSESSIONS_ASYNC );
if(hr==DPERR_CONNECTING)
{
mprintf((0,"Waiting for EnumSessions() to connect.\n"));
return DPERR_CONNECTING;
}
if FAILED(hr)
{
mprintf((0,"Unable to EnumSessions() for Directplay.\n"));
switch(hr)
{
case DPERR_CONNECTING:
mprintf((0,"Error code: DPERR_CONNECTING\n"));
break;
case DPERR_CONNECTIONLOST:
mprintf((0,"Error code: DPERR_CONNECTIONLOST\n"));
break;
case DPERR_EXCEPTION:
mprintf((0,"Error code: DPERR_EXCEPTION\n"));
break;
case DPERR_GENERIC:
mprintf((0,"Error code: DPERR_GENERIC\n"));
break;
case DPERR_INVALIDOBJECT:
mprintf((0,"Error code: DPERR_INVALIDOBJECT\n"));
break;
case DPERR_INVALIDPARAMS:
mprintf((0,"Error code: DPERR_INVALIDPARAMS\n"));
break;
case DPERR_NOCONNECTION:
mprintf((0,"Error code: DPERR_NOCONNECTION\n"));
break;
case DPERR_UNINITIALIZED:
mprintf((0,"Error code: DPERR_UNINITIALIZED\n"));
break;
case DPERR_USERCANCEL:
mprintf((0,"Error code: DPERR_USERCANCEL\n"));
break;
default:
mprintf((0,"Error code: Unknown\n"));
break;
}
return DPERR_NOCONNECTION;
}
else
mprintf((0,"EnumSessions() returned DP_OK\n"));
return DP_OK;
}
// This function will look for incoming messages, and dispatch them accordingly
void dp_DirectPlayDispatch()
{
HRESULT hr;
ubyte packet_data[32000];//MAX_PACKET_SIZE+1];
unsigned long dwMsgBufferSize = 32000;//MAX_PACKET_SIZE;
DPID idFrom = 0;
DPID idTo = 0;
network_address from_addr;
LPDPMSG_CREATEPLAYERORGROUP new_player_msg;
//Put messages in the buffers
if((!DP_active)||(!lpDirectPlay4A))
{
mprintf((0,"Can't dispatch DirectPlay message because DirectPlay isn't active!\n"));
return;
}
hr = lpDirectPlay4A->Receive(&idFrom, &idTo,DPRECEIVE_ALL,packet_data, &dwMsgBufferSize);
if(FAILED(hr))
{
switch(hr)
{
case DPERR_BUFFERTOOSMALL:
mprintf((0,"Error: lpDirectPlay4A->Receive() returned DPERR_BUFFERTOOSMALL -- needs %d\n",dwMsgBufferSize));
break;
case DPERR_GENERIC:
mprintf((0,"Error: lpDirectPlay4A->Receive() returned DPERR_GENERIC\n"));
break;
case DPERR_INVALIDOBJECT:
mprintf((0,"Error: lpDirectPlay4A->Receive() returned DPERR_INVALIDOBJECT\n"));
break;
case DPERR_INVALIDPARAMS:
mprintf((0,"Error: lpDirectPlay4A->Receive() returned DPERR_INVALIDPARAMS\n"));
break;
case DPERR_INVALIDPLAYER:
mprintf((0,"Error: lpDirectPlay4A->Receive() returned DPERR_INVALIDPLAYER\n"));
break;
case DPERR_NOMESSAGES:
//Not really an error....
//mprintf((0,"Error: lpDirectPlay4A->Receive() returned DPERR_NOMESSAGES\n"));
break;
default:
mprintf((0,"Unknown error code from DirectPlay::Receive() -- %x\n",hr));
}
}
else
{
// Now we have actual data -- do something with it.
if (idFrom == DPID_SYSMSG)
{
// This is a system message
LPDPMSG_GENERIC lpMsg = (LPDPMSG_GENERIC)packet_data;
switch(lpMsg->dwType)
{
case DPSYS_CREATEPLAYERORGROUP:
// New player joined the game
{
mprintf((0,"Got a DPSYS_CREATEPLAYERORGROUP packet!\n"));
new_player_msg = (LPDPMSG_CREATEPLAYERORGROUP) lpMsg;
//Store this player's info
for(int i=0;i<MAX_PENDING_NEW_CONNECTIONS;i++)
{
if(Pending_dp_conn[i] == DPID_UNKNOWN)
{
//new connection slot
Pending_dp_conn[i] = new_player_msg->dpId;
break;
}
}
}
break;
case DPSYS_DESTROYPLAYERORGROUP:
// Player left the game
break;
case DPSYS_ADDPLAYERTOGROUP:
case DPSYS_DELETEPLAYERFROMGROUP:
case DPSYS_SESSIONLOST:
case DPSYS_HOST:
case DPSYS_SETPLAYERORGROUPDATA:
case DPSYS_SETPLAYERORGROUPNAME:
case DPSYS_SENDCOMPLETE:
break;
default:
Int3(); // Get Kevin
mprintf((0,"Unknown system message from DirectPlay! %d\n",lpMsg->dwType));
}
}
else
{
if(dwMsgBufferSize>=MAX_PACKET_SIZE)
{
mprintf((0,"Error: Packet too large for D3 to handle! Discarding!!!!!\n"));
}
else
{
// Presumably this is from a player we know about...
memset(&from_addr,0,sizeof(network_address));
from_addr.connection_type = NP_DIRECTPLAY;
memcpy(from_addr.address,&idFrom,sizeof(DPID));
nw_psnet_buffer_packet((ubyte *)packet_data,dwMsgBufferSize,&from_addr);
}
}
}
}
// Send a packet to a direct play user
int dp_DirectPlaySend(network_address *who_to,ubyte *data,int len,bool reliable)
{
DPID idTo;
HRESULT hr;
unsigned long send_flags;
if((!DP_active)||(!lpDirectPlay4A))
{
mprintf((0,"Can't send DirectPlay message because DirectPlay isn't active!\n"));
return 0;
}
ASSERT(who_to->connection_type==NP_DIRECTPLAY);
send_flags = DPSEND_ASYNC;
if(reliable)
send_flags |= DPSEND_GUARANTEED;
memcpy(&idTo,who_to->address,sizeof(DPID));
hr = lpDirectPlay4A->SendEx(NetPlayers[Player_num].dpidPlayer,idTo,send_flags,
data,len,0,0,NULL,NULL);
if(FAILED(hr))
return 0;
else
return 1;
}
void dp_DirectPlayDestroyPlayer(DPID who)
{
HRESULT hr;
if((!DP_active)||(!lpDirectPlay4A))
return;
hr = lpDirectPlay4A->DestroyPlayer(who);
if(FAILED(hr))
{
switch(hr)
{
case DPERR_ACCESSDENIED:
mprintf((0,"lpDirectPlay4A->DestroyPlayer() returned DPERR_ACCESSDENIED.\n"));
break;
case DPERR_CONNECTIONLOST:
mprintf((0,"lpDirectPlay4A->DestroyPlayer() returned DPERR_CONNECTIONLOST.\n"));
break;
case DPERR_INVALIDOBJECT:
mprintf((0,"lpDirectPlay4A->DestroyPlayer() returned DPERR_INVALIDOBJECT.\n"));
break;
case DPERR_INVALIDPLAYER:
mprintf((0,"lpDirectPlay4A->DestroyPlayer() returned DPERR_INVALIDPLAYER.\n"));
break;
case DPERR_UNAVAILABLE:
mprintf((0,"lpDirectPlay4A->DestroyPlayer() returned DPERR_UNAVAILABLE.\n"));
break;
default:
mprintf((0,"Unknown error returned by nw_DirectPlayDestroyPlayer() -- %x\n",hr));
}
}
}
//if(Use_DirectPlay)
int dp_DirectPlayJoinGame(LPDPSESSIONDESC2 session)
{
HRESULT hr;
do
{
hr = lpDirectPlay4A->Open(session,DPOPEN_JOIN | DPOPEN_RETURNSTATUS );
if(DPERR_CONNECTING==hr)
{
mprintf((0,"Waiting for Directplay session to start(DPERR_CONNECTING)!\n"));
Sleep(50);
}
}while(DPERR_CONNECTING==hr);
if(FAILED(hr))
{
switch(hr)
{
case DPERR_ACCESSDENIED:
mprintf((0,"Failed to create Directplay session (DPERR_ACCESSDENIED)!\n"));
break;
case DPERR_ALREADYINITIALIZED:
mprintf((0,"Failed to create Directplay session (DPERR_ALREADYINITIALIZED)!\n"));
break;
case DPERR_AUTHENTICATIONFAILED:
mprintf((0,"Failed to create Directplay session (DPERR_AUTHENTICATIONFAILED)!\n"));
break;
case DPERR_CANNOTCREATESERVER:
mprintf((0,"Failed to create Directplay session (DPERR_CANNOTCREATESERVER)!\n"));
break;
case DPERR_CANTLOADCAPI:
mprintf((0,"Failed to create Directplay session (DPERR_CANTLOADCAPI)!\n"));
break;
case DPERR_CANTLOADSECURITYPACKAGE:
mprintf((0,"Failed to create Directplay session (DPERR_CANTLOADSECURITYPACKAGE)!\n"));
break;
case DPERR_CANTLOADSSPI:
mprintf((0,"Failed to create Directplay session (DPERR_CANTLOADSSPI)!\n"));
break;
case DPERR_CONNECTIONLOST:
mprintf((0,"Failed to create Directplay session (DPERR_CONNECTIONLOST)!\n"));
break;
case DPERR_ENCRYPTIONFAILED:
mprintf((0,"Failed to create Directplay session (DPERR_ENCRYPTIONFAILED)!\n"));
break;
case DPERR_ENCRYPTIONNOTSUPPORTED:
mprintf((0,"Failed to create Directplay session (DPERR_ENCRYPTIONNOTSUPPORTED)!\n"));
break;
case DPERR_INVALIDFLAGS:
mprintf((0,"Failed to create Directplay session (DPERR_INVALIDFLAGS)!\n"));
break;
case DPERR_INVALIDPARAMS:
mprintf((0,"Failed to create Directplay session (DPERR_INVALIDPARAMS)!\n"));
break;
case DPERR_INVALIDPASSWORD:
mprintf((0,"Failed to create Directplay session (DPERR_INVALIDPASSWORD)!\n"));
break;
case DPERR_LOGONDENIED:
mprintf((0,"Failed to create Directplay session (DPERR_LOGONDENIED)!\n"));
break;
case DPERR_NOCONNECTION:
mprintf((0,"Failed to create Directplay session (DPERR_NOCONNECTION)!\n"));
break;
case DPERR_NONEWPLAYERS:
mprintf((0,"Failed to create Directplay session (DPERR_NONEWPLAYERS)!\n"));
break;
case DPERR_NOSESSIONS:
mprintf((0,"Failed to create Directplay session (DPERR_NOSESSIONS)!\n"));
break;
case DPERR_SIGNFAILED:
mprintf((0,"Failed to create Directplay session (DPERR_SIGNFAILED)!\n"));
break;
case DPERR_TIMEOUT:
mprintf((0,"Failed to create Directplay session (DPERR_TIMEOUT)!\n"));
break;
case DPERR_UNINITIALIZED:
mprintf((0,"Failed to create Directplay session (DPERR_UNINITIALIZED)!\n"));
break;
case DPERR_USERCANCEL:
mprintf((0,"Failed to create Directplay session (DPERR_USERCANCEL)!\n"));
break;
default:
mprintf((0,"Failed to create Directplay session (unknown)!\n"));
}
//return 0;
}
else
{
HRESULT hres;
DPNAME client_player;
ZeroMemory(&client_player, sizeof(DPNAME));
client_player.dwSize = sizeof(DPNAME);
client_player.lpszShortNameA = Players[Player_num].callsign;
client_player.lpszLongNameA = NULL;
mprintf((0,"Creating local player...\n"));
NetPlayers[Player_num].hPlayerEvent = CreateEvent(NULL, // no security
FALSE, // auto reset
FALSE, // initial event reset
NULL); // no name
if (NetPlayers[Player_num].hPlayerEvent == NULL)
{
mprintf((0,"Failed to create directplay notification event!\n"));
dp_EndGame();
DP_active = false;
return 0;
}
hres = lpDirectPlay4A->CreatePlayer( &NetPlayers[Player_num].dpidPlayer, &client_player, NetPlayers[Player_num].hPlayerEvent,
NULL,0, 0);
if(FAILED(hres))
{
mprintf((0,"Failed to create directplay player in dp_DirectPlayJoinGame()\n"));
switch(hres)
{
case DPERR_CANTADDPLAYER:
mprintf((0,"Unable to create player. Error code: DPERR_CANTADDPLAYER\n"));
break;
case DPERR_CANTCREATEPLAYER:
mprintf((0,"Unable to create player. Error code: DPERR_CANTCREATEPLAYER\n"));
break;
case DPERR_CONNECTIONLOST:
mprintf((0,"Unable to create player. Error code: DPERR_CONNECTIONLOST\n"));
break;
case DPERR_INVALIDFLAGS:
mprintf((0,"Unable to create player. Error code: DPERR_INVALIDFLAGS\n"));
break;
case DPERR_INVALIDPARAMS:
mprintf((0,"Unable to create player. Error code: DPERR_INVALIDPARAMS\n"));
break;
case DPERR_NOCONNECTION:
mprintf((0,"Unable to create player. Error code: DPERR_NOCONNECTION\n"));
break;
default:
mprintf((0,"Unable to create player. Error code: Unknown\n"));
break;
}
return 0;
}
return 1;
}
return 1;
}
void dp_ShutdownDirectPlay()
{
int i;
mprintf((0,"Freeing DirectPlay memory\n"));
for(i=0;i<MAX_DIRECTPLAY_CONNECTIONS;i++)
{
if(dpconns[i].conn!=NULL)
{
mem_free(dpconns[i].conn);
dpconns[i].conn = NULL;
dpconns[i].name[0]=NULL;
}
}
if(lpdplconnection)
mem_free(lpdplconnection);
if(lpAddress)
mem_free(lpAddress);
lpAddress = NULL;
lpdplconnection = NULL;
// Delete any previous directplay instance
mprintf((0,"Releasing DirectPlay COM object (lpDirectPlay4A)\n"));
//if(lpDirectPlay4A)
// lpDirectPlay4A->Release();
//lpDirectPlay4A = NULL;
mprintf((0,"Done shutting down DirectPlay.\n"));
}
// ---------------------------------------------------------------------------
// EnumModemAddress
// ---------------------------------------------------------------------------
// Description: Enumeration callback called by DirectPlayLobby.
// Enumerates the DirectPlay address chunks. If the
// chunk contains modem strings, add them to the control.
// Arguments:
// REFGUID [in] GUID of the address type
// DWORD [in] size of chunk
// LPVOID [in] pointer to chunk
// LPVOID [in] user-defined context
// Returns:
// BOOL FALSE to stop enumerating after the first callback
BOOL FAR PASCAL EnumModemAddress(REFGUID lpguidDataType, DWORD dwDataSize,
LPCVOID lpData, LPVOID lpContext)
{
HWND hWnd = (HWND) lpContext;
LPSTR lpszStr = (LPSTR) lpData;
// modem
if (IsEqualGUID(lpguidDataType, DPAID_Modem))
{
// loop over all strings in list
while (strlen(lpszStr))
{
mprintf((0,"Found modem: %s\n",lpszStr));
if(Num_modems_found<MAX_MODEMS)
{
// store modem name
strcpy(Modems_found[Num_modems_found].name,lpszStr);
Num_modems_found++;
}
// skip to next string
lpszStr += strlen(lpszStr) + 1;
}
}
return (TRUE);
}
//char Directplay_modem_list[MAX_MODEMS][200];
//int Num_modems_found = 0;
//Call this function with size set to 0, and it will fill in size with
//the amount of buffer space you need
//Otherwise, it will fill in the buffer with a bunch of null delimited
//strings, with a double null at the end.
int dp_GetModemChoices(char *buffer,unsigned long *size)
{
LPDIRECTPLAY4A lpTempDP4;
HRESULT hr;
void * connection = NULL;;
int i;
Num_modems_found = 0;
if(SUCCEEDED(CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectPlay4A, (LPVOID*)&lpTempDP4)))
{
lpTempDP4->EnumConnections(&DPD3_GUID,
DirectPlayEnumConnectionsCallback, 0, 0);
for(i=0;i<MAX_DIRECTPLAY_CONNECTIONS;i++)
{
if(strcmpi(dpconns[i].name,"Modem Connection For DirectPlay")==0)
{
//mprintf((0,"Found DirectPlay connection: %s\n",name));
connection = dpconns[i].conn;
break;
}
}
if(!connection)
{
mprintf((0,"Unable to find DirectPlay Modem connection.\n"));
return 0;
}
memset(&dpconns,0,sizeof(dpconnections)*MAX_DIRECTPLAY_CONNECTIONS);
hr = lpTempDP4->InitializeConnection(connection, 0);
for(i=0;i<MAX_DIRECTPLAY_CONNECTIONS;i++)
{
if(dpconns[i].conn!=NULL)
{
mem_free(dpconns[i].conn);
dpconns[i].conn = NULL;
dpconns[i].name[0]=NULL;
}
}
if(FAILED(hr))
{
mprintf((0,"lpTempDP4->InitializeConnection() failed.\n"));
switch(hr)
{
case DPERR_ALREADYINITIALIZED:
mprintf((0,"Error: DPERR_ALREADYINITIALIZED\n"));
break;
case DPERR_INVALIDFLAGS:
mprintf((0,"Error: DPERR_INVALIDFLAGS\n"));
break;
case DPERR_INVALIDPARAMS:
mprintf((0,"Error: DPERR_INVALIDPARAMS\n"));
break;
case DPERR_UNAVAILABLE:
mprintf((0,"Error: DPERR_UNAVAILABLE\n"));
break;
default:
mprintf((0,"Error: Unknown\n"));
}
return 0;
}
lpTempDP4->GetPlayerAddress(0,buffer,size);
if(buffer)
{
if(lpDirectPlayLobby3A)
{
lpDirectPlayLobby3A->Release();
lpDirectPlayLobby3A = NULL;
}
hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectPlayLobby3A, (LPVOID*)&lpDirectPlayLobby3A);
if(SUCCEEDED(hr))
lpDirectPlayLobby3A->EnumAddress( EnumModemAddress,buffer, *size, 0);
else
mprintf((0,"Couldn't create IID_IDirectPlayLobby3A COM Instance!\n"));
}
lpTempDP4->Release();
return 1;
}
return 0;
}
// Register a DirectPlay lobby aware application
// Use this so a directplay lobby provider such as zone.com can launch the game
//
// Parameters:
// appname The non-localized name of the application (ie. "Descent 3") DON'T LOCALIZE THIS! IT IS AN ID
// exefile Executable file name (without path)
// exepath Path to executable file
// arguments Any command line arguments the app needs
// workingdir The Working directory for the application
// description Localized description of the application
void dp_RegisterLobbyApplication(char *appname,char *exefile,char *exepath,char *arguments,char *workingdir,char *description)
{
static DPAPPLICATIONDESC AppDesc;
AppDesc.dwSize = sizeof(DPAPPLICATIONDESC);
AppDesc.dwFlags = 0;
AppDesc.lpszApplicationNameA = appname;
AppDesc.guidApplication = DPD3_GUID;
AppDesc.lpszFilenameA = exefile;
AppDesc.lpszCommandLineA = arguments;
AppDesc.lpszPathA = exepath;
AppDesc.lpszCurrentDirectoryA = workingdir;
AppDesc.lpszDescriptionA = description;
HRESULT hr;
mprintf((0,"Registering DirectPlay Lobby application:\n"));
mprintf((0,"AppDesc.lpszApplicationNameA = %s\n",appname));
mprintf((0,"AppDesc.lpszFilenameA = %s\n",exefile));
mprintf((0,"AppDesc.lpszCommandLineA = %s\n",arguments));
mprintf((0,"AppDesc.lpszPathA = %s\n",exepath));
mprintf((0,"AppDesc.lpszCurrentDirectoryA = %s\n",workingdir));
mprintf((0,"AppDesc.lpszDescriptionA = %s\n",description));
hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectPlayLobby3A, (LPVOID*)&lpDirectPlayLobby3A);
if(SUCCEEDED(hr))
{
hr = lpDirectPlayLobby3A->RegisterApplication(0,&AppDesc);
if(FAILED(hr))
{
mprintf((0,"IDirectPlayLobby3::RegisterApplication() failed.\n"));
if(hr==DPERR_INVALIDFLAGS)
mprintf((0,"Error = DPERR_INVALIDFLAGS\n"));
else if(hr==DPERR_INVALIDPARAMS)
mprintf((0,"Error = DPERR_INVALIDPARAMS\n"));
else
mprintf((0,"Error = ??????????? %x\n",hr));
}
else
{
mprintf((0,"IDirectPlayLobby3::RegisterApplication() succeded.\n"));
}
}
else
{
mprintf((0,"IDirectPlayLobby3 CoCreateInstance() failed.\n"));
return;
}
//lpDirectPlayLobby3A->Release();
}
// Returns TRUE if the game was launched from a lobby
bool dp_DidLobbyLaunchGame()
{
HRESULT hr;
unsigned long buffersize = sizeof(DPLCONNECTION);
Directplay_lobby_launched_game = false;
if(lpDirectPlayLobby3A)
{
lpDirectPlayLobby3A->Release();
lpDirectPlayLobby3A = NULL;
}
CoInitialize(NULL);
hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectPlayLobby3A, (LPVOID*)&lpDirectPlayLobby3A);
if(SUCCEEDED(hr))
{
hr = lpDirectPlayLobby3A->GetConnectionSettings(0,NULL,&buffersize);
if(FAILED(hr))
{
if(hr == DPERR_NOTLOBBIED)
{
mprintf((0,"Application not started from a lobby.\n"));
lpDirectPlayLobby3A->Release();
lpDirectPlayLobby3A = NULL;
return false;
}
mprintf((0,"Unable to determine DirectPlay lobby connection info buffer size!!!\n"));
lpDirectPlayLobby3A->Release();
lpDirectPlayLobby3A = NULL;
return false;
}
lpdplconnection = (LPDPLCONNECTION) mem_malloc(buffersize);
hr = lpDirectPlayLobby3A->GetConnectionSettings(0,lpdplconnection,&buffersize);
lpDirectPlayLobby3A->Release();
lpDirectPlayLobby3A = NULL;
if(FAILED(hr))
{
mprintf((0,"IDirectPlayLobby3::GetConnectionSettings() failed.\n"));
if(hr == DPERR_NOTLOBBIED)
{
mprintf((0,"Application not started from a lobby.\n"));
return false;
}
else
{
mprintf((0,"Unknown error from IDirectPlayLobby3::GetConnectionSettings().\n"));
return false;
}
}
else
{
mprintf((0,"Application was started from a lobby.\n"));
Directplay_lobby_launched_game = true;
return true;
}
}
else
{
mprintf((0,"IDirectPlayLobby3 CoCreateInstance() failed.\n"));
}
return false;
}
// Autoconnects to a game or starts one, based on the directplay lobby stuff
bool dp_AutoConnect()
{
if(!Directplay_lobby_launched_game)
return false;
if(lpdplconnection->dwFlags==DPLCONNECTION_CREATESESSION)
{
// We are hosting a game
Use_DirectPlay = true;
//What level do we use? what dll? what pps, etc....
}
else if(lpdplconnection->dwFlags==DPLCONNECTION_JOINSESSION)
{
// We are joining a game
Use_DirectPlay = true;
}
return false;
}