2010-12-19 143 views
3

我的Delphi 2010应用程序需要将Windows用户添加到本地管理员组。我使用NetLocalGroupAddMembers得到了这部分工作。将SID转换为名称

现在应用程序需要使用其他语言的本地化版本的Windows。为此,我使用带LsaLookupSids函数的SID来获取组的已翻译名称,但无法执行此操作,因为我不知道如何进行API调用。

我将不胜感激有人可以请教我如何使用LsaLookupSids函数从SID获取组名('Administrators'的英文版美国版Windows)。

以下是我的代码:

function AddUser(const username, password: PChar; resetpassword: boolean): boolean; stdcall; 
var 
    NetApiStatus: NET_API_STATUS; 
    UserInfo1003: USER_INFO_1003; 
    UserInfo1005: USER_INFO_1005; 
    ui: USER_INFO_1; 
    grp: String; 
    sid: PSID; 
    snu: SID_NAME_USE; 
    sidsize: LongWord; 
    refdomain: PLsaReferencedDomainList; //array [0..MAX_PATH - 1] of char; 
    refdomainsize: LongWord; 
    sidstring: PChar; 
    lgmi3: _LOCALGROUP_MEMBERS_INFO_3; 
    reftranname: PLsaTranslatedName; 
begin 
    if UserExists(username) then begin 


    sidstring := PChar('S-1-5-32-544'); //Local Administrators group 

    refdomain := AllocMem(SizeOf(refdomain)); 
    FillChar(refdomain, SizeOf(refdomain), 0); 

    reftranname := AllocMem(SizeOf(reftranname)); 

    sidsize := 0; 
    sid := nil; 
    sid := AllocMem(Length(sidstring)); 
    sid := PChar(sidstring); 
    try 
     LsaLookupSids(GetPolicyHandle, 1, sid, refdomain, reftranname); 
     grp := reftranname^.Name.Buffer; 
     showmessage('messg ' + grp); 
    finally 
     FreeMem(sid, sidsize); 
    end; 
    end; 

回答

4

简单的例子。你也可以使用http://blog.delphi-jedi.net/security-library/(如TJwSecurityId)。

此代码不使用LsaLookupSids,但内部LookupAccountSid(但对于本地组我不认为它确实很重要)。

uses 
    JclSecurity, JclWin32; 

// Raises exception in case of invalid ASID or if SID is not found 
function GetNameFromSid(ASID: String): String; 
var 
    lSidLen: DWORD; 
    lSid: PSID; 
    lName, lDomain: WideString; 
begin 
    lSidLen := SECURITY_MAX_SID_SIZE; 

    lSid := AllocMem(lSidLen); 
    try 
    StringToSID(ASID, lSid, lSidLen); 
    LookupAccountBySid(lSid, lName, lDomain); 
    Result := lName; 
    finally 
    FreeMem(lSid); 
    end; 
end; 
6

你不需要LsaLookupSids,这意味着用于查找或SID的数组。 查找单个SID通常使用LookupAccountSid完成。例如:

uses JwaWindows; // or JwaSddl, JwaWinBase; 
    var 
     Sid: PSID; 
     peUse: DWORD; 
     cchDomain: DWORD; 
     cchName: DWORD; 
     Name: array of Char; 
     Domain: array of Char; 
    begin 
     Sid := nil; 
     // First convert String SID to SID 
     Win32Check(ConvertStringSidToSid(PChar('S-1-5-32-544'), Sid)); 

     cchName := 0; 
     cchDomain := 0; 
     // Get Length 
     if (not LookupAccountSid(nil, Sid, nil, cchName, nil, cchDomain, peUse)) 
     and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then 
     begin 
     SetLength(Name, cchName); 
     SetLength(Domain, cchDomain); 
     if LookupAccountSid(nil, Sid, @Name[0], cchName, @Domain[0], cchDomain, peUse) then 
     begin 
      // note: cast to PChar because LookupAccountSid returns zero terminated string 
      ShowMessageFmt('%s\%s', [PChar(Domain), PChar(Name)]); 
     end; 
     end; 

     if Assigned(Sid) then 
     LocalFree(DWORD(Sid)); 
使用Jwscl

或更容易:使用JCL

uses JwsclSid; 

    var 
     Sid: TJwSecurityId; 
    begin 
     Sid := TJwSecurityId.Create('S-1-5-32-544'); 
     try 
     ShowMessage(Sid.GetAccountName); 
     finally 
     Sid.Free; 
     end;