NetUserGetLocalGroups - how to call it?

Posted by SteveL on Stack Overflow See other posts from Stack Overflow or by SteveL
Published on 2010-12-21T21:26:40Z Indexed on 2010/12/22 11:54 UTC
Read the original article Hit count: 297

Filed under:
|

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.

© Stack Overflow or respective owner

Related posts about delphi

Related posts about winapi