IPXMGR.CPP 84 KB

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