state->chunk_ptr = chunk_ptr;
state->is_last_chunk = true;
+ if (talloc_total_blocks(chunk_mem) != 1) {
+ /*
+ * As we typically only have autogenerated callers
+ * of this function, we can enforce that chunk_mem
+ * doesn't have any talloc children yet.
+ *
+ * This makes the error handling in the
+ * NDR_ERR_INCOMPLETE_BUFFER case simpler.
+ */
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return tevent_req_post(req, ev);
+ }
+
tevent_req_defer_callback(req, state->ev);
talloc_set_destructor(state,
tevent_req_data(pp->call_req,
struct dcerpc_binding_handle_call_params_state);
enum ndr_err_code ndr_err;
+ struct ndr_push *pipe_pull = NULL;
const uint32_t *count = NULL;
- uint32_t saved_offset;
- size_t saved_ndr_blocks;
- size_t saved_mem_blocks;
if (call_state->pull == NULL) {
return;
return;
}
- /* pull the structure from the blob */
- saved_offset = call_state->pull->offset;
- saved_ndr_blocks = talloc_total_blocks(call_state->pull);
- saved_mem_blocks = talloc_total_blocks(state->chunk_mem);
+ /*
+ * setup a shallow copy subcontext, which we might destroy
+ */
+ ndr_err = ndr_pull_subcontext_start(call_state->pull, &pipe_pull,
+ 0xFFFFFFFF, 0);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS error;
+ error = ndr_map_error2ntstatus(ndr_err);
+ tevent_req_nterror(req, error);
+ return;
+ }
- call_state->pull->current_mem_ctx = state->chunk_mem;
- ndr_err = call_state->call_pipe->ndr_pull(call_state->pull,
- NDR_SCALARS|NDR_BUFFERS,
- state->chunk_ptr);
+ /* pull the structure from the subcontext */
+ pipe_pull->current_mem_ctx = state->chunk_mem;
+ ndr_err = pipe_pull->ndr_pull(pipe_pull,
+ NDR_SCALARS|NDR_BUFFERS,
+ state->chunk_ptr);
if (ndr_err == NDR_ERR_INCOMPLETE_BUFFER) {
- SMB_ASSERT(saved_mem_blocks == 1);
- SMB_ASSERT(saved_ndr_blocks == talloc_total_blocks(call_state->pull));
+ TALLOC_FREE(pipe_pull);
talloc_free_children(state->chunk_mem);
- call_state->pull->offset = saved_offset;
return;
}
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS error;
error = ndr_map_error2ntstatus(ndr_err);
- //if (h->ops->ndr_pull_failed) {
- // h->ops->ndr_pull_failed(h, error,
- // &state->response,
- // state->call);
- //}
tevent_req_nterror(req, error);
return;
}
- //if (h->ops->do_ndr_print) {
- // h->ops->do_ndr_print(h, NDR_OUT,
- // state->params->r_ptr, state->call);
- //}
-
- //if (h->ops->ndr_validate_out) {
- // error = h->ops->ndr_validate_out(h,
- // state->pull,
- // state->params->r_ptr,
- // state->call);
- // if (!NT_STATUS_IS_OK(error)) {
- // tevent_req_nterror(req, error);
- // return;
- // }
- //}
+ ndr_err = ndr_pull_subcontext_end(call_state->pull, pipe_pull,
+ 0xFFFFFFFF, 0);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS error;
+ error = ndr_map_error2ntstatus(ndr_err);
+ tevent_req_nterror(req, error);
+ return;
+ }
+ TALLOC_FREE(pipe_pull);
ndr_err = ndr_pull_pop(call_state->pull);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {