2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1998,
5 * Largely re-written : 2005
6 * Copyright (C) Jeremy Allison 1998 - 2005
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "../librpc/gen_ndr/srv_spoolss.h"
24 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
25 #include "../libcli/named_pipe_auth/npa_tstream.h"
26 #include "rpc_server.h"
27 #include "smbd/globals.h"
30 #define DBGC_CLASS DBGC_RPC_SRV
32 /****************************************************************************
33 Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
34 ****************************************************************************/
36 static ssize_t
fill_rpc_header(struct pipes_struct
*p
, char *data
, size_t data_to_copy
)
38 size_t len_needed_to_complete_hdr
=
39 MIN(data_to_copy
, RPC_HEADER_LEN
- p
->in_data
.pdu
.length
);
41 DEBUG(10, ("fill_rpc_header: data_to_copy = %u, "
42 "len_needed_to_complete_hdr = %u, "
44 (unsigned int)data_to_copy
,
45 (unsigned int)len_needed_to_complete_hdr
,
46 (unsigned int)p
->in_data
.pdu
.length
));
48 if (p
->in_data
.pdu
.data
== NULL
) {
49 p
->in_data
.pdu
.data
= talloc_array(p
, uint8_t, RPC_HEADER_LEN
);
51 if (p
->in_data
.pdu
.data
== NULL
) {
52 DEBUG(0, ("talloc failed\n"));
56 memcpy((char *)&p
->in_data
.pdu
.data
[p
->in_data
.pdu
.length
],
57 data
, len_needed_to_complete_hdr
);
58 p
->in_data
.pdu
.length
+= len_needed_to_complete_hdr
;
60 return (ssize_t
)len_needed_to_complete_hdr
;
63 static bool get_pdu_size(struct pipes_struct
*p
)
66 /* the fill_rpc_header() call insures we copy only
67 * RPC_HEADER_LEN bytes. If this doesn't match then
68 * somethign is very wrong and we can only abort */
69 if (p
->in_data
.pdu
.length
!= RPC_HEADER_LEN
) {
70 DEBUG(0, ("Unexpected RPC Header size! "
71 "got %d, expected %d)\n",
72 (int)p
->in_data
.pdu
.length
,
74 set_incoming_fault(p
);
78 frag_len
= dcerpc_get_frag_length(&p
->in_data
.pdu
);
80 /* verify it is a reasonable value */
81 if ((frag_len
< RPC_HEADER_LEN
) ||
82 (frag_len
> RPC_MAX_PDU_FRAG_LEN
)) {
83 DEBUG(0, ("Unexpected RPC Fragment size! (%d)\n",
85 set_incoming_fault(p
);
89 p
->in_data
.pdu_needed_len
= frag_len
- RPC_HEADER_LEN
;
91 /* allocate the space needed to fill the pdu */
92 p
->in_data
.pdu
.data
= talloc_realloc(p
, p
->in_data
.pdu
.data
,
94 if (p
->in_data
.pdu
.data
== NULL
) {
95 DEBUG(0, ("talloc_realloc failed\n"));
96 set_incoming_fault(p
);
103 /****************************************************************************
104 Call this to free any talloc'ed memory. Do this after processing
105 a complete incoming and outgoing request (multiple incoming/outgoing
107 ****************************************************************************/
109 static void free_pipe_context(struct pipes_struct
*p
)
111 data_blob_free(&p
->out_data
.frag
);
112 data_blob_free(&p
->out_data
.rdata
);
113 data_blob_free(&p
->in_data
.data
);
115 DEBUG(3, ("free_pipe_context: "
116 "destroying talloc pool of size %lu\n",
117 (unsigned long)talloc_total_size(p
->mem_ctx
)));
118 talloc_free_children(p
->mem_ctx
);
121 /****************************************************************************
122 Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
123 ****************************************************************************/
125 static ssize_t
process_incoming_data(struct pipes_struct
*p
, char *data
, size_t n
)
127 size_t data_to_copy
= MIN(n
, RPC_MAX_PDU_FRAG_LEN
128 - p
->in_data
.pdu
.length
);
130 DEBUG(10, ("process_incoming_data: Start: pdu.length = %u, "
131 "pdu_needed_len = %u, incoming data = %u\n",
132 (unsigned int)p
->in_data
.pdu
.length
,
133 (unsigned int)p
->in_data
.pdu_needed_len
,
136 if(data_to_copy
== 0) {
138 * This is an error - data is being received and there is no
139 * space in the PDU. Free the received data and go into the
142 DEBUG(0, ("process_incoming_data: "
143 "No space in incoming pdu buffer. "
144 "Current size = %u incoming data size = %u\n",
145 (unsigned int)p
->in_data
.pdu
.length
,
147 set_incoming_fault(p
);
152 * If we have no data already, wait until we get at least
153 * a RPC_HEADER_LEN * number of bytes before we can do anything.
156 if ((p
->in_data
.pdu_needed_len
== 0) &&
157 (p
->in_data
.pdu
.length
< RPC_HEADER_LEN
)) {
159 * Always return here. If we have more data then the RPC_HEADER
160 * will be processed the next time around the loop.
162 return fill_rpc_header(p
, data
, data_to_copy
);
166 * At this point we know we have at least an RPC_HEADER_LEN amount of
167 * data stored in p->in_data.pdu.
171 * If pdu_needed_len is zero this is a new pdu.
172 * Check how much more data we need, then loop again.
174 if (p
->in_data
.pdu_needed_len
== 0) {
176 bool ok
= get_pdu_size(p
);
180 if (p
->in_data
.pdu_needed_len
> 0) {
184 /* If rret == 0 and pdu_needed_len == 0 here we have a PDU
185 * that consists of an RPC_HEADER only. This is a
186 * DCERPC_PKT_SHUTDOWN, DCERPC_PKT_CO_CANCEL or
187 * DCERPC_PKT_ORPHANED pdu type.
188 * Deal with this in process_complete_pdu(). */
192 * Ok - at this point we have a valid RPC_HEADER.
193 * Keep reading until we have a full pdu.
196 data_to_copy
= MIN(data_to_copy
, p
->in_data
.pdu_needed_len
);
199 * Copy as much of the data as we need into the p->in_data.pdu buffer.
200 * pdu_needed_len becomes zero when we have a complete pdu.
203 memcpy((char *)&p
->in_data
.pdu
.data
[p
->in_data
.pdu
.length
],
205 p
->in_data
.pdu
.length
+= data_to_copy
;
206 p
->in_data
.pdu_needed_len
-= data_to_copy
;
209 * Do we have a complete PDU ?
210 * (return the number of bytes handled in the call)
213 if(p
->in_data
.pdu_needed_len
== 0) {
214 process_complete_pdu(p
);
218 DEBUG(10, ("process_incoming_data: not a complete PDU yet. "
219 "pdu.length = %u, pdu_needed_len = %u\n",
220 (unsigned int)p
->in_data
.pdu
.length
,
221 (unsigned int)p
->in_data
.pdu_needed_len
));
223 return (ssize_t
)data_to_copy
;
226 /****************************************************************************
227 Accepts incoming data on an internal rpc pipe.
228 ****************************************************************************/
230 static ssize_t
write_to_internal_pipe(struct pipes_struct
*p
, char *data
, size_t n
)
232 size_t data_left
= n
;
237 DEBUG(10, ("write_to_pipe: data_left = %u\n",
238 (unsigned int)data_left
));
240 data_used
= process_incoming_data(p
, data
, data_left
);
242 DEBUG(10, ("write_to_pipe: data_used = %d\n",
249 data_left
-= data_used
;
256 /****************************************************************************
257 Replies to a request to read data from a pipe.
259 Headers are interspersed with the data at PDU intervals. By the time
260 this function is called, the start of the data could possibly have been
261 read by an SMBtrans (file_offset != 0).
263 Calling create_rpc_reply() here is a hack. The data should already
264 have been prepared into arrays of headers + data stream sections.
265 ****************************************************************************/
267 static ssize_t
read_from_internal_pipe(struct pipes_struct
*p
, char *data
,
268 size_t n
, bool *is_data_outstanding
)
270 uint32 pdu_remaining
= 0;
271 ssize_t data_returned
= 0;
274 DEBUG(0,("read_from_pipe: pipe not open\n"));
278 DEBUG(6,(" name: %s len: %u\n",
279 get_pipe_name_from_syntax(talloc_tos(), &p
->syntax
),
283 * We cannot return more than one PDU length per
288 * This condition should result in the connection being closed.
289 * Netapp filers seem to set it to 0xffff which results in domain
290 * authentications failing. Just ignore it so things work.
293 if(n
> RPC_MAX_PDU_FRAG_LEN
) {
294 DEBUG(5,("read_from_pipe: too large read (%u) requested on "
295 "pipe %s. We can only service %d sized reads.\n",
297 get_pipe_name_from_syntax(talloc_tos(), &p
->syntax
),
298 RPC_MAX_PDU_FRAG_LEN
));
299 n
= RPC_MAX_PDU_FRAG_LEN
;
303 * Determine if there is still data to send in the
304 * pipe PDU buffer. Always send this first. Never
305 * send more than is left in the current PDU. The
306 * client should send a new read request for a new
310 pdu_remaining
= p
->out_data
.frag
.length
311 - p
->out_data
.current_pdu_sent
;
313 if (pdu_remaining
> 0) {
314 data_returned
= (ssize_t
)MIN(n
, pdu_remaining
);
316 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, "
317 "current_pdu_sent = %u returning %d bytes.\n",
318 get_pipe_name_from_syntax(talloc_tos(), &p
->syntax
),
319 (unsigned int)p
->out_data
.frag
.length
,
320 (unsigned int)p
->out_data
.current_pdu_sent
,
321 (int)data_returned
));
324 p
->out_data
.frag
.data
325 + p
->out_data
.current_pdu_sent
,
328 p
->out_data
.current_pdu_sent
+= (uint32
)data_returned
;
333 * At this point p->current_pdu_len == p->current_pdu_sent (which
334 * may of course be zero if this is the first return fragment.
337 DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length "
338 "= %u, p->out_data.rdata.length = %u.\n",
339 get_pipe_name_from_syntax(talloc_tos(), &p
->syntax
),
341 (unsigned int)p
->out_data
.data_sent_length
,
342 (unsigned int)p
->out_data
.rdata
.length
));
344 if (p
->out_data
.data_sent_length
>= p
->out_data
.rdata
.length
) {
346 * We have sent all possible data, return 0.
353 * We need to create a new PDU from the data left in p->rdata.
354 * Create the header/data/footers. This also sets up the fields
355 * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
356 * and stores the outgoing PDU in p->current_pdu.
359 if(!create_next_pdu(p
)) {
360 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n",
361 get_pipe_name_from_syntax(talloc_tos(), &p
->syntax
)));
365 data_returned
= MIN(n
, p
->out_data
.frag
.length
);
367 memcpy(data
, p
->out_data
.frag
.data
, (size_t)data_returned
);
368 p
->out_data
.current_pdu_sent
+= (uint32
)data_returned
;
371 (*is_data_outstanding
) = p
->out_data
.frag
.length
> n
;
373 if (p
->out_data
.current_pdu_sent
== p
->out_data
.frag
.length
) {
374 /* We've returned everything in the out_data.frag
375 * so we're done with this pdu. Free it and reset
376 * current_pdu_sent. */
377 p
->out_data
.current_pdu_sent
= 0;
378 data_blob_free(&p
->out_data
.frag
);
380 if (p
->out_data
.data_sent_length
>= p
->out_data
.rdata
.length
) {
382 * We're completely finished with both outgoing and
383 * incoming data streams. It's safe to free all
384 * temporary data from this request.
386 free_pipe_context(p
);
390 return data_returned
;
393 bool fsp_is_np(struct files_struct
*fsp
)
395 enum FAKE_FILE_TYPE type
;
397 if ((fsp
== NULL
) || (fsp
->fake_file_handle
== NULL
)) {
401 type
= fsp
->fake_file_handle
->type
;
403 return ((type
== FAKE_FILE_TYPE_NAMED_PIPE
)
404 || (type
== FAKE_FILE_TYPE_NAMED_PIPE_PROXY
));
407 struct np_proxy_state
{
409 uint16_t device_state
;
410 uint64_t allocation_size
;
411 struct tstream_context
*npipe
;
412 struct tevent_queue
*read_queue
;
413 struct tevent_queue
*write_queue
;
416 static struct np_proxy_state
*make_external_rpc_pipe_p(TALLOC_CTX
*mem_ctx
,
417 const char *pipe_name
,
418 const struct tsocket_address
*local_address
,
419 const struct tsocket_address
*remote_address
,
420 struct auth_serversupplied_info
*server_info
)
422 struct np_proxy_state
*result
;
424 const char *socket_dir
;
425 struct tevent_context
*ev
;
426 struct tevent_req
*subreq
;
427 struct netr_SamInfo3
*info3
;
433 result
= talloc(mem_ctx
, struct np_proxy_state
);
434 if (result
== NULL
) {
435 DEBUG(0, ("talloc failed\n"));
439 result
->read_queue
= tevent_queue_create(result
, "np_read");
440 if (result
->read_queue
== NULL
) {
441 DEBUG(0, ("tevent_queue_create failed\n"));
445 result
->write_queue
= tevent_queue_create(result
, "np_write");
446 if (result
->write_queue
== NULL
) {
447 DEBUG(0, ("tevent_queue_create failed\n"));
451 ev
= s3_tevent_context_init(talloc_tos());
453 DEBUG(0, ("s3_tevent_context_init failed\n"));
457 socket_dir
= lp_parm_const_string(
458 GLOBAL_SECTION_SNUM
, "external_rpc_pipe", "socket_dir",
459 get_dyn_NCALRPCDIR());
460 if (socket_dir
== NULL
) {
461 DEBUG(0, ("externan_rpc_pipe:socket_dir not set\n"));
464 socket_np_dir
= talloc_asprintf(talloc_tos(), "%s/np", socket_dir
);
465 if (socket_np_dir
== NULL
) {
466 DEBUG(0, ("talloc_asprintf failed\n"));
470 info3
= talloc_zero(talloc_tos(), struct netr_SamInfo3
);
472 DEBUG(0, ("talloc failed\n"));
476 status
= serverinfo_to_SamInfo3(server_info
, NULL
, 0, info3
);
477 if (!NT_STATUS_IS_OK(status
)) {
479 DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
485 subreq
= tstream_npa_connect_send(talloc_tos(), ev
,
488 remote_address
, /* client_addr */
489 NULL
, /* client_name */
490 local_address
, /* server_addr */
491 NULL
, /* server_name */
493 server_info
->user_session_key
,
494 data_blob_null
/* delegated_creds */);
495 if (subreq
== NULL
) {
497 DEBUG(0, ("tstream_npa_connect_send to %s for pipe %s and "
498 "user %s\\%s failed\n",
499 socket_np_dir
, pipe_name
, info3
->base
.domain
.string
,
500 info3
->base
.account_name
.string
));
503 ok
= tevent_req_poll(subreq
, ev
);
506 DEBUG(0, ("tevent_req_poll to %s for pipe %s and user %s\\%s "
507 "failed for tstream_npa_connect: %s\n",
508 socket_np_dir
, pipe_name
, info3
->base
.domain
.string
,
509 info3
->base
.account_name
.string
,
514 ret
= tstream_npa_connect_recv(subreq
, &sys_errno
,
518 &result
->device_state
,
519 &result
->allocation_size
);
522 DEBUG(0, ("tstream_npa_connect_recv to %s for pipe %s and "
523 "user %s\\%s failed: %s\n",
524 socket_np_dir
, pipe_name
, info3
->base
.domain
.string
,
525 info3
->base
.account_name
.string
,
526 strerror(sys_errno
)));
537 NTSTATUS
np_open(TALLOC_CTX
*mem_ctx
, const char *name
,
538 const struct tsocket_address
*local_address
,
539 const struct tsocket_address
*remote_address
,
540 struct auth_serversupplied_info
*server_info
,
541 struct messaging_context
*msg_ctx
,
542 struct fake_file_handle
**phandle
)
544 const char **proxy_list
;
545 struct fake_file_handle
*handle
;
547 proxy_list
= lp_parm_string_list(-1, "np", "proxy", NULL
);
549 handle
= talloc(mem_ctx
, struct fake_file_handle
);
550 if (handle
== NULL
) {
551 return NT_STATUS_NO_MEMORY
;
554 if ((proxy_list
!= NULL
) && str_list_check_ci(proxy_list
, name
)) {
555 struct np_proxy_state
*p
;
557 p
= make_external_rpc_pipe_p(handle
, name
,
562 handle
->type
= FAKE_FILE_TYPE_NAMED_PIPE_PROXY
;
563 handle
->private_data
= p
;
565 struct pipes_struct
*p
;
566 struct ndr_syntax_id syntax
;
567 const char *client_address
;
569 if (!is_known_pipename(name
, &syntax
)) {
571 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
574 if (tsocket_address_is_inet(remote_address
, "ip")) {
575 client_address
= tsocket_address_inet_addr_string(
578 if (client_address
== NULL
) {
580 return NT_STATUS_NO_MEMORY
;
586 p
= make_internal_rpc_pipe_p(handle
, &syntax
, client_address
,
587 server_info
, msg_ctx
);
589 handle
->type
= FAKE_FILE_TYPE_NAMED_PIPE
;
590 handle
->private_data
= p
;
593 if (handle
->private_data
== NULL
) {
595 return NT_STATUS_PIPE_NOT_AVAILABLE
;
603 bool np_read_in_progress(struct fake_file_handle
*handle
)
605 if (handle
->type
== FAKE_FILE_TYPE_NAMED_PIPE
) {
609 if (handle
->type
== FAKE_FILE_TYPE_NAMED_PIPE_PROXY
) {
610 struct np_proxy_state
*p
= talloc_get_type_abort(
611 handle
->private_data
, struct np_proxy_state
);
614 read_count
= tevent_queue_length(p
->read_queue
);
615 if (read_count
> 0) {
625 struct np_write_state
{
626 struct event_context
*ev
;
627 struct np_proxy_state
*p
;
632 static void np_write_done(struct tevent_req
*subreq
);
634 struct tevent_req
*np_write_send(TALLOC_CTX
*mem_ctx
, struct event_context
*ev
,
635 struct fake_file_handle
*handle
,
636 const uint8_t *data
, size_t len
)
638 struct tevent_req
*req
;
639 struct np_write_state
*state
;
642 DEBUG(6, ("np_write_send: len: %d\n", (int)len
));
643 dump_data(50, data
, len
);
645 req
= tevent_req_create(mem_ctx
, &state
, struct np_write_state
);
652 status
= NT_STATUS_OK
;
656 if (handle
->type
== FAKE_FILE_TYPE_NAMED_PIPE
) {
657 struct pipes_struct
*p
= talloc_get_type_abort(
658 handle
->private_data
, struct pipes_struct
);
660 state
->nwritten
= write_to_internal_pipe(p
, (char *)data
, len
);
662 status
= (state
->nwritten
>= 0)
663 ? NT_STATUS_OK
: NT_STATUS_UNEXPECTED_IO_ERROR
;
667 if (handle
->type
== FAKE_FILE_TYPE_NAMED_PIPE_PROXY
) {
668 struct np_proxy_state
*p
= talloc_get_type_abort(
669 handle
->private_data
, struct np_proxy_state
);
670 struct tevent_req
*subreq
;
674 state
->iov
.iov_base
= CONST_DISCARD(void *, data
);
675 state
->iov
.iov_len
= len
;
677 subreq
= tstream_writev_queue_send(state
, ev
,
681 if (subreq
== NULL
) {
684 tevent_req_set_callback(subreq
, np_write_done
, req
);
688 status
= NT_STATUS_INVALID_HANDLE
;
690 if (NT_STATUS_IS_OK(status
)) {
691 tevent_req_done(req
);
693 tevent_req_nterror(req
, status
);
695 return tevent_req_post(req
, ev
);
701 static void np_write_done(struct tevent_req
*subreq
)
703 struct tevent_req
*req
= tevent_req_callback_data(
704 subreq
, struct tevent_req
);
705 struct np_write_state
*state
= tevent_req_data(
706 req
, struct np_write_state
);
710 received
= tstream_writev_queue_recv(subreq
, &err
);
712 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
715 state
->nwritten
= received
;
716 tevent_req_done(req
);
719 NTSTATUS
np_write_recv(struct tevent_req
*req
, ssize_t
*pnwritten
)
721 struct np_write_state
*state
= tevent_req_data(
722 req
, struct np_write_state
);
725 if (tevent_req_is_nterror(req
, &status
)) {
728 *pnwritten
= state
->nwritten
;
732 struct np_ipc_readv_next_vector_state
{
739 static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state
*s
,
740 uint8_t *buf
, size_t len
)
745 s
->len
= MIN(len
, UINT16_MAX
);
748 static int np_ipc_readv_next_vector(struct tstream_context
*stream
,
751 struct iovec
**_vector
,
754 struct np_ipc_readv_next_vector_state
*state
=
755 (struct np_ipc_readv_next_vector_state
*)private_data
;
756 struct iovec
*vector
;
760 if (state
->ofs
== state
->len
) {
766 pending
= tstream_pending_bytes(stream
);
771 if (pending
== 0 && state
->ofs
!= 0) {
772 /* return a short read */
779 /* we want at least one byte and recheck again */
782 size_t missing
= state
->len
- state
->ofs
;
783 if (pending
> missing
) {
784 /* there's more available */
785 state
->remaining
= pending
- missing
;
788 /* read what we can get and recheck in the next cycle */
793 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
798 vector
[0].iov_base
= state
->buf
+ state
->ofs
;
799 vector
[0].iov_len
= wanted
;
801 state
->ofs
+= wanted
;
808 struct np_read_state
{
809 struct np_proxy_state
*p
;
810 struct np_ipc_readv_next_vector_state next_vector
;
813 bool is_data_outstanding
;
816 static void np_read_done(struct tevent_req
*subreq
);
818 struct tevent_req
*np_read_send(TALLOC_CTX
*mem_ctx
, struct event_context
*ev
,
819 struct fake_file_handle
*handle
,
820 uint8_t *data
, size_t len
)
822 struct tevent_req
*req
;
823 struct np_read_state
*state
;
826 req
= tevent_req_create(mem_ctx
, &state
, struct np_read_state
);
831 if (handle
->type
== FAKE_FILE_TYPE_NAMED_PIPE
) {
832 struct pipes_struct
*p
= talloc_get_type_abort(
833 handle
->private_data
, struct pipes_struct
);
835 state
->nread
= read_from_internal_pipe(
836 p
, (char *)data
, len
, &state
->is_data_outstanding
);
838 status
= (state
->nread
>= 0)
839 ? NT_STATUS_OK
: NT_STATUS_UNEXPECTED_IO_ERROR
;
843 if (handle
->type
== FAKE_FILE_TYPE_NAMED_PIPE_PROXY
) {
844 struct np_proxy_state
*p
= talloc_get_type_abort(
845 handle
->private_data
, struct np_proxy_state
);
846 struct tevent_req
*subreq
;
848 np_ipc_readv_next_vector_init(&state
->next_vector
,
851 subreq
= tstream_readv_pdu_queue_send(state
,
855 np_ipc_readv_next_vector
,
856 &state
->next_vector
);
857 if (subreq
== NULL
) {
860 tevent_req_set_callback(subreq
, np_read_done
, req
);
864 status
= NT_STATUS_INVALID_HANDLE
;
866 if (NT_STATUS_IS_OK(status
)) {
867 tevent_req_done(req
);
869 tevent_req_nterror(req
, status
);
871 return tevent_req_post(req
, ev
);
874 static void np_read_done(struct tevent_req
*subreq
)
876 struct tevent_req
*req
= tevent_req_callback_data(
877 subreq
, struct tevent_req
);
878 struct np_read_state
*state
= tevent_req_data(
879 req
, struct np_read_state
);
883 ret
= tstream_readv_pdu_queue_recv(subreq
, &err
);
886 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
891 state
->is_data_outstanding
= (state
->next_vector
.remaining
> 0);
893 tevent_req_done(req
);
897 NTSTATUS
np_read_recv(struct tevent_req
*req
, ssize_t
*nread
,
898 bool *is_data_outstanding
)
900 struct np_read_state
*state
= tevent_req_data(
901 req
, struct np_read_state
);
904 if (tevent_req_is_nterror(req
, &status
)) {
907 *nread
= state
->nread
;
908 *is_data_outstanding
= state
->is_data_outstanding
;
913 * @brief Create a new RPC client context which uses a local dispatch function.
915 * @param[in] conn The connection struct that will hold the pipe
917 * @param[out] spoolss_pipe A pointer to the connected rpc client pipe.
919 * @return NT_STATUS_OK on success, a corresponding NT status if an
922 NTSTATUS
rpc_connect_spoolss_pipe(connection_struct
*conn
,
923 struct rpc_pipe_client
**spoolss_pipe
)
927 /* TODO: check and handle disconnections */
929 if (!conn
->spoolss_pipe
) {
930 status
= rpc_pipe_open_internal(conn
,
931 &ndr_table_spoolss
.syntax_id
,
933 conn
->sconn
->msg_ctx
,
934 &conn
->spoolss_pipe
);
935 if (!NT_STATUS_IS_OK(status
)) {
940 *spoolss_pipe
= conn
->spoolss_pipe
;