CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

IPXMGR.CPP (85514B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/IPXMGR.CPP 3     10/13/97 2:20p Steve_t $ */
     17 /***************************************************************************
     18  **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **
     19  ***************************************************************************
     20  *                                                                         *
     21  *                 Project Name : Command & Conquer                        *
     22  *                                                                         *
     23  *                    File Name : IPXMGR.CPP                               *
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : December 20, 1994                        *
     28  *                                                                         *
     29  *                  Last Update : May 4, 1995 [BRR]                        *
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  * Functions:                                                       			*
     33  *   IPXManagerClass::IPXManagerClass -- class constructor                 *
     34  *   IPXManagerClass::~IPXManagerClass -- class destructor                 *
     35  *   IPXManagerClass::Init -- initialization routine								*
     36  *   IPXManagerClass::Is_IPX -- tells if IPX is installed or not				*
     37  *   IPXManagerClass::Set_Timing -- sets timing for all connections			*
     38  *   IPXManagerClass::Create_Connection -- creates a new connection        *
     39  *   IPXManagerClass::Delete_Connection -- deletes a connection            *
     40  *   IPXManagerClass::Num_Connections -- gets the # of connections			*
     41  *   IPXManagerClass::Connection_ID -- gets the given connection's ID      *
     42  *   IPXManagerClass::Connection_Name -- gets name for given connection    *
     43  *   IPXManagerClass::Connection_Address -- retrieves connection's address	*
     44  *   IPXManagerClass::Connection_Index -- gets given connection's index    *
     45  *   IPXManagerClass::Set_Connection_Parms -- sets connection's name & id	*
     46  *   IPXManagerClass::Send_Global_Message -- sends a Global Message			*
     47  *   IPXManagerClass::Get_Global_Message -- polls the Global Message queue	*
     48  *   IPXManagerClass::Send_Private_Message -- Sends a Private Message		*
     49  *   IPXManagerClass::Get_Private_Message -- Polls Private Message queue	*
     50  *   IPXManagerClass::Service -- main polling routine for IPX Connections	*
     51  *   IPXManagerClass::Get_Bad_Connection -- returns bad connection ID      *
     52  *   IPXManagerClass::Global_Num_Send	-- gets # entries in send queue	   *
     53  *   IPXManagerClass::Global_Num_Receive -- gets # entries in recv queue   *
     54  *   IPXManagerClass::Private_Num_Send -- gets # entries in send queue	   *
     55  *   IPXManagerClass::Private_Num_Receive -- gets # entries in recv queue  *
     56  *   IPXManagerClass::Set_Bridge -- prepares to cross a bridge             *
     57  *   IPXManagerClass::Set_Socket -- sets socket ID for all connections		*
     58  *   IPXManagerClass::Response_Time -- Returns largest Avg Response Time   *
     59  *   IPXManagerClass::Global_Response_Time -- Returns Avg Response Time    *
     60  *   IPXManagerClass::Reset_Response_Time -- Reset response time 				*
     61  *   IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf           *
     62  *   IPXManagerClass::Mono_Debug_Print -- debug output routine					*
     63  *   IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory		*
     64  *   IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory				*
     65  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     66 
     67 #include	"function.h"
     68 #include <stdio.h>
     69 //#include <mem.h> PG
     70 //#include <i86.h> PG
     71 #include "ipxmgr.h"
     72 #include "wwlib32.h"	// to enable mono output
     73 
     74 #ifdef WINSOCK_IPX
     75 
     76 #include "WSProto.h"
     77 #include "WSPIPX.h"
     78 
     79 #else	//WINSOCK_IPX
     80 
     81 #include "ipx95.h"
     82 #ifdef WIN32
     83 #include "tcpip.h"
     84 #else
     85 #include	"fakesock.h"
     86 #endif	//WIN32
     87 
     88 #endif	//WINSOCK_IPX
     89 
     90 // Turn off "expression is not meaningful".
     91 //#pragma warning 628 9
     92 
     93 //#include "WolDebug.h"
     94 
     95 /***************************************************************************
     96  * IPXManagerClass::IPXManagerClass -- class constructor                   *
     97  *                                                                         *
     98  * INPUT:                                                                  *
     99  *		glb_maxlen		Global Channel maximum packet length						*
    100  *		pvt_maxlen		Private Channel maximum packet length						*
    101  *		socket			socket ID to use													*
    102  *		product_id		a unique numerical ID for this product						*
    103  *                                                                         *
    104  * OUTPUT:                                                                 *
    105  *		none.																						*
    106  *                                                                         *
    107  * WARNINGS:                                                               *
    108  *		The socket number is byte-swapped, since IPX requires socket ID's		*
    109  *		to be stored high/low.																*
    110  *                                                                         *
    111  * HISTORY:                                                                *
    112  *   12/20/1994 BR : Created.                                              *
    113  *=========================================================================*/
    114 IPXManagerClass::IPXManagerClass (int glb_maxlen, int pvt_maxlen,
    115 	int glb_num_packets, int pvt_num_packets, unsigned short socket,
    116 	unsigned short product_id)
    117 {
    118 	int i;
    119 #ifdef WINSOCK_IPX
    120 	/*
    121 	** Find out if Packet protocol services are available through Winsock.
    122 	*/
    123 	if ( PacketTransport ) {
    124 		delete  PacketTransport;
    125 		PacketTransport = NULL;
    126 	}
    127 	PacketTransport = new WinsockInterfaceClass;
    128 	assert ( PacketTransport != NULL );
    129 
    130 	if ( PacketTransport->Init() ){
    131 		IPXStatus = 1;
    132 	}else{
    133 		IPXStatus = 0;
    134 	}
    135 	delete PacketTransport;
    136 	PacketTransport = NULL;
    137 
    138 #else	//WINSOCK_IPX
    139 
    140 	//------------------------------------------------------------------------
    141 	//	Initialize data members
    142 	//------------------------------------------------------------------------
    143 	//........................................................................
    144 	//	IPXStatus = 1 if IPX is installed, 0 if not
    145 	//........................................................................
    146 	if (IPX_SPX_Installed()==0) {
    147 		IPXStatus = 0;
    148 	}
    149 	else {
    150 		IPXStatus = 1;
    151 	}
    152 #endif	//WINSOCK_IPX
    153 
    154 	//........................................................................
    155 	//	Set listening state flag to off
    156 	//........................................................................
    157 	Listening = 0;
    158 
    159 	//........................................................................
    160 	//	No memory has been alloc'd yet
    161 	//........................................................................
    162 	RealMemAllocd = 0;
    163 
    164 	//........................................................................
    165 	//	Set max packet sizes, for allocating real-mode memory
    166 	//........................................................................
    167 	Glb_MaxPacketLen = glb_maxlen;
    168 	Glb_NumPackets = glb_num_packets;
    169 	Pvt_MaxPacketLen = pvt_maxlen;
    170 	Pvt_NumPackets = pvt_num_packets;
    171 
    172 	//........................................................................
    173 	//	Save the app's product ID
    174 	//........................................................................
    175 	ProductID = product_id;
    176 
    177 	//........................................................................
    178 	//	Save our socket ID number
    179 	//........................................................................
    180 	Socket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) |
    181 		(((unsigned long)socket & 0xff00) >> 8));
    182 
    183 	//------------------------------------------------------------------------
    184 	//	Get the user's IPX local connection number
    185 	//------------------------------------------------------------------------
    186 	ConnectionNum = 0;
    187 #ifndef WINSOCK_IPX
    188 	if (IPXStatus) {
    189 		ConnectionNum = IPX_Get_Connection_Number();
    190 	}
    191 #endif	//WINSOCK_IPX
    192 
    193 	//------------------------------------------------------------------------
    194 	//	Init connection states
    195 	//------------------------------------------------------------------------
    196 	NumConnections = 0;
    197 	CurConnection = 0;
    198 	for (i = 0; i < CONNECT_MAX; i++) {
    199 		Connection[i] = 0;
    200 	}
    201 	GlobalChannel = 0;
    202 
    203 	SendOverflows = 0;
    204 	ReceiveOverflows = 0;
    205 	BadConnection = CONNECTION_NONE;
    206 
    207 	//------------------------------------------------------------------------
    208 	//	Init timing parameters
    209 	//------------------------------------------------------------------------
    210 	RetryDelta = 2;		// 2 ticks between retries
    211 	MaxRetries = -1;		// disregard # retries
    212 	Timeout = 60;			// report bad connection after 1 second
    213 
    214 }	/* end of IPXManagerClass */
    215 
    216 
    217 /***************************************************************************
    218  * IPXManagerClass::~IPXManagerClass -- class destructor                   *
    219  *                                                                         *
    220  * INPUT:                                                                  *
    221  *		none.																						*
    222  *                                                                         *
    223  * OUTPUT:                                                                 *
    224  *		none.																						*
    225  *                                                                         *
    226  * WARNINGS:                                                               *
    227  *		none.																						*
    228  *                                                                         *
    229  * HISTORY:                                                                *
    230  *   12/20/1994 BR : Created.                                              *
    231  *=========================================================================*/
    232 IPXManagerClass::~IPXManagerClass()
    233 {
    234 	int i;
    235 
    236 	//------------------------------------------------------------------------
    237 	//	Stop all IPX events
    238 	//------------------------------------------------------------------------
    239 	if (Listening) {
    240 		IPXConnClass::Stop_Listening();
    241 		Listening = 0;
    242 	}
    243 
    244 	//------------------------------------------------------------------------
    245 	//	Free all protected-mode memory
    246 	//------------------------------------------------------------------------
    247 	if (GlobalChannel) {
    248 		delete GlobalChannel;
    249 		GlobalChannel = 0;
    250 	}
    251 	for (i = 0; i < NumConnections; i++) {
    252 		delete Connection[i];
    253 		Connection[i] = 0;
    254 	}
    255 	NumConnections = 0;
    256 
    257 	//------------------------------------------------------------------------
    258 	//	Free all real-mode memory
    259 	//------------------------------------------------------------------------
    260 	if (RealMemAllocd) {
    261 		Free_RealMode_Mem();
    262 		RealMemAllocd = 0;
    263 	}
    264 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    265 #ifdef WIN32
    266 #ifndef WINSOCK_IPX
    267 //PG	Unload_IPX_Dll();
    268 #endif
    269 #endif
    270 #endif
    271 }	/* end of ~IPXManagerClass */
    272 
    273 
    274 /***************************************************************************
    275  * IPXManagerClass::Init -- initialization routine									*
    276  *                                                                         *
    277  * This routine allocates memory, & initializes variables						*
    278  *                                                                         *
    279  * INPUT:                                                                  *
    280  *		none.																						*
    281  *                                                                         *
    282  * OUTPUT:                                                                 *
    283  *		1 = OK, 0 = error																		*
    284  *                                                                         *
    285  * WARNINGS:                                                               *
    286  *		none.																						*
    287  *                                                                         *
    288  * HISTORY:                                                                *
    289  *   12/20/1994 BR : Created.                                              *
    290  *=========================================================================*/
    291 int IPXManagerClass::Init()
    292 {
    293 	int i;
    294 
    295 	if (Session.Type != GAME_INTERNET) {
    296 
    297 		//------------------------------------------------------------------------
    298 		//	Error if IPX not installed
    299 		//------------------------------------------------------------------------
    300 		if (!IPXStatus) {
    301 			return(0);
    302 		}
    303 
    304 		//------------------------------------------------------------------------
    305 		//	Stop Listening
    306 		//------------------------------------------------------------------------
    307 		if (Listening) {
    308 			IPXConnClass::Stop_Listening();
    309 			Listening = 0;
    310 		}
    311 
    312 		//------------------------------------------------------------------------
    313 		//	Free Real-mode memory
    314 		//------------------------------------------------------------------------
    315 		if (RealMemAllocd) {
    316 			Free_RealMode_Mem();
    317 			RealMemAllocd = 0;
    318 		}
    319 
    320 	} else {
    321 		/*
    322 		** Pretend IPX is available for Internet games whether it is or not
    323 		*/
    324 		IPXStatus = 1;
    325 	}
    326 
    327 	//------------------------------------------------------------------------
    328 	//	Free protected-mode memory
    329 	//------------------------------------------------------------------------
    330 	if (GlobalChannel) {
    331 		delete GlobalChannel;
    332 		GlobalChannel = 0;
    333 	}
    334 	for (i = 0; i < NumConnections; i++) {
    335 		delete Connection[i];
    336 		Connection[i] = 0;
    337 	}
    338 	NumConnections = 0;
    339 
    340 	if (Session.Type != GAME_INTERNET) {
    341 		//------------------------------------------------------------------------
    342 		//	Allocate real-mode memory
    343 		//------------------------------------------------------------------------
    344 		if (!Alloc_RealMode_Mem()) return(0);
    345 		RealMemAllocd = 1;
    346 	}
    347 
    348 	//------------------------------------------------------------------------
    349 	//	Allocate the Global Channel
    350 	//------------------------------------------------------------------------
    351 	GlobalChannel = new IPXGlobalConnClass (Glb_NumPackets, Glb_NumPackets,
    352 		Glb_MaxPacketLen, ProductID);
    353 	if (!GlobalChannel) {
    354 		return(0);
    355 	}
    356 	GlobalChannel->Init();
    357 	GlobalChannel->Set_Retry_Delta (RetryDelta);
    358 	GlobalChannel->Set_Max_Retries (MaxRetries);
    359 	GlobalChannel->Set_TimeOut (Timeout);
    360 
    361 	//------------------------------------------------------------------------
    362 	//	Configure the IPX Connections
    363 	//------------------------------------------------------------------------
    364 	IPXConnClass::Configure(Socket, ConnectionNum, ListenECB, SendECB,
    365 		FirstHeaderBuf, SendHeader, FirstDataBuf, SendBuf, Handler, PacketLen);
    366 
    367 	//------------------------------------------------------------------------
    368 	//	Start Listening
    369 	//------------------------------------------------------------------------
    370 	if (Session.Type != GAME_INTERNET) {
    371 		if (!IPXConnClass::Start_Listening()) return(0);
    372 	}
    373 	Listening = 1;
    374 
    375 	return(1);
    376 
    377 }	/* end of Init */
    378 
    379 
    380 /***************************************************************************
    381  * IPXManagerClass::Is_IPX -- tells if IPX is installed or not					*
    382  *                                                                         *
    383  * INPUT:                                                                  *
    384  *		none.																						*
    385  *                                                                         *
    386  * OUTPUT:                                                                 *
    387  *		1 = IPX is installed; 0 = isn't													*
    388  *                                                                         *
    389  * WARNINGS:                                                               *
    390  *		none.																						*
    391  *                                                                         *
    392  * HISTORY:                                                                *
    393  *   12/20/1994 BR : Created.                                              *
    394  *=========================================================================*/
    395 int IPXManagerClass::Is_IPX(void)
    396 {
    397 	return(IPXStatus);
    398 
    399 }	/* end of Is_IPX */
    400 
    401 
    402 /***************************************************************************
    403  * IPXManagerClass::Set_Timing -- sets timing for all connections				*
    404  *                                                                         *
    405  * This will set the timing parameters for all existing connections, and	*
    406  * all connections created from now on.  This allows an application to		*
    407  * measure the Response_Time while running, and adjust timing accordingly.	*
    408  *                                                                         *
    409  * INPUT:                                                                  *
    410  *		retrydelta	value to set for retry delta 										*
    411  *		maxretries	value to set for max # retries									*
    412  *		timeout		value to set for connection timeout								*
    413  *                                                                         *
    414  * OUTPUT:                                                                 *
    415  *		none.																						*
    416  *                                                                         *
    417  * WARNINGS:                                                               *
    418  *		none.																						*
    419  *                                                                         *
    420  * HISTORY:                                                                *
    421  *   07/02/1995 BR : Created.                                              *
    422  *=========================================================================*/
    423 void IPXManagerClass::Set_Timing (unsigned long retrydelta,
    424 	unsigned long maxretries, unsigned long timeout)
    425 {
    426 	int i;
    427 
    428 	RetryDelta = retrydelta;
    429 	MaxRetries = maxretries;
    430 	Timeout = timeout;
    431 
    432 	if (GlobalChannel) {
    433 		GlobalChannel->Set_Retry_Delta (RetryDelta);
    434 		GlobalChannel->Set_Max_Retries (MaxRetries);
    435 		GlobalChannel->Set_TimeOut (Timeout);
    436 	}
    437 
    438 	for (i = 0; i < NumConnections; i++) {
    439 		Connection[i]->Set_Retry_Delta (RetryDelta);
    440 		Connection[i]->Set_Max_Retries (MaxRetries);
    441 		Connection[i]->Set_TimeOut (Timeout);
    442 	}
    443 
    444 }	/* end of Set_Timing */
    445 
    446 
    447 /***************************************************************************
    448  * IPXManagerClass::Create_Connection -- creates a new connection          *
    449  *                                                                         *
    450  * INPUT:                                                                  *
    451  *		id				application-specific numerical ID for this connection		*
    452  *		node			ptr to IPXNodeIDType (name & address)							*
    453  *		address		IPX address for this connection									*
    454  *                                                                         *
    455  * OUTPUT:                                                                 *
    456  *		1 = OK, 0 = error																		*
    457  *                                                                         *
    458  * WARNINGS:                                                               *
    459  *		Never create a connection with an 'id' of -1.								*
    460  *                                                                         *
    461  * HISTORY:                                                                *
    462  *   12/20/1994 BR : Created.                                              *
    463  *=========================================================================*/
    464 int IPXManagerClass::Create_Connection(int id, char *name,
    465 	IPXAddressClass *address)
    466 {
    467 	//------------------------------------------------------------------------
    468 	//	Error if IPX not installed
    469 	//------------------------------------------------------------------------
    470 	if (!IPXStatus) {
    471 		return(0);
    472 	}
    473 
    474 	//------------------------------------------------------------------------
    475 	//	Error if no more room
    476 	//------------------------------------------------------------------------
    477 	if (NumConnections==CONNECT_MAX) {
    478 		return(0);
    479 	}
    480 
    481 	//------------------------------------------------------------------------
    482 	//	Create new connection
    483 	//------------------------------------------------------------------------
    484 	Connection[NumConnections] = new IPXConnClass(Pvt_NumPackets,
    485 		Pvt_NumPackets, Pvt_MaxPacketLen, ProductID, address, id, name);
    486 	if (!Connection[NumConnections]) {
    487 		return(0);
    488 	}
    489 
    490 	Connection[NumConnections]->Init ();
    491 	Connection[NumConnections]->Set_Retry_Delta (RetryDelta);
    492 	Connection[NumConnections]->Set_Max_Retries (MaxRetries);
    493 	Connection[NumConnections]->Set_TimeOut (Timeout);
    494 
    495 	NumConnections++;
    496 
    497 	return(1);
    498 
    499 }	/* end of Create_Connection */
    500 
    501 
    502 /***************************************************************************
    503  * IPXManagerClass::Delete_Connection -- deletes a connection              *
    504  *                                                                         *
    505  * INPUT:                                                                  *
    506  *		id		ID of connection to delete													*
    507  *                                                                         *
    508  * OUTPUT:                                                                 *
    509  *		1 = OK, 0 = error																		*
    510  *                                                                         *
    511  * WARNINGS:                                                               *
    512  *		none.																						*
    513  *                                                                         *
    514  * HISTORY:                                                                *
    515  *   12/20/1994 BR : Created.                                              *
    516  *=========================================================================*/
    517 int IPXManagerClass::Delete_Connection(int id)
    518 {
    519 	int i,j;
    520 
    521 	//------------------------------------------------------------------------
    522 	//	Error if IPX not installed
    523 	//------------------------------------------------------------------------
    524 	if (!IPXStatus) {
    525 		return(0);
    526 	}
    527 
    528 	//------------------------------------------------------------------------
    529 	//	Error if no connections to delete
    530 	//------------------------------------------------------------------------
    531 	if (NumConnections==0) {
    532 		return(0);
    533 	}
    534 
    535 	//------------------------------------------------------------------------
    536 	//	Loop through all connections
    537 	//------------------------------------------------------------------------
    538 	for (i = 0; i < NumConnections; i++) {
    539 		//.....................................................................
    540 		//	If a match, delete it
    541 		//.....................................................................
    542 		if (Connection[i]->ID==id) {
    543 			delete Connection[i];
    544 
    545 			//..................................................................
    546 			//	Move array elements back one index
    547 			//..................................................................
    548 			for (j = i; j < NumConnections - 1; j++) {
    549 				Connection[j] = Connection[j+1];
    550 			}
    551 
    552 			//..................................................................
    553 			//	Adjust counters
    554 			//..................................................................
    555 			NumConnections--;
    556 			if (CurConnection >= NumConnections)
    557 				CurConnection = 0;
    558 			return(1);
    559 		}
    560 	}
    561 
    562 	//------------------------------------------------------------------------
    563 	//	No match; error
    564 	//------------------------------------------------------------------------
    565 	return(0);
    566 
    567 }	/* end of Delete_Connection */
    568 
    569 
    570 /***************************************************************************
    571  * IPXManagerClass::Num_Connections -- gets the # of connections				*
    572  *                                                                         *
    573  * INPUT:                                                                  *
    574  *		none.																						*
    575  *                                                                         *
    576  * OUTPUT:                                                                 *
    577  *		# of connections																		*
    578  *                                                                         *
    579  * WARNINGS:                                                               *
    580  *		none.																						*
    581  *                                                                         *
    582  * HISTORY:                                                                *
    583  *   01/25/1995 BR : Created.                                              *
    584  *=========================================================================*/
    585 int IPXManagerClass::Num_Connections(void)
    586 {
    587 	return(NumConnections);
    588 
    589 }	/* end of Num_Connections */
    590 
    591 
    592 /***************************************************************************
    593  * IPXManagerClass::Connection_ID -- gets the given connection's ID        *
    594  *                                                                         *
    595  * INPUT:                                                                  *
    596  *		index			index of connection to retrieve									*
    597  *                                                                         *
    598  * OUTPUT:                                                                 *
    599  *		ID for that connection, CONNECTION_NONE if invalid index					*
    600  *                                                                         *
    601  * WARNINGS:                                                               *
    602  *		none.																						*
    603  *                                                                         *
    604  * HISTORY:                                                                *
    605  *   01/25/1995 BR : Created.                                              *
    606  *=========================================================================*/
    607 int IPXManagerClass::Connection_ID(int index)
    608 {
    609 	if (index >= 0 && index < NumConnections) {
    610 		return(Connection[index]->ID);
    611 	}
    612 	else {
    613 		return(CONNECTION_NONE);
    614 	}
    615 }	/* end of Connection_ID */
    616 
    617 
    618 /***************************************************************************
    619  * IPXManagerClass::Connection_Name -- retrieves name for given connection *
    620  *                                                                         *
    621  * INPUT:                                                                  *
    622  *		id		ID of connection to get name of											*
    623  *                                                                         *
    624  * OUTPUT:                                                                 *
    625  *		ptr to connection's name, NULL if not found									*
    626  *                                                                         *
    627  * WARNINGS:                                                               *
    628  *		none.																						*
    629  *                                                                         *
    630  * HISTORY:                                                                *
    631  *   01/19/1995 BR : Created.                                              *
    632  *=========================================================================*/
    633 char *IPXManagerClass::Connection_Name(int id)
    634 {
    635 	int i;
    636 
    637 	for (i = 0; i < NumConnections; i++) {
    638 		if (Connection[i]->ID==id) {
    639 			return(Connection[i]->Name);
    640 		}
    641 	}
    642 
    643 	return(NULL);
    644 
    645 }	/* end of Connection_Name */
    646 
    647 
    648 /***************************************************************************
    649  * IPXManagerClass::Connection_Address -- retrieves connection's address	*
    650  *                                                                         *
    651  * INPUT:                                                                  *
    652  *		id		ID of connection to get address for										*
    653  *                                                                         *
    654  * OUTPUT:                                                                 *
    655  *		pointer to IXPAddressClass, NULL if not found								*
    656  *                                                                         *
    657  * WARNINGS:                                                               *
    658  *		none.																						*
    659  *                                                                         *
    660  * HISTORY:                                                                *
    661  *   01/19/1995 BR : Created.                                              *
    662  *=========================================================================*/
    663 IPXAddressClass * IPXManagerClass::Connection_Address(int id)
    664 {
    665 	int i;
    666 
    667 	for (i = 0; i < NumConnections; i++) {
    668 		if (Connection[i]->ID==id) {
    669 			return(&Connection[i]->Address);
    670 		}
    671 	}
    672 
    673 	return(NULL);
    674 
    675 }	/* end of Connection_Address */
    676 
    677 
    678 /***************************************************************************
    679  * IPXManagerClass::Connection_Index -- gets given connection's index      *
    680  *                                                                         *
    681  * INPUT:                                                                  *
    682  *		ID to retrieve index for															*
    683  *                                                                         *
    684  * OUTPUT:                                                                 *
    685  *		index for this connection, CONNECTION_NONE if not found					*
    686  *                                                                         *
    687  * WARNINGS:                                                               *
    688  *		none.																						*
    689  *                                                                         *
    690  * HISTORY:                                                                *
    691  *   01/25/1995 BR : Created.                                              *
    692  *=========================================================================*/
    693 int IPXManagerClass::Connection_Index(int id)
    694 {
    695 	int i;
    696 
    697 	for (i = 0; i < NumConnections; i++) {
    698 		if (Connection[i]->ID==id) {
    699 			return(i);
    700 		}
    701 	}
    702 
    703 	return(CONNECTION_NONE);
    704 
    705 }	/* end of Connection_Index */
    706 
    707 
    708 /***************************************************************************
    709  * IPXManagerClass::Set_Connection_Parms -- sets connection's name & id		*
    710  *                                                                         *
    711  * INPUT:                                                                  *
    712  *		index		connection index															*
    713  *		id			new connection ID															*
    714  *		name		new connection name														*
    715  *                                                                         *
    716  * OUTPUT:                                                                 *
    717  *		none.																						*
    718  *                                                                         *
    719  * WARNINGS:                                                               *
    720  *		none.																						*
    721  *                                                                         *
    722  * HISTORY:                                                                *
    723  *   01/25/1995 BR : Created.                                              *
    724  *=========================================================================*/
    725 void IPXManagerClass::Set_Connection_Parms(int index, int id, char *name)
    726 {
    727 	if (index >= NumConnections)
    728 		return;
    729 
    730 	Connection[index]->ID = id;
    731 	strcpy(Connection[index]->Name,name);
    732 
    733 }	/* end of Set_Connection_Parms */
    734 
    735 
    736 /***************************************************************************
    737  * IPXManagerClass::Send_Global_Message -- sends a Global Message				*
    738  *                                                                         *
    739  * INPUT:                                                                  *
    740  *		buf			buffer to send															*
    741  *		buflen		length of buf															*
    742  *		ack_req		1 = ACK required; 0 = no ACK required							*
    743  *		address		address to send to; NULL = broadcast							*
    744  *                                                                         *
    745  * OUTPUT:                                                                 *
    746  *		1 = OK, 0 = error																		*
    747  *                                                                         *
    748  * WARNINGS:                                                               *
    749  *		none.																						*
    750  *                                                                         *
    751  * HISTORY:                                                                *
    752  *   01/25/1995 BR : Created.                                              *
    753  *=========================================================================*/
    754 int IPXManagerClass::Send_Global_Message(void *buf, int buflen,
    755 	int ack_req, IPXAddressClass *address)
    756 {
    757 	int rc;
    758 
    759 	//------------------------------------------------------------------------
    760 	//	Error if IPX not installed or not Listening
    761 	//------------------------------------------------------------------------
    762 	if (!IPXStatus || !Listening) return(0);
    763 
    764 	rc = GlobalChannel->Send_Packet (buf, buflen, address, ack_req);
    765 	if (!rc) {
    766 		SendOverflows++;
    767 	}
    768 
    769 	return(rc);
    770 
    771 }	/* end of Send_Global_Message */
    772 
    773 
    774 /***************************************************************************
    775  * IPXManagerClass::Get_Global_Message -- polls the Global Message queue	*
    776  *                                                                         *
    777  * INPUT:                                                                  *
    778  *		buf				buffer to store received packet								*
    779  *		buflen			length of data placed in 'buf'								*
    780  *		address			IPX address of sender											*
    781  *		product_id		product ID of sender												*
    782  *                                                                         *
    783  * OUTPUT:                                                                 *
    784  *		1 = OK, 0 = error																		*
    785  *                                                                         *
    786  * WARNINGS:                                                               *
    787  *		none.																						*
    788  *                                                                         *
    789  * HISTORY:                                                                *
    790  *   01/25/1995 BR : Created.                                              *
    791  *=========================================================================*/
    792 int IPXManagerClass::Get_Global_Message(void *buf, int *buflen,
    793 	IPXAddressClass *address, unsigned short *product_id)
    794 {
    795 	//------------------------------------------------------------------------
    796 	//	Error if IPX not installed or not Listening
    797 	//------------------------------------------------------------------------
    798 	if (!IPXStatus || !Listening) return(0);
    799 
    800 	return(GlobalChannel->Get_Packet (buf, buflen, address, product_id));
    801 
    802 }	/* end of Get_Global_Message */
    803 
    804 
    805 /***************************************************************************
    806  * IPXManagerClass::Send_Private_Message -- Sends a Private Message			*
    807  *                                                                         *
    808  * INPUT:                                                                  *
    809  *		buf			buffer to send															*
    810  *		buflen		length of 'buf'														*
    811  *		conn_id		connection ID to send to (CONNECTION_NONE = all)			*
    812  *		ack_req		1 = ACK required; 0 = no ACK required							*
    813  *                                                                         *
    814  * OUTPUT:                                                                 *
    815  *		1 = OK, 0 = error																		*
    816  *                                                                         *
    817  * WARNINGS:                                                               *
    818  *		none.																						*
    819  *                                                                         *
    820  * HISTORY:                                                                *
    821  *   01/25/1995 BR : Created.                                              *
    822  *=========================================================================*/
    823 int IPXManagerClass::Send_Private_Message(void *buf, int buflen, int ack_req,
    824 	int conn_id)
    825 {
    826 	int i;						// loop counter
    827 	int connect_idx;			// index of channel to send to, if specified
    828 
    829 	//------------------------------------------------------------------------
    830 	//	Error if IPX not installed or not Listening
    831 	//------------------------------------------------------------------------
    832 
    833 	if (!IPXStatus || !Listening || (NumConnections==0)) {
    834 		return(0);
    835 	}
    836 
    837 	//------------------------------------------------------------------------
    838 	//	Send the message to all connections
    839 	//------------------------------------------------------------------------
    840 	if (conn_id==CONNECTION_NONE) {
    841 		//.....................................................................
    842 		//	Check for room in all connections
    843 		//.....................................................................
    844 		for (i = 0; i < NumConnections; i++) {
    845 			if (Connection[i]->Queue->Num_Send() ==
    846 				Connection[i]->Queue->Max_Send()) {
    847 				SendOverflows++;
    848 				return(0);
    849 			}
    850 		}
    851 
    852 		//.....................................................................
    853 		//	Send packet to all connections
    854 		//.....................................................................
    855 		for (i = 0; i < NumConnections; i++) {
    856 			Connection[i]->Send_Packet (buf, buflen, ack_req);
    857 		}
    858 		return(1);
    859 	}
    860 
    861 	//------------------------------------------------------------------------
    862 	//	Send the message to the specified connection
    863 	//------------------------------------------------------------------------
    864 	else {
    865 		connect_idx = Connection_Index (conn_id);
    866 		if (connect_idx == CONNECTION_NONE) {
    867 			SendOverflows++;
    868 			return(0);
    869 		}
    870 
    871 		//.....................................................................
    872 		//	Check for room in the connection
    873 		//.....................................................................
    874 		if (Connection[connect_idx]->Queue->Num_Send() ==
    875 			Connection[connect_idx]->Queue->Max_Send()) {
    876 			SendOverflows++;
    877 			return(0);
    878 		}
    879 
    880 		//.....................................................................
    881 		//	Send the packet to that connection
    882 		//.....................................................................
    883 		Connection[connect_idx]->Send_Packet (buf, buflen, ack_req);
    884 		return(1);
    885 	}
    886 
    887 }	/* end of Send_Private_Message */
    888 
    889 
    890 /***************************************************************************
    891  * IPXManagerClass::Get_Private_Message -- Polls the Private Message queue	*
    892  *                                                                         *
    893  * INPUT:                                                                  *
    894  *		buf			buffer to store incoming packet									*
    895  *		buflen		length of data placed in 'buf'									*
    896  *		conn_id		filled in with connection ID of sender							*
    897  *                                                                         *
    898  * OUTPUT:                                                                 *
    899  *		1 = OK, 0 = error																		*
    900  *                                                                         *
    901  * WARNINGS:                                                               *
    902  *		none.																						*
    903  *                                                                         *
    904  * HISTORY:                                                                *
    905  *   01/25/1995 BR : Created.                                              *
    906  *=========================================================================*/
    907 int IPXManagerClass::Get_Private_Message(void *buf, int *buflen, int *conn_id)
    908 {
    909 	int i;
    910 	int rc;
    911 	int c_id;
    912 
    913 	//------------------------------------------------------------------------
    914 	//	Error if IPX not installed or not Listening
    915 	//------------------------------------------------------------------------
    916 	if (!IPXStatus || !Listening || (NumConnections==0)) {
    917 		return(0);
    918 	}
    919 
    920 	//------------------------------------------------------------------------
    921 	//	Safety check: ensure CurConnection is in range.
    922 	//------------------------------------------------------------------------
    923 	if (CurConnection >= NumConnections) {
    924 		CurConnection = 0;
    925 	}
    926 
    927 	//------------------------------------------------------------------------
    928 	//	Scan all connections for a received packet, starting with 'CurConnection'
    929 	//------------------------------------------------------------------------
    930 	for (i = 0; i < NumConnections; i++) {
    931 
    932 		//.....................................................................
    933 		//	Check this connection for a packet
    934 		//.....................................................................
    935 		rc = Connection[CurConnection]->Get_Packet (buf, buflen);
    936 		c_id = Connection[CurConnection]->ID;
    937 
    938 		//.....................................................................
    939 		//	Increment CurConnection to the next connection index
    940 		//.....................................................................
    941 		CurConnection++;
    942 		if (CurConnection >= NumConnections) {
    943 			CurConnection = 0;
    944 		}
    945 
    946 		//.....................................................................
    947 		//	If we got a packet, return the connection ID
    948 		//.....................................................................
    949 		if (rc) {
    950 			(*conn_id) = c_id;
    951 			return(1);
    952 		}
    953 	}
    954 
    955 	return(0);
    956 
    957 }	/* end of Get_Private_Message */
    958 
    959 
    960 /***************************************************************************
    961  * IPXManagerClass::Service -- main polling routine for IPX Connections		*
    962  *                                                                         *
    963  * INPUT:                                                                  *
    964  *		none.																						*
    965  *                                                                         *
    966  * OUTPUT:                                                                 *
    967  *		1 = OK, 0 = error																		*
    968  *                                                                         *
    969  * WARNINGS:                                                               *
    970  *		none.																						*
    971  *                                                                         *
    972  * HISTORY:                                                                *
    973  *   01/25/1995 BR : Created.                                              *
    974  *=========================================================================*/
    975 int IPXManagerClass::Service(void)
    976 {
    977 	int rc = 1;
    978 	int i;
    979 	CommHeaderType *packet;
    980 	int packetlen;
    981 	IPXAddressClass address;
    982 
    983 #ifdef WINSOCK_IPX
    984 
    985 
    986 	unsigned char temp_receive_buffer[1024];
    987 	int	temp_receive_buffer_len;
    988 	int	temp_address_len;
    989 
    990 
    991 	char temp_address [128];
    992 
    993 	if ( PacketTransport ) {
    994 
    995 		do {
    996 			temp_receive_buffer_len = sizeof (temp_receive_buffer);
    997 			temp_address_len = sizeof (temp_address);
    998 			packetlen = PacketTransport->Read ( temp_receive_buffer, temp_receive_buffer_len, temp_address, temp_address_len );
    999 			if ( packetlen ) {
   1000 				CurDataBuf = (char*)temp_receive_buffer;
   1001 				address = *((IPXAddressClass*) temp_address);
   1002 
   1003 				packet = (CommHeaderType *)CurDataBuf;
   1004 				if (packet->MagicNumber == GlobalChannel->Magic_Num()) {
   1005 
   1006 					/*
   1007 					** Put the packet in the Global Queue
   1008 					*/
   1009 					if (!GlobalChannel->Receive_Packet (packet, packetlen, &address))
   1010 						ReceiveOverflows++;
   1011 				} else {
   1012 					if (packet->MagicNumber == ProductID) {
   1013 
   1014 						/*
   1015 						** Find the Private Queue that this packet is for
   1016 						*/
   1017 						bool found_address = false;
   1018 						for (i = 0; i < NumConnections; i++) {
   1019 							if (Connection[i]->Address == address) {
   1020 								found_address = true;
   1021 								if (!Connection[i]->Receive_Packet (packet, packetlen))
   1022 									ReceiveOverflows++;
   1023 								break;
   1024 							}
   1025 						}
   1026 						if( Session.Type == GAME_INTERNET )
   1027 						{
   1028 							/*
   1029 							** This packet came from an unknown source. If it looks like one of our players
   1030 							** packets then it might be from a player whos IP has changed.
   1031 							*/
   1032 							if (!found_address) {
   1033 								if (packet->Code == ConnectionClass::PACKET_DATA_NOACK){
   1034 									/*
   1035 									** Magic number and packet code are valid. It's probably a C&C packet.
   1036 									*/
   1037 									EventClass *event = (EventClass*) (((char*) packet) + sizeof (CommHeaderType));
   1038 
   1039 									/*
   1040 									** If this is a framesync packet then grab the address and match it to an existing player.
   1041 									*/
   1042 									if (event->Type == EventClass::FRAMESYNC) {
   1043 										int id = event->ID;
   1044 
   1045 										assert (id != PlayerPtr->ID);
   1046 										for ( int i=1 ; i<Session.Players.Count() ; i++) {
   1047 											if (Session.Players[i]->Player.ID == id) {
   1048 
   1049 												int iConnectionIndex = Connection_Index(id);
   1050 												if( iConnectionIndex != CONNECTION_NONE ) //	(else Create_Connections() has not yet been called)
   1051 												{
   1052 													/*
   1053 													** Found a likely candidate. Update his address. It should be OK to drop this
   1054 													** packet since it's a framesync packet and will will pick up the next one.
   1055 													*/
   1056 													Session.Players[i]->Address = address;
   1057 													Connection[iConnectionIndex]->Address = address;
   1058 												}
   1059 												break;
   1060 											}
   1061 										}
   1062 									}
   1063 								}
   1064 							}
   1065 						}
   1066 					}
   1067 				}
   1068 			}
   1069 
   1070 		} while (packetlen);
   1071 
   1072 	}
   1073 
   1074 
   1075 
   1076 
   1077 #else	//WINSOCK_IPX
   1078 
   1079 #ifdef WIN32
   1080 
   1081 	unsigned char temp_receive_buffer[1024];
   1082 	int	recv_length;
   1083 
   1084 	if (Winsock.Get_Connected() || Special.IsFromWChat) {
   1085 
   1086 		if (!Winsock.Get_Connected()) return (0);
   1087 
   1088 		/*
   1089 		** This is an internet connection so get the packets from winsock
   1090 		*/
   1091 		while ((recv_length = Winsock.Read(temp_receive_buffer, 1024))!=0) {
   1092 
   1093 			CurHeaderBuf = NULL;
   1094 			CurDataBuf = (char*)&temp_receive_buffer[0];
   1095 
   1096 			/*.....................................................................
   1097 			Compute the length of the packet (byte-swap the length in the IPX hdr)
   1098 			.....................................................................*/
   1099 			packetlen = recv_length;
   1100 
   1101 			/*.....................................................................
   1102 			Extract the sender's address from the IPX header
   1103 			.....................................................................*/
   1104 			address.Set_Address (CurHeaderBuf);
   1105 
   1106 			/*.....................................................................
   1107 			Examine the Magic Number of the received packet to determine if this
   1108 			packet goes into the Global Queue, or into one of the Private Queues
   1109 			.....................................................................*/
   1110 			packet = (CommHeaderType *)CurDataBuf;
   1111 			if (packet->MagicNumber == GlobalChannel->Magic_Num()) {
   1112 				/*..................................................................
   1113 				Put the packet in the Global Queue
   1114 				..................................................................*/
   1115 				if (!GlobalChannel->Receive_Packet (packet, packetlen, &address))
   1116 					ReceiveOverflows++;
   1117 			} else {
   1118 				if (packet->MagicNumber == ProductID) {
   1119 					/*..................................................................
   1120 					Find the Private Queue that this packet is for
   1121 					..................................................................*/
   1122 					for (i = 0; i < NumConnections; i++) {
   1123 						if (Connection[i]->Address == address) {
   1124 							if (!Connection[i]->Receive_Packet (packet, packetlen))
   1125 								ReceiveOverflows++;
   1126 							break;
   1127 						}
   1128 					}
   1129 				}
   1130 			}
   1131 
   1132 		}
   1133 	} else {
   1134 #if(0)//PG
   1135 		while (IPX_Get_Outstanding_Buffer95(&temp_receive_buffer[0])) {
   1136 
   1137 			CurHeaderBuf = (IPXHEADER*)&temp_receive_buffer[0];
   1138 			CurDataBuf = (char*)&temp_receive_buffer[sizeof(IPXHeaderType)];
   1139 
   1140 			/*.....................................................................
   1141 			Compute the length of the packet (byte-swap the length in the IPX hdr)
   1142 			.....................................................................*/
   1143 			packetlen = ((CurHeaderBuf->Length & 0xff) << 8) |
   1144 				(CurHeaderBuf->Length >> 8);
   1145 			packetlen -= sizeof(IPXHeaderType);
   1146 
   1147 			/*.....................................................................
   1148 			Extract the sender's address from the IPX header
   1149 			.....................................................................*/
   1150 			address.Set_Address (CurHeaderBuf);
   1151 
   1152 			/*.....................................................................
   1153 			Examine the Magic Number of the received packet to determine if this
   1154 			packet goes into the Global Queue, or into one of the Private Queues
   1155 			.....................................................................*/
   1156 			packet = (CommHeaderType *)CurDataBuf;
   1157 			if (packet->MagicNumber == GlobalChannel->Magic_Num()) {
   1158 				/*..................................................................
   1159 				Put the packet in the Global Queue
   1160 				..................................................................*/
   1161 				if (!GlobalChannel->Receive_Packet (packet, packetlen, &address))
   1162 					ReceiveOverflows++;
   1163 			} else {
   1164 				if (packet->MagicNumber == ProductID) {
   1165 					/*..................................................................
   1166 					Find the Private Queue that this packet is for
   1167 					..................................................................*/
   1168 					for (i = 0; i < NumConnections; i++) {
   1169 						if (Connection[i]->Address == address) {
   1170 							if (!Connection[i]->Receive_Packet (packet, packetlen))
   1171 								ReceiveOverflows++;
   1172 							break;
   1173 						}
   1174 					}
   1175 				}
   1176 			}
   1177 		}
   1178 #endif
   1179 	}
   1180 
   1181 
   1182 #else	//WIN32
   1183 
   1184 
   1185 	//------------------------------------------------------------------------
   1186 	//	Error if IPX not installed or not Listening
   1187 	//------------------------------------------------------------------------
   1188 	if (!IPXStatus || !Listening) {
   1189 		return(0);
   1190 	}
   1191 
   1192 	//------------------------------------------------------------------------
   1193 	//	Loop until there are no more packets to process.
   1194 	//------------------------------------------------------------------------
   1195 	while (1) {
   1196 
   1197 		//.....................................................................
   1198 		//	Check the BufferFlags for the "current" buffer; if it's empty,
   1199 		//	break; out of the loop.
   1200 		//.....................................................................
   1201 		if (BufferFlags[CurIndex]==0) {
   1202 			break;
   1203 		}
   1204 
   1205 		//.....................................................................
   1206 		//	Compute the length of the packet (byte-swap the length in the IPX hdr)
   1207 		//.....................................................................
   1208 		packetlen = ((CurHeaderBuf->Length & 0xff) << 8) |
   1209 			(CurHeaderBuf->Length >> 8);
   1210 		packetlen -= sizeof(IPXHeaderType);
   1211 
   1212 		//.....................................................................
   1213 		//	Extract the sender's address from the IPX header
   1214 		//.....................................................................
   1215 		address.Set_Address (CurHeaderBuf);
   1216 
   1217 		//.....................................................................
   1218 		//	Examine the Magic Number of the received packet to determine if this
   1219 		//	packet goes into the Global Queue, or into one of the Private Queues
   1220 		//.....................................................................
   1221 		packet = (CommHeaderType *)CurDataBuf;
   1222 		if (packet->MagicNumber == GlobalChannel->Magic_Num()) {
   1223 
   1224 			//..................................................................
   1225 			//	Put the packet in the Global Queue
   1226 			//..................................................................
   1227 			if (!GlobalChannel->Receive_Packet (packet, packetlen, &address)) {
   1228 				ReceiveOverflows++;
   1229 			}
   1230 		}
   1231 
   1232 		//.....................................................................
   1233 		//	Find the Private Queue that this packet is for
   1234 		//.....................................................................
   1235 		else if (packet->MagicNumber == ProductID) {
   1236 			for (i = 0; i < NumConnections; i++) {
   1237 				if (Connection[i]->Address == address) {
   1238 					if (!Connection[i]->Receive_Packet (packet, packetlen)) {
   1239 						ReceiveOverflows++;
   1240 					}
   1241 					break;
   1242 				}
   1243 			}
   1244 		}
   1245 
   1246 		//.....................................................................
   1247 		//	Set the current BufferFlags to 0 (since we've cleaned out this buffer)
   1248 		//.....................................................................
   1249 		BufferFlags[CurIndex] = 0;
   1250 
   1251 		//.....................................................................
   1252 		//	Go to the next packet buffer
   1253 		//.....................................................................
   1254 		CurIndex++;
   1255 		CurHeaderBuf = (IPXHeaderType *)(((char *)CurHeaderBuf) + FullPacketLen);
   1256 		CurDataBuf = ((char *)CurDataBuf) + FullPacketLen;
   1257 		if (CurIndex >= NumBufs) {
   1258 			CurHeaderBuf = FirstHeaderBuf;
   1259 			CurDataBuf = FirstDataBuf;
   1260 			CurIndex = 0;
   1261 		}
   1262 	}
   1263 
   1264 #endif	//WIN32
   1265 #endif	//WINSOCK_IPX
   1266 
   1267 	//------------------------------------------------------------------------
   1268 	//	Service all connections.  If a connection reports that it's gone "bad",
   1269 	//	report an error to the caller.  If it's the Global Channel, un-queue the
   1270 	//	send entry that's holding things up.  This will keep the Global Channel
   1271 	//	from being clogged by one un-ACK'd outgoing packet.
   1272 	//------------------------------------------------------------------------
   1273 	if (GlobalChannel) {
   1274 		if (!GlobalChannel->Service()) {
   1275 			GlobalChannel->Queue->UnQueue_Send (NULL, NULL, 0);
   1276 			rc = 0;
   1277 		}
   1278 	}
   1279 	for (i = 0; i < NumConnections; i++) {
   1280 		if (!Connection[i]->Service()) {
   1281 			rc = 0;
   1282 			BadConnection = Connection[i]->ID;
   1283 		}
   1284 	}
   1285 
   1286 	if (rc) {
   1287 		BadConnection = CONNECTION_NONE;
   1288 	}
   1289 
   1290 	return(rc);
   1291 
   1292 }	/* end of Service */
   1293 
   1294 /***************************************************************************
   1295  * IPXManagerClass::Get_Bad_Connection -- returns bad connection ID        *
   1296  *                                                                         *
   1297  * INPUT:                                                                  *
   1298  *		none.																						*
   1299  *                                                                         *
   1300  * OUTPUT:                                                                 *
   1301  *		ID of bad connection; CONNECTION_NONE if none.								*
   1302  *                                                                         *
   1303  * WARNINGS:                                                               *
   1304  *		none.																						*
   1305  *                                                                         *
   1306  * HISTORY:                                                                *
   1307  *   05/04/1995 BRR : Created.                                             *
   1308  *=========================================================================*/
   1309 int IPXManagerClass::Get_Bad_Connection(void)
   1310 {
   1311 	return(BadConnection);
   1312 
   1313 }	/* end of Get_Bad_Connection */
   1314 
   1315 
   1316 /***************************************************************************
   1317  * IPXManagerClass::Global_Num_Send	-- reports # entries in send queue		*
   1318  *                                                                         *
   1319  * INPUT:                                                                  *
   1320  *		none.																						*
   1321  *                                                                         *
   1322  * OUTPUT:                                                                 *
   1323  *		# entries in the Global Send Queue												*
   1324  *                                                                         *
   1325  * WARNINGS:                                                               *
   1326  *		none.																						*
   1327  *                                                                         *
   1328  * HISTORY:                                                                *
   1329  *   01/25/1995 BR : Created.                                              *
   1330  *=========================================================================*/
   1331 int IPXManagerClass::Global_Num_Send(void)
   1332 {
   1333 	//------------------------------------------------------------------------
   1334 	//	Error if IPX not installed or not Listening
   1335 	//------------------------------------------------------------------------
   1336 	if (!IPXStatus || !Listening) {
   1337 		return(0);
   1338 	}
   1339 
   1340 	return(GlobalChannel->Queue->Num_Send());
   1341 
   1342 }	/* end of Global_Num_Send */
   1343 
   1344 
   1345 /***************************************************************************
   1346  * IPXManagerClass::Global_Num_Receive -- reports # entries in recv queue	*
   1347  *                                                                         *
   1348  * INPUT:                                                                  *
   1349  *		none.																						*
   1350  *                                                                         *
   1351  * OUTPUT:                                                                 *
   1352  *		# entries in the Global Receive Queue											*
   1353  *                                                                         *
   1354  * WARNINGS:                                                               *
   1355  *		none.																						*
   1356  *                                                                         *
   1357  * HISTORY:                                                                *
   1358  *   01/25/1995 BR : Created.                                              *
   1359  *=========================================================================*/
   1360 int IPXManagerClass::Global_Num_Receive(void)
   1361 {
   1362 	//------------------------------------------------------------------------
   1363 	//	Error if IPX not installed or not Listening
   1364 	//------------------------------------------------------------------------
   1365 	if (!IPXStatus || !Listening) {
   1366 		return(0);
   1367 	}
   1368 
   1369 	return(GlobalChannel->Queue->Num_Receive());
   1370 
   1371 }	/* end of Global_Num_Receive */
   1372 
   1373 
   1374 /***************************************************************************
   1375  * IPXManagerClass::Private_Num_Send -- reports # entries in send queue		*
   1376  *                                                                         *
   1377  * INPUT:                                                                  *
   1378  *		# entries in the Private Send Queue												*
   1379  *                                                                         *
   1380  * OUTPUT:                                                                 *
   1381  *		1 = OK, 0 = error																		*
   1382  *                                                                         *
   1383  * WARNINGS:                                                               *
   1384  *		none.																						*
   1385  *                                                                         *
   1386  * HISTORY:                                                                *
   1387  *   01/25/1995 BR : Created.                                              *
   1388  *=========================================================================*/
   1389 int IPXManagerClass::Private_Num_Send(int id)
   1390 {
   1391 	int i;
   1392 	int maxnum;
   1393 
   1394 	//------------------------------------------------------------------------
   1395 	//	Error if IPX not installed or not Listening
   1396 	//------------------------------------------------------------------------
   1397 	if (!IPXStatus || !Listening || (NumConnections==0)) {
   1398 		return(0);
   1399 	}
   1400 
   1401 	//------------------------------------------------------------------------
   1402 	//	If connection ID specified, return that connection's # of packets
   1403 	//------------------------------------------------------------------------
   1404 	if (id != CONNECTION_NONE) {
   1405 		i = Connection_Index(id);
   1406 		if (i != CONNECTION_NONE) {
   1407 			return(Connection[i]->Queue->Num_Send());
   1408 		}
   1409 		else {
   1410 			return(0);
   1411 		}
   1412 
   1413 	}
   1414 
   1415 	//------------------------------------------------------------------------
   1416 	//	Otherwise, return the max # of all connections
   1417 	//------------------------------------------------------------------------
   1418 	else {
   1419 		maxnum = 0;
   1420 		for (i = 0; i < NumConnections; i++) {
   1421 			if (Connection[i]->Queue->Num_Send() > maxnum) {
   1422 				maxnum = Connection[i]->Queue->Num_Send();
   1423 			}
   1424 		}
   1425 		return(maxnum);
   1426 	}
   1427 
   1428 }	/* end of Private_Num_Send */
   1429 
   1430 
   1431 /***************************************************************************
   1432  * IPXManagerClass::Private_Num_Receive -- reports # entries in recv queue	*
   1433  *                                                                         *
   1434  * INPUT:                                                                  *
   1435  *		id		ID of connection to query													*
   1436  *                                                                         *
   1437  * OUTPUT:                                                                 *
   1438  *		# entries in the Private Receive Queue											*
   1439  *                                                                         *
   1440  * WARNINGS:                                                               *
   1441  *		none.																						*
   1442  *                                                                         *
   1443  * HISTORY:                                                                *
   1444  *   01/25/1995 BR : Created.                                              *
   1445  *=========================================================================*/
   1446 int IPXManagerClass::Private_Num_Receive(int id)
   1447 {
   1448 	int i;
   1449 	int maxnum;
   1450 
   1451 	//------------------------------------------------------------------------
   1452 	//	Error if IPX not installed or not Listening
   1453 	//------------------------------------------------------------------------
   1454 	if (!IPXStatus || !Listening || (NumConnections==0))
   1455 		return(0);
   1456 
   1457 	//------------------------------------------------------------------------
   1458 	//	If connection ID specified, return that connection's # of packets
   1459 	//------------------------------------------------------------------------
   1460 	if (id != CONNECTION_NONE) {
   1461 		i = Connection_Index(id);
   1462 		if (i != CONNECTION_NONE) {
   1463 			return(Connection[i]->Queue->Num_Receive());
   1464 		}
   1465 		else {
   1466 			return(0);
   1467 		}
   1468 
   1469 	}
   1470 
   1471 	//------------------------------------------------------------------------
   1472 	//	Otherwise, return the max # of all connections
   1473 	//------------------------------------------------------------------------
   1474 	else {
   1475 		maxnum = 0;
   1476 		for (i = 0; i < NumConnections; i++) {
   1477 			if (Connection[i]->Queue->Num_Receive() > maxnum) {
   1478 				maxnum = Connection[i]->Queue->Num_Receive();
   1479 			}
   1480 		}
   1481 		return(maxnum);
   1482 	}
   1483 
   1484 }	/* end of Private_Num_Receive */
   1485 
   1486 
   1487 /***************************************************************************
   1488  * IPXManagerClass::Set_Socket -- sets socket ID for all connections			*
   1489  *                                                                         *
   1490  * INPUT:                                                                  *
   1491  *		socket	new socket ID to use														*
   1492  *                                                                         *
   1493  * OUTPUT:                                                                 *
   1494  *		none.																						*
   1495  *                                                                         *
   1496  * WARNINGS:                                                               *
   1497  *		Do not call this function after communications have started; you		*
   1498  *		must call it before calling Init().												*
   1499  *		The socket number is byte-swapped, since IPX requires socket ID's		*
   1500  *		to be stored high/low.																*
   1501  *                                                                         *
   1502  * HISTORY:                                                                *
   1503  *   01/25/1995 BR : Created.                                              *
   1504  *=========================================================================*/
   1505 void IPXManagerClass::Set_Socket(unsigned short socket)
   1506 {
   1507 	Socket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) |
   1508 		(((unsigned long)socket & 0xff00) >> 8));
   1509 
   1510 }	/* end of Set_Socket */
   1511 
   1512 
   1513 /***************************************************************************
   1514  * IPXManagerClass::Response_Time -- Returns largest Avg Response Time     *
   1515  *                                                                         *
   1516  * INPUT:                                                                  *
   1517  *		none.																						*
   1518  *                                                                         *
   1519  * OUTPUT:                                                                 *
   1520  *		largest avg response time															*
   1521  *                                                                         *
   1522  * WARNINGS:                                                               *
   1523  *		none.																						*
   1524  *                                                                         *
   1525  * HISTORY:                                                                *
   1526  *   05/04/1995 BRR : Created.                                             *
   1527  *=========================================================================*/
   1528 unsigned long IPXManagerClass::Response_Time(void)
   1529 {
   1530 	unsigned long resp;
   1531 	unsigned long maxresp = 0;
   1532 	int i;
   1533 
   1534 	for (i = 0; i < NumConnections; i++) {
   1535 		resp = Connection[i]->Queue->Avg_Response_Time();
   1536 		if (resp > maxresp) {
   1537 			maxresp = resp;
   1538 		}
   1539 	}
   1540 
   1541 	return(maxresp);
   1542 
   1543 }	/* end of Response_Time */
   1544 
   1545 
   1546 /***************************************************************************
   1547  * IPXManagerClass::Global_Response_Time -- Returns Avg Response Time      *
   1548  *                                                                         *
   1549  * INPUT:                                                                  *
   1550  *		none.																						*
   1551  *                                                                         *
   1552  * OUTPUT:                                                                 *
   1553  *		avg global channel response time													*
   1554  *                                                                         *
   1555  * WARNINGS:                                                               *
   1556  *		none.																						*
   1557  *                                                                         *
   1558  * HISTORY:                                                                *
   1559  *   05/04/1995 BRR : Created.                                             *
   1560  *=========================================================================*/
   1561 unsigned long IPXManagerClass::Global_Response_Time(void)
   1562 {
   1563 	if (GlobalChannel) {
   1564 		return (GlobalChannel->Queue->Avg_Response_Time());
   1565 	}
   1566 	else {
   1567 		return (0);
   1568 	}
   1569 
   1570 }	/* end of Global_Response_Time */
   1571 
   1572 
   1573 /***************************************************************************
   1574  * IPXManagerClass::Reset_Response_Time -- Reset response time					*
   1575  *                                                                         *
   1576  * INPUT:                                                                  *
   1577  *		none.																						*
   1578  *                                                                         *
   1579  * OUTPUT:                                                                 *
   1580  *		none.																						*
   1581  *                                                                         *
   1582  * WARNINGS:                                                               *
   1583  *		none.																						*
   1584  *                                                                         *
   1585  * HISTORY:                                                                *
   1586  *   05/04/1995 BRR : Created.                                             *
   1587  *=========================================================================*/
   1588 void IPXManagerClass::Reset_Response_Time(void)
   1589 {
   1590 	int i;
   1591 
   1592 	for (i = 0; i < NumConnections; i++) {
   1593 		Connection[i]->Queue->Reset_Response_Time();
   1594 	}
   1595 
   1596 	if (GlobalChannel)
   1597 		GlobalChannel->Queue->Reset_Response_Time();
   1598 
   1599 }	/* end of Reset_Response_Time */
   1600 
   1601 
   1602 /***************************************************************************
   1603  * IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf             *
   1604  *                                                                         *
   1605  * INPUT:                                                                  *
   1606  *		none.																						*
   1607  *                                                                         *
   1608  * OUTPUT:                                                                 *
   1609  *		buf ptr																					*
   1610  *                                                                         *
   1611  * WARNINGS:                                                               *
   1612  *		none.																						*
   1613  *                                                                         *
   1614  * HISTORY:                                                                *
   1615  *   05/04/1995 BRR : Created.                                             *
   1616  *=========================================================================*/
   1617 void * IPXManagerClass::Oldest_Send(void)
   1618 {
   1619 	int i,j;
   1620 	unsigned long time;
   1621 	unsigned long mintime = 0xffffffff;
   1622 	SendQueueType *send_entry;				// ptr to send entry header
   1623 	CommHeaderType *packet;
   1624 	void *buf = NULL;
   1625 
   1626 	for (i = 0; i < NumConnections; i++) {
   1627 
   1628 		send_entry = NULL;
   1629 
   1630 		for (j = 0; j < Connection[i]->Queue->Num_Send(); j++) {
   1631 			send_entry = Connection[i]->Queue->Get_Send(j);
   1632 			if (send_entry) {
   1633 				packet = (CommHeaderType *)send_entry->Buffer;
   1634 				if (packet->Code == ConnectionClass::PACKET_DATA_ACK &&
   1635 					send_entry->IsACK == 0) {
   1636 					break;
   1637 				}
   1638 				else {
   1639 					send_entry = NULL;
   1640 				}
   1641 			}
   1642 		}
   1643 
   1644 		if (send_entry!=NULL) {
   1645 
   1646 			time = send_entry->FirstTime;
   1647 
   1648 			if (time < mintime) {
   1649 				mintime = time;
   1650 				buf = send_entry->Buffer;
   1651 			}
   1652 		}
   1653 	}
   1654 
   1655 	return(buf);
   1656 
   1657 }	/* end of Oldest_Send */
   1658 
   1659 
   1660 /***************************************************************************
   1661  * IPXManagerClass::Set_Bridge -- prepares to cross a bridge               *
   1662  *                                                                         *
   1663  * This routine is designed to prevent the connection from having to			*
   1664  * call Get_Local_Target, except the minimum number of times, since that	*
   1665  * routine is buggy & goes away for long periods sometimes.						*
   1666  *                                                                         *
   1667  * INPUT:                                                                  *
   1668  *		bridge		network number of the destination bridge						*
   1669  *                                                                         *
   1670  * OUTPUT:                                                                 *
   1671  *		none																						*
   1672  *                                                                         *
   1673  * WARNINGS:                                                               *
   1674  *		none																						*
   1675  *                                                                         *
   1676  * HISTORY:                                                                *
   1677  *   07/06/1995 BRR : Created.                                             *
   1678  *=========================================================================*/
   1679 void IPXManagerClass::Set_Bridge(NetNumType bridge)
   1680 {
   1681 	if (GlobalChannel) {
   1682 		GlobalChannel->Set_Bridge(bridge);
   1683 	}
   1684 
   1685 }	/* end of Set_Bridge */
   1686 
   1687 
   1688 /***************************************************************************
   1689  * IPXManagerClass::Configure_Debug -- sets up special debug values        *
   1690  *                                                                         *
   1691  * Mono_Debug_Print2() can look into a packet to pull out a particular		*
   1692  * ID, and can print both that ID and a string corresponding to				*
   1693  * that ID.  This routine configures these values so it can find				*
   1694  * and decode the ID.  This ID is used in addition to the normal				*
   1695  * CommHeaderType values.																	*
   1696  *                                                                         *
   1697  * INPUT:                                                                  *
   1698  *		index				connection index to configure (-1 = Global Channel)	*
   1699  *		type_offset		ID's byte offset into packet									*
   1700  *		type_size		size of ID, in bytes; 0 if none								*
   1701  *		names				ptr to array of names; use ID as an index into this	*
   1702  *		namestart		numerical value of 1st name in the array					*
   1703  *		namecount		# in the names array; 0 if none.								*
   1704  *                                                                         *
   1705  * OUTPUT:                                                                 *
   1706  *		none.																						*
   1707  *                                                                         *
   1708  * WARNINGS:                                                               *
   1709  *		Names shouldn't be longer than 12 characters.								*
   1710  *                                                                         *
   1711  * HISTORY:                                                                *
   1712  *   05/31/1995 BRR : Created.                                             *
   1713  *=========================================================================*/
   1714 void IPXManagerClass::Configure_Debug(int index, int type_offset,
   1715 	int type_size, char **names, int namestart, int namecount)
   1716 {
   1717 	if (index == -1) {
   1718 		GlobalChannel->Queue->Configure_Debug (type_offset, type_size, names,
   1719 			namestart, namecount);
   1720 	}
   1721 	else if (Connection[index]) {
   1722 		Connection[index]->Queue->Configure_Debug (type_offset, type_size, names,
   1723 			namestart, namecount);
   1724 	}
   1725 
   1726 }	/* end of Configure_Debug */
   1727 
   1728 
   1729 /***************************************************************************
   1730  * IPXManagerClass::Mono_Debug_Print -- debug output routine					*
   1731  *                                                                         *
   1732  * INPUT:                                                                  *
   1733  *		index			index of connection to display (-1 = Global Channel)		*
   1734  *		refresh		1 = complete screen refresh										*
   1735  *                                                                         *
   1736  * OUTPUT:                                                                 *
   1737  *		1 = OK, 0 = error																		*
   1738  *                                                                         *
   1739  * WARNINGS:                                                               *
   1740  *		none.																						*
   1741  *                                                                         *
   1742  * HISTORY:                                                                *
   1743  *   01/25/1995 BR : Created.                                              *
   1744  *=========================================================================*/
   1745 void IPXManagerClass::Mono_Debug_Print(int index, int refresh)
   1746 {
   1747 #ifdef WWLIB32_H
   1748 	char txt[80];
   1749 	int i;
   1750 
   1751 	if (index == -1)
   1752 		GlobalChannel->Queue->Mono_Debug_Print (refresh);
   1753 
   1754 	else if (Connection[index])
   1755 		Connection[index]->Queue->Mono_Debug_Print (refresh);
   1756 
   1757 	if (refresh) {
   1758 		Mono_Set_Cursor (20,1);
   1759 		Mono_Printf ("IPX Queue:");
   1760 
   1761 		Mono_Set_Cursor (9,2);
   1762 		Mono_Printf ("Average Response Time:");
   1763 
   1764 		Mono_Set_Cursor (43,1);
   1765 		Mono_Printf ("Send Overflows:");
   1766 
   1767 		Mono_Set_Cursor (40,2);
   1768 		Mono_Printf ("Receive Overflows:");
   1769 
   1770 	}
   1771 
   1772 	Mono_Set_Cursor (32,1);
   1773 	Mono_Printf ("%d",index);
   1774 
   1775 	Mono_Set_Cursor (32,2);
   1776 	if (index == -1) {
   1777 		Mono_Printf ("%d  ", GlobalChannel->Queue->Avg_Response_Time());
   1778 	}
   1779 	else {
   1780 		Mono_Printf ("%d  ", Connection[index]->Queue->Avg_Response_Time());
   1781 	}
   1782 
   1783 	Mono_Set_Cursor (59,1);
   1784 	Mono_Printf ("%d  ", SendOverflows);
   1785 
   1786 	Mono_Set_Cursor (59,2);
   1787 	Mono_Printf ("%d  ", ReceiveOverflows);
   1788 
   1789 	for (i = 0; i < NumBufs; i++) {
   1790 		if (BufferFlags[i]) {
   1791 			txt[i] = 'X';
   1792 		}
   1793 		else {
   1794 			txt[i] = '_';
   1795 		}
   1796 	}
   1797 	txt[i] = 0;
   1798 	Mono_Set_Cursor ((80-NumBufs)/2,3);
   1799 	Mono_Printf ("%s",txt);
   1800 
   1801 #else
   1802 	index = index;
   1803 	refresh = refresh;
   1804 #endif
   1805 
   1806 }	/* end of Mono_Debug_Print */
   1807 
   1808 
   1809 /***************************************************************************
   1810  * IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory			*
   1811  *                                                                         *
   1812  * INPUT:                                                                  *
   1813  *		none.																						*
   1814  *                                                                         *
   1815  * OUTPUT:                                                                 *
   1816  *		1 = OK, 0 = error																		*
   1817  *                                                                         *
   1818  * WARNINGS:                                                               *
   1819  *		none.																						*
   1820  *                                                                         *
   1821  * HISTORY:                                                                *
   1822  *   12/20/1994 BR : Created.                                              *
   1823  *=========================================================================*/
   1824 int IPXManagerClass::Alloc_RealMode_Mem(void)
   1825 {
   1826 
   1827 #ifdef WIN32
   1828 	return (1);
   1829 #else
   1830 
   1831 	union REGS regs;
   1832 	struct SREGS sregs;
   1833 	int size;									// required size of allocation
   1834 	unsigned char *realmode;				// start addresses of real-mode data
   1835 	int realmodelen;							// length of real-mode data
   1836 	unsigned long func_val;
   1837 	char *p;										// for parsing buffer
   1838 	int i;
   1839 
   1840 	//------------------------------------------------------------------------
   1841 	//	Compute # of buffers we need to allocate, & the max size of each one
   1842 	//------------------------------------------------------------------------
   1843 	NumBufs = Glb_NumPackets + (Pvt_NumPackets * CONNECT_MAX);
   1844 
   1845 	PacketLen = Glb_MaxPacketLen + sizeof (GlobalHeaderType);
   1846 	if (Pvt_MaxPacketLen + sizeof (CommHeaderType) > PacketLen)
   1847 		PacketLen = Pvt_MaxPacketLen + sizeof (CommHeaderType);
   1848 
   1849 	FullPacketLen = PacketLen + sizeof(IPXHeaderType);
   1850 
   1851 	//------------------------------------------------------------------------
   1852 	//	Compute the size of everything we'll ever need, allocate it in one big
   1853 	//	chunk.  The memory is used as follows:
   1854 	//	- Real-mode assembly IPX callback routine, plus its data,
   1855 	//	  (which includes the ListenECB)
   1856 	//	- Array of IPX Packet buffers (IPXHeader plus data buffer)
   1857 	//	- SendECB: ECB for sending
   1858 	//	- SendHeader: IPX Header for sending
   1859 	//	- SendBuf: Packet buffer for sending
   1860 	//	- BufferFlags: 1 byte for each incoming packet buffer; 1=in use, 0=free
   1861 	//------------------------------------------------------------------------
   1862 	realmode = (unsigned char *)Get_RM_IPX_Address();
   1863 	realmodelen = Get_RM_IPX_Size();
   1864 	size = realmodelen + 				// assembly routine & its data
   1865 		(FullPacketLen * NumBufs) +	// array of packet buffers
   1866 		sizeof(ECBType) +					// SendECB
   1867 		FullPacketLen +					// SendHeader & SendBuf
   1868 		NumBufs;								// BufferFlags
   1869 	if (size > 65535) {
   1870 		return(0);
   1871 	}
   1872 
   1873 	//------------------------------------------------------------------------
   1874 	//	Allocate DOS memory for the ECB, IPXHeader & packet buffers:
   1875 	//	AX = 0x100
   1876 	//	BX = # paragraphs to allocate
   1877 	//	- if Success, AX = real-mode segment, DX = selector
   1878 	//	- if Failure, carry flag is set
   1879 	//------------------------------------------------------------------------
   1880 	memset (&regs, 0 ,sizeof(regs));
   1881 	segread (&sregs);
   1882 	regs.x.eax = DPMI_ALLOC_DOS_MEM;						// DPMI function to call
   1883 	regs.x.ebx = ((size + 15) >> 4);						// # paragraphs to allocate
   1884 	int386x (DPMI_INT, &regs, &regs, &sregs);			// allocate the memory
   1885 
   1886 	//------------------------------------------------------------------------
   1887 	//	If the carry flag is set, DPMI is indicating an error.
   1888 	//------------------------------------------------------------------------
   1889 	if (regs.x.cflag) {
   1890 		return(0);
   1891 	}
   1892 
   1893 	//------------------------------------------------------------------------
   1894 	//	Save the values of the returned segment & selector
   1895 	//------------------------------------------------------------------------
   1896 	Selector = regs.w.dx;
   1897 	Segment = regs.w.ax;
   1898 	RealMemSize = size;
   1899 	RealModeData = (RealModeDataType *)(((long)Segment) << 4);
   1900 
   1901 	//------------------------------------------------------------------------
   1902 	//	Lock the memory (since we're servicing interrupts with it)
   1903 	//	AX = 0x600
   1904 	//	BX:CX = starting linear address of memory to lock
   1905 	//	SI:DI = size of region to lock (in bytes)
   1906 	//	- If Failure, carry flag is set.
   1907 	//------------------------------------------------------------------------
   1908 	memset (&regs, 0 ,sizeof(regs));
   1909 	segread (&sregs);
   1910 	regs.x.eax = DPMI_LOCK_MEM;							// DPMI function to call
   1911 	regs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16;
   1912 	regs.x.ecx = ((long)RealModeData & 0x0000ffff);
   1913 	regs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16;
   1914 	regs.x.edi = ((long)RealMemSize & 0x0000ffff);
   1915 	int386x (DPMI_INT, &regs, &regs, &sregs);			// call DPMI
   1916 
   1917 	//------------------------------------------------------------------------
   1918 	//	If the carry flag is set, DPMI is indicating an error.
   1919 	//------------------------------------------------------------------------
   1920 	if (regs.x.cflag) {
   1921 		memset (&regs, 0 ,sizeof(regs));
   1922 		segread (&sregs);
   1923 		regs.x.eax = DPMI_FREE_DOS_MEM;						// DPMI function to call
   1924 		regs.x.edx = Selector;									// ptr to free
   1925 		int386x (DPMI_INT, &regs, &regs, &sregs);			// free the memory
   1926 		return(0);
   1927 	}
   1928 
   1929 	//------------------------------------------------------------------------
   1930 	//	Copy the Real-mode code into our memory buffer
   1931 	//------------------------------------------------------------------------
   1932 	p = (char *)(((long)Segment) << 4);
   1933 	memcpy (p,realmode,realmodelen);
   1934 	p += realmodelen;
   1935 
   1936 	//------------------------------------------------------------------------
   1937 	//	Compute & save the entry point for the real-mode packet handler
   1938 	//------------------------------------------------------------------------
   1939 	func_val = (unsigned long)RealModeData;
   1940 	Handler = (((func_val & 0xffff0) << 12) |
   1941 		((func_val & 0x000f) + RealModeData->FuncOffset));
   1942 
   1943 	//------------------------------------------------------------------------
   1944 	//	Fill in buffer pointers
   1945 	//------------------------------------------------------------------------
   1946 	ListenECB = &(RealModeData->ListenECB);
   1947 
   1948 	FirstHeaderBuf = (IPXHeaderType *)p;
   1949 	FirstDataBuf = (((char *)FirstHeaderBuf) + sizeof(IPXHeaderType));
   1950 	CurIndex = 0;
   1951 	CurHeaderBuf = FirstHeaderBuf;
   1952 	CurDataBuf = FirstDataBuf;
   1953 	p += FullPacketLen * NumBufs;
   1954 
   1955 	SendECB = (ECBType *)p;
   1956 	p += sizeof (ECBType);
   1957 
   1958 	SendHeader = (IPXHeaderType *)p;
   1959 	p += sizeof (IPXHeaderType);
   1960 
   1961 	SendBuf = (char *)p;
   1962 	p += PacketLen;
   1963 
   1964 	BufferFlags = (char *)p;
   1965 
   1966 	//------------------------------------------------------------------------
   1967 	//	Fill in the real-mode routine's data (The ECB will be filled in when we
   1968 	//	command IPX to Listen).
   1969 	//------------------------------------------------------------------------
   1970 	RealModeData->NumBufs = (short)NumBufs;
   1971 	RealModeData->BufferFlags = (char *)
   1972 		((((long)BufferFlags & 0xffff0) << 12) |
   1973 		((long)BufferFlags & 0x0000f));
   1974 	RealModeData->PacketSize = (short)FullPacketLen;
   1975 	RealModeData->FirstPacketBuf = (IPXHeaderType *)
   1976 		((((long)FirstHeaderBuf & 0xffff0) << 12) |
   1977 		((long)FirstHeaderBuf & 0x0000f));
   1978 	RealModeData->CurIndex = 0;
   1979 	RealModeData->CurPacketBuf = RealModeData->FirstPacketBuf;
   1980 	RealModeData->Semaphore = 0;
   1981 	RealModeData->ReEntrantCount = 0;
   1982 
   1983 	//------------------------------------------------------------------------
   1984 	//	Init state of all buffers to empty
   1985 	//------------------------------------------------------------------------
   1986 	for (i = 0; i < NumBufs; i++) {
   1987 		BufferFlags[i] = 0;
   1988 	}
   1989 
   1990 	//------------------------------------------------------------------------
   1991 	//	Check the start & end markers in the real-mode memory area
   1992 	//------------------------------------------------------------------------
   1993 	if (RealModeData->Marker1 != 0x1111 ||
   1994 		RealModeData->Marker2 != 0x2222) {
   1995 		Free_RealMode_Mem();
   1996 		return(0);
   1997 	}
   1998 	else {
   1999 		return(1);
   2000 	}
   2001 #endif	//WIN32
   2002 }	/* end of Alloc_Realmode_Mem */
   2003 
   2004 
   2005 /***************************************************************************
   2006  * IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory				*
   2007  *                                                                         *
   2008  * INPUT:                                                                  *
   2009  *		none.																						*
   2010  *                                                                         *
   2011  * OUTPUT:                                                                 *
   2012  *		1 = OK, 0 = error																		*
   2013  *                                                                         *
   2014  * WARNINGS:                                                               *
   2015  *		none.																						*
   2016  *                                                                         *
   2017  * HISTORY:                                                                *
   2018  *   12/20/1994 BR : Created.                                              *
   2019  *=========================================================================*/
   2020 int IPXManagerClass::Free_RealMode_Mem(void)
   2021 {
   2022 
   2023 #ifdef WIN32
   2024 
   2025 	return (1);
   2026 
   2027 #else	//WIN32
   2028 
   2029 	union REGS regs;
   2030 	struct SREGS sregs;
   2031 	int rc = 1;
   2032 
   2033 	//------------------------------------------------------------------------
   2034 	//	Unlock the memory
   2035 	//------------------------------------------------------------------------
   2036 	memset (&regs, 0 ,sizeof(regs));
   2037 	segread (&sregs);
   2038 	regs.x.eax = DPMI_UNLOCK_MEM;							// DPMI function to call
   2039 	regs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16;
   2040 	regs.x.ecx = ((long)RealModeData & 0x0000ffff);
   2041 	regs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16;
   2042 	regs.x.edi = ((long)RealMemSize & 0x0000ffff);
   2043 	int386x (DPMI_INT, &regs, &regs, &sregs);			// call DPMI
   2044 
   2045 	//------------------------------------------------------------------------
   2046 	//	If the carry flag is set, DPMI is indicating an error.
   2047 	//------------------------------------------------------------------------
   2048 	if (regs.x.cflag) {
   2049 		rc = 0;
   2050 	}
   2051 
   2052 	//------------------------------------------------------------------------
   2053 	//	Free DOS memory
   2054 	//------------------------------------------------------------------------
   2055 	memset (&regs, 0 ,sizeof(regs));
   2056 	segread (&sregs);
   2057 	regs.x.eax = DPMI_FREE_DOS_MEM;						// DPMI function to call
   2058 	regs.x.edx = Selector;									// ptr to free
   2059 	int386x (DPMI_INT, &regs, &regs, &sregs);			// free the memory
   2060 
   2061 	return(rc);
   2062 #endif	//WIN32
   2063 
   2064 }	/* end of Free_Realmode_Mem */
   2065 
   2066 /*************************** end of ipxmgr.cpp *****************************/