1513 lines
27 KiB
C
1513 lines
27 KiB
C
/*++
|
||
|
||
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());
|
||
}
|