{$X+,B-,V-} {essential compiler directives}

UNIT nwMess;

{ nwMess unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R.Spronk }

INTERFACE

Uses nwIntr,nwMisc;

{ Primary functions:                    Interrupt: comments:

* BroadcastToConsole                    (F215/09)
* GetBroadcastMessage                   (F215/01)
* GetBroadcastMode                      (DE..(..04))
* SendBroadcastMessage                  (F215/00)
* SendConsoleBroadcast                  (F217/D1)
* SetBroadcastMode                      (DE..(..0x)), x= 0,1,2,3

  Secondary Functions:

* SendMessageToUser

  Not implemented:

- CheckPipeStatus                       (F215/08)  (1)
- CloseMessagePipe                      (F215/07)  (1)
- DisableStationBroadcast               (F215/02)  (3)
- EnableStationBroadcast                (F215/03)  (3)
- GetPersonalMessage                    (F215/05)  (1)
- LogNetworkMessage                     (F215/0D)  (2)
- OpenMessagePipe                       (F215/06)  (1)
- SendPersonalMessage                   (F215/04)  (1)

Notes:
 (1) These calls are NOT supported by Netware 386 versions shipped after
     December 1990, because they use pipe mechanisms, which cause a
     considerable deal of server overhead.
     These functions are not implemented in this unit.
     Use IPX/SPX peer-to-peer communication instead (nwIPX,nwSPX,nwPEP).
 (2) Network msg file no longer supported by 3.x
 (3) Not supported by Netware 3.x. Use SetBroadcastMode instead.
}

Var result:word;

{F215/09 [2.15c+]}
Function BroadcastToConsole(message:string):boolean;
{ broadcast a message to the file server console. }

{F215/01 [2.15c+]}
Function GetBroadcastMessage(var bmessage: string):boolean;
{ Reads a broadcast message strored at server }

{DE..(..04) [1.x/2.x/ 3.x]}
Function GetBroadcastMode(var bmode:byte):boolean;
{ Returns the message mode. }

{F215/00 [2.15c+]}
Function SendBroadcastMessage( message:string;
                               connCount:byte;
                               connList:TconnectionList;
                               VAR resultlist:TconnectionList ):boolean;
{ Sends a broadcast message to a number of logical connections. }

{DE..(..0n) n=0,1,2,3 [1.x/2.x/3.x]}
Function SetBroadcastMode(bmode:byte):boolean;

{F217/D1 [2.15c+]}
Function SendConsoleBroadcast(message:string; connCount:byte;
                              connList:TconnectionList       ):boolean;
{ Sends a message to a number of connections, as if the message was send
 by a console broadcast command. Console oprator privileges required. }

{--------------------Secondary Functions-------------------------------}

Procedure SendMessageToUser(UserName,Message:String);
{ sends a message to a (group of) users.
  The username may contain wildcards (* and ?).
  The message will not be received by stations whose status is CASTOFF.}


IMPLEMENTATION {============================================================}

USES nwConn;

{DE..(..04) [1.x/2.x/ 3.x]}
Function GetBroadcastMode(var bmode:byte):boolean;
{ Returns the message mode.

  00 Server Stores : Netware Messages and User Messages,
     Shell automaticly displays messages.
  01 Server Stores : Server Messages. (User messages discarded)
     Shell automaticly displays messages.
  02 Server stores : Server messages only.
     Applications have to use GetBroadCastMessage to see if there is a message.
  03 Server stores : Server messages and User messages.
     Applications have to use GetBroadCastMessage to see if there is a message. }
var regs : TTregisters;
begin
regs.ah := $de;
regs.dl := $04;
RealModeIntr($21,regs);
bmode := regs.al;
result:=$00; { the call has no return codes }
GetBroadCastMode:=True;
end;


{DE..(..0n) n=0,1,2,3 [1.x/2.x/3.x]}
Function SetBroadcastMode(bmode:byte):boolean;
{ Sets the new message mode.

  possible resultcode: $FF ( illegal broadcastmode supplied or
                             the broadcastmode after the call is not equal
                             to the intended broadcast mode )

  00 Server Stores : Netware Messages and User Messages,
     Shell automaticly displays messages.
  01 Server Stores : Server Messages. (User messages discarded)
     Shell automaticly displays messages.
  02 Server stores : Server messages only.
     Applications have to use GetBroadCastMessage to see if there is a message.
  03 Server stores : Server messages and User messages.
     Applications have to use GetBroadCastMessage to see if there is a message.     }
var regs : TTregisters;
begin
if (bmode <4)
 then begin
      regs.ah := $de;
      regs.dl := bmode;
      RealModeIntr($21,regs);
      if regs.al<>bmode  { if confirmation of new mode unequal desired mode }
       then result:=$FF
       else result:=$00;
      end
 else result:=$FF;
SetBroadcastMode:=(result=0);
end;



{F215/01 [2.15c+]}
Function GetBroadcastMessage(var bmessage: string):boolean;
{ An application should poll this to see if there is a broadcastmessage
  stored (for this workstation) at the default server.
  The message mode must be 2 or 3. (No Notification by Shell)
  If no message was stored at the server, or the message was empty,
  this function will return FALSE and an errorcode of $103. }
Type Treq=record
          len      :word;
          subF     :byte;
          end;
     Trep=record
          _message:string[55];
          end;
     TPreq=^Treq;
     TPrep=^Trep;
BEGIN
With TPreq(GlobalreqBuf)^
 do begin
    subF:=$01;
    len:=1;
    end;
F2SystemCall($15,sizeOf(Treq),sizeOf(Trep),result);
If result=0
 then bmessage:=TPrep(GlobalReplyBuf)^._message;

if bmessage[0]=#0 then result:=$103; { whups! empty message }

GetBroadCastMessage:=(result=0);
{ returncodes:
  00 Successful; FC Message Queue Full;
  FE I/O failure: Lack of dynamic workspace.
  103 No msgs stored at server. }
end;


{F215/00 [2.15c+]}
Function SendBroadcastMessage( message:string;
                               connCount:byte;
                               connList:TconnectionList;
                               VAR resultlist:TconnectionList ):boolean;
{ Sends a broadcast message to a number of logical connections.
  The connectionlist is an array[1..connCount] of logical connection numbers,
  the result of the broadcast can be found in the resultList parameter.
  example:
    connCount=5
    connList=  [ 4,9,1,5,2 ]

    resultList= [$00, $00, $FC, $FD, $FF]

    possible codes in resultList:
      $00: broadcast to this logical connnection was successful.
      $FC: message rejected, buffer for this station already contains a message,
      $FD: invalid connection number
      $FF: The target connection has blocked incoming messages,
           or the target connection is not in use. }
Type Treq=record
          len      :word;
          subF     :byte;
          _connCount     :byte;
          connLandMessage:array[1..306] of byte; { 250 conn, 56 msg }
          end;
     Trep=record
          connCount:byte;
          _ResultList:TconnectionList;
          end;
     TPreq=^Treq;
     TPrep=^Trep;
Var t:byte;
BEGIN
With TPreq(GlobalReqBuf)^
 do begin
    subF:=$00;
    _connCount:=connCount;
    move(connList[1],connLandMessage[1],connCount);
    t:=ord(message[0]); if t>55 then t:=55;
    move(message[0],connLandMessage[connCount+1],t+1);
    len:=3+connCount+t; { 2 bytes + [connList] + len(str) + str[0] }
    end;
F2SystemCall($15,sizeOf(Treq),sizeOf(Trep),result);
If result=0
 then with TPrep(GlobalReplyBuf)^
      do resultList:=_resultlist;
SendBroadcastMessage:=(result=0);
end;


{F215/09 [2.15c+]}
Function BroadcastToConsole(message:string):boolean;
{ broadcast a message to the file server console.
  The message (max 60 chars, in ascii range [$20..$7E]) will be displayed
  at the bottom of the console screen.
  This function truncates the messagelength to 60 and repaces illegal
  characters with a . }
Type Treq=record
          len      :word;
          subF     :byte;
          _message :string;
          end;
     TPreq=^Treq;
Var t:byte;
BEGIN
With TPreq(GlobalReqBuf)^
 do begin
    subF:=$09;
    PstrCopy(_message,message,60);
    for t:=1 to 60
      do if (_message[t]<>#$0) and
            ((_message[t]<#$20) or (_message[t]>#$7E))
         then _message[t]:='.';
    len:=62;
    end;
F2SystemCall($15,sizeOf(Treq),0,result);
BroadcastToConsole:=(result=0);
{ resultcodes:  00 success ; $FC message queue full ;
               $FE I/O failure: lack of dynamic workspace }
end;


{F217/D1 [2.15c+]}
Function SendConsoleBroadcast(message:string; connCount:byte;
                              connList:TconnectionList       ):boolean;
{Sends a message to a number of connections, as if the message was send
 by a console oprator. Console operator privileges required.
 If connCount equals 0, then the message is send to all connections. }
Type Treq=record
          len      :word;
          subF     :byte;
          _ConnCount:byte;
          _connAndMess:array[1..306] of byte;
          end;
    TPreq=^Treq;
Var t:byte;
BEGIN
With TPreq(GlobalReqBuf)^
 do begin
    subF:=$D1;
    _connCount:=connCount;
    Move(connList[1],_connAndMess[1],connCount);
    t:=ord(message[0]); if t>55 then t:=55;
    {!! to do: strip hi-bit of message.. }
    Move(message[0],_connAndMess[connCount+1],t+1);
    len:=t+connCount+3;
    end;
F2SystemCall($17,sizeOf(Treq),0,result);
SendConsoleBroadcast:=(result=0);
{Resultcodes: $00 success; $C6 No Console Rights}
end;

{=================== Secondary Functions ===================================}

Procedure SendMessageToUser(UserName,Message:String);
{ sends a message to a (group of) users.
  The username may contain wildcards (* and ?).
  The message will not be received by stations whose status is CASTOFF.}
{ calls nwConn.getObjectConnectionNumber and nwMess.SendBroadcastMessage }
Var NbrOfConn:byte;
    connList,ResultList:TconnectionList;
begin
IF NwConn.GetObjectConnectionNumbers(UserName,1 {OT_USER},NbrOfConn,connList)
   AND (NbrOfConn>0)
 then SendBroadcastMessage(Message,NbrOfConn,connList,ResultList);
end;


end. {unit nwMess}
