Reputation: 319
My Delphi 2010 application needs to add a Windows user to the local Administrators group. I got this part working using NetLocalGroupAddMembers.
Now the application needs to work in localized versions of Windows with other languages. For this I am using the SID with the LsaLookupSids function to get the translated name of the group, but am unable to do it because I don't know how to make the API call.
I would be grateful is someone could please show me how to use the LsaLookupSids function to get the group name ('Administrators' in English US version of Windows) from the SID.
Following is my code:
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;
Upvotes: 3
Views: 4015
Reputation: 7340
You don't need LsaLookupSids, this is meant for lookup or an array of SID's. Lookup of a single SID is usually done using LookupAccountSid. Example:
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));
or even easier using Jwscl:
uses JwsclSid;
var
Sid: TJwSecurityId;
begin
Sid := TJwSecurityId.Create('S-1-5-32-544');
try
ShowMessage(Sid.GetAccountName);
finally
Sid.Free;
end;
Upvotes: 6
Reputation: 1285
Simple example using JCL. You also could same using http://blog.delphi-jedi.net/security-library/ (like TJwSecurityId).
This code does not use LsaLookupSids, but internally LookupAccountSid (but for local group I don't think that it does matter).
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;
Upvotes: 4