(*
   I hope somebody finds the following code useful.
This code has been adapted from ALLSWAG.  It returns the Network
station number, user name and full name.  I have tested it with
Novell Netware 3.12 and WFW.

    At least I hope this will save some of you some time.  It took me
some time to figure out exactly how to get it done.  (Now it appears
clearer :))

Even if you don't understand the details, you can still use the
functions.  For the sake of those like me, who are new to the
language:  You can copy the code in between the dotted lines and put
it in a file and use it as a unit.
*)

unit General;

interface
function StationNumber:byte;
Function GetNetUserName : String;
Function GetNetFullName(User_Name : String) : String;

implementation
function StationNumber:byte;  { MY logical Station(connection)-Number }
var
 RetVal : Byte;
begin
 asm
   MOV AH, $DC;
   INT 21H
   MOV RetVal, AL;
 end;
 Result := Retval;
end;


Function GetNetUserName : String;

var
  Request : record                     { Request buffer for "Get Conn Info" }
    Len  : Word;                       { Buffer length - 2                  }
    Func : Byte;                       { Subfunction number ( = $16 )       }
    Conn : Byte                        { Connection number to be researched }
  end;

  Reply    : record                    { Reply buffer for "Get Conn Info"   }
    Len    : Word;                     { Buffer length - 2                  }
    ID     : Longint;                  { Object ID (hi-lo order)            }
    Obj    : Word;                     { Object type (hi-lo order again)    }
    Name   : array[ 1..48 ] of Byte;   { Object name as ASCII string        }
    Time   : array[ 1.. 7 ] of Byte;   { Y, M, D, Hr, Min, Sec, DOW         }
                                       { Y < 80 is in the next century      }
                                       { DOW = 0 -> 6, Sunday -> Saturday   }
    Filler : Byte                      { Call screws up without this!       }
  end;

  W      : Word;
  RetVal : Byte;

begin
                                       { "Get Connection Information"       }
  with Request do                      { Initialize request buffer:         }
  begin
    Len := 2;                                    { Buffer length,           }
    Func := $16;                                 { API function,            }
    Conn := StationNumber                    { Returned in previous call!         }
  end;

  Reply.Len := SizeOf( Reply ) - 2;    { Initialize reply buffer length     }

  asm
   push ds
   push ss
   push es
    MOV AH, $E3;                         { Connection Services API call       }
    LEA SI, Request               { Location of request buffer         }
    PUSH SS
    POP DS
    LEA DI, Reply                { Location of reply buffer           }
    PUSH SS
    POP ES
    INT 21H
    MOV RetVal, AL
    pop ES
    pop SS
    pop DS
  end;

  if ( RetVal = 0 )                        { Success code returned in AL   }
       and ( Hi( Reply.Obj ) = 1 )          { Obj of 1 is a user,           }
       and ( Lo( Reply.Obj ) = 0 ) then     {   stored Hi-Lo                }
    with Reply do
    begin
      Move( Name, Result[ 1 ], 48 );           { Convert ASCIIZ to string }
      Result[ 0 ] := #48;
      W := 1;
      while ( Result[ W ] <> #0 )
            and ( W < 48 ) do
        Inc( W );
      Result[ 0 ] := Char( W - 1 )
    end
  else
    Result := ''
end;


Function GetNetFullName(User_Name : String) : String;
Type
  RequestBuffer = Record
    RequestBufferLength : Word;
    Code                : Byte;
    ObjectType          : Word;
    ObjectNameLength    : Byte;
    ObjectName          : Array[1..48] of char;
    SegmentNumber       : Byte;
    PropertyNameLength  : Byte;
    PropertyName        : Array[1..15] of char;
  end;

  ReplyBuffer = Record
    ReplyBufferLength : Word;
    PropertyValue     : Array[1..128] of char;
    MoreSegments      : Byte;
    PropertyFlags     : Byte;
  end;

Var
  Request : RequestBuffer;
  Reply   : ReplyBuffer;
  PropertyName : String[15];
  Counter : Byte;
  Temp    : String[128];

begin
  PropertyName := 'IDENTIFICATION';
  Request.RequestBufferLength := SizeOf(Request) - 2;
  Request.Code := $3D;
  Request.SegmentNumber := 1;
  Request.ObjectType := $0100;
  Request.ObjectNameLength := SizeOf(Request.ObjectName);
  FillChar(Request.ObjectName, SizeOf(Request.ObjectName), #0);

  For Counter := 1 to length(User_Name) do
    Request.ObjectName[Counter] := User_Name[Counter];

  Request.PropertyNameLength := SizeOf(Request.PropertyName);
  FillChar(Request.PropertyName, SizeOf(Request.PropertyName), #0);

  For Counter := 1 to Length(PropertyName) do
    Request.PropertyName[Counter] := PropertyName[Counter];
  Reply.ReplyBufferLength := SizeOf(Reply) - 2;

 asm
  PUSH SS
  PUSH DS
  MOV AH, $E3;
  LEA SI, Request
  PUSH SS
  POP DS
  LEA DI,Reply
  PUSH SS
  POP ES
  INT 21H
  POP DS
  POP SS
 end;

  Temp := '';
  Counter := 1;
  While (Reply.PropertyValue[Counter] <> #0) do
  begin
    Temp := Temp + Reply.PropertyValue[Counter];
    inc(Counter);
  end;
  Result := Temp;
end;
end.
-------------Code Ends------------------------

Sajan Thomas
Computer and Communication Services Department
Milwaukee School of Engineering
Milwaukee, WI 53202
Tel. (414)-277-7498
(Internet Address: THOMAS@MSOE.EDU)

-------------------------------------------------------------------------------

   Here is a function to get the login date and time from Netware.
The function returns the result in TDateTime format, which can be
formatted with any of the built-in routines.
e.g.
DateString := FormatDateTime('"I  logged in on" dddd, mmmm d, yyyy, ' +
'"at" hh:mm AM/PM', GetLoginTime(stationnumber)); 
 returns the login date and time for the current user. ( It uses the 
StationNumber function that I posted yesterday).
   You can find out the login date and time for any station, provided 
you _know_ the station number.  The results of the function when 
supplied a non-existant station number is unpredictable!!
   Again, this function has been adapted from material found in the 
ALLSWAG.ZIP file.

  Hope this helps someone.

Enjoy,
Sajan.


----code begins--------------------
Function GetLoginTime(LogicalStationNo: Integer):TDateTime;
Var
  I,X            : Integer;
  RequestBuffer  : Record
                     PacketLength : Integer;
                     FunctionVal  : Byte;
                     ConnectionNo : Byte;
                   end;
  ReplyBuffer    : Record
                     ReturnLength : Integer;
                     UniqueID1    : Packed Array [1..2] of Byte;
                     UniqueID2    : Packed Array [1..2] of Byte;
                     ConnType     : Packed Array [1..2] of Byte;
                     ObjectName   : Packed Array [1..48] of Byte;
                     LoginTime    : Packed Array [1..8] of Byte;
                   end;
  Month          : String[3];
  Year,
  Day,
  Hour,
  Minute         : String[2];
  retval : byte;

Begin
  With RequestBuffer Do begin
    PacketLength := 2;
    FunctionVal := 22;  { 22 = Get Station Info }
    ConnectionNo := LogicalStationNo;
  end;
  ReplyBuffer.ReturnLength := 62;
  asm
    push ds
    push ss
    mov ah, $e3;
    lea SI, RequestBuffer
    push ss
    pop ds
    lea di, ReplyBuffer
    push ss
    pop es
    int 21h
    mov retval, al
    pop ss
    pop ds
  end;
  if RetVal = 0 then
   begin
    With ReplyBuffer Do
     begin
       Str(LoginTime[1]:2,Year);
       Str(LoginTime[2], Month);
       Str(LoginTime[3]:2,Day);
       Str(LoginTime[4]:2,Hour);
       Str(LoginTime[5]:2,Minute);
       if Day[1] = ' ' then Day[1] := '0';
       if Hour[1] = ' ' then Hour[1] := '0';
       if Minute[1] = ' ' then Minute[1] := '0';
       Result := StrToDateTime(Month+'/'+Day+'/'+Year+' ' + Hour + ':' + Minute);
    end { With };
   end;
End;
----------code ends-----------------

Sajan Thomas
Computer and Communication Services Department
Milwaukee School of Engineering
Milwaukee, WI 53202
Tel. (414)-277-7498
(Internet Address: THOMAS@MSOE.EDU)

unit Netapi;

interface
type
 TFileServerName = array [0..48] of char;
 TNodeAddress = record
    nodeHi : longint;
    nodeLo : Integer;
    end;


Function GetConnectionNumber:Longint;
Function GetConnectionID(fileServerName:TFileServerName; var connectionID:integer):Integer;
Function GetDefaultConnectionID:Integer;
Procedure GetFileServerName(connID:integer; var fileservername:TFileServerName);
Function GetInternetAddress(connectionNumber : longint; var networkNumber: longint;
         var physicalNodeAddress:TNodeAddress; var socketNumber: integer):Integer;
Function IntSwap(unswappedInteger : integer):Integer;
Function LongSwap(unswappedLong : longint):Longint;
Function GetNetworkNumber : String;
Function GetNodeAddress : String;
{Call example: FileServerName(GetDefaultConnectionID) }
Function FileServerName(connID : integer) : String;


implementation
Uses SysUtils;
Function GetInternetAddress; external 'NWNETAPI';
Function GetConnectionNumber; external 'NWNETAPI';
Function GetConnectionID; external 'NWNETAPI';
Function GetDefaultConnectionID; external 'NWNETAPI';
Procedure GetFileServerName; external 'NWNETAPI';
Function IntSwap; external 'NWNETAPI';
Function LongSwap; external 'NWNETAPI';

Function GetNetworkNumber : String;
 var
  networkno : longint;
  nodeaddr : TNodeAddress;
  socketno : integer;
Begin
 GetInternetAddress(GetConnectionNumber,networkno, nodeaddr, socketno);
 Result := IntToHex(LongSwap(networkno), 1);
End;



Function GetNodeAddress : String;
 var
  networkno : longint;
  nodeaddr : TNodeAddress;
  socketno : integer;
Begin
 GetInternetAddress(GetConnectionNumber,networkno, nodeaddr, socketno);
 Result := IntToHex(longswap(nodeaddr.nodehi), 1) +
           IntToHex(lo(nodeaddr.nodelo), 1) +
           IntToHex(hi(nodeaddr.nodelo), 1);
End;

Function FileServerName(connID : integer) : String;
Var
 FSName : TFileServerName;
Begin
 FillChar(FSName, 48, ' ');  {need to initialize it}
 GetFileServerName(connID, FSName);
 Result := StrPas(FSName);
End;

end.
---------- code ends---------------

Enjoy,
Sajan.

Sajan Thomas
Computer and Communication Services Department
Milwaukee School of Engineering
Milwaukee, WI 53202
Tel. (414)-277-7498
(Internet Address: THOMAS@MSOE.EDU)

