Hi,
I am using Delphi 2010, latest version (from repository) of JEDI WinAPI and Windows Security Code Library (WSCL).
I don't know how to call the NetUserSetGroups function. The way I am doing it, it is throwing an exception:
Access violation at address 5B8760BE
in module 'netapi32.dll'. Write of
address 00000000.
Following is my code:
unit uFunc;
interface
uses Windows, SysUtils, JwaWindows, JwsclSid, Classes;
function UserExists(const username: PChar): boolean; stdcall;
function AddUser(const username, password: PChar; resetpassword: boolean): boolean; stdcall;
//function AddLogonAsAService(ID: pchar): boolean;
implementation
uses Dialogs;
// Returns true if the username exists on the local computer
function UserExists(const username: PChar): boolean; stdcall;
var
NetApiStatus: NET_API_STATUS;
ui: PUSER_INFO_0;
begin
NetApiStatus := NetUserGetInfo(nil, PWideChar(username), 0, PByte(ui));
if Assigned(ui) then
NetApiBufferFree(ui);
if (NetApiStatus <> NERR_Success) and (NetApiStatus <> NERR_UserNotFound) then
RaiseLastOSError(NetApiStatus);
Result := (NetApiStatus = NERR_Success);
end;
function AddPrivilegeToAccount(AAccountName, APrivilege: String): DWORD;
var
lStatus: TNTStatus;
lObjectAttributes: TLsaObjectAttributes;
lPolicyHandle: TLsaHandle;
lPrivilege: TLsaUnicodeString;
lSid: PSID;
lSidLen: DWORD;
lTmpDomain: String;
lTmpDomainLen: DWORD;
lTmpSidNameUse: TSidNameUse;
lPrivilegeWStr: String;
begin
ZeroMemory(@lObjectAttributes, SizeOf(lObjectAttributes));
lStatus := LsaOpenPolicy(nil, lObjectAttributes, POLICY_LOOKUP_NAMES, lPolicyHandle);
if lStatus <> STATUS_SUCCESS then begin
Result := LsaNtStatusToWinError(lStatus);
Exit;
end;
try
lTmpDomainLen := DNLEN; // In 'clear code' this should be get by LookupAccountName
SetLength(lTmpDomain, lTmpDomainLen);
lSidLen := SECURITY_MAX_SID_SIZE;
GetMem(lSid, lSidLen);
try
if LookupAccountName(nil, PChar(AAccountName), lSid, lSidLen, PChar(lTmpDomain),
lTmpDomainLen, lTmpSidNameUse) then begin
lPrivilegeWStr := APrivilege;
lPrivilege.Buffer := PWideChar(lPrivilegeWStr);
lPrivilege.Length := Length(lPrivilegeWStr) * SizeOf(Char);
lPrivilege.MaximumLength := lPrivilege.Length;
lStatus := LsaAddAccountRights(lPolicyHandle, lSid, @lPrivilege, 1);
Result := LsaNtStatusToWinError(lStatus);
end
else
Result := GetLastError;
finally
FreeMem(lSid);
end;
finally
LsaClose(lPolicyHandle);
end;
end;
//if user does not exists, create a local username with the supplied password
//if resetpassword, then reset password to the supplied parameter
//add the user to the local administrators group (note that this must work
//on all languages, use the SID of the group)
//give the user the "run as a service" privilege.
//enable the user if it is disabled.
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;
sidstring: String;
lgmi3: LOCALGROUP_MEMBERS_INFO_3;
jwSid: TJwSecurityID;
dwEntriesRead, dwEntriesTotal: PDWORD;
lgi01: LOCALGROUP_USERS_INFO_0;
plgi01 : PLOCALGROUP_USERS_INFO_0;
i: Integer;
gsl: TStringList;
begin
if UserExists(username) then begin
if resetpassword then begin
NetApiStatus := NetUserChangePassword(nil, PChar(username), PChar(''), PChar(password));
// If old password is incorrect then force password change
if (NetApiStatus = ERROR_INVALID_PASSWORD) then begin
UserInfo1003.usri1003_password := PChar(password);
NetApiStatus := NetUserSetInfo(nil, PChar(username), 1003, @UserInfo1003, nil);
end;
if (NetApiStatus <> NERR_Success) and (NetApiStatus <> NERR_UserNotFound) then
RaiseLastOSError(NetApiStatus);
// UserInfo1005.usri1005_priv := USER_PRIV_ADMIN;
// NetApiStatus := NetApiStatus and NetUserSetInfo(nil, PChar(username), 1005, @UserInfo1005, nil);
end;
end
else begin
ui.usri1_name := PChar(username);
ui.usri1_password := PChar(Password);
ui.usri1_password_age := 0; // ignored in this call
ui.usri1_priv := USER_PRIV_USER; //
ui.usri1_home_dir := nil;
ui.usri1_comment := PChar('');
ui.usri1_flags := UF_SCRIPT or UF_DONT_EXPIRE_PASSWD;
ui.usri1_script_path := nil;
NetApiStatus := NetUserAdd(nil, 1, @ui, nil);
if NetApiStatus <> NERR_Success then
RaiseLastOSError(NetApiStatus);
end;
Result := (NetApiStatus = NERR_Success);
//check if user already belongs to Administrators group
if Result then begin
sidstring := 'S-1-5-32-544'; //Local Administrators group
jwSid := TJwSecurityID.Create(sidstring);
try
grp := jwSid.GetAccountName('');
finally
jwSid.Free;
end;
gsl := TStringList.Create;
try
// New(plgi01);
NetApiStatus := NetUserGetLocalGroups(nil, PChar(username), 0, LG_INCLUDE_INDIRECT, PByte(plgi01),
MAX_PREFERRED_LENGTH, dwEntriesRead, dwEntriesTotal);
if NetApiStatus = NERR_SUCCESS then
showmessage('messg ' + IntTostr(dwEntriesRead^));
for i := 0 to dwEntriesRead^ - 1 do begin
gsl.Add(PLOCALGROUP_USERS_INFO_0(plgi01)^.lgrui0_name);
Inc(Integer(plgi01), SizeOf(Pointer));
end;
Result := (NetApiStatus = NERR_Success);
NetAPIBufferFree(plgi01);
if Result then
Result := gsl.Find(grp, i);
finally
gsl.Free;
end;
end;
//Add user to administrators group
if Result then begin
lgmi3.lgrmi3_domainandname := PChar(UserName);
NetApiStatus := NetLocalGroupAddMembers(nil, PChar(grp), 3, @lgmi3, 1);
if NetApiStatus <> NERR_Success then
RaiseLastOSError(NetApiStatus);
end;
Result := (NetApiStatus = NERR_Success);
try
AddPrivilegeToAccount(UserName, 'SeServiceLogonRight');
except
// showmessage('messg in an Excecpt');
end;
end;
end.
Would appreciate if someone could kindly show me how I can call this function?
Thanks in advance.