示例#1
2
int main(void)
{
  // GetCurrentProcess cannot fail
  HANDLE hProcess = GetCurrentProcess();

  if (OpenProcessToken(hProcess, TOKEN_READ, &hProcess))
  {
    LUID seCreateSymbolicLinkPrivilege;

    if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &seCreateSymbolicLinkPrivilege))
    {
      DWORD length;

      printf("SeCreateSymbolicLinkPrivilege = %ld, %ld\n", seCreateSymbolicLinkPrivilege.HighPart, seCreateSymbolicLinkPrivilege.LowPart);

      if (!GetTokenInformation(hProcess, TokenPrivileges, NULL, 0, &length))
      {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
          TOKEN_PRIVILEGES* privileges = (TOKEN_PRIVILEGES*)malloc(length);
          if (GetTokenInformation(hProcess, TokenPrivileges, privileges, length, &length))
          {
            BOOL found = FALSE;
            DWORD count = privileges->PrivilegeCount;

            printf("User has %ld privileges\n", count);

            if (count > 0)
            {
              LUID_AND_ATTRIBUTES* privs = privileges->Privileges;
              while (count-- > 0 && !luid_eq(privs->Luid, seCreateSymbolicLinkPrivilege))
                privs++;
              found = (count > 0);
            }

            printf("User does%s have the SeCreateSymbolicLinkPrivilege\n", (found ? "" : "n't"));
          }
          else
          {
            fprintf(stderr, "Second GetTokenInformation failed\n");
          }

          free(privileges);
        }
        else
        {
          fprintf(stderr, "First GetTokenInformation failed\n");
        }
      }
      else
      {
        fprintf(stderr, "Impossible output from GetTokenInformation\n");
      }
    }
    else
    {
      fprintf(stderr, "LookupPrivilegeValue failed\n");
    }

    CloseHandle(hProcess);
  }
  else
  {
    fprintf(stderr, "OpenProcessToken failed\n");
  }

  LSA_HANDLE hPolicy;
  NTSTATUS r;
  LSA_OBJECT_ATTRIBUTES attributes = {0, NULL, NULL, 0, NULL, NULL};
  attributes.Length = sizeof(attributes);

  LUID seCreateSymbolicLinkPrivilege;

  if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &seCreateSymbolicLinkPrivilege))
  {
    // POLICY_LOOKUP_NAMES: LsaLookupNames2, LsaEnumerateAccountRights, LsaLookupSids, LsaAddAccountRights
    // POLICY_VIEW_LOCAL_INFORMATION: LsaEnumerateAccountsWithUserRight
    // Elevation: LsaEnumerateAccountRights, LsaEnumerateAccountsWithUserRight, LsaRemoveAccountRights, LsaAddAccountRights
    if (NT_SUCCESS(r = LsaOpenPolicy(NULL, &attributes, POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &hPolicy)))
    {
      LSA_REFERENCED_DOMAIN_LIST* referencedDomains;
      LSA_TRANSLATED_SID2* sids;
      LSA_UNICODE_STRING name;
      name.Buffer = L"Users";
      name.Length = wcslen(name.Buffer) * sizeof(WCHAR);
      name.MaximumLength = name.Length + sizeof(WCHAR);
  
      if (NT_SUCCESS(r = LsaLookupNames2(hPolicy, LSA_LOOKUP_ISOLATED_AS_LOCAL, 1, &name, &referencedDomains, &sids)))
      {
        LSA_UNICODE_STRING* rights;
        ULONG count;
        LsaFreeMemory(referencedDomains);

        if (NT_SUCCESS(r = LsaEnumerateAccountRights(hPolicy, sids->Sid, &rights, &count)))
        {
          LSA_UNICODE_STRING* right = rights;
          printf("%ld right%s found\n", count, PLURAL(count));
          while (count-- > 0)
          {
            printf("  %.*S\n", right->Length / 2, right->Buffer);
            right++;
          }

          LsaFreeMemory(rights);

          LSA_ENUMERATION_INFORMATION* allSidsRaw;
          LSA_UNICODE_STRING lsaCreateSymbolicLinkPrivilege;
          lsaCreateSymbolicLinkPrivilege.Buffer = SE_CREATE_SYMBOLIC_LINK_NAME;
          lsaCreateSymbolicLinkPrivilege.Length = wcslen(lsaCreateSymbolicLinkPrivilege.Buffer) * sizeof(WCHAR);
          lsaCreateSymbolicLinkPrivilege.MaximumLength = lsaCreateSymbolicLinkPrivilege.Length + sizeof(WCHAR);
          if (NT_SUCCESS(r = LsaEnumerateAccountsWithUserRight(hPolicy, &lsaCreateSymbolicLinkPrivilege, (void**)&allSidsRaw, &count)))
          {
            LSA_ENUMERATION_INFORMATION* sid = allSidsRaw;
            PSID* allSids;
            PSID* p;
            PLSA_TRANSLATED_NAME names;
            ULONG i = count;

            printf("%ld SID%s found\n", count, PLURAL(count));
            p = allSids = (PSID*)malloc(count * sizeof(PSID));

            while (i-- > 0)
              *p++ = (sid++)->Sid;

            if (NT_SUCCESS(r = LsaLookupSids(hPolicy, count, allSids, &referencedDomains, &names)))
            {
              PLSA_TRANSLATED_NAME name = names;
              BOOL usersAssigned = FALSE;

              LsaFreeMemory(referencedDomains);

              while (count-- > 0)
              {
                LPTSTR sidString;
                USHORT len = name->Name.Length / 2;
                ConvertSidToStringSid(*allSids++, &sidString);
                printf("  %.*S (%S)\n", len, name->Name.Buffer, sidString);
                usersAssigned |= (len > 4 && !wcsncmp(L"Users", name->Name.Buffer, len));
                name++;
                LocalFree(sidString);
              }

              printf("Users had%s got SeCreateSymbolicLinkPrivilege\n", (usersAssigned ? "" : "n't"));
              if (usersAssigned)
              {
                if (!NT_SUCCESS(r = LsaRemoveAccountRights(hPolicy, sids->Sid, FALSE, &lsaCreateSymbolicLinkPrivilege, 1)))
                {
                  fprintf(stderr, "Lsa failed with code %x\n", r);
                }
              }
              else
              {
                if (!NT_SUCCESS(r = LsaAddAccountRights(hPolicy, sids->Sid, &lsaCreateSymbolicLinkPrivilege, 1)))
                {
                  fprintf(stderr, "LsaAddAccountRights failed with code %x\n", r);
                }
              }

              LsaFreeMemory(names);
            }
            else
            {
              fprintf(stderr, "LsaLookupSids2 failed with code %x\n", r);
            }
              
            LsaFreeMemory(allSidsRaw);
            free(allSids);
          }
          else
          {
            fprintf(stderr, "LsaEnumerateAccountsWithUserRight failed with code %x\n", r);
          }
        }
        else
        {
          fprintf(stderr, "LsaEnumerateAccountRights failed with code %x\n", r);
        }

        LsaFreeMemory(sids);
      }
      else
      {
        fprintf(stderr, "LsaLookupNames2 failed with code %x\n", r);
      }
  
      LsaClose(hPolicy);
    }
    else
    {
      fprintf(stderr, "LsaOpenPolicy failed with code %x\n", r);
    }
  }
  else
  {
    fprintf(stderr, "LookupPrivilegeValue failed\n");
  }
}
示例#2
0
BOOL lsp_add(LSA_HANDLE lsa_handle, LPTSTR user, LPTSTR privilegeConstant)
{
  LSA_ACCOUNT         account;
  NTSTATUS            nt_status;
  LSA_UNICODE_STRING  privilege;
  PSID                sid;
  BOOL                success = TRUE;

  if (!valid_privilege(&privilege, privilegeConstant))
    return FALSE;

  if (!valid_user(lsa_handle, &sid, user))
    return FALSE;

  if (!lsa_account_from_sid(lsa_handle, sid, &account))
  {
    FreeSid(sid);
    return FALSE;
  }

  print_string(L"Adding %s to ", privilegeConstant);
  print_account(&account);
  print_string(L".\n");

  nt_status = LsaAddAccountRights(lsa_handle, sid, &privilege, 1);
  if (nt_status != STATUS_SUCCESS)
  {
    FreeSid(sid);
    return lsa_error(nt_status, L"LsaAddAccountRights");
  }

  FreeSid(sid);

  return TRUE;
}
示例#3
0
文件: setup.c 项目: Moteesh/reactos
static VOID
AddImpersonatePrivilege(VOID)
{
    /* S-1-5-6 -- "Service" group */
    static SID ServiceSid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } };

    NTSTATUS Status;
    LSA_HANDLE PolicyHandle;
    LSA_OBJECT_ATTRIBUTES ObjectAttributes;
    LSA_UNICODE_STRING RightString;

    ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
    Status = LsaOpenPolicy(NULL, &ObjectAttributes,
                           POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
                           &PolicyHandle);
    if (!NT_SUCCESS(Status))
    {
        ERR("LsaOpenPolicy() failed with Status 0x%08lx\n", Status);
        return;
    }

    RtlInitUnicodeString(&RightString, L"SeImpersonatePrivilege");
    Status = LsaAddAccountRights(PolicyHandle, &ServiceSid, &RightString, 1);
    if (!NT_SUCCESS(Status))
    {
        ERR("LsaAddAccountRights(\"S-1-5-6\", \"%wZ\") failed with Status 0x%08lx\n", Status, &RightString);
    }

    LsaClose(PolicyHandle);
}
示例#4
0
HRESULT TCUserAccount::SetRight(LPTSTR pszPrivilege)
{
  // Not supported under Windows9x
  if (IsWin9x())
    return S_FALSE;

  // Fail if Init has not been called successfully
  if (!m_hPolicy || m_spSIDPrincipal.IsNull())
    return E_UNEXPECTED;

  // Fail if the specified pointer is NULL
  if (!pszPrivilege)
    return E_POINTER;

  // Get a pointer to a UNICODE version of the specified privilege
  USES_CONVERSION;
  LPWSTR pszWidePrivilege = T2W(pszPrivilege);

  // Create an LSA_UNICODE_STRING for the specified privilege name
  LSA_UNICODE_STRING lsaString;
  lsaString.Length        = (USHORT)(wcslen(pszWidePrivilege) * sizeof(WCHAR));
  lsaString.MaximumLength = (USHORT)(lsaString.Length + sizeof(WCHAR));
  lsaString.Buffer        = pszWidePrivilege;

  // Attempt to add the specified privilege to the current user
  RETURN_FAILED(LsaAddAccountRights(m_hPolicy, m_spSIDPrincipal,
    &lsaString, 1));

  // Indicate success
  return S_OK;
}
示例#5
0
/**
 * @brief
 * 		add_privilege - add_privilege: returns 0 if privname has been added for account
 * 		referenced by sid; otherwise, 1.
 *
 * @param[in]	sid	-	The security identifier (SID) structure is a variable-length structure
 * 						 used to uniquely identify users or groups.
 * @param[in]	privname	-	privilege name
 *
 * @return	int
 * @retval	1	: if privname has not been added for account referenced by sid
 * @retval	0	: if privname has been added for account referenced by sid
 */
int
add_privilege(SID *sid, char *privname)
{
	LSA_UNICODE_STRING rights;
	LSA_HANDLE h_policy = INVALID_HANDLE_VALUE;
	LSA_OBJECT_ATTRIBUTES  obj_attrs;
	NTSTATUS lsa_stat;
	BOOL	rval = 1;
	WCHAR	*privnameW = NULL;
	int	priv_len = 0;

	if (privname == NULL) {
		fprintf(stderr, "add_privilege: NULL privname\n");
		return (1);
	}

	if (!IsValidSid(sid)) {
		fprintf(stderr, "add_privilege: Not a valid sid\n");
		return (1);
	}

	priv_len = strlen(privname) + 1;
	privnameW = (WCHAR *)malloc(priv_len * sizeof(WCHAR));

	if (privnameW == NULL) {
		fprintf(stderr, "add_privilege: malloc failed\n");
		return (1);
	}

	mbstowcs(privnameW, privname, priv_len);
	init_lsa_string(&rights, privnameW);

	ZeroMemory(&obj_attrs, sizeof(obj_attrs));
	if( LsaOpenPolicy(NULL, &obj_attrs, POLICY_ALL_ACCESS, &h_policy) \
							!= ERROR_SUCCESS ) {
		fprintf(stderr, "add_privilege: Unable to open policy!\n");
		goto add_privilege_end;
	}

	if( (lsa_stat=LsaAddAccountRights( h_policy, sid, &rights, 1 )) != \
							ERROR_SUCCESS ) {
		fprintf(stderr,
			"add_privilege: adding privilege %s failed! - err %d\n",
			privname, LsaNtStatusToWinError(lsa_stat));
		goto add_privilege_end;
	}

	printf("\tadded %s\n", privname);
	rval = 0;

add_privilege_end:
	if (h_policy != INVALID_HANDLE_VALUE)
		LsaClose(h_policy);

	if (privnameW != NULL)
		(void)free(privnameW);

	return (rval);
}
示例#6
0
NTSTATUS
SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
		      LPWSTR PrivilegeName, BOOL bEnable)
{
	LSA_UNICODE_STRING PrivilegeString;

	/* Create a LSA_UNICODE_STRING for the privilege name. */
	InitLsaString(&PrivilegeString, PrivilegeName);

	/* grant or revoke the privilege, accordingly */
	if (bEnable)
		return (LsaAddAccountRights(PolicyHandle, AccountSid,
			&PrivilegeString, 1));
	else
		return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
			FALSE, &PrivilegeString, 1));
}
void GrantPrivilege(PSID sid, LPCWSTR userRight)
{
    LSA_HANDLE hPolicy = OpenPolicy(POLICY_LOOKUP_NAMES | POLICY_CREATE_ACCOUNT);

    try
    {
        LSA_UNICODE_STRING lsaUserRight;
        InitLsaString(&lsaUserRight, (LPWSTR)userRight);
        CheckRetVal(LsaAddAccountRights(hPolicy, sid, &lsaUserRight, 1));

        LsaClose(hPolicy);
    }
    catch (const std::exception&)
    {
        LsaClose(hPolicy);
        throw;
    }
}
示例#8
0
static BOOL ObtainLockPagesPrivilege() {
    HANDLE token;
    PTOKEN_USER user = NULL;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) {
        DWORD size = 0;

        GetTokenInformation(token, TokenUser, NULL, 0, &size);
        if (size) {
            user = (PTOKEN_USER) LocalAlloc(LPTR, size);
        }

        GetTokenInformation(token, TokenUser, user, size, &size);
        CloseHandle(token);
    }

    if (!user) {
        return FALSE;
    }

    LSA_HANDLE handle;
    LSA_OBJECT_ATTRIBUTES attributes;
    ZeroMemory(&attributes, sizeof(attributes));

    BOOL result = FALSE;
    if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) {
        LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME));

        if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) {
            LOG_NOTICE("Huge pages support was successfully enabled, but reboot required to use it");
            result = TRUE;
        }

        LsaClose(handle);
    }

    LocalFree(user);
    return result;
}
NTSTATUS
SetPrivilegeOnAccount(
    LSA_HANDLE PolicyHandle,    // open policy handle
    PSID AccountSid,            // SID to grant privilege to
    LPWSTR PrivilegeName,       // privilege to grant (Unicode)
    BOOL bEnable                // enable or disable
    )
{
    LSA_UNICODE_STRING PrivilegeString;

    //
    // Create a LSA_UNICODE_STRING for the privilege name.
    //
    InitLsaString(&PrivilegeString, PrivilegeName);

    //
    // grant or revoke the privilege, accordingly
    //
    if(bEnable) {
        return LsaAddAccountRights(
                PolicyHandle,       // open policy handle
                AccountSid,         // target SID
                &PrivilegeString,   // privileges
                1                   // privilege count
                );
    }
    else {
        return LsaRemoveAccountRights(
                PolicyHandle,       // open policy handle
                AccountSid,         // target SID
                FALSE,              // do not disable all rights
                &PrivilegeString,   // privileges
                1                   // privilege count
                );
    }
}
示例#10
0
USHORT SERVICES_grant_privilege(const TEXT* account, pfnSvcError err_handler, const WCHAR* privilege)
{
/***************************************************
 *
 * S E R V I C E _ g r a n t _ l o g o n _ r i g h t
 *
 ***************************************************
 *
 * Functional description
 *  Grants the "Log on as a service" right to account.
 *  This is a Windows NT, 2000, XP, 2003 security thing.
 *  To run a service under an account other than LocalSystem, the account
 *  must have this right. To succeed granting the right, the current user
 *  must be an Administrator.
 *  Returns FB_SUCCESS when actually granted the right.
 *  Returns FB_LOGON_SRVC_RIGHT_ALREADY_DEFINED if right was already granted
 *  to the user.
 *  Returns FB_FAILURE on any error.
 *
 *  OM - AUG 2003 - Initial implementation
 *  OM - SEP 2003 - Control flow revision, no functional change
 *
 ***************************************************/

	LSA_OBJECT_ATTRIBUTES ObjectAttributes;
	LSA_HANDLE PolicyHandle;

	// Open the policy on the local machine.
	ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
	NTSTATUS lsaErr = LsaOpenPolicy(NULL, &ObjectAttributes,
		POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &PolicyHandle);
	if (lsaErr != (NTSTATUS) 0)
		return (*err_handler)(LsaNtStatusToWinError(lsaErr), "LsaOpenPolicy", NULL);

	// Obtain the SID of the user/group.
	// First, dummy call to LookupAccountName to get the required buffer sizes.
	DWORD cbSid;
	DWORD cchDomain;
	cbSid = cchDomain = 0;
	SID_NAME_USE peUse;
	LookupAccountName(NULL, account, NULL, &cbSid, NULL, &cchDomain, &peUse);
	PSID pSid = (PSID) LocalAlloc(LMEM_ZEROINIT, cbSid);
	if (pSid == 0)
	{
		DWORD err = GetLastError();
		LsaClose(PolicyHandle);
		return (*err_handler)(err, "LocalAlloc(Sid)", NULL);
	}
	TEXT* pDomain = (LPTSTR) LocalAlloc(LMEM_ZEROINIT, cchDomain);
	if (pDomain == 0)
	{
		DWORD err = GetLastError();
		LsaClose(PolicyHandle);
		LocalFree(pSid);
		return (*err_handler)(err, "LocalAlloc(Domain)", NULL);
	}
	// Now, really obtain the SID of the user/group.
	if (LookupAccountName(NULL, account, pSid, &cbSid, pDomain, &cchDomain, &peUse) == 0)
	{
		DWORD err = GetLastError();
		LsaClose(PolicyHandle);
		LocalFree(pSid);
		LocalFree(pDomain);
		return (*err_handler)(err, "LookupAccountName", NULL);
	}

	PLSA_UNICODE_STRING UserRights;
	ULONG CountOfRights = 0;
	NTSTATUS ntStatus = LsaEnumerateAccountRights(PolicyHandle, pSid, &UserRights, &CountOfRights);
	if (ntStatus == (NTSTATUS) 0xC0000034L) //STATUS_OBJECT_NAME_NOT_FOUND
		CountOfRights = 0;
	// Check if the seServiceLogonRight is already granted
	ULONG i;
	for (i = 0; i < CountOfRights; i++)
	{
		if (wcscmp(UserRights[i].Buffer, privilege) == 0)
			break;
	}
	LsaFreeMemory(UserRights); // Don't leak
	LSA_UNICODE_STRING PrivilegeString;
	if (CountOfRights == 0 || i == CountOfRights)
	{
		// Grant the SeServiceLogonRight to users represented by pSid.
		const int string_buff_size = 100;
		WCHAR tempStr[string_buff_size];
		wcsncpy(tempStr, privilege, string_buff_size - 1);
		tempStr[string_buff_size - 1] = 0;

		PrivilegeString.Buffer = tempStr;
		PrivilegeString.Length = wcslen(tempStr) * sizeof(WCHAR);
		PrivilegeString.MaximumLength = sizeof(tempStr);
		if ((lsaErr = LsaAddAccountRights(PolicyHandle, pSid, &PrivilegeString, 1)) != (NTSTATUS) 0)
		{
			LsaClose(PolicyHandle);
			LocalFree(pSid);
			LocalFree(pDomain);
			return (*err_handler)(LsaNtStatusToWinError(lsaErr), "LsaAddAccountRights", NULL);
		}
	}
	else
	{
		LsaClose(PolicyHandle);
		LocalFree(pSid);
		LocalFree(pDomain);
		return FB_PRIVILEGE_ALREADY_GRANTED;
	}

	LsaClose(PolicyHandle);
	LocalFree(pSid);
	LocalFree(pDomain);

	return FB_SUCCESS;
}
示例#11
0
文件: account.c 项目: borland667/pbis
static
DWORD
ProcessAddRemoveAccountRights(
    IN PRPC_PARAMETERS pRpcParams,
    IN BOOLEAN Add,
    IN PSTR AccountRights,
    IN BOOLEAN RemoveAll,
    IN PSTR AccountName
    )
{
    DWORD err = ERROR_SUCCESS;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    LSA_BINDING hLsa = NULL;
    LW_PIO_CREDS pCreds = NULL;
    WCHAR wszSysName[] = {'\\', '\\', '\0'};
    DWORD policyAccessMask = LSA_ACCESS_LOOKUP_NAMES_SIDS |
                             LSA_ACCESS_CREATE_SPECIAL_ACCOUNTS;
    POLICY_HANDLE hPolicy = NULL;
    PSID pAccountSid = NULL;
    PSTR *ppszAccountRightNames = NULL;
    DWORD numAccountRightNames = 0;
    PWSTR *ppwszAccountRightNames = NULL;
    DWORD i = 0;
    
    err = CreateRpcCredentials(pRpcParams,
                               &pCreds);
    BAIL_ON_LSA_ERROR(err);

    err = CreateLsaRpcBinding(pRpcParams,
                              pCreds,
                              &hLsa);
    BAIL_ON_LSA_ERROR(err);

    ntStatus = LsaOpenPolicy2(hLsa,
                              wszSysName,
                              NULL,
                              policyAccessMask,
                              &hPolicy);
    BAIL_ON_NT_STATUS(ntStatus);

    err = ResolveAccountNameToSid(
                          hLsa,
                          AccountName,
                          &pAccountSid);
    BAIL_ON_LSA_ERROR(err);

    if (AccountRights)
    {
        err = GetStringListFromString(
                              AccountRights,
                              SEPARATOR_CHAR,
                              &ppszAccountRightNames,
                              &numAccountRightNames);
        BAIL_ON_LSA_ERROR(err);

        err = LwAllocateMemory(
                       sizeof(ppwszAccountRightNames[0]) * numAccountRightNames,
                       OUT_PPVOID(&ppwszAccountRightNames));
        BAIL_ON_LSA_ERROR(err);

        for (i = 0; i < numAccountRightNames; i++)
        {
            err = LwMbsToWc16s(ppszAccountRightNames[i],
                               &ppwszAccountRightNames[i]);
            BAIL_ON_LSA_ERROR(err);
        }
    }

    if (Add)
    {
        ntStatus = LsaAddAccountRights(
                              hLsa,
                              hPolicy,
                              pAccountSid,
                              ppwszAccountRightNames,
                              numAccountRightNames);
        BAIL_ON_NT_STATUS(ntStatus);

        fprintf(stdout, "Successfully added account rights to %s\n", AccountName);
    }
    else
    {
        ntStatus = LsaRemoveAccountRights(
                              hLsa,
                              hPolicy,
                              pAccountSid,
                              RemoveAll,
                              ppwszAccountRightNames,
                              numAccountRightNames);
        BAIL_ON_NT_STATUS(ntStatus);

        fprintf(stdout, "Successfully removed account rights from %s\n", AccountName);
    }

error:
    if (ntStatus || err)
    {
        PCSTR errName = LwNtStatusToName(ntStatus);
        PCSTR errDescription = LwNtStatusToDescription(ntStatus);

        if (ntStatus)
        {
            errName = LwNtStatusToName(ntStatus);
            errDescription = LwNtStatusToDescription(ntStatus);
        }
        else
        {
            errName = LwWin32ErrorToName(err);
            errDescription = LwWin32ErrorToDescription(err);
        }

        fprintf(stderr, "Error: %s (%s)\n",
                LSA_SAFE_LOG_STRING(errName),
                LSA_SAFE_LOG_STRING(errDescription));
    }

    if (hPolicy)
    {
        LsaClose(hLsa, hPolicy);
    }

    if (hLsa)
    {
        LsaFreeBinding(&hLsa);
    }

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    for (i = 0; i < numAccountRightNames; i++)
    {
        LW_SAFE_FREE_MEMORY(ppwszAccountRightNames[i]);
        LW_SAFE_FREE_MEMORY(ppszAccountRightNames[i]);
    }
    LW_SAFE_FREE_MEMORY(ppwszAccountRightNames);
    LW_SAFE_FREE_MEMORY(ppszAccountRightNames);

    if (err == ERROR_SUCCESS &&
        ntStatus != STATUS_SUCCESS)
    {
        err = LwNtStatusToWin32Error(ntStatus);
    }

    return err;
}