IPXMGR.CPP 83 KB

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