#include "pch.hpp"
//
//============================================================
//
// Contents:  Network Protocol code
//
// Owner   :  AndyG
// Created :  Aug 2 1999
//
// All Rights reserved worldwide (c) Microsoft
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               
//============================================================
//
#include "Net_Header.hpp"
#include "GUNGameList.h"






//
// Check to see which protocols are valid on this machine
//
bool __stdcall gos_CheckConnectionAvailable( int Connection )
{
	switch( Connection )
	{
		case NP_TCP:
			return hasTCP;
		case NP_IPX:
			return hasIPX;
		case NP_MODEM:
			return hasModem;
		case NP_SERIAL:
			return hasSerial;
		case NP_ZONEMATCH:
			return hasZoneMatch;
	}
	return 0;
}


//
// At the start of a game, check to see valid protocols on a machine
//
void _stdcall CheckProtocols()
{
	IDirectPlay4* temp_dplay4;
	DPCOMPOUNDADDRESSELEMENT comAdd[3];
	DWORD Size;
	void* p_address;
	DWORD result;
//
// Mark all protocols as invalid
//
	hasTCP=0;
	hasIPX=0;
	hasModem=0;
	hasSerial=0;
	hasZoneMatch=0;
	Connected=NP_NOT;
//
// Check for TCPIP
//
	wCoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (void**)&temp_dplay4 );

	int port;
	port = GetDirectPlayPort();

	comAdd[0].guidDataType	= DPAID_ServiceProvider;
	comAdd[0].dwDataSize	= sizeof(GUID);
	comAdd[0].lpData		= (void*)&DPSPGUID_TCPIP;
	comAdd[1].guidDataType	= DPAID_INet;								// Create a compund address
	comAdd[1].dwDataSize	= 1;
	comAdd[1].lpData		= "";
	comAdd[2].guidDataType	= DPAID_INetPort;
	comAdd[2].dwDataSize	= sizeof(port);
	comAdd[2].lpData		= (void *)&port;

	int num_elements;
	if (port)
		num_elements = 3;
	else
		num_elements = 2;

	AllowFail=1;
	Size=0;
	wCreateCompoundAddress( dplobby3, comAdd, num_elements, NULL, &Size );
	p_address = (void*)malloc(Size);
	wCreateCompoundAddress( dplobby3, comAdd, num_elements, p_address, &Size );
	result = wInitializeConnection( temp_dplay4, p_address, 0 );		// Try to initialize the connection
	GameOSFPU()
	AllowFail=0;

	if( SUCCEEDED(result) )
		hasTCP=1;

	free( p_address );
	wRelease( temp_dplay4 );


//
// Check for ZoneMatch if TCP present
//
	// jcem - no ZoneMatch - CheckForZoneMatch();

//
// Check for IPX
//
	wCoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (void**)&temp_dplay4 );

	comAdd[0].guidDataType = DPAID_ServiceProvider;
	comAdd[0].dwDataSize = sizeof(GUID);
	comAdd[0].lpData = (void*)&DPSPGUID_IPX;

	AllowFail=1;
	Size=0;
	wCreateCompoundAddress( dplobby3, comAdd, 1, NULL, &Size );
	p_address = (void*)malloc(Size);
	wCreateCompoundAddress( dplobby3, comAdd, 1, p_address, &Size );
	result = wInitializeConnection( temp_dplay4, p_address, 0 );		// Try to initialize the connection
	GameOSFPU();
	AllowFail=0;

	if( SUCCEEDED(result) )
		hasIPX=1;

	free( p_address );
	wRelease( temp_dplay4 );
//
// Check for serial ports (Using Win32)
//
	SerialPortNames=0;
    /* jcem - no Serial
	for( int t0=1; t0<9; t0++ )
	{
		char Buffer[10];
		sprintf( Buffer, "COM%d",t0 );

		HANDLE hCom = CreateFile( Buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );

		if (hCom != INVALID_HANDLE_VALUE)								// If it's a valid COM port
		{
			ListOfNames* pTemp=(ListOfNames*)gos_Malloc( sizeof(ListOfNames)+strlen(Buffer), Heap_Network );
			pTemp->pNext=0;
			pTemp->Data=t0;
			strcpy( pTemp->Name, Buffer );
			if( SerialPortNames )
			{
				ListOfNames* pLast=SerialPortNames;
				while( pLast->pNext )									// Add to end of list
					pLast=pLast->pNext;
				pLast->pNext=pTemp;
			}
			else
			{
				SerialPortNames=pTemp;
			}
			hasSerial=1;
			CloseHandle( hCom );
		}
	}
    */
//
// Check for modems
//
	ModemNames=0;

    /* jcem - no modems
	wCoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (void**)&temp_dplay4 );

	comAdd[0].guidDataType = DPAID_ServiceProvider;
	comAdd[0].dwDataSize = sizeof(GUID);
	comAdd[0].lpData = (void*)&DPSPGUID_MODEM;

	comAdd[1].guidDataType = DPAID_Modem;
	comAdd[1].dwDataSize = 1;
	comAdd[1].lpData = "";

	comAdd[2].guidDataType = DPAID_Phone;
	comAdd[2].dwDataSize = 1;
	comAdd[2].lpData = "";

	AllowFail=1;
	Size=0;
	wCreateCompoundAddress( dplobby3, comAdd, 3, NULL, &Size );
	p_address = (void*)malloc(Size);
	wCreateCompoundAddress( dplobby3, comAdd, 3, p_address, &Size );
	result = wInitializeConnection( temp_dplay4, p_address, 0 );		// Try to initialize the connection
	GameOSFPU();
	AllowFail=0;

	if( SUCCEEDED(result) )
	{
		DWORD ModemSize=0;
		wGetPlayerAddress( temp_dplay4, 0, NULL, &ModemSize );
		void* address = malloc(ModemSize);								// Enumerate all modems
		wGetPlayerAddress( temp_dplay4, 0, address, &ModemSize );
		wEnumAddress( dplobby3, ModemCallback, address, ModemSize, 0 );
		free( address );
	}

	free( p_address );
	wRelease( temp_dplay4 );
    */
//
// Restore FPU settings after enumeration
//
	GameOSFPU();
}








//
// Used to verify TCPIP working correctly. - Data returned is ignored
//
BOOL PASCAL QuickEnumSessionsCallback( LPCDPSESSIONDESC2 lpSessionDesc, LPDWORD lpdwTimeOut, DWORD dwFlags, void* lpContext )
{
    return false;
}

HRESULT PASCAL QuickEnum( bool async )
{
    HRESULT result;
	DPSESSIONDESC2 sessionDesc;
	memset( &sessionDesc, 0, sizeof(sessionDesc) );
	sessionDesc.dwSize=sizeof(sessionDesc);
	memcpy( &sessionDesc.guidApplication, &Environment.NetworkGUID, sizeof(GUID) );
	AllowFail=1;
    DWORD dwFlags = DPENUMSESSIONS_RETURNSTATUS | DPENUMSESSIONS_ALL | DPENUMSESSIONS_PASSWORDREQUIRED;
    if ( async )
    {
        dwFlags |= DPENUMSESSIONS_ASYNC;
    }

	result = wEnumSessions( dplay4, &sessionDesc, 0, QuickEnumSessionsCallback, 0, dwFlags );
	AllowFail=0;
    return result;
}


//
// Open a TCPIP connection
//
// You can pass the address of the server or NULL for the sub net.
//
//
bool __stdcall gos_ConnectTCP( char* IPAddress, WORD port )
{
	long result;
	DPCOMPOUNDADDRESSELEMENT comAdd[3];
	DWORD Size;
	void* p_address;

	if( !IPAddress )
		IPAddress="";
//
// Select TCPIP service provider
//
	comAdd[0].guidDataType = DPAID_ServiceProvider;
	comAdd[0].dwDataSize = sizeof(GUID);
	comAdd[0].lpData = (void*)&DPSPGUID_TCPIP;
//
// Store the TCPIP address of the server, or a pointer to a NULL for broadcast on the subnet
//
	comAdd[1].guidDataType = DPAID_INet;
	comAdd[1].dwDataSize = strlen(IPAddress)+1;
	comAdd[1].lpData = IPAddress;
//
// User passed a port to play through a firewall? (disables multiple games on a single machine)
//
	if( port!=0 )
	{
		comAdd[2].guidDataType = DPAID_INetPort;
		comAdd[2].dwDataSize = sizeof(WORD);
		comAdd[2].lpData = &port;
	}
//
// Create a compound address
//
	AllowFail=1;
	Size=0;
	wCreateCompoundAddress( dplobby3, comAdd, port ? 3 : 2, NULL, &Size );
	p_address = (void*)malloc(Size);
	wCreateCompoundAddress( dplobby3, comAdd, port ? 3 : 2, p_address, &Size );
//
// Initialize the connection
//
	result = wInitializeConnection( dplay4, p_address, 0 );
	GameOSFPU();

	AllowFail=0;
	free( p_address );
		
	if( FAILED(result) )
		return 0;
//
// Enum games available - this is done to detect bad server addresses
//
    result = QuickEnum( true );
//
// If there was an error, kill the connection
//
	if( FAILED(result) )
	{
		if( dplay4 )
		{
			wRelease( dplay4 );
			dplay4=0;
		}
		wCoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (LPVOID*)&dplay4 );
		GameOSFPU();
		return false;
	}
//
// Otherwise connected
//
	GameOSFPU();
	Connected = NP_TCP;
	return true;
}











////
////
//////
////// Open an IPX connection
//////
//////
////bool __stdcall gos_ConnectIPX()
////{
////	gosASSERT( !Connected );
////
////	long result;
////	DPCOMPOUNDADDRESSELEMENT comAdd[1];
////	DWORD Size;
////	void* p_address;
//////
////// Select IPX service provider
//////
////	comAdd[0].guidDataType = DPAID_ServiceProvider;
////	comAdd[0].dwDataSize = sizeof(GUID);
////	comAdd[0].lpData = (void*)&DPSPGUID_IPX;
//////
////// Create a compound address
//////
////	AllowFail=1;
////	Size=0;
////	wCreateCompoundAddress( dplobby3, comAdd, 1, NULL, &Size );
////	p_address = (void*)malloc(Size);
////	wCreateCompoundAddress( dplobby3, comAdd, 1, p_address, &Size );
//////
////// Initialize the connection
//////
////	result = wInitializeConnection( dplay4, p_address, 0 );
////	GameOSFPU();
////	AllowFail=0;
////
////	free( p_address );
////
////	GameOSFPU();
////
////	if( FAILED(result) )
////		return 0;
////
//////
////// Init game list functionality
//////
////	InitLanGames();
////
////	GameOSFPU();
////
////	Connected = NP_IPX;
////
////	return true;
////}
////
////
////
////




////
//////
////// Open an Modem connection
//////
////// Pass the phone number to dial and an optional modem number
//////
////bool __stdcall gos_ConnectModem( char* PhoneNumber, DWORD Modem )
////{
////	gosASSERT( !Connected );
////
////	DPCOMPOUNDADDRESSELEMENT comAdd[3];
////	long result;
////	DWORD Size;
////	void* p_address;
////	EnumResult=DPERR_CONNECTING;
//////
////// Answer mode?
//////
////	if( 0==PhoneNumber )
////		PhoneNumber="";
//////
////// Check modem number is valid and get name
//////
////	char* ModemName=(char*)gos_NetInformation( gos_NameOfModem, Modem );
////	if( 0==ModemName )
////		return 0;
//////
////// Select modem service provider
//////
////	comAdd[0].guidDataType = DPAID_ServiceProvider;
////	comAdd[0].dwDataSize = sizeof(GUID);
////	comAdd[0].lpData = (void*)&DPSPGUID_MODEM;
//////
////// Select modem
//////
////	comAdd[1].guidDataType = DPAID_Modem;
////	comAdd[1].dwDataSize = strlen(ModemName)+1;
////	comAdd[1].lpData = ModemName;
//////
////// Use phone number
//////
////	comAdd[2].guidDataType = DPAID_Phone;
////	comAdd[2].dwDataSize = strlen(PhoneNumber)+1;
////	comAdd[2].lpData = PhoneNumber;
//////
////// Create a compound address
//////
////	AllowFail=1;
////	Size=0;
////	wCreateCompoundAddress( dplobby3, comAdd, 3, NULL, &Size );
////	p_address = (void*)malloc(Size);
////	wCreateCompoundAddress( dplobby3, comAdd, 3, p_address, &Size );
//////
////// Initialize the connection
//////
////	result = wInitializeConnection( dplay4, p_address, 0 );
////	GameOSFPU();
////	AllowFail=0;
////	free( p_address );
////		
////	GameOSFPU();
////
////	if( FAILED(result) )
////		return 0;
////
//////
////// Init game list functionality
//////
////	InitLanGames();
////
////	Connected = NP_MODEM;
//////
//////
//////
////	return true;
////}
////
////
////













//
// Open an Serial connection
//
// You must pass a COM port number to try, 57600, 8, N, 1, RTS/DTR hardware flow control always used
//
bool __stdcall gos_ConnectSerialPort( DWORD com_port )
{
	gosASSERT( !Connected );

	DWORD Size;
	void* p_address;
	DPCOMPOUNDADDRESSELEMENT comAdd[2];
	DPCOMPORTADDRESS dp_comaddress;
//
// Setup 57600, 8, N, 1, RTS/DTR hardware flow control settings
//
	dp_comaddress.dwComPort = com_port+1;				// DirectPlay numbers are 1 upwards
	dp_comaddress.dwBaudRate = CBR_57600;
	dp_comaddress.dwStopBits = ONESTOPBIT;
	dp_comaddress.dwParity = NOPARITY;
	dp_comaddress.dwFlowControl = DPCPA_RTSDTRFLOW;
//
// Select Serial service provider
//
	comAdd[0].guidDataType = DPAID_ServiceProvider;
	comAdd[0].dwDataSize = sizeof(GUID);
	comAdd[0].lpData = (void*)&DPSPGUID_SERIAL;
//
// Specify COM port to use
//
	comAdd[1].guidDataType = DPAID_ComPort;
	comAdd[1].dwDataSize = sizeof(DPCOMPORTADDRESS);
	comAdd[1].lpData = (void*)&dp_comaddress;
//
// Create a compound address
//
	AllowFail=1;
	Size=0;
	wCreateCompoundAddress( dplobby3, comAdd, 2, NULL, &Size );
	p_address = (void*)malloc(Size);
	wCreateCompoundAddress( dplobby3, comAdd, 2, p_address, &Size );
//
// Initialize the connection
//
	HRESULT result = wInitializeConnection( dplay4, p_address, 0 );
	GameOSFPU();
	AllowFail=0;
	free( p_address );
		
	GameOSFPU();

	if( FAILED(result) )
		return 0;
//
// Init game list functionality
//
	InitLanGames();

	GameOSFPU();

	Connected = NP_SERIAL;

	return true;
}



//
// Open a TCPIP connection and enum sessions via ZoneTech
//
// You can pass the address of the ZoneTech server or NULL for the sub net.
//
//
#if 1
bool __stdcall gos_ConnectZoneMatch( char* IPAddress, WORD port )
{
    if ( Connected == NP_ZONEMATCH )
    {
        return true;
    }

	gosASSERT( !Connected );


	if( !IPAddress && !Environment.ZoneMatchServerIP)
		return FALSE;

	//
	// we can use address from above or environment address as ZoneMatchServerIP
	//
	
	if (!Environment.ZoneMatchServerIP)
	{
		Environment.ZoneMatchServerIP = (char *) gos_Malloc(strlen(IPAddress)+1);

		strcpy(Environment.ZoneMatchServerIP ,IPAddress);
	}
    else if ( IPAddress && strcmp(IPAddress, Environment.ZoneMatchServerIP) )
    {
        if ( strlen(Environment.ZoneMatchServerIP) < strlen(IPAddress) )
        {
            gos_Free( Environment.ZoneMatchServerIP );
            Environment.ZoneMatchServerIP = NULL;
		    Environment.ZoneMatchServerIP = (char *) gos_Malloc(strlen(IPAddress)+1);
        }
        strcpy(Environment.ZoneMatchServerIP ,IPAddress);
    }


        

	//if (!gos_ConnectTCP(NULL,0))
	//	return false;


	
	InitGUNGames();

    Connected = NP_ZONEMATCH;
    
    
	return true;
}
#endif