607 lines
20 KiB
Plaintext
607 lines
20 KiB
Plaintext
{$B-,V-,X+}
|
|
UNIT nwIPX;
|
|
|
|
{$DEFINE ProtMode}
|
|
{$IFDEF MSDOS} {$UNDEF ProtMode} {$DEFINE RealMode} {$ENDIF}
|
|
{$IFDEF ProtMode} sorry, protected mode not supported (yet) {$ENDIF}
|
|
|
|
{ nwIPX unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R.Spronk }
|
|
|
|
INTERFACE
|
|
|
|
Uses Dos,nwMisc;
|
|
|
|
{ Primary IPX calls: Subf: Comments:
|
|
|
|
IPXCancelEvent 6 AES
|
|
* IPXCloseSocket 1 (1)
|
|
IPXDisconnectFromTarget B (1)
|
|
* IPXGetInterNetworkaddress 9
|
|
* IPXGetIntervalMarker 8
|
|
* IPXGetLocalTarget 2
|
|
- IPXGetPacketSize D (IPX internal use only)
|
|
* IPXInitialize INT 2F
|
|
- IPXInitializeNetworkAddress C (IPX internal use only)
|
|
* IPXListenForPacket 4
|
|
* IPXOpenSocket 0
|
|
* IPXRelinquishControl A
|
|
* IPXScheduleIPXEvent 5 AES
|
|
IPXScheduleSpecialEvent 7
|
|
* IPXSendPacket 3
|
|
- IPXTerminateSockets E (IPX internal use only)
|
|
|
|
Secondary calls:
|
|
|
|
* IPXpresent
|
|
* IPXsetupSendECB
|
|
* IPXsetupListenECB
|
|
|
|
Notes: (1) These functions use INT 21 and are not to be called from
|
|
within an ESR.
|
|
}
|
|
|
|
CONST
|
|
LONG_LIVED_SOCKET = TRUE; { IPXopenSocket }
|
|
SHORT_LIVED_SOCKET = FALSE;
|
|
|
|
{*** PACKET TYPES ***}
|
|
|
|
UNKNOWN_PACKET_TYPE =0; { (basic) Unknown IPX packet }
|
|
IPX_PACKET_TYPE =0;
|
|
RIP_PACKET_TYPE =1; { Routing Information Packet }
|
|
ECHO_PACKET_TYPE =2;
|
|
ERROR_PACKET_TYPE =3;
|
|
PEP_PACKET_TYPE =4; { Packet Exchange Protocol }
|
|
SPX_PACKET_TYPE =5; { Sequenced Packet Protocol Packet }
|
|
PUP_PACKET_TYPE =12;
|
|
DOD_IP_PACKET_TYPE =13; { Internet Protocol packet Type }
|
|
NCP_PACKET_TYPE =17; { NetWare Core Protocol }
|
|
{ Experimental packet types: 20 - 37 }
|
|
|
|
{*** SOCKET NUMBERS ***}
|
|
|
|
{0001-0BB8 Registered with Xerox }
|
|
SKT_XEROX_ROUTING_INFORMATION= $0001;
|
|
SKT_ECHO_PROTOCOL = $0002;
|
|
SKT_ERROR_HANDLER = $0003;
|
|
|
|
{0020-003F Xerox : Experimental }
|
|
SKT_NW4_TIME_SYNC_SERVER = $0040; { used by OT_NW4_TIME_SYNC_SERVER }
|
|
SKT_FILE_SERVICE = $0451; { see also $8140, used by OT_RSPCX_SERVER }
|
|
SKT_SERVICE_ADVERTISING = $0452; { SAP }
|
|
SKT_ROUTING_INFORMATION = $0453; { Novell's RIP Socket }
|
|
SKT_NETBIOS = $0455;
|
|
SKT_DIAGNOSTIC = $0456;
|
|
{ 0457h ??? (appears to be related to server serial numbers) }
|
|
|
|
{0BB9-FFFF Xerox : Dynamically assignable Sockets }
|
|
{0BB9-3FFF Novell: }
|
|
SKT_NMA_AGENT =$2F90; { used by OT_NMA_AGENT (NMS) }
|
|
|
|
{4000-7FFF Novell: Dynamically assignable Sockets }
|
|
{ Use a socket in this range for your own applications. }
|
|
{ To avoid conflicts with other programs, you are advised NOT }
|
|
{ to use sockets numbers where the hi-byte equals the low-byte, }
|
|
{ C programmers mostly use those to avoid byte-order swapping. }
|
|
|
|
{ ! See the SKT_XXX file in the XIPX archive for the latest info
|
|
on socket numbers... }
|
|
|
|
{8000-FFFF Novell: Well known sockets, registered with Novell. }
|
|
SKT_EMAIL_CHAT =$8055; { Niche Corp. }
|
|
SKT_EMAIL_CHAT_2 =$8056; { Niche Corp. }
|
|
SKT_BTRIEVE =$8058;
|
|
SKT_BTRIEVE_2 =$8059;
|
|
SKT_NW_SQL =$805A;
|
|
SKT_NW_SQL_2 =$805B;
|
|
SKT_GAMESERVER =$805C;
|
|
SKT_GAMESERVER_2 =$805D;
|
|
SKT_PRINT_SERVER =$8060;
|
|
SKT_DIGITAL_CHAT =$806C; { Digital Inc. }
|
|
SKT_NW_ACCESS_SERVER =$806F;
|
|
SKT_OXXI_EMAIL_CHAT =$80C3; { Oxxi Inc. }
|
|
SKT_PRINT_SERVER_2 =$811E;
|
|
SKT_INTEL_EMAIL_CHAT =$845F; { Intel Corp. }
|
|
SKT_WINDOWS_EMAIL_CHAT =$9017;
|
|
SKT_JOB_SERVER =$9022;
|
|
|
|
Var Result:word; { unit errorcode variable }
|
|
|
|
Type TipxHeader=Record
|
|
checksum :word; { not used, set to $FFFF }
|
|
length :word; { total number of bytes }
|
|
TransportControl :byte; { used by bridges: low 4 bits= hop count }
|
|
packetType :byte; { ignored by IPX, used by higher level
|
|
protocols only. $00=unknown packet type}
|
|
destination,
|
|
source :TinternetWorkAddress;
|
|
{ if dest.network equals 0; dest
|
|
assumed on same network as sender }
|
|
{ if dest.node =$FFFFFFFFFFFF, packet
|
|
will be sent to all nodes. }
|
|
end;
|
|
{ Fields within IPX and SPX are high-low. Byte swapping will be done
|
|
by the IPX functions, except network and node addresses. }
|
|
|
|
Tfragment=record { address and size of buffer fragment. }
|
|
Address:Pointer;
|
|
Size:word;
|
|
end;
|
|
|
|
Tecb=record
|
|
Linkaddress :Pointer; { used by IPX itself }
|
|
ESRaddress :Pointer;
|
|
InUseFlag :Byte; { reset to $00 when request completed }
|
|
CompletionCode :Byte; { valid after InUseFlag becomes $00;
|
|
completionCode=$00: packet sent/received. }
|
|
SocketNumber :word;
|
|
IPXworkspace :array[1..4] of byte;
|
|
DriverWorkspace :array[1..12] of byte;
|
|
Immediateaddress:Tnodeaddress; { 6 bytes }
|
|
FragmentCount :word; { must be >0 }
|
|
Fragment :array[1..2] of Tfragment; { [1..FragmentCount] }
|
|
{ The number of fragments is unlimited.
|
|
However, most applications use 1 or 2. }
|
|
end;
|
|
Tpecb=^Tecb;
|
|
|
|
{ TAESecb=:
|
|
Offset Size Description
|
|
00h DWORD Link
|
|
04h DWORD ESR address
|
|
08h BYTE in use flag (see below)
|
|
09h 5 BYTEs AES workspace }
|
|
|
|
Function IpxPresent:boolean;
|
|
{ Determines if an IPX driver is loaded. Calls IPXInitialize. }
|
|
|
|
Function IPXinitialize:Boolean;
|
|
{ Determines if an IPX driver is loaded. }
|
|
|
|
{IPX/SPX: 09h}
|
|
Function IPXGetInternetworkAddress(Var Address:TinterNetworkAddress):boolean;
|
|
{ This call returns the network and node address of the requesting workstation. }
|
|
{ The two byte socketnumber must be appended to the end to form a full }
|
|
{ 12-Byte network address. The socketnumber will be set to 0000, indicating
|
|
that it has to be filled later with a meaningfule number. }
|
|
|
|
{IPX/SPX: 00h}
|
|
Function IPXOpenSocket(Var socket:word; PermanentSocket:boolean):boolean;
|
|
{ When an application wants to send or receive packets on a socket,
|
|
it should first open the socket. PermanentSocket should be set to TRUE
|
|
if the socket is used by a TSR. This way, the socket will only be
|
|
closed when the IPXcloseSocket function is called. Otherwise, set to FALSE. }
|
|
|
|
{IPX/SPX: 01h}
|
|
Function IPXCloseSocket(socket:word):boolean;
|
|
{ Closes the socket. TSRs should close permanent sockets before terminating. }
|
|
|
|
{IPX/SPX: 02h}
|
|
Function IPXGetLocalTarget(Address:TinternetworkAddress;
|
|
Var ImmAddr:TnodeAddress;
|
|
Var Ticks:word ):boolean;
|
|
{ Returns the nodeaddress (Immediate address) of a bridge/router that
|
|
connects the senders' network with the target-network. If the target
|
|
lies within the same network as the sender, the returned node address
|
|
is the same as the target node-address. }
|
|
|
|
{IPX/SPX: 03h}
|
|
Function IPXSendPacket(Var Ecb:Tecb):boolean;
|
|
{ After calling this function, control is immediately turned back to the
|
|
calling process, whilst in the background the IPX driver is trying to
|
|
send the packet. To check if the message has been sent, check the
|
|
ECB.InUseFlag or use a SendESR.
|
|
The ecb must be filled with appropriate values before calling this function,
|
|
the socket to send on must be open. }
|
|
|
|
{IPX/SPX: 0Fh}
|
|
Function IPXInternalSendPacket(Var Ecb:Tecb):boolean;
|
|
|
|
{IPX/SPX: 04h}
|
|
Function IPXListenForPacket(Var Ecb:Tecb):Boolean;
|
|
{ After calling this function, control is immediately turned back to the
|
|
calling process. The IPX driver will wait in the background for a packet
|
|
to be received. To check if a message has been received, check the
|
|
ECB.InUseFlag or use a ListenESR.
|
|
The ecb must be filled with appropriate values before calling this function,
|
|
the socket to receive on must be open. }
|
|
|
|
{IPX/SPX: 0Ah}
|
|
Function IPXrelinquishControl:boolean;
|
|
{ Temporarily gives away CPU time to bakcground processes. This call
|
|
improves efficeincy by informing the IPX driver that the CPU is
|
|
available. }
|
|
|
|
{IPX/SPX: 08h}
|
|
Function IPXgetIntervalMarker(Var ticks:word):boolean;
|
|
{ Gets a time marker from IPX. The difference between two known
|
|
time-markers can be used to determine if a timeout has occurred.
|
|
1 Tick = 1/18.2 second. }
|
|
|
|
{IPX/SPX: 06h}
|
|
Function IPXcancelEvent(ECB:Tecb):boolean;
|
|
{ AES call: Cancel an event.
|
|
When the event is canceled, the ECB.InUseFlag will be set to $00 and the
|
|
ECB.CompletionCode to $FC: Event Canceled. }
|
|
|
|
{IPX/SPX: 0Bh}
|
|
Function IPXdisconnectFromTarget(Address:TinternetworkAddress):boolean;
|
|
{ Informs the listening socket at the specified adress that no more
|
|
packets will be sent to the listening socket.
|
|
This function is not required in your application, it is merely used
|
|
to inform some drivers that the connection (if any) has ended. }
|
|
|
|
{IPX/SPX: 05h}
|
|
Function IPXscheduleIPXevent(ticks:word;Var ECB:Tecb):boolean;
|
|
{ AES call: schedule an event.
|
|
After calling this function, control is immediately turned back to the
|
|
calling process. After waiting the number of ticks specified
|
|
(1 tick= 1/18.2 sec.), the IPX driver activates the ECB.
|
|
This function should never be called with an ECB that is still in use
|
|
by the IPXdriver (i.e. ECB.InUseFlag should be 0 before calling)
|
|
}
|
|
|
|
{UPX: 0007}
|
|
Function IPXscheduleSpecialEvent(ticks:word;Var ECB:Tecb):boolean;
|
|
|
|
Procedure IpxSpxSystemCall(Var regs:registers);
|
|
{ Provides an entry into the INT A7 interrupt handler;
|
|
Valid only if IPXinitialize or IPXinstalled were called previously. }
|
|
|
|
{************** Secondary Procedures ***************************************}
|
|
|
|
Procedure IPXSetupListenECB(ESRptr:Pointer; ReceiveSocket:word;
|
|
BufPtr:Pointer; BufSize:word;
|
|
{out:} Var IpxHdr:TipxHeader; Var ecb:Tecb);
|
|
{ Clears IPXheader and ECB, sets values of the required fields within
|
|
the ecb and IPX header. }
|
|
|
|
Procedure IPXsetupSendECB(ESRptr:pointer; SourceSocket:Word;
|
|
DestAddr:TinterNetworkAddress;
|
|
BufPtr:pointer; BufSize:word;
|
|
{out:} Var IpxHdr:TipxHeader; Var ecb:Tecb);
|
|
{ Clears IPXheader and ECB, sets values of the required fields within
|
|
the ecb and IPX header. }
|
|
|
|
IMPLEMENTATION {==============================================================}
|
|
|
|
CONST
|
|
IPX_MAX_DATA_LENGTH =546;
|
|
|
|
Var IpxSpxCall:Procedure;
|
|
|
|
Procedure IpxSpxSystemCall(Var regs:registers); assembler;
|
|
{ This method of calling IPX/SPX is preferred by Novell. }
|
|
{ For what its' worth: this call is 48 bytes longer than the other one.. }
|
|
asm
|
|
{ check if IpxSpxCall known. If not, return error $FF in fake AL }
|
|
xor ah,ah
|
|
mov al,$FF
|
|
les di,IpxSpxCall
|
|
mov bx,es
|
|
cmp bx,$0000
|
|
je @1
|
|
{ move fake regs registers to 'real' registers }
|
|
{ AX, BX, CX, DX, SI, DI, ES only. }
|
|
les di,regs
|
|
mov ax,es:[di+16]
|
|
push ax { push new es }
|
|
mov ax,es:[di+12]
|
|
push ax { push new di }
|
|
mov ax,es:[di]
|
|
mov bx,es:[di+2]
|
|
mov cx,es:[di+4]
|
|
mov dx,es:[di+6]
|
|
mov si,es:[di+10]
|
|
pop di
|
|
pop es
|
|
{ farr call to A7 interrup handler }
|
|
push bp
|
|
CALL IpxSpxCall
|
|
pop bp
|
|
@1: { move 'real' registers to fake regs registers }
|
|
push es
|
|
push di
|
|
les di,regs
|
|
mov es:[di],ax
|
|
mov es:[di+2],bx
|
|
mov es:[di+4],cx
|
|
mov es:[di+6],dx
|
|
mov es:[di+10],si
|
|
pop ax { ax:= 'di' }
|
|
mov es:[di+12],ax
|
|
pop ax { ax:= 'es' }
|
|
mov es:[di+16],ax
|
|
end;
|
|
|
|
Function IPXinitialize:Boolean;
|
|
CONST DOS_MULTIPLEX =$2F;
|
|
Var regs:registers;
|
|
begin
|
|
Regs.AX:=$7A00;
|
|
INTR(DOS_MULTIPLEX,Regs);
|
|
if regs.AL<>$FF
|
|
then begin
|
|
Result:=IPX_NOT_INSTALLED;
|
|
IpxInitialize:=false
|
|
end
|
|
else begin
|
|
@IpxSpxCall:=Ptr(Regs.es,Regs.di);
|
|
Result:=0;
|
|
IpxInitialize:=true;
|
|
end;
|
|
end;
|
|
|
|
Function IpxPresent:boolean;
|
|
begin
|
|
IpxPresent:=IpxInitialize
|
|
end;
|
|
|
|
{IPX: 09h}
|
|
Function IPXGetInternetworkAddress(Var Address:TinterNetworkAddress):boolean;
|
|
{ This call returns the network and node address of the requesting workstation. }
|
|
{ The two byte socketnumber must be appended to the end to form a full }
|
|
{ 12-Byte network address. }
|
|
Var regs:registers;
|
|
begin
|
|
regs.bx:=$0009;
|
|
regs.es:=seg(Address);
|
|
regs.si:=ofs(Address);
|
|
IpxSpxSystemCall(Regs);
|
|
result:=regs.al;
|
|
address.socket:=$0000; { unknown, to be set later. }
|
|
if result<>$FF
|
|
then result:=$00;
|
|
IPXGetInternetworkAddress:=(result=$00);
|
|
{ possible resultcodes: $00 Successful; $FF IPX not initialized }
|
|
end;
|
|
|
|
{IPX: 00}
|
|
Function IPXOpenSocket(Var socket:word; permanentSocket:boolean):boolean;
|
|
Var regs:registers;
|
|
reqForSocket:boolean;
|
|
begin
|
|
regs.bx:=$0000;
|
|
if permanentSocket
|
|
then regs.al:=$FF
|
|
else regs.al:=$00;
|
|
regs.dx:=swap(socket); {hi-lo}
|
|
reqForSocket:=(socket=$0000);
|
|
|
|
IpxSpxSystemCall(Regs);
|
|
|
|
result:=regs.al;
|
|
if reqForSocket
|
|
then socket:=swap(regs.dx); {force lo-hi}
|
|
IPXopenSocket:=(result=0);
|
|
{ resultcodes: $00 successful; $FE Socket Table Is Full;
|
|
$FF socket already open OR IPX not initilazed. }
|
|
end;
|
|
|
|
{IPX: 01}
|
|
Function IPXCloseSocket(socket:word):boolean;
|
|
Var regs:registers;
|
|
begin
|
|
regs.bx:=$01;
|
|
regs.dx:=swap(socket);
|
|
IpxSpxSystemCall(regs);
|
|
result:=regs.al;
|
|
if result<>$FF then result:=$00;
|
|
IPXCloseSocket:=(result=$00);
|
|
{ possible resultcodes: $00 Successful; $FF IPX not initialized }
|
|
end;
|
|
|
|
|
|
{IPX: 02}
|
|
Function IPXGetLocalTarget(Address:TinternetworkAddress;
|
|
Var ImmAddr:TnodeAddress;
|
|
VAR ticks:Word ):boolean;
|
|
{ Ticks = estimated transmission time, in number of ticks (1/18 sec) }
|
|
Var reqAddr:TinternetworkAddress;
|
|
repNode:TnodeAddress;
|
|
Regs :registers;
|
|
begin
|
|
move(Address,reqAddr,10);
|
|
reqAddr.socket:=swap(Address.socket); {hi-lo}
|
|
With regs
|
|
do begin
|
|
bx:=$0002;
|
|
es:=seg(reqAddr); si:=ofs(reqAddr); di:=ofs(repNode);
|
|
IpxSpxSystemCall(regs);
|
|
ticks:=regs.cx;
|
|
result:=regs.al;
|
|
if result=0
|
|
then move(repNode,ImmAddr,6);
|
|
end;
|
|
IPXGetLocalTarget:=(result=$00);
|
|
{ resultcodes: $00 Successful; $FA No path to destination node found;
|
|
$FF IPX not initialized. }
|
|
end;
|
|
|
|
Function IPXSendPacket(Var Ecb:Tecb):boolean;
|
|
{ the ecb must be filled, before calling this function }
|
|
{ Right after this call, IPXrelinquishControl should be called Iteratively,
|
|
this allows the sending of the IPX packet. }
|
|
Var regs:Registers;
|
|
begin
|
|
regs.bx:=$0003;
|
|
regs.es:=seg(ecb);
|
|
regs.si:=ofs(ecb);
|
|
IpxSpxSystemCall(Regs);
|
|
result:=regs.al;
|
|
if result<>$FF then result:=$00;
|
|
IpxSendPacket:=(result=$00);
|
|
{ possible resultcodes: $00 Successful; $FF IPX not initialized }
|
|
end;
|
|
|
|
|
|
Function IPXInternalSendPacket(Var Ecb:Tecb):boolean;
|
|
Var regs:Registers;
|
|
begin
|
|
regs.bx:=$000F;
|
|
regs.es:=seg(ecb);
|
|
regs.si:=ofs(ecb);
|
|
IpxSpxSystemCall(Regs);
|
|
result:=regs.al;
|
|
if result<>$FF then result:=$00;
|
|
IpxInternalSendPacket:=(result=$00);
|
|
{ possible resultcodes: $00 Successful; $FF IPX not initialized }
|
|
end;
|
|
|
|
|
|
Function IPXListenForPacket(Var Ecb:Tecb):Boolean;
|
|
{ socket must be opened, ECB (partly) filled. }
|
|
Var regs:Registers;
|
|
begin
|
|
regs.bx:=$0004;
|
|
regs.es:=seg(ecb);
|
|
regs.si:=ofs(ecb);
|
|
IpxSpxSystemCall(Regs);
|
|
result:=regs.al;
|
|
if result<>$FF
|
|
then result:=$00;
|
|
IpxListenForPacket:=(result=$00);
|
|
{resultcodes: $00 Successful;
|
|
$FF Listening Socket doesn't exist OR IPX not initialized }
|
|
end;
|
|
|
|
Function IPXrelinquishControl:boolean;
|
|
Var regs:Registers;
|
|
begin
|
|
regs.bx:=$000A;
|
|
IpxSpxSystemCall(Regs);
|
|
result:=regs.al;
|
|
if result<>$FF then result:=$00;
|
|
IpxrelinquishControl:=(result=$00);
|
|
{resultcodes: $00 Successful; $FF IPX not initialized }
|
|
end;
|
|
|
|
Function IPXgetIntervalMarker(Var ticks:word):boolean;
|
|
Var regs:Registers;
|
|
begin
|
|
regs.bx:=$0008;
|
|
IpxSpxSystemCall(Regs);
|
|
ticks:=regs.ax;
|
|
result:=$00;
|
|
IPXgetIntervalMarker:=True;
|
|
end;
|
|
|
|
Function IPXcancelEvent(ECB:Tecb):boolean;
|
|
Var regs:registers;
|
|
begin
|
|
regs.bx:=$0006;
|
|
regs.es:=seg(ecb);
|
|
regs.si:=ofs(ecb);
|
|
IpxSpxSystemCall(Regs);
|
|
result:=regs.al;
|
|
IPXcancelEvent:=(result=0);
|
|
{ resultcodes: 00 Successful; F9 ECB cannot be canceled;
|
|
FF ECB not in use OR IPX not initialized. }
|
|
end;
|
|
|
|
Function IPXdisconnectFromTarget(Address:TinternetworkAddress):boolean;
|
|
VAR regs:registers;
|
|
LocAddr:TinternetworkAddress;
|
|
begin
|
|
move(Address,LocAddr,10);
|
|
LocAddr.socket:=swap(Address.socket);
|
|
regs.bx:=$000B;
|
|
regs.es:=seg(LocAddr);
|
|
regs.si:=ofs(LocAddr);
|
|
IpxSpxSystemCall(Regs);
|
|
result:=regs.al;
|
|
if result<>$FF
|
|
then result:=$00;
|
|
IPXdisconnectFromTarget:=(result=0);
|
|
{resultcodes: $00 Successful; $FF IPX not initialized }
|
|
end;
|
|
|
|
Function IPXscheduleIPXevent(ticks:word;Var ECB:Tecb):boolean;
|
|
Var regs:registers;
|
|
begin
|
|
regs.bx:=$0005;
|
|
regs.ax:=ticks;
|
|
regs.es:=seg(ECB);
|
|
regs.si:=ofs(ECB);
|
|
IpxSpxSystemCall(Regs);
|
|
if result<>$FF
|
|
then result:=$00;
|
|
IPXscheduleIPXevent:=(result=0);
|
|
{resulcodes: 00 successful; FF IPX not initialized }
|
|
end;
|
|
|
|
Function IPXscheduleSpecialEvent(ticks:word;Var ECB:Tecb):boolean;
|
|
Var regs:registers;
|
|
begin
|
|
regs.bx:=$0007;
|
|
regs.ax:=ticks;
|
|
regs.es:=seg(ECB);
|
|
regs.si:=ofs(ECB);
|
|
IpxSpxSystemCall(Regs);
|
|
if result<>$FF
|
|
then result:=$00;
|
|
IPXscheduleSpecialEvent:=(result=0);
|
|
{resulcodes: 00 successful; FF IPX not initialized }
|
|
end;
|
|
|
|
{************** Secondary Procedures ***************************************}
|
|
|
|
Procedure IPXSetupListenECB(ESRptr:Pointer;ReceiveSocket:word;
|
|
BufPtr:Pointer;BufSize:word;
|
|
{out:} Var IpxHdr:TipxHeader; Var ecb:Tecb);
|
|
{ Clears IPXheader and ECB, sets values of the required fields within
|
|
the ecb and IPX header. }
|
|
{ ECB: ESR adress field, socket number, fragment count, frag.descriptor fields }
|
|
begin
|
|
FillChar(ecb,SizeOf(Tecb),#0);
|
|
FillChar(ipxHdr,SizeOF(TipxHeader),#0);
|
|
WITH ECB
|
|
do begin
|
|
if ESRptr<>NIL
|
|
then ESRaddress:=ESRptr;
|
|
Fragmentcount:=2;
|
|
socketNumber:=swap(ReceiveSocket); {hi-lo}
|
|
|
|
Fragment[1].Address:=@ipxHdr;
|
|
Fragment[2].Address:=BufPtr;
|
|
Fragment[1].size:=SizeOf(Tipxheader);
|
|
Fragment[2].size:=BufSize;
|
|
end;
|
|
end;
|
|
|
|
Procedure IPXsetupSendECB(ESRptr:pointer; SourceSocket:word;
|
|
DestAddr:TinterNetworkAddress;
|
|
BufPtr:pointer; BufSize:word;
|
|
{out:} Var IpxHdr:TipxHeader; Var ecb:Tecb);
|
|
{ Clears IPXheader and ECB, sets values of the required fields within
|
|
the ecb and IPX header. }
|
|
Var ImmAddr:TnodeAddress;
|
|
Ticks:word;
|
|
begin
|
|
fillchar(ipxHdr,SizeOf(TipxHeader),#0);
|
|
with ipxhdr
|
|
do begin
|
|
PacketType:=IPX_PACKET_TYPE;
|
|
Move(DestAddr,Destination,10);
|
|
destination.socket:=swap(DestAddr.socket); {hi-lo}
|
|
end;
|
|
IPXGetLocalTarget(DestAddr,ImmAddr,Ticks);
|
|
fillchar(ecb,sizeOf(ecb),#0);
|
|
With ecb
|
|
do begin
|
|
if ESRptr<>NIL
|
|
then ESRaddress:=ESRptr;
|
|
socketNumber:=swap(SourceSocket); {hi-lo}
|
|
Move(ImmAddr,ImmediateAddress,6);
|
|
FragmentCount:=2;
|
|
fragment[1].Address:=@ipxhdr;
|
|
fragment[1].size:=SizeOf(TipxHeader);
|
|
fragment[2].Address:=BufPtr;
|
|
fragment[2].size:=BufSize;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
end.
|