static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_request *add_req;
	struct ldb_message *msg;
	struct ldb_result *parent_res;
	const struct ldb_val *parent_sd = NULL;
	const struct ldb_val *user_sd;
	struct ldb_dn *dn = req->op.add.message->dn;
	struct ldb_dn *parent_dn, *nc_root;
	struct ldb_message_element *objectclass_element, *sd_element;
	int ret;
	const struct dsdb_schema *schema;
	DATA_BLOB *sd;
	const struct dsdb_class *objectclass;
	static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL };
	uint32_t instanceType;
	bool isNC = false;
	uint32_t sd_flags = dsdb_request_sd_flags(req, NULL);

	/* do not manipulate our control entries */
	if (ldb_dn_is_special(dn)) {
		return ldb_next_request(module, req);
	}

	user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
	sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
	/* nTSecurityDescriptor without a value is an error, letting through so it is handled */
	if (user_sd == NULL && sd_element) {
		return ldb_next_request(module, req);
	}

	ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));

	instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);

	if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
		isNC = true;
	}

	if (!isNC) {
		ret = dsdb_find_nc_root(ldb, req, dn, &nc_root);
		if (ret != LDB_SUCCESS) {
			ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n",
				ldb_dn_get_linearized(dn));
			return ret;
		}

		if (ldb_dn_compare(dn, nc_root) == 0) {
			DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn)));
			isNC = true;
		}
	}

	if (isNC) {
		DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn)));
	}
	if (!isNC) {
		/* if the object has a parent, retrieve its SD to
		 * use for calculation. Unfortunately we do not yet have
		 * instanceType, so we use dsdb_find_nc_root. */

		parent_dn = ldb_dn_get_parent(req, dn);
		if (parent_dn == NULL) {
			return ldb_oom(ldb);
		}

		/* we aren't any NC */
		ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
					    parent_attrs,
					    DSDB_FLAG_NEXT_MODULE |
					    DSDB_FLAG_AS_SYSTEM |
					    DSDB_SEARCH_SHOW_RECYCLED,
					    req);
		if (ret != LDB_SUCCESS) {
			ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find SD for %s\n",
				  ldb_dn_get_linearized(parent_dn));
			return ret;
		}
		if (parent_res->count != 1) {
			return ldb_operr(ldb);
		}
		parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
	}

	schema = dsdb_get_schema(ldb, req);

	objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
	if (objectclass_element == NULL) {
		return ldb_operr(ldb);
	}

	objectclass = dsdb_get_last_structural_class(schema,
						     objectclass_element);
	if (objectclass == NULL) {
		return ldb_operr(ldb);
	}

	/*
	 * The SD_FLAG control is ignored on add
	 * and we default to all bits set.
	 */
	sd_flags = SECINFO_OWNER|SECINFO_GROUP|SECINFO_SACL|SECINFO_DACL;

	sd = get_new_descriptor(module, dn, req,
				objectclass, parent_sd,
				user_sd, NULL, sd_flags);
	if (sd == NULL) {
		return ldb_operr(ldb);
	}
	msg = ldb_msg_copy_shallow(req, req->op.add.message);
	if (msg == NULL) {
		return ldb_oom(ldb);
	}
	if (sd_element != NULL) {
		sd_element->values[0] = *sd;
	} else {
		ret = ldb_msg_add_steal_value(msg,
					      "nTSecurityDescriptor",
					      sd);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	}

	ret = ldb_build_add_req(&add_req, ldb, req,
				msg,
				req->controls,
				req, dsdb_next_callback,
				req);
	LDB_REQ_SET_LOCATION(add_req);
	if (ret != LDB_SUCCESS) {
		return ldb_error(ldb, ret,
				 "descriptor_add: Error creating new add request.");
	}

	return ldb_next_request(module, add_req);
}