static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac)
{
	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
	const char * const no_attrs[] = { NULL };
	struct ldb_message_element *el;
	struct ldb_message *tmp_msg;
	struct ldb_dn *res_dn;
	struct ldb_result *res;
	int ret;
	ret = dsdb_get_expected_new_values(ac,
					   ac->msg,
					   "fSMORoleOwner",
					   &el,
					   ac->req->operation);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	if (el == NULL) {
		/* we are not affected */
		return LDB_SUCCESS;
	}
	if (el->num_values != 1) {
		goto choose_error_code;
	}

	/* Create a temporary message for fetching the "fSMORoleOwner" */
	tmp_msg = ldb_msg_new(ac->msg);
	if (tmp_msg == NULL) {
		return ldb_module_oom(ac->module);
	}
	ret = ldb_msg_add(tmp_msg, el, 0);
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	res_dn = ldb_msg_find_attr_as_dn(ldb, ac, tmp_msg, "fSMORoleOwner");
	talloc_free(tmp_msg);

	if (res_dn == NULL) {
		ldb_set_errstring(ldb,
				  "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
		goto choose_error_code;
	}

	/* Fetched DN has to reference a "nTDSDSA" entry */
	ret = dsdb_module_search(ac->module, ac, &res, res_dn, LDB_SCOPE_BASE,
				 no_attrs,
				 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
				 ac->req, "(objectClass=nTDSDSA)");
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	if (res->count != 1) {
		ldb_set_errstring(ldb,
				  "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	talloc_free(res);

	return LDB_SUCCESS;

choose_error_code:
	/* this is just how it is */
	if (ac->req->operation == LDB_ADD) {
		return LDB_ERR_CONSTRAINT_VIOLATION;
	} else {
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}
}
static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac)
{
	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
	const char * const no_attrs[] = { NULL };
	struct ldb_message_element *el;
	struct ldb_message *tmp_msg;
	struct ldb_dn *res_dn;
	struct ldb_result *res;
	int ret;
	ret = dsdb_get_expected_new_values(ac,
					   ac->msg,
					   "fSMORoleOwner",
					   &el,
					   ac->req->operation);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	if (el == NULL) {
		 
		return LDB_SUCCESS;
	}
	if (el->num_values != 1) {
		goto choose_error_code;
	}

	 
	tmp_msg = ldb_msg_new(ac->msg);
	if (tmp_msg == NULL) {
		return ldb_module_oom(ac->module);
	}
	ret = ldb_msg_add(tmp_msg, el, 0);
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	res_dn = ldb_msg_find_attr_as_dn(ldb, ac, tmp_msg, "fSMORoleOwner");
	talloc_free(tmp_msg);

	if (res_dn == NULL) {
		ldb_set_errstring(ldb,
				  "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
		goto choose_error_code;
	}

	 
	ret = dsdb_module_search(ac->module, ac, &res, res_dn, LDB_SCOPE_BASE,
				 no_attrs,
				 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
				 ac->req, "(objectClass=nTDSDSA)");
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	if (res->count != 1) {
		ldb_set_errstring(ldb,
				  "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	talloc_free(res);

	return LDB_SUCCESS;

choose_error_code:
	 
	if (ac->req->operation == LDB_ADD) {
		return LDB_ERR_CONSTRAINT_VIOLATION;
	} else {
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}
}