You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1512 lines
28 KiB
1512 lines
28 KiB
/*++
|
|
|
|
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));
|
|
if (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);
|
|
|
|
if (pImmediateAddress && pNetworkAddress) {
|
|
status = _VwIPXGetLocalTarget( pNetworkAddress,
|
|
pImmediateAddress,
|
|
&transportTime );
|
|
}
|
|
else {
|
|
status = IPX_BAD_REQUEST;
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
//
|
|
// 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();
|
|
|
|
if (pXecb == NULL) {
|
|
return;
|
|
}
|
|
|
|
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 = 0;
|
|
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());
|
|
}
|