Alexander M.
Alexander M.

Reputation: 781

User Friendly Name from system account, workgroup

My process (regular app, not a service. app is launched by service, not by user, but in user's session) runs under SYSTEM account (it's required by other reasons) in user's session(s). Is there any way to get current session's user friendly name if the PC is in a workgroup?

-getting desktop's ('Progrman') user as -GetTokenInformation - LookupAccountSid - and making a TranslateName does not give me the f.name () in a workgroup (as written in msdn, it works in a domain).

-GetUserNameExW does not give me f.name because my process works under SYSTEM account (GetUserNameExW retrieves the data for calling process's account)

So, is there any other way of process-independent user friendly name providing for workgroups ?

function GetUserNameEx(var AUserName: string; var AFriendlyUserName: string): Boolean;
var
  ProcessID: Integer;
  phToken, hProcess, hWindow: THandle;
  cbBuf: Cardinal;
  ptiUser: PTOKEN_USER;
  snu: SID_NAME_USE;
  szDomain, szUser : array [0..50] of Char;
  chDomain, chUser : Cardinal;

  UserName1: array[0..250] of Char;
  FriendlyUserName: array[0..250] of Char;
  Size: DWORD;

const
  NameUnknown = 0; // Unknown name type.
  NameFullyQualifiedDN = 1;  // Fully qualified distinguished name
  NameSamCompatible = 2; // Windows NT® 4.0 account name
  NameDisplay = 3;  // A "friendly" display name
  NameUniqueId = 6; // GUID string that the IIDFromString function returns
  NameCanonical = 7;  // Complete canonical name
  NameUserPrincipal = 8; // User principal name
  NameCanonicalEx = 9;
  NameServicePrincipal = 10;  // Generalized service principal name
  DNSDomainName = 11;  // DNS domain name, plus the user name

begin
  Result := False;
  AUserName := '';
  AFriendlyUserName := '';
  hWindow := FindWindow('Progman', 'Program Manager');
  if hWindow <> 0 then
  begin
    GetWindowThreadProcessID(hWindow, @ProcessID);
    hProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
    if hProcess <> 0 then
    begin
      if OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, phToken) then
      begin
        if not GetTokenInformation(phToken, TokenUser, nil, 0, cbBuf) then
          if GetLastError()<> ERROR_INSUFFICIENT_BUFFER then exit;
        if cbBuf = 0 then exit;
        GetMem(ptiUser, cbBuf);
        try
          chDomain := 50;
          chUser   := 50;
          if GetTokenInformation(phToken, TokenUser, ptiUser, cbBuf, cbBuf) then
            if LookupAccountSid(nil, ptiUser.User.Sid, szUser, chUser, szDomain,
              chDomain, snu) then
              begin
                AUserName := szUser;
                Result := True;

                if Trim(szDomain) <> '' then
                begin
                  FillChar(UserName1, 251, 0);
                  FillChar(FriendlyUserName, 251, 0);
                  StrCopy(UserName1, PChar(Trim(szDomain) + '\' + Trim(szUser)));
                  Size := 251;
  //THIS CODE WORKS FOR DOMAINS ONLY, NOT FOR WORKGROUPS
                  if TranslateName(@UserName1, NameSamCompatible, NameDisplay, @FriendlyUserName, @Size) then
                    AFriendlyUserName := Trim(FriendlyUserName);
                end;
              end
            else
              raise Exception.Create('Error in GetTokenUser');
        finally
          FreeMem(ptiUser);
        end;
      end
      else begin
        AUserName := 'OpenProcessToken = False';
        Result := False;
      end
    end
    else begin
      AUserName := '';
      Result := False;
    end
  end
  else begin
    AUserName := '';
    Result := False;
  end
end;

Upvotes: 0

Views: 417

Answers (1)

Anders
Anders

Reputation: 101764

GetUserNameEx respects impersonation so you can call ImpersonateLoggedOnUser with your token to get information about the user.

However, in a workgroup environment only NameSamCompatible seems to work and everything else returns ERROR_NONE_MAPPED (The user name is not available in the specified format).

Calling NetUserGetInfo also just returns a empty string for usri*_full_name.

There is also a undocumented shell function to retrieve the display name but it just falls back to GetUserName when GetUserNameEx fails.

Upvotes: 1

Related Questions