{$X+,B-,V-} {essential compiler directives}

UNIT nwServ;

{ nwServ unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R. Spronk }

INTERFACE

uses nwIntr,NwMisc,nwConn;

Var result:word;

{ Primary Functions:                      Interrupt: Comments:

* CheckConsolePrivileges                  (F217/C8)
* ClearConnectionNumber                   (F217/D2)
* DisableFileServerLogin                  (F217/CB)
. DisableTransactionTracking              (F217/CF)
* DownFileServer                          (F217/D3)
* EnableFileServerLogin                   (F217/CC)
. EnableTransactionTracking               (F217/D0)
* GetConnectionsOpenFiles                 (F217/EB)
  GetConnectionsUsingAFile                (F217/EC)
* GetDiskUtilization                      (F217/0E)
* GetFileServerDateAndTime                (F214)
* GetFileServerDescriptionStrings         (F217/C9)
* GetFileServerLoginStatus                (F217/CD)
* GetNetworkSerialNumber                  (F217/12)
* GetFileServerInformation                (F217/11)
* SetFileServerDateAndTime                (F217/CA)
* VerifyNetworkSerialNumber               (F217/0C)

  Secondary functions:

* CheckNetwareVersion

  Not supported by netware 3.x: (2.x only)

- GetBinderyObjectDiskSpaceLeft           (F217/E6) (failed during testing)
- GetConnectionsTaskInformation           (E3../DA)
- GetConnectionsUsageStats                (E3../E5)
- GetConnectionsUsingAFile                (E3../DC)
- GetDiskCacheStats                       (E3../D6)
- GetDiskChannelStats                     (E3../D9)
- GetDriveMappingTable                    (E3../D7)
- GetFileServerLANIOStats                 (E3../E7)
- GetFileServerMiscInformation            (E3../E8)
- GetFileSystemStats                      (E3../D4)
- GetLANDriverConfigInfo                  (E3../E3)
- GetLogicalRecordInformation             (E3../E0)
- GetLogicalRecordsByConnection           (E3../DF)
- GetPhysicalDiskStats                    (E3../D8)
- GetPhysicalRecordLocksByFile            (E3../DE)
- GetPhysRecLocksByConnectAndFile         (E3../DD)
}


Type TFileServerInformation
               =Record
                ServerName         : string[48];
                NetwareVersion     : Byte;
                NetwareSubVersion  : Byte; { 0..99 }
                ConnectionsMax     : word;
                ConnectionsInUse   : word;
                MaxConnVol         : word; { max connected volumes }
                {---Advanced Netware 2.1x/3.x------------}
                OS_revision        : byte;
                SFT_level          : byte;
                TTS_level          : byte;
                peak_conn_used     : word; { max simult.used connections}
                accounting_version : byte;
                vap_version        : byte;
                queuing_version               : byte;
                print_server_version          : byte;
                virtual_console_version       : byte;
                security_restrictions_level   : byte;
                Internetwork_bridge_version   : byte;
                Undefined                     : Array [1..60] of Byte;
                End;

Type TfileInfoRecord=record
                     TaskNbr      :Word;
                     LockType     :Byte; { 00 no lock; FE file lock; FF locked by Begin Share File Set }
                     AccessFlag   :Byte;
                     LockFlag     :Byte;
                     VolNbr       :Byte; { 0..31 }
                     ParentEntryId:Longint;
                     DirEntryId   :Longint;
                     ForkCount    :Byte;
                     NStype       :Byte;
                     FileName     :String;
                     end;
     TfileInfoRecList=array[1..28] of TfileInfoRecord;

Type TfileUsageList=record
                    UseCount         :word;
                    OpenCount        :word;
                    OpenForReadCount :word;
                    OpenForWriteCount:word;
                    DenyReadCount    :word;
                    DenyWriteCount   :word;
                    LockFlag         :Byte; { boolean }
                    NStype           :Byte; { Fork Count = File siz? of NStype? }
                    NbrOfRec         :word; { max 70 }
                    FileUsage:array[1..70] of record
                                              ConnNbr   :word;
                                              TaskNbr   :word;
                                              LockType  :byte;
                                              AccessFlag:Byte;
                                              LockFlag  :Byte;
                                              end;
                    end;

{F217/C8 [2.15c+]}
FUNCTION CheckConsolePrivileges : Boolean;

{F217/D2 [2.15c+]}
Function ClearConnectionNumber(connectionNbr:byte):boolean;
{ Console Rights needed;
  -Terminates a connection. }

{F217/CB [2.15c+]}
FUNCTION DisableFileServerLogin : Boolean;

{F217/CF [2.15c+]}
FUNCTION DisableTransactionTracking : Boolean;

{F217/D3 [2.15c+]}
FUNCTION DownFileServer (ForceFlag : Boolean) : Boolean;

{F217/CC [2.15c+]}
FUNCTION EnableFileServerLogin : Boolean;

{F217/D0 [2.15c+]}
FUNCTION EnableTransactionTracking : Boolean;


{F217/EB [3.0+]}
FUNCTION GetConnectionsOpenFiles
           ( ConnNumber         : Byte;
     {i/o:}  var LastRecordSeen : word;
     {out:}  var NbrOfRecords   : word;
             var FileInfo       : TfileInfoRecList ) : Boolean;

{F217/0E [2.15c+]}
FUNCTION GetDiskUtilization(volNbr:byte; objID:Longint;
                        Var usedDirs,usedFiles,usedBlocks:Word ):Boolean;

{F214    [2.15c+]}
FUNCTION GetFileServerDateAndTime ( Var time:TnovTime): Boolean;

{F217/C9 [2.15c+]}
FUNCTION GetFileServerDescriptionStrings(Var companyName,
                                             VersionAndRevision,revisionDate,
                                             copyrightNotice:String
                                         ):Boolean;

{F217/CD [2.15c+]}
FUNCTION GetFileServerLoginStatus (Var LoginEnabled:Boolean): Boolean;
{ if Login is enabled then returns TRUE in LoginEnabled }

{F217/12 [2.15c+]}
Function GetNetworkSerialNumber(Var serialNbr:LongInt; Var ApplicNbr:Word ):Boolean;
{return the serial number and application number for the software
	  installed on the file server}

{F217/11 [2.15c+]}
Function GetFileServerInformation (Var serverInfo:TFileServerInformation):boolean;
{determine the version of software installed on the file server and how it is configured}

{F217/CA [2.15c+]}
FUNCTION SetFileServerDateAndTime(time:TnovTime):Boolean;
{need console operator privileges to do this}

{F217/OC [2.15c+]}
Function VerifyNetworkSerialNumber(serialNbr: LongInt ;
                               Var ApplicNbr: Word     ):Boolean;
{if the network serial number to be verified is correct, the reply
	  buffer will contain the corresponding application number }

{*********************** Secondary Functions ******************************}

{ [1.x/2.x/3.x] }
FUNCTION CheckNetwareVersion(MinimumVersion,MinimumSubVersion,
                             MinimumRevision,MinimumSFT,MinimumTTS:word):Boolean;

IMPLEMENTATION{=============================================================}


{F217/D2 [2.15c+]}
Function ClearConnectionNumber(connectionNbr:byte):boolean;
{ Console Rights needed;
  -Terminates a connection. }
Type Treq=record
          len : word;
          subf: byte;
          _connNbr:byte;
          end;
     TPreq=^Treq;
begin
With TPreq(GlobalReqBuf)^
do begin
   len:=2;
   subf:=$D2;
   _connNbr:=connectionNbr
   end;
F2SystemCall($17,SizeOf(Treq),0,result);
ClearConnectionNumber:=(result=0);
{result codes: 00 successful; C6 No Console Rights}
end;

{F214 [2.15c+]}
FUNCTION GetFileServerDateAndTime ( Var time:TnovTime): Boolean;
Type Trep=TnovTime;
     TPrep=^Trep;
BEGIN
F2SystemCall($14,0,SizeOf(Trep),result);
Time:=TPrep(GlobalreplyBuf)^;
if time.year>100
 then time.year:=time.year-100;
{ year<80 : 21st century }
result:=0;
getFileServerDateAndTime:=TRUE;
end;


{F217/CA [2.15c+]}
FUNCTION SetFileServerDateAndTime (time:TnovTime): Boolean;
Type Treq=record
          Len:word;
          subF:byte;
          _time:TnovTime
          end;
     TPreq=^Treq;
BEGIN
{ year<80 : 21st century }
WITH TPreq(GlobalReqBuf)^
do begin
   Len:=SizeOf(Treq)-3; { dow is not a parameter }
   subF:=$CA;
   _time:=time;
   end;
F2SystemCall($17,SizeOf(Treq),0,result);
SetFileServerDateAndTime:=(Result=$00);
{ Resulcodes: $00 Success; $C6 No Console Operator Rights }
end;


{F217/11 [2.15c+]}
Function GetFileServerInformation (Var serverInfo:TFileServerInformation):boolean;
{determine the version of software installed on the file server and how it is configured}

{SeeAlso: GetDiskUtilization, GetNetworkSerialNumber, GetFileServerLoginStatus,
          GetFileServerDateAndTime}

Type TReq=Record
          Len  : word;
          SubF : Byte;
          End;
     TRep=TFileServerInformation;
     TPreq=^Treq;
     TPrep=^Trep;

Var t:word;
Begin
With TPreq(GlobalReqBuf)^
Do Begin
   Len := 1;
   SubF:= $11;
   End;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep)-1,result);
Move(GlobalReplyBuf^[1],GlobalReplyBuf^[2],SizeOf(Trep)-1);
serverInfo:=TPrep(GlobalReplyBuf)^;
With serverinfo
do begin
   connectionsMax  :=Swap(connectionsMax);   { force lo-hi again }
   ConnectionsInUse:=Swap(connectionsInUse);
   MaxConnVol      :=Swap(maxConnVol);
   peak_conn_used  :=Swap(peak_conn_used);
   for t:=48 downto 1
    do if serverInfo.serverName[t]=#0
        then serverInfo.serverName[0]:=chr(t-1);
   end;
GetFileServerInformation:=(result=0);
End;



{F217/C9 [2.15c+]}
FUNCTION GetFileServerDescriptionStrings(Var companyName,
                                             VersionAndRevision,revisionDate,
                                             copyrightNotice:String
                                         ):Boolean;
{SeeAlso: GetFileServerLoginStatus, GetFileServerInformation. }
Type Treq=record
          len : word;
          subf: byte;
          end;
     Trep=record
          stuff : array [1..512] of byte;
          end;
     TPreq=^Treq;
     TPrep=^Trep;
Var x,xofs:word;
begin
With TPreq(GlobalReqBuf)^
do begin
   len  := 1;
   subf := $c9;
   end;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
companyName:=''; VersionAndRevision:='';
revisionDate:=''; copyrightNotice:='';
if result=$00
 then with TPrep(GlobalReplyBuf)^
      do begin
         x:=1;xofs:=x;
         while (stuff[x]<>$00) and (x<512) do inc(x);
         ZStrCopy(companyName,stuff[xofs],x-xofs);

         inc(x);xofs:=x; { skip 1 zero. ? skip more zero's? }
         While (stuff[x]<>$00) and (x<512) do inc(x);
         ZStrCopy(VersionAndRevision,stuff[xofs],x-xofs);

         inc(x);xofs:=x;
         While (stuff[x]<>$00) and (x<512) do inc(x);
         ZStrCopy(revisionDate,stuff[xofs],x-xofs); { mm/dd/yy }

         inc(x);xofs:=x;
         While (stuff[x]<>$00) and (x<512) do inc(x);
         ZStrCopy(copyrightNotice,stuff[xofs],x-xofs);
         end;
GetFileServerDescriptionStrings:=(Result=$00);
end;



{F217/D3 [2.15c+]}
FUNCTION DownFileServer (ForceFlag : Boolean) : Boolean;
Type Treq=record
          len  : word;
          subf : byte;
          flag : byte;
          end;
     TPreq=^Treq;
BEGIN
With TPreq(GlobalReqBuf)^
do begin
   len  := 2;
   subf := $D3;
   if ForceFlag then flag := $FF { non-zero }
                else flag := $00;
   end;
F2SystemCall($17,SizeOf(Treq),0,result);
DownFileServer:=(result=0);
{ resultcodes: 00=successful; C6 No Console Rights ; FF Open Files}
end;


{F217/CF [3.x]}
FUNCTION DisableTransactionTracking : Boolean;
{ Caller must have console-operator rights. }
Type Treq=record
          len : word;
          subf: byte
          end;
     TPreq=^Treq;
BEGIN
With TPreq(GlobalReqBuf)^
 do begin
    len := 1;
    subf:= $CF;
    end;
F2SystemCall($17,SizeOf(Treq),0,result);
DisableTransactionTracking:=(result=0);
{ resultcodes: 00=successful; C6 No Console Rights }
end;


{F217/D0 [3.x]}
FUNCTION EnableTransactionTracking : Boolean;
{ Caller must have console-operator rights. }
Type Treq=record
          len : word;
          subf: byte
          end;
     TPreq=^Treq;
BEGIN
With TPreq(GlobalReqBuf)^
 do begin
    len := 1;
    subf:= $D0;
    end;
F2SystemCall($17,SizeOf(Treq),0,result);
EnableTransactionTracking:=(result=0);
{ resultcodes: 00=successful; C6 No Console Rights }
end;


{F217/CB [2.15c+]}
FUNCTION DisableFileServerLogin : Boolean;
{ Caller must have console-operator rights. }
Type Treq=record
          len : word;
          subf: byte
          end;
     TPreq=^Treq;
BEGIN
With TPreq(GlobalReqBuf)^
 do begin
    len := 1;
    subf:= $CB;
    end;
F2SystemCall($17,SizeOf(Treq),0,result);
DisableFileServerLogin:=(result=0);
{ resultcodes: 00=successful; C6 No Console Rights }
end;



{F217/CC [2.15c+]}
FUNCTION EnableFileServerLogin : Boolean;
{ Caller needs console-operator rights. }
Type Treq=record
          len : word;
          subf: byte
          end;
     TPreq=^Treq;
BEGIN
With TPreq(GlobalReqBuf)^
 do begin
    len := 1;
    subf:= $CC;
    end;
F2SystemCall($17,SizeOf(Treq),0,result);
EnableFileServerLogin:=(result=0);
{ resultcodes: 00=successful; C6 No Console Rights }
end;



{F217/CD [2.15c+]}
FUNCTION GetFileServerLoginStatus( Var LoginEnabled:Boolean ): Boolean;
{ if Login is enabled then returns TRUE in LoginEnabled }
{ result byte:  00h  - Success, C6h No Console Rights }
{ Caller must have operator status.}
Type TReq=record
          Len     : Word;
          SubF    : Byte;
          end;
     TRep=record
          Flag    : Byte;
          end;
     TPreq=^Treq;
     TPrep=^Trep;
begin
with TPreq(GlobalReqBuf)^
 do begin
    Len     := 1;
    SubF    := $CD;
    end;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
LoginEnabled:=Boolean(TPrep(GlobalReplyBuf)^.Flag);
GetFileServerLoginStatus := (result=0);
end;


{F217/C8 [2.15c+]}
FUNCTION CheckConsolePrivileges : Boolean;
Type TReq=record
          Len  : Word;
          SubF : Byte;
          end;
     TPreq=^Treq;
begin
with TPReq(GlobalReqBuf)^
 do begin
    Len  := 1;
    SubF := $C8;
    end;
F2SystemCall($17,SizeOf(Treq),0,result);
CheckConsolePrivileges := (Result=$00);
{ result byte:  00h  - Success, C6h No Console Rights }
end;


{F217/EB [3.0+]}
FUNCTION GetConnectionsOpenFiles
           ( ConnNumber         : Byte;
     {i/o:}  var LastRecordSeen : word;
     {out:}  var NbrOfRecords   : word;
             var FileInfo       : TfileInfoRecList ) : Boolean;

{ the calling workstation must have console operator privileges }
{ LastRecordSeen is an i/o parameter;
  -An initial value of 0 has to be supplied;
  -The function can be called until LastRecordSeen becomes 0,
   indicating the end of the FIR-list.

  to be called iteratively. }

Type TReq=record
          len           :word;
          subf          :byte;
          logicalConnNbr:word;
          lastRecSeen   :word; {lo-hi, $0000 on first call }
          end;
     TRep=record
          nextReqRec : word; { lo-hi, use as lastRecSeen in next iterative call }
                             { $0000 if no more records }
          RecCount   : word;
          FIRbuf:array[1..508] of byte;
          end;
     TPreq=^Treq;
     TPrep=^Trep;
Var t,Foff:Word;
begin

With TPreq(GlobalReqBuf)^
 do begin
    len:=sizeof(Treq)-2;
    subf:=$EB;
    logicalConnNbr:=connNumber;
    lastRecSeen:=LastRecordSeen; { force hi-lo }
    end;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
if result=$00
 then with TPrep(GlobalReplyBuf)^
      do begin
         { Copy recCount FIRs from FIRbuf to the FileInfo[] array }
         LastRecordSeen:=NextReqRec;
         NbrOfrecords:=RecCount;
         Foff:=0;
         For t:=1 to RecCount
          do begin
             Move(FIRbuf[1+Foff],FileInfo[t],17+FIRbuf[Foff+17]);
             inc(Foff,17+FIRbuf[Foff+17]);
             { Direntry and ParentEntry may have to be swapped lo-hi }
             end;
         end
 else begin
      NbrOfRecords:=0;
      LastRecordSeen:=0;
      end;
GetConnectionsOpenFiles:=(result=$00);
{ errorcodes: $00 Success; $C6 no console privileges }
end;


{F217/EC }
Function GetConnectionsUsingAFile(VolNbr:Byte; EntryId:Longint; NStype:byte;
                            {i/o} Var LastRecordSeen:word;
                                  Var NbrOfRecords:Word;
                                  Var FileInfo:TfileUsageList):boolean;
{ This call returns all connection numbers using the file specified
  by the Volume Number and Directory Entry Id. }

{ !! UNDER CONSTRUCTION !! }

Type TReq=record
          len        :word;
          subf       :byte;
          NStype     :Byte;  {= data stream type / Fork type }
          VolNbr     :Byte;
          DirEntryId :Longint;
          LastRecSeen:Word;   {initially set to 0}
          end;

     TRep=record
          NextRec          :word; { iteration }

          UseCount         :word;
          OpenCount        :word;
          OpenForReadCount :word;
          OpenForWriteCount:word;
          DenyReadCount    :word;
          DenyWriteCount   :word;
          LockFlag         :Byte; { boolean }
          NStype           :Byte; { Fork Count -> ?? NStype }
          NbrOfRec         :word; { max 70 }
          FileUsage:array[1..70] of record
                                    ConnNbr   :word;
                                    TaskNbr   :word;
                                    LockType  :byte;
                                    AccessFlag:Byte;
                                    LockFlag  :Byte;
                                    end;
          end;
     TPreq=^Treq;
     TPrep=^Trep;
begin
With TPreq(GlobalReqBuf)^
 do begin
    len:=sizeof(Treq)-2;
    subf:=$EC;

    end;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
if result=$00
 then with TPrep(GlobalReplyBuf)^
      do begin

         end
 else begin
      NbrOfRecords:=0;
      LastRecordSeen:=0;
      end;
GetConnectionsUsingAFile:=(result=$00);
{ errorcodes: $00 Success; $C6 no console privileges }
end;


{F217/0E [2.15c+]}
FUNCTION GetDiskUtilization(volNbr:byte; objID:Longint;
                        Var usedDirs,usedFiles,usedBlocks:Word ):Boolean;
{ SeeAlso: GetFileServerInformation,getBinderyObjectDiskSpaceLeft }
Type TReq=record
          Len  : Word;
          SubF : Byte;
          _volNbr:Byte;
          _objID:longInt; { hi-lo }
          end;
     TRep=record
          _volNbr:Byte;
          _objID:Longint; {hi-lo}
          _usedDirs,
          _usedFiles,
          _usedBlocks:Word; { all hi-lo }
          end;
    TPreq=^Treq;
    TPrep=^Trep;
begin
with TPReq(GlobalReqBuf)^
 do begin
    Len  := SizeOf(TReq)-2;
    SubF := $0E;
    _volNbr:=volNbr;
    _objID:=Lswap(objID);
    end;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
if result=$00
then begin
     with TPrep(GlobalReplyBuf)^
     do begin
        usedDirs:=swap(_usedDirs);    { force lo-hi }
        usedFiles:=swap(_usedFiles);  { force lo-hi }
        usedBlocks:=swap(_usedBlocks);{ force lo-hi }
        end;
     end;
GetDiskUtilization:=(result=$00);
{Resultcodes: 00h successful; 98h volume doesn't exist
              89h No Search Privileges
   	      F2h no Object read privileges }
end;


{F217/12 [2.15c+]}
Function GetNetworkSerialNumber(Var serialNbr:LongInt; Var ApplicNbr:Word ):Boolean;
{return the serial number and application number for the software
	  installed on the file server}
{SeeAlso: VerifyNetworkSerialNumber,GetFileServerInformation}
Type TReq=record
          Len     : Word;
          SubF    : Byte;
          end;
     TRep=record
          _serNbr   : LongInt; {hi-lo}
          _applicNbr: Word;    {hi-lo}
          end;
     TPreq=^Treq;
     TPrep=^Trep;
begin
with TPreq(GlobalReqBuf)^
 do begin
    Len     := 1;
    SubF    := $12;
    end;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
with TPrep(GlobalReplyBuf)^
 do begin
    ApplicNbr:=swap(_applicNbr);   { force lo-hi }
    serialNbr:=Lswap(_serNbr);     { force lo-hi }
    end;
GetNetworkSerialNumber := (result=0);
end;



{F217/OC [2.15c+]}
Function VerifyNetworkSerialNumber(serialNbr: LongInt ;
                               Var ApplicNbr: Word     ):Boolean;
{if the network serial number to be verified is correct, the reply
	  buffer will contain the corresponding application number }
{SeeAlso: GetNetworkSerialNumber}
Type Treq=record
          Len        : Word;
          SubF       : Byte;
          _netwSerNbr: LongInt; {hi-lo}
          end;
     TRep=record
          _applicNbr: word; {hi-lo}
          end;
     TPreq=^Treq;
     TPrep=^Trep;
begin
with TPReq(GlobalReqBuf)^
 do begin
    Len     := 1;
    SubF    := $0C;
    _netwSerNbr:=Lswap(serialNbr);
    end;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
with TPrep(GlobalReplyBuf)^
do begin
   ApplicNbr:=swap(_applicNbr); { force lo-hi }
   end;
VerifyNetworkSerialNumber := (result=0);
end;

{****************** secondary functions ************************************}


FUNCTION CheckNetwareVersion(MinimumVersion,MinimumSubVersion,
                             MinimumRevision,MinimumSFT,MinimumTTS:word):Boolean;
{ checks if the current OS/TTS/SFT version is greater or equal to the minimal version }
Var info:TFileServerInformation;
    res:boolean;
begin
IF GetFileServerInformation(info)
then begin
     IF (info.NetwareVersion>MinimumVersion)
       then res:=true
       else if (info.NetwareVersion=MinimumVersion)
               AND (info.NetwareSubVersion>MinimumSubVersion)
            then res:=true
            else if (info.NetwareVersion=MinimumVersion)
                    AND (info.NetwareSubVersion=MinimumSubVersion)
                    AND (info.OS_Revision>=MinimumRevision)
                 then res:=true
                 else res:=false
     end
else res:=false;

CheckNetwareVersion:=res AND (info.SFT_Level>=MinimumSFT)
                         AND (info.TTS_Level>=MinimumTTS)
end;

end. {unit nwServ}