mirror of
https://github.com/samba-team/samba.git
synced 2025-01-26 10:04:02 +03:00
r8024: avoid one memcpy in the ipc_trans dcesrv_output() callback
we now can reference the DATA_BLOB that is used inside the dcesrv subsystem metze (This used to be commit 078f42bc3f74c66b69c7f76005812b221d691f7a)
This commit is contained in:
parent
5afa0a2d62
commit
4e2ac8b458
@ -350,14 +350,14 @@ static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
|
||||
static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *output, size_t *nwritten)
|
||||
{
|
||||
DATA_BLOB *blob = private_data;
|
||||
|
||||
if (out->length < blob->length) {
|
||||
blob->length = out->length;
|
||||
if (output->length < blob->length) {
|
||||
blob->length = output->length;
|
||||
}
|
||||
memcpy(blob->data, out->data, blob->length);
|
||||
memcpy(blob->data, output->data, blob->length);
|
||||
*nwritten = blob->length;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -616,20 +616,33 @@ static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
|
||||
struct ipctp_dcesrv_output {
|
||||
struct smbsrv_request *req;
|
||||
struct smb_trans2 *trans;
|
||||
};
|
||||
static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *_output, size_t *nwritten)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
DATA_BLOB *blob = private_data;
|
||||
DATA_BLOB *output;
|
||||
struct ipctp_dcesrv_output *ipctp = private_data;
|
||||
|
||||
if (out->length > blob->length) {
|
||||
/*
|
||||
* do it the fast way without doing an extra memcpy()
|
||||
*
|
||||
* we need to reference the the DATA_BLOB itself,
|
||||
* because out->data isn't always a valid talloc pointer
|
||||
*/
|
||||
output = talloc_reference(ipctp->req, _output);
|
||||
NT_STATUS_HAVE_NO_MEMORY(output);
|
||||
|
||||
if (output->length > ipctp->trans->in.max_data) {
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
if (out->length < blob->length) {
|
||||
blob->length = out->length;
|
||||
}
|
||||
memcpy(blob->data, out->data, blob->length);
|
||||
*nwritten = blob->length;
|
||||
ipctp->trans->out.data.data = output->data;
|
||||
ipctp->trans->out.data.length = MIN(ipctp->trans->in.max_data, output->length);
|
||||
|
||||
*nwritten = ipctp->trans->out.data.length;
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -638,38 +651,36 @@ static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
|
||||
struct smbsrv_request *req, struct smb_trans2 *trans)
|
||||
{
|
||||
struct pipe_state *p;
|
||||
struct ipc_private *private = ntvfs->private_data;
|
||||
struct ipc_private *ipcp = ntvfs->private_data;
|
||||
struct ipctp_dcesrv_output ipctp;
|
||||
NTSTATUS status;
|
||||
|
||||
/* the fnum is in setup[1] */
|
||||
p = pipe_state_find(private, trans->in.setup[1]);
|
||||
if (!p) {
|
||||
return NT_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
p = pipe_state_find(ipcp, trans->in.setup[1]);
|
||||
if (!p) return NT_STATUS_INVALID_HANDLE;
|
||||
|
||||
trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
|
||||
if (!trans->out.data.data) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
/*
|
||||
* just to be sure we doesn't have something uninitialized
|
||||
* the real work is done in the dcesrv_output() callback
|
||||
*/
|
||||
trans->out.data = data_blob(NULL, 0);
|
||||
|
||||
/* pass the data to the dcerpc server. Note that we don't
|
||||
expect this to fail, and things like NDR faults are not
|
||||
reported at this stage. Those sorts of errors happen in the
|
||||
dcesrv_output stage */
|
||||
status = dcesrv_input(p->dce_conn, &trans->in.data);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
/*
|
||||
now ask the dcerpc system for some output. This doesn't yet handle
|
||||
async calls. Again, we only expect NT_STATUS_OK. If the call fails then
|
||||
the error is encoded at the dcerpc level
|
||||
async calls. Again, we only expect NT_STATUS_OK or STATUS_BUFFER_OVERFLOW.
|
||||
If the call fails then the error is encoded at the dcerpc level
|
||||
*/
|
||||
status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
return status;
|
||||
}
|
||||
ipctp.req = req;
|
||||
ipctp.trans = trans;
|
||||
status = dcesrv_output(p->dce_conn, &ipctp, ipc_trans_dcesrv_output);
|
||||
NT_STATUS_IS_ERR_RETURN(status);
|
||||
|
||||
trans->out.setup_count = 0;
|
||||
trans->out.setup = NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user