1456 lines
48 KiB
Plaintext
1456 lines
48 KiB
Plaintext
{$X+,B-,V-,S-} {essential compiler directives}
|
|
|
|
UNIT nwConn;
|
|
|
|
{ nwConn unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R. Spronk }
|
|
{ Includes modifications to Attach/Detach by H. Jelonneck }
|
|
|
|
INTERFACE
|
|
|
|
{ Primary Functions: Interrupt: comments:
|
|
|
|
Connection Services
|
|
-------------------
|
|
|
|
* AttachToFileServer (F100)
|
|
* AttachToFileServerWithAddress (F100)
|
|
* DetachFromFileServer (F101)
|
|
. EnterLoginArea (F217/0A)
|
|
* GetConnectionInformation (F217/16)
|
|
* GetConnectionNumber (DC..)
|
|
* GetInternetAddress (F217/13)
|
|
* GetObjectConnectionNumbers (F217/15)
|
|
* GetWorkstationNodeAddress (EE..)
|
|
* LoginToFileserver (F217/14) UNencrypted
|
|
* LoginEncrToFileserver (F217/18) encrypted
|
|
* Logout (F219)
|
|
* LogoutFromFileServer (F102)
|
|
|
|
Secondary Functions:
|
|
|
|
* GetUserAtConnection
|
|
* GetObjectLoginControl
|
|
* GetObjectNodeControl
|
|
* ObjectCanLoginAt
|
|
|
|
Workstation Services
|
|
--------------------
|
|
|
|
* EndOfJob (D6) to be rewritten to F218
|
|
* GetConnectionID (EF04)
|
|
* GetConnectionIDtable (EF03) (1)
|
|
* GetDefaultConnectionID (F002)
|
|
* GetEndOfJobStatus (BB..)
|
|
* GetFileServerName (EF04)
|
|
* GetNetwareErrorMode (DD..)
|
|
* GetNetwareShellVersion (EA00)
|
|
* GetNumberOfLocalDrives (DB..)
|
|
* GetPreferredConnectionID (F001)
|
|
* GetPrimaryConnectionID (F005)
|
|
* GetShowDots (E908)
|
|
* GetWorkstationEnvironment (EAxx,xx>00) (2)
|
|
* SetEndOfJobStatus (BB..)
|
|
* SetNetwareErrorMode (DD..)
|
|
* SetPreferredConnectionID (F000)
|
|
* SetPrimaryConnectionID (F004)
|
|
* SetShowDots (E908)
|
|
|
|
Secondary Functions:
|
|
|
|
* GetEffectiveConnectionID (F001,F002,F005)
|
|
* IsConnectionIDinUse (EF03)
|
|
|
|
|
|
Not Implemented:
|
|
----------------
|
|
|
|
- GetStationsLoggedInformation (F217/05) (3)
|
|
- Login (F217/00) (4)
|
|
- MapUserToStationSet (F217/02) (5)
|
|
|
|
Notes: -Only functions marked with a * have been tested; others might work.
|
|
-(1): This function returns the complete Connection ID table. The
|
|
partial function IsConnectionIDInUse has been moved to the
|
|
secondary function group.
|
|
-(2): This function is an extension to EA00 GetNetwareShellVersion.
|
|
A function that returns all returned information from the call
|
|
EAxx,xx>00 is sometimes referred to as GetWShardwareAndOS.
|
|
|
|
-NOT implemented in this API:
|
|
(3): Replaced by F217/16 GetConnectionInformation.
|
|
(4): This function has been replaced by F217/14 LoginToFileServer.
|
|
(5): Replaced by F217/15 GetObjectConnectionNumbers.
|
|
|
|
-NW 386 can support up to 250 connections, NW 286 Max 100.
|
|
-Type TconnectionList=array[1..250] of byte (Declared in unit nwMisc)
|
|
|
|
}
|
|
|
|
Uses nwIntr,nwMisc,nwBindry;
|
|
|
|
|
|
Const MaxServers=8;
|
|
|
|
Type TServerNameTableEntry = Array [1..48] OF Char;
|
|
TServerNameTable = Array[1..MaxServers] OF TServerNameTableEntry;
|
|
|
|
TConnectionIDTableEntry=
|
|
Record
|
|
SlotInUse : Byte;
|
|
OrderNumber : Byte;
|
|
ServerAddress : TinternetworkAddress;
|
|
ReceiveTimeOut : Word;
|
|
RouterAddress : TnodeAddress;
|
|
PacketSeqNbr : Byte;
|
|
ConnectionNumber : Byte;
|
|
ConnectionStatus : Byte;
|
|
MaxTimeOut : Word;
|
|
WConnectionNumber: Word;
|
|
MajorNWrev : Byte;
|
|
ServerFlags : Byte;
|
|
MinorNWrev : Byte;
|
|
END;
|
|
TConnectionIDTable = Array [1..MaxServers] OF TConnectionIDTableEntry;
|
|
|
|
TloginControl=Record
|
|
AccountDisabled :boolean;
|
|
AccountExpirationDate :TNovTime; { dmy valid only }
|
|
|
|
MinimumPasswordLength :byte;
|
|
PasswordControlFlag :byte;
|
|
DaysBetweenPasswordChanges:word;
|
|
PasswordExpirationDate :TnovTime;
|
|
LastLoginTime :TnovTime; {dmy, hms valid only }
|
|
GraceLoginsRemaining :Byte;
|
|
MaxGraceLoginsAllowed :byte;
|
|
BadLoginCount :byte;
|
|
AccountResetTime :TnovTime; {dmy, hms valid only }
|
|
LastIntruderAddress :TinterNetworkAddress;
|
|
|
|
MaxConcurrentConnections :byte;
|
|
LoginTimes :array[1..42] of byte;
|
|
|
|
DiskSpace :Longint;
|
|
end;
|
|
|
|
TnodeControl=array[1..12] of record
|
|
net :TnetworkAddress;
|
|
node:TnodeAddress;
|
|
end;
|
|
|
|
Var result1:word;
|
|
|
|
{BB.. [2.0/2.1/3.x]}
|
|
Function SetEndOfJobStatus( EndOfJobFlag: Boolean ):Boolean;
|
|
{ When this function is called with EndOfJobFlag=False and control is returned
|
|
to the root COMMAND.COM, COMMAND.COM will NOT perform an EOJ action. }
|
|
|
|
{BB.. [2.0/2.1/3.x]}
|
|
Function GetEndOfJobStatus(Var EndOfJobFlag: Boolean ):Boolean;
|
|
|
|
{F218 [2.15c+]}
|
|
FUNCTION EndOfJob(All : Boolean):boolean;
|
|
{ Forces an end of job }
|
|
|
|
{E908 (shell 3.00+)}
|
|
Function SetShowDots( Show:Boolean):Boolean;
|
|
|
|
{E908 (shell 3.00+)}
|
|
Function GetShowDots(Var Shown:Boolean):Boolean;
|
|
|
|
{F219 [2.15c+]}
|
|
Function Logout:boolean;
|
|
{ Logout from all file servers, remains attached to Server, effective EOJ }
|
|
|
|
{DB.. [2.0/2.1/3.x]}
|
|
Function GetNumberOfLocalDrives( Var drives:Byte ):Boolean;
|
|
|
|
{DC.. [2.0/2.1/3.x]}
|
|
Function GetConnectionNumber(Var ConnectionNbr:byte):boolean;
|
|
{ Returns connection number of requesting WS }
|
|
|
|
{DD.. [2.0/2.1/3.x]}
|
|
Function SetNetwareErrorMode( errMode:Byte):boolean;
|
|
{ Sets the shell's handling mode for dealing with netware errors. }
|
|
|
|
{DD.. [2.0/2.1/3.x]}
|
|
Function GetNetwareErrorMode(Var errMode:Byte):boolean;
|
|
|
|
{E3../0A [2.0/2.1/3.x]}
|
|
Function EnterLoginArea( LoginSubDirName:String;
|
|
numberOfLocalDrives:Byte ):boolean;
|
|
{ Changes the login directory. Used by boot-proms. }
|
|
|
|
{F217/13 [2.15c+]}
|
|
Function GetInternetAddress( ConnNbr : byte;
|
|
var IntNetAddress:TinternetworkAddress):boolean;
|
|
|
|
{F217/14 [2.15c+] UNENCRYPTED}
|
|
Function LoginToFileServer( objName:String; objType:word;
|
|
password : string ):boolean;
|
|
|
|
{F217/18 [2.15c+] ENCRYPTED}
|
|
FUNCTION LoginEncrToFileServer(ObjName: String; ObjType: Word;
|
|
PassWord: String ): Boolean;
|
|
|
|
{F217/15 [2.15c+]}
|
|
Function GetObjectConnectionNumbers( objName:String; objType:Word;
|
|
Var numberOfConnections: Byte;
|
|
Var connections: TconnectionList ):boolean;
|
|
{ returns a list of connectionnumbers where objects of the desired type and
|
|
name are logged in. }
|
|
|
|
{F217/16 [2.15c+]}
|
|
Function GetConnectionInforMation (ConnectionNbr:byte;
|
|
Var objName:String;
|
|
Var objType:Word;
|
|
Var objId:LongInt;
|
|
Var LoginTime:TnovTime ):boolean;
|
|
|
|
{EA00 [2.0/2.1/3.x]}
|
|
Function GetNetwareShellVersion( Var MajorVersion,MinorVersion,
|
|
RevisionLevel :Byte ):Boolean;
|
|
{ Returns information about a WS environment. Queries shell. }
|
|
|
|
{EAxx,xx>00 [2.0/2.1/3.x]}
|
|
Function GetWorkstationEnvironment(Var OStype,OSversion,
|
|
HardwareType,ShortHWType:String):Boolean;
|
|
|
|
{EE.. [2.0/2.1/3.x]}
|
|
FUNCTION GetWorkstationNodeAddress( var physicalNodeAddress: TNodeAddress ):boolean;
|
|
{ Get the physical address of the workstation (6 bytes hi-endian) }
|
|
|
|
|
|
{EF03 [2.0/2.1/3.x]}
|
|
Function GetConnectionIDTable( ConnectionID: Byte ; Var TableEntry: TConnectionIDTableEntry ):boolean;
|
|
{ Returns a copy of the entry in the shells' ConnectionID table corresponding
|
|
with the given ConnectionID. }
|
|
|
|
{EF04 [2.0/2.1/3.x]}
|
|
Function GetConnectionID( serverName: String; Var ConnectionID: Byte):boolean;
|
|
|
|
|
|
{EF04 [2.0/2.1/3.x]}
|
|
Function GetFileServerName( ConnectionID : byte; var ServerName : string):boolean;
|
|
{ get name of file server. file server number must be in range [1..MaxServers] }
|
|
|
|
{F000 [2.0/2.1/3.x]}
|
|
Function SetPreferredConnectionID( ConnectionID :byte ):boolean;
|
|
|
|
{F001 [2.0/2.1/3.x]}
|
|
Function GetPreferredConnectionID(var connID : byte):boolean;
|
|
|
|
{F002 [2.0/2.1/3.x]}
|
|
FUNCTION GetDefaultConnectionID(var connID :byte):boolean;
|
|
|
|
{F004 [2.0/2.1/3.x]}
|
|
FUNCTION SetPrimaryConnectionID( primaryConnectionID :Byte ):boolean;
|
|
|
|
{F005 [2.0/2.1/3.x]}
|
|
FUNCTION GetPrimaryConnectionID(var connID :byte ):boolean;
|
|
|
|
{F100 [2.0+]}
|
|
Function AttachToFileServerWithAddress(ServerName:string;
|
|
ServerAddr:TinternetworkAddress;
|
|
Var ConnectionID:Byte):Boolean;
|
|
|
|
{F100 [2.0/2.1/3.x] (also calls EF03,EF04)}
|
|
Function AttachToFileServer(ServerName : String; Var ConnectionID:Byte):Boolean;
|
|
{ Create an attachment between a server and a workstation. }
|
|
|
|
{F101 [2.0/2.1/3.x]}
|
|
Function DetachFromFileServer( ConnectionID:byte ):boolean;
|
|
{ removes server from shell's server table. Relinquishes the
|
|
fileserver connection number and breaks the connection. }
|
|
|
|
{F102 [2.0/2.1/3.x]}
|
|
Function LogoutFromFileServer(var ConnectionID: byte):boolean;
|
|
{logout from one file server}
|
|
|
|
{***** secondary Functions, result1 variable is not used *******************}
|
|
|
|
{EF03 [2.0/2.1/3.x] secondary Function }
|
|
Function IsConnectionIDinUse( ConnectionID: Byte ):boolean;
|
|
|
|
Function GetUserAtConnection( ConnectionNbr:byte; var username: string):boolean;
|
|
{This function provides a short method of obtaining just the USERID.}
|
|
|
|
Function GetEffectiveConnectionID(Var connId:byte):boolean;
|
|
{What server are the requests currently sent to? }
|
|
|
|
Function GetObjectLoginControl(ObjName:string; ObjType:word;
|
|
VAR LoginControlInfo:TloginControl):boolean;
|
|
|
|
Function GetObjectNodeControl( ObjName:string; ObjType:word;
|
|
{i/o} Var seqNbr:integer;
|
|
{out} Var NodeControlInfo:TnodeControl):boolean;
|
|
|
|
Function ObjectCanLoginAt(ObjName:String; ObjType:Word;
|
|
LoginTime:TnovTime ):Boolean;
|
|
{ -If the fields hour,min,sec and dayOfWeek are filled, the time
|
|
will be checked against the login timerestrictions.
|
|
-If the fields year,month,day are filled ( >0 ), the date
|
|
will be checked with the expiration date of the account and
|
|
with the Account disabled Flag. }
|
|
|
|
IMPLEMENTATION{=============================================================}
|
|
|
|
Type TPConnectionIDTPtr=^TConnectionIDTable;
|
|
TPServerNTPtr=^TServerNameTable;
|
|
|
|
{F000 [2.0/2.1/3.x]}
|
|
Function SetPreferredConnectionID( ConnectionID :byte ):boolean;
|
|
{ The preferred server is the default server to which the request
|
|
packets are sent.
|
|
Calls are routed to the preferred server. (IF explicitly set!).
|
|
If the preferred server was not set then the requests are routed to
|
|
the server that is attached to the current drive. If the current
|
|
drive is a local drive then the requests will be sent to the primary
|
|
server (mostly the server the shell initially attached to.) }
|
|
var regs : TTregisters;
|
|
begin
|
|
regs.ax := $F000;
|
|
regs.dl := ConnectionID; { 1..MaxServers, 0 to clear }
|
|
RealModeIntr($21,regs);
|
|
result1:=0;
|
|
SetPreferredConnectionID:=TRUE;
|
|
end;
|
|
|
|
{F004 [2.0/2.1/3.x]}
|
|
FUNCTION SetPrimaryConnectionID( primaryConnectionID :Byte ):boolean;
|
|
var regs : TTregisters;
|
|
begin
|
|
regs.ax := $F004;
|
|
regs.dl := primaryConnectionID; { 1..MaxServers, or 0 to clear }
|
|
RealModeIntr($21,regs);
|
|
result1:=0;
|
|
SetPrimaryConnectionID:=TRUE;
|
|
end;
|
|
|
|
{F005 [2.0/2.1/3.x]}
|
|
FUNCTION GetPrimaryConnectionID(var connID :byte ):boolean;
|
|
{ returns connection number of the primary file server (1..MaxServers) }
|
|
var regs : TTregisters;
|
|
begin
|
|
regs.ax := $F005;
|
|
RealModeIntr($21,regs);
|
|
connID := regs.al;
|
|
if connId>MaxServers
|
|
then result1:=$FF
|
|
else result1:=$00;
|
|
GetPrimaryConnectionID:=(result1=0);
|
|
end;
|
|
|
|
{F002 [2.0/2.1/3.x]}
|
|
FUNCTION GetDefaultConnectionID(var connID :byte):boolean;
|
|
{ Returns the connection ID of the file server to which
|
|
the packets are currently being sent. }
|
|
var regs : TTregisters;
|
|
begin
|
|
regs.ax := $F002;
|
|
RealModeIntr($21,regs);
|
|
connID := regs.al; { 1..MaxServers }
|
|
if connId>MaxServers
|
|
then result1:=$FF
|
|
else result1:=$00;
|
|
GetDefaultConnectionID:=(result1=0);
|
|
end;
|
|
|
|
{F001 [2.0/2.1/3.x]}
|
|
Function GetPreferredConnectionID(var connID : byte):boolean;
|
|
var regs : TTregisters;
|
|
begin
|
|
regs.ax := $F001;
|
|
RealModeIntr($21,regs);
|
|
connID := regs.al; { 1..MaxServers, or 0 if the preferred server was not set }
|
|
{ The preferred coneection is reset to 0 by an EOJ. }
|
|
if connId>MaxServers
|
|
then result1:=$FF
|
|
else result1:=$00;
|
|
GetPreferredConnectionID:=(result1=0);
|
|
end;
|
|
|
|
|
|
|
|
{EF04 [2.0/2.1/3.x]}
|
|
Function GetConnectionID( serverName: String; Var ConnectionID: Byte):boolean;
|
|
Type ptarr=^arr;
|
|
arr=Array[0..MaxServers*32] of Byte;
|
|
Var regs : TTregisters;
|
|
NameTable : Array [1..MaxServers*48] of Byte;
|
|
ServerNames: Array [1..MaxServers] of String;
|
|
t : Byte;
|
|
begin
|
|
UpString(ServerName);
|
|
regs.ax := $EF04;
|
|
RealModeIntr($21,regs);
|
|
{ get pointer to shell's server name table. }
|
|
move(nwPtr(regs.es, regs.si)^,NameTable,MaxServers*48);
|
|
For t := 0 to 7
|
|
do ZstrCopy(ServerNames[t+1],NameTable[1+ t*48],48);
|
|
|
|
t:=1;
|
|
While ((t<9) and (ServerNames[t]<>ServerName))
|
|
do inc(t);
|
|
If t=9
|
|
then result1:=$FC { invalid server name }
|
|
else begin
|
|
ConnectionID:=t;
|
|
{ ServerName found. Is ConnectionID valid ? }
|
|
regs.ax:=$EF03;
|
|
RealModeIntr($21,regs);
|
|
IF (ptarr(nwPtr(regs.es,regs.si))^[(ConnectionID-1)*32] = $00 ) {= $FF ?? }
|
|
then begin
|
|
ConnectionID:=0;
|
|
result1:=$FC { ConnectionID invalid => servername invalid }
|
|
end
|
|
else result1:=$00;
|
|
end;
|
|
GetConnectionID:=(result1=0);
|
|
end;
|
|
|
|
|
|
{EF04 [2.0/2.1/3.x]}
|
|
Function GetFileServerName( ConnectionID : Byte; Var ServerName : String):boolean;
|
|
{ Get the name of file server, associated with the ConnectionID.
|
|
The File server number must be in the range [1..MaxServers].
|
|
The function will fail (result1=$FF) if connID falls outside of this range. }
|
|
Type ptarr=^arr;
|
|
arr=Array[0..MaxServers*32] of Byte;
|
|
Var regs : TTregisters;
|
|
NameTable : Array [1..MaxServers*48] of Byte;
|
|
ServerNames: Array [1..MaxServers] of String;
|
|
t : Byte;
|
|
begin
|
|
regs.ax := $EF04;
|
|
RealModeIntr($21,regs);
|
|
{ Get pointer to shell's server name table. }
|
|
move(nwPtr(regs.es, regs.si)^,NameTable,MaxServers*48);
|
|
For t := 0 to 7
|
|
do ZstrCopy(ServerNames[t+1],NameTable[1+ t*48],48);
|
|
|
|
if ((ConnectionID<1) or (ConnectionID>MaxServers))
|
|
then ServerName:=''
|
|
else ServerName := ServerNames[ConnectionID];
|
|
IF ServerName=''
|
|
then result1:=$FF
|
|
else begin { The name is valid, but is the ConnectionID valid ? }
|
|
regs.ax:=$EF03;
|
|
RealModeIntr($21,regs);
|
|
IF (ptarr(nwPtr(regs.es,regs.si))^[(ConnectionID-1)*32] = $00 ) {= $FF ?? }
|
|
then begin
|
|
result1:=$FF; { ConnectionID invalid => servername invalid }
|
|
ServerName:='';
|
|
end
|
|
else result1:=$00;
|
|
end;
|
|
GetFileServerName:=(result1=0);
|
|
end;
|
|
|
|
|
|
Function AttachToFileServerWithAddress(ServerName:string;
|
|
ServerAddr:TinternetworkAddress;
|
|
Var ConnectionID:Byte):Boolean;
|
|
{ Create an attachment between a server and a workstation. }
|
|
{ Does not Login the workstation. }
|
|
{ After attaching, and beFore logging in, you must set the preferred server
|
|
to the ConnectionID of the server. }
|
|
{ Will not report an error if you're already attached to
|
|
-or even logged on to- the target server. }
|
|
{ Attaches to the server whose address is supplied. The server name will
|
|
be placed in the server name tables, even if the servername is incorrect or
|
|
the supplied servername isn't associated with the supplied address. }
|
|
{ Based on the InsertServer Function in LOGON.PAS by Barry Nance, and
|
|
on Rose, p.262 }
|
|
Var ConnectionIDTPtr : TPConnectionIDTPtr;
|
|
ServerNTPtr : TPServerNTPtr;
|
|
NewServerSlot,i : Byte;
|
|
OldConnId : Byte;
|
|
ServIsAttached : Boolean;
|
|
AccessLevel : Byte;
|
|
ObjID : Longint;
|
|
|
|
Regs:TTRegisters;
|
|
|
|
NewServer:Boolean;
|
|
|
|
Var cid:byte;
|
|
|
|
BEGIN
|
|
{ If server known, take adress from shells' tables.
|
|
If server not known, try to read its' adress from a servers' bindery.
|
|
This will fail if you're not connected to at least one server.
|
|
Once an adress has been found, AttachToFileServerWithAdress is called. }
|
|
|
|
ServerAddr.socket:=swap($0451); { swapped hi-lo}
|
|
UpString(ServerName);
|
|
|
|
regs.ax:=$EF03;
|
|
RealModeIntr($21,regs);
|
|
ConnectionIDTPtr:=nwPtr(regs.es,regs.si); { Ptr to TConnectionIDTable }
|
|
|
|
{ Determine whether the suplied server is already known/attached to }
|
|
|
|
ConnectionID:=0;
|
|
REPEAT
|
|
inc(ConnectionID)
|
|
UNTIL (ConnectionID>MaxServers)
|
|
or ((ConnectionIDTPtr^[ConnectionID].SlotInUse>0)
|
|
and IsEqualNetworkAddress(ConnectionIDTPtr^[ConnectionID].ServerAddress,ServerAddr)
|
|
);
|
|
|
|
NewServer:=(ConnectionID>MaxServers);
|
|
|
|
{ If the server is a new server, put it in the sorted ConnectionIDTable }
|
|
IF NewServer
|
|
then begin
|
|
{ Determine free slot to insert new server }
|
|
NewServerSlot := 1;
|
|
WHILE (ConnectionIDTPtr^[NewServerSlot].SlotInUse <> $00)
|
|
AND (NewServerSlot <= MaxServers)
|
|
do inc(NewServerSlot);
|
|
IF NewServerSlot > MaxServers
|
|
then begin
|
|
result1:=$7C;
|
|
AttachToFileServerWithAddress := False;
|
|
exit;
|
|
end;
|
|
|
|
With ConnectionIDTPtr^[NewServerSlot]
|
|
do begin
|
|
ServerAddress:=ServerAddr;
|
|
OrderNumber := 0;
|
|
For i := 1 TO MaxServers
|
|
do begin
|
|
IF (ConnectionIDTPtr^[i].SlotInUse <> $00)
|
|
and (ConnectionIDTPtr^[i].OrderNumber>=OrderNumber)
|
|
then OrderNumber:=ConnectionIDTPtr^[i].OrderNumber+1;
|
|
end;
|
|
SlotInUse := $FF; { Must be set to $FF before attaching }
|
|
end;
|
|
ConnectionID:=NewServerSlot;
|
|
end
|
|
else { NOT a new server.. }
|
|
IF (ConnectionIDTPtr^[ConnectionID].ConnectionNumber > 0)
|
|
AND (ConnectionIDTPtr^[ConnectionID].ConnectionNumber < $FF)
|
|
AND (ConnectionIDTPtr^[ConnectionID].ConnectionStatus = $FF)
|
|
then Begin { ServerIsKnown }
|
|
GetPreferredConnectionID (OldConnId);
|
|
SetPreferredConnectionID (ConnectionID);
|
|
ServIsAttached := GetBinderyAccessLevel (AccessLevel, ObjID);
|
|
SetPreferredConnectionID (OldConnID);
|
|
IF ServIsAttached { ServerIsAlreadyAttached / caller may even be looged on }
|
|
then begin
|
|
result1:=0;
|
|
AttachToFileServerWithAddress := True;
|
|
exit;
|
|
end;
|
|
End;
|
|
|
|
{ Create an attachment }
|
|
With Regs
|
|
do begin
|
|
AX := $F100;
|
|
DL := ConnectionID;
|
|
RealModeIntr($21,Regs);
|
|
result1 := AL;
|
|
{ F8 already attached to server; F9 No Free connection slots at server;
|
|
FA no more server slots; FE Server Bindery Locked;
|
|
FF No response from server }
|
|
end;
|
|
|
|
IF NewServer
|
|
then begin
|
|
if result1<>$00 { F9/FA/FE/FF error at server/no response from server }
|
|
then Begin { Note that the combination of a 'new' server and err. F8 is impossible }
|
|
ConnectionIDTPtr^[NewServerSlot].SlotInUse:=$00;
|
|
{ Invalid server, Free slot again }
|
|
end
|
|
else begin
|
|
{ Valid server, sort ConnectionID table }
|
|
With ConnectionIDTPtr^[NewServerSlot]
|
|
do begin
|
|
SlotInUse:=$00; { temporarily set to 0, For sorting purposes }
|
|
OrderNumber := 1;
|
|
For i := 1 TO MaxServers
|
|
do begin
|
|
IF ConnectionIDTPtr^[i].SlotInUse <> $00
|
|
then begin
|
|
IF IsLowerNetworkAddress(ConnectionIDTPtr^[i].ServerAddress, ServerAddress)
|
|
then inc(OrderNumber)
|
|
else inc(ConnectionIDTPtr^[i].OrderNumber)
|
|
end;
|
|
end;
|
|
SlotInUse:=$FF;
|
|
end;
|
|
{ Put new servers' name in server Name Table }
|
|
regs.ax := $EF04;
|
|
RealModeIntr($21,regs);
|
|
ServerNTPtr:=nwPtr(regs.es, regs.si); { pointer to shell's server name table. }
|
|
FillChar(ServerNTPtr^[NewServerSlot],48,#0);
|
|
If ServerName[0]>#47
|
|
then ServerName[0]:=#47;
|
|
Move(ServerName[1],ServerNTPtr^[NewServerSlot],Length (ServerName));
|
|
end;
|
|
end;
|
|
|
|
AttachToFileServerWithAddress:=(result1=0);
|
|
{ Valid completion codes:
|
|
7C Maximum number of attached servers exceeded.
|
|
F8 already attached to server;
|
|
F9 No Free connection slots at specified server;
|
|
FA no more server slots;
|
|
FF No response from server
|
|
FC No Free slots in shells' ConnectionID table; }
|
|
end;
|
|
|
|
|
|
Function AttachToFileServer(ServerName : String; Var ConnectionID:Byte):Boolean;
|
|
{ Create an attachment between a server and a workstation. }
|
|
{ !! you have to be attached to at least 1 server before calling this function. }
|
|
{ Does not Login the workstation. }
|
|
{ After attaching, and beFore logging in, you must set the preferred server
|
|
to the ConnectionID of the server. }
|
|
{ Will not report an error if you're already attached to
|
|
-or even logged on to- the target server. }
|
|
Var ConnectionIDTPtr : TPConnectionIDTPtr;
|
|
OldConnId : Byte;
|
|
ServIsAttached : Boolean;
|
|
AccessLevel : Byte;
|
|
ObjID : Longint;
|
|
|
|
PropValue :Tproperty;
|
|
MoreSegments :boolean;
|
|
PropFlags :Byte;
|
|
|
|
Regs:TTRegisters;
|
|
|
|
ServAddr:TinternetworkAddress;
|
|
BEGIN
|
|
{ If server known, take adress from shells' tables.
|
|
If server not known, try to read its' address from a servers' bindery.
|
|
This will fail if you're not connected to at least one server.
|
|
Once an adress has been found, AttachToFileServerWithAdress is called. }
|
|
UpString(ServerName);
|
|
|
|
regs.ax:=$EF03;
|
|
RealModeIntr($21,regs);
|
|
ConnectionIDTPtr:=nwPtr(regs.es,regs.si); { Ptr to TConnectionIDTable }
|
|
|
|
{ Determine whether the suplied server is already known/attached to }
|
|
IF GetConnectionID(ServerName,ConnectionID)
|
|
then Begin
|
|
IF (ConnectionIDTPtr^[ConnectionID].ConnectionNumber > 0)
|
|
AND (ConnectionIDTPtr^[ConnectionID].ConnectionNumber < $FF)
|
|
AND (ConnectionIDTPtr^[ConnectionID].ConnectionStatus = $FF)
|
|
then Begin { ServerIsKnown }
|
|
GetPreferredConnectionID (OldConnId);
|
|
SetPreferredConnectionID (ConnectionID);
|
|
ServIsAttached := GetBinderyAccessLevel (AccessLevel, ObjID);
|
|
SetPreferredConnectionID (OldConnID);
|
|
result1:=0;
|
|
IF ServIsAttached { ServerIsAlreadyAttached / caller may even be looged on }
|
|
then begin
|
|
AttachToFileServer := True;
|
|
exit;
|
|
end
|
|
else ServAddr:=ConnectionIDTPtr^[ConnectionID].ServerAddress;
|
|
end
|
|
End
|
|
Else begin
|
|
IF ReadPropertyValue(ServerName,OT_FILE_SERVER,'NET_ADDRESS',1,PropValue,moreSegments,propFlags)
|
|
then begin
|
|
result1:=0;
|
|
Move(PropValue,ServAddr,SizeOf(TinternetworkAddress));
|
|
end
|
|
else begin
|
|
result1:=$FC;
|
|
AttachToFileServer:=False;
|
|
exit;
|
|
end;
|
|
End;
|
|
|
|
if result1=0
|
|
then AttachToFileServerWithAddress(ServerName,ServAddr,ConnectionID);
|
|
|
|
AttachToFileServer:=(result1=0);
|
|
{ Valid completion codes:
|
|
7C Maximum number of attached servers exceeded.
|
|
7D Bindery read error (The supplied server can't be located/doesn't exist)
|
|
F8 already attached to server;
|
|
F9 No Free connection slots at specified server;
|
|
FA no more server slots;
|
|
FE Server Bindery Locked;
|
|
FF No response from server
|
|
FC No Free slots in shells' ConnectionID table; }
|
|
END;
|
|
|
|
|
|
{F101 [2.0/2.1/3.x]}
|
|
Function DetachFromFileServer( ConnectionID:Byte ):boolean;
|
|
{ removes server from shell's server table. Relinquishes the
|
|
fileserver connection number and breaks the connection.
|
|
The function will fail (result1=$FF) if connID falls outside of the range [1..MaxServers].}
|
|
Type ArrPtr=^Tarr;
|
|
Tarr=Array[0..MaxServers*48] of Byte;
|
|
Var regs : TTregisters;
|
|
begin
|
|
if (ConnectionID<1) or (ConnectionID>MaxServers)
|
|
then result1:=$FF
|
|
else begin
|
|
regs.ax := $F101;
|
|
regs.dl := ConnectionID; { 1..MaxServers }
|
|
RealModeIntr($21,regs);
|
|
result1 := regs.al;
|
|
{ returncodes: 00 successful; FF Connection Doesn't exist }
|
|
end;
|
|
DetachFromFileServer:=(result1=0);
|
|
end;
|
|
|
|
|
|
{EF03 [2.0/2.1/3.x]}
|
|
Function GetConnectionIDTable( ConnectionID: Byte ; Var TableEntry: TConnectionIDTableEntry ):boolean;
|
|
{ Returns a copy of the entry in the shells' ConnectionID table corresponding
|
|
With the given ConnectionID. All fields are returned lo-hi, except Net and Node
|
|
addresses.
|
|
The function will fail (result1=$FF) if connID falls outside of the range [1..MaxServers].}
|
|
Type ptarr=^tarr;
|
|
tarr=Array[0..MaxServers*32] of Byte;
|
|
Var regs:TTregisters;
|
|
begin
|
|
If ((ConnectionID<1) or (ConnectionID>MaxServers))
|
|
then result1:=$FF
|
|
else begin
|
|
regs.ax:=$EF03;
|
|
RealModeIntr($21,regs);
|
|
move( ptarr(nwPtr(regs.es,regs.si))^[(ConnectionID-1)*32], TableEntry, 32 );
|
|
With TableEntry
|
|
do begin
|
|
ServerAddress.socket:=swap(ServerAddress.socket); { Force lo-hi }
|
|
ReceiveTimeOut:=swap(ReceiveTimeOut); { Force lo-hi }
|
|
MaxTimeOut:=swap(MaxTimeOut); { Force lo-hi }
|
|
WconnectionNumber:=swap(WconnectionNumber); { force lo-hi }
|
|
end;
|
|
result1:=$00;
|
|
end;
|
|
GetConnectionIDTable:=(result1=0);
|
|
end;
|
|
|
|
|
|
{DC.. [2.0/2.1/3.x]}
|
|
Function GetConnectionNumber(Var ConnectionNbr:byte):boolean;
|
|
{ returns connection number of requesting WS (1..100) }
|
|
var regs:TTRegisters;
|
|
begin
|
|
regs.Ah:=$DC;
|
|
RealModeIntr($21,regs);
|
|
ConnectionNbr:=Regs.AL; { logical WS connection # }
|
|
{ cl= first digit of logical conn #, ch= second digit of conn# }
|
|
result1:=0;
|
|
GetConnectionNumber:=true;
|
|
end;
|
|
|
|
|
|
{F217/16 [2.15c+]}
|
|
Function GetConnectionInformation (ConnectionNbr:byte;
|
|
Var objName:String;
|
|
Var objType:Word;
|
|
Var objId:LongInt;
|
|
Var LoginTime:TnovTime ):boolean;
|
|
Type TReq=Record
|
|
PacketLength : Word;
|
|
FunctionVal : Byte;
|
|
_ConnectionNo : Byte;
|
|
End;
|
|
Trep=Record
|
|
_objId :LongInt; { hi-lo }
|
|
_ObjType : word; { hi-lo }
|
|
_ObjName : Array [1..48] of Byte;
|
|
_LoginTime : TnovTime;
|
|
Reserved:word;
|
|
End;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Var i,x: Integer;
|
|
Begin
|
|
With TPreq(GlobalReqBuf)^
|
|
Do Begin
|
|
PacketLength := 2;
|
|
FunctionVal := $16;
|
|
_ConnectionNo := ConnectionNbr;
|
|
End;
|
|
F2SystemCall($17,SizeOf(Treq),SizeOf(TRep),result1);
|
|
If result1 = 0
|
|
Then Begin
|
|
With TPrep(GlobalReplyBuf)^
|
|
Do Begin
|
|
ZstrCopy(ObjName,_objName,48);
|
|
ObjId:=Lswap(_objId);
|
|
ObjType:=swap(_objType);
|
|
logintime:=_logintime;
|
|
End;
|
|
End;
|
|
{ patch to have a NIL object return an error. }
|
|
if objName='' then result1:=$FD; { no_such_connection }
|
|
GetConnectionInformation:=(result1=0);
|
|
End { GetConnectInfo };
|
|
|
|
|
|
|
|
{F217/14 [2.15c+,unencrypted]}
|
|
Function LoginToFileServer( objName:String; objType:word;
|
|
password : string ):boolean;
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_objType :Word; { hi-lo }
|
|
_objName :String[47]; { asciiz? }
|
|
_objPassw:String[127]; { allowed to be '' }
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$14;
|
|
_objType:=swap(objType);
|
|
PStrCopy(_objName,objName,47); _objName[47]:=#0; UpString(_objName);
|
|
PStrCopy(_objPassw,password,127); UpString(_objPassw);
|
|
end;
|
|
F2SystemCall($17,SizeOf(Treq),0,result1);
|
|
LoginToFileServer:=(result1=0)
|
|
end;
|
|
|
|
|
|
{F217/18 [3.x]}
|
|
FUNCTION LoginEncrToFileServer(ObjName: String; ObjType: Word; PassWord: String): Boolean;
|
|
{ assumes the current effective server = the server to login to. }
|
|
|
|
|
|
FUNCTION LoginEncrypted(ObjName : String; ObjType : Word; VAR key : TencryptionKey): Boolean;
|
|
Type Treq=RECORD
|
|
BufLen : Word;
|
|
_func : Byte;
|
|
_key : TencryptionKey;
|
|
_ObjType: Word;
|
|
_ObjName: String[48];
|
|
End;
|
|
TPreq=^Treq;
|
|
Begin
|
|
With TPreq(GlobalReqBuf)^
|
|
do Begin
|
|
_func := $18;
|
|
_key := key;
|
|
_ObjType := Swap(objType);
|
|
PstrCopy(_ObjName,ObjName,48); UpString(_ObjName);
|
|
if ObjName[0]<#48
|
|
then _objName[0]:=objName[0]
|
|
else _objname[0]:=#48;
|
|
BufLen:=ord(_ObjName[0])+12;
|
|
End;
|
|
F2SystemCall($17,SizeOf(Treq),0,result1);
|
|
LoginEncrypted:=(result1=0);
|
|
End;
|
|
|
|
VAR
|
|
key : TencryptionKey;
|
|
ObjId:LongInt;
|
|
|
|
Begin
|
|
UpString(password);
|
|
if password[0]>#127
|
|
Then password[0]:=#127;
|
|
|
|
IF GetEncryptionKey(key)
|
|
Then Begin
|
|
IF GetBinderyObjectId(objName,objType,ObjId)
|
|
Then Begin
|
|
EncryptPassword(objId,password,key);
|
|
LoginEncrypted(ObjName, ObjType, key);
|
|
End;
|
|
End
|
|
Else LoginToFileServer(ObjName, ObjType, Password);
|
|
|
|
LoginEncrToFileServer:= (result1=0);
|
|
End;
|
|
|
|
|
|
{F219 [2.15c+]}
|
|
Function Logout:boolean;
|
|
{logout from all file servers, remains attached to Server, effective EOJ }
|
|
begin
|
|
F2SystemCall($19,0,0,result1);
|
|
result1:=$00;
|
|
Logout:=true;
|
|
end;
|
|
|
|
|
|
{F102 [2.0/2.1/3.x]}
|
|
Function LogoutFromFileServer(var ConnectionID: byte):boolean;
|
|
{logout from one file server}
|
|
var regs : TTregisters;
|
|
begin
|
|
regs.ah := $F1;
|
|
regs.al := $02;
|
|
regs.dl := ConnectionID;
|
|
RealModeIntr($21,regs);
|
|
result1:=00;
|
|
LogoutFromFileServer:=True;
|
|
end;
|
|
|
|
{EE.. [2.0/2.1/3.x]}
|
|
FUNCTION GetWorkstationNodeAddress( var physicalNodeAddress: TNodeAddress ):boolean;
|
|
{ Get the physical station address (6 bytes hi-endian) }
|
|
Var Regs :TTRegisters;
|
|
Begin
|
|
{Get the physical address from the Network Card}
|
|
Regs.Ah := $EE;
|
|
RealModeIntr($21,Regs);
|
|
result1:=Regs.AL;
|
|
{nw node= CX BX AX hi-endian}
|
|
physicalNodeAddress[1]:=Regs.CH;
|
|
physicalNodeAddress[2]:=Regs.CL;
|
|
physicalNodeAddress[3]:=Regs.bh;
|
|
physicalNodeAddress[4]:=Regs.bl;
|
|
physicalNodeAddress[5]:=Regs.ah;
|
|
physicalNodeAddress[6]:=Regs.al;
|
|
result1 := 0;
|
|
GetWorkstationNodeAddress:=true;
|
|
End;
|
|
|
|
|
|
{F217/13 [2.15c+]}
|
|
Function GetInternetAddress( ConnNbr : byte;
|
|
Var IntNetAddress:TinterNetworkAddress
|
|
):boolean;
|
|
Type TReq=record
|
|
length : word;
|
|
subfunction : byte;
|
|
connection : byte;
|
|
end;
|
|
TRep=record
|
|
network : LongInt; { array [1..4] of byte } { hi-lo }
|
|
node : array [1..6] of byte; { hi-lo }
|
|
socket : word; { array [1..2] of byte } { hi-lo }
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
BEGIN
|
|
With TPreq(GlobalreqBuf)^
|
|
do begin
|
|
length := 2;
|
|
subfunction := $13;
|
|
connection := ConnNbr;
|
|
end;
|
|
F2SystemCall($17,SizeOf(Treq),SizeOf(TRep),result1);
|
|
if result1 = 0
|
|
then With TPrep(GlobalreplyBuf)^
|
|
do begin
|
|
move(network,IntNetAddress.net,4); {_is_ and stays hi-lo }
|
|
move(node,IntNetAddress.node,6); { _is_ and stays hi-lo }
|
|
IntNetAddress.socket:=swap(socket); { force lo-hi }
|
|
end;
|
|
GetInternetAddress:=(result1=0);
|
|
end;
|
|
|
|
{D6.. [2.0/2.1/3.x]}
|
|
FUNCTION EndOfJob(All : Boolean):boolean;
|
|
{ forces an end of job
|
|
If All is TRUE, then ends all jobs, otherwise ends a single job.
|
|
Ending a job unlocks and clears all locked or logged files and records.
|
|
It close all open network and local files and resets error and lock modes.
|
|
It also resets the workstation environment. }
|
|
Var NovRegs:TTRegisters;
|
|
BEGIN
|
|
with NovRegs
|
|
do begin
|
|
AH := $D6;
|
|
if All
|
|
then BX := $FFFF
|
|
else BX := $00;
|
|
end;
|
|
RealModeIntr($21,NovRegs);
|
|
result1:=$00;
|
|
EndOfJob:=True;
|
|
end;
|
|
|
|
{$IFDEF NewCalls}
|
|
|
|
{F218 [2.15c+]}
|
|
FUNCTION EndOfJob(All : Boolean):boolean;
|
|
{ forces an end of job
|
|
If All is TRUE, then ends all jobs, otherwise ends a single job.
|
|
Ending a job unlocks and clears all locked or logged files and records.
|
|
It close all open network and local files and resets error and lock modes.
|
|
It also resets the workstation environment. }
|
|
Type Treq=record
|
|
len:word;
|
|
_all:word;
|
|
end;
|
|
{ ??? ERR: unclear how the req buffer should be... }
|
|
TPreq=^Treq;
|
|
BEGIN
|
|
With TPreq(GlobalReqBuf)^
|
|
do begin
|
|
if All
|
|
then _all := $FFFF
|
|
else _all := $0000;
|
|
len:=2;
|
|
end;
|
|
F2SystemCall($18,2,0,result1);
|
|
result1:=$00;
|
|
EndOfJob:=True;
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
{F217/0A [2.0/2.1/3.x]}
|
|
Function EnterLoginArea( LoginSubDirName:String;
|
|
numberOfLocalDrives:Byte ):boolean;
|
|
{ Changes the login directory. Used by boot-proms.
|
|
LoginSubDirName contains the name of a sub directory under SYS:LOGIN
|
|
(e.g. 'V330' means login.exe is to be executed in directory SYS:LOGIN\V330)}
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
_numLocDr:Byte;
|
|
_subDirName:String[255];
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$0A;
|
|
_numLocDr:=numberOfLocalDrives;
|
|
PstrCopy(_subDirName,LoginSubDirName,255); UpString(_subDirName);
|
|
end;
|
|
F2SystemCall($17,Sizeof(Treq),0,result1);
|
|
EnterLoginArea:=(result1=0)
|
|
end;
|
|
|
|
{F217/15 [2.15c+]}
|
|
Function GetObjectConnectionNumbers( objName:String; objType:Word;
|
|
Var numberOfConnections: Byte;
|
|
Var connections: TconnectionList ):boolean;
|
|
{ returns a list of connectionnumbers where objects of the desired type and
|
|
name are logged in.
|
|
Tconnectionlist is defined as an array[1..100] of byte. Max connections for
|
|
Netware 286 = 100. Netware 386 allows more than 100 connections.
|
|
If you pass a bad Objectname or the object is not logged in, the errorcode
|
|
is NOT set to NO_SUCH_OBJECT ($FC), but GetObjectConnectionNumbers returns 0.}
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
_objType:Word; { hi-lo}
|
|
_objName:String[47];
|
|
end;
|
|
Trep=record
|
|
_NbrOfConn:Byte;
|
|
_connList:TconnectionList
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$15;
|
|
PstrCopy(_objName,objName,47); _objname[47]:=#0; UpString(_objName);
|
|
_objType:=swap(objType);
|
|
end;
|
|
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result1);
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
connections:=_connList;
|
|
NumberOfConnections:=_NbrOfConn;
|
|
end;
|
|
getObjectConnectionNumbers:=(result1=0)
|
|
end;
|
|
|
|
|
|
{EA00 [2.0/2.1/3.x]}
|
|
Function GetNetwareShellVersion( Var MajorVersion,MinorVersion,
|
|
RevisionLevel :Byte ):Boolean;
|
|
{ Returns information about a WS environment. Queries shell.
|
|
See also: GetWorkstationEnvironment }
|
|
|
|
Var regs:TTRegisters;
|
|
tmp1,tmp2:word;
|
|
Begin
|
|
With regs
|
|
do begin
|
|
AX:=$EA00;
|
|
GetGlobalBufferAddress(tmp1,tmp2,ES,DI);
|
|
{ Set ES:DI to real-mode address of GlobalReplyBuffer }
|
|
{ Returned value NOT used, but registers need a valid value anyway. }
|
|
RealModeIntr($21,regs);
|
|
MajorVersion:=BH;
|
|
MinorVersion:=BL;
|
|
{ shell version>=3.00 : }
|
|
{ CH = Shell Type. 0=conventional, 1= expanded, 2= extended }
|
|
RevisionLevel:=CL; { 1=A,2=B etc. }
|
|
end;
|
|
result1:=$00;
|
|
GetNetwareShellVersion:=True;
|
|
end;
|
|
|
|
{EAxx,xx>00 [2.0/2.1/3.x] (shell version >=3.00) }
|
|
Function GetWorkstationEnvironment(Var OStype,OSversion,
|
|
HardwareType,ShortHWType:String):Boolean;
|
|
Type Treply=record
|
|
stringz4:array[1..4*32] of char;
|
|
end;
|
|
TPreply=^Treply;
|
|
Var regs:TTRegisters;
|
|
sNo,k:Byte;
|
|
tmp1,tmp2:word;
|
|
Begin
|
|
With regs
|
|
do begin
|
|
AX:=$EA01;
|
|
BX:=$00;
|
|
GetGlobalBufferAddress(tmp1,tmp2,ES,DI);
|
|
{ set ES:DI to real-mode address of GlobalReplyBuffer }
|
|
RealModeIntr($21,regs);
|
|
end;
|
|
OStype:='';
|
|
OSVersion:='';
|
|
HardwareType:='';
|
|
ShortHWtype:='';
|
|
sNo:=0;k:=0;
|
|
With TPreply(GlobalReplyBuf)^
|
|
do begin
|
|
while sNo<4
|
|
do begin
|
|
inc(k);
|
|
while ((k<128) and (stringz4[k]<>#0))
|
|
do begin
|
|
Case sNo of
|
|
0:OStype:=OStype+stringz4[k];
|
|
1:OSversion:=OSversion+stringz4[k];
|
|
2:HardwareType:=HardwareType+stringz4[k];
|
|
3:ShortHWtype:=ShortHWtype+stringz4[k];
|
|
end; {case}
|
|
inc(k);
|
|
end;
|
|
inc(Sno);
|
|
end;
|
|
end;
|
|
result1:=$00;
|
|
GetWorkstationEnvironment:=True;
|
|
end;
|
|
|
|
{DD.. [2.0/2.1/3.x]}
|
|
Function SetNetwareErrorMode( errMode:Byte):boolean;
|
|
{ Sets the shell's handling mode for dealing with netware errors.
|
|
0: default, INT 24 handler 'Abort, Retry, Fail';
|
|
1: a netware error number is returned in AL;
|
|
2: the netware error number is translated to a DOS error number,
|
|
this number is returned.
|
|
An EOJ resets the errormode to 0. }
|
|
Var regs:TTregisters;
|
|
begin
|
|
Regs.AH:=$DD;
|
|
Regs.DL:=errMode;
|
|
RealModeIntr($21,Regs);
|
|
{ regs.al now contains previous error mode }
|
|
result1:=$00;
|
|
SetNetWareErrorMode:=True;
|
|
end;
|
|
|
|
{DD.. [2.0/2.1/3.x]}
|
|
Function GetNetwareErrorMode(Var errMode:Byte):boolean;
|
|
Var regs:TTregisters;
|
|
begin
|
|
Regs.AH:=$DD;
|
|
Regs.DL:=0;
|
|
RealModeIntr($21,Regs);
|
|
{ regs.al now contains previous error mode }
|
|
errMode:=regs.al;
|
|
regs.ah:=$DD;
|
|
RealModeIntr($21,regs); { reset old error mode }
|
|
result1:=$00;
|
|
GetNetWareErrorMode:=True;
|
|
end;
|
|
|
|
|
|
|
|
{BB.. [2.0/2.1/3.x]}
|
|
Function SetEndOfJobStatus( EndOfJobFlag: Boolean ):Boolean;
|
|
{ When this function is called with EndOfJobFlag=False and control is returned
|
|
to the root COMMAND.COM, COMMAND.COM will NOT perform an EOJ action. }
|
|
Var regs:TTRegisters;
|
|
begin
|
|
regs.AH:=$BB;
|
|
If EndOfJobFlag
|
|
then regs.AL:=$01
|
|
else regs.AL:=$00;
|
|
RealModeIntr($21,Regs);
|
|
{ AL now contains previous EOJ Flag }
|
|
result1:=$00;
|
|
SetEndOfJobStatus:=True;
|
|
end;
|
|
|
|
{BB.. [2.0/2.1/3.x]}
|
|
Function GetEndOfJobStatus(Var EndOfJobFlag: Boolean ):Boolean;
|
|
Var regs:TTRegisters;
|
|
begin
|
|
regs.AH:=$BB;
|
|
regs.al:=$00;
|
|
RealModeIntr($21,Regs);
|
|
{ AL now contains previous EOJ Flag }
|
|
EndOfJobFlag:=(regs.al<>0);
|
|
regs.ah:=$BB;
|
|
RealModeIntr($21,regs); { reset old eoj-status }
|
|
result1:=$00;
|
|
GetEndOfJobStatus:=True;
|
|
end;
|
|
|
|
{E908 (shell 3.00+)}
|
|
Function SetShowDots( Show:Boolean):Boolean;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ax:=$E908;
|
|
if Show
|
|
then regs.bl:=$01
|
|
else regs.bl:=$00;
|
|
RealModeIntr($21,Regs);
|
|
result1:=$00;
|
|
SetShowDots:=True;
|
|
end;
|
|
|
|
{E908 (shell 3.00+)}
|
|
Function GetShowDots(Var Shown:Boolean):Boolean;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ax:=$E908;
|
|
RealModeIntr($21,Regs);
|
|
Shown:=(regs.bl<>0);
|
|
regs.ax:=$E908;
|
|
RealModeIntr($21,regs); {reset old 'show dots' parameter}
|
|
result1:=$00;
|
|
GetShowDots:=True;
|
|
end;
|
|
|
|
{DB.. [2.0/2.1/3.x]}
|
|
Function GetNumberOfLocalDrives( Var drives:Byte ):Boolean;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ah:=$DB;
|
|
RealModeIntr($21,Regs);
|
|
drives:=Regs.AL;
|
|
result1:=$00;
|
|
GetNumberOfLocalDrives:=TRUE;
|
|
end;
|
|
|
|
|
|
{=======SECONDARY FUNCTIONS===================================================}
|
|
|
|
|
|
{EF03 [2.0/2.1/3.x] secondary Function }
|
|
Function IsConnectionIDinUse( ConnectionID: Byte ):boolean;
|
|
{ This function returns FALSE if connId isn't in the range [1..MaxServers] }
|
|
Type ptarr=^arr;
|
|
arr=Array[0..MaxServers*32] of Byte;
|
|
Var regs:TTregisters;
|
|
begin
|
|
If ((ConnectionID<1) or (ConnectionID>MaxServers))
|
|
then IsConnectionIDInUse:=FALSE { NWTP04: TRUE }
|
|
else begin
|
|
regs.ax:=$EF03;
|
|
RealModeIntr($21,regs);
|
|
IsConnectionIDinUse:=(ptarr(nwPtr(regs.es,regs.si))^[(ConnectionID-1)*32]
|
|
<> $00 )
|
|
end;
|
|
end;
|
|
|
|
Function GetUserAtConnection( ConnectionNbr:byte; var username: string):boolean;
|
|
{This function provides a shorter method of obtaining just the USERID.}
|
|
var id:LongInt;
|
|
typ:word;
|
|
time:TnovTime;
|
|
begin
|
|
getUserAtConnection:=GetConnectionInformation(ConnectionNbr,username,typ,id,time);
|
|
end;
|
|
|
|
|
|
Function GetEffectiveConnectionID(Var connId:byte):boolean;
|
|
begin
|
|
if NOT (GetPreferredConnectionID(connId) and (connId<>0))
|
|
then if NOT (GetDefaultConnectionID(ConnId) and (connId<>0))
|
|
then GetPrimaryConnectionID(ConnId);
|
|
GetEffectiveConnectionID:=(result1=$00);
|
|
end;
|
|
|
|
|
|
Function GetObjectLoginControl(ObjName:string; ObjType:word;
|
|
VAR LoginControlInfo:TloginControl):boolean;
|
|
{ Caller must have access to the bindery property LOGIN_CONTROL.
|
|
Default: you need to be supervisor-equivalent or the object the property
|
|
is associated with. (reading your 'own' information)
|
|
|
|
PasswordcontrolFlag:
|
|
00 User is allowed to change PW.
|
|
01 User is NOT allowed to change PW.
|
|
02 User is allowed to change PW, but the new password must be unique.
|
|
03 User is NOT allowed to change PW, and a new password, to be changed
|
|
by the supervisor, must be unique.
|
|
}
|
|
Var LCpropVal:Tproperty;
|
|
lc:record
|
|
_AccExpDate :array[1..3] of byte; {yy mm dd}
|
|
_AccDisabled :boolean;
|
|
_PWexpDate :array[1..3] of byte; {yy mm dd}
|
|
_GraceLoginsRemaining:byte;
|
|
_DaysBetwPWchanges :word; {hi-lo}
|
|
_MaxGraceLogins :byte;
|
|
_minPWlen :byte;
|
|
_unknown1 :byte; {! = hi-byte of maxConcConn }
|
|
_MaxConcConn :byte;
|
|
_loginTimes :array[1..42] of byte;
|
|
_LastLoginTime :array[1..6] of byte; {yy mm dd hh mm ss}
|
|
_PWcontrol :byte;
|
|
_unknown2 :byte; { not used }
|
|
_MaxDiskSpace :Longint; { hi-lo }
|
|
_unknown3 :Byte; {! = hi-byte of bad login count }
|
|
_badLoginCount :byte;
|
|
_AccountResetTime :LongInt; { minutes since 1/1/1985 }
|
|
_lastIntruderAddress :TinterNetworkAddress;
|
|
end ABSOLUTE LCpropVal;
|
|
moreSegments:boolean;
|
|
propFlags:byte;
|
|
|
|
Procedure Min2NovTime(m:Longint; Var time:TnovTime);
|
|
Const darr:array[1..12] of word=(0,31,59,90,120,151,181,212,243,273,304,334);
|
|
Var d,dr:word;
|
|
i,Lastleap:byte;
|
|
begin
|
|
d:=(m div 1440);
|
|
i:=0;
|
|
lastLeap:=84;
|
|
while d>((3+(i*4))*365)+31+28
|
|
do begin
|
|
dec(d);
|
|
lastLeap:=85+3+(i*4);
|
|
inc(i);
|
|
end;
|
|
WITH time
|
|
do begin
|
|
year:=(d DIV 365)+85;
|
|
dr:=(d MOD 365);
|
|
month:=1;
|
|
while (month<12) and (dr>darr[month+1]) do inc(month);
|
|
day:=(dr-darr[month]);
|
|
if (day=28) and (month=2) and (lastLeap=year)
|
|
then inc(day);
|
|
dr:=(m mod 1440);
|
|
hour:=(dr div 60);
|
|
min:=(dr mod 60);
|
|
sec:=0;
|
|
end;
|
|
end;
|
|
begin
|
|
IF nwBindry.ReadPropertyValue(ObjName,ObjType,'LOGIN_CONTROL',1,
|
|
LCpropval,moreSegments,propFlags)
|
|
then begin
|
|
FillChar(LoginControlInfo,SizeOf(LoginControlInfo),#0);
|
|
With LoginControlInfo
|
|
do begin
|
|
AccountDisabled :=lc._AccDisabled;
|
|
move(lc._AccExpDate[1],AccountExpirationDate.year,3);
|
|
move(lc._PWexpDate[1],PasswordExpirationDate.year,3);
|
|
MinimumPasswordLength :=lc._minPWlen;
|
|
PasswordControlFlag :=lc._PWcontrol;
|
|
DaysBetweenPasswordChanges:=swap(lc._DaysBetwPWchanges);
|
|
Move(lc._lastLoginTime[1],LastLoginTime.year,6);
|
|
GraceLoginsRemaining :=lc._GraceLoginsRemaining;
|
|
MaxGraceLoginsAllowed :=lc._maxGraceLogins;
|
|
BadLoginCount :=lc._badLoginCount;
|
|
Min2NovTime(Lswap(lc._AccountResetTime),AccountResetTime);
|
|
LastIntruderAddress :=lc._LastIntruderAddress;
|
|
LastIntruderAddress.socket:=swap(LastIntruderAddress.socket); {force lo-hi}
|
|
MaxConcurrentConnections :=lc._MaxConcConn;
|
|
Move(lc._LoginTimes[1],LoginTimes[1],42);
|
|
|
|
DiskSpace :=Lswap(lc._MaxDiskSpace);
|
|
end;
|
|
result1:=$00;
|
|
end
|
|
else result1:=nwBindry.result1;
|
|
GetObjectLoginControl:=(result1=0);
|
|
end;
|
|
|
|
Function ObjectCanLoginAt(ObjName:String; ObjType:Word;
|
|
LoginTime:TnovTime ):Boolean;
|
|
{ Caller must have access to the bindery property LOGIN_CONTROL.
|
|
Default: you need to be supervisor-equivalent or the object the property
|
|
is associated with. (reading your 'own' information)
|
|
|
|
-If one or more of the fields hour,min,sec,dayOfWeek contain a value >0,
|
|
the supplied time will be checked against the login timerestrictions.
|
|
(this means that checking '00:00 on sundays' is impossible)
|
|
-If one or more of the fields year,month,day contain a value >0 , the
|
|
date will be checked with the expiration date of the account and
|
|
with the Account disabled Flag. }
|
|
Var CanLog:Boolean;
|
|
Info:Tlogincontrol;
|
|
half_hrs:word;
|
|
begin
|
|
IF GetObjectLoginControl(ObjName,ObjType,Info)
|
|
then begin
|
|
if (logintime.month>0) and (loginTime.day>0)
|
|
then CanLog:=((NOT Info.AccountDisabled) and
|
|
IsLaterNovTime(Info.AccountExpirationDate,loginTime))
|
|
else CanLog:=true;
|
|
if (logintime.hour>0) or (loginTime.min>0)
|
|
or (logintime.sec>0) or (logintime.DayOfWeek>0)
|
|
then begin
|
|
half_hrs:=(loginTime.DayOfWeek * 48)+(LoginTime.hour *2);
|
|
if LoginTime.min>=30
|
|
then inc(half_hrs);
|
|
If half_hrs>=336
|
|
then result1:=$122
|
|
else CanLog:=CanLog AND
|
|
((Info.LoginTimes[(half_hrs DIV 8)+1]
|
|
AND (1 SHL (half_hrs MOD 8)) ) >0)
|
|
end;
|
|
end
|
|
else begin
|
|
CanLog:=(result1=$FB); {no such property}
|
|
result1:=0;
|
|
end;
|
|
ObjectCanLoginAt:=(result1=0) and CanLog;
|
|
end;
|
|
|
|
Function GetObjectNodeControl( ObjName:string; ObjType:word;
|
|
{i/o} Var seqNbr:integer;
|
|
{out} Var NodeControlInfo:TnodeControl):boolean;
|
|
Var NCpropVal:Tproperty;
|
|
moreSegments:boolean;
|
|
propFlags:byte;
|
|
begin
|
|
if seqNbr=$FBFB
|
|
then result1:=$EC
|
|
else begin
|
|
if seqNbr<1 then seqNbr:=1;
|
|
IF nwBindry.ReadPropertyValue(ObjName,ObjType,'NODE_CONTROL',seqNbr,
|
|
NCpropval,moreSegments,propFlags)
|
|
then begin
|
|
Move(NCpropVal,NodeControlInfo,120);
|
|
if moreSegments
|
|
then inc(seqNbr)
|
|
else seqNbr:=Integer($FBFB);
|
|
end
|
|
else result1:=nwBindry.result1;
|
|
end;
|
|
GetObjectNodeControl:=(result1=0);
|
|
{ $EC No more records (no such segment);
|
|
$FB No restrictions found (No such property) }
|
|
end;
|
|
|
|
|
|
end. { end of unit nwConn }
|
|
|