| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /* $Header: /CounterStrike/IPX.CPP 1 3/03/97 10:24a Joe_bostic $ */
- /***************************************************************************
- ** 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 **
- ***************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : IPX.CPP *
- * *
- * Programmer : Barry Nance *
- * from Client/Server LAN Programming *
- * Westwood-ized by Bill Randolph *
- * *
- * Start Date : December 14, 1994 *
- * *
- * Last Update : December 15, 1994 [BR] *
- * *
- *-------------------------------------------------------------------------*
- * Pitfalls: *
- * - Never try to use a closed socket; always check the return code from *
- * IPX_Open_Socket(). *
- * - Always give IPX an outstanding ECB for listening, before you send. *
- * - It turns out that IPX is pretty bad about saving registers, so if *
- * you have any register variables in your program, they may get *
- * trashed. To circumvent this, all functions in this module save & *
- * restore the registers before invoking any IPX or NETX function. *
- * *
- *-------------------------------------------------------------------------*
- * Functions: *
- * IPX_SPX_Installed -- checks for installation of IPX/SPX *
- * IPX_Open_Socket -- opens an IPX socket for sending or receiving *
- * IPX_Close_Socket -- closes an open socket *
- * IPX_Get_Connection_Number -- gets local Connection Number *
- * IPX_Get_1st_Connection_Num -- gets 1st Connect Number for given user *
- * IPX_Get_Internet_Address -- gets Network Number & Node Address *
- * IPX_Get_User_ID -- gets user ID from Connection Number *
- * IPX_Listen_For_Packet -- commands IPX to listen for a packet *
- * IPX_Send_Packet -- commands IPX to send a packet *
- * IPX_Get_Local_Target -- fills in ImmediateAddress field of ECB *
- * IPX_Cancel_Event -- cancels an operation in progress *
- * Let_IPX_Breath -- gives IPX some CPU time *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include <stdio.h>
- //#include <mem.h>
- //#include <i86.h>
- #include "ipx.h"
- #ifdef WIN32
- #include "ipx95.h"
- #endif //WIN32
- // Turn off "expression is not meaningful".
- //#pragma warning 628 9
- /***************************************************************************
- * IPX_SPX_Installed -- checks for installation of IPX/SPX *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * 0 = not installed; 1 = IPX only, 2 = IPX and SPX are installed *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/14/1994 BR : Created. *
- *=========================================================================*/
- int IPX_SPX_Installed(void)
- {
- return false;
- #ifdef WIN32
- #ifdef TIBERIAN_SUN
- return(false);
- #else
- #if (0)//PG
- if ( Load_IPX_Dll () ){
- return ( IPX_Initialise() );
- }else{
- return(false);
- }
- #endif
- #endif
- #else //WIN32
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- //------------------------------------------------------------------------
- // Init all registers to 0's
- //------------------------------------------------------------------------
- memset (®s, 0, sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0, sizeof(rmi));
- //------------------------------------------------------------------------
- // Fill in registers for the DPMI call, function 0x300
- //------------------------------------------------------------------------
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = 0x002f; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //------------------------------------------------------------------------
- // Fill in registers for the real-mode interrupt handler.
- // To test for the presence of IPX, set AH to 0x7a, AL to 0, and invoke
- // interrupt 0x2f (the "multiplex" interrupt). If IPX is installed,
- // AL will be 0xff, and ES:DI will contain the IPX/SPX function address.
- //------------------------------------------------------------------------
- rmi.eax = 0x00007a00;
- //------------------------------------------------------------------------
- // call DPMI
- //------------------------------------------------------------------------
- int386x(DPMI_INT, ®s, ®s, &sregs);
- //------------------------------------------------------------------------
- // If IPX isn't there, return 0
- //------------------------------------------------------------------------
- if ( (rmi.eax & 0x00ff) != 0xff) {
- return(0);
- }
- //------------------------------------------------------------------------
- // Test for SPX by invoking the IPX_SPX function with BX = 0x10, and AL = 0.
- // If SPX is present, AL will be 0xff.
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = IPX_INT; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.ebx = 0x00000010;
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- //------------------------------------------------------------------------
- // SPX is installed; return '2'
- //------------------------------------------------------------------------
- if ( (rmi.eax & 0x00ff) == 0xff) {
- return(2);
- }
- //------------------------------------------------------------------------
- // SPX is not installed; return '1'
- //------------------------------------------------------------------------
- return(1);
- #endif //WIN32
- } /* end of IPX_SPX_Installed */
- /***************************************************************************
- * IPX_Open_Socket -- opens an IPX socket for sending or receiving *
- * *
- * INPUT: *
- * socket the socket number to open *
- * *
- * OUTPUT: *
- * 0 = OK *
- * -1 = IPX not installed *
- * 0xfe = socket table is full *
- * 0xff = socket is already open *
- * *
- * WARNINGS: *
- * The application must define its socket number carefully. Use *
- * values from 0x4000 to 0x8000 for custom socket numbers. The app *
- * must know its own socket number as well as the socket number of *
- * a destination workstation. *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Open_Socket(unsigned short socket)
- {
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- int rc;
- //------------------------------------------------------------------------
- // Open the socket:
- // DX = socket number
- // AL = 0 for short-lived socket, 0xff for long-lived socket
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = IPX_INT; // interrupt # to invoke
- sregs.es = FP_SEG (&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF (&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.ebx = IPX_OPEN_SOCKET; // function code
- rmi.edx = socket; // desired socket #
- rmi.eax = 0x00ff; // make this a long-lived socket
- //........................................................................
- // call DPMI
- //........................................................................
- int386x (DPMI_INT, ®s, ®s, &sregs);
- rc = (rmi.eax & 0xff);
- return(rc);
- } /* end of IPX_Open_Socket */
- #endif //WIN32
- /***************************************************************************
- * IPX_Close_Socket -- closes an open socket *
- * *
- * INPUT: *
- * socket socket number to close *
- * *
- * OUTPUT: *
- * 0 = ok, -1 = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Close_Socket(unsigned short socket)
- {
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- //------------------------------------------------------------------------
- // Close the socket:
- // DX = socket number
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = IPX_INT; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.ebx = IPX_CLOSE_SOCKET;
- rmi.edx = socket;
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- return(0);
- } /* end of IPX_Close_Socket */
- #endif //WIN32
- /***************************************************************************
- * IPX_Get_Connection_Number -- gets local Connection Number *
- * *
- * This Novell call will the return the user's local "Connection Number". *
- * This value will be 0 if the user isn't logged into Novell, so this *
- * routine can be used to detect if other calls (such as Get_Local_Target) *
- * will be OK. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * Connection Number, 0 = none *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Get_Connection_Number(void)
- {
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- int num;
- //------------------------------------------------------------------------
- // Call Interrupt 0x21, with AH = 0xdc. This tells Novell to put the local
- // connection number into AL.
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = 0x21; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.eax = 0x0000dc00;
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- num = rmi.eax & 0x00ff;
- return(num);
- } /* end of IPX_Get_Connection_Number */
- #endif //WIN32
- /***************************************************************************
- * IPX_Get_1st_Connection_Num -- gets 1st Connect Number for given user *
- * *
- * This gets the Connection Number for the given User ID. Since a user *
- * may be logged in more than once, this just returns the first connection *
- * found and ignores the others. *
- * *
- * INPUT: *
- * username name of the user to get the Connection Number for *
- * *
- * OUTPUT: *
- * first-found Connection Number for that user, 0 if user not logged in *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Get_1st_Connection_Num (char * username)
- {
- struct request_buffer {
- unsigned short len; // username length + 5
- unsigned char buffer_type; // ConnectionNum = 0x15
- unsigned short object_type; // set ot 0x0100
- unsigned char name_len; // length of username
- char name [48]; // copy of username
- unsigned short reserved;
- };
- struct reply_buffer {
- unsigned short len;
- unsigned char number_connections; // will be 0 - 100
- unsigned char connection_num [100]; // array of connection numbers
- unsigned short reserved[2];
- };
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- struct request_buffer * reqbuf;
- struct reply_buffer * replybuf;
- unsigned short segment; // for DOS allocation
- unsigned short selector; // for DOS allocation
- int num_conns; // # connections returned
- int conn_num; // connection number
- int rc;
- //------------------------------------------------------------------------
- // Allocate DOS memory to store the buffers passed to the interrupt
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- regs.x.eax = DPMI_ALLOC_DOS_MEM; // DPMI function to call
- regs.x.ebx = (sizeof(struct request_buffer) + // # paragraphs to allocate
- sizeof(struct reply_buffer) + 15) >> 4;
- int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory
- //------------------------------------------------------------------------
- // If the carry flag is set, DPMI is indicating an error.
- //------------------------------------------------------------------------
- if (regs.x.cflag) {
- return(0);
- }
- //------------------------------------------------------------------------
- // Get pointers to allocated memory.
- // 'reqbuf' is just the returned real-mode segment, multiplied by 16.
- // 'replybuf' is an offset from 'reqbuf'.
- //------------------------------------------------------------------------
- segment = regs.w.ax;
- selector = regs.w.dx;
- reqbuf = (struct request_buffer *)(segment << 4);
- replybuf = (struct reply_buffer *)
- (((char *)reqbuf) + sizeof (struct request_buffer));
- //------------------------------------------------------------------------
- // Init the contents of the request & reply buffers
- //------------------------------------------------------------------------
- reqbuf->len = (unsigned short)(strlen(username) + 5);
- reqbuf->buffer_type = 0x15;
- reqbuf->object_type = 0x0100;
- reqbuf->name_len = (unsigned char) strlen(username);
- strcpy(reqbuf->name, username);
- reqbuf->reserved = reqbuf->reserved; // prevent compiler warning
- replybuf->len = 101;
- replybuf->reserved[0] = replybuf->reserved[0]; // prevent compiler warning
- replybuf->reserved[0] = replybuf->reserved[1]; // prevent compiler warning
- //------------------------------------------------------------------------
- // Invoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = 0x21; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.eax = 0x0000e300;
- rmi.ds = segment;
- rmi.esi = 0;
- rmi.es = segment;
- rmi.edi = sizeof(struct request_buffer);
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- //------------------------------------------------------------------------
- // Stash the 1st connection number
- //------------------------------------------------------------------------
- rc = (rmi.eax & 0x00ff); // if AL !=0, error
- num_conns = replybuf->number_connections; // # times user is logged in
- conn_num = (int )replybuf->connection_num[0]; // 1st connection #
- //------------------------------------------------------------------------
- // Free DOS memory
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- regs.x.eax = DPMI_FREE_DOS_MEM; // DPMI function to call
- regs.x.edx = selector; // ptr to free
- int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory
- //------------------------------------------------------------------------
- // Return error if function failed, or user not logged in
- //------------------------------------------------------------------------
- if (rc != 0 || num_conns==0) {
- return(0);
- }
- else {
- return(conn_num);
- }
- } /* end of IPX_Get_1st_Connection_Num */
- #endif //WIN32
- /***************************************************************************
- * IPX_Get_Internet_Address -- gets Network Number & Node Address *
- * *
- * Once you've obtained a Connection Number from IPX_Get_Connection_Number *
- * or IPX_Get_1st_Connection_Num, use this function to translate it into *
- * a Network Number and Node Address; then, place those numbers in the *
- * IPX header for outgoing packets. *
- * *
- * INPUT: *
- * connection_number Connection Number to translate *
- * network_number ptr: will hold Network Number *
- * physical_node ptr: will hold Node Address *
- * *
- * OUTPUT: *
- * 0 = OK, -1 = error *
- * *
- * WARNINGS: *
- * If connection_number is 0 and NETX isn't running, this routine *
- * will just put garbage into the network_number and physical_node. *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Get_Internet_Address(int connection_number,
- unsigned char * network_number, unsigned char * physical_node)
- {
- struct request_buffer {
- unsigned short len;
- unsigned char buffer_type; // Internet = 0x13
- unsigned char connection_number; // Conn. Number to translate
- };
- struct reply_buffer {
- unsigned short len;
- unsigned char network_number [4]; // filled in by IPX
- unsigned char physical_node [6]; // filled in by IPX
- unsigned short server_socket; // filled in by IPX, but don't use!
- };
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- struct request_buffer * reqbuf;
- struct reply_buffer * replybuf;
- unsigned short segment; // for DOS allocation
- unsigned short selector; // for DOS allocation
- //------------------------------------------------------------------------
- // Error if invalid connection is given
- //------------------------------------------------------------------------
- if (connection_number==0) {
- return(-1);
- }
- //------------------------------------------------------------------------
- // Allocate DOS memory to store the buffers passed to the interrupt
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- regs.x.eax = DPMI_ALLOC_DOS_MEM; // DPMI function to call
- regs.x.ebx = (sizeof(struct request_buffer) + // # paragraphs to allocate
- sizeof(struct reply_buffer) + 15) >> 4;
- int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory
- //------------------------------------------------------------------------
- // If the carry flag is set, DPMI is indicating an error.
- //------------------------------------------------------------------------
- if (regs.x.cflag) {
- return(-1);
- }
- //------------------------------------------------------------------------
- // Get pointers to allocated memory.
- // 'reqbuf' is just the returned real-mode segment, multiplied by 16.
- // 'replybuf' is an offset from 'reqbuf'.
- //------------------------------------------------------------------------
- segment = regs.w.ax;
- selector = regs.w.dx;
- reqbuf = (struct request_buffer *)(segment << 4);
- replybuf = (struct reply_buffer *)
- (((char *)reqbuf) + sizeof (struct request_buffer));
- //------------------------------------------------------------------------
- // Init the contents of the request & reply buffers
- //------------------------------------------------------------------------
- reqbuf->len = 2;
- reqbuf->buffer_type = 0x13;
- reqbuf->connection_number = (unsigned char)connection_number;
- replybuf->len = 12;
- replybuf->network_number[0] = replybuf->network_number[0]; // suppress warning
- replybuf->physical_node[0] = replybuf->physical_node[0]; // suppress warning
- replybuf->server_socket = replybuf->server_socket; // suppress warning
- //------------------------------------------------------------------------
- // Invoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = 0x21; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.eax = 0x0000e300;
- rmi.ds = segment;
- rmi.esi = 0;
- rmi.es = segment;
- rmi.edi = sizeof(struct request_buffer);
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- memcpy(network_number, replybuf->network_number, 4);
- memcpy(physical_node, replybuf->physical_node, 6);
- //------------------------------------------------------------------------
- // Free DOS memory
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- regs.x.eax = DPMI_FREE_DOS_MEM; // DPMI function to call
- regs.x.edx = selector; // ptr to free
- int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory
- return(0);
- } /* end of IPX_Get_Internet_Address */
- #endif //WIN32
- /***************************************************************************
- * IPX_Get_User_ID -- gets user ID from Connection Number *
- * *
- * INPUT: *
- * connection_number Connection Number to get User ID for *
- * user_id ptr to buffer to put User ID into; *
- * size must be >= 48 chars *
- * *
- * OUTPUT: *
- * 0 = OK, -1 = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Get_User_ID(int connection_number, char * user_id)
- {
- struct request_buffer {
- unsigned short len;
- unsigned char buffer_type; // 0x16 = UserID buffer type
- unsigned char connection_number; // Connection Number to get ID for
- };
- struct reply_buffer {
- unsigned short len;
- unsigned char object_id[4];
- unsigned char object_type[2];
- char object_name[48];
- char login_time[7];
- unsigned short reserved;
- };
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- struct request_buffer * reqbuf;
- struct reply_buffer * replybuf;
- unsigned short segment; // for DOS allocation
- unsigned short selector; // for DOS allocation
- //------------------------------------------------------------------------
- // Error if invalid connection is given
- //------------------------------------------------------------------------
- if (connection_number==0) {
- return(-1);
- }
- //------------------------------------------------------------------------
- // Allocate DOS memory to store the buffers passed to the interrupt
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- regs.x.eax = DPMI_ALLOC_DOS_MEM; // DPMI function to call
- regs.x.ebx = (sizeof(struct request_buffer) + // # paragraphs to allocate
- sizeof(struct reply_buffer) + 15) >> 4;
- int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory
- //------------------------------------------------------------------------
- // If the carry flag is set, DPMI is indicating an error.
- //------------------------------------------------------------------------
- if (regs.x.cflag) {
- return(-1);
- }
- //------------------------------------------------------------------------
- // Get pointers to allocated memory.
- // 'reqbuf' is just the returned real-mode segment, multiplied by 16.
- // 'replybuf' is an offset from 'reqbuf'.
- //------------------------------------------------------------------------
- segment = regs.w.ax;
- selector = regs.w.dx;
- reqbuf = (struct request_buffer *)(segment << 4);
- replybuf = (struct reply_buffer *)
- (((char *)reqbuf) + sizeof (struct request_buffer));
- //------------------------------------------------------------------------
- // Init the contents of the request & reply buffers
- //------------------------------------------------------------------------
- reqbuf->len = 2;
- reqbuf->buffer_type = 0x16;
- reqbuf->connection_number = (unsigned char)connection_number;
- replybuf->len = sizeof(struct reply_buffer) - 2;
- replybuf->object_id[0] = replybuf->object_id[0]; // suppress warnings
- replybuf->object_type[0] = replybuf->object_type[0]; // suppress warnings
- replybuf->login_time[0] = replybuf->login_time[0]; // suppress warnings
- replybuf->reserved = replybuf->reserved; // suppress warnings
- //------------------------------------------------------------------------
- // Invoke Int 21 with AH=0xe3, DS:SI=&request_buffer, ES:DI=&reply_buffer
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = 0x21; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.eax = 0x0000e300;
- rmi.ds = segment;
- rmi.esi = 0;
- rmi.es = segment;
- rmi.edi = sizeof(struct request_buffer);
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- //------------------------------------------------------------------------
- // Fill in the caller's buffer with the user name
- //------------------------------------------------------------------------
- strncpy(user_id, replybuf->object_name, 48);
- //------------------------------------------------------------------------
- // Free DOS memory
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- regs.x.eax = DPMI_FREE_DOS_MEM; // DPMI function to call
- regs.x.edx = selector; // ptr to free
- int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory
- return(0);
- } /* end of IPX_Get_User_ID */
- #endif //WIN32
- /***************************************************************************
- * IPX_Listen_For_Packet -- commands IPX to listen for a packet *
- * *
- * Before calling this function, you must fill in an ECB: *
- * SocketNumber: must contain the socket you've opened, *
- * and are "listening" on *
- * Event_Service_Routine: optionally points to a callback routine *
- * PacketCount: set to 2, to tell IPX there are 2 areas to *
- * store the incoming data in *
- * Packet[0].Address: set to the address of an IPXHeaderType *
- * Packet[0].Length: sizeof(IPXHeaderType) *
- * Packet[1].Address: address of data buffer, for the packet *
- * Packet[1].Length: size of the data buffer *
- * *
- * When the packet is received, ECBType.CompletionCode will be 0 if *
- * successful. Otherwise, some error occurred. *
- * *
- * You should initialize the ECB to 0's before filling it in. *
- * *
- * INPUT: *
- * ecb_ptr pointer to a filled-in ECB; MUST be real-mode memory *
- * *
- * OUTPUT: *
- * 0 = OK, IPX error otherwise *
- * *
- * WARNINGS: *
- * The ECB must be located in real-mode memory, as well as the values *
- * pointed to in the ECB (the IPX Header, the buffer to send, etc.) *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Listen_For_Packet(struct ECB *ecb_ptr)
- {
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- //------------------------------------------------------------------------
- // Call IPX with ES:SI=ecb_ptr
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = IPX_INT; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.ebx = IPX_LISTEN_FOR_PACKET;
- rmi.es = (short)((long)ecb_ptr >> 4);
- rmi.esi = (long)((long)ecb_ptr & 0x000f);
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- return(rmi.eax & 0x00ff);
- } /* end of IPX_Listen_For_Packet */
- #endif //WIN32
- /***************************************************************************
- * IPX_Send_Packet -- commands IPX to send a packet *
- * *
- * Before calling this function, you must fill in an ECB: *
- * SocketNumber: must contain the socket you've opened, *
- * and are sending on *
- * Event_Service_Routine: optionally points to a callback routine *
- * PacketCount: set to 2, to tell IPX there are 2 areas the *
- * outgoing data is stored in *
- * Packet[0].Address: set to the address of an IPXHeaderType *
- * Packet[0].Length: sizeof(IPXHeaderType) *
- * Packet[1].Address: address of buffer containing data to send *
- * Packet[1].Length: size of the data buffer *
- * ImmediateAddress: must be filled in with the node address of *
- * the bridge that will route the message; *
- * fill this in by calling IPX_Get_Local_Target *
- * *
- * Also, you must fill in the IPXHeaderType with certain values: *
- * PacketType: set to 4 for IPX *
- * DestNetworkNumber: Network Number of the destination system *
- * DestNetworkNode: Node Address of the destination system *
- * DestNetworkSocket: the destination system's socket to send to; *
- * this doesn't have to be the same as the *
- * socket opened on the local machine. *
- * *
- * You should initialize the ECB & IPXHeader to 0's before filling them in.*
- * *
- * INPUT: *
- * ecb_ptr pointer to a filled-in ECB *
- * *
- * OUTPUT: *
- * none. This function doesn't return anything; the caller must check *
- * its ECB.CompletionCode for: 0 = OK, IPX Error otherwise. *
- * *
- * WARNINGS: *
- * The ECB must be located in real-mode memory, as well as the values *
- * pointed to in the ECB (the IPX Header, the buffer to send, etc.) *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- void IPX_Send_Packet(struct ECB *ecb_ptr)
- {
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- //------------------------------------------------------------------------
- // Call IPX with ES:SI=ecb_ptr
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = IPX_INT; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.ebx = IPX_SEND_PACKET;
- rmi.es = (short)((long)ecb_ptr >> 4);
- rmi.esi = (long)((long)ecb_ptr & 0x000f);
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- } /* end of IPX_Send_Packet */
- #endif //WIN32
- /***************************************************************************
- * IPX_Get_Local_Target -- fills in ImmediateAddress field of ECB *
- * *
- * Use this function to fill in the ECB's ImmediateAddress field when *
- * sending a packet. The Immediate Address is the node address of the *
- * bridge that must route the message. If there is no bridge, it's *
- * filled in with the destination Node Address. In either case, it *
- * will contain the proper value for sending. *
- * *
- * INPUT: *
- * dest_network destination Network Number *
- * dest_node destination Node Address *
- * dest_socket destination Socket Number *
- * bridge_address field to fill in with Immediate Address *
- * *
- * OUTPUT: *
- * 0 = OK, error otherwise *
- * *
- * WARNINGS: *
- * If the Connection Number is 0 (user not logged in), dest_network *
- * and dest_node will be garbage, and this routine will probably crash. *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Get_Local_Target(unsigned char *dest_network, unsigned char *dest_node,
- unsigned short dest_socket, unsigned char *bridge_address)
- {
- struct request_buffer {
- unsigned char network_number [4];
- unsigned char physical_node [6];
- unsigned short socket;
- };
- struct reply_buffer {
- unsigned char local_target [6];
- };
- unsigned int rc;
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- struct request_buffer *reqbuf;
- struct reply_buffer *replybuf;
- unsigned short segment; // for DOS allocation
- unsigned short selector; // for DOS allocation
- //------------------------------------------------------------------------
- // Allocate DOS memory to store the buffers passed to the interrupt
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- regs.x.eax = DPMI_ALLOC_DOS_MEM; // DPMI function to call
- regs.x.ebx = (sizeof(struct request_buffer) + // # paragraphs to allocate
- sizeof(struct reply_buffer) + 15) >> 4;
- int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory
- //------------------------------------------------------------------------
- // If the carry flag is set, DPMI is indicating an error.
- //------------------------------------------------------------------------
- if (regs.x.cflag) {
- return(-1);
- }
- //------------------------------------------------------------------------
- // Get pointers to allocated memory.
- // 'reqbuf' is just the returned real-mode segment, multiplied by 16.
- // 'replybuf' is an offset from 'reqbuf'.
- //------------------------------------------------------------------------
- segment = regs.w.ax;
- selector = regs.w.dx;
- reqbuf = (struct request_buffer *)(segment << 4);
- replybuf = (struct reply_buffer *)
- (((char *)reqbuf) + sizeof (struct request_buffer));
- //------------------------------------------------------------------------
- // Init the contents of the request & reply buffers
- //------------------------------------------------------------------------
- memcpy(reqbuf->network_number, dest_network, 4);
- memcpy(reqbuf->physical_node, dest_node, 6);
- reqbuf->socket = dest_socket;
- //------------------------------------------------------------------------
- // Invoke IPX with DS:SI=&request_buffer, ES:DI=&reply_buffer
- //------------------------------------------------------------------------
- //........................................................................
- // Fill in registers for the DPMI call
- //........................................................................
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = IPX_INT; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //........................................................................
- // Fill in registers for the interrupt call
- //........................................................................
- rmi.ebx = IPX_GET_LOCAL_TARGET;
- rmi.ds = segment;
- rmi.esi = 0;
- rmi.es = segment;
- rmi.edi = sizeof(struct request_buffer);
- //........................................................................
- // call DPMI
- //........................................................................
- int386x(DPMI_INT, ®s, ®s, &sregs);
- rc = (rmi.eax & 0x00ff);
- memcpy(bridge_address, replybuf->local_target, 6);
- //------------------------------------------------------------------------
- // Free DOS memory
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- regs.x.eax = DPMI_FREE_DOS_MEM; // DPMI function to call
- regs.x.edx = selector; // ptr to free
- int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory
- return(rc);
- } /* end of IPX_Get_Local_Target */
- #endif //WIN32
- /***************************************************************************
- * IPX_Cancel_Event -- cancels an operation in progress *
- * *
- * INPUT: *
- * ecb_ptr pointer to ECB event to cancel *
- * *
- * OUTPUT: *
- * ??? *
- * *
- * WARNINGS: *
- * The ECB must be located in real-mode memory, as well as the values *
- * pointed to in the ECB (the IPX Header, the buffer to send, etc.) *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- int IPX_Cancel_Event(struct ECB *ecb_ptr)
- {
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- unsigned int rc;
- //------------------------------------------------------------------------
- // Fill in registers for the DPMI call
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = IPX_INT; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //------------------------------------------------------------------------
- // Fill in registers for the interrupt call
- //------------------------------------------------------------------------
- rmi.ebx = IPX_CANCEL_EVENT;
- rmi.es = (short)((long)ecb_ptr >> 4);
- rmi.esi = (long)((long)ecb_ptr & 0x000f);
- //------------------------------------------------------------------------
- // call DPMI
- //------------------------------------------------------------------------
- int386x(DPMI_INT, ®s, ®s, &sregs);
- rc = (rmi.eax & 0x00ff);
- return(rc);
- } /* end of IPX_Cancel_Event */
- #endif //WIN32
- /***************************************************************************
- * Let_IPX_Breath -- gives IPX some CPU time *
- * *
- * Use this function if you're polling the ECB's InUse flag, waiting *
- * for it to go to 0: *
- * *
- * while ECBType.InUse *
- * Let_IPX_Breath(); *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/15/1994 BR : Created. *
- *=========================================================================*/
- #ifndef WIN32 // WIN32 version is in IPX95.CPP
- void Let_IPX_Breath(void)
- {
- union REGS regs;
- struct SREGS sregs;
- RMIType rmi;
- //------------------------------------------------------------------------
- // Fill in registers for the DPMI call
- //------------------------------------------------------------------------
- memset (®s, 0 ,sizeof(regs));
- segread (&sregs);
- memset (&rmi, 0 ,sizeof(rmi));
- regs.w.ax = DPMI_CALL_REAL_INT; // DPMI function to call
- regs.w.bx = IPX_INT; // interrupt # to invoke
- sregs.es = FP_SEG(&rmi); // tell DPMI where the RMI is
- regs.x.edi = FP_OFF(&rmi);
- //------------------------------------------------------------------------
- // Fill in registers for the interrupt call
- //------------------------------------------------------------------------
- rmi.ebx = IPX_RELINQUISH_CONTROL;
- //------------------------------------------------------------------------
- // call DPMI
- //------------------------------------------------------------------------
- int386x(DPMI_INT, ®s, ®s, &sregs);
- } /* end of Let_IPX_Breath */
- #endif //WIN32
- /**************************** end of ipx.cpp *******************************/
|