1#!/usr/bin/perl
2# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
3# Published under the GNU General Public License
4use strict;
5use warnings;
6
7use Test::More tests => 8;
8use FindBin qw($RealBin);
9use lib "$RealBin";
10use Util;
11use Parse::Pidl::Util qw(MyDumper);
12use Parse::Pidl::Samba3::ClientNDR qw(ParseFunction);
13use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
14
15# Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
16my $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
17is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionInEnv($fn, "r."));
18is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionOutEnv($fn, "r."));
19
20$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
21is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionInEnv($fn, "r."));
22is_deeply({ "foo" => "r.out.foo" }, GenerateFunctionOutEnv($fn, "r."));
23
24$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
25is_deeply({ }, GenerateFunctionInEnv($fn, "r."));
26is_deeply({ "foo" => "r.out.foo" }, GenerateFunctionOutEnv($fn, "r."));
27
28my $x = new Parse::Pidl::Samba3::ClientNDR();
29
30$fn = { NAME => "bar", ELEMENTS => [ ] };
31$x->ParseFunction("foo", $fn);
32is($x->{res},
33"struct rpccli_bar_state {
34	TALLOC_CTX *out_mem_ctx;
35};
36
37static void rpccli_bar_done(struct tevent_req *subreq);
38
39struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx,
40				   struct tevent_context *ev,
41				   struct rpc_pipe_client *cli)
42{
43	struct tevent_req *req;
44	struct rpccli_bar_state *state;
45	struct tevent_req *subreq;
46
47	req = tevent_req_create(mem_ctx, &state,
48				struct rpccli_bar_state);
49	if (req == NULL) {
50		return NULL;
51	}
52	state->out_mem_ctx = NULL;
53
54	subreq = dcerpc_bar_send(state,
55				 ev,
56				 cli->binding_handle);
57	if (tevent_req_nomem(subreq, req)) {
58		return tevent_req_post(req, ev);
59	}
60	tevent_req_set_callback(subreq, rpccli_bar_done, req);
61	return req;
62}
63
64static void rpccli_bar_done(struct tevent_req *subreq)
65{
66	struct tevent_req *req = tevent_req_callback_data(
67		subreq, struct tevent_req);
68	struct rpccli_bar_state *state = tevent_req_data(
69		req, struct rpccli_bar_state);
70	NTSTATUS status;
71	TALLOC_CTX *mem_ctx;
72
73	if (state->out_mem_ctx) {
74		mem_ctx = state->out_mem_ctx;
75	} else {
76		mem_ctx = state;
77	}
78
79	status = dcerpc_bar_recv(subreq,
80				 mem_ctx);
81	TALLOC_FREE(subreq);
82	if (!NT_STATUS_IS_OK(status)) {
83		tevent_req_nterror(req, status);
84		return;
85	}
86
87	tevent_req_done(req);
88}
89
90NTSTATUS rpccli_bar_recv(struct tevent_req *req,
91			 TALLOC_CTX *mem_ctx)
92{
93	struct rpccli_bar_state *state = tevent_req_data(
94		req, struct rpccli_bar_state);
95	NTSTATUS status;
96
97	if (tevent_req_is_nterror(req, &status)) {
98		tevent_req_received(req);
99		return status;
100	}
101
102	/* Steal possible out parameters to the callers context */
103	talloc_steal(mem_ctx, state->out_mem_ctx);
104
105	tevent_req_received(req);
106	return NT_STATUS_OK;
107}
108
109NTSTATUS rpccli_bar(struct rpc_pipe_client *cli,
110		    TALLOC_CTX *mem_ctx)
111{
112	NTSTATUS status;
113
114	status = dcerpc_bar(cli->binding_handle,
115			    mem_ctx);
116	if (!NT_STATUS_IS_OK(status)) {
117		return status;
118	}
119
120	/* Return result */
121	return NT_STATUS_OK;
122}
123
124");
125
126$x = new Parse::Pidl::Samba3::ClientNDR();
127
128$fn = { NAME => "bar", ELEMENTS => [ ], RETURN_TYPE => "WERROR" };
129$x->ParseFunction("foo", $fn);
130is($x->{res},
131"struct rpccli_bar_state {
132	TALLOC_CTX *out_mem_ctx;
133	WERROR result;
134};
135
136static void rpccli_bar_done(struct tevent_req *subreq);
137
138struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx,
139				   struct tevent_context *ev,
140				   struct rpc_pipe_client *cli)
141{
142	struct tevent_req *req;
143	struct rpccli_bar_state *state;
144	struct tevent_req *subreq;
145
146	req = tevent_req_create(mem_ctx, &state,
147				struct rpccli_bar_state);
148	if (req == NULL) {
149		return NULL;
150	}
151	state->out_mem_ctx = NULL;
152
153	subreq = dcerpc_bar_send(state,
154				 ev,
155				 cli->binding_handle);
156	if (tevent_req_nomem(subreq, req)) {
157		return tevent_req_post(req, ev);
158	}
159	tevent_req_set_callback(subreq, rpccli_bar_done, req);
160	return req;
161}
162
163static void rpccli_bar_done(struct tevent_req *subreq)
164{
165	struct tevent_req *req = tevent_req_callback_data(
166		subreq, struct tevent_req);
167	struct rpccli_bar_state *state = tevent_req_data(
168		req, struct rpccli_bar_state);
169	NTSTATUS status;
170	TALLOC_CTX *mem_ctx;
171
172	if (state->out_mem_ctx) {
173		mem_ctx = state->out_mem_ctx;
174	} else {
175		mem_ctx = state;
176	}
177
178	status = dcerpc_bar_recv(subreq,
179				 mem_ctx,
180				 &state->result);
181	TALLOC_FREE(subreq);
182	if (!NT_STATUS_IS_OK(status)) {
183		tevent_req_nterror(req, status);
184		return;
185	}
186
187	tevent_req_done(req);
188}
189
190NTSTATUS rpccli_bar_recv(struct tevent_req *req,
191			 TALLOC_CTX *mem_ctx,
192			 WERROR *result)
193{
194	struct rpccli_bar_state *state = tevent_req_data(
195		req, struct rpccli_bar_state);
196	NTSTATUS status;
197
198	if (tevent_req_is_nterror(req, &status)) {
199		tevent_req_received(req);
200		return status;
201	}
202
203	/* Steal possible out parameters to the callers context */
204	talloc_steal(mem_ctx, state->out_mem_ctx);
205
206	/* Return result */
207	*result = state->result;
208
209	tevent_req_received(req);
210	return NT_STATUS_OK;
211}
212
213NTSTATUS rpccli_bar(struct rpc_pipe_client *cli,
214		    TALLOC_CTX *mem_ctx,
215		    WERROR *werror)
216{
217	WERROR result;
218	NTSTATUS status;
219
220	status = dcerpc_bar(cli->binding_handle,
221			    mem_ctx,
222			    &result);
223	if (!NT_STATUS_IS_OK(status)) {
224		return status;
225	}
226
227	/* Return result */
228	if (werror) {
229		*werror = result;
230	}
231
232	return werror_to_ntstatus(result);
233}
234
235");
236
237