Link to home
Start Free TrialLog in
Avatar of rene_moeller
rene_moeller

asked on

Login name on NT4

How do i get the login name from another NT4 workstation in the network?
Avatar of d003303
d003303

Do you mean you supply the computer name and get the currently logged on console user ?
Avatar of rene_moeller

ASKER

Yes, a more exactly way to put it. And a little piece of code would be nice.
Hi

  If your application uses the BDE, you can use the following code to get the user logged on:

function GetCurrUser : String;
var
  pcNetUser : PChar;
begin
  pcNetUser := StrAlloc (256);  

  if DbiGetNetUserName (pcNetUser) = 0 then
    Result := StrPas (pcNetUser)
  else
    Result := '';  

  StrDispose (pcNetUser);
end;

I hope this helps with the username.

Edo
Hi
  I just found this after some digging.

>>Untested.

procedure GetComputerName
var
  i : integer;
  ComputerName : string;
begin
  SetLength(ComputerName,NSize);
  if GetComputerName(PChar(ComputerName), NSize) then
    StatusBar.Panels[1].Text:= 'PC: '+ ComputerName;
end;

HTH

Edo
Thx EDO, but I don't use BDE in the app. I'll keep the example in mind to another time.
mmh, I am fighting around with some netapi32.dll calls right now, always get GPFs... I'll keep digging.

Slash/d003303
Hi d003303,
I knew this was a "tuffy". Still getting GPF's?

ASKER CERTIFIED SOLUTION
Avatar of d003303
d003303

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks d003303,

I'll test it in the week-end. It looks very promising.
oops, I forgot to implement the new exception handler.
The lines
type

  ENetAPIException = class(Exception)
    NetAPIErrorCode : LongInt;
  end;

  PWKSTA_USER_INFO_0 = ^TWKSTA_USER_INFO_0;
should read
type

  ENetAPIException = class(Exception)
    NetAPIErrorCode : LongInt;
    constructor Create(AMsg : string; ErrCode : LongInt);
  end;

constructor ENetAPIException.Create(AMsg : string; ErrCode : LongInt);
begin
  inherited Create(AMsg);
  NetAPIErrorCode := ErrCode;
end;

type

  PWKSTA_USER_INFO_0 = ^TWKSTA_USER_INFO_0;
and the lines
          if (FResult = ERROR_MORE_DATA) and (UsrTotal <> 0)
           then PrefMaxLen := PrefMaxLen * 2
           else raise Exception.Create('NetWkstaUserEnum ' + IntToStr(FResult));
should read
          if (FResult = ERROR_MORE_DATA) and (UsrTotal <> 0)
           then PrefMaxLen := PrefMaxLen * 2
           else raise ENetAPIException.Create('Error calling NetWkstaUserEnum', FResult);

Happy testing,
Slash/d003303
Thanks d003303,

You are nothing less than brilliant. It works and it was exacltly what I was looking for. Thanks again.
Thx, no prob.
Yo,
another method to get the logged on user(s), but only if they are logged on interactively. This returns one entry for ordinary NT WS/Server, and a list of all users connected via terminals/console on e.g. Citrix WinStation or Hydra (tested).

procedure GetUsersFromRemoteReg(WksName : string; HiveList : TStrings);
var Registry : TRegistry;
    Index    : Integer;
begin
  Registry := TRegistry.Create;
  try
    Registry.RootKey := HKEY_USERS;
    if not Registry.RegistryConnect(WksName)
     then Exit;
    Registry.OpenKey('', false);
    if Registry.HasSubkeys then
     begin
       Registry.GetKeyNames(HiveList);
       for Index := 0 to HiveList.Count - 1
        do if UpperCase(HiveList[Index]) = '.DEFAULT' then
         begin
           HiveList.Delete(Index);
           Break;
         end;
      end;
    Registry.CloseKey;
  finally
    Registry.Free;
  end;
end;

procedure TranslateSIDToAccountNames(WksName : string; HiveList : TStrings);
var Registry : TRegistry;
    lUsrName,
    lDomName,
    lSID,
    peUse,
    Index    : Integer;
    UsrName,
    DomName,
    SID      : PChar;
begin
  Registry := TRegistry.Create;
  try
    Registry.RootKey := HKEY_LOCAL_MACHINE;
    if not Registry.RegistryConnect(WksName)
     then Exit;
    for Index := 0 to HiveList.Count - 1 do
     if Registry.OpenKey('SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\' + HiveList[Index], false) then
      begin
        lSID := Registry.GetDataSize('Sid');
        GetMem(SID, lSID);
        try
          Registry.ReadBinaryData('Sid', SID[0], lSID);
          if IsValidSid(SID) then
           begin
             lUsrName := 0;
             lDomName := 0;
             LookupAccountSid(PChar(WksName), SID, UsrName, lUsrName, DomName, lDomName, peUse);
             GetMem(UsrName, lUsrName);
             GetMem(DomName, lDomName);
             try
               if not LookupAccountSid(PChar(WksName), SID, UsrName, lUsrName, DomName, lDomName, peUse)
                then raise Exception.Create('LookupAccountSid failed');
               HiveList[Index] := string(DomName) + '\' + string(UsrName);
             finally
               FreeMem(DomName, lDomName);
               FreeMem(UsrName, lUsrName);
             end;
           end;
        finally
          Registry.CloseKey;
          FreeMem(SID, lSID);
        end;
      end;
  finally
    Registry.Free;
  end;
end;

Call these functions like the above example,

    GetUsersFromRemoteReg(Edit1.Text, Listbox1.Items);
    TranslateSIDToAccountNames(Edit1.Text, Listbox1.Items);

and have fun.
Slash/d003303