用户友好名称来自系统帐户,工作组

时间:2018-03-09 05:55:08

标签: delphi winapi

我的流程(常规应用,不是服务。应用是由服务启动,而不是由用户启动,但在用户会话中)在用户会话中在 SYSTEM帐户(其他原因需要)下运行( S)。如果PC在工作组中 ,有没有办法获得当前会话的用户友好名称

-getting desktop('Progrman')用户为-GetTokenInformation - LookupAccountSid - 并且使TranslateName不会给我工作组中的f.name()(如msdn中所述,它在域中工作)。

-GetUserNameExW没有给我f.name,因为我的进程在SYSTEM帐户下运行(GetUserNameExW检索调用进程帐户的数据)

那么,与流程无关的用户友好名称还有其他方式为工作组提供 吗?

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;

1 个答案:

答案 0 :(得分:1)

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.