Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1696 lines
34 KiB

/*++
Module Name:
novell.c
Abstract:
C interface to Netware DOS interface
WARNING WARNING WARNING
WARNING WARNING WARNING
The C mini-assembler will save and restore SI, DI, and BP on behalf of a
fn with an __asm block in it, but expects functions called within the asm
block to adhere to the same convention. The enteripx function does NOT do
this, so you must explicitly save SI, DI, and BP in each of the fns that
calls enteripx. DS is never saved by the compiler, so you must save it
yourself if you modify it.
Author:
Jeff Roberts (jroberts) 27-Oct-1994
Revision History:
27-Oct-1994 jroberts
Created this module.
--*/
#include <string.h>
#include "novell.h"
#ifdef WIN
#include "sysinc.h"
#include "rpc.h"
#include "rpctran.h"
#include "callback.h"
#define TASKID_C taskid,
#define TASKID taskid
//
// Id for IPX to identify us.
//
DWORD taskid = 0xffffffff;
//
// handle to nwipxspx.dll
//
HANDLE nwipxspx;
#else
#define TASKID_C
#define TASKID
void __far * __pascal __far
I_RpcAllocate (
unsigned int Size
);
void __pascal __far
I_RpcFree (
void __far * Object
);
#define RpcpMemoryCopy _fmemcpy
#endif // WIN .. else
#define MAX_FILE_SERVER 5
void __far * enteripx;
unsigned __pascal
ASMIPXInitialize(
)
/*++
Routine Description:
Verify existence of Netware and initialize the IPX entry point.
Arguments:
none
Return Value:
zero if ok
nonzero if failure
Exceptions:
none
--*/
{
unsigned char RetVal = 0xff;
enteripx = 0;
_asm
{
push si
push di
push bp
xor ax, ax
mov es, ax
mov ax, 0x7a00
push ds
int 0x2f
pop ds
pop bp
cmp al, 0ffh
jne no_ipx
mov cx, es ; if int 2f is not virtualized,
or cx, cx ; AL will be correct but the segment
jz no_ipx ; of the ipx entry point will be wrong
mov word ptr enteripx, di
mov ax, es
mov word ptr enteripx+2, ax
inc RetVal ; zero if ok, 1 if not
no_ipx:
pop di
pop si
}
return RetVal;
}
BYTE __pascal
ASMIPXCancelEvent(
ECB __far * ecb
)
{
_asm
{
push si
push di
push bp
mov bx, 6
les si, ecb
call dword ptr enteripx
pop bp
pop di
pop si
}
}
void __pascal
ASMIPXCloseSocket(
WORD Socket
)
{
_asm
{
push si
push di
push bp
mov bx, 1
mov dx, Socket
call dword ptr enteripx
pop bp
pop di
pop si
}
}
void __pascal
ASMIPXGetInternetworkAddress(
IPX_ADDRESS __far * Buffer
)
{
_asm
{
push si
push di
push bp
mov bx, 9
les si, Buffer
call dword ptr enteripx
pop bp
pop di
pop si
}
}
WORD __pascal
ASMIPXGetIntervalMarker(
)
{
_asm
{
push si
push di
push bp
mov bx, 8
call dword ptr enteripx
pop bp
pop di
pop si
}
}
BYTE __pascal
ASMIPXListenForPacket(
ECB __far * ecb
)
{
_asm
{
push si
push di
push bp
mov bx, 4
les si, ecb
call dword ptr enteripx
pop bp
pop di
pop si
}
}
BYTE __pascal
ASMIPXOpenSocket(
WORD __far * Socket,
unsigned fPermanent
)
{
_asm
{
push si
push di
push bp
mov bx, 0
les si, Socket
mov dx, es:[si]
mov ax, fPermanent
call dword ptr enteripx
pop bp
les si, Socket
mov es:[si], dx
pop di
pop si
}
}
void __pascal
ASMIPXRelinquishControl(
)
{
_asm
{
push si
push di
push bp
mov bx, 0x0a
call dword ptr enteripx
pop bp
pop di
pop si
}
}
void __pascal
ASMIPXSendPacket(
ECB __far * ecb
)
{
_asm
{
push si
push di
push bp
mov bx, 3
les si, ecb
call dword ptr enteripx
pop bp
pop di
pop si
}
}
void __pascal
ASMSPXAbortConnection(
WORD Conn
)
{
_asm
{
push si
push di
push bp
mov bx, 0x14
mov dx, Conn
call dword ptr enteripx
pop bp
pop di
pop si
}
}
BYTE __pascal
ASMSPXInitialize(
BYTE __far * majorver,
BYTE __far * minorver,
WORD __far * MaxConn,
WORD __far * availConn
)
{
_asm
{
push si
push di
push bp
mov bx, 0x10
mov al, 0
call dword ptr enteripx
pop bp
les si, majorver
mov byte ptr es:[si], bh
les si, minorver
mov byte ptr es:[si], bl
les si, MaxConn
mov word ptr es:[si], cx
les si, availConn
mov word ptr es:[si], dx
pop di
pop si
}
}
BYTE __pascal
ASMSPXEstablishConnection(
BYTE RetryCount,
BYTE fWatchdog,
WORD __far * pConn,
ECB __far * ecb
)
{
_asm
{
push si
push di
push bp
mov bx, 0x11
les si, ecb
mov al, RetryCount
mov ah, fWatchdog
call dword ptr enteripx
pop bp
les si, pConn
mov es:[si], dx
pop di
pop si
}
}
void __pascal
ASMSPXListenForSequencedPacket(
ECB __far * ecb
)
{
_asm
{
push si
push di
push bp
mov bx, 0x17
les si, ecb
call dword ptr enteripx
pop bp
pop di
pop si
}
}
void __pascal
ASMSPXSendSequencedPacket(
WORD Conn,
ECB __far * ecb
)
{
_asm
{
push si
push di
push bp
mov bx, 0x16
les si, ecb
mov dx, Conn
call dword ptr enteripx
pop bp
pop di
pop si
}
}
void __pascal
ASMSPXTerminateConnection(
WORD Conn,
ECB __far * ecb
)
{
_asm
{
push si
push di
push bp
mov bx, 0x13
les si, ecb
mov dx, Conn
call dword ptr enteripx
pop bp
pop di
pop si
}
}
unsigned __pascal
ASMIPXGetMaxPacketSize(
)
{
_asm
{
push si
push di
push bp
mov bx, 0x001a
call dword ptr enteripx
pop bp
pop di
pop si
}
//
// max packet size is in AX
//
}
void __pascal
ASMIPXDisconnectFromTarget(
BYTE __far * Address
)
{
_asm
{
push si
push di
push bp
mov bx, 0x0b
les si, Address
call dword ptr enteripx
pop bp
pop di
pop si
}
}
int __pascal
ASMIPXGetLocalTarget(
BYTE far * NetAddress,
BYTE far * Target,
int far * DelayTime
)
{
/*++
Routine Description:
Note that ES:SI is the destination address and ES:DI is the target.
Since both of the original args are far ptrs and may not be in the
same segment, I copy to/from buffers on the stack. That way
we are guaranteed to have both buffers in the same segment.
Arguments:
Return Value:
Exceptions:
--*/
BYTE LocalNetAddress[12];
BYTE LocalTarget[6];
int ReturnCode;
RpcpMemoryCopy(LocalNetAddress, NetAddress, 12);
_asm
{
push si
push di
push bp
mov bx, 2
push ss
pop es
lea si, LocalNetAddress
lea di, LocalTarget
call enteripx
pop bp
xor ah, ah
mov ReturnCode, ax
les si, DelayTime
mov word ptr es:[si], cx
pop di
pop si
}
RpcpMemoryCopy(Target, LocalTarget, 6);
return ReturnCode;
}
typedef struct
{
ECB ecb;
IPX_HEADER ipx;
NCP_REQUEST req;
}
NCP_REQUEST_ECB;
typedef struct
{
ECB ecb;
IPX_HEADER ipx;
NCP_RESPONSE resp;
}
NCP_RESPONSE_ECB;
void
SetupEcb(
ECB __far * ecb,
unsigned Socket,
unsigned BodyLength
)
{
IPX_HEADER __far * ipx = (IPX_HEADER __far *) (ecb+1);
ecb->socketNumber = Socket;
ecb->ESRAddress = NULL;
ecb->fragmentCount = 2;
ecb->fragmentDescriptor[0].size = sizeof( IPX_HEADER );
ecb->fragmentDescriptor[0].address = ipx;
ecb->fragmentDescriptor[1].size = BodyLength - sizeof(ECB) - sizeof(IPX_HEADER);
ecb->fragmentDescriptor[1].address = ipx+1;
}
FindFileServers(
IPX_ADDRESS * Servers,
unsigned MaxServers,
unsigned QueryType,
unsigned TickLimit
)
/*++
Routine Description:
Arguments:
Servers - space to store <MaxServers> server addresses
MaxServers - the number of entries in <Servers>
QueryType - either SAP_GENERAL_QUERY or SAP_NEAREST_QUERY
Return Value:
number of entries filled (i.e., servers found)
--*/
{
#define MAX_SAP_RESPONSE (480)
unsigned i;
unsigned Socket;
unsigned result;
struct
{
ECB ecb;
IPX_HEADER ipx;
SAP_RESPONSE resp;
}
__far * mem;
struct
{
ECB ecb;
IPX_HEADER ipx;
SAP_REQUEST sap;
} req;
unsigned start;
unsigned EcbCount;
unsigned ServerCount = 0;
//
// Allocate a socket.
//
result = IPXOpenSocket( TASKID_C &Socket, 0 );
if (result != 0)
{
return 0;
}
//
// Request memory for receive ECBs.
//
EcbCount = MaxServers * 2;
mem = 0;
while (0 == mem)
{
EcbCount /= 2;
if (0 == EcbCount)
{
return 0;
}
mem = I_RpcAllocate( EcbCount * sizeof(*mem));
}
//
// Submit receive ECBs to IPX.
//
for (i=0; i < EcbCount; ++i)
{
SetupEcb(&mem[i].ecb, Socket, sizeof(*mem));
IPXListenForPacket( TASKID_C &mem[i].ecb );
}
//
// Send the SAP request.
//
req.ipx.PacketType = IPX_PACKET_TYPE;
req.ipx.Destination.Network = 0;
req.ipx.Destination.Socket = SAP_SOCKET;
_fmemset( &req.ipx.Destination.Node, 0xff, sizeof(req.ipx.Destination.Node) );
SetupEcb(&req.ecb, Socket, sizeof(req));
_fmemset( &req.ecb.immediateAddress, 0xff, sizeof(req.ecb.immediateAddress) );
req.sap.QueryType = QueryType;
req.sap.ServerType = FILE_SERVER;
IPXSendPacket( TASKID_C &req.ecb );
while (req.ecb.inUseFlag != 0)
IPXRelinquishControl();
if (req.ecb.completionCode != 0)
{
goto cleanup;
}
//
// Collate responses.
//
start = IPXGetIntervalMarker(TASKID);
do
{
for (i = 0; i < EcbCount; i++)
{
if (mem[i].ecb.inUseFlag == 0)
{
if (mem[i].ecb.completionCode == 0x00)
{
mem[i].ipx.Length = ByteSwapShort( mem[i].ipx.Length );
mem[i].ipx.Length -= (sizeof(IPX_HEADER) + 4);
if (mem[i].ipx.Source.Socket == SAP_SOCKET &&
mem[i].ipx.Length >= sizeof(SAP_ENTRY) &&
(mem[i].resp.PacketType == SAP_GENERAL_RESPONSE ||
mem[i].resp.PacketType == SAP_NEAREST_RESPONSE))
{
// Copy these addresses to our table.
//
unsigned j;
unsigned ResponseCount = mem[i].ipx.Length / sizeof(SAP_ENTRY);
for (j = 0; j < ResponseCount && ServerCount < MaxServers; j++)
{
_fmemcpy( &Servers[ServerCount], &mem[i].resp.Entries[j].Address, 10 );
++ServerCount;
}
}
}
if (ServerCount < MaxServers)
{
IPXListenForPacket(TASKID_C &mem[i].ecb );
}
}
}
IPXRelinquishControl();
}
while (IPXGetIntervalMarker(TASKID) - start < TickLimit && ServerCount < MaxServers);
cleanup:
//
// Cancel remaining receives.
//
for (i = 0; i < EcbCount; i++)
{
if (mem[i].ecb.inUseFlag)
{
IPXCancelEvent( TASKID_C&mem[i].ecb );
while (mem[i].ecb.inUseFlag)
IPXRelinquishControl();
}
}
//
// Release memory and the socket.
//
I_RpcFree( mem );
IPXCloseSocket( TASKID_C Socket );
return ServerCount;
}
unsigned FileServerCount = 0;
unsigned ActiveFileServer = 0;
IPX_ADDRESS Servers[MAX_FILE_SERVER];
unsigned
ConnectToAnyFileServer(
NETWARE_CONNECTION * Connection,
unsigned TickCount
)
/*++
Routine Description:
Arguments:
Connection - will be filled in if we get a connection
Return Value:
zero if connection was created, else the completion code
--*/
{
unsigned i;
unsigned Status;
unsigned Socket;
unsigned RetryCount = 0;
retry:
//
// Find some servers to which we'll try to connect.
//
if (0 == FileServerCount)
{
FileServerCount = FindFileServers(Servers, MAX_FILE_SERVER, SAP_NEAREST_QUERY, TickCount);
}
//
// I think the routers are smart enough that this is not necessary.
//
// if (0 == FileServerCount)
// {
// FileServerCount = FindFileServers(Servers, MAX_FILE_SERVER, SAP_GENERAL_QUERY, TickCount);
// }
if (0 == FileServerCount)
{
Connection->ReturnCode = 0xff;
return 0xff;
}
//
// Get a receive socket.
//
Socket = 0;
Status = IPXOpenSocket( TASKID_C &Socket, 0 );
if (Status)
{
Connection->ReturnCode = Status;
return Status;
}
//
// Now, attach to each until one succeeds.
//
Status = ~0;
for (i=0; i < FileServerCount && Status; ++i)
{
NCP_REQUEST_ECB Request;
NCP_RESPONSE_ECB Response;
Connection->KnowImmediateAddress = 0;
Connection->Socket = Socket;
Connection->Sequence = 0;
Connection->Id = 0xffff;
_fmemcpy(&Connection->Server, &Servers[i], 10);
Request.req.RequestType = NCP_TYPE_CONNECT;
Status = NcpTransaction(Connection, &Request, sizeof(Request), &Response, sizeof(Response));
if (0 == Status)
{
Connection->Id = (Response.resp.conn_no_high << 8) | Response.resp.conn_no_low;
Connection->Sequence = 1;
break;
}
else
{
Connection->Socket = 0;
}
}
if (Status && !RetryCount)
{
FileServerCount = 0;
++RetryCount;
goto retry;
}
return Status;
}
NcpTransaction(
NETWARE_CONNECTION __far * Connection,
NCP_REQUEST_ECB __far * Request,
unsigned RequestLength,
NCP_RESPONSE_ECB __far * Response,
unsigned ResponseLength
)
{
unsigned Attempts;
unsigned StartTick;
unsigned Status;
SetupEcb(&Response->ecb, Connection->Socket, ResponseLength);
//
// Post response. I think this needs to occur before the call to
// IPXGetLocalTarget.
//
IPXListenForPacket( TASKID_C &Response->ecb );
SetupEcb(&Request->ecb, Connection->Socket, RequestLength);
if (!Connection->KnowImmediateAddress)
{
Status = IPXGetLocalTarget(TASKID_C
&Connection->Server,
Connection->ImmediateAddress,
&Connection->DelayTime
);
if (Status)
{
return Status;
}
Connection->KnowImmediateAddress = 1;
//
// Let's not have any miniscule retry intervals.
//
if (Connection->DelayTime < 100)
{
Connection->DelayTime = 100;
}
}
Request->ipx.PacketType = NCP_PACKET_TYPE;
_fmemcpy(&Request->ecb.immediateAddress, &Connection->ImmediateAddress, 6);
_fmemcpy(&Request->ipx.Destination, &Connection->Server, sizeof(IPX_ADDRESS));
Request->ipx.Destination.Socket = NCP_SOCKET;
Request->req.seq_no = Connection->Sequence;
Request->req.conn_no_low = Connection->Id % 0x100;
Request->req.conn_no_high = Connection->Id / 0x100;
Request->req.task_no = Connection->Task;
Attempts = 0;
do
{
//
// Send request.
//
++Attempts;
IPXSendPacket( TASKID_C &Request->ecb );
while (Request->ecb.inUseFlag)
IPXRelinquishControl();
if (Request->ecb.completionCode)
{
Connection->ReturnCode = Request->ecb.completionCode;
break;
}
StartTick = IPXGetIntervalMarker(TASKID);
wait:
//
// Wait for valid response.
//
IPXRelinquishControl();
if (IPXGetIntervalMarker(TASKID) - StartTick > Connection->DelayTime * 5)
{
continue;
}
if (Response->ecb.inUseFlag)
{
goto wait;
}
if (!Response->ecb.completionCode)
{
if (Response->ipx.Length < sizeof(IPX_HEADER) + sizeof(NCP_RESPONSE) ||
Response->resp.seq_no != Connection->Sequence ||
Response->resp.RequestType != NCP_TYPE_REPLY ||
0 != _fmemcmp(&Response->ipx.Source, &Connection->Server, 10))
{
IPXListenForPacket( TASKID_C &Response->ecb );
goto wait;
}
}
}
while ( Response->ecb.inUseFlag && Attempts < 3 );
//
// Try to get a reasonable return code from the response.
//
if (Response->ecb.inUseFlag)
{
Connection->ReturnCode = ECB_MISC_FAILURE;
}
else if (Response->ecb.completionCode)
{
Connection->ReturnCode = Response->ecb.completionCode;
}
else
{
Connection->ReturnCode = Response->resp.ret_code;
}
++Connection->Sequence;
Connection->ConnectionStatus = Response->resp.conn_status;
return Connection->ReturnCode;
}
unsigned
DisconnectFromServer(
NETWARE_CONNECTION * Connection
)
{
unsigned Status;
NCP_REQUEST_ECB Request;
NCP_RESPONSE_ECB Response;
if (!Connection->Socket)
{
return 0;
}
Request.req.RequestType = NCP_TYPE_DISCONNECT;
Status = NcpTransaction(Connection, &Request, sizeof(Request), &Response, sizeof(Response));
IPXCloseSocket(TASKID_C Connection->Socket);
return Status;
}
unsigned
ReadPropertyValue(
NETWARE_CONNECTION __far * Connection,
char __far * ObjectName,
unsigned ObjectType,
char __far * PropertyName,
unsigned Segment,
unsigned char __far * Value,
unsigned char __far * MoreSegments,
unsigned char __far * PropertyFlags
)
{
//
// In addition to the NCP base fields (up through subfn length), we need
//
// 1 byte for subfunction code
// 2 bytes for object type (hi-lo)
// 1 byte for object name length
// up to 47 bytes for object name
// 1 byte for segment number
// 1 byte for property name length
// up to 15 bytes for property name
//
struct
{
NCP_REQUEST_ECB hdr;
unsigned char buf[1+2+1+47+1+1+15];
}
Request;
struct
{
NCP_RESPONSE_ECB hdr;
unsigned char PropertyValue[128];
unsigned char MoreSegments;
unsigned char PropertyFlags;
}
Response;
unsigned ObjectNameLength = _fstrlen(ObjectName);
unsigned PropertyNameLength = _fstrlen(PropertyName);
//
// Fill in the request.
//
Request.hdr.req.RequestType = NCP_TYPE_REQUEST;
Request.hdr.req.req_code = NCP_FN_SCAN_BINDERY;
Request.hdr.req.subfn_length = ByteSwapShort(6 + ObjectNameLength + PropertyNameLength);
Request.buf[0] = NCP_SUBFN_READ_PROPERTY_VALUE;
Request.buf[1] = (unsigned char) (ObjectType / 0x100);
Request.buf[2] = (unsigned char) (ObjectType % 0x100);
Request.buf[3] = (unsigned char) ObjectNameLength;
RpcpMemoryCopy(Request.buf+4, ObjectName, ObjectNameLength);
Request.buf[4+ObjectNameLength] = (unsigned char) Segment;
Request.buf[5+ObjectNameLength] = (unsigned char) PropertyNameLength;
RpcpMemoryCopy(Request.buf+6+ObjectNameLength, PropertyName, PropertyNameLength);
//
// Get the data.
//
NcpTransaction(Connection,
&Request.hdr,
sizeof(Request),
&Response.hdr,
sizeof(Response)
);
if (!Connection->ReturnCode &&
!Connection->ConnectionStatus)
{
if (Value)
{
_fmemcpy(Value, Response.PropertyValue, 128);
}
if (MoreSegments)
{
*MoreSegments = Response.MoreSegments;
}
if (PropertyFlags)
{
*PropertyFlags = Response.PropertyFlags;
}
}
return Connection->ReturnCode;
}
//
//========================================================================
//
#if defined(WIN)
#include "windows.h"
typedef void
(__far __pascal *PTR_IpxDisconnectFromTarget)(
DWORD taskid,
BYTE __far * Address
);
typedef int
(__far __pascal *PTR_IpxGetLocalTarget)(
DWORD taskid,
BYTE __far * Address,
BYTE __far * Node,
int __far * Delay
);
typedef int
(__far __pascal *PTR_IpxInitialize)(
DWORD __far * ptaskid,
WORD MaxEcbs,
WORD MaxPacketSize
);
typedef int
(__far __pascal *PTR_IpxOpenSocket)(
DWORD taskid,
WORD __far * Socket,
BYTE SocketType
);
typedef void
(__far __pascal *PTR_IpxCloseSocket)(
DWORD taskid,
WORD Socket
);
typedef WORD
(__far __pascal *PTR_IpxGetIntervalMarker)(
DWORD taskid
);
typedef void
(__far __pascal *PTR_IpxSendPacket)(
DWORD taskid,
ECB __far * ecb
);
typedef void
(__far __pascal *PTR_IpxListenForPacket)(
DWORD taskid,
ECB __far * ecb
);
typedef int
(__far __pascal *PTR_IpxCancelEvent)(
DWORD taskid,
ECB __far * ecb
);
typedef void
(__far __pascal *PTR_IpxRelinquishControl)(
);
typedef int
(__far __pascal *PTR_IpxGetMaxPacketSize)(
);
typedef int
(__far __pascal *PTR_SpxInitialize)(
DWORD __far * TaskId,
WORD maxecb,
WORD maxpacketsize,
BYTE __far * majorver,
BYTE __far * minorver,
WORD __far * MaxConn,
WORD __far * availConn
);
typedef void
(__far __pascal *PTR_SpxAbortConnection)(
WORD Conn
);
typedef void
(__far __pascal *PTR_SpxSendSequencedPacket)(
DWORD taskid,
WORD Conn,
ECB __far * ecb
);
typedef void
(__far __pascal *PTR_SpxListenForSequencedPacket)(
DWORD taskid,
ECB __far * ecb
);
typedef int
(__far __pascal *PTR_SpxEstablishConnection)(
DWORD taskid,
BYTE RetryCount,
BYTE WatchDog,
WORD __far * Conn,
ECB __far * ecb
);
typedef void
(__far __pascal *PTR_SpxTerminateConnection)(
DWORD taskid,
WORD Conn,
ECB __far * ecb
);
typedef int
(__far __pascal *PTR_IpxSpxDeinit)(
DWORD taskid
);
struct IPX_FN_POINTERS
{
PTR_IpxInitialize IpxInitialize;
PTR_IpxOpenSocket IpxOpenSocket;
PTR_IpxCloseSocket IpxCloseSocket;
PTR_IpxGetIntervalMarker IpxGetIntervalMarker;
PTR_IpxSendPacket IpxSendPacket;
PTR_IpxListenForPacket IpxListenForPacket;
PTR_IpxCancelEvent IpxCancelEvent;
PTR_IpxRelinquishControl IpxRelinquishControl;
PTR_IpxGetMaxPacketSize IpxGetMaxPacketSize;
PTR_IpxGetLocalTarget IpxGetLocalTarget;
PTR_IpxDisconnectFromTarget IpxDisconnectFromTarget;
PTR_IpxSpxDeinit IpxSpxDeinit;
};
struct SPX_FN_POINTERS
{
PTR_SpxInitialize SpxInitialize;
PTR_SpxAbortConnection SpxAbortConnection;
PTR_SpxSendSequencedPacket SpxSendSequencedPacket;
PTR_SpxListenForSequencedPacket SpxListenForSequencedPacket;
PTR_SpxEstablishConnection SpxEstablishConnection;
PTR_SpxTerminateConnection SpxTerminateConnection;
};
extern HINSTANCE nwipxspx;
struct IPX_FN_POINTERS IpxFns;
struct SPX_FN_POINTERS SpxFns;
void __far * _fmalloc(unsigned);
unsigned __pascal
WrapperForIPXInitialize(
DWORD __far * pTaskId,
WORD MaxEcbs,
WORD MaxPacketSize
)
{
WORD tmp;
tmp = SetErrorMode( SEM_NOOPENFILEERRORBOX );
nwipxspx = LoadLibrary( "nwipxspx.dll" );
SetErrorMode( tmp );
if (nwipxspx >= HINSTANCE_ERROR)
{
IpxFns.IpxInitialize = (PTR_IpxInitialize) GetProcAddress( nwipxspx, "IPXInitialize");
IpxFns.IpxSpxDeinit = (PTR_IpxSpxDeinit) GetProcAddress( nwipxspx, "IPXSPXDeinit");
IpxFns.IpxOpenSocket = (PTR_IpxOpenSocket) GetProcAddress( nwipxspx, "IPXOpenSocket");
IpxFns.IpxCloseSocket = (PTR_IpxCloseSocket) GetProcAddress( nwipxspx, "IPXCloseSocket");
IpxFns.IpxGetIntervalMarker = (PTR_IpxGetIntervalMarker) GetProcAddress( nwipxspx, "IPXGetIntervalMarker");
IpxFns.IpxSendPacket = (PTR_IpxSendPacket) GetProcAddress( nwipxspx, "IPXSendPacket");
IpxFns.IpxListenForPacket = (PTR_IpxListenForPacket) GetProcAddress( nwipxspx, "IPXListenForPacket");
IpxFns.IpxCancelEvent = (PTR_IpxCancelEvent) GetProcAddress( nwipxspx, "IPXCancelEvent");
IpxFns.IpxRelinquishControl = (PTR_IpxRelinquishControl) GetProcAddress( nwipxspx, "IPXRelinquishControl");
IpxFns.IpxGetMaxPacketSize = (PTR_IpxGetMaxPacketSize) GetProcAddress( nwipxspx, "IPXGetMaxPacketSize");
IpxFns.IpxGetLocalTarget = (PTR_IpxGetLocalTarget) GetProcAddress( nwipxspx, "IPXGetLocalTarget");
IpxFns.IpxDisconnectFromTarget = (PTR_IpxDisconnectFromTarget) GetProcAddress( nwipxspx, "IPXDisconnectFromTarget");
SpxFns.SpxInitialize = (PTR_SpxInitialize) GetProcAddress( nwipxspx, "SPXInitialize");
SpxFns.SpxAbortConnection = (PTR_SpxAbortConnection) GetProcAddress( nwipxspx, "SPXAbortConnection");
SpxFns.SpxSendSequencedPacket = (PTR_SpxSendSequencedPacket) GetProcAddress( nwipxspx, "SPXSendSequencedPacket");
SpxFns.SpxListenForSequencedPacket=(PTR_SpxListenForSequencedPacket) GetProcAddress( nwipxspx, "SPXListenForSequencedPacket");
SpxFns.SpxEstablishConnection = (PTR_SpxEstablishConnection) GetProcAddress( nwipxspx, "SPXEstablishConnection");
SpxFns.SpxTerminateConnection = (PTR_SpxTerminateConnection) GetProcAddress( nwipxspx, "SPXTerminateConnection");
return (*IpxFns.IpxInitialize)(pTaskId, MaxEcbs, MaxPacketSize);
}
else
{
nwipxspx = 0;
return ASMIPXInitialize();
}
}
int __pascal
WrapperForIPXOpenSocket(
DWORD TaskId,
WORD __far * Socket,
BYTE SocketType
)
{
int rv;
if (nwipxspx)
{
rv = (*IpxFns.IpxOpenSocket)(TaskId, Socket, SocketType);
return(rv);
}
else
{
return (ASMIPXOpenSocket(Socket, SocketType));
}
}
void __pascal
WrapperForIPXDisconnectFromTarget(
DWORD TaskId,
BYTE __far * Address
)
{
if (nwipxspx)
{
(*IpxFns.IpxDisconnectFromTarget)(TaskId, Address);
}
else
{
ASMIPXDisconnectFromTarget(Address);
}
}
int __pascal
WrapperForIPXGetLocalTarget(
DWORD TaskId,
BYTE __far * Address,
BYTE __far * Node,
int __far * Delay
)
{
if (nwipxspx)
{
return (*IpxFns.IpxGetLocalTarget)(TaskId, Address, Node, Delay);
}
else
{
return (ASMIPXGetLocalTarget(Address, Node, Delay));
}
}
void __pascal
WrapperForIPXCloseSocket(
DWORD TaskId,
WORD Socket
)
{
if (nwipxspx)
{
(*IpxFns.IpxCloseSocket)(TaskId, Socket);
}
else
{
ASMIPXCloseSocket(Socket);
}
}
WORD __pascal
WrapperForIPXGetIntervalMarker(
DWORD TaskId
)
{
if (nwipxspx)
{
return (*IpxFns.IpxGetIntervalMarker)(TaskId);
}
else
{
return ASMIPXGetIntervalMarker();
}
}
void __pascal
WrapperForIPXSendPacket(
DWORD TaskId,
ECB __far * ecb
)
{
if (nwipxspx)
{
(*IpxFns.IpxSendPacket)(TaskId, ecb);
}
else
{
ASMIPXSendPacket(ecb);
}
}
void __pascal
WrapperForIPXListenForPacket(
DWORD TaskId,
ECB __far * ecb
)
{
if (nwipxspx)
{
(*IpxFns.IpxListenForPacket)(TaskId, ecb);
}
else
{
ASMIPXListenForPacket(ecb);
}
}
int __pascal
WrapperForIPXCancelEvent(
DWORD TaskId,
ECB __far * ecb
)
{
if (nwipxspx)
{
return (*IpxFns.IpxCancelEvent)(TaskId, ecb);
}
else
{
return ASMIPXCancelEvent(ecb);
}
}
void __pascal
WrapperForIPXRelinquishControl(
)
{
if (nwipxspx)
{
(*IpxFns.IpxRelinquishControl)();
}
else
{
ASMIPXRelinquishControl();
}
}
int __pascal
WrapperForIPXGetMaxPacketSize(
)
{
if (nwipxspx)
{
return (*IpxFns.IpxGetMaxPacketSize)();
}
else
{
return(ASMIPXGetMaxPacketSize());
}
}
int __pascal
WrapperForSPXInitialize(
DWORD __far * TaskId,
WORD maxecb,
WORD maxpacketsize,
BYTE __far * majorver,
BYTE __far * minorver,
WORD __far * MaxConn,
WORD __far * availConn
)
{
if (nwipxspx)
{
return (*SpxFns.SpxInitialize)(TaskId,
maxecb,
maxpacketsize,
majorver,
minorver,
MaxConn,
availConn);
}
else
{
return (ASMSPXInitialize(majorver,
minorver,
MaxConn,
availConn));
}
}
void __pascal
WrapperForSPXAbortConnection(
WORD Conn
)
{
if (nwipxspx)
{
(*SpxFns.SpxAbortConnection)(Conn);
}
else
{
(ASMSPXAbortConnection(Conn));
}
}
void __pascal
WrapperForSPXSendSequencedPacket(
DWORD TaskId,
WORD Conn,
ECB __far * ecb
)
{
if (nwipxspx)
{
(*SpxFns.SpxSendSequencedPacket)(TaskId, Conn, ecb);
}
else
{
ASMSPXSendSequencedPacket(Conn, ecb);
}
}
void __pascal
WrapperForSPXListenForSequencedPacket(
DWORD TaskId,
ECB __far * ecb
)
{
if (nwipxspx)
{
(*SpxFns.SpxListenForSequencedPacket)(TaskId, ecb);
}
else
{
ASMSPXListenForSequencedPacket(ecb);
}
}
int __pascal
WrapperForSPXEstablishConnection(
DWORD TaskId,
BYTE RetryCount,
BYTE WatchDog,
WORD __far * Conn,
ECB __far * ecb
)
{
if (nwipxspx)
{
return (*SpxFns.SpxEstablishConnection)(TaskId,
RetryCount,
WatchDog,
Conn,
ecb
);
}
else
{
return (ASMSPXEstablishConnection(RetryCount,
WatchDog,
Conn,
ecb));
}
}
void __pascal
WrapperForSPXTerminateConnection(
DWORD TaskId,
WORD Conn,
ECB __far * ecb
)
{
if (nwipxspx)
{
(*SpxFns.SpxTerminateConnection)(TaskId,
Conn,
ecb
);
}
else
{
ASMSPXTerminateConnection(Conn, ecb);
}
}
int __pascal
WrapperForIPXSPXDeinit(
DWORD TaskId
)
{
if (nwipxspx)
{
return (*IpxFns.IpxSpxDeinit)(TaskId);
}
else
{
return (1);
}
}
#endif // __RPC_WIN__