1. Re: IPX network]
--------------7DB87CB4BA3FF8E61801BDDA
argh... patrat has his replyto field set to himself *specifically*
so this message i intended for the listserv was sent to
him only, so, thomas, you'll have 2 copies of this msg
------------begin intended post
> Thomas Parslow wrote:
> How can I get my programs to communicate over a IPX or TCP/IP network?
> If at all possible I would like to do this in Euphoria for DOS
wellllll...
i have 2 different versions of ipx units for dos written in
pascal/asm (actually, i have several units... many even... for
all sorts of ipx/novell/netware/lan/netbios/decnet and file
record locking and NFS stuff and other wierd stuff) that you
or anyone else can take a crack at converting to EU...
these two units, in particular, seemed like the
easiest/best written of the stuff i've got for ipx...
anyways, like i said, anyone wants to take a shot at this
is *more* than welcome to... Rob? Pete? Irv? Dave? Ralf? Jiri?
Carl? Art? (who'd i ferget?)
I had sat down to start converting these units since there
*is* such a high demand for network EU (*pokes rob*) support,
not just tcpip, but file/record locking, ipx, and stuff
for *dos* EU... (i tried to get EUsock to work with dos32lib
and it just wouldnt shoehorn... spent *hours* at it...
dave? jesus? {yeah i fergot you :) greg too :|) but my
pascal is just too rusty, and trueEU sidetracked me :)
so... any takers? comments?
attached are the 2 units: ipx.pas and ipxunit.pas
funfun! --Hawke'
--------------7DB87CB4BA3FF8E61801BDDA
name="Ipx.pas"
Content-Disposition: inline;
filename="Ipx.pas"
{
From: greg.miller at shivasys.com
>Could you tell me where to get the ipx units?
I'll post the IPX source here again. (Perhaps this should go into
the FAQ? :) There seems to be a big demand for this unit.
{ ipx - IPX communication protocol primitives. }
unit ipx;
interface uses DOS;
type
MessageStr = String;
IPX_REGS = Registers;
Byte4 = array[0..3] of byte;
NetworkNumber = Byte4;
NetworkNode = array[0..5] of byte;
ECB = record
link_address : Pointer;
event_service_routine : Pointer;
in_use : byte;
completion_code : byte;
socket_number : word;
ipx_workspace : Byte4;
driver_workspace : array[0..11] of
byte;
immediate_address : NetworkNode;
fragment_count : word;
fragment : array [0..1] of
record
address :
pointer;
length :
word;
end;
end;
IPXHEADER = record
checksum : word;
length : word;
transport_control : byte;
packet_type : byte;
dest_network_number : NetworkNumber;
dest_network_node : NetworkNode;
dest_network_socket : word;
source_network_number : NetworkNumber;
source_network_node : NetworkNode;
source_network_socket : word;
end;
{ ZeroEcb - store zeros in all ecb fields.
Pre: e is an ECB.
Post: e is fully zeroed. }
procedure ZeroEcb( var e : ECB );
{ ZeroHeader - Store zeros in all header fields.
Pre: h is an IPXHEADER.
Post: h is fulled zeroed. }
procedure ZeroHeader( var h : IPXHEADER );
{ Get1stConnectionNumber - Return first connection number for user name
Pre: username is valid Novell user name
Post: Returns first connection number username is logged on or
0 if not logged on. }
function Get1stConnectionNumber( username : string ) : word;
{ GetInternetAddress - Get the network:node address for a connection.
Pre: connection_number is valid for a logged on user.
Post: network_number is valid number of network.
physical_node is valid station node.
}
function GetInternetAddress( connection_number : byte;
var network_number : NetworkNumber; {hi:lo}
var physical_node : NetworkNode ) : integer;
{ IPXSPXNotLoaded - Executed when ipxspx called but not loaded.
Pre: IPX not loaded.
Post: Execution aborted. }
procedure IPXSPXNotLoaded(var NovRegs : Registers);
{ IPXInstalled - Determine if IPX is installed on workstation.
Pre: Either IPX is or is not installed.
Post: If IPX installed initialize global IPXLocation to IPX
entry
point and return TRUE.
Otherwise initialize global IPXLocation to
IPXSPXNotLoaded
entry point and return FALSE. }
function IPXInstalled : Boolean;
{ IPXSPX - Call ipxspx at address in IPXLocation.
Pre: IPXInstalled has been called.
IPX is installed and NovRegs assigned IPX or SPX function
and parameter values. Not checking is done.
Post: IPX or SPX function is called.
NovRegs assigned by call. }
procedure IPXSPX(var NovRegs:Registers);
{ IPXRelinquishControl - Give ipx momentary control of CPU.
Pre: IPX loaded.
Post: IPX execution done. }
procedure IPXRelinquishControl;
{ IPXCancelEvent - Cancels pending event associated with ECB.
Pre: e is valid ECB.
Post: 00 - Success.
F9 - ECB cannot be canceled.
FF - ECB not in use. }
function IPXCancelEvent( var e : ECB ) : byte;
{ IPXDisconnectFromTarget - Notify listening node that communications
woth
specified socket are being terminated.
Pre: number:node:socket are valid.
Post: Node notified. }
procedure IPXDisconnectFromTarget( network_number : NetWorkNumber;
network_node : NetWorkNode;
network_socket : word );
{ IPXScheduleEvent - Schedule processing of ECB after timer ticks.
Pre: ticks is number of 18.2 per second ticks.
e is a valid ECB at the time processing occurs.
Post: e is processed after timer ticks. }
procedure IPXScheduleEvent( ticks : word; var e : ECB );
{ IPXOpenSocket - Open an application socket.
Pre: socket to use (BBA-7FFF). All assumed short-lived.
Post: 00 - Success.
FE - Socket table full.
FF - Socket already open. }
function IPXOpenSocket( socket : word ) : byte;
{ IPXCloseSocket - Close socket. No harm if already closed.
Pre: socket to close.
Post: socket is closed. }
procedure IPXCloseSocket( socket : word );
{ IPXListenForPacket - Submit an ECB for use when packet received. Must
have ECB available when packet received by IPX.
Pre: e storage is available when ECB processed by IPX.
e.socket_number opened.
e.event_svc-routine valid routine or NULL.
e.fragment_count normally 2.
e.fragment[0].address to IPX Header buffer.
e.fragment[0].length = 30.
e.fragment[1].address to data area <=546 bytes long.
e.fragment[1].length = length of data area.
Post: If socket opened, e is added to pool and return TRUE.
Otherwise return FALSE. }
function IPXListenForPacket( var e : ECB ) : Boolean;
{ IPXSendPacket - Send packet using given ECB.
Pre: e storage is available when ECB processed by IPX.
e.socket_number opened.
e.event_svc-routine valid routine or NULL.
e.immediate_address is address of destination
workstation.
e.fragment_count normally 2.
e.fragment[0].address to IPX Header buffer.
e.fragment[0].length = 30.
e.fragment[1].address to data area <=546 bytes long.
e.fragment[1].length = length of data area.
Post: e.completion_code of: 00 - Message sent.
FC - Event canceled.
FD - Bad packet. }
{ IPXGetLocalTarget - Get the bridge address (or node if not bridged)
for
network:node address.
Pre: dest_network - network number of workstation.
dest_node - network node of workstation.
dest_socket - network socket of workstation.
Post: bridge_address is routing information used by
IPXSendPacket.
Return 00 - Success.
FA - No path to destination. }
function IPXGetLocalTarget( var dest_network : NetworkNumber;
var dest_node : NetworkNode;
dest_socket : word;
var bridge_address : NetworkNode ) : byte;
{ IPXGetIntervalMarker - Return time marker measured in 18.2/sec ticks.
Pre: None.
Post: Return time marker. }
function IPXGetIntervalMarker : word;
{ IPXSend - Send a packet to network:node:socket using send_ecb and
send_header. send_ecb/send_header should be defined outside of
IPXSend as both may be in use by ipx after IPXSend completes,
releasing any local variables.
Pre: dest_network - network number of destination.
dest_node - network node of destination.
dest_socket - socket of destination.
packet_ptr - pointer to send packet.
packet_len - length of send packet
send_ecb - ECB to use for sending.
send_header - IPXHEADER to use for sending.
send_socket - socket to use for sending.
Post: If destination reachable, packet is sent. }
procedure IPXSend( var dest_network : NetworkNumber;
var dest_node : NetworkNode;
dest_socket : word; { hi:lo }
packet_ptr : Pointer;
packet_len : integer;
var send_ecb : ECB;
var send_header : IPXHEADER;
send_socket : word );
{ IPXReceive - Submit an ECB/header and storage buffer for a received
message.
Pre: receive_ecb - ECB allocated for recieving.
receive_header - IPXHEADER allocated for receiving.
receive_socket - socket to receive on.
Post: message - area allocated for received message
holds data.
message_size - size of message area in bytes.
}
procedure IPXReceive( var receive_ecb : ECB;
var receive_header : IPXHEADER;
receive_socket : word;
message : Pointer;
message_size : word );
{ IPXReceivedFrame - Returns TRUE if message frame received in ECB.
Pre: receive_ecb - ECB allocated for recieving.
Post: Returns TRUE if message frame received in ECB.
}
function IPXReceivedFrame( receive_ecb : ECB ) : Boolean;
{_________________________________________________________________________}
implementation
type
REQUESTBUFFER = record
dest_network_number : NetWorkNumber;
dest_network_node : NetworkNode;
dest_network_socket : word;
end;
REPLYBUFFER = record
node_address : NetworkNode;
end;
var IPXLocation : Pointer; { Address of ipx }
{ abort - Display message and halt.
Pre: message is a string. }
procedure abort( message : string );
begin
writeln( message );
Halt(1);
end;
{$F+}
{ Get1stConnectionNumber - Return first connection number for user name
Pre: username is valid Novell user name
Post: Returns first connection number username is logged on or
0 if not logged on. }
function Get1stConnectionNumber( username : string ) : word;
var
NovRegs : Registers;
Request : record
len : Word;
buffer_type : Byte;
object_type : Word;
name : string[47];
end;
Reply : record
len : Word;
number_connections : byte;
connection_num : array[0..99] of byte;
end;
begin
with Request do begin
len := 51;
buffer_type := $15;
object_type := $0100;
name := username;
end;
Reply.len := 101; { Maximum number of user connections }
with NovRegs do begin
AH := $E3;
DS := Seg(Request); {DS:SI points to request}
SI := Ofs(Request);
ES := Seg(Reply); {ES:DI points to reply}
DI := Ofs(Reply);
MsDos(NovRegs);
if (Al <> 0) or (Reply.number_connections = 0)
then Get1stConnectionNumber := 0
else Get1stConnectionNumber := Reply.connection_num[0];
end;
end;
{ GetInternetAddress - Get the network:node address for a connection.
Pre: connection_number is valid for a logged on user.
Post: network_number is valid number of network.
physical_node is valid station node.
}
function GetInternetAddress( connection_number : byte;
var network_number : NetworkNumber; {hi:lo}
var physical_node : NetworkNode ) : integer;
var
NovRegs : Registers;
Request : record
len : word;
buffer_type : byte;
connection_number : byte;
end;
Reply : record
len : word;
network_number : NetworkNumber;
physical_node : NetworkNode;
server_socket : word;
end;
begin
with Request do begin
len := 2;
buffer_type := $13;
end;
Request.connection_number := connection_number;
Reply.len := 12;
with NovRegs do begin
AH := $E3;
DS := Seg(Request); {DS:SI points to request}
SI := Ofs(Request);
ES := Seg(Reply); {ES:DI points to reply}
DI := Ofs(Reply);
MsDos(NovRegs);
Ah := 0;
GetInternetAddress := Ax;
end;
network_number := Reply.network_number;
physical_node := Reply.physical_node;
end;
{ IPXSPXNotLoaded - Executed when ipxspx called but not loaded.
Pre: IPX not loaded.
Post: Execution aborted. }
procedure IPXSPXNotLoaded(var NovRegs : Registers);
begin
abort('IPX not loaded');
end;
{ ZeroEcb - store zeros in all ecb fields.
Pre: e is an ECB.
Post: e is fully zeroed. }
procedure ZeroEcb( var e : ECB );
var i : byte;
begin
with e do begin
link_address := Ptr(0,0);
event_service_routine := Ptr(0,0);
in_use := 0;
completion_code := 0;
socket_number := 0;
for i := 0 to 3 do
ipx_workspace[i] := 0;
for i := 0 to 11 do
driver_workspace[i] := 0;
for i := 0 to 5 do
immediate_address[i] := 0;
fragment_count := 0;
for i := 0 to 1 do begin
fragment[i].address := Ptr(0,0);
fragment[i].length := 0;
end;
end;
end;
{ ZeroHeader - Store zeros in all header fields.
Pre: h is an IPXHEADER.
Post: h is fulled zeroed. }
procedure ZeroHeader( var h : IPXHEADER );
var i : byte;
begin
with h do begin
checksum := 0;
length := 0;
transport_control := 0;
packet_type := 0;
for i := 0 to 3 do
dest_network_number[i] := 0;
for i := 0 to 5 do
dest_network_node[i] := 0;
dest_network_socket := 0;
for i := 0 to 3 do
source_network_number[i] := 0;
for i := 0 to 5 do
source_network_node[i] := 0;
source_network_socket := 0;
end;
end;
{ IPXInstalled - Determine if IPX is installed on workstation.
Pre: Either IPX is or is not installed.
Post: If IPX installed initialize global IPXLocation to IPX
entry
point and return TRUE.
Otherwise initialize global IPXLocation to
IPXSPXNotLoaded
entry point and return FALSE. }
function IPXInstalled : Boolean;
var NovRegs : IPX_REGS;
begin
with NovRegs do begin
AX := $7A00; {func 7Ah of int 2Fh is used to detect IPX}
Intr($2F,NovRegs);
if AL = $FF then begin {if AL is FFh then IPX is loaded and
available}
IPXInstalled := TRUE;
IPXLocation := Ptr(ES,DI); {pointer to IPX entry point in ES:DI}
end
else begin
IPXInstalled := FALSE; {no IPX installed}
IPXLocation := @IPXSPXNotLoaded;
end;
end;
end;
{ IPXSPX - Call ipxspx at address in IPXLocation.
Pre: IPXInstalled has been called.
IPX is installed and NovRegs assigned IPX or SPX
function
and parameter values. Not checking is done.
Post: IPX or SPX function is called.
NovRegs assigned by call. }
procedure IPXSPX(var NovRegs:Registers);
var Ax_, Bx_, Dx_, Di_, Si_, Es_ : word;
begin
with NovRegs do begin { Assign simple variables record field
values }
Ax_ := Ax;
Bx_ := Bx;
Dx_ := Dx;
Di_ := Di;
Si_ := Si;
Es_ := Es;
end;
asm { Assembler instructions. }
mov Ax, Ax_ { Initialize CPU registers.}
mov Bx, Bx_
mov Dx, Dx_
mov Di, Di_
mov Si, Si_
mov Es, Es_
push Bp
call dword ptr IPXLocation { Call IPX via address at
IPXLocation. }
pop Bp
mov Ax_, Ax
mov Dx_, Dx
end;
NovRegs.Ax := Ax_; { Return register values to caller }
NovRegs.Dx := Dx_;
end;
{ IPXRelinquishControl - Give ipx momentary control of CPU.
Pre: IPX loaded.
Post: IPX execution done. }
procedure IPXRelinquishControl;
var NovRegs : IPX_REGS;
begin
with NovRegs do begin
Bx := $0a;
IPXSPX(NovRegs);
end
end;
{ IPXCancelEvent - Cancels pending event associated with ECB.
Pre: e is valid ECB.
Post: 00 - Success.
F9 - ECB cannot be canceled.
FF - ECB not in use. }
function IPXCancelEvent( var e : ECB ) : byte;
var NovRegs : IPX_REGS;
begin
with NovRegs do begin
Bx := $06;
ES := Seg(e); {ES:SI points to ecb}
SI := Ofs(e);
IPXSPX(NovRegs);
IPXCancelEvent := AL;
end
end;
{ IPXDisconnectFromTarget - Notify listening node that communications
woth
specified socket are being terminated.
Pre: number:node:socket are valid.
Post: Node notified. }
procedure IPXDisconnectFromTarget( network_number : NetWorkNumber;
network_node : NetWorkNode;
network_socket : word );
var NovRegs : IPX_REGS;
request_buffer : REQUESTBUFFER;
begin
with request_buffer do begin
dest_network_number := network_number;
dest_network_node := network_node;
dest_network_socket := network_socket;
end;
with NovRegs do begin
Bx := $0B;
ES := Seg(request_buffer); {ES:SI points to ecb}
SI := Ofs(request_buffer);
IPXSPX(NovRegs);
end
end;
{ IPXScheduleEvent - Schedule processing of ECB after timer ticks.
Pre: ticks is number of 18.2 per second ticks.
e is a valid ECB at the time processing occurs.
Post: e is processed after timer ticks. }
procedure IPXScheduleEvent( ticks : word; var e : ECB );
var NovRegs : IPX_REGS;
begin
with NovRegs do begin
Bx := $05;
Ax := ticks;
ES := Seg(e);
SI := Ofs(e);
IPXSPX(NovRegs);
end;
end;
{ IPXOpenSocket - Open an application socket.
Pre: socket to use (BBA-7FFF). All assumed short-lived.
Post: 00 - Success.
FE - Socket table full.
FF - Socket already open. }
function IPXOpenSocket( socket : word ) : byte;
var NovRegs : IPX_REGS;
begin
with NovRegs do begin
Dx := socket;
Bx := 0;
Al := 0;
IPXSPX(NovRegs);
Ah := 0;
IPXOpenSocket := Ax;
end
end;
{ IPXCloseSocket - Close socket. No harm if already closed.
Pre: socket to close.
Post: socket is closed. }
procedure IPXCloseSocket( socket : word );
var NovRegs : IPX_REGS;
begin
with NovRegs do begin
Dx := socket;
Bx := $0001;
IPXSPX(NovRegs);
end
end;
{ IPXListenForPacket - Submit an ECB for use when packet received. Must
have ECB available when packet received by IPX.
Pre: e storage is available when ECB processed by IPX.
e.socket_number opened.
e.event_svc-routine valid routine or NULL.
e.fragment_count normally 2.
e.fragment[0].address to IPX Header buffer.
e.fragment[0].length = 30.
e.fragment[1].address to data area <=546 bytes long.
e.fragment[1].length = length of data area.
Post: If socket opened, e is added to pool and return TRUE.
Otherwise return FALSE. }
function IPXListenForPacket( var e : ECB ) : Boolean;
var NovRegs : IPX_REGS;
begin
with NovRegs do begin
BX := $0004;
ES := Seg(e); {ES:SI points to ecb}
SI := Ofs(e);
IPXSPX(NovRegs);
IPXListenForPacket := Al = 00;
end
end;
{ IPXSendPacket - Send packet using given ECB.
Pre: e storage is available when ECB processed by IPX.
e.socket_number opened.
e.event_svc-routine valid routine or NULL.
e.immediate_address is address of destination
workstation.
e.fragment_count normally 2.
e.fragment[0].address to IPX Header buffer.
e.fragment[0].length = 30.
e.fragment[1].address to data area <=546 bytes long.
e.fragment[1].length = length of data area.
Post: e.completion_code of: 00 - Message sent.
FC - Event canceled.
FD - Bad packet. }
procedure IPXSendPacket( var e: ECB );
var NovRegs : IPX_REGS;
begin
with NovRegs do begin
ES := Seg(e); {ES:SI points to ecb}
SI := Ofs(e);
BX := $0003;
IPXSPX(NovRegs);
end
end;
{ IPXGetLocalTarget - Get the bridge address (or node if not bridged)
for
network:node address.
Pre: dest_network - network number of workstation.
dest_node - network node of workstation.
dest_socket - network socket of workstation.
Post: bridge_address is routing information used by
IPXSendPacket.
Return 00 - Success.
FA - No path to destination. }
function IPXGetLocalTarget( var dest_network : NetworkNumber;
var dest_node : NetworkNode;
dest_socket : word;
var bridge_address : NetworkNode ) : byte;
var
NovRegs : Registers;
Request : record
network_number : NetworkNumber;
physical_node : NetworkNode;
socket : word;
end;
Reply : record
local_target : NetworkNode;
end;
begin
with Request do begin
network_number := dest_network;
physical_node := dest_node;
socket := dest_socket;
end;
with NovRegs do begin
Es := Seg(Request);
Si := Ofs(Request);
Di := Ofs(Reply);
Bx := $0002;
IPXSPX(NovRegs);
Ah := 0;
IPXGetLocalTarget := Ax;
bridge_address := Reply.local_target;
end
end;
{ IPXGetIntervalMarker - Return time marker measured in 18.2/sec ticks.
Pre: None.
Post: Return time marker. }
function IPXGetIntervalMarker : word;
var
NovRegs : Registers;
begin
with NovRegs do begin
Bx := $0008;
IPXSPX(NovRegs);
IPXGetIntervalMarker := Ax;
end
end;
{ IPXSend - Send a packet to network:node:socket using send_ecb and
send_header. send_ecb/send_header should be defined outside
of
IPXSend as both may be in use by ipx after IPXSend
completes,
releasing any local variables.
Pre: dest_network - network number of destination.
dest_node - network node of destination.
dest_socket - socket of destination.
packet_ptr - pointer to send packet.
packet_len - length of send packet
send_ecb - ECB to use for sending.
send_header - IPXHEADER to use for sending.
send_socket - socket to use for sending.
Post: If destination reachable, packet is sent. }
procedure IPXSend( var dest_network : NetworkNumber;
var dest_node : NetworkNode;
dest_socket : word; { hi:lo }
packet_ptr : Pointer;
packet_len : integer;
var send_ecb : ECB;
var send_header : IPXHEADER;
send_socket : word );
begin
ZeroEcb(send_ecb);
ZeroHeader(send_header);
send_ecb.socket_number := send_socket; { Socket used for sending }
if IPXGetLocalTarget( dest_network,
dest_node,
dest_socket,
send_ecb.immediate_address ) = 0
then begin
with send_ecb do begin
fragment_count := 2;
fragment[0].address := @send_header;
fragment[0].length := sizeof(IPXHEADER);
fragment[1].address := packet_ptr;
fragment[1].length := packet_len;
end;
with send_header do begin
packet_type := 4;
dest_network_number := dest_network;
dest_network_node := dest_node;
dest_network_socket := dest_socket;
end;
IPXSendPacket( send_ecb );
end;
end;
{ IPXReceive - Submit an ECB/header and storage buffer for a received
message.
Pre: receive_ecb - ECB allocated for recieving.
receive_header - IPXHEADER allocated for receiving.
receive_socket - socket to receive on.
Post: message - area allocated for received message
holds data.
message_size - size of message area in bytes.
}
procedure IPXReceive( var receive_ecb : ECB;
var receive_header : IPXHEADER;
receive_socket : word;
message : Pointer;
message_size : word );
begin
ZeroEcb(receive_ecb);
ZeroHeader(receive_header);
with receive_ecb do begin
socket_number := receive_socket; { Socket used for receiving }
fragment_count := 2;
fragment[0].address := @receive_header;
fragment[0].length := sizeof(IPXHEADER);
fragment[1].address := message;
fragment[1].length := message_size;
end;
if not IPXListenForPacket( receive_ecb ) then
abort('IPX Error - Failure initializing.');
IPXRelinquishControl; { Give ipx opportunity to process
}
end;
{ IPXReceivedFrame - Returns TRUE if message frame received in ECB.
Pre: receive_ecb - ECB allocated for recieving.
Post: Returns TRUE if message frame received in ECB.
}
function IPXReceivedFrame( receive_ecb : ECB ) : Boolean;
begin
IPXReceivedFrame := (receive_ecb.completion_code = 0) and
(receive_ecb.in_use = 0);
end;
begin
end.
--------------7DB87CB4BA3FF8E61801BDDA
name="Ipxunit.pas"
Content-Disposition: inline;
filename="Ipxunit.pas"
Unit IpxUnit;
Interface
uses dos;
const
IPX_PACKET_TYPE = 4;
type
NetWrkAdr = record
NetworkNumber : array [1..4] of byte;
NodeAddress : array [1..6] of byte;
end;
IpxHeader = record
CheckSum : word;
Len : word;
TransportControl : byte;
PacketType : byte;
Destination : NetWrkAdr;
DestinationSocket : word;
Source : NetWrkAdr;
SourceSocket : word;
end;
ConNbrArr = record
Len : word;
Count : byte;
Connections : array [1..250] of byte;
end;
ftype = record
Adr : pointer;
Len : word;
end;
Ecb = record
LinkAddress : pointer;
EventServiceRoutine: pointer;
StatusFlag : byte;
CompletionCode : byte;
SocketNumber : word;
WorkSpace : array [1..4] of byte;
DriverWorkSpace : array [1..12] of byte;
ImmediateAddress : array [1..6] of byte;
FragmentCount : word;
FragmentDescriptor : array [1..2] of ftype;
end;
ConnInfo = record
Len : word;
ObjectID : array [1..4] of byte;
ObjectType : word;
ObjectName : array [1..48] of byte;
LoginTime : array [1..7] of byte;
Reserved : word;
end;
NetType = array [1..4] of byte;
NodType = array [1..6] of byte;
var
regs : registers;
ipxrutofs,
ipxrutseg : word;
{-----------------------------------------------------------------------------}
function LeadingZero(w:word) : String;
function Time : String;
procedure WriteHexByte(b : byte);
function IpxPresent : boolean;
procedure IpxServicesCall;
function IpxCreateSocket (Socket : word) : boolean;
function LocalConnectionNumber : byte;
procedure IpxDeleteSocket (Socket : word);
procedure GetInternetAddress (ConnectionNbr : byte; var NetNod : NetWrkAdr);
procedure UserInfo (ConnectionNumber: byte; var ConnInfoRec : ConnInfo);
procedure GetConnections (UserName: string; var ConNbrRec : ConNbrArr);
procedure GetLocalTarget(DestNet : NetWrkAdr;
DestSock : word; var LocalTarget : NodType );
procedure SendMessage(ConnectionNumber : byte; Message : String);
Procedure IpxSendPacket(var SendEcb : Ecb);
Procedure IpxReadPacket(var ReadEcb : Ecb);
Implementation
{----------------------------------------------------------------------------}
function LeadingZero;
var
s : String;
begin
Str(w:0,s);
if Length(s) = 1 then
s := '0' + s;
LeadingZero := s;
end;
{----------------------------------------------------------------------------}
function Time;
var
h, m, s, hund : Word;
begin
GetTime(h,m,s,hund);
Time:=LeadingZero(h)+':'+LeadingZero(m)+':'+LeadingZero(s);
end;
{----------------------------------------------------------------------------}
procedure WriteHexByte;
const
hexChars : array [0..$F] of Char =
'0123456789ABCDEF';
begin
Write(hexChars[b shr 4],
hexChars[b and $F]);
end;
{----------------------------------------------------------------------------}
function IpxPresent;
const
MULTIPLEXER = $2F;
IPXINSTALLED = $FF;
begin
regs.ax:=$7A00;
intr(MULTIPLEXER,regs);
if (regs.al = IPXINSTALLED) then IpxPresent:=TRUE
else IpxPresent:=FALSE;
end;
{----------------------------------------------------------------------------}
procedure IpxServicesCall;
begin
intr($7a,regs);
end;
{----------------------------------------------------------------------------}
function IpxCreateSocket;
const
IPX_CreateSocket = $00;
PermanentSocket = $FF;
TemporarySocket = $00;
var
SwapSocket : word;
begin
SwapSocket:=swap(Socket);
regs.al:=TemporarySocket;
regs.bx:=IPX_CreateSocket;
regs.dx:=SwapSocket;
IpxServicesCall;
if (regs.al = $00) then IpxCreateSocket:=TRUE
else IpxCreateSocket:=FALSE;
{0FEh Full Socket Table
0FFh Socket Already Opened}
end;
{----------------------------------------------------------------------------}
procedure IpxDeleteSocket;
const
IPX_DeleteSocket = $01;
var
SwapSocket : word;
begin
SwapSocket:=swap(Socket);
regs.bx:=IPX_DeleteSocket;
regs.dx:=SwapSocket;
IpxServicesCall;
end;
{----------------------------------------------------------------------------}
function LocalConnectionNumber;
const
GET_CONNECTION_NUMBER = $DC;
begin
regs.ah:=GET_CONNECTION_NUMBER;
regs.al:=$00;
msdos(regs);
LocalConnectionNumber:=regs.al;
end;
{----------------------------------------------------------------------------}
procedure GetInternetAddress;
const
GET_INTERNET_ADDRESS = $13;
NETWARE_SERVICE_E3 = $E3;
var
ReqBlk : record
Len : word;
ReqType : byte;
ConnNbr : byte;
end;
ResBlk : record
Len : word;
NetNod : NetWrkAdr;
SrvSocket : word;
end;
begin
with ReqBlk do
begin
Len:=sizeof(ReqBlk) - sizeof(Len);
ReqType:=GET_INTERNET_ADDRESS;
ConnNbr:=ConnectionNbr;
end;
with ResBlk do Len:=sizeof(ResBlk) - sizeof(Len);
regs.ah:=NETWARE_SERVICE_E3;
regs.ds:=seg(ReqBlk); regs.si:=ofs(ReqBlk);
regs.es:=seg(ResBlk); regs.di:=ofs(ResBlk);
msdos(regs);
if regs.al <> $00 then writeln('Error GETINTERNETADDRESS...')
else
begin
NetNod.NetworkNumber:=ResBlk.NetNod.NetworkNumber;
NetNod.NodeAddress:= ResBlk.NetNod.NodeAddress;
end;
end;
{----------------------------------------------------------------------------}
procedure UserInfo;
const
GET_CONNECTION_INFORMATION = $16;
NETWARE_SERVICE_E3 = $E3;
var
ReqBlk : record
Len : word;
ReqType : byte;
ConnNbr : byte;
end;
begin
with ReqBlk do
begin
Len :=sizeof(ReqBlk) - sizeof(Len);
ReqType:=GET_CONNECTION_INFORMATION;
ConnNbr:=ConnectionNumber;
end;
with ConnInfoRec do Len:=sizeof(ConnInfoRec) - sizeof(Len);
regs.ah:=NETWARE_SERVICE_E3;
regs.ds:=seg(ReqBlk); regs.si:=ofs(ReqBlk);
regs.es:=seg(ConnInfoRec); regs.di:=ofs(ConnInfoRec);
msdos(regs);
end;
{----------------------------------------------------------------------------}
procedure GetConnections;
const
GET_OBJECT_CONNECTION_NUMBERS= $15;
USER_BINDERY_OBJECT_TYPE = $0001;
NETWARE_SERVICE_E3 = $E3;
var
ReqBlk : record
Len : word;
RequestType : byte;
ObjectType : word;
NameLength : byte;
Name : array [1..48] of byte;
end;
swapbind : word;
i : integer;
begin
swapbind:=swap(USER_BINDERY_OBJECT_TYPE);
with ReqBlk do
begin
Len:=sizeof(ReqBlk) - sizeof(Len);
RequestType:=GET_OBJECT_CONNECTION_NUMBERS;
ObjectType:=SwapBind;
end;
ReqBlk.NameLength:=Length(UserName);
for i:=1 to ReqBlk.NameLength do ReqBlk.Name[i]:=ord(UserName[i]);
with ConNbrRec do Len:=sizeof(ConNbrRec) - sizeof(Len);
regs.ah:=NETWARE_SERVICE_E3;
regs.ds:=seg(ReqBlk); regs.si:=ofs(ReqBlk);
regs.es:=seg(ConNbrRec); regs.di:=ofs(ConNbrRec);
msdos(regs);
if regs.al <> 0 then ConNbrRec.Count:=0;
end;
{----------------------------------------------------------------------------}
procedure GetLocalTarget;
const
IPX_GetLocalTarget = $02;
var
ReqBlk : record
Dnetwork : NetWrkAdr;
DSocket : word;
end;
ResBlk : record
Ltarget : NodType;
end;
swapsocket : word;
begin
swapsocket:=swap(DestSock);
ReqBlk.Dnetwork:=DestNet;
ReqBlk.DSocket :=swapsocket;
regs.bx:=IPX_GetLocalTarget;
regs.es:=seg(ReqBlk);
regs.si:=ofs(ReqBlk);
regs.di:=ofs(ResBlk);
IpxServicesCall;
if regs.al = $00 then LocalTarget:=ResBlk.Ltarget;
{0FAh No path to Destination}
end;
{----------------------------------------------------------------------------}
procedure SendMessage;
const
USER_BINDERY_OBJECT_TYPE = $0001;
NETWARE_SERVICE_E1 = $E1;
var
ReqBlk : record
Len : word;
Bindery : word;
ConnNbr : byte;
Mlen : byte;
Mens : array [1..45] of byte;
end;
ResBlk : record
Len : word;
Filler : array [1..100] of byte;
end;
i : integer;
begin
with ReqBlk do
begin
Bindery:=swap(USER_BINDERY_OBJECT_TYPE);
ConnNbr:=ConnectionNumber;
Mlen:=Length(Message);
Len:=Mlen + 4;
for i:=1 to Mlen do mens[i]:=ord(message[i]);
end;
ResBlk.Len:=$6400;
regs.ah:=NETWARE_SERVICE_E1;
regs.ds:=seg(ReqBlk); regs.si:=ofs(ReqBlk);
regs.es:=seg(ResBlk); regs.di:=ofs(ResBlk);
msdos(regs);
end;
{----------------------------------------------------------------------------}
Procedure IpxSendPacket;
const
IPX_SendPacket = $03;
begin
regs.bx:=IPX_SendPacket;
regs.es:=Seg(SendEcb);
regs.si:=Ofs(SendEcb);
IpxServicesCall;
while (SendEcb.StatusFlag <> 0) do ;
end;
{----------------------------------------------------------------------------}
Procedure IpxReadPacket;
const
IPX_ReceivePacket = $04;
begin
regs.bx:=IPX_ReceivePacket;
regs.es:=Seg(ReadEcb);
regs.si:=Ofs(ReadEcb);
IpxServicesCall;
if regs.al <> $00 then
begin
writeln('Error Read Packet ');
WriteHexByte(Regs.al);
end;
{0ffh NonExistant socket}
end;
{----------------------------------------------------------------------------}
{----------------------------------------------------------------------------}
begin
end.
--------------7DB87CB4BA3FF8E61801BDDA--