summaryrefslogtreecommitdiffstats
path: root/private/nw/vwipxspx/dll/vwdos.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/vwipxspx/dll/vwdos.c')
-rw-r--r--private/nw/vwipxspx/dll/vwdos.c1502
1 files changed, 1502 insertions, 0 deletions
diff --git a/private/nw/vwipxspx/dll/vwdos.c b/private/nw/vwipxspx/dll/vwdos.c
new file mode 100644
index 000000000..31a8ee5ba
--- /dev/null
+++ b/private/nw/vwipxspx/dll/vwdos.c
@@ -0,0 +1,1502 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ vwdos.c
+
+Abstract:
+
+ ntVdm netWare (Vw) IPX/SPX Functions
+
+ Vw: The peoples' network
+
+ Contains handlers for DOS IPX/SPX calls (netware functions). The IPX APIs
+ use WinSock to perform the actual operations
+
+ Contents:
+ VwIPXCancelEvent
+ VwIPXCloseSocket
+ VwIPXDisconnectFromTarget
+ VwIPXGenerateChecksum
+ VwIPXGetInformation
+ VwIPXGetInternetworkAddress
+ VwIPXGetIntervalMarker
+ VwIPXGetLocalTarget
+ VwIPXGetLocalTargetAsync
+ VwIPXGetMaxPacketSize
+ VwIPXInitialize
+ VwIPXListenForPacket
+ VwIPXOpenSocket
+ VwIPXRelinquishControl
+ VwIPXScheduleAESEvent
+ VwIPXScheduleIPXEvent
+ VwIPXSendPacket
+ VwIPXSendWithChecksum
+ VwIPXSPXDeinit
+ VwIPXVerifyChecksum
+
+ VwSPXAbortConnection
+ VwSPXEstablishConnection
+ VwSPXGetConnectionStatus
+ VwSPXInitialize
+ VwSPXListenForConnection
+ VwSPXListenForSequencedPacket
+ VwSPXSendSequencedPacket
+ VwSPXTerminateConnection
+
+Author:
+
+ Richard L Firth (rfirth) 30-Sep-1993
+
+Environment:
+
+ User-mode Win32
+
+Revision History:
+
+ 30-Sep-1993 rfirth
+ Created
+
+--*/
+
+#include "vw.h"
+#pragma hdrstop
+
+//
+// functions
+//
+
+
+VOID
+VwIPXCancelEvent(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Cancels event described by an ECB
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 06h
+ ES:SI ECB
+
+ Outputs
+ AL Completion code:
+ 00h Success
+ F9h Can't cancel ECB
+ FFh ECB not in use
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPECB pEcb;
+ WORD status;
+
+ CHECK_INTERRUPTS("VwIPXCancelEvent");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXCancelEvent,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXCancelEvent(%04x:%04x)\n",
+ getES(),
+ getSI()
+ ));
+
+ IPX_GET_IPX_ECB(pEcb);
+
+ status = _VwIPXCancelEvent( pEcb );
+
+ IPX_SET_STATUS(status);
+}
+
+
+VOID
+VwIPXCloseSocket(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Closes a socket and cancels any outstanding events on the socket.
+ Closing an unopened socket does not return an error
+ ESRs in cancelled ECBs are not called
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 01h
+ DX Socket Number
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD socketNumber;
+
+ CHECK_INTERRUPTS("VwIPXCloseSocket");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXCloseSocket,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXCloseSocket(%#x)\n",
+ B2LW(IPX_SOCKET_PARM())
+ ));
+
+ IPX_GET_SOCKET(socketNumber);
+
+ _VwIPXCloseSocket( socketNumber );
+
+}
+
+
+VOID
+VwIPXDisconnectFromTarget(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Performs no action for NTVDM IPX
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 0Bh
+ ES:SI Request buffer:
+ Destination Network DB 4 DUP (?)
+ Destination Node DB 6 DUP (?)
+ Destination Socket DB 2 DUP (?)
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXDisconnectFromTarget");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXDisconnectFromTarget,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXDisconnectFromTarget\n"
+ ));
+}
+
+
+VOID
+VwIPXGenerateChecksum(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Generates checksum for a transmit ECB
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 21h
+ ES:SI ECB address
+
+ Outputs
+ No registers
+ ECB checksum field is updated
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXGenerateChecksum");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXGenerateChecksum,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXGenerateChecksum\n"
+ ));
+}
+
+
+VOID
+VwIPXGetInformation(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Returns a bit-map of supported functions
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 1Fh
+ DX 0000h
+
+ Outputs
+ DX Bit map:
+ 0001h Set if IPX is IPXODI.COM, not dedicated IPX
+ 0002h Set if checksum functions (20h, 21h, 22h) supported
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXGetInformation");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXGetInformation,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXGetInformation\n"
+ ));
+
+ IPX_SET_INFORMATION(IPX_ODI);
+}
+
+
+VOID
+VwIPXGetInternetworkAddress(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Returns a buffer containing the net number and node number for this
+ station.
+
+ This function cannot return an error (!)
+
+ Assumes: 1. GetInternetAddress has been successfully called in the
+ DLL initialization phase
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 09h
+
+ Outputs
+ ES:SI Buffer
+ Network Address DB 4 DUP (?)
+ Node Address DB 6 DUP (?)
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPINTERNET_ADDRESS pAddr;
+
+ CHECK_INTERRUPTS("VwIPXGetInternetworkAddress");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXGetInternetworkAddress,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXGetInternetworkAddress(%04x:%04x)\n",
+ getES(),
+ getSI()
+ ));
+
+ pAddr = (LPINTERNET_ADDRESS)IPX_BUFFER_PARM(sizeof(*pAddr));
+
+ _VwIPXGetInternetworkAddress( pAddr );
+}
+
+
+VOID
+VwIPXGetIntervalMarker(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Just returns the tick count maintained by Asynchronous Event Scheduler
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 08h
+
+ Outputs
+ AX Interval marker
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXGetIntervalMarker");
+
+ setAX( _VwIPXGetIntervalMarker() );
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXGetIntervalMarker,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXGetIntervalMarker: Returning %04x\n",
+ getAX()
+ ));
+}
+
+
+VOID
+VwIPXGetLocalTarget(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Given a target address of the form (network address {4}, node address {6}),
+ returns the node address of the target if on the same network, or the node
+ address of the router which knows how to get to the next hop in reaching the
+ eventual target
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 02h
+ ES:SI Request buffer
+ Destination Network DB 4 DUP (?)
+ Destination Node DB 6 DUP (?)
+ Destination Socket DB 2 DUP (?)
+ ES:DI Response buffer
+ Local Target DB 6 DUP (?)
+
+ Outputs
+ AL Completion code
+ 00h Success
+ FAh No path to destination node found
+ AH Number of hops to destination
+ CX Transport time
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPBYTE pImmediateAddress;
+ LPBYTE pNetworkAddress;
+ WORD transportTime;
+ WORD status;
+
+ CHECK_INTERRUPTS("VwIPXGetLocalTarget");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXGetLocalTarget,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXGetLocalTarget(target buf @ %04x:%04x, local buf @ %04x:%04x)\n",
+ getES(),
+ getSI(),
+ getES(),
+ getDI()
+ ));
+
+
+ pImmediateAddress = POINTER_FROM_WORDS(getES(), getDI(), 6);
+ pNetworkAddress = POINTER_FROM_WORDS(getES(), getSI(), 12);
+
+ status = _VwIPXGetLocalTarget( pNetworkAddress,
+ pImmediateAddress,
+ &transportTime );
+
+
+ setCX( transportTime );
+ setAH(1);
+
+ IPX_SET_STATUS(status);
+}
+
+
+VOID
+VwIPXGetLocalTargetAsync(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+ This call is Asynchronous
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXGetLocalTargetAsync");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_ANY,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXGetLocalTargetAsync\n"
+ ));
+}
+
+
+VOID
+VwIPXGetMaxPacketSize(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Returns the maximum packet size the underlying network can handle
+
+ Assumes: 1. A successfull call to GetMaxPacketSize has been made during
+ DLL initialization
+ 2. Maximum packet size is constant
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 1Ah
+
+ Outputs
+ AX Maximum packet size
+ CX IPX retry count
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD maxPacketSize;
+ WORD retryCount;
+
+ CHECK_INTERRUPTS("VwIPXGetMaxPacketSize");
+
+ maxPacketSize = _VwIPXGetMaxPacketSize( &retryCount );
+
+ setAX(maxPacketSize);
+
+ //
+ // BUGBUG: The DOS Assembly and C manuals differ slightly here: DOS says
+ // we return the IPX retry count in CX. There is no corresponding parameter
+ // in the C interface?
+ //
+
+ setCX(retryCount);
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXGetMaxPacketSize,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXGetMaxPacketSize: PacketSize=%d, RetryCount=%d\n",
+ getAX(),
+ getCX()
+ ));
+}
+
+
+VOID
+VwIPXInitialize(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXInitialize");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_ANY,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXInitialize\n"
+ ));
+}
+
+
+VOID
+VwIPXListenForPacket(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Queue a listen request against a socket. All listen requests will be
+ completed asynchronously, unless cancelled by app
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 04h
+ ES:SI ECB address
+
+ Outputs
+ AL Completion code
+ FFh Socket doesn't exist
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPECB pEcb;
+ WORD status;
+
+ CHECK_INTERRUPTS("VwIPXListenForPacket");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXListenForPacket,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXListenForPacket(%04x:%04x)\n",
+ getES(),
+ getSI()
+ ));
+
+ IPX_GET_IPX_ECB(pEcb);
+
+ status = _VwIPXListenForPacket( pEcb, ECB_PARM_ADDRESS() );
+
+ IPX_SET_STATUS(status);
+}
+
+
+VOID
+VwIPXOpenSocket(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Opens a socket for use by IPX or SPX. Puts the socket into non-blocking mode.
+ The socket will be bound to IPX
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ AL Socket Longevity flag
+ This parameter is actually in BP - AX has been sequestered
+ by the VDD dispatcher
+ BX 00h
+ DX Requested Socket Number
+
+ CX DOS PDB. This parameter is not part of the IPX API.
+ Added because we need to remember which DOS executable created
+ the socket: we need to clean-up short-lived sockets when the
+ executable terminates
+
+ Outputs
+ AL Completion code:
+ 00h Success
+ FFh Socket already open
+ FEh Socket table full
+ DX Assigned socket number
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ BYTE socketLife;
+ WORD socketNumber;
+ WORD status;
+
+ CHECK_INTERRUPTS("VwIPXOpenSocket");
+
+ IPX_GET_SOCKET_LIFE(socketLife);
+ IPX_GET_SOCKET(socketNumber);
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXOpenSocket,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXOpenSocket(Life=%02x, Socket=%04x, Owner=%04x)\n",
+ socketLife,
+ B2LW(socketNumber),
+ IPX_SOCKET_OWNER_PARM()
+ ));
+
+
+ status = _VwIPXOpenSocket( &socketNumber,
+ socketLife,
+ IPX_SOCKET_OWNER_PARM() );
+
+ if ( status == IPX_SUCCESS )
+ IPX_SET_SOCKET(socketNumber);
+
+ IPX_SET_STATUS(status);
+}
+
+
+VOID
+VwIPXRelinquishControl(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Just sleep for a nominal amount. Netware seems to be dependent on the
+ default setting of the PC clock, so one timer tick (1/18 second) would
+ seem to be a good value
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 0Ah
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXRelinquishControl");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXRelinquishControl,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXRelinquishControl\n"
+ ));
+
+ _VwIPXRelinquishControl();
+
+}
+
+
+VOID
+VwIPXScheduleAESEvent(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Schedules a an event to occur in some number of ticks. When the tick count
+ reaches 0, the ECB InUse field is cleared and any ESR called
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 07h
+ AX Delay time - number of 1/18 second ticks
+ ES:SI ECB address
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPXECB pXecb = AES_ECB_PARM();
+ WORD ticks = IPX_TICKS_PARM();
+
+ CHECK_INTERRUPTS("VwIPXScheduleAESEvent");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXScheduleAESEvent,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXScheduleAESEvent(%04x:%04x, %04x)\n",
+ getES(),
+ getSI(),
+ ticks
+ ));
+
+ ScheduleEvent(pXecb, ticks);
+}
+
+
+VOID
+VwIPXScheduleIPXEvent(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Schedules a an event to occur in some number of ticks. When the tick count
+ reaches 0, the ECB InUse field is cleared and any ESR called
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 05h
+ AX Delay time - number of 1/18 second ticks
+ ES:SI ECB address
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPECB pEcb;
+ WORD ticks = IPX_TICKS_PARM();
+
+ CHECK_INTERRUPTS("VwIPXScheduleIPXEvent");
+
+ IPX_GET_IPX_ECB(pEcb);
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXScheduleIPXEvent,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXScheduleIPXEvent(%04x:%04x, %04x)\n",
+ getES(),
+ getSI(),
+ ticks
+ ));
+
+ _VwIPXScheduleIPXEvent( ticks, pEcb, ECB_PARM_ADDRESS() );
+
+}
+
+
+VOID
+VwIPXSendPacket(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Sends a packet to the target machine/router. This call can be made on a
+ socket that is not open
+
+ The app must have filled in the following IPX_ECB fields:
+
+ EsrAddress
+ Socket
+ ImmediateAddress
+ FragmentCount
+ fragment descriptor fields
+
+ and the following IPX_PACKET fields:
+
+ PacketType
+ Destination.Net
+ Destination.Node
+ Destination.Socket
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 03h
+ CX DOS PDB. This parameter is not part of the IPX API.
+ Added because we need to remember which DOS executable owns the
+ socket IF WE MUST CREATE A TEMPORTARY SOCKET: we need to clean-up
+ short-lived sockets when the executable terminates
+ ES:SI ECB Address
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPECB pEcb;
+ WORD owner;
+
+ CHECK_INTERRUPTS("VwIPXSendPacket");
+
+ IPX_GET_IPX_ECB(pEcb);
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXSendPacket,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXSendPacket(%04x:%04x), owner = %04x\n",
+ getES(),
+ getSI(),
+ IPX_SOCKET_OWNER_PARM()
+ ));
+
+ _VwIPXSendPacket(pEcb,
+ ECB_PARM_ADDRESS(),
+ IPX_SOCKET_OWNER_PARM()
+ );
+}
+
+
+VOID
+VwIPXSendWithChecksum(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+ This call is Asynchronous
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXSendWithChecksum");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXSendWithChecksum,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXSendWithChecksum\n"
+ ));
+}
+
+
+VOID
+VwIPXSPXDeinit(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+ This call is Synchronous
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXSPXDeinit");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_ANY,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXSPXDeinit\n"
+ ));
+}
+
+
+VOID
+VwIPXVerifyChecksum(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+ This call is Synchronous
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHECK_INTERRUPTS("VwIPXVerifyChecksum");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_IPXVerifyChecksum,
+ IPXDBG_LEVEL_INFO,
+ "VwIPXVerifyChecksum\n"
+ ));
+}
+
+
+VOID
+VwSPXAbortConnection(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Aborts this end of a connection
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 14h
+ DX Connection ID
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD connectionId = SPX_CONNECTION_PARM();
+
+ CHECK_INTERRUPTS("VwSPXAbortConnection");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_SPXAbortConnection,
+ IPXDBG_LEVEL_INFO,
+ "VwSPXAbortConnection(%04x)\n",
+ connectionId
+ ));
+
+ _VwSPXAbortConnection(connectionId);
+}
+
+
+VOID
+VwSPXEstablishConnection(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Creates a connection with a remote SPX socket. The remote end can be on
+ this machine (i.e. same app in DOS world)
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 11h
+ AL Retry count
+ AH WatchDog flag
+ ES:SI ECB Address
+
+ Outputs
+ AL Completion code:
+ 00h Attempting to talk to remote
+ EFh Local connection table full
+ FDh Fragment count not 1; buffer size not 42
+ FFh Send socket not open
+ DX Connection ID
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD status;
+ BYTE retryCount = SPX_RETRY_COUNT_PARM();
+ BYTE watchDogFlag = SPX_WATCHDOG_FLAG_PARM();
+ WORD connectionId;
+ LPECB pEcb;
+
+ CHECK_INTERRUPTS("VwSPXEstablishConnection");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_SPXEstablishConnection,
+ IPXDBG_LEVEL_INFO,
+ "VwSPXEstablishConnection(%02x, %02x, %04x:%04x)\n",
+ retryCount,
+ watchDogFlag,
+ ECB_PARM_SEGMENT(),
+ ECB_PARM_OFFSET()
+ ));
+
+ IPX_GET_IPX_ECB( pEcb );
+
+ IPXDUMPECB((pEcb, getES(), getSI(), ECB_TYPE_SPX, TRUE, TRUE, FALSE));
+
+ status = _VwSPXEstablishConnection( retryCount,
+ watchDogFlag,
+ &connectionId,
+ pEcb,
+ ECB_PARM_ADDRESS() );
+
+
+ SPX_SET_CONNECTION_ID( connectionId );
+ SPX_SET_STATUS( status );
+}
+
+
+VOID
+VwSPXGetConnectionStatus(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Returns buffer crammed full of useful statistics or something (hu hu huh)
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 15h
+ DX Connection ID
+ ES:SI Buffer address
+
+ Outputs
+ AL Completion code:
+ 00h Connection is active
+ EEh No such connection
+
+ on output, buffer in ES:SI contains:
+
+ BYTE ConnectionStatus
+ BYTE WatchDogActive
+ WORD LocalConnectionID
+ WORD RemoteConnectionID
+ WORD SequenceNumber
+ WORD LocalAckNumber
+ WORD LocalAllocationNumber
+ WORD RemoteAckNumber
+ WORD RemoteAllocationNumber
+ WORD LocalSocket
+ BYTE ImmediateAddress[6]
+ BYTE RemoteNetwork[4]
+ WORD RetransmissionCount
+ WORD RetransmittedPackets
+ WORD SuppressedPackets
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD status;
+ WORD connectionId = SPX_CONNECTION_PARM();
+ LPSPX_CONNECTION_STATS pStats = (LPSPX_CONNECTION_STATS)SPX_BUFFER_PARM(sizeof(*pStats));
+
+ CHECK_INTERRUPTS("VwSPXGetConnectionStatus");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_SPXGetConnectionStatus,
+ IPXDBG_LEVEL_INFO,
+ "VwSPXGetConnectionStatus: connectionId=%04x\n",
+ connectionId
+ ));
+
+ status = _VwSPXGetConnectionStatus( connectionId,
+ pStats );
+
+
+ SPX_SET_STATUS(status);
+}
+
+
+VOID
+VwSPXInitialize(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Informs the app that SPX is present on this station
+
+ This call is Synchronous
+
+Arguments:
+
+ Inputs
+ BX 10h
+ AL 00h
+
+ Outputs
+ AL Installation flag:
+ 00h Not installed
+ FFh Installed
+ BH SPX Major revision number
+ BL SPX Minor revision number
+ CX Maximum SPX connections supported
+ normally from SHELL.CFG
+ DX Available SPX connections
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD status;
+ BYTE majorRevisionNumber;
+ BYTE minorRevisionNumber;
+ WORD maxConnections;
+ WORD availableConnections;
+
+ CHECK_INTERRUPTS("VwSPXInitialize");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_SPXInitialize,
+ IPXDBG_LEVEL_INFO,
+ "VwSPXInitialize\n"
+ ));
+
+
+ status = _VwSPXInitialize( &majorRevisionNumber,
+ &minorRevisionNumber,
+ &maxConnections,
+ &availableConnections );
+
+
+ setBH( majorRevisionNumber );
+ setBL( minorRevisionNumber );
+ setCX( maxConnections );
+ setDX( availableConnections );
+ SPX_SET_STATUS(status);
+}
+
+
+VOID
+VwSPXListenForConnection(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Listens for an incoming connection request
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 12h
+ AL Retry count
+ AH SPX WatchDog flag
+ ES:SI ECB Address
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ BYTE retryCount = SPX_RETRY_COUNT_PARM();
+ BYTE watchDogFlag = SPX_WATCHDOG_FLAG_PARM();
+ LPECB pEcb;
+
+ CHECK_INTERRUPTS("VwSPXListenForConnection");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_SPXListenForConnection,
+ IPXDBG_LEVEL_INFO,
+ "VwSPXListenForConnection(%02x, %02x, %04x:%04x)\n",
+ retryCount,
+ watchDogFlag,
+ ECB_PARM_SEGMENT(),
+ ECB_PARM_OFFSET()
+ ));
+
+ IPX_GET_IPX_ECB( pEcb );
+
+ IPXDUMPECB((pEcb, getES(), getSI(), ECB_TYPE_SPX, TRUE, FALSE, FALSE));
+
+ _VwSPXListenForConnection( retryCount,
+ watchDogFlag,
+ pEcb,
+ ECB_PARM_ADDRESS() );
+}
+
+
+VOID
+VwSPXListenForSequencedPacket(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Attempts to receive an SPX packet. This call is made against the top-level
+ socket (the socket in SPX-speak, not the connection). We can receive a
+ packet from any connection assigned to this socket. In this function, we
+ just queue the ECB (since there is no return status, we expect that the
+ app has supplied an ESR) and let AES handle it
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 17h
+ ES:SI ECB Address
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPECB pEcb;
+
+ CHECK_INTERRUPTS("VwSPXListenForSequencedPacket");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_SPXListenForSequencedPacket,
+ IPXDBG_LEVEL_INFO,
+ "VwSPXListenForSequencedPacket(%04x:%04x)\n",
+ ECB_PARM_SEGMENT(),
+ ECB_PARM_OFFSET()
+ ));
+
+ IPX_GET_IPX_ECB( pEcb );
+
+ IPXDUMPECB((pEcb, getES(), getSI(), ECB_TYPE_SPX, TRUE, FALSE, FALSE));
+
+ _VwSPXListenForSequencedPacket( pEcb,
+ ECB_PARM_ADDRESS());
+
+}
+
+
+VOID
+VwSPXSendSequencedPacket(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Sends a packet on an SPX connection
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 16h
+ DX Connection ID
+ ES:SI ECB address
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD connectionId = SPX_CONNECTION_PARM();
+ LPECB pEcb;
+
+ CHECK_INTERRUPTS("VwSPXSendSequencedPacket""VwSPXSendSequencedPacket");
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_SPXSendSequencedPacket,
+ IPXDBG_LEVEL_INFO,
+ "VwSPXSendSequencedPacket(%04x, %04x:%04x)\n",
+ connectionId,
+ getES(),
+ getSI()
+ ));
+
+ IPX_GET_IPX_ECB( pEcb );
+
+ IPXDUMPECB((pEcb, getES(), getSI(), ECB_TYPE_SPX, TRUE, TRUE, FALSE));
+
+ _VwSPXSendSequencedPacket( connectionId,
+ pEcb,
+ ECB_PARM_ADDRESS() );
+
+}
+
+
+VOID
+VwSPXTerminateConnection(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Terminates a connection
+
+ This call is Asynchronous
+
+Arguments:
+
+ Inputs
+ BX 13h
+ DX Connection ID
+ ES:SI ECB Address
+
+ Outputs
+ Nothing
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD connectionId = SPX_CONNECTION_PARM();
+ LPECB pEcb;
+
+ CHECK_INTERRUPTS("VwSPXTerminateConnection");
+
+ IPX_GET_IPX_ECB( pEcb );
+
+ IPXDBGPRINT((__FILE__, __LINE__,
+ FUNCTION_SPXTerminateConnection,
+ IPXDBG_LEVEL_INFO,
+ "VwSPXTerminateConnection(%04x, %04x:%04x)\n",
+ connectionId,
+ ECB_PARM_SEGMENT(),
+ ECB_PARM_OFFSET()
+ ));
+
+ _VwSPXTerminateConnection(connectionId, pEcb, ECB_PARM_ADDRESS());
+}