tc->ref_count++;
}
+/*
+ helper for talloc_reference()
+*/
+static int talloc_reference_destructor(void *ptr)
+{
+ void **handle = ptr;
+ talloc_free(*handle);
+ return 0;
+}
+
+/*
+ make a secondary reference to a pointer, hanging off the given context.
+ the pointer remains valid until both the original caller and this given
+ context are freed.
+
+ the major use for this is when two different structures need to reference the
+ same underlying data, and you want to be able to free the two instances separately,
+ and in either order
+*/
+void *talloc_reference(const void *context, const void *ptr)
+{
+ void **handle;
+ handle = _talloc(context, sizeof(void *));
+ if (handle == NULL) {
+ return NULL;
+ }
+ /* note that we hang the destructor off the handle, not the
+ main context as that allows the caller to still setup their
+ own destructor on the context if they want to */
+ talloc_set_destructor(handle, talloc_reference_destructor);
+ talloc_increase_ref_count(ptr);
+ *handle = discard_const(ptr);
+ return *handle;
+}
+
/*
add a name to an existing pointer - va_list version
/*
- destroy a general handle. This relies on the talloc destructor being set up correctly
+ destroy a general handle.
*/
static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h)
{
}
-/*
- close an open domain context
-*/
-static int samr_Domain_destructor(void *ptr)
-{
- struct samr_domain_state *d_state = ptr;
- /* we need to explicitly free the connect state to lower the
- reference count */
- talloc_free(d_state->connect_state);
- return 0;
-}
-
/*
samr_OpenDomain
*/
return NT_STATUS_NO_MEMORY;
}
- d_state->connect_state = c_state;
+ d_state->connect_state = talloc_reference(d_state, c_state);
d_state->sam_ctx = c_state->sam_ctx;
d_state->domain_sid = talloc_strdup(d_state, sidstr);
d_state->domain_name = talloc_strdup(d_state, domain_name);
talloc_free(d_state);
return NT_STATUS_NO_MEMORY;
}
- talloc_set_destructor(d_state, samr_Domain_destructor);
- talloc_increase_ref_count(c_state);
-
+
h_domain->data = d_state;
h_domain->destroy = samr_handle_destroy;
*r->out.domain_handle = h_domain->wire_handle;
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
-/*
- close an open domain context
-*/
-static int samr_Account_destructor(void *ptr)
-{
- struct samr_account_state *a_state = ptr;
- /* we need to explicitly free the domain state to lower the
- reference count */
- talloc_free(a_state->domain_state);
- return 0;
-}
-
/*
samr_CreateDomainGroup
*/
}
a_state->sam_ctx = d_state->sam_ctx;
a_state->access_mask = r->in.access_mask;
- a_state->domain_state = d_state;
+ a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(d_state, msg.dn);
a_state->account_sid = talloc_strdup(d_state, sidstr);
a_state->account_name = talloc_strdup(d_state, groupname);
if (!a_state->account_name || !a_state->account_sid) {
+ talloc_free(a_state);
return NT_STATUS_NO_MEMORY;
}
g_handle->data = a_state;
g_handle->destroy = samr_handle_destroy;
- /* the domain state is in use one more time */
- talloc_increase_ref_count(d_state);
- talloc_set_destructor(a_state, samr_Account_destructor);
-
*r->out.group_handle = g_handle->wire_handle;
*r->out.rid = rid;
}
a_state->sam_ctx = d_state->sam_ctx;
a_state->access_mask = r->in.access_mask;
- a_state->domain_state = d_state;
+ a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(d_state, msg.dn);
a_state->account_sid = talloc_strdup(d_state, sidstr);
a_state->account_name = talloc_strdup(d_state, account_name);
if (!a_state->account_name || !a_state->account_sid) {
+ talloc_free(a_state);
return NT_STATUS_NO_MEMORY;
}
/* create the policy handle */
u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
if (!u_handle) {
+ talloc_free(a_state);
return NT_STATUS_NO_MEMORY;
}
u_handle->destroy = samr_handle_destroy;
/* the domain state is in use one more time */
- talloc_increase_ref_count(d_state);
- talloc_set_destructor(a_state, samr_Account_destructor);
+
*r->out.user_handle = u_handle->wire_handle;
*r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
}
a_state->sam_ctx = d_state->sam_ctx;
a_state->access_mask = r->in.access_mask;
- a_state->domain_state = d_state;
+ a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
a_state->account_sid = talloc_strdup(a_state, sidstr);
a_state->account_name = talloc_strdup(a_state, groupname);
g_handle->data = a_state;
g_handle->destroy = samr_handle_destroy;
- /* the domain state is in use one more time */
- talloc_increase_ref_count(d_state);
- talloc_set_destructor(a_state, samr_Account_destructor);
-
*r->out.group_handle = g_handle->wire_handle;
return NT_STATUS_OK;
}
a_state->sam_ctx = d_state->sam_ctx;
a_state->access_mask = r->in.access_mask;
- a_state->domain_state = d_state;
+ a_state->domain_state = talloc_reference(a_state, d_state);
a_state->account_dn = talloc_steal(d_state, msgs[0]->dn);
a_state->account_sid = talloc_strdup(d_state, sidstr);
a_state->account_name = talloc_strdup(d_state, account_name);
u_handle->data = a_state;
u_handle->destroy = samr_handle_destroy;
- /* the domain state is in use one more time */
- talloc_increase_ref_count(d_state);
- talloc_set_destructor(a_state, samr_Account_destructor);
-
*r->out.user_handle = u_handle->wire_handle;
return NT_STATUS_OK;