static NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx,
				 TALLOC_CTX *mem_ctx,
				 struct unixid *unixid,
				 struct dom_sid **sid)
{
	int ret;
	NTSTATUS status;
	struct ldb_context *ldb = idmap_ctx->ldb_ctx;
	struct ldb_result *res = NULL;
	struct ldb_message *msg;
	const struct dom_sid *unix_sid;
	struct dom_sid *new_sid;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	const char *id_type;

	const char *sam_attrs[] = {"objectSid", NULL};
	
	/* 
	 * First check against our local DB, to see if this user has a
	 * mapping there.  This means that the Samba4 AD DC behaves
	 * much like a winbindd member server running idmap_ad
	 */
	
	switch (unixid->type) {
		case ID_TYPE_UID:
			if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
				ret = dsdb_search_one(idmap_ctx->samdb, tmp_ctx, &msg,
						      ldb_get_default_basedn(idmap_ctx->samdb),
						      LDB_SCOPE_SUBTREE,
						      sam_attrs, 0,
						      "(&(|(sAMaccountType=%u)(sAMaccountType=%u)(sAMaccountType=%u))"
						      "(uidNumber=%u)(objectSid=*))",
						      ATYPE_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST, unixid->id);
			} else {
				/* If we are not to use the rfc2307 attributes, we just emulate a non-match */
				ret = LDB_ERR_NO_SUCH_OBJECT;
			}

			if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
				DEBUG(1, ("Search for uidNumber=%lu gave duplicate results, failing to map to a SID!\n",
					  (unsigned long)unixid->id));
				status = NT_STATUS_NONE_MAPPED;
				goto failed;
			} else if (ret == LDB_SUCCESS) {
				*sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid");
				if (*sid == NULL) {
					DEBUG(1, ("Search for uidNumber=%lu did not return an objectSid!\n",
						  (unsigned long)unixid->id));
					status = NT_STATUS_NONE_MAPPED;
					goto failed;
				}
				talloc_free(tmp_ctx);
				return NT_STATUS_OK;
			} else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
				DEBUG(1, ("Search for uidNumber=%lu gave '%s', failing to map to a SID!\n",
					  (unsigned long)unixid->id, ldb_errstring(idmap_ctx->samdb)));
				status = NT_STATUS_NONE_MAPPED;
				goto failed;
			}

			id_type = "ID_TYPE_UID";
			break;
		case ID_TYPE_GID:
			if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
				ret = dsdb_search_one(idmap_ctx->samdb, tmp_ctx, &msg,
						      ldb_get_default_basedn(idmap_ctx->samdb),
						      LDB_SCOPE_SUBTREE,
						      sam_attrs, 0,
						      "(&(|(sAMaccountType=%u)(sAMaccountType=%u))(gidNumber=%u))",
						      ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP,
						      unixid->id);
			} else {
				/* If we are not to use the rfc2307 attributes, we just emulate a non-match */
				ret = LDB_ERR_NO_SUCH_OBJECT;
			}
			if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
				DEBUG(1, ("Search for gidNumber=%lu gave duplicate results, failing to map to a SID!\n",
					  (unsigned long)unixid->id));
				status = NT_STATUS_NONE_MAPPED;
				goto failed;
			} else if (ret == LDB_SUCCESS) {
				*sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid");
				if (*sid == NULL) {
					DEBUG(1, ("Search for gidNumber=%lu did not return an objectSid!\n",
						  (unsigned long)unixid->id));
					status = NT_STATUS_NONE_MAPPED;
					goto failed;
				}
				talloc_free(tmp_ctx);
				return NT_STATUS_OK;
			} else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
				DEBUG(1, ("Search for gidNumber=%lu gave '%s', failing to map to a SID!\n",
					  (unsigned long)unixid->id, ldb_errstring(idmap_ctx->samdb)));
				status = NT_STATUS_NONE_MAPPED;
				goto failed;
			}

			id_type = "ID_TYPE_GID";
			break;
		default:
			DEBUG(1, ("unixid->type must be type gid or uid (got %u) for lookup with id %lu\n",
				  (unsigned)unixid->type, (unsigned long)unixid->id));
			status = NT_STATUS_NONE_MAPPED;
			goto failed;
	}

	ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
				 NULL, "(&(|(type=ID_TYPE_BOTH)(type=%s))"
				 "(xidNumber=%u))", id_type, unixid->id);
	if (ret != LDB_SUCCESS) {
		DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
		status = NT_STATUS_NONE_MAPPED;
		goto failed;
	}

	if (res->count == 1) {
		const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
							       "type", NULL);

		*sid = idmap_msg_get_dom_sid(mem_ctx, res->msgs[0],
					     "objectSid");
		if (*sid == NULL) {
			DEBUG(1, ("Failed to get sid from db: %u\n", ret));
			status = NT_STATUS_NONE_MAPPED;
			goto failed;
		}

		if (type == NULL) {
			DEBUG(1, ("Invalid type for mapping entry.\n"));
			talloc_free(tmp_ctx);
			return NT_STATUS_NONE_MAPPED;
		}

		if (strcmp(type, "ID_TYPE_BOTH") == 0) {
			unixid->type = ID_TYPE_BOTH;
		} else if (strcmp(type, "ID_TYPE_UID") == 0) {
			unixid->type = ID_TYPE_UID;
		} else {
			unixid->type = ID_TYPE_GID;
		}

		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	DEBUG(6, ("xid not found in idmap db, create S-1-22- SID.\n"));

	/* For local users/groups , we just create a rid = uid/gid */
	if (unixid->type == ID_TYPE_UID) {
		unix_sid = &global_sid_Unix_Users;
	} else {
		unix_sid = &global_sid_Unix_Groups;
	}

	new_sid = dom_sid_add_rid(mem_ctx, unix_sid, unixid->id);
	if (new_sid == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto failed;
	}

	*sid = new_sid;
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;

failed:
	talloc_free(tmp_ctx);
	return status;
}
static NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx,
				 TALLOC_CTX *mem_ctx,
				 struct unixid *unixid,
				 struct dom_sid **sid)
{
	int ret;
	NTSTATUS status;
	struct ldb_context *ldb = idmap_ctx->ldb_ctx;
	struct ldb_result *res = NULL;
	struct ldb_message *msg;
	const struct dom_sid *unix_sid;
	struct dom_sid *new_sid;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	const char *id_type;

	const char *sam_attrs[] = {"objectSid", NULL};
	
	 
	
	switch (unixid->type) {
		case ID_TYPE_UID:
			if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
				ret = dsdb_search_one(idmap_ctx->samdb, tmp_ctx, &msg,
						      ldb_get_default_basedn(idmap_ctx->samdb),
						      LDB_SCOPE_SUBTREE,
						      sam_attrs, 0,
						      "(&(|(sAMaccountType=%u)(sAMaccountType=%u)(sAMaccountType=%u))"
						      "(uidNumber=%u)(objectSid=*))",
						      ATYPE_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST, unixid->id);
			} else {
				 
				ret = LDB_ERR_NO_SUCH_OBJECT;
			}

			if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
				DEBUG(1, ("Search for uidNumber=%lu gave duplicate results, failing to map to a SID!\n",
					  (unsigned long)unixid->id));
				status = NT_STATUS_NONE_MAPPED;
				goto failed;
			} else if (ret == LDB_SUCCESS) {
				*sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid");
				if (*sid == NULL) {
					DEBUG(1, ("Search for uidNumber=%lu did not return an objectSid!\n",
						  (unsigned long)unixid->id));
					status = NT_STATUS_NONE_MAPPED;
					goto failed;
				}
				talloc_free(tmp_ctx);
				return NT_STATUS_OK;
			} else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
				DEBUG(1, ("Search for uidNumber=%lu gave '%s', failing to map to a SID!\n",
					  (unsigned long)unixid->id, ldb_errstring(idmap_ctx->samdb)));
				status = NT_STATUS_NONE_MAPPED;
				goto failed;
			}

			id_type = "ID_TYPE_UID";
			break;
		case ID_TYPE_GID:
			if (lpcfg_parm_bool(idmap_ctx->lp_ctx, NULL, "idmap_ldb", "use rfc2307", false)) {
				ret = dsdb_search_one(idmap_ctx->samdb, tmp_ctx, &msg,
						      ldb_get_default_basedn(idmap_ctx->samdb),
						      LDB_SCOPE_SUBTREE,
						      sam_attrs, 0,
						      "(&(|(sAMaccountType=%u)(sAMaccountType=%u))(gidNumber=%u))",
						      ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP,
						      unixid->id);
			} else {
				 
				ret = LDB_ERR_NO_SUCH_OBJECT;
			}
			if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
				DEBUG(1, ("Search for gidNumber=%lu gave duplicate results, failing to map to a SID!\n",
					  (unsigned long)unixid->id));
				status = NT_STATUS_NONE_MAPPED;
				goto failed;
			} else if (ret == LDB_SUCCESS) {
				*sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid");
				if (*sid == NULL) {
					DEBUG(1, ("Search for gidNumber=%lu did not return an objectSid!\n",
						  (unsigned long)unixid->id));
					status = NT_STATUS_NONE_MAPPED;
					goto failed;
				}
				talloc_free(tmp_ctx);
				return NT_STATUS_OK;
			} else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
				DEBUG(1, ("Search for gidNumber=%lu gave '%s', failing to map to a SID!\n",
					  (unsigned long)unixid->id, ldb_errstring(idmap_ctx->samdb)));
				status = NT_STATUS_NONE_MAPPED;
				goto failed;
			}

			id_type = "ID_TYPE_GID";
			break;
		default:
			DEBUG(1, ("unixid->type must be type gid or uid (got %u) for lookup with id %lu\n",
				  (unsigned)unixid->type, (unsigned long)unixid->id));
			status = NT_STATUS_NONE_MAPPED;
			goto failed;
	}

	ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
				 NULL, "(&(|(type=ID_TYPE_BOTH)(type=%s))"
				 "(xidNumber=%u))", id_type, unixid->id);
	if (ret != LDB_SUCCESS) {
		DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
		status = NT_STATUS_NONE_MAPPED;
		goto failed;
	}

	if (res->count == 1) {
		const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
							       "type", NULL);

		*sid = idmap_msg_get_dom_sid(mem_ctx, res->msgs[0],
					     "objectSid");
		if (*sid == NULL) {
			DEBUG(1, ("Failed to get sid from db: %u\n", ret));
			status = NT_STATUS_NONE_MAPPED;
			goto failed;
		}

		if (type == NULL) {
			DEBUG(1, ("Invalid type for mapping entry.\n"));
			talloc_free(tmp_ctx);
			return NT_STATUS_NONE_MAPPED;
		}

		if (strcmp(type, "ID_TYPE_BOTH") == 0) {
			unixid->type = ID_TYPE_BOTH;
		} else if (strcmp(type, "ID_TYPE_UID") == 0) {
			unixid->type = ID_TYPE_UID;
		} else {
			unixid->type = ID_TYPE_GID;
		}

		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	DEBUG(6, ("xid not found in idmap db, create S-1-22- SID.\n"));

	 
	if (unixid->type == ID_TYPE_UID) {
		unix_sid = &global_sid_Unix_Users;
	} else {
		unix_sid = &global_sid_Unix_Groups;
	}

	new_sid = dom_sid_add_rid(mem_ctx, unix_sid, unixid->id);
	if (new_sid == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto failed;
	}

	*sid = new_sid;
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;

failed:
	talloc_free(tmp_ctx);
	return status;
}